-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import pygame | ||
|
||
import game.game_config as config | ||
|
||
|
||
class Block: | ||
def __init__(self, x, y, color): | ||
self.x = x | ||
self.y = y | ||
self.color = color | ||
|
||
def draw(self, screen): | ||
pygame.draw.rect(screen, self.color, (self.x, self.y, | ||
config.BLOCK_LEN, config.BLOCK_LEN)) | ||
|
||
def get_points(self): | ||
return [(self.x, self.y), (self.x + config.BLOCK_LEN, self.y), | ||
(self.x + config.BLOCK_LEN, self.y + config.BLOCK_LEN), | ||
(self.x, self.y + config.BLOCK_LEN)] | ||
|
||
def move_y_pos(self, y): | ||
self.y -= y | ||
|
||
|
||
class Pipe(Block): | ||
def __init__(self, x, y, w, color): | ||
super().__init__(x, y, color) | ||
self.w = w | ||
self.scored = False | ||
|
||
def draw(self, screen): | ||
pygame.draw.rect(screen, self.color, (self.x, self.y, | ||
self.w, config.PIPE_HEIGHT)) | ||
|
||
def get_points(self): | ||
return [(self.x, self.y), (self.x + self.w, self.y), (self.x + self.w, self.y + config.PIPE_HEIGHT), | ||
(self.x, self.y + config.PIPE_HEIGHT)] | ||
|
||
|
||
class Player(Block): | ||
def __init__(self, x, y, color): | ||
super().__init__(x, y, color) | ||
self.vx = 0 | ||
self.vy = 0 | ||
self.g = config.GRAVITY | ||
self.ax = config.ACC_X | ||
self.ay = config.ACC_Y | ||
|
||
def get_points(self): | ||
points = [(self.x + config.PLAYER_LEN, self.y), (self.x, self.y + config.PLAYER_LEN), | ||
(self.x - config.PLAYER_LEN, self.y), (self.x, self.y - config.PLAYER_LEN)] | ||
return points | ||
|
||
def draw(self, screen): | ||
points = self.get_points() | ||
pygame.draw.polygon(screen, self.color, points) | ||
|
||
def no_move(self): | ||
self.vy += self.g | ||
self.__move() | ||
|
||
def move_left(self): | ||
self.vx = 0 | ||
self.vy = 0 | ||
self.vx -= self.ax | ||
self.vy -= (self.ay - self.g) | ||
self.__move() | ||
|
||
def move_right(self): | ||
self.vx = 0 | ||
self.vy = 0 | ||
self.vx += self.ax | ||
self.vy -= (self.ay - self.g) | ||
self.__move() | ||
|
||
def __move(self): | ||
self.x += self.vx | ||
self.y += self.vy | ||
if self.x - config.PLAYER_LEN < 0: | ||
self.x = config.PLAYER_LEN | ||
elif self.x + config.PLAYER_LEN > config.WINDOW_WIDTH: | ||
self.x = config.WINDOW_WIDTH - config.PLAYER_LEN |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import random | ||
|
||
import pygame | ||
|
||
import game.game_config as config | ||
from game.block import Block, Pipe, Player | ||
from pygame_colliders import ConvexCollider | ||
|
||
pygame.init() | ||
|
||
SCREEN = pygame.display.set_mode((config.WINDOW_WIDTH, config.WINDOW_HEIGHT), pygame.NOFRAME) | ||
|
||
|
||
class Game: | ||
def __init__(self): | ||
self.score = 0 | ||
self.colorId = 0 | ||
self.pipes = [] | ||
self.blocks = [] | ||
self.player = Player(config.WINDOW_WIDTH / 2, | ||
config.WINDOW_HEIGHT / 2, config.PLAYER_COLOR) | ||
self.start = False | ||
self.__draw() | ||
|
||
def reset(self): | ||
self.__init__() | ||
|
||
def frame_step(self, action): | ||
if action == config.ACTION.NOTHING: | ||
if self.start: | ||
self.player.no_move() | ||
elif action == config.ACTION.LEFT: | ||
self.start = True | ||
self.player.move_left() | ||
elif action == config.ACTION.RIGHT: | ||
self.start = True | ||
self.player.move_right() | ||
|
||
self.__handle_pipe_blocks() | ||
self.__move_y_pos() | ||
self.__calculate_score() | ||
self.__draw() | ||
return self.__is_collision() | ||
|
||
def __handle_pipe_blocks(self): | ||
n = len(self.pipes) | ||
if n == 0: | ||
gap_y = -config.PIPE_HEIGHT | ||
gap_x = self.__create_pipe(gap_y) | ||
self.__create_block(gap_x, gap_y) | ||
elif n < 6: | ||
gap_y = self.pipes[n - 1].y - config.WINDOW_HEIGHT / 2 | ||
gap_x = self.__create_pipe(gap_y) | ||
self.__create_block(gap_x, gap_y, True) | ||
else: | ||
pipe = self.pipes[0] | ||
if pipe.y >= config.WINDOW_HEIGHT: | ||
self.pipes.pop(0) | ||
self.pipes.pop(0) | ||
|
||
while self.blocks[0].y >= config.WINDOW_HEIGHT: | ||
self.blocks.pop(0) | ||
|
||
def __create_pipe(self, y): | ||
gap_x = random.randint(config.PIPE_GAP_X[0], config.PIPE_GAP_X[1]) | ||
self.pipes.append(Pipe(0, y, gap_x, config.COLORS[self.colorId])) | ||
self.pipes.append( | ||
Pipe(gap_x + config.PIPE_GAP_LEN, y, config.WINDOW_WIDTH - gap_x - config.PIPE_GAP_LEN, | ||
config.COLORS[self.colorId])) | ||
return gap_x | ||
|
||
def __create_block(self, gap_x, gap_y, two=False): | ||
mid_x = gap_x + config.PIPE_GAP_LEN / 2 | ||
mid_y = gap_y + config.PIPE_HEIGHT / 2 | ||
if two: | ||
dx = random.randint(int(config.BLOCK_AREA_WIDTH[0]), int(config.BLOCK_AREA_WIDTH[1])) | ||
dy = random.randint(int(config.BLOCK_AREA_HEIGHT[0]), int(config.BLOCK_AREA_HEIGHT[1])) | ||
self.blocks.append(Block(mid_x + dx, mid_y + dy, config.COLORS[self.colorId])) | ||
dx = random.randint(int(config.BLOCK_AREA_WIDTH[0]), int(config.BLOCK_AREA_WIDTH[1])) | ||
dy = random.randint(int(config.BLOCK_AREA_HEIGHT[0]), int(config.BLOCK_AREA_HEIGHT[1])) | ||
self.blocks.append(Block(mid_x + dx, mid_y - dy, config.COLORS[self.colorId])) | ||
|
||
def __move_y_pos(self): | ||
t = self.player.y - config.WINDOW_HEIGHT / 2 | ||
if t < 0: | ||
self.player.move_y_pos(t) | ||
for pipe in self.pipes: | ||
pipe.move_y_pos(t) | ||
for block in self.blocks: | ||
block.move_y_pos(t) | ||
|
||
def __draw(self): | ||
SCREEN.fill(config.BACKGROUND_COLOR) | ||
for pipe in self.pipes: | ||
pipe.draw(SCREEN) | ||
for block in self.blocks: | ||
block.draw(SCREEN) | ||
self.player.draw(SCREEN) | ||
pygame.display.update() | ||
|
||
def __is_collision(self): | ||
if self.player.y + config.PLAYER_LEN >= config.WINDOW_HEIGHT: | ||
return True | ||
player_points = self.player.get_points() | ||
collider_player = ConvexCollider(player_points) | ||
for pipe in self.pipes: | ||
if pipe.y + config.PIPE_HEIGHT < self.player.y - config.PLAYER_LEN: | ||
break | ||
else: | ||
pipe_points = pipe.get_points() | ||
collider_pipe = ConvexCollider(pipe_points) | ||
if collider_player.collide(collider_pipe): | ||
return True | ||
|
||
for block in self.blocks: | ||
if block.y + config.BLOCK_LEN < self.player.y - config.PLAYER_LEN: | ||
break | ||
else: | ||
block_points = block.get_points() | ||
collider_block = ConvexCollider(block_points) | ||
if collider_player.collide(collider_block): | ||
return True | ||
|
||
return False | ||
|
||
def __calculate_score(self): | ||
for pipe in self.pipes: | ||
if not pipe.scored: | ||
if pipe.y >= config.WINDOW_HEIGHT / 2: | ||
self.score += 0.5 | ||
pipe.scored = True | ||
else: | ||
break | ||
self.colorId = int(self.score) // len(config.COLORS) % len(config.COLORS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from enum import Enum | ||
|
||
# 帧数 | ||
FPS = 60 | ||
|
||
# 窗口大小 | ||
WINDOW_WIDTH = 378 | ||
WINDOW_HEIGHT = 680 | ||
|
||
# 颜色 | ||
BACKGROUND_COLOR = (250, 255, 250) | ||
PLAYER_COLOR = (0, 0, 0) | ||
COLORS = ( | ||
[140, 188, 255], | ||
[149, 93, 182], | ||
[238, 92, 66], | ||
[232, 219, 34], | ||
[139, 232, 146] | ||
) | ||
|
||
# 玩家方块大小 | ||
PLAYER_LEN = 15 | ||
|
||
# 矩形障碍物 | ||
PIPE_HEIGHT = 36 | ||
PIPE_GAP_LEN = 128 | ||
PIPE_GAP_X = (0 + 30, WINDOW_WIDTH - PIPE_GAP_LEN - 30) | ||
|
||
# 正方形障碍物 | ||
BLOCK_LEN = 25 | ||
BLOCK_AREA_WIDTH = (-PIPE_GAP_LEN * 0.4, PIPE_GAP_LEN * 0.4) | ||
BLOCK_AREA_HEIGHT = (PIPE_GAP_LEN * 0.6, PIPE_GAP_LEN * 0.8) | ||
|
||
# 物理参数 | ||
GRAVITY = 0.25 | ||
ACC_X = 1.0 | ||
ACC_Y = 8.5 | ||
|
||
|
||
# 动作 | ||
class ACTION(Enum): | ||
NOTHING = 0 | ||
LEFT = 1 | ||
RIGHT = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from game.game import Game | ||
from game.game_config import FPS | ||
from game.game_config import ACTION | ||
import pygame | ||
|
||
game_state = Game() | ||
|
||
fps_clock = pygame.time.Clock() | ||
|
||
run = True | ||
while run: | ||
action = ACTION.NOTHING | ||
for event in pygame.event.get(): | ||
if event.type == pygame.QUIT: | ||
run = False | ||
if event.type == pygame.KEYDOWN: | ||
if event.key == pygame.K_LEFT: | ||
action = ACTION.LEFT | ||
elif event.key == pygame.K_RIGHT: | ||
action = ACTION.RIGHT | ||
elif event.key == pygame.K_ESCAPE: | ||
run = False | ||
|
||
done = game_state.frame_step(action) | ||
if done: | ||
print(game_state.score) | ||
game_state.reset() | ||
|
||
fps_clock.tick(FPS) | ||
|
||
pygame.quit() |