-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
244 lines (207 loc) · 8.83 KB
/
main.py
File metadata and controls
244 lines (207 loc) · 8.83 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
# RPG Main Executable
import pygame as pg
import random
from os import path
from settings import *
from sprites import *
from keybinds import *
class Game:
def __init__(self):
# initialize game window, etc
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
self.clock = pg.time.Clock()
pg.display.set_caption(TITLE + " | FPS: " + str(int(self.clock.get_fps())))
self.running = True
self.font_name = pg.font.match_font(FONT_NAME)
self.load_data()
def load_data(self):
# Load HighScore
self.dir = path.dirname(__file__)
img_dir = path.join(self.dir, 'img')
with open(path.join(self.dir, HS_FILE), 'w') as f:
# Catch exception if file doesn't exist already
try:
self.highscore = int(f.read())
# Self populate the HS to be 0
except:
self.highscore = 0
self.spritesheet = Spritesheet(path.join(img_dir, SPRITESHEET))
# Load cloud images
self.cloud_images = []
for i in range(1, 4):
self.cloud_images.append(pg.image.load(path.join(img_dir, 'cloud{}.png'.format(i))).convert())
# Load sounds
self.sound_dir = path.join(self.dir, 'sounds')
self.jump_sound = pg.mixer.Sound(
path.join(self.sound_dir, 'player_jump.wav')) # TODO: Move this to a SoundDB system
self.boost_sound = pg.mixer.Sound(
path.join(self.sound_dir, 'powerup_sound.wav')) # TODO: Move this to a SoundDB system
def new(self):
# Restarts game / Start a new game
self.score = 0
self.all_sprites = pg.sprite.LayeredUpdates()
self.platforms = pg.sprite.Group()
self.powerups = pg.sprite.Group()
self.mobs = pg.sprite.Group()
self.clouds = pg.sprite.Group()
self.player = Player(self)
for platform in PLATFORM_LIST:
Platform(self, *platform) # Take the list and explode it to list items
self.mob_timer = 0
pg.mixer.music.load(path.join(self.sound_dir, 'maintheme.ogg')) # TODO: Move this to a SoundDB system
for i in range(6):
c = Cloud(self)
c.rect.y += 500
def run(self):
# game loop
pg.mixer.music.play(loops=-1) # Infinite looping.
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
pg.mixer.music.fadeout(500)
def update(self):
# game loop - update
self.all_sprites.update()
# Spawn a mob
now = pg.time.get_ticks()
if now - self.mob_timer > 5000 + random.choice([-1000, -500, 0, 500, 1000]):
self.mob_timer = now
Mob(self)
print("Spawned Mob")
# Collision with the MOB
mob_hits = pg.sprite.spritecollide(self.player, self.mobs, False, pg.sprite.collide_mask)
if mob_hits:
self.playing = False
# print(str(int(self.clock.get_fps()))) # Display FPS in Console
# Check if player hits a platform WHILE falling
if self.player.vel.y > 0:
hits = pg.sprite.spritecollide(self.player, self.platforms, False)
if hits:
lowest = hits[0]
for hit in hits:
if hit.rect.bottom > lowest.rect.bottom:
lowest = hit
if lowest.rect.right + 7 > self.player.pos.x > lowest.rect.left - 7:
if self.player.pos.y < lowest.rect.centery:
self.player.pos.y = lowest.rect.top + 1
self.player.vel.y = 0
self.player.jumping = False
# If player reaches top part of the screen (1/4) scroll platforms down
if self.player.rect.top <= HEIGHT / 4:
if randrange(100) < 15:
Cloud(self)
self.player.pos.y += max(abs(self.player.vel.y), 2)
for cloud in self.clouds:
cloud.rect.y += max(abs(self.player.vel.y / 2), 2)
for mob in self.mobs:
mob.rect.y += max(abs(self.player.vel.y), 2)
for platform in self.platforms:
platform.rect.y += max(abs(self.player.vel.y), 2)
# Unload platforms that are not in game windows. (Window HEIGHT + 20%)
if platform.rect.top >= (HEIGHT * 1.20):
platform.kill()
self.score += random.randrange(5, 10)
# PowerUps collision detection
powerup_hits = pg.sprite.spritecollide(self.player, self.powerups, True)
for powerup in powerup_hits:
if powerup.type == 'boost':
self.boost_sound.play()
self.player.vel.y = -BOOST_POWER
self.player.jumping = False
# Die condition
if self.player.rect.bottom > HEIGHT:
# Scroll the camera with the player
for sprite in self.all_sprites:
sprite.rect.y -= max(self.player.vel.y, 10)
if sprite.rect.bottom < 0:
sprite.kill()
if len(self.platforms) == 0:
self.playing = False
# Spawn new platform to keep same avg of platforms
while len(self.platforms) < 10:
width = random.randrange(50, 100)
Platform(self, random.randrange(0, WIDTH - width), # Generate X spawn cords.
random.randrange(-75, -30)) # Generate Y spawn cords.
def events(self):
# Game Loop - events
for event in pg.event.get():
# check for closing the window
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
# Jumping
if event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
self.player.jump()
if event.type == pg.KEYUP:
if event.key == pg.K_SPACE:
self.player.jump_cut()
def draw(self):
# Game Loop - draw
self.screen.fill(BGCOLOR)
self.all_sprites.draw(self.screen)
self.draw_text(str(self.score), 22, WHITE, WIDTH / 2, 15)
pg.display.flip()
def show_start_screen(self):
# Game splash screen
pg.mixer.music.load(path.join(self.sound_dir, 'mainmenu.ogg')) # TODO: Move this to a SoundDB system
pg.mixer.music.play(loops=-1)
self.screen.fill(BGCOLOR)
self.draw_text(TITLE, 50, WHITE, WIDTH / 2, HEIGHT / 4)
self.draw_text("ARROWS to Move. SPACE to Jump", 22, WHITE, WIDTH / 2, HEIGHT / 2)
self.draw_text("Press a key to play.", 22, WHITE, WIDTH / 2, HEIGHT * 3 / 4)
self.draw_text("High Score:" + str(self.highscore), 22, WHITE, WIDTH / 2, 15)
pg.display.flip()
self.wait_for_key()
pg.mixer.music.fadeout(500)
def show_gameover_screen(self):
# Skip GameOver screen if "X" is pressed while playing
if not self.running:
return
# Game over screen
pg.mixer.music.load(path.join(self.sound_dir, 'mainmenu.ogg')) # TODO: Move this to a SoundDB system
pg.mixer.music.play(loops=-1)
self.screen.fill(BGCOLOR)
self.draw_text("GAME OVER", 50, WHITE, WIDTH / 2, HEIGHT / 4)
self.draw_text("Score: " + str(self.score), 22, WHITE, WIDTH / 2, HEIGHT / 2)
self.draw_text("Press any key to play again.", 22, WHITE, WIDTH / 2, HEIGHT * 3 / 4)
# Check for new High Score.
if self.score > self.highscore:
self.highscore = self.score
self.draw_text("You got a new HIGH SCORE: ", 22, WHITE, WIDTH / 2, HEIGHT / 2 + 40)
with open(path.join(self.dir, HS_FILE), 'w') as f:
f.write(str(self.score))
else:
self.draw_text("HIGH SCORE: " + str(self.highscore), 22, WHITE, WIDTH / 2, HEIGHT / 2 + 40)
pg.display.flip()
self.wait_for_key()
pg.mixer.music.fadeout(500)
def wait_for_key(self):
waiting = True
while waiting:
self.clock.tick(FPS)
for event in pg.event.get():
if event.type == pg.QUIT:
waiting = False
self.running = False
if event.type == pg.KEYUP:
waiting = False
def draw_text(self, text, size, color, x, y):
font = pg.font.Font(self.font_name, size)
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
self.screen.blit(text_surface, text_rect)
g = Game()
g.show_start_screen()
while g.running:
g.new() # Generates a new game
g.run() # Runs the game
g.show_gameover_screen()
pg.quit()