@@ -6,3 +6,185 @@ Game API
6
6
This is documentation for the game API - based upon the amazing work done by
7
7
Larry Hastings. THIS IS A STRAW MAN.
8
8
9
+
10
+ Overview
11
+ ========
12
+
13
+ Writing games is a wonderful way to introduce programming to beginners. We aim
14
+ to make this as simple as possible given the hardware constraints of the BBC
15
+ micro:bit. As Larry says,
16
+
17
+ Using [the micro:bit] properly can require clever code and programming
18
+ insights far beyond what is reasonable to expect from the micro:bit's
19
+ beginner programmers. Not to mention, the code size for these solutions
20
+ would eat into the astonishingly restrictive RAM space available on the
21
+ micro:bit.
22
+
23
+ Wise words indeed. Larry's excellent primer and discussion of his work can be
24
+ found here:
25
+
26
+ https://bitbucket.org/larry/microbit_game
27
+
28
+ The purpose of this document is to outline the three classes as imagined in
29
+ the microbit API. It's currently a straw man that we can poke with a stick. The
30
+ intention is to create an API suitable for eleven year old kids so much of my
31
+ re-write / re-naming is done with this in mind. PLEASE FEEL FREE TO CHANGE.
32
+
33
+ There are three classes (each described below) found in the `microbit.game `
34
+ namespace:
35
+
36
+ * `Controller ` (was accelerometer_scaler_new) - simplifies the reading of the accelerometer so that it is appropriate for controlling games.
37
+ * `Trigger ` (was button_minder) - easy reading of button states.
38
+ * `Scheduler ` - a very simple scheduler to trigger things after some pre-defined period of time.
39
+
40
+ Controller
41
+ ==========
42
+
43
+ The micro:bit would be great for controlling a character or scrolling the
44
+ screen. This class allows kids to define a range of desired numeric states to
45
+ be output as the device is moved along a certain axis.
46
+
47
+ The class introduces "dead zones" to ensure tremours in movement don't result
48
+ in wildly changing values.
49
+
50
+ It's also possible to reverse the range by setting the upper bound as the
51
+ output minimum and the lower bound as the output maximum.
52
+
53
+ Finally, it's possible to set the size of the middle of the range. As Larry
54
+ explains,
55
+
56
+ If you were simulating a lever balancing on a fulcrum, you might want a
57
+ large range to mean 0 (hold steady), and small ranges on the ends to mean
58
+ "tilt left" (-1) and "tilt right" (+1).
59
+
60
+ .. py :class :: Controller(read, accel_min = 512 , accel_max = 512 , out_min = - 2 , out_max = 2 , middle = 200 , deadzone = 0.2 )
61
+
62
+ Creates a controller object with the ``read `` function that takes no
63
+ arguments and returns an integer. This function is called to get the
64
+ current value of the accelerometer.
65
+
66
+ ``accel_min `` defines the minimum value reported by the ``read `` function
67
+ that the object should accept. Values below this will be clipped to
68
+ ``accel_min ``.
69
+
70
+ ``accel_max `` defines the maximum value reported by the ``read `` function
71
+ that the object should accept. Values above this will be clipped to
72
+ ``accel_max ``.
73
+
74
+ ``out_min `` defines the minimum value the object should scale to. The
75
+ object's ``scan `` method will never report a number lower than this.
76
+
77
+ ``out_max `` defines the maximum value the object should scale to. The
78
+ object's ``scan `` method will never report a number higher than this.
79
+
80
+ ``middle `` defines the amount to pad the centre region of the input in
81
+ terms of the accelerometer's range. The non-US "centre" is not used to
82
+ avoid spelling confusion.
83
+
84
+ ``deadzone `` represents how big the dead zones are, expressed as a floating
85
+ point number relating to the "live" zones. The default value of 0.2 makes
86
+ the dead zones 20% of the size of the live zones.
87
+
88
+ .. py :method :: scan()
89
+
90
+ Scans the current state returned by the ``read `` function. Returns the
91
+ current scaled value.
92
+
93
+ Trigger
94
+ =======
95
+
96
+ The micro:bit has two buttons: A and B. This class makes it easy to track
97
+ their state so they can be used to trigger events and actions in games.
98
+
99
+ .. py :class :: Trigger(a, b, delay)
100
+
101
+ Creates a trigger object. One of each of the parameters must be used. If
102
+ ``a `` is set to ``True `` then the object will monitor button A. If ``b ``
103
+ is set to ``True `` then the object will monitor button B. If the ``delay ``
104
+ argument is set to an integer indicating milliseconds then the object will
105
+ monitor both buttons if both buttons are pressed and held within ``delay ``
106
+ period of time.
107
+
108
+ The ``delay `` argument permits us to hit both buttons simultaneously. Since
109
+ we are notoriously slower than computers it's likely that there may be a
110
+ slight ``delay `` between pressing A and pressing B.
111
+
112
+ .. py :method :: pressed()
113
+
114
+ Returns ``True `` if the button state monitored by the object (defined when
115
+ initialising - see above) is pressed (either, A or B or both). Otherwise,
116
+ returns ``False ``.
117
+
118
+ Scheduler
119
+ =========
120
+
121
+ Often people will want to do something, pause for a while, then do other
122
+ things. In other words, they'll need a way to schedule things to happen in the
123
+ future. This class is similar to the scheduler class in Python's sched module
124
+ found in the standard library.
125
+
126
+ Users add events (represented by arbitrary values) and time delays to the
127
+ schedule. Run the schedule to pause and, at the appropriate moment, get the
128
+ next scheduled event.
129
+
130
+ .. py :class :: Scheduler
131
+
132
+ Creates an object to be used to schedule events after pre-defined periods
133
+ of time.
134
+
135
+ .. py :method :: add(event, delta, repeat = False )
136
+
137
+ Add an ``event `` to the schedule object to be fired at ``delta ``
138
+ milliseconds in the future. If ``repeat `` is ``True `` then this event will
139
+ continue to fire after ``delta `` amount of time. If ``repeat `` is ``False ``
140
+ the event will only fire once.
141
+
142
+ Returns ``True `` if the ``event `` was added to the schedule.
143
+
144
+ .. py :method :: cancel(event)
145
+
146
+ Cancels all the events from the schedule identified by ``event ``. Returns
147
+ the number of matching events cancelled.
148
+
149
+ .. py :method :: clear()
150
+
151
+ Clears all the events from the schedule. Returns the number of events
152
+ cancelled.
153
+
154
+ .. py :method :: run()
155
+
156
+ Runs the scheduler. The program blocks until it's time for the next
157
+ event to fire. The return value (at the time when the event fires) is the
158
+ arbitrary ``event `` value passed in to the ``add `` method when the event
159
+ was created.
160
+
161
+ Re-run to get the next scheduled event at the expected time.
162
+
163
+ Running the scheduler with an empty schedule is an error. It will raise an
164
+ as-yet-to-be determined exceptioni (IndexError - the schedule is perhaps a
165
+ sort of sequence?).
166
+
167
+ Here's a made up example of the scheduler in use::
168
+
169
+ schedule = game.Scheduler()
170
+ events = {
171
+ 'b': 5000,
172
+ 'a': 1000,
173
+ 'c': 6000,
174
+ }
175
+ for k, v in events.items():
176
+ schedule.add(k, v)
177
+ while True:
178
+ try:
179
+ ev = schedule.run() # blocks until the next scheduled event
180
+ print(ev)
181
+ except IndexError:
182
+ break
183
+
184
+ This should output::
185
+
186
+ a
187
+ b
188
+ c
189
+
190
+ ...after 1, 5 and 6 seconds respectively.
0 commit comments