Move all root .py files into playscii/ package directory. Rename playscii.py to app.py, add __main__.py entry point. Convert bare imports to relative (within package) and absolute (in formats/ and games/). Data dirs stay at root.
153 lines
4.7 KiB
Python
153 lines
4.7 KiB
Python
import math
|
|
import random
|
|
|
|
from playscii.game_util_objects import Character, Player, StaticTileBG, WarpTrigger
|
|
|
|
|
|
class PlatformWorld(StaticTileBG):
|
|
draw_col_layer = True
|
|
|
|
|
|
class PlatformPlayer(Player):
|
|
# from http://www.piratehearts.com/blog/2010/08/30/40/:
|
|
# JumpSpeed = sqrt(2.0f * Gravity * JumpHeight);
|
|
|
|
art_src = "player"
|
|
# collision_shape_type = CST_AABB
|
|
col_width = 2
|
|
col_height = 3
|
|
handle_key_events = True
|
|
fast_move_steps = 1
|
|
col_radius = 1.75
|
|
move_accel_x = 400
|
|
move_accel_y = 2500
|
|
ground_friction = 20
|
|
air_friction = 15
|
|
max_jump_press_time = 0.15
|
|
editable = Player.editable + ["max_jump_press_time"]
|
|
jump_key = "x"
|
|
|
|
def __init__(self, world, obj_data=None):
|
|
Player.__init__(self, world, obj_data)
|
|
self.jump_time = 0
|
|
# don't jump again until jump is released and pressed again
|
|
self.jump_ready = True
|
|
self.started_jump = False
|
|
|
|
def started_colliding(self, other):
|
|
Player.started_colliding(self, other)
|
|
if isinstance(other, PlatformMonster):
|
|
# landing atop monster?
|
|
dx, dy = other.x - self.x, other.y - self.y
|
|
if abs(dy) > abs(dx) and dy < -1:
|
|
other.destroy()
|
|
|
|
def is_affected_by_gravity(self):
|
|
return True
|
|
|
|
def handle_key_down(self, key, shift_pressed, alt_pressed, ctrl_pressed):
|
|
if key == self.jump_key and self.jump_ready:
|
|
self.jump()
|
|
self.jump_ready = False
|
|
self.started_jump = True
|
|
|
|
def handle_key_up(self, key, shift_pressed, alt_pressed, ctrl_pressed):
|
|
if key == self.jump_key:
|
|
self.jump_ready = True
|
|
|
|
def allow_move_y(self, dy):
|
|
# disable regular up/down movement, jump button sets move_y directly
|
|
return False
|
|
|
|
def update_state(self):
|
|
self.state = (
|
|
"stand"
|
|
if self.is_on_ground() and (self.move_x, self.move_y) == (0, 0)
|
|
else "walk"
|
|
)
|
|
|
|
def moved_this_frame(self):
|
|
delta = math.sqrt(
|
|
abs(self.last_x - self.x) ** 2
|
|
+ abs(self.last_y - self.y) ** 2
|
|
+ abs(self.last_z - self.z) ** 2
|
|
)
|
|
return delta > self.stop_velocity
|
|
|
|
def is_on_ground(self):
|
|
# works for now: just check for -Y contact with first world object
|
|
ground = self.world.get_first_object_of_type("PlatformWorld")
|
|
contact = self.collision.contacts.get(ground.name, None)
|
|
if not contact:
|
|
return False
|
|
return contact.overlap.y < 0
|
|
|
|
def jump(self):
|
|
self.jump_time += self.get_time_since_last_update() / 1000
|
|
if self.jump_time < self.max_jump_press_time:
|
|
self.move_y += 1
|
|
|
|
def update(self):
|
|
on_ground = self.is_on_ground()
|
|
if on_ground and self.jump_time > 0:
|
|
self.jump_time = 0
|
|
# poll jump key for variable length jump
|
|
if self.world.app.il.is_key_pressed(self.jump_key) and (
|
|
self.started_jump or not on_ground
|
|
):
|
|
self.jump()
|
|
self.started_jump = False
|
|
Player.update(self)
|
|
# wobble as we walk a la ELC2
|
|
if self.state == "walk" and on_ground:
|
|
self.y += math.sin(self.world.app.updates) / 5
|
|
|
|
|
|
class PlatformMonster(Character):
|
|
art_src = "monster"
|
|
move_state = "stand"
|
|
animating = True
|
|
fast_move_steps = 2
|
|
move_accel_x = 100
|
|
col_radius = 1
|
|
|
|
def pre_first_update(self):
|
|
# pick random starting direction
|
|
self.move_dir_x = random.choice([-1, 1])
|
|
self.set_timer_function("hit_wall", self.check_wall_hits, 0.2)
|
|
|
|
def is_affected_by_gravity(self):
|
|
return True
|
|
|
|
def allow_move_y(self, dy):
|
|
return False
|
|
|
|
def check_wall_hits(self):
|
|
"Turn around if a wall is immediately ahead of direction we're moving."
|
|
# check collision in direction we're moving
|
|
margin = 0.1
|
|
if self.move_dir_x > 0:
|
|
x = self.x + self.col_radius + margin
|
|
else:
|
|
x = self.x - self.col_radius - margin
|
|
y = self.y
|
|
# DEBUG see trace destination
|
|
# lines = [(self.x, self.y, 0), (x, y, 0)]
|
|
# self.app.debug_line_renderable.set_lines(lines)
|
|
hits, shapes = self.world.get_colliders_at_point(
|
|
x,
|
|
y,
|
|
# include_object_names=[],
|
|
include_class_names=["PlatformWorld", "PlatformMonster"],
|
|
exclude_object_names=[self.name],
|
|
)
|
|
if len(hits) > 0:
|
|
self.move_dir_x = -self.move_dir_x
|
|
|
|
def update(self):
|
|
self.move(self.move_dir_x, 0)
|
|
Character.update(self)
|
|
|
|
|
|
class PlatformWarpTrigger(WarpTrigger):
|
|
warp_class_names = ["Player", "PlatformMonster"]
|