python游戏引擎ppb介绍(5)爆炸:精灵的碰撞与删除

本文介绍了一个简单的游戏场景中,如何实现导弹与目标之间的碰撞检测及碰撞后的处理逻辑,包括目标消失、导弹销毁和添加爆炸效果等。

导弹击中靶子,这里涉及到精灵的碰撞检测;之后,靶子和这枚导弹都应当消失,这是精灵的删除。另外,我们希望看到一个靶子爆炸的效果。爆炸效果是另外一个动画精灵,它在自己的动画完成后自动删除。

http://p1-tt-ipv6.byteimg.com/large/pgc-image/7ed3093a49794a6cbf6c4aba67f7f502

碰撞逻辑与之后的动作

碰撞检测的逻辑放在靶子中:

  1. 从场景中找到所有导弹对象
  2. 判断导弹对象与自己的距离(图片中点距离)
  3. 如果距离小于自己尺寸的1/2,则说明碰撞了

检测到碰撞后做三件事:

  1. 删除自己
  2. 删除导弹
  3. 在自己原来的位置上放一个爆炸精灵
class Target(ppb.Sprite):

    image = ppb.Image("resources/Target.png")

    speed= 50

    layer= 1

    def on_update(self, event, signal):

       self.rotation-=self.speed* event.time_delta

       for p in event.scene.get(kind=Projectile):

           if (p.position - self.position).length <= self.size/ 2:

               event.scene.add(BombImg(position=self.position))

               event.scene.remove(self)

               event.scene.remove(p)

 

因为导弹的碰撞是随时有可能发生的,所以这个逻辑就放在on_update事件中。

枚举所有导弹对象:

for p in event.scene.get(kind=Projectile)

 

距离计算:

if (p.position - self.position).length <= self.size/ 2:

 

这里又使用了简洁的向量计算,位置的差代表距离向量,它的length即模长,代表距离的绝对值。

由于导弹的攻击点就在图片的中间,靶子又是圆形的(size/2正好是半径),所以两个位置之间的距离可以完美表明碰撞。如果是图片是更加复杂的形状,这个碰撞逻辑就显得粗糙了。如果想做得漂亮,就得使用专门物理引擎。

删除精灵:

event.scene.remove(self)

event.scene.remove(p)

 

爆炸精灵

爆炸精灵是一个动画精灵,它的图片有16张:

http://p9-tt-ipv6.byteimg.com/large/pgc-image/408f2bfc71724853a6a5714a84e667f1

http://p1-tt-ipv6.byteimg.com/large/pgc-image/f5030600e2a545d69d550c1ddf4449d2

http://p26-tt.byteimg.com/large/pgc-image/f77df31ec53d45548fecaf295bcbd4d3

http://p3-tt-ipv6.byteimg.com/large/pgc-image/6fdb44bea5104703bada945cb08cb234

http://p6-tt-ipv6.byteimg.com/large/pgc-image/e92ce970eba54c3099d71f46c29ca01b

http://p9-tt-ipv6.byteimg.com/large/pgc-image/be00340046d14304b3647c0be52e8b36

http://p6-tt-ipv6.byteimg.com/large/pgc-image/fe3c966e2f2d468681ebb659e7075ec5

http://p6-tt-ipv6.byteimg.com/large/pgc-image/1c18dfceff244f1f9c9ac3babc90d40a

http://p6-tt-ipv6.byteimg.com/large/pgc-image/9fc35ec5d21d4b2caa4493efde2916b8

http://p3-tt-ipv6.byteimg.com/large/pgc-image/7fae23cbbbdb4c19a0e7a03a585f145d

http://p9-tt-ipv6.byteimg.com/large/pgc-image/24d7d3517f6849b59657c715b74863b2

http://p1-tt-ipv6.byteimg.com/large/pgc-image/fc2027fb8a4d46de9b73db5919341f78

http://p1-tt-ipv6.byteimg.com/large/pgc-image/f2a7f5d599374e65aee35138455961ad

http://p6-tt-ipv6.byteimg.com/large/pgc-image/58436bfdd08a447e838ecc6efac58d29

http://p6-tt-ipv6.byteimg.com/large/pgc-image/ecf7b4f9115844a8b330fff5ea1396ae

http://p9-tt-ipv6.byteimg.com/large/pgc-image/507f2b8428204f35ab378f5654835697

当我们采用指定图片的时候,精灵的类名与图片的命名就无须一致。

精灵类代码如下:

class BombImg(ppb.Sprite):

    layer= 1

    image = Animation("resources/bomb_{0..15}.png", 16)

    def on_update(self, update_event, signal):

        if self.image.current_frame==15:

            update_event.scene.remove(self)

 

这里设置动态的时候,帧数设置为16,意思是希望整个爆炸过程在1秒中完成。

self.image.current_frame标志着当前动画精灵所显示的帧号。我们希望显示一次爆炸后,精灵本身就消失,所以当它的帧号等于15时,我们就删除它。

http://p9-tt-ipv6.byteimg.com/large/dfic-imagehandler/fa6cfa99-60d9-4ae0-b04e-18fad3f5c454

完整代码

现在的运行效果,看起来已经差不多了,下节课我们将加入声音和文字,让游戏的观感更完整。

目前为止的代码如下:

import ppb

from ppb.features.animation import Animation





class Blob(ppb.Sprite):

    image = Animation("resources/blob_{0..6}.png", 10)

    layer= 3



    def on_button_pressed(self, event, signal):

        if event.button== ppb.buttons.Primary:

           p1= (event.position- self.position).normalize()

           event.scene.add(Projectile(position=self.position, direction= p1))



    def on_mouse_motion(self, event, signal):

        p1= (event.position- self.position).normalize()

        self.rotation= 270-p1.angle(ppb.Vector(1,0))



class Target(ppb.Sprite):

    image = ppb.Image("resources/Target.png")

    speed= 50

    layer= 1

    def on_update(self, update_event, signal):

       self.rotation-=self.speed* update_event.time_delta

       for p in update_event.scene.get(kind=Projectile):

           if (p.position - self.position).length <= self.size/ 2:

               update_event.scene.add(BombImg(position=self.position))

               update_event.scene.remove(self)

               update_event.scene.remove(p)

               break



class BombImg(ppb.Sprite):

    layer= 1

    image = Animation("resources/bomb_{0..15}.png", 16)

    def on_update(self, update_event, signal):

        if self.image.current_frame==15:

            update_event.scene.remove(self)



class Projectile(ppb.Sprite):

    image = ppb.Image("resources/Projectile.png")

    speed = 6

    layer= 2



    def on_update(self, update_event, signal):

       self._rotation= 90- self.direction.angle(ppb.Vector(1,0))

       self.position += self.direction * self.speed * update_event.time_delta





def setup(scene):

    scene.add(Blob(pos=(0, -3.5)))

    for x in range(-4, 5, 2):

       scene.add(Target(position=ppb.Vector(x, 3)))





ppb.run(setup=setup,resolution=(800, 600))

 

http://p6-tt-ipv6.byteimg.com/large/dfic-imagehandler/0b67399b-74a6-4714-ae23-e101064cbc33

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

圣手书生肖让

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值