用PPB打飞机游戏:挑战爆表的速度与刺激!

发布时间:2024-07-29 09:30:15 浏览量:121次

打出子弹就是制造一个源源不断移动的新精灵。

今天我们来说说怎么创建精灵以及它们的自动平移,还有层这个概念,同时开始使用资源路径。

发射子弹

原来Projectile是导弹的意思。那我们建立了第三个精灵类:Projectile。

Projectile.png

它的图片看起来比较抽象。

与前两个精灵一样,我们只需要建立一个同名类就可以默认关联这个图片,但这次我们想直接指定图片。因为我们不想所有的图片都和源代码放在一起。我们在代码目录中新建一个子目录resources,并把所有图片都搬到这个目录下。这样我们就必须显式地指定精灵的图片,不过很简单,就像下面这样:

class Projectile(ppb.Sprite):    image = ppb.Image("resources/Projectile.png")    speed = 6    layer= 2    def on_update(self, event, signal):        self.position += self.direction * self.speed * event.time_delta

这里的speed=6代表导弹的飞行速度,每秒飞行6个距离单位,考虑到屏幕横宽为25个距离单位,这个速度已经相当快了。

观察导弹的on_update函数,根据速度(speed)和方向(direction)改变导弹的位置。依然使用向量计算,让代码清晰简洁。

这里的方向(direction)不是精灵的内置属性(相关的内置属性是rotation)。它和speed一样,是一个额外属性。direction属性没有初始值,会在发射时指定并保持不变。

导弹类中还定义了一个新参数:层号(layer)。精灵重叠时,层号大的会覆盖层号小的。我们可以简单理解为每个精灵按照层号从小到大排序显示,层号小的先显示;层号大的后显示,位于上方。

点击鼠标

我们希望当鼠标左键点击时,发射一枚导弹。只需给Blob类新增一个响应鼠标按下的事件:

class Blob(ppb.Sprite):    image = Animation("resources/blob_{0..6}.png", 10)    layer= 3    def on_mouse_motion(self, event, signal):        p1= (event.position- self.position).normalize()        self.rotation= 270 - p1.angle(ppb.Vector(1,0))    # 新增函数    def on_button_pressed(self, event, signal):        if event.button== ppb.buttons.Primary:            p1= (event.position- self.position).normalize()            p2= 90- p1.angle(ppb.Vector(1,0))            event.scene.add(Projectile(position=self.position, direction= p1, rotation=p2))

on_button_pressed事件处理鼠标按下事件。更精细的交互处理可能还会涉及鼠标抬起事件——按下和抬起才算是一次点击。但在这里,按下鼠标就发射导弹,操作逻辑清晰,没有影响。

鼠标按下事件event中包含按下按钮的信息,保存在event.button中,有三种可能性:

  • 主键(默认为左键)
  • 辅键(默认为右键)
  • 中间键

分别对应不同的鼠标键。这个设置具有很强大的扩展性,适应机器上不同设置的需要。

以下计算又是向量计算,分别计算出导弹的旋转角度(rotation)和前进方向(direction)。

在这种情况下,direction进行归一化处理是必要的,因为在导弹的代码中,我们用它和速度的乘积来计算新位置,如果模不是1,会影响速度的真实值。

观察导弹图片,它的方向是向下的,所以它的值和导弹图片的前进方向有一个固定的差距。

event中还包括一个重要信息,即场景本身。借此参数,可以在场景中新增一个导弹精灵,跟在setup函数中那样。

场景布局与层号作用

def setup(scene):    scene.add(Blob(pos=(0, -3.5)))    for x in range(-4, 5, 2):       scene.add(Target(layer=(x+4)/2,position=ppb.Vector(x, 3)))

布置屏幕时,给每个靶子设置不同的层号。比如上面代码的5个靶子,从左到右分别是0,1,2,3,4。导弹永远在左边两个靶子上面,在右边两个下面,但在中间那个层号相同的靶子上则随机,有时上有时下!

所以,为了在两个精灵交叠时有明确表现,最好设定特定的层号。


完整代码

下次上课,我们来实现导弹击中靶子后的效果。现在,先看一下目前的完整源代码。

因为我们把图片放在了子目录下,所以每个类都做了相应的修改。

import ppbfrom ppb.features.animation import Animationclass 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()            p2= 90- p1.angle(ppb.Vector(1,0))            event.scene.add(Projectile(position=self.position, direction= p1, rotation=p2))    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    def on_update(self, update_event, signal):       self.rotation-=self.speed* update_event.time_deltaclass Projectile(ppb.Sprite):    size = 1    image = ppb.Image("resources/Projectile.png")    speed = 6    layer= 2    def on_update(self, event, signal):       self.position += self.direction * self.speed * event.time_deltadef setup(scene):    scene.add(Blob(pos=(0, -3.5)))    for x in range(-4, 5, 2):       scene.add(Target(layer=(x+4)/2,position=ppb.Vector(x, 3)))ppb.run(setup=setup,resolution=(800, 600))


想要了解更多关于游戏设计、动画制作等专业知识,欢迎点击咨询火星时代教育。

热门课程推荐

热门资讯

请绑定手机号

x

同学您好!

您已成功报名0元试学活动,老师会在第一时间与您取得联系,请保持电话畅通!
确定