def __init__(self, scene, spawn_cell: tuple, *groups): super().__init__( scene, Cell.WIDTH * spawn_cell[0] + (Cell.WIDTH - self.WIDTH) // 2, Cell.HEIGHT * (spawn_cell[1] + 1) - self.HEIGHT, *groups) self.speed_y = Float(0) self.speed_x = Float(0) self.last_x_direction = DirectionX.RIGHT self.weapon_index = 0 self.weapons = [NoneWeapon(self.scene, self), Pistol(self.scene, self)] self.set_weapon(self.weapon_index) ObjectWithHealth.__init__(self)
def __init__(self, scene, obj, *groups, offset_y=Properties.OFFSET_Y): super().__init__(scene, 0, 0, *groups, render_level=3) self.obj = obj BarIndicator.__init__(self, Properties.WIDTH, Properties.HEIGHT, BarIndicatorColor(*Properties.BAR_COLOR), Properties.BORDER_SIZE, obj.get_max_health(), obj.get_health()) self.offset_y = Float(offset_y)
def process_logic(self, events): if self.is_dead(): self.scene.game_over() for event in events: if event.type == pg.KEYDOWN and event.key == pg.K_c: self.set_weapon((self.weapon_index + 1) % len(self.weapons)) pressed = pg.key.get_pressed() if pressed[pg.K_a]: self.speed_x = -Properties.X_SPEED if pressed[pg.K_d]: self.speed_x = Properties.X_SPEED if pressed[pg.K_SPACE]: if self.is_grounded(): self.speed_y = -sqrt( 2 * Gravitation.G * Properties.JUMP_HEIGHT) if not self.is_grounded(): self.speed_y += Gravitation.G vector_x = Float(self.speed_x) vector_y = Float(self.speed_y) self.add_vectors(vector_x, vector_y) self.speed_x = Float(self.speed_x) self.speed_y = Float(self.speed_y) if self.get_y() >= self.scene.height: self.damage(self.get_max_health()) if not self.animation.playing_once: if self.speed_x != 0: self.last_x_direction = (DirectionX.RIGHT if self.speed_x > 0 else DirectionX.LEFT) d = ('left' if self.last_x_direction == DirectionX.LEFT else 'right') if self.speed_x != 0: if self.speed_x > 0: if self.is_grounded(): self.animation.set_animation('walk_right') else: self.animation.set_animation('jump_right') else: if self.is_grounded(): self.animation.set_animation('walk_left') else: self.animation.set_animation('jump_left') else: self.animation.set_animation('none_' + d) self.speed_x = 0 if pg.mouse.get_pressed(3)[0]: self.get_weapon().fire()
def is_grounded(self): if Float(self.speed_y) != 0: return False for obj in self.scene.get_objects('can_collide'): if obj is self: continue if self.get_x2() > obj.get_x1() and self.get_x1() < obj.get_x2( ) and self.get_y2() == obj.get_y1(): return True return False
def update(self): inner_pos = self.get_inner_pos() if Float(inner_pos[0]) > Float(self.obj.get_x()): self.x -= inner_pos[0] - self.obj.get_x() elif Float(self.obj.get_x2()) > Float(inner_pos[0] + self.inner_size[0]): self.x += self.obj.get_x2() - (inner_pos[0] + self.inner_size[0]) if Float(inner_pos[1]) > Float(self.obj.get_y()): self.y -= inner_pos[1] - self.obj.get_y() elif Float(self.obj.get_y2()) > Float(inner_pos[1] + self.inner_size[1]): self.y += self.obj.get_y2() - (inner_pos[1] + self.inner_size[1]) self.x = sorted([0, self.x, self.obj.scene.width - self.width])[1] self.y = sorted([0, self.y, self.obj.scene.height - self.height])[1]
def can_fire(self): if self.remaining == 0: return False self.update_remaining_time() if self.remaining_time > 0: return False d = self.player.get_last_x_direction() if d == DirectionX.LEFT: rect = (self.player.get_x1() - self.get_extra_width() - BulletProperties.WIDTH, self.player.get_y1(), self.player.get_x1(), self.player.get_y2()) else: rect = (self.player.get_x2(), self.player.get_y1(), self.player.get_x2() + self.get_extra_width() + BulletProperties.WIDTH, self.player.get_y2()) if Float(rect[0]) < 0 or Float(rect[2]) > self.scene.get_width() or \ Float(rect[1]) < 0 or Float(rect[3]) > self.scene.get_height(): return False for obj in self.scene.get_objects('can_collide'): if is_intersection(rect, obj.get_rect()): return False return True
def update_image(self): image = get_surface(self.width, self.height) image.fill(self.color.border) offset_x, offset_y = self.border_size image.fill(self.color.background, (offset_x, offset_y, self.width - 2 * offset_x, self.height - 2 * offset_y)) cnt = self.width - 2 * offset_x cnt = int(Float(ceil(cnt * self.current / self.max))) image.fill(self.color.full, (offset_x, offset_y, cnt, self.height - 2 * offset_y)) self.image = image
def add_vectors(self, vector_x, vector_y): # Oy if Float(self.get_y() + vector_y) < 0: vector_y = max(vector_y, -self.get_y()) self.speed_y = 0 for obj in self.scene.get_objects('can_collide'): if obj is self: continue if self.get_x2() > obj.get_x1() and self.get_x1() < obj.get_x2(): if self.get_y2() <= obj.get_y1() < Float(self.get_y2() + vector_y): vector_y = obj.get_y1() - self.get_y2() self.speed_y = 0 if self.get_y1() >= obj.get_y2() > Float(self.get_y1() + vector_y): vector_y = obj.get_y2() - self.get_y1() self.speed_y = 0 self.y += vector_y # Ox if Float(self.get_x1() + vector_x) < 0 or Float(self.get_x2() + vector_x) > Float( self.scene.get_width()): vector_x = sorted([ -self.get_x1(), vector_x, Float(self.scene.get_width() - self.get_x2()) ])[1] self.speed_x = 0 for obj in self.scene.get_objects('can_collide'): if obj is self: continue if self.get_y2() > obj.get_y1() and self.get_y1() < obj.get_y2(): if self.get_x2() <= obj.get_x1() < Float(self.get_x2() + vector_x): vector_x = obj.get_x1() - self.get_x2() self.speed_x = 0 if self.get_x1() >= obj.get_x2() > Float(self.get_x1() + vector_x): vector_x = obj.get_x2() - self.get_x1() self.speed_x = 0 self.x += vector_x
def __init__(self, scene, a: float, b: float, radius: float, *groups): super().__init__(scene, a - radius, b - radius, *groups, render_level=1) self.a = a self.b = b self.radius = radius self.width = int(Float(2 * self.radius)) self.height = int(Float(2 * self.radius)) image_red = get_surface(self.width, self.height) image_green = get_surface(self.width, self.height) for x in range(self.width): for y in range(self.height): if circle_and_rect_collide((Float(x + self.x), Float(y + self.y), Float(x + self.x + 1), Float(y + self.y + 1)), (self.a, self.b, self.radius)): image_red.set_at((x, y), Color.RED) image_green.set_at((x, y), Color.GREEN) dct = { 'none': ((image_red, 1),), 'detected': ((image_green, 30), (image_red, 30)) } self.animation.override_animations(dct)
def add_vector_x(self, vector): if Float(self.get_x1() + vector) < 0 or Float(self.get_x2() + vector) > Float(self.scene.get_width()): vector = sorted([-self.get_x1(), vector, Float(self.scene.get_width() - self.get_x2())])[1] self.speed_x = 0 collided_object = None for obj in self.scene.get_objects('can_collide'): if self.get_y2() > obj.get_y1() and self.get_y1() < obj.get_y2(): if self.get_x2() <= obj.get_x1() < Float(self.get_x2() + vector): vector = obj.get_x1() - self.get_x2() self.speed_x = 0 collided_object = obj if self.get_x1() >= obj.get_x2() > Float(self.get_x1() + vector): vector = obj.get_x2() - self.get_x1() self.speed_x = 0 collided_object = obj if self.collide_with(obj): collided_object = obj self.speed_x = 0 if collided_object is not None: if self.scene.get_group('damageable').has(collided_object): collided_object.damage(self.damage) self.x += vector
def set_health(self, value): if Float(0) <= Float(value) <= self.get_max_health(): self._health = Float(value) self.on_health_updated()
def set_y(self, value): self.y = Float(value)
def get_health(self): return Float(self._health)
def get_x(self): return Float(self.x)
def get_current(self): return Float(self.current)
def subf(segment: tuple, coord: float): if Float(segment[0]) <= Float(coord) <= Float(segment[1]): return 0 return min(Float((coord - segment[0]) ** 2), Float((coord - segment[1]) ** 2))
def is_intersection(r1, r2): # r1, r2 = (x1, y1, x2, y2); # (x1, y1) - левый верхний угол, (x2, y2) - правый нижний return not (Float(r2[3]) <= Float(r1[1]) or Float(r2[0]) >= Float(r1[2]) or Float(r2[1]) >= Float(r1[3]) or Float(r2[2]) <= Float(r1[0]))
def get_middle_x(self): return Float((self.get_x1() + self.get_x2()) / 2)
def circle_and_rect_collide(rect, circle): def subf(segment: tuple, coord: float): if Float(segment[0]) <= Float(coord) <= Float(segment[1]): return 0 return min(Float((coord - segment[0]) ** 2), Float((coord - segment[1]) ** 2)) return Float(subf((rect[0], rect[2]), circle[0]) + subf((rect[1], rect[3]), circle[1])) < Float(circle[2] ** 2)
def set_x(self, value): self.x = Float(value)
def get_x2(self): return Float(self.x + self.width)
def is_dead(self): return self.get_health() == Float(0)
def damage(self, value): value = max(Float(0), Float(self.get_health() - value)) self.set_health(value)
def get_y(self): return Float(self.y)
def get_middle_y(self): return Float((self.get_y1() + self.get_y2()) / 2)
def get_y2(self): return Float(self.y + self.height)
def heal(self, value): value = min(self.get_max_health(), Float(self.get_health() + value)) self.set_health(value)
def process_logic(self, events): if Float(self.speed_x) == 0: self.kill() else: vector_x = self.speed_x self.add_vector_x(vector_x)
def __init__(self, current=None): if current is None: current = self.HEALTH self._max_health = Float(self.HEALTH) self._health = 0 self.set_health(current)
def get_rect(self): return Float(self.x), Float(self.y), Float(self.x + self.width), Float(self.y + self.height)