pygame-KidsCanCode系列jumpy-part16-enemy敌人
接上回继续,这次我们要给游戏加点难度,增加几个随机出现的敌人,玩家碰到敌人后Game Over。
最终效果如下,头上顶个"电风扇"的家伙,就是敌人。
一、先定义敌人类
1 # 敌人类 2 class Mob(pg.sprite.Sprite): 3 def __init__(self, game): 4 pg.sprite.Sprite.__init__(self) 5 self.game = game 6 self.current_frame = 0 7 self.last_update = 0 8 self.image_up = self.game.spritesheet.get_image("flyMan_fly.png") 9 self.image_down = self.game.spritesheet.get_image("flyMan_jump.png") 10 self.image = self.image_up 11 self.rect = self.image.get_rect() 12 self.rect.centerx = random.choice([-100, WIDTH + 100]) 13 self.vx = random.randrange(1, 4) 14 if self.rect.centerx > WIDTH: 15 self.vx *= -1 16 self.rect.y = random.randrange(HEIGHT / 2) 17 self.vy = 0 18 self.dy = 0.5 19 20 def update(self): 21 self.rect.x += self.vx 22 self.vy += self.dy 23 # 敌人上下移动 24 if abs(self.vy) > 3: 25 self.dy *= -1 26 center = self.rect.center 27 if self.dy < 0: 28 self.image = self.image_up 29 else: 30 self.image = self.image_down 31 self.rect = self.image.get_rect() 32 self.rect.center = center 33 self.rect.y += self.vy 34 # 超出边界自动清除资源 35 if self.rect.left > WIDTH + 100 or self.rect.right < -100: 36 self.kill()
代码并不复杂,要注意的地方,已经加了注释,注意下坐标的初始化处理。在[-100,100]的x坐标,[0,HEIGHT/2]的y坐标范围内,随机选1个位置,让敌人出现,然后为了有上下振动的的效果,update中对y轴速度有一个偏移量dy的处理。
二、然后调整main.py
update函数中每隔一定时间,加入敌人
1 def update(self): 2 self.all_sprites.update() 3 4 # 每隔一定时间,随机加入敌人 5 now = pg.time.get_ticks() 6 if now - self.mob_timer > MOB_FREQ + random.choice([-1000, -500, 0, 500, 1000]): 7 self.mob_timer = now 8 mob = Mob(self) 9 # 指定分层 10 self.all_sprites.add(mob, layer=MOB_LAYER) 11 self.mobs.add(mob) 12 13 # 与敌人的碰撞检测 14 mob_hits = pg.sprite.spritecollide(self.player, self.mobs, False) 15 if mob_hits: 16 self.playing = False 17 18 ... 19 20 if self.player.rect.top < HEIGHT / 4: 21 self.player.pos.y += max(abs(self.player.vel.y), 2) 22 # 屏幕滚动时,敌人也要相应的滚动 23 for mob in self.mobs: 24 mob.rect.top += max(abs(self.player.vel.y), 2) 25 if mob.rect.top > HEIGHT: 26 mob.kill() 27 ...
这里有几个小技巧:
2.1 敌人出现的频度,可以调整MOB_FREQ 这个常量,它在settings.py中定义
# enemy MOB_FREQ = 8000
表示每8秒左右出现一个敌人,然后为了更具随机性,if条件中还加入了random.choice([-1000, -500, 0, 500, 1000]),所以最终敌人出现的时间间隔,实际是 7.0s、7.5s、8.0s、8.5s、9s 中某一个。
2.2 兔子向上跳,所有档板向下滚动时,敌人也要同步向下滚动,不然画面会不太自然(有兴趣的可以把这一段去掉试试)
2.3 为了防止敌人,被档板、加速器之类的给遮挡住,这里我们使用了pygame中的分层概念。其实就是类似ps中的图层概念,层越高的对象,就越在最上面。即:层"低"的对象,会被层"高"的对象遮挡掉。
为了使用分层,all_sprites必须换成LayeredUpdates,参考以下代码:
1 def new(self): 2 self.score = 0 3 # 这里换成LayeredUpdates为了体现"分层"效果 4 self.all_sprites = pg.sprite.LayeredUpdates() 5 self.platforms = pg.sprite.Group() 6 self.powerups = pg.sprite.Group() 7 # 敌人的分组 8 self.mobs = pg.sprite.Group() 9 self.player = Player(self) 10 # 指定分层 11 self.all_sprites.add(self.player, layer=PLAYER_LAYER) 12 self.mob_timer = 0
这些分层值,同样可以定义在settings.py中
1 # layer 2 PLAYER_LAYER = 4 3 MOB_LAYER = 3 4 PLATFORM_LAYER = 1 5 POWERUP_LAYER = 2
细心的朋友可能发现一个问题:兔子与敌人的碰撞检测貌似有点怪,明明还差着一些距离,就认为碰上了。这个问题,下节我们再来讨论改进办法。
源码参考:https://github.com/yjmyzz/kids-can-code/tree/master/part_16
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。