76be5831b0615732ff4626a31529a52dff9afbe4
[minwii.git] / src / pgu / engine.py
1 """a state engine.
2 """
3 import pygame
4 from pygame.locals import *
5
6 class State:
7 """Template Class -- for a state.
8
9 <pre>State(game,value...)</pre>
10
11 <dl>
12 <dt>game<dd>The state engine.
13 <dt>value<dd>I usually pass in a custom value to a state
14 </dl>
15
16 <p>For all of the template methods, they should return None unless they return
17 a new State to switch the engine to.</p>
18 """
19 def __init__(self,game,value=None):
20 self.game,self.value = game,value
21 def init(self):
22 """Template Method - Initialize the state, called once the first time a state is selected.
23
24 <pre>State.init()</pre>
25 """
26 return
27 def paint(self,screen):
28 """Template Method - Paint the screen. Called once after the state is selected.
29
30 <p>State is responsible for calling <tt>pygame.display.flip()</tt> or whatever.</p>
31
32 <pre>State.paint(screen)</pre>
33 """
34 return
35
36 def repaint(self):
37 """Template Method - Request a repaint of this state.
38
39 <pre>State.repaint()</pre>
40 """
41 self._paint = 1
42 def update(self,screen):
43 """Template Method - Update the screen.
44
45 <p>State is responsible for calling <tt>pygame.display.update(updates)</tt> or whatever.</p>
46
47 <pre>State.update(screen)</pre>
48 """
49 return
50 def loop(self):
51 """Template Method - Run a logic loop, called once per frame.
52
53 <pre>State.loop()</pre>
54 """
55 return
56 def event(self,e):
57 """Template Method - Recieve an event.
58
59 <pre>State.event(e)</pre>
60 """
61 return
62
63 class Quit(State):
64 """A state to quit the state engine.
65
66 <pre>Quit(game,value)</pre>
67 """
68
69 def init(self):
70 self.game.quit = 1
71
72 class Game:
73 """Template Class - The state engine.
74 """
75 def fnc(self,f,v=None):
76 s = self.state
77 if not hasattr(s,f): return 0
78 f = getattr(s,f)
79 if v != None: r = f(v)
80 else: r = f()
81 if r != None:
82 self.state = r
83 self.state._paint = 1
84 return 1
85 return 0
86
87 def run(self,state,screen=None):
88 """Run the state engine, this is a infinite loop (until a quit occurs).
89
90 <pre>Game.run(state,screen=None)</pre>
91
92 <dl>
93 <dt>game<dd>a state engine
94 <dt>screen<dd>the screen
95 </dl>
96 """
97 self.quit = 0
98 self.state = state
99 if screen != None: self.screen = screen
100
101 self.init()
102
103 while not self.quit:
104 self.loop()
105
106 def loop(self):
107 s = self.state
108 if not hasattr(s,'_init') or s._init:
109 s._init = 0
110 if self.fnc('init'): return
111 else:
112 if self.fnc('loop'): return
113 if not hasattr(s,'_paint') or s._paint:
114 s._paint = 0
115 if self.fnc('paint',self.screen): return
116 else:
117 if self.fnc('update',self.screen): return
118
119 for e in pygame.event.get():
120 #NOTE: this might break API?
121 #if self.event(e): return
122 if not self.event(e):
123 if self.fnc('event',e): return
124
125 self.tick()
126 return
127
128 def init(self):
129 """Template Method - called at the beginning of State.run() to initialize things.
130
131 <pre>Game.init()</pre>
132 """
133 return
134
135 def tick(self):
136 """Template Method - called once per frame, usually for timer purposes.
137
138 <pre>Game.tick()</pre>
139 """
140 pygame.time.wait(10)
141
142 def event(self,e):
143 """Template Method - called with each event, so the engine can capture special events.
144
145 <pre>Game.event(e): return captured</pre>
146
147 <p>return a True value if the event is captured and does not need to be passed onto the current
148 state</p>
149 """
150 if e.type is QUIT:
151 self.state = Quit(self)
152 return 1
153
154 # vim: set filetype=python sts=4 sw=4 noet si :