forked from emilyk123/Titanium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.py
302 lines (247 loc) · 13.7 KB
/
game.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
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
# Used tutorial https://www.youtube.com/watch?v=2gABYM5M0ww&list=LL&index=5&t=2735s&ab_channel=DaFluffyPotato
# How to create custom events: https://stackoverflow.com/questions/24475718/pygame-custom-event
# How to create a timer: https://www.pygame.org/docs/ref/time.html#pygame.time.set_timer
# https://pygame.readthedocs.io/en/latest/4_text/text.html (How to put text on the screen for time)
import sys
import pygame
import time
import random
from player import Player
from tilemap import Tilemap
from object import MovingRectangle
from power import PowerUp
from screen import MainMenu
from screen import PauseMenu
from screen import GameOver
from utils import load_images
from powerUpSpeed import SpeedPowerUP
from powerUpInvisble import InvisblePowerUp
from enum import Enum
class CurrentState(Enum):
MainMenu = 1
Game = 2
GameOver = 3
Pause = 4
class Game:
def __init__(self):
pygame.init()
self.screen_width = 640
self.screen_height = 480
self.display_width = 320
self.display_height = 240
self.spawn_position = (self.display_width / 2, self.display_height - 32)
# Keeps track of which state the player is at in the game
self.current_state = CurrentState.MainMenu
self.main_menu = MainMenu(self)
self.pause_menu = PauseMenu(self)
self.game_over = GameOver(self)
self.current_level = 1
# Create game window
self.display = pygame.Surface((self.display_width, self.display_height))
self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
# Create clock used to limit frame rate
self.clock = pygame.time.Clock()
# Create custom event
self.player_move_event = pygame.USEREVENT + 1
self.menu_delay_event = pygame.USEREVENT + 2
# [Up, Left, Down, Right]
self.player_movement = [False, False, False, False]
self.tilemap = Tilemap(self)
#--------initialize tilemap
# Create player player at spawn position
self.player = Player(self.spawn_position)
# Create power-up with random positioning logic
#self.power = PowerUp(self.display_width, self.display_height, self)
# Initialize the tilemap
# self.tilemap = Tilemap(self)
# Game Tile Sprites
self.assets = {
'ground': load_images('ground'),
'end_tiles': load_images('end_tiles'),
'water': load_images('water'),
'health': load_images('health')
}
# Keeps track of when the player has pressed the left mouse button
self.clicked = False
self.can_click_button = True
self.start_time = time.time() % 60
self.time = 0
# Try to load level 1, if it's not there then load game without it
try:
self.tilemap.load('level01.json')
except FileNotFoundError:
pass
# Creating the powerup instances here
x, y = 100, 100 # Example initial positions for power-ups
self.invisble_powerUp = InvisblePowerUp(100,100)
self.speed_powerUp = SpeedPowerUP(200,150)
self.player_movement_delay = 100
self.power = PowerUp(self.display_width, self.display_height, self.tilemap)
# instance
# level 1
self.mover = MovingRectangle(x=self.display_width, y=self.display_height - 80, width=64, height=16, speed=-3)
self.mover1 = MovingRectangle(x=self.display_width, y=self.display_height - 128, width=64, height=16, speed=-2)
# level 2
self.mover2 = MovingRectangle(x=self.display_width, y=self.display_height - 96, width=64, height=16, speed=-2)
self.mover3 = MovingRectangle(x=self.display_width, y=self.display_height - 208, width=64, height=16, speed=-2)
def load_level(self, level, tilemap):
# Try to load level , if it's not there then load game without it
try:
tilemap.load(level)
except FileNotFoundError:
pass
def run(self):
# Set timer for player movement)
pygame.time.set_timer(self.player_move_event, self.player_movement_delay)
# Set timer to put a delay how fast the player can press menu buttons
pygame.time.set_timer(self.menu_delay_event, 500)
self.load_level('level01.json', self.tilemap)
while True:
self.time = int((time.time() % 60) - self.start_time)
# Checks all key and mouse presses
for event in pygame.event.get():
# Pressing the red x at the corner of the window closes the game
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Allow player to move
if event.type == self.player_move_event:
self.player.can_move = True
# Allow the player to click buttons in the menu again
if event.type == self.menu_delay_event:
self.can_click_button = True
# Check for input with WASD or the arrow keys
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.current_state = CurrentState.Pause
# If timer has passed time limit, allow player input
if self.player.can_move:
if event.key == pygame.K_w or event.key == pygame.K_UP:
self.player_movement[0] = True
if event.key == pygame.K_a or event.key == pygame.K_LEFT:
self.player_movement[1] = True
if event.key == pygame.K_s or event.key == pygame.K_DOWN:
self.player_movement[2] = True
if event.key == pygame.K_d or event.key == pygame.K_RIGHT:
self.player_movement[3] = True
# Subtract player_movement[3] (Right) from player_movement[1] (Left) to get horizontal direction
# Subtract player_movement[2] (Down) from player_movement[0] (Up) to get vertical direction
# List of mover rects that the player is able to be on top of
self.player.move(self.tilemap, (self.player_movement[3] - self.player_movement[1], self.player_movement[2] - self.player_movement[0]), self, [self.mover.rect, self.mover1.rect, self.mover2, self.mover3])
# Check for collision between player and power-up
# if self.player.collision(self.power):
# print("Power-up collected! Moving to a new position.")
# self.power.randomize_position()
# # Don't allow player movement until timer has met time limit again
# self.player.can_move = False
if event.type == pygame.KEYUP:
# When keys are released, set player_movement back to false
if event.key == pygame.K_w or event.key == pygame.K_UP:
self.player_movement[0] = False
if event.key == pygame.K_a or event.key == pygame.K_LEFT:
self.player_movement[1] = False
if event.key == pygame.K_s or event.key == pygame.K_DOWN:
self.player_movement[2] = False
if event.key == pygame.K_d or event.key == pygame.K_RIGHT:
self.player_movement[3] = False
if event.type == pygame.MOUSEBUTTONDOWN:
self.clicked = True
else:
self.clicked = False
if not self.player.is_alive:
self.current_state = CurrentState.GameOver
self.player.is_alive = True
self.player.health = 3
if self.current_state == CurrentState.MainMenu:
self.display.fill((255, 255, 255))
self.main_menu.render(self.display)
if self.clicked and self.main_menu.current_button == "Start" and self.can_click_button:
self.current_state = CurrentState.Game
self.can_click_button = False
if self.clicked and self.main_menu.current_button == "Quit":
pygame.quit()
sys.exit()
elif self.current_state == CurrentState.Pause:
self.display.fill((255, 255, 255))
self.pause_menu.render(self.display)
if self.clicked and self.pause_menu.current_button == "MainMenu" and self.can_click_button:
self.current_state = CurrentState.MainMenu
self.can_click_button = False
if self.clicked and self.pause_menu.current_button == "Quit":
pygame.quit()
sys.exit()
elif self.current_state == CurrentState.GameOver:
self.display.fill((255, 255, 255))
self.game_over.render(self.display)
if self.clicked and self.game_over.current_button == "Restart" and self.can_click_button:
self.current_state = CurrentState.Game
self.can_click_button = False
if self.clicked and self.game_over.current_button == "Quit":
pygame.quit()
sys.exit()
elif self.current_state == CurrentState.Game:
# Recolor the background so it covers everything from the last frame
self.display.fill((106, 183, 215))
# Add all of the tiles for the background
self.tilemap.render(self.display)
if self.current_level == 1:
# moves the rectangle
self.mover.move(self.display_width)
self.mover1.move(self.display_width)
# draws the rectangle and color red
self.mover.draw(self.display, "RED")
self.mover1.draw(self.display, "RED")
# if player collides with rectangle move along with the rectangle
if self.player.rect().colliderect(self.mover.rect):
if self.player.rect().bottom <= self.mover.rect.bottom:
# move the player with the rectangle speed
self.player.position[0] += self.mover.speed
if self.player.rect().colliderect(self.mover1.rect):
if self.player.rect().bottom <= self.mover1.rect.bottom:
# move the player with the rectangle speed
self.player.position[0] += self.mover1.speed
if self.current_level == 2:
self.mover2.move(self.display_width)
self.mover3.move(self.display_width)
# Draw squares in top right corner to display the player's health
self.tilemap.draw_health(self.display, self.player)
self.mover2.draw(self.display, "RED")
self.mover3.draw(self.display, "RED")
if self.player.rect().colliderect(self.mover2.rect):
if self.player.rect().bottom <= self.mover2.rect.bottom:
# move the player with the rectangle speed
self.player.position[0] += self.mover2.speed
if self.player.rect().colliderect(self.mover3.rect):
if self.player.rect().bottom <= self.mover3.rect.bottom:
# move the player with the rectangle speed
self.player.position[0] += self.mover3.speed
# Draw power-ups at their positions
self.invisble_powerUp.draw(self.display)
self.speed_powerUp.draw(self.display)
# Check for collision with power-ups
if self.player.rect().colliderect(self.invisble_powerUp.rect):
# print("Invisible Power-Up collected!")
self.invisble_powerUp.randomize_position(self.display_width, self.display_height)
if self.player.rect().colliderect(self.speed_powerUp.rect):
# print("Speed Power-Up collected!")
self.speed_powerUp.randomize_position(self.display_width, self.display_height)
# using player movement delay here
self.speed_powerUp.speed_up(self)
# Draw power-up at random positions
self.power.draw(self.display)
# Draw the player at its current location to the screen
self.player.render(self.display)
# Draw squares in top right corner to display the player's health
self.tilemap.draw_health(self.display, self.player)
# Draw text for the timer
font = pygame.font.SysFont('Consolas', 16)
img = font.render('Time: ' + str(self.time), True, pygame.Color(0, 0, 0))
self.display.blit(img, (0, 0))
# Blit the screen, display, with all of the sprites on to the screen
# The display is smaller than the screen so it scales up the size of everything in the display
self.screen.blit(pygame.transform.scale(self.display, self.screen.get_size()), (0, 0))
# Updates the display to show all changes made to the game
pygame.display.update()
# Makes the game run at 60 frames per second
self.clock.tick(60)
Game().run()