/
pygame_demo2.py
430 lines (364 loc) · 13.6 KB
/
pygame_demo2.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
#!/usr/bin/python
# import the relevant libraries
import sys
import time
import pygame
from pygame import gfxdraw
import random
import os
import math
import noise
# from pygame.locals import *
from Vec2d import Vec2d as Vec2d
from Vector2d import Vector2d as Vector2d
# define screen size
SCREEN = (640, 480)
# control Frame Rate
CLOCK = pygame.time.Clock()
FPS = 50
# define background musicfile
BACKGROUND_MUSIC = "monkey_island_theme.mp3"
class FinishedException(Exception):
def __init__(self, msg):
self.msg = msg
class GameObject(object):
"""Abstract class definition"""
def __init__(self, surface, game_engine):
self.surface = surface
self.game_engine = game_engine
def update(self):
"""update every step"""
pass
def initialize(self):
"""set initial state"""
pass
def move(self):
"""move something"""
pass
def draw(self):
"""draw on screen"""
pass
class StarField(GameObject):
def __init__(self, surface, game_engine, direction=(1, 0), color=(255, 255, 255), amplitude=10):
GameObject.__init__(self, surface, game_engine)
rand_x = [random.random() * self.surface.get_width() for x in xrange(200)]
rand_y = [random.random() * self.surface.get_height() for y in xrange(200)]
self.points = zip(rand_x, rand_y)
self.color = color
self.direction = direction
self.amplitude = amplitude
self.degree = math.pi / 360
def update(self):
newpoints = []
for x, y in self.points:
# boundary check
if 0 > x :
x = self.surface.get_width()
if x > self.surface.get_width() :
x = 0
if 0 > y :
y = self.surface.get_height()
if y > self.surface.get_height() :
y = 0
# directioon
point = (int(x + self.direction[0]), int(y + math.sin(self.degree * x) * self.amplitude + self.direction[1]))
newpoints.append(point)
self.points = newpoints
self.draw()
def draw(self):
for point in self.points:
self.surface.set_at(point, self.color)
class WormHole(GameObject):
def __init__(self, surface, game_engine, color=(255, 255, 255)):
GameObject.__init__(self, surface, game_engine)
self.color = color
self.middle = Vec2d(self.surface.get_width() / 2, self.surface.get_height() / 2)
self.circles = []
self.initialize()
self.angle = 0
def initialize(self):
for index in range(10):
circle = []
first = Vec2d(20 * index * 1.2, 0)
for degree in xrange(0, 360, 5):
circle.append(first.rotated(degree))
self.circles.append(circle)
def run(self):
angle = self.angle
index = 1
for circle in self.circles:
origin = self.middle + Vec2d(10 * index * 1.2, 0).rotated(angle)
for point in circle:
point.rotate(5)
draw_point = origin + point
self.surface.set_at((int(draw_point.x), int(draw_point.y)), self.color)
# rotate for next circle
angle += 10
index += 1
self.angle += 10
#self.draw()
def draw(self):
pass
class Bean(object):
def __init__(self, surface, beans, parameter_dict):
self.__dict__.update(parameter_dict)
self.surface = surface
self.beans = beans
self.vel = 3 # or option vel
self.accel = -0.004 # or option accel
def draw(self):
if self.vel < 0 :
self.beans.remove(self)
self.x_off += 0.0007
self.y_off += 0.0007
self.vel += self.accel
self.x += abs(noise.pnoise1(self.x_off) * self.vel) - self.vel / 2
self.y += abs(noise.pnoise1(self.y_off) * self.vel) - self.vel / 2
self.surface.set_at((int(self.x), int(self.y)), self.get_color())
def get_color(self):
h = abs(noise.pnoise1((self.x_off + self.y_off) / 2)) * 360
color = pygame.Color(0, 255, 0, 100)
print color
# color.hsva = (h, 100, 100, 4)
return(color)
class CoffeeDraw(GameObject):
def __init__(self, surface, game_engine):
GameObject.__init__(self, surface, game_engine)
self.beans = []
self.framecount = 1
def update(self):
self.framecount += 1
x_off = self.framecount * 0.0003
y_off = x_off + 20
x = noise.pnoise1(x_off) * self.surface.get_width()
y = noise.pnoise1(y_off) * self.surface.get_height()
# every 8th frame a new bean
print len(self.beans)
if self.framecount % 8 == 0:
self.beans.append(Bean(self.surface, self.beans, {
"x" : x,
"y" : y,
"x_off" : x_off,
"y_off" : y_off}))
for bean in self.beans:
bean.draw()
class BouncingHline(GameObject):
def __init__(self, surface, game_engine, speed, color=(255, 255, 255), amplitude=10, start=0):
GameObject.__init__(self, surface, game_engine)
self.color = color
self.speed = speed
self.amplitude = amplitude
self.y = None
self.degree = speed * math.pi / 360
self.angle = start * self.degree
def update(self):
self.y = self.surface.get_height() / 2 + self.amplitude * math.sin(self.angle)
self.angle += self.degree
self.draw()
def draw(self):
pygame.draw.line(self.surface, self.color, (0, self.y), (self.surface.get_width(), self.y))
class RotatingLine(GameObject):
def __init__(self, surface, game_engine):
self.surface = surface
self.game_engine = game_engine
self.initialize()
self.origin = Vec2d(self.surface.get_width() / 2, self.surface.get_height() /2)
self.origin1 = Vec2d(self.surface.get_width() / 3, self.surface.get_height() /2)
self.color = (255, 0, 0)
self.vector = None
self.initialize()
def update(self):
"""update every step"""
self.move()
self.draw()
def initialize(self):
"""set initial state"""
self.vector = Vec2d(100, 0)
self.diffvector = Vec2d(50, 0.1)
def move(self):
"""move something"""
self.vector.rotate(1)
self.origin.rotate(1)
self.origin1.rotate(3)
def draw(self):
"""draw on screen"""
pygame.draw.line(self.surface, self.color, self.origin, self.origin + self.vector)
pygame.draw.line(self.surface, self.color, self.origin1, self.origin1 + self.vector.perpendicular())
class GameEngine(object):
"""Controls Life of many GameObjects"""
def __init__(self, surface, gamestat):
"""just __init__"""
self.surface = surface
self.gamestat = gamestat
# create initial set of character
self.game_objects = []
self.generate()
def update(self):
""" handle all characters an generate more if to less on screen"""
# update characters
for game_object in self.game_objects:
game_object.update()
return("running")
def generate(self):
""" generates a new character and put it on the list """
self.game_objects.append(CoffeeDraw(self.surface, self))
# self.game_objects.append(RotatingLine(self.surface, self))
# self.game_objects.append(StarField(self.surface, self, direction=(1, 3), color=100, amplitude=2))
# self.game_objects.append(StarField(self.surface, self, direction=(2, 2), color=150, amplitude=1))
# self.game_objects.append(StarField(self.surface, self, direction=(3, 1), color=160, amplitude=2))
# self.game_objects.append(BouncingHline(self.surface, self, speed=1, color=255, amplitude=100, start=0))
# self.game_objects.append(BouncingHline(self.surface, self, speed=1, color=225, amplitude=99, start=5))
# self.game_objects.append(BouncingHline(self.surface, self, speed=1, color=205, amplitude=98, start=10))
# self.game_objects.append(BouncingHline(self.surface, self, speed=1, color=185, amplitude=97, start=15))
# self.game_objects.append(BouncingHline(self.surface, self, speed=1, color=165, amplitude=96, start=20))
def delete(self, child, clicked):
"""deletes child from list"""
for item in self.game_objects:
if item == child:
self.game_objects.remove(item)
class SetPalette(object):
"""simple sets palette"""
def __init__(self, surface, palette):
self.surface = surface
self.palette = palette
def run(self):
self.surface.set_palette(self.palette)
raise FinishedException("job done, delete me")
class FlashEffect(object):
"""Flashes Surface, fade all colors to white"""
def __init__(self, surface, beat, repeat, amount):
self.surface = surface
self.beat = beat
self.repeat = repeat
self.amount = amount
# current timestamp
self.timestamp = time.time() + beat
# how long will the surface be white
self.flash_active = 0
# white palette
self.white = []
for x in xrange(255):
self.white.append((255, 255, 255))
self.old_palette = None
def run(self):
if self.flash_active == 1:
# reset to old palette
self.surface.set_palette(self.old_palette)
self.flash_active = 0
elif self.flash_active > 0:
# surface was flashed
self.flash_active -= 1
elif time.time() >= self.timestamp:
# trigger for new flash was reached
self.old_palette = self.surface.get_palette()
self.surface.set_palette(self.white)
self.timestamp = time.time() + self.beat
# flash will last 5 Frames
self.flash_active = 5
self.amount -= 1
if self.amount == 0:
raise FinishedException("finished work, delete me")
class FadeEffect(object):
"""Flashes Surface, fade all colors to white"""
def __init__(self, surface, counter=7):
self.surface = surface
self.palette = self.surface.get_palette()
# fade to black in counter Frames
self.counter = counter
def run(self):
newpalette = []
for (red, green, blue) in self.surface.get_palette():
red = int(red / 1.2)
green = int(green / 1.2 )
blue = int(blue / 1.2 )
newpalette.append((red, green, blue))
self.counter -= 1
self.surface.set_palette(newpalette)
print self.counter
if self.counter == 0:
raise FinishedException("finished work, delete me")
class TimeLine(object):
"""Controls Postprocessing Effects"""
def __init__(self, surface):
"""just __init__"""
self.surface = surface
self.effects = []
self.initialize()
def update(self):
try:
effect = self.effects[0]
try:
effect.run()
except FinishedException:
print "%s ended" % effect.__class__.__name__
del self.effects[0]
except IndexError:
print "No more effekts to do"
pass
def initialize(self):
"""generate list of effects"""
self.effects.append(FlashEffect(self.surface, beat=2, repeat=True, amount=5))
self.effects.append(FadeEffect(self.surface))
self.effects.append(SetPalette(self.surface, PALETTE))
self.effects.append(WormHole(self.surface, self, 255))
def ingame_loop(surface, game_engine, post_processor):
""" main ingame loop """
while True:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
sys.exit(0)
keyinput = pygame.key.get_pressed()
if keyinput is not None:
# print keyinput
if keyinput[pygame.K_ESCAPE]:
return("lost")
# sleep between every frame
CLOCK.tick(FPS)
# time.sleep( sleeptime__in_seconds )
# blank screen
# surface.fill(0)
# update everything
pygame.display.set_caption("frame rate: %.2f frames per second" % CLOCK.get_fps())
state = game_engine.update()
post_processor.update()
# state of engine could be
# running
# finished - player reached end of game
# lost - player lost game
if state != "running" :
return(state)
# update the screen to show the latest screen image
pygame.display.update()
def main():
"""just __main__"""
# this is where one sets how long the script
# sleeps for, between frames.sleeptime__in_seconds = 0.05
# initialise the display window
screen = pygame.display.set_mode(SCREEN, 0, 8)
global PALETTE
PALETTE = []
for index in xrange(255):
PALETTE.append((index, 0,0))
old_palette = screen.get_palette()
screen.set_palette(PALETTE)
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(BACKGROUND_MUSIC)
pygame.mixer.music.play(-1) # endless background music
while True:
# main logic of game
game_engine = GameEngine(screen, None)
post_processor = TimeLine(screen)
# start game loop
state = ingame_loop(screen, game_engine, post_processor)
# state could be
# finished - player finished level
# lost - player lost
# if player click, restart will be true
if state == "lost":
sys.exit(0)
elif state == "finished":
sys.exit(0)
if __name__ == "__main__" :
main()