Repository navigation
Expand file tree
/
Copy pathArkanoidClone.py
More file actions
381 lines (302 loc) · 13 KB
/
Copy pathArkanoidClone.py
File metadata and controls
381 lines (302 loc) · 13 KB
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
import sys
import pygame
import random
from Sprites.PlayerPaddle import PlayerPaddle
from Sprites.Block import Block
from Sprites.Ball import Ball
from Levels.LevelRenderer import LevelRenderer
from Screens.StartScreen import StartScreen
from Screens.EndScreen import EndScreen
from Screens.ContinueScreen import ContinueScreen
from Screens.HighScoreScreen import HighScoreScreen
from Screens.OptionsScreen import OptionsScreen
from Utilities.BoonHandler import BoonHandler
from Utilities.MainGame import MainGame
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
MOUSEBUTTONDOWN,
QUIT
)
# required setup before rendering
pygame.init()
pygame.display.set_caption("BARKanoid")
icon = pygame.image.load("Assests/singledog.png")
pygame.display.set_icon(icon)
main = True
new_game = True
# music and effects
pygame.mixer.init()
pygame.mixer.music.load("Assests/vastness.mp3")
pygame.mixer.music.play(-1)
# main game class
mg = MainGame()
# ------------------------ helper functions -----------------------------------
# ------------------------------------------------------------------------------
def check_for_quit(event):
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == QUIT:
pygame.quit()
sys.exit()
# takes a button action and preforms it -- all button actions must be implemented here
def call_button_function(button):
mg.currentScreen = None
match button.button_action:
case "start": # starts the game
mg.runningStart = False
mg.runningMain = True
case "main": # goes to main screen -- start screen
mg.runningStart = True
mg.runningMain = False
return True
case "highscores":
run_high_score_screen()
case "options":
run_options_screen()
case "continue":
# get and handle boon
mg.boonHandler.handle_boon(mg.boon_name)
case "quit":
pygame.quit()
sys.exit()
# option functions
case "music_on":
pygame.mixer.music.play(-1)
return False
case "music_off":
pygame.mixer.music.stop()
return False
def run_high_score_screen():
runningHighScore = True
while runningHighScore:
if mg.currentScreen is None:
mg.currentScreen = HighScoreScreen()
mg.currentScreen.draw()
mg.currentScreen.update()
for event in pygame.event.get():
check_for_quit(event)
if event.type == MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed(num_buttons=3) == (1,0,0):
for button in mg.currentScreen.button_list:
if pygame.Rect.collidepoint(button.rect, pygame.mouse.get_pos()):
# get button action and call required method
call_button_function(button)
break
runningHighScore = False
pygame.display.flip()
def run_options_screen():
runningOptions = True
exit_options = False
while runningOptions:
if mg.currentScreen is None:
mg.currentScreen = OptionsScreen()
mg.currentScreen.draw()
mg.currentScreen.update()
for event in pygame.event.get():
check_for_quit(event)
if event.type == MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed(num_buttons=3) == (1,0,0):
for button in mg.currentScreen.button_list:
if pygame.Rect.collidepoint(button.rect, pygame.mouse.get_pos()):
# get button action and call required method
exit_options = call_button_function(button)
break
if exit_options:
runningOptions = False
pygame.display.flip()
def run_continue_screen():
runningContinue = True
while runningContinue:
if mg.currentScreen is None:
mg.currentScreen = ContinueScreen()
mg.currentScreen.draw()
boon_number = random.randint(0,len(mg.boonHandler.boons)-1)
mg.boon_name = mg.currentScreen.update(mg.currentLevel, mg.playerScore, mg.boonHandler, boon_number)
for event in pygame.event.get():
check_for_quit(event)
if event.type == MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed(num_buttons=3) == (1,0,0):
for button in mg.currentScreen.button_list:
if pygame.Rect.collidepoint(button.rect, pygame.mouse.get_pos()):
# get button action and call required method
exit_options = call_button_function(button)
break
runningContinue = False
pygame.display.flip()
# -----------------------------------------------------------------------------
# ------------------------ end of helper functions ----------------------------
# ------------------------------ main game logic
while main:
mg.currentScreen = None
runningGameOver = False
levelRenderer = LevelRenderer()
# main sprites
player = PlayerPaddle()
playerGroup = pygame.sprite.GroupSingle(player)
ballGroup = pygame.sprite.Group()
ball = Ball()
ballGroup.add(ball)
mg.boonHandler = BoonHandler(player,ballGroup)
clock = pygame.time.Clock()
mg.playerScore = 0
displayScore = 0
myfont = pygame.font.SysFont("Good Times Regular", 25, True)
level_finished = True
mg.currentLevel = 0
# ----------START of Start Screen Loop-------------
while mg.runningStart:
if mg.currentScreen is None:
mg.currentScreen = StartScreen()
mg.currentScreen.draw()
mg.currentScreen.update()
# always check for exit events before continuing the loop
for event in pygame.event.get():
check_for_quit(event)
if event.type == MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed(num_buttons=3) == (1,0,0):
for button in mg.currentScreen.button_list:
if pygame.Rect.collidepoint(button.rect, pygame.mouse.get_pos()):
# get button action and call required method
call_button_function(button)
break
pygame.display.flip()
# ----------END of Start Screen Loop-------------
# ----------START of Main Game Loop-------------
while mg.runningMain:
clock.tick(60)
# always check for exit events before continuing the loop
for event in pygame.event.get():
check_for_quit(event)
# get the new/next level -- levels gets popped -- we don't keep finished levels---
for level in levelRenderer.levels:
if level_finished:
mg.currentLevel += 1
current_difficulty = level.get_difficulty()
SCREEN_WIDTH = level.get_screen_width()
SCREEN_HEIGHT = level.get_screen_height()
INITIAL_COLOR = level.get_level_color()
screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
print("Drawing main screen!")
all_sprites = pygame.sprite.Group()
# set balls
for ball in ballGroup:
ball.rect.x = (SCREEN_WIDTH/2)
ball.rect.y = (SCREEN_HEIGHT-45)
all_sprites.add(ball)
# set paddle
player.rect.x = ((SCREEN_WIDTH/2)-25)
player.rect.y = (SCREEN_HEIGHT-20)
all_sprites.add(player)
# create function that applies block boons
blocks = level.blocks
level_finished = False
break
if not levelRenderer.levels:
displayScore = mg.playerScore
runningGameOver = True
mg.runningMain = False
break
# --------------------------------------------------------------------------------
# start the game logic after the level has rendered--------------------------------
player.update(pygame.key.get_pressed(), SCREEN_WIDTH)
for ball in ballGroup:
endGame = ball.update(SCREEN_WIDTH,SCREEN_HEIGHT)
if endGame == False and len(ballGroup) == 0:
displayScore = mg.playerScore
mg.runningMain = False
runningGameOver = True
break
## DRAW on screen
#in the loop and first or else objects will appear to grow
screen.fill(INITIAL_COLOR)
for block in blocks:
block.draw(screen, current_difficulty)
for object in all_sprites:
screen.blit(object.surf, object.rect)
score = myfont.render("Score: " + str(mg.playerScore), 1, (255,255,0))
screen.blit(score, (SCREEN_WIDTH-120, 25))
#------------------paddle hit-----------------------------------------------
for ball in ballGroup:
if pygame.sprite.spritecollide(ball, playerGroup, False):
if(ball.rect.bottom-5 <= player.rect.top
and ball.rect.top-5 <= player.rect.top
and ball.velocity[1] >= 0):
ball.bounce("top_or_bottom")
#---------------------------------------------------------------------------
#------------------block hits-----------------------------------------------
blocks_hit = pygame.sprite.spritecollide(ball, blocks, False)
for block in blocks_hit:
# keeping hit logic seperate for easier readability
# -5 and +5 is for offset from imperfect pixel collision on rects
# check velocity on top and bottom bounce eliminates sometimes registering top or bottom bounce when it should be side bounce
# top bounce
if(ball.rect.bottom-5 <= block.rect.top
and ball.rect.top-5 <= block.rect.top
and ball.velocity[1] >= 0):
ball.bounce("top_or_bottom")
# bottom bounce
elif(ball.rect.bottom+5 >= block.rect.bottom
and ball.rect.top+5 >= block.rect.bottom
and ball.velocity[1] < 0):
ball.bounce("top_or_bottom")
# left bounce
elif(ball.rect.left-5 <= block.rect.left
and ball.rect.right-5 <= block.rect.left):
ball.bounce("sides")
# right bounce
elif(ball.rect.left+5 >= block.rect.right
and ball.rect.right+5 >= block.rect.right):
ball.bounce("sides")
mg.playerScore += 10
block.block_hit(screen)
break
#------------------------------------------------------------------------------
if not blocks:
levelRenderer.levels.pop(0)
level_finished = True
# ----------START of Continue Loop-------------
if(len(levelRenderer.levels) > 0):
run_continue_screen()
# ----------END of Continue Loop-------------
pygame.display.flip()
# ----------END of Main Game Loop-------------
# ----------START of Game Over Loop-------------
while runningGameOver:
if mg.currentScreen is None:
mg.currentScreen = EndScreen()
mg.currentScreen.draw()
mg.currentScreen.update(mg.playerScore)
# ----------START of Enter High Score Loop-------------
is_highscore = mg.currentScreen.check_for_high_score(displayScore)
if(is_highscore):
runningEnterHighScore = True
while runningEnterHighScore:
for event in pygame.event.get():
check_for_quit(event)
player_name = mg.currentScreen.draw_high_score_popup()
mg.currentScreen.save_high_score(player_name, mg.playerScore)
displayScore = 0
runningEnterHighScore = False
# ----------START of Enter High Score Loop-------------
for event in pygame.event.get():
check_for_quit(event)
if event.type == MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed(num_buttons=3) == (1,0,0):
for button in mg.currentScreen.button_list:
if pygame.Rect.collidepoint(button.rect, pygame.mouse.get_pos()):
# get button action and call required method
call_button_function(button)
break
runningGameOver = False
pygame.display.flip()
# ----------END of Game Over Loop-------------
pygame.quit()
sys.exit()