diff --git a/lab5/IntroRust.otf b/lab5/IntroRust.otf new file mode 100644 index 0000000..7cc32d5 Binary files /dev/null and b/lab5/IntroRust.otf differ diff --git a/lab5/ProximaNova.otf b/lab5/ProximaNova.otf new file mode 100644 index 0000000..82fa9ff Binary files /dev/null and b/lab5/ProximaNova.otf differ diff --git a/lab5/gun.py b/lab5/gun.py index 570bc05..5d7b3da 100644 --- a/lab5/gun.py +++ b/lab5/gun.py @@ -1,6 +1,7 @@ from __future__ import annotations import math from copy import deepcopy +import time from random import choice, uniform, randrange as rnd from dataclasses import dataclass, field @@ -23,6 +24,9 @@ GAME_COLORS = [RED, BLUE, YELLOW, GREEN, MAGENTA, CYAN] WIDTH = 800 HEIGHT = 600 +pygame.init() +font = pygame.font.Font('IntroRust.otf', 25) +font2 = pygame.font.Font('IntroRust.otf', 16) @dataclass @@ -33,6 +37,7 @@ class Ball: color: int = field(default_factory=lambda: choice(GAME_COLORS)) time_to_split: typing.Optional[int] = field(default_factory=lambda: choice([None, rnd(5, 25)])) live: int = 30 + source: int = 0 def move(self): """Переместить мяч по прошествии единицы времени. @@ -92,6 +97,7 @@ class Ball: @dataclass class Gun: + gun_id: int = field(default_factory=lambda: rnd(1, 1000000)) bullet: bool = 0 f2_power: int = 10 f2_on: bool = 0 @@ -118,14 +124,15 @@ class Gun: new_ball.r += 5 new_ball.v[0] = self.f2_power * math.cos(self.an) new_ball.v[1] = - self.f2_power * math.sin(self.an) + new_ball.source = self.gun_id game.balls.append(new_ball) self.f2_on = False self.f2_power = 10 def targetting(self, event): """Прицеливание. Зависит от положения мыши.""" - if event and event.pos[0] != 20: - self.an = math.atan((event.pos[1] - self.y0) / (event.pos[0] - self.x0)) + if event and event.pos[0] != self.x0: + self.an = math.atan2((event.pos[1] - self.y0), (event.pos[0] - self.x0)) if self.f2_on: self.color = RED else: @@ -179,6 +186,13 @@ class Gun: else: self.color = GREY + def hittest(self, obj): + if self.x0 - 50 - obj.r < obj.position[0] < self.x0 + 50 + obj.r \ + and self.y0 - obj.r < obj.position[1] < self.y0 + 35 + obj.r \ + and hasattr(obj, 'source') and obj.source != self.gun_id: + return True + return False + @dataclass class Target: @@ -188,7 +202,6 @@ class Target: vx: float = field(default_factory=lambda: rnd(-4, 6)) vy: float = field(default_factory=lambda: rnd(-4, 6)) color: int = RED - points: int = 0 live: int = 1 ax: float = 0 ay: float = 0 @@ -197,9 +210,9 @@ class Target: oscillation_ampl: float = field(default_factory=lambda: rnd(0, 6) * choice([0, 0, 1])) oscillation_phase: float = field(default_factory=lambda: uniform(0, 2 * np.pi)) - def hit(self, points=1): + def hit(self, game: Game, points=1): """Попадание шарика в цель.""" - self.points += points + game.points += points def draw(self, screen): pygame.draw.circle( @@ -264,6 +277,8 @@ class Game: finished: bool = False clock: pygame.time.Clock = field(default_factory=pygame.time.Clock) fps: int = FPS + points: int = 0 + screen: pygame.Surface = field(default_factory=lambda: pygame.display.set_mode((WIDTH, HEIGHT))) def move(self): for target in self.targets: @@ -276,11 +291,14 @@ class Game: ball1, ball2 = ball.get_split() self.balls.pop([i for i in range(len(self.balls)) if self.balls[i].position is ball.position][0]) self.balls.extend([ball1, ball2]) + for gun in self.guns: + if gun.hittest(ball): + self.guns.remove(gun) for target in self.targets: if ball.hittest(target) and target.live: target.live = 0 ball.live = -1 - target.hit() + target.hit(self) self.targets.remove(target) self.targets.append(Target()) for gun in self.guns: @@ -294,6 +312,8 @@ class Game: target.draw(screen) for ball in self.balls: ball.draw(screen) + score_text = font.render(str(self.points), 1, BLACK) + screen.blit(score_text, (10, 10)) pygame.display.update() def process_event(self, event): @@ -307,9 +327,8 @@ class Game: gun.handle_event(event, self) def main_loop(self): - screen = pygame.display.set_mode((WIDTH, HEIGHT)) while not self.finished: - self.draw(screen) + self.draw(self.screen) self.clock.tick(self.fps) for event in pygame.event.get(): self.process_event(event) @@ -317,6 +336,28 @@ class Game: pygame.quit() -pygame.init() +rules_text = ''' +Управление левой пушкой: +a - влево, d - вправо, qe - наведение, s - стрелять +Управление правой: +jl - движение, uo - наведение, k - стрелять + +Некоторые снаряды разрывные - разбиваются на 2. +Цели бывают обычные (те, которые полностью красные) - они +движутся, просто отражаясь от стенок, - +а также те, которые движутся случайно, и те, которые вращаются + +Кликните, чтобы начать +''' game = Game() +y = 100 +game.screen.fill(0x2e2646) +for line in rules_text.split('\n'): + surface = font2.render(line, True, WHITE) + game.screen.blit(surface, (WIDTH / 2 - surface.get_width() / 2, y)) + y += 5 + surface.get_height() +rules_surface = font2.render(rules_text, True, WHITE) +pygame.display.update() +while not any(ev.type == pygame.MOUSEBUTTONUP or ev.type == pygame.QUIT for ev in pygame.event.get()): + pass game.main_loop()