def update(self): time = pyxel.frame_count p1_state = State(is_right_side=False, mine_team=self.p1.state, enemy_team=self.p2.state, ball_pos=self.ball.pos, time=time) p2_state = State(is_right_side=True, mine_team=self.p2.state, enemy_team=self.p1.state, ball_pos=self.ball.pos, time=time) self.p1.update(p1_state) self.p2.update(p2_state) ball_pos = self.ball.updated() self.ball.pos = ball_pos if ball_pos.y <= 0: self.ball.pos = Pos(ball_pos.x, -ball_pos.y) self.ball.vy *= -1 if ball_pos.y >= self.game_info.height: self.ball.pos = Pos( ball_pos.x, self.game_info.height - (ball_pos.y - self.game_info.height)) self.ball.vy *= -1 if ball_pos.x < 0: # p2 ゴール play_se(Sound.RIGHT_POINT) self.p2.add_score() self.ball.pos = Pos(self.game_info.width // 2, self.game_info.height // 2) self.ball.vx = 1 self.ball.vy = random.random() * 2 if ball_pos.x > self.game_info.width: # p1 ゴール play_se(Sound.LEFT_POINT) self.p1.add_score() self.ball.pos = Pos(self.game_info.width // 2, self.game_info.height // 2) self.ball.vx = -1 self.ball.vy = random.random() * 2 for player in (self.p1, self.p2): if player.atk_pos.x - BAR_WIDTH // 2 <= ball_pos.x <= player.atk_pos.x + BAR_WIDTH // 2: if player.atk_pos.y - ATK_SIZE // 2 <= ball_pos.y <= player.atk_pos.y + ATK_SIZE // 2: self.ball.vx = self.ball.vx * -1 diff = ball_pos.y - player.atk_pos.y + (random.random() - 0.5) * 2 self.ball.vy += diff if player.def_pos.x - BAR_WIDTH // 2 <= ball_pos.x <= player.def_pos.x + BAR_WIDTH // 2: if player.def_pos.y - DEF_SIZE // 2 <= ball_pos.y <= player.def_pos.y + DEF_SIZE // 2: self.ball.vx = self.ball.vx * -1 diff = ball_pos.y - player.def_pos.y self.ball.vy += diff // 6 # 最高速度規制 if self.ball.vy > MAX_VY: self.ball.vy = MAX_VY if self.ball.vy < -MAX_VY: self.ball.vy = -MAX_VY
def __init__(self, gi: GameInfo, team: Team, reversed: bool): validate_name(team.name) self.team = team self.game_info = gi self.score = 0 if not reversed: self.atk_pos = Pos(gi.width // 12 * 5, gi.height // 2) self.def_pos = Pos(gi.width // 12 * 1, gi.height // 2) else: self.atk_pos = Pos(gi.width // 12 * 7, gi.height // 2) self.def_pos = Pos(gi.width // 12 * 11, gi.height // 2)
def update(info, ball): # ボールの動作コピペ ball_pos = ball.updated() ball.pos = ball_pos ball_x, ball_y = ball_pos if ball_pos.y <= 0: ball.pos = Pos(ball_pos.x, -ball_pos.y) ball.vy *= -1 if ball_pos.y >= info.height: ball.pos = Pos(ball_pos.x, info.height - (ball_pos.y - info.height)) ball.vy *= -1 return ball
def __init__(self, width: int, height: int, offset_x: int, offset_y: int, left_team: Team, right_team: Team): self.game_info = GameInfo(width=width, height=height) self.p1 = TeamManager(self.game_info, left_team, reversed=False) self.p2 = TeamManager(self.game_info, right_team, reversed=True) self.offset_x = offset_x self.offset_y = offset_y self.ball = Ball(BALL_SIZE, Pos(width // 2, height // 2), 1, random.random() * 5)
def update(self, state: State): # ゲームが長引いたらだんだん近づける # (TeamManager がこれを持ってしまってるのあまりよくない) direction = -1 if state.is_right_side else 1 time_pos = direction * 0.1 if state.time % SADDEN_DEATH_DURATION == 1 else 0 # これ以上は近づけない if self.game_info.width // 2 - DMZ_SIZE < self.atk_pos.x < self.game_info.width // 2 + DMZ_SIZE: time_pos = 0 atk_action = self.team.atk_action(info=self.game_info, state=state) assert isinstance(atk_action, (int, float)), 'atk_action の返り値が数値ではありません' assert -self.game_info.atk_return_limit <= atk_action <= self.game_info.atk_return_limit, 'atk_action の返り値が大きすぎます' self.atk_pos = Pos(self.atk_pos.x + time_pos, self._move_y(atk_action, self.atk_pos, ATK_SIZE)) def_action = self.team.def_action(info=self.game_info, state=state) assert isinstance(atk_action, (int, float)), 'def_action の返り値が数値ではありません' assert -self.game_info.def_return_limit <= def_action <= self.game_info.def_return_limit, 'def_action の返り値が大きすぎます' self.def_pos = Pos(self.def_pos.x + time_pos * 5, self._move_y(def_action, self.def_pos, DEF_SIZE))
def draw(self): pyxel.rect(self.offset_x, self.offset_y, self.game_info.width, self.game_info.height, Color.GRAY.value) ball_x, ball_y = self.absolute(self.ball.pos) pyxel.rect(ball_x - BALL_SIZE // 2, ball_y - BALL_SIZE // 2, BALL_SIZE, BALL_SIZE, Color.GREEN.value) for player in (self.p1, self.p2): x, y = self.absolute(player.atk_pos) pyxel.rect(x - BAR_WIDTH // 2, y - ATK_SIZE // 2, BAR_WIDTH, ATK_SIZE, Color.BLUE.value) x, y = self.absolute(player.def_pos) pyxel.rect(x - BAR_WIDTH // 2, y - DEF_SIZE // 2, BAR_WIDTH, DEF_SIZE, Color.YELLO.value) x, y = self.absolute(Pos(0, self.game_info.height)) scores = f'{self.p1.score_label} {self.p2.score_label}' pyxel.text(x + PADDING, y + PADDING, scores, Color.GRAY.value)
def updated(self): return Pos(self.pos.x + self.vx, self.pos.y + self.vy)
def __init__(self): self.prev_ball = Pos(0, 0)