Mercurial > skaapsteker
annotate skaapsteker/engine.py @ 454:95527fd29872
More complete game load/save/restart.
author | Jeremy Thurgood <firxen@gmail.com> |
---|---|
date | Sat, 09 Apr 2011 20:47:35 +0200 |
parents | 4bec05fed6c7 |
children | fb9258d66137 |
rev | line source |
---|---|
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
1 """Top-level engine for switching scenes.""" |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
2 |
447 | 3 import os |
4 | |
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
5 import pygame.display |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
6 import pygame.time |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
7 import pygame.event |
14 | 8 from pygame.locals import QUIT, USEREVENT |
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
9 |
447 | 10 from . import options |
11 | |
127
e1dd3b785269
Initial game state stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
126
diff
changeset
|
12 |
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
13 class Engine(object): |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
14 |
262 | 15 def __init__(self, soundsystem): |
250
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
16 # avoid circular imports |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
17 from .gamestate import GameState |
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
18 self._framerate = 60 |
14 | 19 self._current_scene = None |
123 | 20 self._fpss = [self._framerate] * 100 |
21 self._cur_frame = 0 | |
447 | 22 self.game_state = GameState(os.path.join(options['save_location'], 'savegame.json')) |
23 if self.game_state.can_resume(): | |
24 self.game_state.load_game() | |
262 | 25 self.soundsystem = soundsystem |
14 | 26 |
27 def change_scene(self, next_scene): | |
447 | 28 self.game_state.save_game() |
262 | 29 self.soundsystem.stop_music() |
14 | 30 if self._current_scene is not None: |
31 self._current_scene.leave() | |
32 self._current_scene = next_scene | |
33 self._current_scene.enter() | |
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
34 |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
35 def run(self): |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
36 """Run the game loop dispatching events as necessary.""" |
14 | 37 assert self._current_scene is not None |
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
38 clock = pygame.time.Clock() |
14 | 39 surface = pygame.display.get_surface() |
11
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
40 while True: |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
41 events = pygame.event.get() |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
42 for ev in events: |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
43 if ev.type is QUIT: |
249814efa91b
Create game engine. Enable quitting.
Simon Cross <hodgestar@gmail.com>
parents:
diff
changeset
|
44 return |
454
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
45 if NewGameEvent.matches(ev): |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
46 self.game_state.new_game() |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
47 fox = self.game_state.world.fox |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
48 ChangeScene.post((ev.scene_type, '.'.join([fox.level, fox.doorway]))) |
14 | 49 if ChangeScene.matches(ev): |
249 | 50 next_scene = ev.next_scene |
51 if not isinstance(next_scene, Scene): | |
264
afd9256ad682
Move between doorways. (Still with hacky collision limiting.)
Jeremy Thurgood <firxen@gmail.com>
parents:
262
diff
changeset
|
52 next_scene = next_scene[0](self.game_state, self.soundsystem, *(next_scene[1:])) |
249 | 53 self.change_scene(next_scene) |
14 | 54 break |
55 self._current_scene.dispatch(ev) | |
123 | 56 self._current_scene.draw(surface, self) |
14 | 57 pygame.display.flip() |
126
9cae256b91d7
Fix bug in FPS calculation. Phew -- we're still fast.
Simon Cross <hodgestar@gmail.com>
parents:
123
diff
changeset
|
58 self._fpss[self._cur_frame] = 1000.0 / clock.tick(self._framerate) |
123 | 59 self._cur_frame = self._cur_frame + 1 if self._cur_frame < 99 else 0 |
60 | |
61 def get_fps(self): | |
62 return sum(self._fpss) / 100 | |
14 | 63 |
64 | |
65 class Scene(object): | |
66 | |
262 | 67 def __init__(self, game_state, soundsystem): |
79
fe8652a060df
Simple menu screen and TextChoice widget
Stefano Rivera <stefano@rivera.za.net>
parents:
14
diff
changeset
|
68 self.widgets = [] |
165
8d45715c587d
Rename ._game_state to game_state for consistency with engine and since everyone and their dog has access to it. :)
Simon Cross <hodgestar@gmail.com>
parents:
133
diff
changeset
|
69 self.game_state = game_state |
262 | 70 self._soundsystem = soundsystem |
14 | 71 |
72 def post(self, ev): | |
73 """Post an event to pygame's event loop.""" | |
74 pygame.event.post(ev) | |
75 | |
76 def enter(self): | |
77 """Enter the scene.""" | |
78 pass | |
79 | |
80 def leave(self): | |
81 """Exit the scene.""" | |
82 pass | |
83 | |
84 def dispatch(self, ev): | |
85 """Dispatch an event.""" | |
79
fe8652a060df
Simple menu screen and TextChoice widget
Stefano Rivera <stefano@rivera.za.net>
parents:
14
diff
changeset
|
86 for widget in self.widgets: |
fe8652a060df
Simple menu screen and TextChoice widget
Stefano Rivera <stefano@rivera.za.net>
parents:
14
diff
changeset
|
87 widget.dispatch(ev) |
14 | 88 |
133
aca8b7456c72
Pass engine to all Scene draw() methods
Stefano Rivera <stefano@rivera.za.net>
parents:
127
diff
changeset
|
89 def draw(self, surface, engine): |
14 | 90 """Update the scene surface.""" |
79
fe8652a060df
Simple menu screen and TextChoice widget
Stefano Rivera <stefano@rivera.za.net>
parents:
14
diff
changeset
|
91 for widget in self.widgets: |
fe8652a060df
Simple menu screen and TextChoice widget
Stefano Rivera <stefano@rivera.za.net>
parents:
14
diff
changeset
|
92 widget.draw(surface) |
14 | 93 |
94 | |
95 class UserEvent(object): | |
96 | |
97 utype = "UNKNOWN" | |
98 | |
99 @classmethod | |
100 def post(cls, **kws): | |
101 ev = pygame.event.Event(USEREVENT, utype=cls.utype, **kws) | |
102 pygame.event.post(ev) | |
103 | |
104 @classmethod | |
105 def matches(cls, ev): | |
106 return ev.type is USEREVENT and ev.utype == cls.utype | |
107 | |
454
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
108 class NewGameEvent(UserEvent): |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
109 |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
110 utype = "NEW_GAME_EVENT" |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
111 |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
112 @classmethod |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
113 def post(cls, scene_type): |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
114 super(NewGameEvent, cls).post(scene_type=scene_type) |
95527fd29872
More complete game load/save/restart.
Jeremy Thurgood <firxen@gmail.com>
parents:
447
diff
changeset
|
115 |
14 | 116 class ChangeScene(UserEvent): |
117 | |
118 utype = "CHANGE_SCENE" | |
119 | |
120 @classmethod | |
121 def post(cls, next_scene): | |
122 super(ChangeScene, cls).post(next_scene=next_scene) | |
244
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
123 |
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
124 class PlayerDied(UserEvent): |
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
125 |
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
126 utype = "PLAYER_DIED" |
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
127 |
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
128 @classmethod |
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
129 def post(cls): |
5bbf90e6a94b
Add minimal support for player death
Neil Muller <drnlmuller@gmail.com>
parents:
189
diff
changeset
|
130 super(PlayerDied, cls).post() |
250
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
131 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
132 class OpenDialog(UserEvent): |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
133 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
134 utype = "OPEN_DIALOG" |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
135 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
136 @classmethod |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
137 def post(cls, npc): |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
138 # request to open dialog box for given NPC sprite |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
139 # will do nothing if the NPC's current state has |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
140 # no text |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
141 super(OpenDialog, cls).post(npc=npc) |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
142 |
383 | 143 class OpenNotification(UserEvent): |
144 | |
145 utype = "OPEN_NOTIFICATION" | |
146 | |
147 @classmethod | |
148 def post(cls, text): | |
149 # request to open dialog box for given NPC sprite | |
150 # will do nothing if the NPC's current state has | |
151 # no text | |
152 super(OpenNotification, cls).post(text=text) | |
153 | |
250
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
154 class CloseDialog(UserEvent): |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
155 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
156 utype = "CLOSE_DIALOG" |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
157 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
158 @classmethod |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
159 def post(cls, npc): |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
160 # close dialog box for given NPC sprite |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
161 # will do nothing if the sprite has no dialog open |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
162 super(CloseDialog, cls).post(npc=npc) |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
163 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
164 class NpcEvent(UserEvent): # TODO: Needed? |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
165 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
166 utype = "NPC_EVENT" |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
167 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
168 @classmethod |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
169 def post(cls, npc, ev): |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
170 """npc is an NPC sprite. |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
171 ev is a DsmEvent for that sprite. |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
172 """ |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
173 super(NpcEvent, cls).post(npc=npc, ev=ev) |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
174 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
175 class GlobalNpcEvent(UserEvent): # TODO: Needed? |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
176 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
177 utype = "GLOBAL_NPC_EVENT" |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
178 |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
179 @classmethod |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
180 def post(cls, ev): |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
181 """Send a DsmEvent event to all NPCs. |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
182 """ |
8d7edd77bfbf
Start hooking up NPC interactions.
Simon Cross <hodgestar@gmail.com>
parents:
249
diff
changeset
|
183 super(GlobalNpcEvent, cls).post(ev=ev) |
290
c68f2f3efc7f
Item dropping and swapping.
Jeremy Thurgood <firxen@gmail.com>
parents:
264
diff
changeset
|
184 |
c68f2f3efc7f
Item dropping and swapping.
Jeremy Thurgood <firxen@gmail.com>
parents:
264
diff
changeset
|
185 |
339
a9d760134706
Rename ItemRepopulationEvent to AddSprite before repurposing it for fireballs.
Simon Cross <hodgestar@gmail.com>
parents:
290
diff
changeset
|
186 class AddSpriteEvent(UserEvent): |
290
c68f2f3efc7f
Item dropping and swapping.
Jeremy Thurgood <firxen@gmail.com>
parents:
264
diff
changeset
|
187 |
339
a9d760134706
Rename ItemRepopulationEvent to AddSprite before repurposing it for fireballs.
Simon Cross <hodgestar@gmail.com>
parents:
290
diff
changeset
|
188 utype = "ADD_SPRITE_EVENT" |
290
c68f2f3efc7f
Item dropping and swapping.
Jeremy Thurgood <firxen@gmail.com>
parents:
264
diff
changeset
|
189 |
c68f2f3efc7f
Item dropping and swapping.
Jeremy Thurgood <firxen@gmail.com>
parents:
264
diff
changeset
|
190 @classmethod |
c68f2f3efc7f
Item dropping and swapping.
Jeremy Thurgood <firxen@gmail.com>
parents:
264
diff
changeset
|
191 def post(cls, item): |
339
a9d760134706
Rename ItemRepopulationEvent to AddSprite before repurposing it for fireballs.
Simon Cross <hodgestar@gmail.com>
parents:
290
diff
changeset
|
192 """Put a Sprite into the world. |
290
c68f2f3efc7f
Item dropping and swapping.
Jeremy Thurgood <firxen@gmail.com>
parents:
264
diff
changeset
|
193 """ |
339
a9d760134706
Rename ItemRepopulationEvent to AddSprite before repurposing it for fireballs.
Simon Cross <hodgestar@gmail.com>
parents:
290
diff
changeset
|
194 super(AddSpriteEvent, cls).post(item=item) |