def __init__(self, world, x, y, ship=CUTTER): self.world = world self.velocity = v(0.0, 5.0) self.position = v(x, y) self.ship = ship self.sprite = pyglet.sprite.Sprite(ship.sprite) self.sprite.position = x, y self.sprite.rotation = 0.0 self.alive = True self.RADIUS = self.ship.radius self.MASS = self.ship.mass self.world.spawn(self) self.tethered = None self.emitter = None self.pick_name() TrackingLabel( self.world, self.name, follow=self, colour=self.ship.colour ) self.setup_particles()
class Collidable(Collider): """Objects that can be collided with. All collidable objects are assumed to be circles, with a fixed radius RADIUS in pixels, and a centre given by inst.position, which must be a wasabi.geom.vector.Vector. Collidable objects maintain their references in the world's spatial hash. We use "fat bounds" with error tracking to reduce the frequency with which we have to move objects. """ _position = v(0, 0) _bounds_pos = v(float('inf'), float('inf')) _fat_bounds = None FATNESS = 50 # how much to offset by; increase this for fast-moving objects alive = True @property def position(self): return self._position @position.setter def position(self, v): self._position = v if (self._position - self._bounds_pos).length2 > self.FATNESS: self._update_bounds() self._bounds_pos = self._position def _update_bounds(self): fat_r = self.RADIUS + self.FATNESS new_bounds = Rect.from_cwh(self.position, fat_r * 2, fat_r * 2) if self._fat_bounds: try: self.world.spatial_hash.remove_rect(self._fat_bounds, self) except (KeyError, IndexError): # weren't in there anyway pass else: self.world.spatial_hash.add_rect(new_bounds, self) else: if self.alive: self.world.spatial_hash.add_rect(new_bounds, self) self._fat_bounds = new_bounds def kill(self): self.world.kill(self) self.alive = False def explode(self): """Explode the object.""" Explosion(self.world, self.position) self.kill() self.world.dispatch_event('on_object_destroyed', self)
def __init__(self, world, text, position=v(0, 0), offset=v(10, -20), colour=WHITE): self.world = world self.colour = colour self.offset = offset self.label = pyglet.text.Label(text, font_name=FONT_NAME, color=colour + (255, )) self.label.x, self.label.y = position self.age = 0 self.world.spawn(self)
def __init__(self, world, position, velocity=v(0, 0), destination='moonbase'): """Create a collectable. destination is the id of a collector this is bound for. It will not be accepted at other collectors. Pass destination=None to allow the collectable to be collected at all collectors. """ self.world = world self.position = position self.velocity = velocity self.destination = destination self.sprite = pyglet.sprite.Sprite(self.img) self.sprite.rotation = random.random() * 360 self.angular_velocity = (random.random() - 0.5) * self.MAX_ANGULAR_VELOCITY self.tethered_to = None self.world.spawn(self)
def draw(self, camera): # set up projection matrix gl.glMatrixMode(gl.GL_PROJECTION) gl.glPushMatrix() gl.glLoadIdentity() gl.gluPerspective(FOVY, camera.aspect(), NEAR_PLANE, FAR_PLANE) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glEnable(gl.GL_DEPTH_TEST) # compute correct clip rect on far plane l, b = camera.position + camera.offset * FAR_PLANE_SCALE r, t = camera.position - camera.offset * FAR_PLANE_SCALE # Create blocks l = int(floor(l / BLOCK_SIZE)) r = int(ceil(r / BLOCK_SIZE)) b = int(floor(b / BLOCK_SIZE)) t = int(ceil(t / BLOCK_SIZE)) for y in range(b, t): for x in range(l, r): c = v(x, y) * BLOCK_SIZE gl.glPushMatrix() gl.glTranslatef(c.x, c.y, 0) self.batch.draw() gl.glPopMatrix() gl.glMatrixMode(gl.GL_PROJECTION) gl.glPopMatrix() gl.glMatrixMode(gl.GL_MODELVIEW) gl.glDisable(gl.GL_DEPTH_TEST)
def __init__(self, world, pos, dir, initial_velocity=v(0, 0)): self.world = world self.position = pos self.velocity = (dir * self.SPEED + initial_velocity) self.sprite = pyglet.sprite.Sprite(Bullet.BULLET) self.sprite.position = pos.x, pos.y self.sprite.rotation = 90 - dir.angle self.world.spawn(self)
def shoot(self): rotation = math.radians(self.sprite.rotation) dir = v( math.sin(rotation), math.cos(rotation) ) laser_sound.play() Bullet(self.world, self.position, dir, self.velocity)
def thrust(self, ts): rotation = math.radians(self.sprite.rotation) accel = self.ship.acceleration a = v( math.sin(rotation) * accel, math.cos(rotation) * accel ) self.velocity += a * ts
def __init__(self): self.batch = Batch() self.starfield_block = StarfieldBlock(rect=Rect.from_cwh( v(0, 0), BLOCK_SIZE, BLOCK_SIZE), batch=self.batch) self.blocks = {}
def spawn_random_collectable(world): cls = random.choice([Cheese, Ice, Metal]) while True: x = (random.random() - 0.5) * 2000 y = (random.random() - 0.5) * 2000 if x * x + y * y > 4e5: break return cls(world, v(x, y))
def random_positions(num, average_range=1000, standard_deviation=400): """Yield num random positions""" while num: dist = random.normalvariate(average_range, standard_deviation) if dist < 600: continue angle = random.random() * 360 yield v(dist, 0).rotated(angle) num -= 1
def generate(cls, world, random=random): while True: dist = random.normalvariate(2500, 1000) if dist > 500: # Don't put asteroids too close to the moon break angle = random.random() * 360 pos = v(0, dist).rotated(angle) return cls(world, pos, random=random)
def __init__(self, world, x=0, y=0): self.world = world self.position = v(x, y) self.load() self.sprite = pyglet.sprite.Sprite(self.img) self.sprite.position = self.position self.rotation = 0 # rotation in degrees self.moonbase = MoonBase(world, self) self.world.spawn(self)
def __init__(self, world, position, velocity=v(0, 0)): self.world = world self.position = position self.velocity = velocity self.sprite = pyglet.sprite.Sprite(self.DROID_OK) self.rotation = random.random() * 360 self.angular_velocity = 200 self.world.spawn(self) self.health = 200 self.player_in_range = False self.world.push_handlers(self.on_region_entered)
def __init__(self, world, position, velocity=v(0, 0), random=random): self.world = world img, self.RADIUS = random.choice(list(zip(self.SPRITES, self.RADIUSES))) self.position = position self.velocity = velocity self.sprite = pyglet.sprite.Sprite(img) # self.sprite.scale = scale self.rotation = random.random() * 360 self.angular_velocity = (random.random() - 0.5) * 60 self.world.spawn(self)
def spawn_fragment(self, position, velocity=v(0, 0)): """Spawn a fragment at the given position.""" cls = self.fragment_class() cls(self.world, position, velocity) new_radius = math.sqrt(self.RADIUS * self.RADIUS - 81) frac = new_radius / self.RADIUS self.sprite.scale *= frac self.RADIUS *= frac if self.RADIUS < 10: self.world.kill(self) cls(self.world, self.position) self.world.dispatch_event('on_object_destroyed', self)
def update(self, ts): u = self.velocity if self.world.keyboard[key.Z]: self.shoot() if self.world.keyboard[key.UP]: self.thrust(ts) thrusting = True else: thrusting = False if self.world.keyboard[key.LEFT]: self.rotate_acw(ts) if self.world.keyboard[key.RIGHT]: self.rotate_cw(ts) if self.tethered: self.update_tethered(ts) # Cap speed speed = self.velocity.length if speed > self.ship.max_speed: self.velocity *= self.ship.max_speed / speed # Constant acceleration formula self.position += 0.5 * (u + self.velocity) * ts direction = v(0, 1).rotated(-self.sprite.rotation) self.tail = self.position - 0.5 * self.ship.radius * direction if self.emitter: exhaust_particles.unbind_controller(self.emitter) self.emitter = None if thrusting: self.template_particle.velocity = tuple(-0.6 * self.ship.max_speed * direction + self.velocity) + (0.0,) self.emitter = StaticEmitter( template=self.template_particle, position=domain.Disc( tuple(self.tail) + (0.0,), (0, 0, 1), 0.5 * self.ship.radius ), rotation=domain.Line( (0, 0, -60), (0, 0, 60), ), rate=100 ) exhaust_particles.bind_controller(self.emitter) self.do_collisions()
def draw(self): self.window.clear() self.camera.position += v(1, 0) self.camera.set_matrix() self.starfield.draw(self.camera) gl.glLoadIdentity() for i, l in enumerate(self.labels): if i == self.selected: c = WHITE else: c = GREY l.color = c + (255,) self.batch.draw()
def fragment(self, position): """Eject a fragment given a bullet impact at position.""" outwards = (position - self.position).normalized() # Place the new fragment where it cannot collide immediately edge_pos = self.position + outwards * (self.RADIUS + 8) # Fire outwards vel = outwards * self.EJECT_SPEED # Add a random component vel += v(0, random.random() * self.EJECT_RANDOMNESS).rotated( random.random() * 360) self.spawn_fragment(edge_pos, vel)
class MoonBase(Collector): id = 'moonbase' alive = True RADIUS = 50.0 OFFSET = v(0, 130.0) def __init__(self, world, moon): self.world = world self.moon = moon def draw(self): """Moon base graphic is currently part of moon.""" def update(self, dt): self.position = self.moon.position + self.OFFSET.rotated( -self.moon.rotation) self.do_collisions()
def setup_world(self): """Create the initial world.""" self.generate_asteroids() moon = Moon(self) TrackingLabel( self, MOONBASE_NAME, follow=moon.moonbase, offset=v(30, 15) ) Signpost( self, MOONBASE_NAME, moon.moonbase ) self.moon = moon self.spawn_player(freebie=True) self.give_money(INITIAL_MONEY)
def __init__(self, world, position, particle_colour=(0.6, 0.6, 0.6), particle_amount=0): self.world = world self.position = v(position) self.load() self.age = 0 self.sprite = pyglet.sprite.Sprite(self.img) self.sprite.position = self.position self.sprite.scale = self.MIN_SCALE self.world.spawn(self) sound = explosion_sound.play() x, y = self.position - self.world.player.position sound.position = x, y, 0.0 sound.min_distance = 300 if particle_amount: self.spawn_particles(particle_colour, particle_amount) else: self.emitter = None
def __init__(self, position=v(0, 0)): self.position = position self.offset = v(WIDTH * -0.5, HEIGHT * -0.5)
def spawn_above_moonbase(self, class_name, *args, **kwargs): """Spawn a thing above the moonbase, wherever it may be right now.""" moon = self.world.moon position = moon.position + v(0, 220).rotated(-moon.rotation) self.do_spawn(class_name, position, *args, **kwargs)
super(Mission, self).skip() self.hud.clear_messages() self.finish() Mission.register_event_type('on_failure') m = Mission('Diagnostics') m.say("{control}: Stand by {name}, we're going to run some diagnostics.", delay=5) m.say("{control}: Let's take you out for a spin. Head towards this marker.", delay=0) m.goal('Move to the marker') m.say('Hold LEFT/RIGHT to rotate. Hold UP to thrust.', colour=WHITE, delay=0) m.spawn('moonbaseapollo.objects.Marker', v(-300, 200), signpost='Waypoint', persistent=False) m.player_must_collect('moonbaseapollo.objects.Marker') m.say("{control}: And now this one.") m.spawn('moonbaseapollo.objects.Marker', v(300, -200), signpost='Waypoint', persistent=False) m.player_must_collect('moonbaseapollo.objects.Marker') m.say( "{control}: {name}, your systems are looking good. You are mission ready!") ICE_POS = v(1500, -1200) m = Mission('Harvesting Ice') m.say(
def __init__(self, world, text, follow, offset=v(10, -20), colour=WHITE): super(TrackingLabel, self).__init__(world, text, offset=offset, colour=colour) self.follow = follow
def draw(self): # track the thing we are labelling self.label.x, self.label.y = v(self.follow.position) + self.offset super(TrackingLabel, self).draw()