Commit before breaking everything
[matches/honours.git] / research / transmission_spectroscopy / simulator / pgu-0.18 / examples / tilevid5.py
1 """<title>tutorial on how to add Sprite collision hit handlers, custom painting</title>"""
2
3 import pygame
4 from pygame.rect import Rect
5 from pygame.locals import *
6 import math
7 import random
8
9 # the following line is not needed if pgu is installed
10 import sys; sys.path.insert(0, "..")
11
12 from pgu import tilevid, timer
13
14 SW,SH = 320,240
15 TW,TH = 16,16
16 SPEED = 2
17 FPS = 40
18
19 def player_new(g,t,value):
20     g.clayer[t.ty][t.tx] = 0
21     s = tilevid.Sprite(g.images['player'],t.rect)
22     g.sprites.append(s)
23     s.loop = player_loop
24     s.groups = g.string2groups('player')
25     s.score = 0
26     g.player = s
27     ##In player_new() I add the shoot handler.
28     ##::
29     s.shoot = player_shoot
30     ##
31
32 def player_loop(g,s):
33     if s.rect.right < g.view.left: g.quit = 1
34     
35     s.rect.x += SPEED
36     
37     keys = pygame.key.get_pressed()
38     dx,dy = 0,0
39     if keys[K_UP]: dy-=1
40     if keys[K_DOWN]: dy+=1
41     if keys[K_LEFT]: dx-=1
42     if keys[K_RIGHT]: dx+=1
43     s.rect.x += dx*5
44     s.rect.y += dy*5
45     s.rect.clamp_ip(g.view)
46     
47     ##In player_loop(), I check for the spacebar.  The spacebar triggers a shot every 8 frames.
48     ##::
49     if keys[K_SPACE] and g.frame%8==0:
50         shot_new(g,s,None)
51     ##
52
53 ##The player_shoot() handler, as well as the shot Sprite functions.  The shot group
54 ##has its agroup set to 'enemy' so it can hit 'enemy' Sprites.
55 ##::
56 def player_shoot(g,s):
57     shot_new(g,s,None)
58     
59 def shot_new(g,t,value):
60     s = tilevid.Sprite(g.images['shot'],(t.rect.right,t.rect.centery-2))
61     g.sprites.append(s)
62     s.agroups = g.string2groups('enemy')
63     s.hit = shot_hit
64     s.loop = shot_loop
65
66 def shot_loop(g,s):
67     s.rect.x += 8
68     if s.rect.left > g.view.right:
69         g.sprites.remove(s)
70 ##    
71         
72 def shot_hit(g,s,a):
73     if a in g.sprites: g.sprites.remove(a)
74     g.player.score += 500
75
76         
77 def enemy_new(g,t,value):
78     g.clayer[t.ty][t.tx] = 0
79     s = tilevid.Sprite(g.images['enemy'],t.rect)
80     g.sprites.append(s)
81     s.loop = enemy_loop
82 ##In enemy_new(), I've added a lot more detail.
83 ##- A move function to handle the type of movement the enemy will do.
84 ##- A record of the origin and entering frame of the enemy (useful for the move functions.)
85 ##- Set up the groups and agroups and a hit handler for the enemy.
86 ##::
87     s.move = value['move']
88     s.origin = pygame.Rect(s.rect)
89     s.frame = g.frame
90     s.groups = g.string2groups('enemy')
91     s.agroups = g.string2groups('player')
92     s.hit = enemy_hit
93 ##
94
95 ##When an enemy is hit, the game quits.
96 ##::
97 def enemy_hit(g,s,a):
98     g.quit = 1
99 ##
100
101 def enemy_loop(g,s):
102     ##In enemy_loop() we call the move handler.
103     ##::
104     s.move(g,s)
105     ##
106     if s.rect.right < g.view.left:
107         g.sprites.remove(s)
108
109 ##The enemy movement handlers.
110 ##::
111 def enemy_move_line(g,s):
112     s.rect.x -= 3
113     
114 def enemy_move_sine(g,s):
115     s.rect.x -= 2
116     s.rect.y = s.origin.y + 65*math.sin((g.frame-s.frame)/10.0)
117     
118 def enemy_move_circle(g,s):
119     s.origin.x -= 1
120     s.rect.y = s.origin.y + 50*math.sin((g.frame-s.frame)/10.0)
121     s.rect.x = s.origin.x + 50*math.cos((g.frame-s.frame)/10.0)
122 ##
123         
124 def tile_block(g,t,a):
125     c = t.config
126     if (c['top'] == 1 and a._rect.bottom <= t._rect.top and a.rect.bottom > t.rect.top):
127         a.rect.bottom = t.rect.top
128     if (c['left'] == 1 and a._rect.right <= t._rect.left and a.rect.right > t.rect.left):
129         a.rect.right = t.rect.left
130     if (c['right'] == 1 and a._rect.left >= t._rect.right and a.rect.left < t.rect.right):
131         a.rect.left = t.rect.right
132     if (c['bottom'] == 1 and a._rect.top >= t._rect.bottom and a.rect.top < t.rect.bottom):
133         a.rect.top = t.rect.bottom
134
135 def tile_coin(g,t,a):
136     a.score += 100
137     g.set((t.tx,t.ty),0)
138     
139 def tile_fire(g,t,a):
140     g.quit = 1
141 ##
142
143 idata = [
144     ('player','player.tga',(4,4,24,24)),
145     ('enemy','enemy.tga',(4,4,24,24)),
146     ('shot','shot.tga',(1,2,6,4)),
147     ]
148
149 ##The codes data has been updated to include information about the appropriate
150 ##movement handlers for enemies.
151 ##::
152 cdata = {
153     1:(player_new,None),
154     2:(enemy_new,{'move':enemy_move_line}),
155     3:(enemy_new,{'move':enemy_move_sine}),
156     4:(enemy_new,{'move':enemy_move_circle}),
157     }
158 ##
159
160 tdata = {
161     0x01:('player',tile_block,{'top':1,'bottom':1,'left':1,'right':1}),
162     0x02:('player',tile_block,{'top':1,'bottom':1,'left':1,'right':1}),
163     0x20:('player',tile_coin,None),
164     0x30:('player',tile_fire,None),
165     }
166     
167 def init():
168     g = tilevid.Tilevid()
169     
170     ##In init(), set the g.view size so that all the handlers will work properly.  (The player_loop one depends on view having the correct size.)
171     ##::
172     g.view.w,g.view.h = SW,SH
173     ##
174     
175     g.screen = pygame.display.set_mode((SW,SH),SWSURFACE)
176     g.frame = 0
177     
178     g.tga_load_tiles('tiles.tga',(TW,TH),tdata)
179     ##In init() I no longer have tga_load_level load the background layer, as 
180     ##we will generate our own multi-layered starfield.
181     ##::
182     g.tga_load_level('level.tga')
183     ##
184     g.bounds = pygame.Rect(TW,TH,(len(g.tlayer[0])-2)*TW,(len(g.tlayer)-2)*TH)
185     g.load_images(idata)
186     g.run_codes(cdata,(0,0,25,17))
187     pygame.font.init()
188     g.font = pygame.font.SysFont('helvetica',16)
189
190     return g
191     
192 def run(g): 
193     g.quit = 0
194     ##In run(), adding a pause variable to the game.
195     ##::
196     g.pause = 0
197     ##
198     
199     t = timer.Timer(FPS)
200
201     ##In run(), initializing the stars.
202     ##::
203     stars = []
204     NS = 256
205     for n in range(0,NS):
206         stars.append([random.randrange(0,SW),random.randrange(0,SH),random.randrange(2,8)])
207     ##
208     
209     while not g.quit:
210         for e in pygame.event.get():
211             if e.type is QUIT: g.quit = 1
212             if e.type is KEYDOWN and e.key == K_ESCAPE: g.quit = 1
213             ##In run(), in the event loop, checking for F10 for full screen, RETURN for pause.
214             ##::
215             if e.type is KEYDOWN and e.key == K_F10:
216                 #g.screen = pygame.display.set_mode((SW,SH),FULLSCREEN|HWSURFACE|DOUBLEBUF)
217                 pygame.display.toggle_fullscreen()
218                 
219             if e.type is KEYDOWN and e.key == K_RETURN:
220                 g.pause ^= 1
221             ##
222
223         ##In run(), handles pause, and also renders the star field before the
224         ##foreground is painted.
225         ##::
226         if not g.pause:
227             g.view.x += SPEED
228             g.run_codes(cdata,(g.view.right/TW,0,1,17))
229             
230             g.loop()
231     
232             g.screen.fill((0,0,0))
233             n = 0
234             for n in range(0,NS):
235                 x,y,s = stars[n]
236                 if ((g.frame*s)%8) < s:
237                     x -= 1
238                 if x < 0: x += SW
239                 stars[n][0] = x
240                 g.screen.set_at((x,y),(255,255,255))
241
242             g.paint(g.screen)
243             img = g.font.render('%05d'%g.player.score,1,(0,0,0))
244             g.screen.blit(img,(0+1,SH-img.get_height()+1))
245             img = g.font.render('%05d'%g.player.score,1,(255,255,255))
246             g.screen.blit(img,(0,SH-img.get_height()))
247             pygame.display.flip()
248             
249             g.frame += 1
250         ##
251
252         t.tick()
253         
254     
255 run(init())

UCC git Repository :: git.ucc.asn.au