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
|
from setup import *
from colors import *
from player import Player
from platform import Platform, PlatformManager
from game_over_display import GameOverDisplay
SAVE_FILENAME = "score.txt"
# Class which handles the main game logic and drawing
class Jumper:
# (Primary, Accent)
colors = (
(COLOR_WHITE, COLOR_BLACK),
(COLOR_LIGHT_PINK, COLOR_BLACK),
(COLOR_LIGHT_BLUE, COLOR_BLACK),
(COLOR_LIGHT_YELLOW, COLOR_BLACK),
(COLOR_ORANGE, COLOR_WHITE),
(COLOR_OFF_RED, COLOR_WHITE),
(COLOR_PURPLE, COLOR_WHITE),
(COLOR_DARK_BLUE, COLOR_WHITE),
(COLOR_BLACK, COLOR_YELLOW),
(COLOR_BLACK, COLOR_RED),
(COLOR_WHITE, COLOR_RED))
color_switch_interval = 250
camera_acceleration = 0.0000025
camera_deceleration = 0.001
jump_power_increase_rate = 0.000005
distance_per_score = 20
# Called on game initialization
def __init__(self):
# Creates an instance of platform manager
self.platform_manager = PlatformManager()
self.color_index = 0
self.color_palette = ColorPalette(self.colors[self.color_index][0],
self.colors[self.color_index][1])
# Camera only moves up, so we only need a y position
self.camera_y = 0
# The speed at which the camera will move up
self.camera_speed = 0.1
# Create our player at the position such that it will land on the platform in the middle of
# the screen
starting_platform_position_y = (SCREEN_HEIGHT -
PlatformManager.platform_spread *
PlatformManager.starting_platform_slot -
Platform.height)
self.player = Player(SCREEN_WIDTH / 2, starting_platform_position_y - Player.height)
# Create the variable which will keep track of the user's score
self.score = 0
# True if the player dies
self.game_over = False
# Game over display will be created when the game ends
self.game_over_display = None
# Writes the current score to the best score file
# This should only be called if the current score is the best score
def set_best_score(self):
# w : Write file
# + : Create if not exists
f = open(SAVE_FILENAME, "w+")
f.write(str(self.score))
f.close()
def get_best_score(self):
try:
# r : Read file
f = open(SAVE_FILENAME, "r")
score = int(f.read())
f.close()
return score
# If the above code threw a FileNotFoundError, it means that our best score file does not
# exist yet; no best score has been set yet. As such, we'll return 0 as the best score.
except FileNotFoundError:
return 0
def update_colors(self, delta_time):
self.color_palette.update(delta_time)
if (self.color_index + 1) * self.color_switch_interval <= self.score:
self.color_index += 1
color_index_mod = self.color_index % len(self.colors)
self.color_palette = ColorPalette(self.colors[color_index_mod][0],
self.colors[color_index_mod][1],
self.color_palette)
Player.color = self.color_palette.get_accent_color()
Platform.color = self.color_palette.get_accent_color()
# Moves the camera every frame
def update_camera_position(self, delta_time):
# Move the camera down
self.camera_y -= self.camera_speed * delta_time
# If the player jumps higher than the camera y position, set the camera y to match the
# position of the player
if self.player.position.y < self.camera_y:
self.camera_y = self.player.position.y
# Increase game difficulty over time
def update_difficulty(self, delta_time):
self.camera_speed += delta_time * self.camera_acceleration
self.player.jump_power += delta_time * self.jump_power_increase_rate
# Update the score based on the highest y position the player has reached
def update_score(self):
self.score = max(self.score, int(-self.player.position.y / self.distance_per_score))
def slow_down_camera(self, delta_time):
self.camera_speed *= max(0, 1 - (delta_time * self.camera_deceleration))
# Called once after the player dies.
# Determines best score and creates the game over display. Sets a new best score if necessary.
def on_game_end(self):
best_score = self.get_best_score()
if self.score > best_score:
best_score = self.score
self.set_best_score()
self.game_over_display = GameOverDisplay(self.score, best_score)
self.game_over = True
# Updates the game logic every frame
def update(self, delta_time):
self.player.resolve_platform_collisions(delta_time, self.platform_manager.platforms)
self.player.update(delta_time)
# If the game has ended and on_game_end was already called
if self.game_over and self.game_over_display is not None:
self.slow_down_camera(delta_time)
self.game_over_display.update()
# If the player just died; if the player died in a previous frame then this will not be
# reached
elif self.player.is_dead(self.camera_y):
self.on_game_end()
# If the player has not died yet; the game is not over
else:
self.update_difficulty(delta_time)
self.update_score()
self.update_camera_position(delta_time)
self.update_colors(delta_time)
# Loop over all pending events and clear them
for event in pygame.event.get():
# If there is a quit event, the user wants to exit
# This will make the close (red X) button work
if event.type == pygame.QUIT:
return COMMAND_EXIT
if event.type == pygame.KEYUP:
if self.game_over:
# If we are on the game over screen and the user presses space, restart the game
if event.key is pygame.K_SPACE:
return COMMAND_START
# Continuously check for key presses
pressed = pygame.key.get_pressed()
if pressed[pygame.K_RIGHT]:
self.player.move_right()
if pressed[pygame.K_LEFT]:
self.player.move_left()
# Perform platform creation and deletion as necessary
self.platform_manager.update(self.camera_y)
# Draws all game objects every frame
def draw(self, screen):
screen.fill(self.color_palette.get_primary_color())
self.draw_score(screen)
self.player.draw(screen, self.camera_y)
self.platform_manager.draw(screen, self.camera_y)
if self.game_over_display is not None:
self.game_over_display.draw(screen)
# Draw the score to the screen
def draw_score(self, screen):
# Use the largest font
text_font = FONT_BIGGER
text_color = self.color_palette.get_text_color()
# Get the middle of the screen
position_x, position_y = SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2
# Create a surface with the score drawn on it
text_surface = text_font.render(str(self.score), True, text_color)
# Calculate where the top left of the surface should be put
top_left = (position_x - text_surface.get_width() / 2,
position_y - text_surface.get_height() / 2)
# Make the score text translucent
text_surface.set_alpha(int(255 * 0.25))
# Draw the text surface onto the screen
screen.blit(text_surface, top_left)
|