tune
[e-sieve] / scale_sieve / ScaleSieve.py
1 from random import randint, randrange, choice
2
3 from pygame import Surface, PixelArray, Rect
4 from pygame.draw import aalines, polygon
5 from pygame.locals import *
6
7 from scale_sieve.pgfw.Game import Game
8 from scale_sieve.pgfw.GameChild import GameChild
9 from scale_sieve.pgfw.Sprite import Sprite
10
11 class ScaleSieve(Game):
12
13 def __init__(self):
14 Game.__init__(self)
15 self.background = Surface(self.display.screen.get_size())
16 self.background.fill((255, 80, 190))
17
18 def set_children(self):
19 Game.set_children(self)
20 self.acid = Acid(self)
21 self.sieve = Sieve(self)
22 self.triangles = Triangles(self)
23
24 def update(self):
25 self.display.screen.blit(self.background, (0, 0))
26 self.triangles.update()
27 self.sieve.update()
28
29
30 class Strip(Sprite):
31
32 LEFT, RIGHT = range(2)
33
34 def __init__(self, parent):
35 Sprite.__init__(self, parent)
36 self.display_surface = self.get_display_surface()
37 self.delegate = self.get_game().delegate
38 self.hshifts = Shift(self, -1, "shift-2"), Shift(self, 1, "shift-2")
39 self.add_frames()
40 self.subscribe(self.respond)
41
42 def add_frames(self):
43 pass
44
45 def respond(self, event):
46 compare = self.delegate.compare
47 if compare(event, "left") or compare(event, "left", True):
48 self.hshifts[self.LEFT].active = not event.cancel
49 elif compare(event, "right") or compare(event, "right", True):
50 self.hshifts[self.RIGHT].active = not event.cancel
51
52 def update(self):
53 for shift in self.hshifts:
54 shift.update()
55 if shift.time:
56 self.move(shift.get_change())
57 Sprite.update(self)
58
59
60 class Shift(GameChild):
61
62 def __init__(self, parent, direction, nodeset):
63 GameChild.__init__(self, parent)
64 self.direction = direction
65 self.active = False
66 self.time = 0
67 self.timer = self.get_game().time_filter
68 self.nodeset = self.get_game().interpolator.get_nodeset(nodeset)
69
70 def update(self):
71 least, greatest = self.nodeset[0].x, self.nodeset[-1].x
72 if self.active and self.time < greatest:
73 self.time = min(self.time + self.timer.get_last_frame_duration(),
74 greatest)
75 elif not self.active and self.time > least:
76 self.time = max(self.time - self.timer.get_last_frame_duration(),
77 least)
78
79 def get_change(self):
80 return self.nodeset.get_y(self.time) * self.direction
81
82
83 class Sieve(Strip):
84
85 UP, DOWN = range(2)
86
87 def __init__(self, parent):
88 Strip.__init__(self, parent)
89 self.delegate = self.get_game().delegate
90 self.location.center = self.display_surface.get_rect().center
91 self.vshifts = Shift(self, -1, "shift"), Shift(self, 1, "shift")
92 self.electric = Electric(self)
93 self.add_location(offset=(self.location.w, 0))
94 for location in self.locations:
95 location.bottom = self.parent.acid.ry[1]
96
97 def add_frames(self):
98 bar_locations = []
99 self.bar_rects = bar_rects = []
100 x = 0
101 sh = 30
102 nodeset = self.get_game().interpolator.get_nodeset("scale")
103 self.bar_w = bar_w = 3
104 self.gaps = gaps = []
105 while x < nodeset[-1].x:
106 bar_locations.append(x)
107 bar_rects.append(Rect(x, 0, bar_w, sh))
108 gaps.append(nodeset.get_y(x, natural=True))
109 x += gaps[-1]
110 surface = Surface((x, sh))
111 transparent_color = (255, 0, 255)
112 surface.fill(transparent_color)
113 surface.set_colorkey(transparent_color)
114 frames = surface, surface.copy()
115 colors = (0, 255, 0), (153, 0, 204)
116 for x in bar_locations:
117 bar_rects.append(Rect(x + surface.get_width(), 0, bar_w, sh))
118 for ii, frame in enumerate(frames):
119 frame.fill(colors[ii], (x, 0, bar_w, sh))
120 frame.fill(colors[ii - 1], (x + 1, 1, 1, sh - 2))
121 for frame in frames:
122 self.add_frame(frame)
123
124 def respond(self, event):
125 Strip.respond(self, event)
126 compare = self.delegate.compare
127 if compare(event, "up") or compare(event, "up", True):
128 self.vshifts[self.UP].active = not event.cancel
129 elif compare(event, "down") or compare(event, "down", True):
130 self.vshifts[self.DOWN].active = not event.cancel
131
132 def update(self):
133 if self.location.right < 0:
134 self.move(self.location.w)
135 if self.locations[1].left > self.display_surface.get_width():
136 self.move(-self.location.w)
137 for shift in self.vshifts:
138 shift.update()
139 if shift.time:
140 self.move(dy=shift.get_change())
141 acid = self.parent.acid
142 if self.location.bottom < acid.ry[0]:
143 self.vshifts[self.UP].time = 0
144 for location in self.locations:
145 location.bottom = acid.ry[0]
146 elif self.location.bottom > acid.get_level():
147 self.vshifts[self.DOWN].time = 0
148 for location in self.locations:
149 location.bottom = acid.get_level()
150 self.electric.location.centery = self.location.centery + 13
151 self.electric.update()
152 for rect in self.bar_rects:
153 rect.centery = self.location.centery
154 Strip.update(self)
155
156
157 class Electric(Sprite):
158
159 def __init__(self, parent):
160 Sprite.__init__(self, parent)
161 self.display_surface = self.get_display_surface()
162 self.add_frames()
163
164 def add_frames(self):
165 surface = Surface((self.display_surface.get_width(),
166 self.parent.location.h - 10))
167 frames = surface, surface.copy()
168 colors = (255, 255, 0), (100, 89, 213)
169 pixel_arrays = PixelArray(frames[0]), PixelArray(frames[1])
170 for x in xrange(len(pixel_arrays[0])):
171 for y in xrange( len(pixel_arrays[0][0])):
172 pixel_arrays[0][x][y] = colors[(y + x) % 2]
173 pixel_arrays[1][x][y] = colors[(y + x + 1) % 2]
174 for pixels in pixel_arrays:
175 del pixels
176 for frame in frames:
177 self.add_frame(frame)
178
179
180 class Triangles(GameChild, list):
181
182 def __init__(self, parent):
183 GameChild.__init__(self, parent)
184 list.__init__(self, [])
185 self.display_surface = self.get_display_surface()
186 self.populate()
187
188 def populate(self):
189 if not self:
190 self.append(Triangle(self))
191 self[-1].location.bottom = 0
192 self.set_next_gap()
193 while self[-1].location.top > -self.display_surface.get_height():
194 self.append(Triangle(self))
195 self[-1].location.bottom = self[-2].location.top - self.next_gap
196 self.set_next_gap()
197
198 def set_next_gap(self):
199 self.next_gap = randint(202, 368)
200
201 def update(self):
202 self.populate()
203 if self[0].location.collidelist(self.parent.sieve.locations) != -1:
204 sieve = self.parent.sieve
205 if self[0].location.colliderect(sieve.electric.location):
206 print "pass"
207 self.remove(self[0])
208 else:
209 for br in sieve.bar_rects:
210 for tr in self[0].collision_rects:
211 if tr.move((self[0].location.left,
212 0)).colliderect(br.move((sieve.location.left,
213 0))):
214 self.remove(self[0])
215 break
216 for triangle in self:
217 triangle.update()
218
219
220 class Triangle(Sprite):
221
222 def __init__(self, parent):
223 Sprite.__init__(self, parent)
224 mark = randint(72, 296)
225 sieve = self.parent.parent.sieve
226 gaps = sieve.gaps
227 start = randrange(0, len(gaps))
228 widths = [gaps[start]]
229 while sum(widths) < mark:
230 widths.append(gaps[(start + len(widths)) % len(gaps)])
231 surface = Surface((sum(widths), 20))
232 surface.set_colorkey((0, 0, 0))
233 x = 0
234 height = surface.get_height()
235 margin = 26
236 self.collision_rects = collision_rects = []
237 for width in widths:
238 x += sieve.bar_w
239 points = (x + margin / 2, height - 2), \
240 (x + width - margin / 2 - 1, height - 2), \
241 (x + width / 2.0, 1)
242 polygon(surface, (60, 255, 220), points)
243 collision_rects.append(Rect(points[0], (width - margin - 1, 1)))
244 x += width - sieve.bar_w
245 self.add_frame(surface)
246 self.location.centerx = self.get_display_surface().get_rect().centerx
247
248 def update(self):
249 acid = self.get_game().acid
250 ratio = 1 - (self.get_game().sieve.location.bottom - acid.ry[0]) / \
251 float(acid.ry[1] - acid.ry[0])
252 self.move(dy=4 * ratio + 2)
253 for rect in self.collision_rects:
254 rect.bottom = self.location.bottom
255 Sprite.update(self)
256
257
258 class Acid(GameChild):
259
260 def __init__(self, parent):
261 GameChild.__init__(self, parent)
262 self.ry = 160, 640
263 self.space = 1
264
265 def get_level(self):
266 return self.space * (self.ry[1] - self.ry[0]) + self.ry[0]