Skip to content

Commit 974f86a

Browse files
author
Federico
committed
added dodgy square
1 parent 49f5cdc commit 974f86a

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import pygame
2+
from pygame.font import Font
3+
from pygame.time import Clock
4+
import random
5+
import sys
6+
7+
8+
class DodgySquare:
9+
def __init__(self):
10+
# Pygame
11+
pygame.init()
12+
13+
# Screen
14+
self.screen_width, self.screen_height = 600, 600
15+
self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
16+
pygame.display.set_caption("Dodgy Square")
17+
18+
# Colours
19+
self.WHITE: tuple = (255, 255, 255)
20+
self.BLACK: tuple = (0, 0, 0)
21+
self.RED: tuple = (255, 99, 71)
22+
23+
# Font
24+
self.font: Font = pygame.font.Font(None, 36)
25+
26+
# Player
27+
self.player_size: int = 50
28+
self.player_speed: int = self.player_size // 2
29+
self.player_pos: list[int] = [self.screen_width // 2, self.screen_height - (2 * self.player_size)]
30+
31+
# Enemies
32+
self.enemy_size: int = 50
33+
self.enemy_pos: list[int] = [random.randint(0, self.screen_width - self.enemy_size), 0]
34+
self.enemy_list = [self.enemy_pos]
35+
self.enemy_speed: int = 3 # Low = slow, High = Fast
36+
self.enemy_frequency: int = 30 # Low = Lots, High = Few
37+
38+
# Clock
39+
self.clock: Clock = pygame.time.Clock()
40+
41+
# Game data
42+
self.game_over: bool = False
43+
self.score: int = 0
44+
self.frame_count: int = 0
45+
self.tick: float = 30
46+
47+
# Set up enemy speed and frequency
48+
self.enemy_speed: int = 3
49+
self.enemy_frequency: int = 30 # Number of frames between enemy creation
50+
51+
def create_enemy(self):
52+
"""Creates a new enemy at a random position"""
53+
54+
enemy_pos = [random.randint(0, self.screen_width - self.enemy_size), 0]
55+
self.enemy_list.append(enemy_pos)
56+
57+
# Function to update enemy positions
58+
def update_enemy_positions(self):
59+
"""Check whether it is time to create a new enemy and then does so"""
60+
61+
if self.frame_count % self.enemy_frequency == 0:
62+
self.create_enemy()
63+
64+
# Give each enemy an id
65+
for idx, enemy_pos in enumerate(self.enemy_list):
66+
# Simulate gravity until off-screen
67+
if 0 <= enemy_pos[1] < self.screen_height:
68+
enemy_pos[1] += self.enemy_speed
69+
else:
70+
# When the enemy has passed
71+
self.enemy_list.pop(idx)
72+
self.score += 1
73+
self.enemy_speed += 0.1
74+
75+
def detect_collision(self, player_pos: list[int], enemy_pos: list[int]) -> bool:
76+
"""Collision detection logic for checking if squares are intercepting"""
77+
78+
px, py = player_pos
79+
ex, ey = enemy_pos
80+
if (px <= ex < (px + self.player_size)) or (ex <= px < (ex + self.enemy_size)):
81+
if (py <= ey < (py + self.player_size)) or (ey <= py < (ey + self.enemy_size)):
82+
return True
83+
return False
84+
85+
# Game over text
86+
def show_game_over(self):
87+
"""Display game-over text"""
88+
89+
game_over_text = self.font.render("Game Over", True, self.WHITE)
90+
self.screen.blit(game_over_text, (self.screen_width // 2 - 70, self.screen_height // 2 - 16))
91+
92+
# Replay the game
93+
def replay_game(self):
94+
"""Reset everything to its initial state"""
95+
96+
self.player_pos: list[int] = [self.screen_width // 2, self.screen_height - (2 * self.player_size)]
97+
self.enemy_list = [self.enemy_pos]
98+
self.enemy_speed: int = 3
99+
self.score: int = 0
100+
self.game_over: bool = False
101+
self.frame_count: int = 0
102+
103+
def draw_character(self, color: tuple, position: list[int], size: int):
104+
"""Draws a rectangle on the screen"""
105+
106+
pygame.draw.rect(self.screen, color, (position[0], position[1], size, size))
107+
108+
# Main game loop
109+
def run(self):
110+
"""Run the game"""
111+
112+
while True:
113+
for event in pygame.event.get():
114+
if event.type == pygame.QUIT:
115+
pygame.quit()
116+
sys.exit()
117+
118+
# Handle key events
119+
if event.type == pygame.KEYDOWN:
120+
match event.key:
121+
case pygame.K_LEFT:
122+
self.player_pos[0] -= self.player_speed
123+
case pygame.K_RIGHT:
124+
self.player_pos[0] += self.player_speed
125+
case pygame.K_UP:
126+
self.player_pos[1] -= self.player_speed
127+
case pygame.K_DOWN:
128+
self.player_pos[1] += self.player_speed
129+
case pygame.K_r if self.game_over:
130+
self.replay_game()
131+
132+
# Make sure the player stays on the screen
133+
self.player_pos[0]: int = max(0, min(self.player_pos[0], self.screen_width - self.player_size))
134+
self.player_pos[1]: int = max(0, min(self.player_pos[1], self.screen_height - self.player_size))
135+
136+
if not self.game_over:
137+
self.update_enemy_positions()
138+
139+
# Check for collisions
140+
for enemy_pos in self.enemy_list:
141+
if self.detect_collision(self.player_pos, enemy_pos):
142+
self.game_over = True
143+
break
144+
145+
# Reset everything for the next frame
146+
self.screen.fill(self.BLACK)
147+
148+
# Draw the player
149+
self.draw_character(self.WHITE, self.player_pos, self.player_size)
150+
151+
# Draw the enemies
152+
for enemy_pos in self.enemy_list:
153+
self.draw_character(self.RED, enemy_pos, self.enemy_size)
154+
155+
# Display the score
156+
score_text = self.font.render("Score: " + str(self.score), True, self.WHITE)
157+
self.screen.blit(score_text, [10, 10])
158+
159+
# Increment the frame count
160+
self.frame_count += 1
161+
else:
162+
self.show_game_over()
163+
164+
# Update the display
165+
pygame.display.update()
166+
167+
# Frame rate
168+
self.clock.tick(60)
169+
170+
171+
# Run the game
172+
if __name__ == '__main__':
173+
game = DodgySquare()
174+
game.run()

0 commit comments

Comments
 (0)