-
Notifications
You must be signed in to change notification settings - Fork 48
/
generate_breakout.py
164 lines (134 loc) · 4.08 KB
/
generate_breakout.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
from pdfrw import PdfWriter, PdfReader
from pdfrw.objects.pdfname import PdfName
from pdfrw.objects.pdfstring import PdfString
from pdfrw.objects.pdfdict import PdfDict
from pdfrw.objects.pdfarray import PdfArray
from generate import make_field, make_js_action, make_page
PAGE_WIDTH = 612
PAGE_HEIGHT = 792
CANVAS_WIDTH = 612
CANVAS_HEIGHT = 400
CANVAS_BOTTOM = PAGE_HEIGHT - CANVAS_HEIGHT
PADDLE_WIDTH = 70
PADDLE_HEIGHT = 10
PADDLE_OFFSET_BOTTOM = CANVAS_BOTTOM + 10
BALL_WIDTH = 15
BALL_HEIGHT = 15
BRICK_ROW_COUNT = 5
BRICK_COLUMN_COUNT = 4
BRICK_WIDTH = 75
BRICK_HEIGHT = 20
BRICK_PADDING = 10
BRICK_OFFSET_BOTTOM = CANVAS_BOTTOM + 120
BRICK_OFFSET_LEFT = 100
# Every object we move, toggle on and off, or take events from must be
# an input widget for this to work in Chrome. In this case, we just
# use text fields.
# Chrome also doesn't implement `addField`, so we can't dynamically
# make these at runtime; we have to do it now at PDF creation time.
fields = []
# User won't see this default value; it gets set in JS.
fields.append(make_field(
'countdown', x=280, y=650,
width=300, height=100,
r=1, g=1, b=1,
value='Open in Chrome!'
))
paddle = make_field(
'paddle',
x=(CANVAS_WIDTH - PADDLE_WIDTH)/2, y=PADDLE_OFFSET_BOTTOM,
width=PADDLE_WIDTH, height=PADDLE_HEIGHT,
r=0.1, g=1.0, b=0.1
)
fields.append(paddle)
for c in range(0, BRICK_COLUMN_COUNT):
for r in range(0, BRICK_ROW_COUNT):
brick_x = r*(BRICK_WIDTH + BRICK_PADDING) + BRICK_OFFSET_LEFT
brick_y = c*(BRICK_HEIGHT + BRICK_PADDING) + BRICK_OFFSET_BOTTOM
brick = make_field(
'brick%d,%d' % (c, r),
x=brick_x, y=brick_y,
width=BRICK_WIDTH, height=BRICK_HEIGHT,
r=0.5, g=0.5, b=0.5
)
fields.append(brick)
ball = make_field(
'ball',
x=(CANVAS_WIDTH - PADDLE_WIDTH)/2, y=CANVAS_BOTTOM + 30,
width=BALL_WIDTH, height=BALL_HEIGHT,
r=0.1, g=1.0, b=0.1
)
fields.append(ball)
score = make_field(
'score',
x=0, y=PAGE_HEIGHT - 50,
width=50, height=20,
r=0.9, g=0.9, b=0.9
)
fields.append(score)
lives = make_field(
'lives',
x=0, y=PAGE_HEIGHT - 100,
width=50, height=20,
r=0.9, g=0.9, b=0.9
)
fields.append(lives)
# A weird trick: Chrome PDFium doesn't expose mouse coordinates in its
# subset of PDF API, so there's no way to get a precise mouse X. So I
# create a tall text area at each pixel column and then just track the
# mouse-enter events on all the columns.
for x in range(0, CANVAS_WIDTH):
band = make_field(
'band' + str(x),
x=x, y=0,
width=1, height=CANVAS_BOTTOM,
r=1, g=1, b=1
)
band.AA = PdfDict()
band.AA.E = make_js_action("""
global.mouseX = %d;
""" % x)
band.AA.Fo = make_js_action("""
if (global.count < 0) global.paused = !global.paused;
""")
fields.append(band)
# See `breakout.js`: used to force rendering cleanup in Chrome.
fields.append(make_field(
'whole', x=0, y=CANVAS_BOTTOM,
width=CANVAS_WIDTH, height=CANVAS_HEIGHT,
r=1, g=1, b=1
))
with open('breakout.js', 'r') as js_file:
script = js_file.read()
# Share our constants with the JS script.
page = make_page(fields, """
var CANVAS_WIDTH = %(CANVAS_WIDTH)s;
var CANVAS_HEIGHT = %(CANVAS_HEIGHT)s;
var CANVAS_BOTTOM = %(CANVAS_BOTTOM)s;
var PADDLE_WIDTH = %(PADDLE_WIDTH)s;
var PADDLE_HEIGHT = %(PADDLE_HEIGHT)s;
var PADDLE_OFFSET_BOTTOM = %(PADDLE_OFFSET_BOTTOM)s;
var BALL_WIDTH = %(BALL_WIDTH)s;
var BALL_HEIGHT = %(BALL_HEIGHT)s;
var BRICK_ROW_COUNT = %(BRICK_ROW_COUNT)s;
var BRICK_COLUMN_COUNT = %(BRICK_COLUMN_COUNT)s;
var BRICK_WIDTH = %(BRICK_WIDTH)s;
var BRICK_HEIGHT = %(BRICK_HEIGHT)s;
var BRICK_PADDING = %(BRICK_PADDING)s;
var BRICK_OFFSET_BOTTOM = %(BRICK_OFFSET_BOTTOM)s;
var BRICK_OFFSET_LEFT = %(BRICK_OFFSET_LEFT)s;
%(script)s
""" % locals())
page.Contents.stream = """
BT
/F1 24 Tf
150 300 Td (Move your mouse down here!) Tj
40 -100 Td (also, README below...) Tj
ET
"""
readme = PdfReader('README.pdf')
out = PdfWriter()
out.addpage(page)
for readme_page in readme.pages:
out.addpage(readme_page)
out.write('breakout.pdf')