-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
149 lines (131 loc) · 4.88 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# Force download of relative modules from jsdelivr before importing.
for module_path in ("ball.py", "paddle.py", "brick.py", "hud.py"):
open(module_path).close()
import pyxel
import enum
from ball import Ball
from paddle import Paddle
from brick import check_levels, load_level
from hud import draw_hud, draw_dropped, draw_game_over, draw_win
class GameState(enum.Enum):
READY = 0
RUNNING = 1
DROPPED = 2
GAME_OVER = 3
WIN = 4
PADDLE_SOUND = 0
BRICK_SOUND = 1
DROP_SOUND = 2
class App:
def __init__(self):
pyxel.init(width=384, height=300, display_scale=3, title="Breakout", fps=60)
pyxel.load("assets/resources.pyxres")
self.levels = check_levels()
self.paddle = Paddle()
self.ball = Ball()
self.reset_ball()
self.bounces = 0
self.live = None
self.score = None
self.bricks = None
self.current_level = None
self.current_game_state = None
self.start_new_game()
pyxel.run(self.update, self.draw)
def start_new_game(self):
self.lives = 3
self.current_level = 1
self.score = 0
self.bricks = load_level(self.levels[self.current_level - 1])
self.reset_ball()
self.current_game_state = GameState.READY
def reset_ball(self):
self.ball.x = self.paddle.x + self.paddle.w / 2 + 10
self.ball.y = self.paddle.y - self.ball.r
self.ball.speedX = self.paddle.deflect_force(self.ball.x)
self.ball.speedY = -2.5
self.ball.out_of_bounds = False
self.bounces = 0
def start_next_level(self):
self.current_level += 1
self.bricks = load_level(self.levels[self.current_level - 1])
self.current_game_state = GameState.READY
self.reset_ball()
def update(self):
self.check_input()
self.paddle.update()
if self.current_game_state == GameState.READY:
# Update the ball X position: it should be stuck to the paddle
self.ball.x = self.paddle.x + self.paddle.w / 2 + 10
if self.current_game_state == GameState.RUNNING:
self.ball.update()
self.check_collision()
if self.ball.out_of_bounds:
pyxel.play(0, DROP_SOUND)
self.lives -= 1
if self.lives > 0:
self.current_game_state = GameState.DROPPED
else:
self.current_game_state = GameState.GAME_OVER
def check_collision(self):
# Ball vs Paddle
collision, _ = self.ball.detect_collision(self.paddle, paddle=True)
if collision:
pyxel.play(0, PADDLE_SOUND)
self.bounces += 1
self.check_speedup()
# Ball vs Bricks
for i in reversed(range(len(self.bricks))):
b = self.bricks[i]
collision, score = self.ball.detect_collision(b)
if collision:
pyxel.play(0, BRICK_SOUND)
self.bounces += 1
self.check_speedup()
self.score += score
del self.bricks[i]
self.check_level_complete()
break
def check_speedup(self):
if self.bounces == 4:
self.ball.speedup(1.0)
if self.bounces == 12:
self.ball.speedup(2.0)
def check_level_complete(self):
if len(self.bricks) == 0:
if len(self.levels) > self.current_level:
self.start_next_level()
else:
self.current_game_state = GameState.WIN
def check_input(self):
if self.current_game_state == GameState.READY:
if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT) or pyxel.btnp(pyxel.KEY_SPACE):
# Launch the ball and set the game running
self.current_game_state = GameState.RUNNING
if self.current_game_state == GameState.DROPPED:
if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT) or pyxel.btnp(pyxel.KEY_SPACE):
self.reset_ball()
self.current_game_state = GameState.READY
if (
self.current_game_state == GameState.GAME_OVER
or self.current_game_state == GameState.WIN
):
if pyxel.btnp(pyxel.KEY_RETURN):
self.start_new_game()
def draw(self):
pyxel.cls(0)
self.paddle.draw()
for b in self.bricks:
b.draw()
self.ball.draw()
draw_hud(score=self.score, lives=self.lives)
if self.current_game_state == GameState.DROPPED:
draw_dropped()
if self.current_game_state == GameState.GAME_OVER:
draw_game_over(score=self.score)
if self.current_game_state == GameState.WIN:
draw_win(score=self.score)
# pyxel.text(10, pyxel.height - 20, str(self.current_game_state), 7)
# pyxel.text(10, pyxel.height - 10, str(self.score), 7)
# Kickstart our app
App()