Mercurial > boomslang
comparison pyntnclick/engine.py @ 854:79b5c1be9a5e default tip
Remove pyntnclick, it's its own library, now
author | Stefano Rivera <stefano@rivera.za.net> |
---|---|
date | Sat, 21 Jun 2014 22:06:09 +0200 |
parents | f95830b58336 |
children |
comparison
equal
deleted
inserted
replaced
852:f95830b58336 | 854:79b5c1be9a5e |
---|---|
1 """Game engine and top-level game loop.""" | |
2 | |
3 import pygame | |
4 import pygame.event | |
5 import pygame.display | |
6 import pygame.time | |
7 from pygame.locals import QUIT, USEREVENT | |
8 | |
9 # We can't do this via our usual UserEvent trickey | |
10 # as it gets generated by pygame.music, which only | |
11 # takes an event type | |
12 MUSIC_ENDED = USEREVENT + 1 | |
13 | |
14 | |
15 class Engine(object): | |
16 def __init__(self, gd): | |
17 self._screen = None | |
18 self._gd = gd | |
19 self.screens = {} | |
20 | |
21 def set_screen(self, screen_name): | |
22 if self._screen is not None: | |
23 self._screen.on_exit() | |
24 self._screen = self.screens[screen_name] | |
25 if self._screen is not None: | |
26 self._screen.on_enter() | |
27 | |
28 def add_screen(self, name, screen): | |
29 self.screens[name] = screen | |
30 | |
31 def run(self): | |
32 """Game loop.""" | |
33 | |
34 get_events = pygame.event.get | |
35 flip = pygame.display.flip | |
36 clock = pygame.time.Clock() | |
37 while True: | |
38 events = get_events() | |
39 for ev in events: | |
40 if ev.type == QUIT: | |
41 return | |
42 elif ev.type == MUSIC_ENDED: | |
43 self._gd.sound.music_ended() | |
44 elif ScreenChangeEvent.matches(ev): | |
45 self.set_screen(ev.screen_name) | |
46 elif ScreenEvent.matches(ev): | |
47 self.screens[ev.screen_name].process_event(ev.event_name, | |
48 ev.data) | |
49 else: | |
50 self._screen.dispatch(ev) | |
51 # Ping the screen / scene | |
52 self._screen.animate() | |
53 surface = pygame.display.get_surface() | |
54 self._screen.draw(surface) | |
55 flip() | |
56 self._fps = 1000.0 / clock.tick( | |
57 self._gd.constants.frame_rate) | |
58 | |
59 | |
60 class Screen(object): | |
61 """A top level object for the screen being displayed""" | |
62 | |
63 def __init__(self, gd): | |
64 # Avoid import loop | |
65 from pyntnclick.widgets.base import Container | |
66 | |
67 self.gd = gd | |
68 self.resource = gd.resource | |
69 | |
70 self.surface_size = gd.constants.screen | |
71 self.surface = None | |
72 self.container = Container((0, 0), self.gd, self.surface_size) | |
73 self.setup() | |
74 | |
75 def on_enter(self): | |
76 """Called when this becomes the current screen.""" | |
77 # Create the surface here as flipping between editor and | |
78 # other things kills pygame.display | |
79 self.surface = pygame.Surface(self.surface_size) | |
80 | |
81 def on_exit(self): | |
82 """Called when this stops being the current screen.""" | |
83 self.surface = None | |
84 | |
85 def setup(self): | |
86 """Override for initialization""" | |
87 pass | |
88 | |
89 def dispatch(self, ev): | |
90 self.container.event(ev) | |
91 | |
92 def animate(self): | |
93 """Called every tick - used for peroidic events, etc. | |
94 | |
95 Interested classes are expected to override this""" | |
96 pass | |
97 | |
98 def draw_background(self): | |
99 self.surface.fill(pygame.Color('gray')) | |
100 | |
101 def draw(self, surface): | |
102 if self.surface: | |
103 self.draw_background() | |
104 self.container.draw(self.surface) | |
105 surface.blit(self.surface, self.surface.get_rect()) | |
106 | |
107 def display_dialog(self, dialog): | |
108 self.container.paused = True | |
109 self.container.add(dialog) | |
110 dialog.grab_focus() | |
111 | |
112 def change_screen(self, new_screen_name): | |
113 ScreenChangeEvent.post(new_screen_name) | |
114 | |
115 def screen_event(self, screen_name, event_name, data=None): | |
116 ScreenEvent.post(screen_name, event_name, data) | |
117 | |
118 def process_event(self, event_name, data): | |
119 pass | |
120 | |
121 | |
122 class UserEvent(object): | |
123 """A user event type allowing subclassing, | |
124 to provide an infinate number of user-defined events | |
125 """ | |
126 | |
127 TYPE = "UNKNOWN" | |
128 | |
129 @classmethod | |
130 def post(cls, **kws): | |
131 ev = pygame.event.Event(USEREVENT, utype=cls.TYPE, **kws) | |
132 pygame.event.post(ev) | |
133 | |
134 @classmethod | |
135 def matches(cls, ev): | |
136 return ev.type == USEREVENT and ev.utype == cls.TYPE | |
137 | |
138 | |
139 class ScreenChangeEvent(UserEvent): | |
140 | |
141 TYPE = "SCREEN_CHANGE" | |
142 | |
143 @classmethod | |
144 def post(cls, screen_name): | |
145 super(ScreenChangeEvent, cls).post(screen_name=screen_name) | |
146 | |
147 | |
148 class ScreenEvent(UserEvent): | |
149 | |
150 TYPE = "SCREEN_EVENT" | |
151 | |
152 @classmethod | |
153 def post(cls, screen_name, event_name, data): | |
154 super(ScreenEvent, cls).post(screen_name=screen_name, | |
155 event_name=event_name, data=data) |