def take_damage(self, amount): self.damage += amount if self.damage >= self.health and not self.has_exploded: # create an explosion self.has_exploded = True Explosion(self._body.position, BLOCK_SIZE, velocity=self._body.velocity) # remove joints for block in self._adjacent_blocks: toremove = self._joints & block._joints for joint in toremove: block._joints.remove(joint) SPACE.remove(*self._joints) self._joints = WeakSet() # remove ties to the construction for block in self._adjacent_blocks: block._adjacent_blocks.remove(self) self._adjacent_blocks = WeakSet() elif self.damage >= self.health * 2: Explosion(self._body.position, BLOCK_SIZE, velocity=self._body.velocity) for i in range(random.randint(1,5)): Resource(self) SPACE.remove(self._body, self._shape) SPACE.blocks.remove(self) if self in SPACE.controllable_blocks: SPACE.controllable_blocks.remove(self) if self in SPACE.controller_blocks: SPACE.controller_blocks.remove(self)
def activate(self): density = 0.01 mass = density inertia = pymunk.moment_for_circle(mass, 0, self.radius) self._tractor_body = pymunk.Body(mass, inertia) self._tractor_body.position = self._body.position self._tractor_body._get_block = ref(self) self._tractor_shape = pymunk.Circle(self._tractor_body, self.radius) self._tractor_shape.collision_type = COLLISION_TYPES["tractor"] self._tractor_shape.sensor = True self._tractor_link = PivotJoint(self._body, self._tractor_body, (0, 0), (0, 0)) SPACE.add(self._tractor_body, self._tractor_shape, self._tractor_link)
def activate(self): density = 0.01 mass = density inertia = pymunk.moment_for_circle(mass, 0, self.radius) self._shield_body = pymunk.Body(mass, inertia) self._shield_body.position = self._body.position self._shield_shape = pymunk.Circle(self._shield_body, self.radius) self._shield_shape.elasticity = 0.5 self._shield_shape.friction= 0.0 self._shield_shape.collision_type = COLLISION_TYPES["shield"] self._shield_link = PivotJoint(self._body, self._shield_body, (0, 0), (0, 0)) SPACE.add(self._shield_body, self._shield_shape, self._shield_link)
def weld_to(self, block): pj = PivotJoint(self._body, block._body, (self._body.position + block._body.position) / 2) gj = GearJoint(self._body, block._body, 0, 1) SPACE.add(pj, gj) # add weak references to each other block._adjacent_blocks.add(self) self._adjacent_blocks.add(block) # and to the joint self._joints.add(pj) block._joints.add(pj) self._joints.add(gj) block._joints.add(gj)
def __init__(self): # load images base_path = "images/blocks/{}.png".format(self.image) self.img = load_image(base_path, self.image_anchor) # create collision object w = h = BLOCK_SIZE inertia = pymunk.moment_for_box(1, w, h) self._body = pymunk.Body(1, inertia) self._body.position = Vec2d(0, 0) self._shape = pymunk.Poly.create_box(self._body, (w, h), radius=0.2) self._shape.collision_type = COLLISION_TYPES['ghost'] self._shape.sensor = True self._shape._get_block = ref(self) SPACE.add(self._body, self._shape) # what can it connect to? self.valid_welds = []
def upkeep(self): if self.decay_chance > random.random(): SPACE.remove(self._shape, self._body) SPACE.resources.remove(self) if hasattr(self._shape, "target") and self._shape.target(): b = self._shape direction = b.target().position - b.body.position if direction.length < BLOCK_SIZE / 2: block = b.target()._get_block() if block: block.resource_count += 1 SPACE.resources.remove(self) # TODO: 160 is the radius of the field... # let's get that dynamically direction.length = max(0.1, (160 - direction.length) / 160) b.body.apply_impulse(direction)
def __init__(self, source=None): # physics r = 4 mass = 0.01 inertia = pymunk.moment_for_circle(mass, 0, r) self._body = pymunk.Body(mass, inertia) p = Vec2d(random.uniform(0, BLOCK_SIZE), 0) p.rotate(random.uniform(0, 2 * math.pi)) self._body.position = source._body.position self._body.velocity = source._body.velocity + p self._shape = pymunk.Circle(self._body, r) self._shape.elasticity = 1.0 self._shape.friction= 0.0 self._shape.collision_type = COLLISION_TYPES["resource"] self._shape._get_resource = ref(self) self._shape.sensor = True SPACE.add(self._body, self._shape) SPACE.resources.add(self)
def __init__(self, source=None, damage=1): source_body = source._body # physics r = 3 mass = 0.01 inertia = pymunk.moment_for_circle(mass, 0, r) self._body = pymunk.Body(mass, inertia) p = Vec2d(BLOCK_SIZE, 0) p.angle = source_body.angle + math.pi / 2 + source.direction * math.pi / 2 self._body.position = source_body.position + p self._body.velocity = source_body.velocity + p * BLOCK_SIZE * 2 self._shape = pymunk.Circle(self._body, r) self._shape.collision_type = COLLISION_TYPES["blaster"] self._shape._get_projectile = ref(self) SPACE.add(self._body, self._shape) SPACE.projectiles.add(self) # SFX if settings.SOUND: random.choice(BLASTER_SFX).play()
def __init__(self, point): self._joints = WeakSet() self._adjacent_blocks = WeakSet() # load images base_path = "images/blocks/{}.png".format(self.image) damaged_path = "images/blocks/{}_damaged.png".format(self.image) destroyed_path = "images/blocks/{}_destroyed.png".format(self.image) self.img = load_image(base_path, self.image_anchor) self.img_damaged = load_image(damaged_path, self.image_anchor) self.img_destroyed = load_image(destroyed_path, self.image_anchor) w = h = BLOCK_SIZE # using (density * 1 ** 2) for these because our units are BLOCK_SIZE inertia = pymunk.moment_for_box(self.material.density, w, h) self._body = pymunk.Body(self.material.density, inertia) self._body.position = point self._shape = pymunk.Poly.create_box(self._body, (w, h)) self._shape.elasticity = self.material.elasticity self._shape.friction = self.material.friction self._shape.collision_type = self.material.collision_type self._shape._get_block = ref(self) SPACE.add(self._body, self._shape) SPACE.register_block(self)
def __init__(self, point, radius, velocity=Vec2d(0, 0), damage=0): self.radius = radius self.damage = damage inertia = pymunk.moment_for_circle(pymunk.inf, 0, radius) self._body = pymunk.Body(pymunk.inf, inertia) self._body.position = point self._body.velocity = velocity self._shape = pymunk.Circle(self._body, radius) self._shape.collision_type = COLLISION_TYPES['explosion'] self._shape._get_explosion = ref(self) SPACE.add(self._body, self._shape) SPACE.register_explosion(self) # play SFX if settings.SOUND: sound = random.choice(EXPLOSION_SFX) # TODO: 3D sound #volume = (500 - (SPACE.camera_lock()._body.position - self._body.position).length) / 500 #if volume > 0: # print volume # sound.volume = random.choice([1.0, .5, .25]) sound.play()
def enemy_ai_update(self): # TODO: This is pretty stupid AI. We'll have to work on that later. # ALWAYS TURN ON SHIELDS if not self.shieldsup: [b.on_key_down() for b in self.slave_blocks if isinstance(b, ShieldBlock)] self.shieldsup = True # ALWAYS FLY TOWARDS PLAYER if not SPACE.camera_lock(): # they win and quit moving [b.on_key_up() for b in self.slave_blocks] return target = SPACE.camera_lock # this is naive, but works for now target_dir = target()._body.position - self._body.position ang = (self._body.angle - target_dir.angle + math.pi / 2) % (math.pi * 2) general_direction = abs((ang) % (math.pi * 2)) < math.pi / 8 ang += self._body.angular_velocity if ang > 0 and abs(ang) <= math.pi: best_direction = "ccw" elif ang > 0 and abs(ang) > math.pi: best_direction = "cw" elif ang < 0 and abs(ang) <= math.pi: best_direction = "cw" elif ang < 0 and abs(ang) > math.pi: best_direction = "ccw" if self._body.angular_velocity > math.pi / 2: [b.on_key_up() for b in self.slave_blocks if b.key == key.LEFT] [b.on_key_down() for b in self.slave_blocks if b.key == key.RIGHT] elif self._body.angular_velocity < -math.pi / 2: [b.on_key_up() for b in self.slave_blocks if b.key == key.RIGHT] [b.on_key_down() for b in self.slave_blocks if b.key == key.LEFT] # TODO: If moving very fast relative to the target, slow down elif best_direction == "cw": [b.on_key_up() for b in self.slave_blocks if b.key == key.RIGHT] [b.on_key_down() for b in self.slave_blocks if b.key == key.LEFT] else: [b.on_key_up() for b in self.slave_blocks if b.key == key.LEFT] [b.on_key_down() for b in self.slave_blocks if b.key == key.RIGHT] # SHOOT AT PLAYER IF CLOSE ang = self._body.angle - target_dir.angle + math.pi / 2 if (target_dir.length <= BLOCK_SIZE * 50 and general_direction): [b.on_key_down() for b in self.slave_blocks if isinstance(b, BlasterBlock)] else: [b.on_key_up() for b in self.slave_blocks if isinstance(b, BlasterBlock)]
def deactivate(self): SPACE.remove(self._tractor_link, self._tractor_body, self._tractor_shape) self._tractor_body = self._tractor_link = self._tractor_shape = None
def deactivate(self): SPACE.remove(self._shield_link, self._shield_body, self._shield_shape) self._shield_body = self._shield_link = self._shield_shape = None
def upkeep(self): self.ttl -= 1 if self.ttl < 1: SPACE.remove(self._shape, self._body) SPACE.projectiles.remove(self)
def upkeep(self): self.ticks -= 1 if self.ticks <= 0: SPACE.remove(self._body, self._shape) SPACE.explosions.remove(self)