preface
[sso] / shaken_and_spit_out / SSO.py
1 from os import listdir
2 from glob import glob
3 from random import choice
4 from collections import deque
5
6 from pygame import cursors, PixelArray, Surface, Color
7 from pygame.mouse import set_cursor
8 from pygame.font import Font
9 from pygame.image import load
10 from pygame.locals import *
11
12 from shaken_and_spit_out.pgfw.Game import Game
13 from shaken_and_spit_out.pgfw.GameChild import GameChild
14 from shaken_and_spit_out.pgfw.Sprite import Sprite
15
16 class SSO(Game):
17
18 def __init__(self):
19 Game.__init__(self)
20 set_cursor(*cursors.tri_left)
21 # string = u"\u2250\u2254\u2258"
22 # font = Font(self.get_resource("display", "font"), 24)
23 # self.message = font.render(string, True, (0, 255, 0))
24 self.backgrounds = [load(path) for path in \
25 glob(self.get_resource("image", "background") + \
26 "*.png")]
27 self.used_backgrounds = []
28 self.set_random_background()
29 self.subscribe(self.respond)
30 self.title.activate()
31
32 def set_children(self):
33 Game.set_children(self)
34 self.title = Title(self)
35
36 def set_random_background(self):
37 index = choice(list(set(range(len(self.backgrounds))).\
38 difference(self.used_backgrounds)))
39 self.used_backgrounds.append(index)
40 if len(self.used_backgrounds) > 3:
41 self.used_backgrounds.pop(0)
42 self.background = self.backgrounds[index]
43
44 def respond(self, event):
45 if self.delegate.compare(event, "reset-game"):
46 self.set_random_background()
47
48 def update(self):
49 self.get_screen().blit(self.background, (0, 0))
50 self.title.update()
51 # self.get_screen().fill((0, 0, 0))
52 # self.get_screen().blit(self.message, (100, 100))
53
54
55 class Title(GameChild):
56
57 def __init__(self, parent):
58 GameChild.__init__(self, parent)
59 self.delegate = self.get_delegate()
60 self.preface = Preface(self)
61 self.subscribe(self.respond)
62 self.subscribe(self.respond, MOUSEBUTTONDOWN)
63 self.deactivate()
64
65 def respond(self, event):
66 if self.delegate.compare(event, "reset-game"):
67 self.activate()
68 elif self.active:
69 if event.type == MOUSEBUTTONDOWN and event.button == 1:
70 print "left-click"
71
72 def deactivate(self):
73 self.active = True
74
75 def activate(self):
76 self.active = True
77 self.preface.reset()
78
79 def update(self):
80 if self.active:
81 self.preface.update()
82
83
84 class Preface(GameChild, Surface):
85
86 def __init__(self, parent):
87 GameChild.__init__(self, parent)
88 ds = self.ds = self.get_display_surface()
89 w, h = ds.get_width(), int(round(ds.get_width() / 3))
90 Surface.__init__(self, (w, h), SRCALPHA)
91 self.background = Surface((w, h))
92 self.background.fill((0, 0, 0))
93 mask = self.mask = Surface((w, h), SRCALPHA)
94 pixels = PixelArray(mask)
95 for y in xrange(h):
96 alpha = int(round(255 - (float(y) / h) * 255))
97 for x in xrange(w):
98 pixels[x][y] = Color(255, 255, 255, alpha)
99 del pixels
100 self.set_text()
101 self.reset()
102
103 def set_text(self):
104 lines = self.get_configuration("text", "preface").upper()
105 lines = str.replace(lines, "\n", " ")
106 lines = lines.upper().split("/")
107 cc = 0
108 for line in lines:
109 if len(line) > cc:
110 cc = len(line)
111 cw = int(round((self.get_width() - 80) / float(cc)))
112 font = Font(self.get_resource("display", "font"), 12)
113 font.set_bold(True)
114 ch = font.metrics(lines[0][0])[0][3]
115 margin = 24
116 surface = Surface((cw * cc,
117 ch * len(lines) + margin * (len(lines) - 1)),
118 SRCALPHA)
119 text = self.text = Sprite(self, 200)
120 text.display_surface = self
121 magic_word = "PSPPIT"
122 magic_colors = deque(((255, 128, 128), (255, 255, 128), (128, 255, 128),
123 (128, 255, 255), (128, 128, 255),
124 (255, 128, 255)))
125 box_rect = Rect(0, 0, cw, ch)
126 for _ in xrange(len(magic_word)):
127 frame = surface.copy()
128 box_rect.top = 0
129 for line in lines:
130 box_rect.left = 0
131 extra = cc - len(line)
132 space_count = 0
133 for char in line:
134 if char == " ":
135 space_count += 1
136 space_widths = [1 + extra / space_count] * space_count
137 for ii in xrange(len(space_widths)):
138 if ii >= (extra % space_count):
139 break
140 space_widths[ii] += 1
141 magic_word_ii = 0
142 for ii in xrange(len(line)):
143 if line != lines[-1] and line[ii] == " ":
144 box_rect.left += cw * space_widths.pop(-1)
145 else:
146 if (magic_word_ii and \
147 magic_word_ii < len(magic_word)) \
148 or line[ii:ii + len(magic_word)] == magic_word:
149 color = magic_colors[magic_word_ii]
150 magic_word_ii += 1
151 else:
152 color = (255, 255, 255)
153 left = font.render(line[ii], True, (255, 0, 0))
154 frame.blit(left, self.get_glyph_rect(left, box_rect, 0))
155 right = font.render(line[ii], True, (0, 0, 255))
156 frame.blit(right, self.get_glyph_rect(right, box_rect,
157 4))
158 glyph = font.render(line[ii], True, color)
159 frame.blit(glyph, self.get_glyph_rect(glyph, box_rect,
160 2))
161 box_rect.left += cw
162 box_rect.top += ch + margin
163 text.add_frame(frame)
164 magic_colors.rotate(-1)
165 text.location.centerx = self.get_width() / 2
166
167 def get_glyph_rect(self, glyph, box_rect, offset):
168 gr = glyph.get_rect()
169 gr.center = box_rect.center
170 gr.left += offset
171 return gr
172
173 def reset(self):
174 self.text.location.top = self.get_height()
175
176 def update(self):
177 self.text.move(dy=-.5)
178 if self.text.location.bottom < 0:
179 self.reset()
180 self.blit(self.background, (0, 0))
181 self.text.update()
182 self.blit(self.mask, (0, 0), None, BLEND_RGBA_MIN)
183 self.ds.blit(self, (0, 0))