Merge lp:~mcfletch/simplegc/tutorial-skeleton into lp:simplegc

Proposed by Mike C. Fletcher
Status: Merged
Merged at revision: 322
Proposed branch: lp:~mcfletch/simplegc/tutorial-skeleton
Merge into: lp:simplegc
Diff against target: 236 lines (+161/-5)
8 files modified
docs/dev.widget.rst (+2/-1)
docs/tutorial.helloworld.rst (+68/-0)
docs/tutorial.rst (+1/-0)
example/hellobase.py (+49/-0)
example/helloworld-01.py (+9/-0)
example/helloworld-02.py (+10/-0)
example/helloworld-03.py (+10/-0)
sgc/locals.py (+12/-4)
To merge this branch: bzr merge lp:~mcfletch/simplegc/tutorial-skeleton
Reviewer Review Type Date Requested Status
Sam Bull Pending
Review via email: mp+120270@code.launchpad.net

Description of the change

Attempt to make the hello world tutorial easier to maintain, as well as making each iterative version much shorter (basically just a single function, an import, and an if __name__ block). Not yet completed (e.g. the 3 subsequent scripts are not described yet), so not yet replacing the original tutorial.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'docs/dev.widget.rst'
2--- docs/dev.widget.rst 2012-08-16 11:38:47 +0000
3+++ docs/dev.widget.rst 2012-08-18 21:38:22 +0000
4@@ -175,7 +175,8 @@
5
6 We can utilise events in our widget by defining an `on_[name]()` method. The
7 method must be prefixed with "on\_" to ensure the event can be set through the
8-config() method automatically and to ensure the EventSlot object will work.
9+config() method automatically and to ensure the :py:class:`sgc.locals.EventSlot`
10+object will work.
11
12 .. literalinclude:: ../example/custom_widget.py
13 :linenos:
14
15=== added file 'docs/tutorial.helloworld.rst'
16--- docs/tutorial.helloworld.rst 1970-01-01 00:00:00 +0000
17+++ docs/tutorial.helloworld.rst 2012-08-18 21:38:22 +0000
18@@ -0,0 +1,68 @@
19+Getting Started
20+---------------
21+
22+Simple Game Code (SGC) attempts to follow Pygame's conventions
23+and usage, so your SGC code will tend to look much like any
24+Pygame module.
25+
26+Imports
27++++++++
28+
29+Your SGC script will need many symbols from both Pygame and
30+SGC.
31+
32+.. literalinclude:: ../example/hellobase.py
33+ :end-before: main
34+
35+Overall Strategy
36+++++++++++++++++
37+
38+Your script needs to do the following to work with SGC:
39+
40+ * Initialize :py:mod:`pygame` and :py:mod:`pygame.font`
41+ * Create a :py:class:`sgc.surface.Screen` instance
42+ * Create a :py:class:`pygame.time.Clock` instance to track inter-frame timings
43+ * Create some SGC widgets
44+ * Start a loop that:
45+
46+ * Gets the current time
47+ * Processes pending Pygame events with SGC :py:func:`sgc.event`
48+ * Redraws/refreshes the screen
49+
50+.. literalinclude:: ../example/hellobase.py
51+ :pyobject: main
52+
53+Processing Events
54++++++++++++++++++
55+
56+SGC needs to process all events that come from Pygame. The easiest way to do this
57+is to insert :py:func:`sgc.event` into your standard Pygame-style event processing
58+loop:
59+
60+.. literalinclude:: ../example/hellobase.py
61+ :pyobject: process_events
62+
63+Updating the Screen
64++++++++++++++++++++
65+
66+SGC also needs to be able to draw its widgets onto the screen on each frame. To
67+do this it needs to know how long has passed since the last frame (to allow for
68+updating animated frames and the like).
69+
70+.. literalinclude:: ../example/hellobase.py
71+ :pyobject: draw_screen
72+
73+Putting it All Together
74+++++++++++++++++++++++++
75+
76+Our code so far just creates a blank Screen and updates it
77+every frame. We'll save it into a file named ``hellobase.py``
78+and use it throughout the rest of this tutorial:
79+
80+.. literalinclude:: ../example/hellobase.py
81+ :language: python
82+ :linenos:
83+
84+The file is available as ``example/hellobase.py`` in the
85+source distribution. We'll use it in the next sections where
86+we will define functions to render some widgets.
87
88=== modified file 'docs/tutorial.rst'
89--- docs/tutorial.rst 2012-06-20 10:55:59 +0000
90+++ docs/tutorial.rst 2012-08-18 21:38:22 +0000
91@@ -16,5 +16,6 @@
92 :maxdepth: 1
93
94 tutorial.get_started
95+ tutorial.helloworld
96 tutorial.events
97 tutorial.theming
98
99=== added file 'example/hellobase.py'
100--- example/hellobase.py 1970-01-01 00:00:00 +0000
101+++ example/hellobase.py 2012-08-18 21:38:22 +0000
102@@ -0,0 +1,49 @@
103+#! /usr/bin/env python
104+import sgc
105+from sgc.locals import *
106+
107+import pygame
108+from pygame.locals import *
109+
110+def main(create_widgets):
111+ """Mainloop for the hello world tutorial code"""
112+ # Initialize the pygame modules we need
113+ pygame.display.init()
114+ pygame.font.init()
115+
116+ # Create a drawing surface
117+ screen = sgc.surface.Screen((640,480))
118+
119+ # Create a clock to update the screen with current time
120+ clock = pygame.time.Clock()
121+ # Create our SGC widgets
122+ create_widgets( screen )
123+
124+ while True:
125+ # get duration to update widgets
126+ time = clock.tick(30)
127+ process_events()
128+ draw_screen(screen, time)
129+
130+def process_events():
131+ """Process waiting events from Pygame using SGC"""
132+ for event in pygame.event.get():
133+ # Tell SGC to process its events
134+ sgc.event(event)
135+ # Now check for non-GUI events you'd like to handle...
136+ if event.type == QUIT:
137+ exit()
138+
139+def draw_screen(screen, time):
140+ """Draw the current state of the screen
141+
142+ screen -- :py:class:`sgc.surface.Screen` instance
143+ time -- time-delta as provided by Clock.tick()
144+ """
145+ screen.fill((0,0,0))
146+ # tell SGC to draw its widgets
147+ sgc.update(time)
148+ pygame.display.flip()
149+
150+if __name__ == "__main__":
151+ main(lambda screen: None)
152
153=== added file 'example/helloworld-01.py'
154--- example/helloworld-01.py 1970-01-01 00:00:00 +0000
155+++ example/helloworld-01.py 2012-08-18 21:38:22 +0000
156@@ -0,0 +1,9 @@
157+from hellobase import *
158+
159+def create_widgets(screen):
160+ """Create a simple button"""
161+ btn = sgc.Button(label="Does Nothing", pos=('50%','50%'))
162+ btn.add(0)
163+
164+if __name__ == "__main__":
165+ main(create_widgets)
166
167=== added file 'example/helloworld-02.py'
168--- example/helloworld-02.py 1970-01-01 00:00:00 +0000
169+++ example/helloworld-02.py 2012-08-18 21:38:22 +0000
170@@ -0,0 +1,10 @@
171+from hellobase import *
172+
173+def create_widgets(screen):
174+ """Create a button, align it to the bottom-right corner of the screen"""
175+ btn = sgc.Button(label="Bottom Right", pos=(0,0))
176+ btn.rect.bottomright = screen.rect.bottomright
177+ btn.add(0)
178+
179+if __name__ == "__main__":
180+ main(create_widgets)
181
182=== added file 'example/helloworld-03.py'
183--- example/helloworld-03.py 1970-01-01 00:00:00 +0000
184+++ example/helloworld-03.py 2012-08-18 21:38:22 +0000
185@@ -0,0 +1,10 @@
186+from hellobase import *
187+
188+def create_widgets(screen):
189+ """Create a button, align it to the bottom-right corner of the screen"""
190+ btn = sgc.Button(label="Exit", on_click=lambda *args: exit())
191+ btn.rect.bottomright = screen.rect.bottomright
192+ btn.add(0)
193+
194+if __name__ == "__main__":
195+ main(create_widgets)
196
197=== modified file 'sgc/locals.py'
198--- sgc/locals.py 2012-08-06 09:57:04 +0000
199+++ sgc/locals.py 2012-08-18 21:38:22 +0000
200@@ -17,25 +17,33 @@
201 class EventSlot(object):
202 """
203 Event slots object. Allows dynamic allocation of events.
204-
205 """
206
207 __slots__ = ("_funcs",)
208
209 def __init__(self, widget, event, funcs=()):
210 """
211- Args:
212+ Arguments
213+
214 widget: The widget you want to bind this event slot to.
215 event: ``str`` The attribute you want to bind to (e.g. 'on_click').
216 funcs: A sequence of functions you want to include by default.
217
218 """
219- assert event.startswith("on_") and hasattr(widget, event), \
220- "Invalid event"
221+ if not event.startswith("on_"):
222+ raise ValueError( "Expected an event name starting with 'on_', got %r"%(
223+ event,
224+ ))
225+ if not hasattr( widget, event ):
226+ raise TypeError( "Event %r does not exist in %s widget"%(
227+ event, widget.__class__,
228+ ))
229 self._funcs = list(funcs)
230 setattr(widget, event, types.MethodType(self, widget, widget.__class__))
231
232 def __call__(self, widget):
233+ """Callback all registered functions for this event
234+ """
235 for f in self._funcs:
236 f(widget)
237

Subscribers

People subscribed via source and target branches