-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathengine.py
297 lines (213 loc) · 7.88 KB
/
engine.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
import logging
import time
import sys
import os
import pygame
import pygame.locals
##############################################################
class Config:
asset_path = os.path.join("assets")
##############################################################
class Colors:
TRANSPARENT = (255, 0, 255)
BLACK = (0, 0, 0)
LIGHT_GREY = (200, 200, 200)
GREY = (128, 128, 128)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 132, 0)
##############################################################
class Kernel:
"""
Simple management interface for all of the
subsystems of the engine. Just passes through
some basic logic so we can manage them easily
"""
def __init__(self, **kwargs):
logfilename = kwargs.get('logfilename', 'game.log')
loglevel = kwargs.get('loglevel', logging.DEBUG)
logging.basicConfig(filename=logfilename, level=loglevel)
logging.info("********************************************")
logging.info("(Kernel) Initializing kernel")
logging.info("(Kernel) Initializing pygame")
pygame.init()
logging.info("(Kernel) PyGame Version: " + pygame.version.ver)
self.ticker = pygame.time.Clock()
self.display_surface = None
self.image_manager = ImageManager(self)
self.sound_manager = SoundManager(self)
self.screen_manager = ScreenManager()
def initialize_display(self, dimensions, fullscreen=False):
flags = pygame.DOUBLEBUF
if fullscreen:
flags = flags | pygame.FULLSCREEN
logging.info("(Kernel) Initializing Display")
self.display_surface = pygame.display.set_mode(dimensions, flags)
assert self.display_surface, "Display failed to initialize."
return self.display_surface
def flip_display(self):
pygame.display.flip()
self.display_surface.fill(Colors.BLUE)
def process_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif self.screen_manager.active_screen:
self.screen_manager.active_screen.handle_event(event)
##############################################################
class ImageManager:
"""
Simple utility for loading and cacheing images
"""
def __init__(self, kernel):
self.loaded_images = {}
self.kernel = kernel
def load(self, filename, transparent=True):
if (filename in self.loaded_images):
return self.loaded_images[filename], self.loaded_images[filename].get_rect()
else:
image = pygame.image.load(os.path.join(
Config.asset_path, "images", filename))
image = image.convert(self.kernel.display_surface)
if (transparent):
image.set_colorkey(Colors.TRANSPARENT)
image.set_alpha(255, pygame.locals.RLEACCEL)
self.loaded_images[filename] = image
return image, image.get_rect()
##############################################################
class SoundManager:
"""
Simple utility class for loading and cacheing sounds
"""
def __init__(self, kernel):
self.loaded_sounds = {}
self.kernel = kernel
def load(self, filename):
if (filename in self.loaded_sounds):
return self.loaded_sounds[filename]
else:
sound = pygame.mixer.Sound(os.path.join(
Config.asset_path, "sounds", filename))
self.loaded_sounds[filename] = sound
return sound
##############################################################
class Screen:
"""
A Screen represents a single screen of the game.
The functionality of the class essentially acts
as an interface to the common actions that you
need throughout a screen of the game. You are
expected to subclass this to make individual
sceens for your game.
"""
def __init__(self, kernel, name):
"""
Standard constructor. Like most things in robo-py,
it takes kernal and then keyword args containing the
following:
name: The name of this screen
"""
self.name = name
self.kernel = kernel
self.initialized = False
self.active = False
self.screen_manager = None;
def initialize(self):
"""
Initializes this screen and sets up any data that is
needed for this screen to run. Note, this automatically
starts the game state running.
"""
logging.info("(Screen '" + self.name + "') Initializing")
self.initialized = True
self.active = True
return True
def destroy(self):
"""
Destroys this screen and uninitializes all of this data.
Should free any resources that this is holding
"""
logging.info("(Screen '" + self.name + "') destroying")
self.active = False
self.initialized = False
return True
def pause(self):
"""
Pause this state, but do not destroy all of its data.
"""
logging.info("(Screen '" + self.name + "') pausing")
self.active = False
return True
def resume(self):
"""
Resume this state without re-initializing all of the data.
"""
logging.info("(Screen " + self.name + "'') resuming")
self.active = True
return True
def handle_event(self, event):
"""
Handles a single event pumped from the system event pump
"""
return True
def update(self, delta):
"""
Tick this screen.
"""
return True
##############################################################
class ScreenManager:
def __init__(self):
self.screens = {}
self.active_screen_name = ""
self.active_screen = None
def register_screen(self, screen):
if screen.name in self.screens:
logging.warning(
"(Screen Manager) Screen " + screen.name + " is already registered.")
return
self.screens[screen.name] = screen
screen.screen_manager = self
logging.info(
"(Screen Manager) Screen '" + screen.name + "' registered.")
def deregister_screen(self, name):
if name not in self.screens:
logging.warning(
"(Screen Manager) Screen " + name + " is not registered.")
return
if self.screens[name].initialized:
self.screens[name].destroy()
if self.active_screen_name == name:
self.active_screen = None
self.active_screen_name = ""
del self.screens[name]
logging.info("(Screen Manager) Screen '" + name + "' deregistered.")
def switch_to(self, name):
if name not in self.screens:
logging.warning(
"(Screen Manager) Screen " + name + " is not registered.")
logging.info("(Screen Manager) Switching to '" + name + "' screen.")
if self.active_screen:
if self.active_screen_name == name:
return
if self.active_screen.initialized:
self.active_screen.pause()
self.active_screen_name = name
self.active_screen = self.screens[name]
if self.active_screen.initialized:
self.active_screen.resume()
else:
self.active_screen.initialize()
def get_screen(self, name):
if name not in self.screens:
logging.warning(
"(Screen Manager) Screen " + name + " is not registered.")
return self.screens[name]
def update(self, delta):
if self.active_screen:
self.active_screen.update(delta)
##############################################################