In player_new() I add the shoot handler.
28: s.shoot = player_shoot
In player_loop(), I check for the spacebar. The spacebar triggers a shot every 8 frames.
48: if keys[K_SPACE] and g.frame%8==0:
49: shot_new(g,s,None)
The player_shoot() handler, as well as the shot Sprite functions. The shot group
has its agroup set to 'enemy' so it can hit 'enemy' Sprites.
55:def player_shoot(g,s):
56: shot_new(g,s,None)
57:
58:def shot_new(g,t,value):
59: s = tilevid.Sprite(g.images['shot'],(t.rect.right,t.rect.centery-2))
60: g.sprites.append(s)
61: s.agroups = g.string2groups('enemy')
62: s.hit = shot_hit
63: s.loop = shot_loop
64:
65:def shot_loop(g,s):
66: s.rect.x += 8
67: if s.rect.left > g.view.right:
68: g.sprites.remove(s)
In enemy_new(), I've added a lot more detail.
- A move function to handle the type of movement the enemy will do.
- A record of the origin and entering frame of the enemy (useful for the move functions.)
- Set up the groups and agroups and a hit handler for the enemy.
86: s.move = value['move']
87: s.origin = pygame.Rect(s.rect)
88: s.frame = g.frame
89: s.groups = g.string2groups('enemy')
90: s.agroups = g.string2groups('player')
91: s.hit = enemy_hit
When an enemy is hit, the game quits.
96:def enemy_hit(g,s,a):
97: g.quit = 1
In enemy_loop() we call the move handler.
103: s.move(g,s)
The enemy movement handlers.
110:def enemy_move_line(g,s):
111: s.rect.x -= 3
112:
113:def enemy_move_sine(g,s):
114: s.rect.x -= 2
115: s.rect.y = s.origin.y + 65*math.sin((g.frame-s.frame)/10.0)
116:
117:def enemy_move_circle(g,s):
118: s.origin.x -= 1
119: s.rect.y = s.origin.y + 50*math.sin((g.frame-s.frame)/10.0)
120: s.rect.x = s.origin.x + 50*math.cos((g.frame-s.frame)/10.0)
The codes data has been updated to include information about the appropriate
movement handlers for enemies.
151:cdata = {
152: 1:(player_new,None),
153: 2:(enemy_new,{'move':enemy_move_line}),
154: 3:(enemy_new,{'move':enemy_move_sine}),
155: 4:(enemy_new,{'move':enemy_move_circle}),
156: }
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: g.view.w,g.view.h = SW,SH
In init() I no longer have tga_load_level load the background layer, as
we will generate our own multi-layered starfield.
181: g.tga_load_level('level.tga')
In run(), adding a pause variable to the game.
195: g.pause = 0
In run(), initializing the stars.
202: stars = []
203: NS = 256
204: for n in range(0,NS):
205: stars.append([random.randrange(0,SW),random.randrange(0,SH),random.randrange(2,8)])
In run(), in the event loop, checking for F10 for full screen, RETURN for pause.
214: if e.type is KEYDOWN and e.key == K_F10:
215: #g.screen = pygame.display.set_mode((SW,SH),FULLSCREEN|HWSURFACE|DOUBLEBUF)
216: pygame.display.toggle_fullscreen()
217:
218: if e.type is KEYDOWN and e.key == K_RETURN:
219: g.pause ^= 1
In run(), handles pause, and also renders the star field before the
foreground is painted.
225: if not g.pause:
226: g.view.x += SPEED
227: g.run_codes(cdata,(g.view.right/TW,0,1,17))
228:
229: g.loop()
230:
231: g.screen.fill((0,0,0))
232: n = 0
233: for n in range(0,NS):
234: x,y,s = stars[n]
235: if ((g.frame*s)%8) < s:
236: x -= 1
237: if x < 0: x += SW
238: stars[n][0] = x
239: g.screen.set_at((x,y),(255,255,255))
240:
241: g.paint(g.screen)
242: img = g.font.render('%05d'%g.player.score,1,(0,0,0))
243: g.screen.blit(img,(0+1,SH-img.get_height()+1))
244: img = g.font.render('%05d'%g.player.score,1,(255,255,255))
245: g.screen.blit(img,(0,SH-img.get_height()))
246: pygame.display.flip()
247:
248: g.frame += 1