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)