Skip to content

Commit bfdc6ec

Browse files
committed
V1
Initial upload of code and assets.
1 parent 44184cd commit bfdc6ec

File tree

6 files changed

+310
-0
lines changed

6 files changed

+310
-0
lines changed

Assets/golf-ball.png

40.3 KB
Loading

Assets/mirror-ball.png

42.1 KB
Loading

Assets/narrow.png

12.8 KB
Loading

Assets/tennis.png

30.3 KB
Loading

Assets/widen.png

20.3 KB
Loading

Game

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
import pygame
2+
import random
3+
import sys
4+
5+
# Initialize
6+
pygame.init()
7+
WIDTH, HEIGHT = 600, 800
8+
screen = pygame.display.set_mode((WIDTH, HEIGHT))
9+
pygame.display.set_caption("Brick")
10+
clock = pygame.time.Clock()
11+
12+
font = pygame.font.SysFont("Arial", 48)
13+
small_font = pygame.font.SysFont("Arial", 24)
14+
15+
WHITE = (255, 255, 255)
16+
RED = (255, 0, 0)
17+
BLACK = (0, 0, 0)
18+
GRAY = (100, 100, 100)
19+
BRICK_COLORS = [(255, 99, 71), (173, 216, 230), (144, 238, 144), (255, 215, 0), (221, 160, 221)]
20+
21+
def draw_vertical_gradient(surface, top_color, bottom_color):
22+
height = surface.get_height()
23+
for y in range(height):
24+
ratio = y / height
25+
r = int(top_color[0] * (1 - ratio) + bottom_color[0] * ratio)
26+
g = int(top_color[1] * (1 - ratio) + bottom_color[1] * ratio)
27+
b = int(top_color[2] * (1 - ratio) + bottom_color[2] * ratio)
28+
pygame.draw.line(surface, (r, g, b), (0, y), (surface.get_width(), y))
29+
30+
# Ball skins
31+
ball_skins = {
32+
"default": None,
33+
"tennis": pygame.image.load("tennis.png"),
34+
"golf": pygame.image.load("golf-ball.png"),
35+
"mirror": pygame.image.load("mirror-ball.png")
36+
}
37+
for key in ball_skins:
38+
if ball_skins[key]:
39+
ball_skins[key] = pygame.transform.scale(ball_skins[key], (20, 20))
40+
selected_skin = "default"
41+
42+
# Powerup icons
43+
powerup_icons = {
44+
'W': pygame.image.load("widen.png"),
45+
'N': pygame.image.load("narrow.png")
46+
}
47+
for key in powerup_icons:
48+
powerup_icons[key] = pygame.transform.scale(powerup_icons[key], (20, 20))
49+
50+
class Particle:
51+
def __init__(self, x, y, color):
52+
self.x = x
53+
self.y = y
54+
self.vx = random.uniform(-2, 2)
55+
self.vy = random.uniform(-2, 2)
56+
self.color = color
57+
self.lifetime = 30
58+
self.size = 4
59+
60+
def update(self):
61+
self.x += self.vx
62+
self.y += self.vy
63+
self.lifetime -= 1
64+
65+
def draw(self, surface):
66+
if self.lifetime > 0:
67+
alpha = max(0, int(255 * (self.lifetime / 30)))
68+
surf = pygame.Surface((self.size, self.size), pygame.SRCALPHA)
69+
surf.fill((*self.color, alpha))
70+
surface.blit(surf, (self.x, self.y))
71+
72+
def draw_button(rect, text):
73+
pygame.draw.rect(screen, GRAY, rect)
74+
pygame.draw.rect(screen, WHITE, rect, 2)
75+
text_surface = small_font.render(text, True, WHITE)
76+
screen.blit(text_surface, (rect.x + rect.width // 2 - text_surface.get_width() // 2, rect.y + rect.height // 2 - text_surface.get_height() // 2))
77+
78+
def show_main_menu():
79+
global selected_skin
80+
while True:
81+
screen.fill(BLACK)
82+
title = font.render("Brick", True, WHITE)
83+
screen.blit(title, (WIDTH // 2 - title.get_width() // 2, HEIGHT // 2 - 150))
84+
start_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 - 30, 150, 50)
85+
exit_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 + 40, 150, 50)
86+
skin_button = pygame.Rect(WIDTH // 2 - 250, HEIGHT // 2 - 30, 150, 50)
87+
draw_button(skin_button, "Ball Skins")
88+
draw_button(start_button, "Start")
89+
draw_button(exit_button, "Exit")
90+
pygame.display.flip()
91+
for event in pygame.event.get():
92+
if event.type == pygame.QUIT:
93+
pygame.quit()
94+
sys.exit()
95+
elif event.type == pygame.MOUSEBUTTONDOWN:
96+
if skin_button.collidepoint(event.pos):
97+
show_skin_menu()
98+
elif start_button.collidepoint(event.pos):
99+
return
100+
elif exit_button.collidepoint(event.pos):
101+
pygame.quit()
102+
sys.exit()
103+
104+
def show_skin_menu():
105+
global selected_skin
106+
while True:
107+
screen.fill(BLACK)
108+
title = font.render("Choose Skin", True, WHITE)
109+
screen.blit(title, (WIDTH // 2 - title.get_width() // 2, 100))
110+
skins = [("default", "Default"), ("tennis", "Tennis"), ("golf", "Golf Ball"), ("mirror", "Mirror Ball")]
111+
buttons = []
112+
for i, (key, label) in enumerate(skins):
113+
btn_rect = pygame.Rect(WIDTH // 2 - 100, 200 + i * 70, 200, 50)
114+
buttons.append((btn_rect, key))
115+
draw_button(btn_rect, label)
116+
back_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT - 100, 150, 50)
117+
draw_button(back_button, "Back")
118+
pygame.display.flip()
119+
for event in pygame.event.get():
120+
if event.type == pygame.QUIT:
121+
pygame.quit()
122+
sys.exit()
123+
elif event.type == pygame.MOUSEBUTTONDOWN:
124+
for btn_rect, key in buttons:
125+
if btn_rect.collidepoint(event.pos):
126+
selected_skin = key
127+
return
128+
if back_button.collidepoint(event.pos):
129+
return
130+
131+
def show_pause_menu():
132+
while True:
133+
screen.fill(BLACK)
134+
title = font.render("Paused", True, WHITE)
135+
screen.blit(title, (WIDTH // 2 - title.get_width() // 2, HEIGHT // 2 - 150))
136+
resume_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 - 30, 150, 50)
137+
menu_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 + 40, 150, 50)
138+
exit_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 + 110, 150, 50)
139+
draw_button(resume_button, "Resume")
140+
draw_button(menu_button, "Quit to Menu")
141+
draw_button(exit_button, "Exit")
142+
pygame.display.flip()
143+
for event in pygame.event.get():
144+
if event.type == pygame.QUIT:
145+
pygame.quit()
146+
sys.exit()
147+
elif event.type == pygame.MOUSEBUTTONDOWN:
148+
if resume_button.collidepoint(event.pos):
149+
return None
150+
elif menu_button.collidepoint(event.pos):
151+
return "menu"
152+
elif exit_button.collidepoint(event.pos):
153+
pygame.quit()
154+
sys.exit()
155+
156+
def reset_game(level=1):
157+
paddle = pygame.Rect(WIDTH // 2 - 80, HEIGHT - 20, 120, 10)
158+
ball = pygame.Rect(WIDTH // 2 - 10, HEIGHT // 2 - 10, 20, 20)
159+
speed = 5 + (level - 1) * 0.5
160+
ball_speed = [speed, -speed]
161+
rows = min(5 + level, 10)
162+
bricks, brick_colors, explosive_indices = [], [], set()
163+
for i in range(10):
164+
for j in range(rows):
165+
idx = len(bricks)
166+
rect = pygame.Rect(5 + i * 60, 40 + j * 30, 50, 20)
167+
bricks.append(rect)
168+
if random.random() < 0.1:
169+
explosive_indices.add(idx)
170+
brick_colors.append(RED) # Red for explosive bricks
171+
else:
172+
brick_colors.append(random.choice(BRICK_COLORS))
173+
174+
return paddle, ball, ball_speed, bricks, brick_colors, explosive_indices, [], None, 0, []
175+
176+
def spawn_powerup(brick_rect):
177+
if random.random() < 0.3:
178+
kind = random.choice(['W', 'N'])
179+
return {'rect': pygame.Rect(brick_rect.centerx, brick_rect.centery, 20, 20), 'type': kind}
180+
return None
181+
182+
def show_game_over_screen():
183+
while True:
184+
screen.fill(BLACK)
185+
title = font.render("Game Over", True, WHITE)
186+
screen.blit(title, (WIDTH // 2 - title.get_width() // 2, HEIGHT // 2 - 120))
187+
restart_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 - 20, 150, 50)
188+
exit_button = pygame.Rect(WIDTH // 2 - 75, HEIGHT // 2 + 60, 150, 50)
189+
draw_button(restart_button, "Restart")
190+
draw_button(exit_button, "Exit")
191+
pygame.display.flip()
192+
for event in pygame.event.get():
193+
if event.type == pygame.QUIT:
194+
pygame.quit()
195+
sys.exit()
196+
elif event.type == pygame.MOUSEBUTTONDOWN:
197+
if restart_button.collidepoint(event.pos):
198+
return "restart"
199+
elif exit_button.collidepoint(event.pos):
200+
pygame.quit()
201+
sys.exit()
202+
203+
def game_loop():
204+
level = 1
205+
while True:
206+
show_main_menu()
207+
level = 1
208+
paddle, ball, ball_speed, bricks, brick_colors, explosive_indices, powerups, active_powerup, powerup_timer, particles = reset_game(level)
209+
running = True
210+
while running:
211+
if level == 1:
212+
draw_vertical_gradient(screen, (0, 0, 50), (0, 0, 0)) # Level 1 gradient
213+
elif level == 2:
214+
draw_vertical_gradient(screen, (50, 0, 0), (0, 0, 50)) # Level 2 gradient
215+
elif level == 3:
216+
draw_vertical_gradient(screen, (0, 50, 0), (0, 0, 50)) # Level 3 gradient
217+
# Add more levels with their respective backgrounds as needed
218+
for event in pygame.event.get():
219+
if event.type == pygame.QUIT:
220+
pygame.quit()
221+
sys.exit()
222+
elif event.type == pygame.KEYDOWN:
223+
if event.key == pygame.K_ESCAPE:
224+
result = show_pause_menu()
225+
if result == "menu":
226+
running = False
227+
keys = pygame.key.get_pressed()
228+
if keys[pygame.K_a] and paddle.left > 0:
229+
paddle.move_ip(-8, 0)
230+
if keys[pygame.K_d] and paddle.right < WIDTH:
231+
paddle.move_ip(8, 0)
232+
ball.move_ip(*ball_speed)
233+
if ball.left <= 0 or ball.right >= WIDTH:
234+
ball_speed[0] *= -1
235+
if ball.top <= 0:
236+
ball_speed[1] *= -1
237+
if ball.bottom >= HEIGHT:
238+
if show_game_over_screen() == "restart":
239+
paddle, ball, ball_speed, bricks, brick_colors, explosive_indices, powerups, active_powerup, powerup_timer, particles = reset_game(level)
240+
continue
241+
else:
242+
pygame.quit()
243+
sys.exit()
244+
if ball.colliderect(paddle) and ball_speed[1] > 0:
245+
ball.bottom = paddle.top
246+
offset = (ball.centerx - paddle.centerx) / (paddle.width / 2)
247+
ball_speed[0] = 5 * offset
248+
ball_speed[1] = -abs(ball_speed[1])
249+
hit_index = ball.collidelist(bricks)
250+
if hit_index != -1:
251+
brick_rect = bricks.pop(hit_index)
252+
brick_color = brick_colors.pop(hit_index)
253+
if hit_index in explosive_indices:
254+
explosive_indices.remove(hit_index)
255+
center_x, center_y = brick_rect.center
256+
explosion_radius = 70
257+
for i in reversed(range(len(bricks))):
258+
if bricks[i].collidepoint(center_x, center_y) or bricks[i].colliderect(pygame.Rect(center_x - explosion_radius, center_y - explosion_radius, explosion_radius * 2, explosion_radius * 2)):
259+
for _ in range(10):
260+
particles.append(Particle(bricks[i].centerx, bricks[i].centery, brick_colors[i]))
261+
bricks.pop(i)
262+
brick_colors.pop(i)
263+
explosive_indices.discard(i)
264+
else:
265+
ball_speed[1] *= -1
266+
for _ in range(10):
267+
particles.append(Particle(brick_rect.centerx, brick_rect.centery, brick_color))
268+
p = spawn_powerup(brick_rect)
269+
if p:
270+
powerups.append(p)
271+
for p in powerups[:]:
272+
p['rect'].y += 4
273+
if p['rect'].colliderect(paddle):
274+
if p['type'] == 'W':
275+
paddle.width = 180
276+
elif p['type'] == 'N':
277+
paddle.width = 60
278+
active_powerup = p['type']
279+
powerup_timer = pygame.time.get_ticks()
280+
powerups.remove(p)
281+
elif p['rect'].top > HEIGHT:
282+
powerups.remove(p)
283+
if active_powerup and pygame.time.get_ticks() - powerup_timer > 10000:
284+
paddle.width = 120
285+
active_powerup = None
286+
if not bricks:
287+
level += 1
288+
pygame.time.delay(1000)
289+
paddle, ball, ball_speed, bricks, brick_colors, explosive_indices, powerups, active_powerup, powerup_timer, particles = reset_game(level)
290+
for particle in particles[:]:
291+
particle.update()
292+
if particle.lifetime <= 0:
293+
particles.remove(particle)
294+
for particle in particles:
295+
particle.draw(screen)
296+
pygame.draw.rect(screen, WHITE, paddle)
297+
if selected_skin == "default" or ball_skins[selected_skin] is None:
298+
pygame.draw.ellipse(screen, WHITE, ball)
299+
else:
300+
screen.blit(ball_skins[selected_skin], ball.topleft)
301+
for i, brick in enumerate(bricks):
302+
pygame.draw.rect(screen, brick_colors[i], brick)
303+
for p in powerups:
304+
screen.blit(powerup_icons[p['type']], p['rect'].topleft)
305+
level_text = small_font.render(f"Level: {level}", True, WHITE)
306+
screen.blit(level_text, (10, 10))
307+
pygame.display.flip()
308+
clock.tick(60)
309+
310+
game_loop()

0 commit comments

Comments
 (0)