class Game(object): def __init__(self): self.camera_position = [0, 0, -512] self.enemies = LazySet() self.entities = LazySet() self.tick_callbacks = LazySet() def create_entity(self, klass, *a, **ka): entity = klass(self) entity.on_setup(*a, **ka) self.entities.add(entity) return entity def remove_entity(self, e): self.entities.remove(e) e.on_remove() def start(self): self.window = pyglet.window.Window(800, 600) self.window.set_vsync(True) self.floor_batch = pyglet.graphics.Batch() self.decal_batch = pyglet.graphics.Batch() self.object_batch = pyglet.graphics.Batch() self.effect_batch = pyglet.graphics.Batch() self.wall_batch = pyglet.graphics.Batch() self.window_batch = pyglet.graphics.Batch() self.status_label = pyglet.text.Label('Loading...', font_name='sans', font_size=8, x=10, y=10, batch=self.window_batch) self.window.set_handler('on_draw', self.on_draw) self.window.set_handler('on_resize', self.on_resize) pyglet.clock.schedule_once(self.setup_resources, 0) pyglet.clock.schedule_once(self.setup_controls, 0) pyglet.clock.schedule_once(self.setup_world, 0) pyglet.clock.schedule_once(self.setup_player, 0) pyglet.clock.schedule_once(self.setup_gameloop, 0) pyglet.app.run() def setup_resources(self, dt): self.notice('Indexing resources...') self.loader = pyglet.resource.Loader( path = ['./resources'], script_home=os.path.abspath(os.path.dirname(__file__))) self.load_image = self.loader.image self.loader.reindex() def setup_controls(self, dt): self.notice('Initializing controls...') self.keys = pyglet.window.key.KeyStateHandler() self.window.push_handlers(self.keys) def setup_world(self, dt): self.notice('Loading world...') self.world = World(self, './ftl/resources/world.json') def setup_player(self, dt): self.notice('Loading player...') self.player = self.create_entity(Player) self.center_camera() def setup_gameloop(self, dt): self.notice('Loading game state...') pyglet.clock.schedule_interval(self.on_tick, 1.0/60) def notice(self, msg): self.status_label.text = msg def on_resize(self, w, h): self.window_size = w, h def on_draw(self): self.window.clear() w, h = self.window_size self.notice('Entities: %d FPS: %d' % ( len(self.entities), pyglet.clock.get_fps())) # Setup perspective glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(-w/2, w/2, -h/2, h/2, -100, 10000) # Move camera above character glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslatef(*map(int, self.camera_position)) # Draw everything but HUD self.floor_batch.draw() self.decal_batch.draw() self.wall_batch.draw() self.object_batch.draw() self.effect_batch.draw() # Draw HUD glLoadIdentity() glTranslatef(-w/2, -h/2, -100) self.window_batch.draw() def on_tick(self, dt): self.handle_player_movement(dt) self.handle_input(dt) for entity in self.entities: entity.tick(dt) for callback in self.tick_callbacks: callback(dt) def handle_player_movement(self, dt): dx = 0.0 dy = 0.0 if self.keys[key.RIGHT]: dx += 1 if self.keys[key.LEFT]: dx -= 1 if self.keys[key.UP]: dy += 1 if self.keys[key.DOWN]: dy -= 1 if dx and dy: # Length of vector is always sqrt(2), so we devide it by sqrt(2) # to get a uniform vector. Works only for diagonal movement. dx *= 0.7071067811865476 # 1/sqrt(2) dy *= 0.7071067811865476 if dx or dy: self.player.move(dx*dt, dy*dt) self.center_camera() else: self.player.move(0.0, 0.0) # Tell the player to stop def handle_input(self, dt): if self.keys[key.E]: self.enemies.add(self.create_entity(Enemy, *self.player.position)) if self.keys[key.D]: import pdb; pdb.set_trace() if self.keys[key.SPACE]: bx, by = self.player.last_move if bx or by: bx, by = normvec((bx, by), 200) bx += (0.5 - random.random()) * 100 by += (0.5 - random.random()) * 100 x, y = self.player.position if self.player.face == 'up': y += 10 if self.player.face == 'down': y -= 10 if self.player.face == 'right': x += 15 if self.player.face == 'left': x -= 15 bullet = self.create_entity(Fireball, x, y+10, bx, by) def center_camera(self): ''' Move the camera above the player, but only if the player leaves a save area. ''' wx, wy, wz = self.camera_position px, py = self.player.position # Desired world position in center of screen wx = max(-30, min(30, px+wx)) - px wy = max(-30, min(30, py+wy)) - py self.camera_position = [wx, wy, wz] self.world.light(*self.player.position)
def setup_world(self, dt): self.notice('Loading world...') self.world = World(self, './ftl/resources/world.json')