zoukankan      html  css  js  c++  java
  • 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()
    View Code

    代码并不复杂,要注意的地方,已经加了注释,注意下坐标的初始化处理。在[-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            ...
    View Code

    这里有几个小技巧:

    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
    View Code

    这些分层值,同样可以定义在settings.py中

    1 # layer
    2 PLAYER_LAYER = 4
    3 MOB_LAYER = 3
    4 PLATFORM_LAYER = 1
    5 POWERUP_LAYER = 2
    View Code

    细心的朋友可能发现一个问题:兔子与敌人的碰撞检测貌似有点怪,明明还差着一些距离,就认为碰上了。这个问题,下节我们再来讨论改进办法。

    源码参考:https://github.com/yjmyzz/kids-can-code/tree/master/part_16

  • 相关阅读:
    二分+RMQ/双端队列/尺取法 HDOJ 5289 Assignment
    思维题 HDOJ 5288 OO’s Sequence
    树形DP Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland
    最大流增广路(KM算法) HDOJ 1853 Cyclic Tour
    最大流增广路(KM算法) HDOJ 1533 Going Home
    最大流增广路(KM算法) HDOJ 2255 奔小康赚大钱
    Complete the Word CodeForces
    Gadgets for dollars and pounds CodeForces
    Vasya and Basketball CodeForces
    Carries SCU
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/pygame-kidscancode-part16-enemy.html
Copyright © 2011-2022 走看看