Quick-Cocos2d-x初学者游戏教程(十) ---------------- 添加游戏障碍物

Quick-Cocos2d-x初学者游戏教程(十)

在我们的游戏中,我们除了添加奖励品外,还需要添加一些必要的障碍物来丰富游戏逻辑,增加游戏难度,所以本章我们将继续上章的内容——添加游戏障碍物。游戏中,障碍物是不止一种,这里有飞行的鸟,有上下移动的飞艇。

创建障碍物-飞艇

其实创建飞艇的逻辑和前面创建心心的逻辑是一样的,只不过这里我想让飞艇不停的上下移动,一方面做点带感的效果出来,另一方面也可以增加游戏难度。

看过之前教程的童鞋,现在应该懂得怎样创建这样的一个飞艇了吧。所以下面我们直接给出它的定义:

local Airship = class("Airship", function()
    return display.newSprite("#airship.png")
end)

local MATERIAL_DEFAULT = cc.PhysicsMaterial(0.0, 0.0, 0.0) 

function Airship:ctor(x, y)

    local airshipSize = self:getContentSize() -- 得到Airship自身的尺寸大小

    local airshipBody = cc.PhysicsBody:createCircle(airshipSize.width / 2,
        MATERIAL_DEFAULT)

    self:setPhysicsBody(airshipBody)
    self:getPhysicsBody():setGravityEnable(false)    

    self:setPosition(x, y)

    local move1 = cc.MoveBy:create(3, cc.p(0, airshipSize.height / 2))
    local move2 = cc.MoveBy:create(3, cc.p(0, -airshipSize.height / 2))
    local SequenceAction = cc.Sequence:create( move1, move2 )
    transition.execute(self, cc.RepeatForever:create( SequenceAction ))
end

return Airship

再强调一点的是:这里我们在创建刚体时把它的密度,反弹力、摩擦力都设为0是为了在碰撞的时候不发生任何物理形变。

密度是用来计算物体质量的,它可以是等于零或大于零的正数。摩擦力经常会设置在0.0到1.0之间,0.0表示没有摩擦力,1.0会产生强摩擦。弹性系数的值通常设置到0.0到1.0之间,0.0表示物体不会弹起,1.0表示物体会完全反弹,即称为弹性碰撞。

创建障碍物-鸟

这里我们要创建一个飞行的小鸟。创建它与创建心心唯一不同的是:它是一个动态的游戏对象。下面是 Bird 的定义:

local Bird = class("Bird", function()
    return display.newSprite("#bird1.png")
end)

local MATERIAL_DEFAULT = cc.PhysicsMaterial(0.0, 0.0, 0.0)

function Bird:ctor(x, y)

    local birdBody = cc.PhysicsBody:createCircle(self:getContentSize().width / 2,
        MATERIAL_DEFAULT)

    self:setPhysicsBody(birdBody)
    self:getPhysicsBody():setGravityEnable(false)    

    self:setPosition(x, y)

    local frames = display.newFrames("bird%d.png", 1, 9)
    local animation = display.newAnimation(frames, 0.5 / 9)
    animation:setDelayPerUnit(0.1)
    local animate = cc.Animate:create(animation)

    self:runAction(cc.RepeatForever:create(animate))
end
return Bird

封装加载函数

现在我们已经创建了心心、飞艇,还有鸟。虽然种类不多,但我已经不想再创建其他的了,反正原理都差不多,所以还是给大家留个自由发挥和创作的机会吧。

创建好游戏对象后,我们接下来要做的就是把它们都加载到场景中。这一过程你可以效仿上一章加载心心的方法来加载另外的两种游戏对象。不过如果你的要求更高,那你一定会想把这些函数封装一下,就如下列代码所示:

function BackgroundLayer:addBody(objectGroupName, class)
    local objects = self.map:getObjectGroup(objectGroupName):getObjects()
    local  dict    = nil
    local  i       = 0
    local  len     = table.getn(objects)

    for i = 0, len-1, 1 do
        dict = objects[i + 1]

        if dict == nil then
            break
        end

        local key = "x"
        local x = dict["x"]
        key = "y"
        local y = dict["y"]

        local sprite = class.new(x, y)
        self.map:addChild(sprite)
    end
end

addBody函数抽象出对象组的名字和类类型作为参数,这样我们就可以通过它来加载各种不同的游戏对象了。

    self:addBody("heart", Heart)
    self:addBody("airship", Airship)
    self:addBody("bird", Bird)

加载这些对象时,不要忘了在 BackgroundLayer 文件中载入相应的文件:

    local Heart = require("app.objects.Heart")
    local Airship = require("app.objects.Airship")
    local Bird = require("app.objects.Bird")

此时运行游戏,你就可以在场景中看见各种不同的游戏对象了。

给鸟添加飞行效果

目前这些障碍物和奖励品都只是随着背景滚动,显得游戏了无生趣,所以接下来我们来给鸟添加一个动态的飞行效果,让玩家可以明显的感受到它是朝前飞的。

那下面我们就来看看怎样实现吧。

1、首先,我们先给 BackgroundLayer 定义一个table数组来存放游戏中所有的鸟,即在ctor方法中加入如下的变量:

    self.bird = {}

2、然后,在创建鸟这个游戏对象时,我们需要把所有的鸟都添加到定义的 self.bird 数组中。所以在 addBody 方法中,我们需要加上一则判断:

    local sprite = class.new(x, y)
    self.map:addChild(sprite)

    if objectGroupName == "bird" then
        table.insert(self.bird, sprite)
    end

即当创建的对象是鸟(bird)时,就把该对象插入 self.bird。

3、接着,我们在 BackgroundLayer 中添加如下的一个函数:

function BackgroundLayer:addVelocityToBird()
    local  dict    = nil
    local  i       = 0
    local  len     = table.getn(self.bird)

    for i = 0, len-1, 1 do
        dict = self.bird[i + 1]
        if dict == nil  then
            break
        end

        local x = dict:getPositionX()
        if x <= display.width  - self.map:getPositionX() then
            if dict:getPhysicsBody():getVelocity().x == 0 then
                dict:getPhysicsBody():setVelocity(cc.p(-70, math.random(-40, 40)))
            else
                table.remove(self.bird, i + 1)
            end
        end
    end
end

在该函数中,我们遍历 self.bird 数组中的所有 Bird 对象,当检测到某个 Bird 对象刚好要进入屏幕,且还没给过它任何速度时,我们会给它一个向左的速度,这个速度的范围从(-70, -40)到(-70, 40)。通俗一点就是说: Bird 对象将在横坐标上有一个大小为70,方向向左的速度;在纵坐标上有一个大小在(-40, 40)之间,方向不定的速度。

其中math.random(-40, 40)可以产生-40到40的随机数。为了不产生相同的随机数,我们需要在MyApp:run()中“种”一棵随机数种子,即添加如下的一行代码:

    math.randomseed(os.time())

当已经给过某些 Bird 对象速度时,我们要把该对象从 self.bird 数组中移除,这样可以减短遍历数组的时间。table.remove(table, pos)函数将删除并返回 table 数组中位于 pos 位置上的元素。

总的来讲,addVelocityToBird 函数的目的就是在小鸟进入屏幕时给它一个速度,让它朝着游戏角色冲过来。

4、最后,因为我们需要不停的遍历 self.bird 数组、不停的检测是否给小鸟加上速度,所以我们需要在刷新屏幕时调用以上的 addVelocityToBird() 函数。

那就偷个懒,直接在 scrollBackgrounds(dt) 函数的最后面添加下列函数:

    self:addVelocityToBird()

现在注释掉GameScene:ctor()方法中的self.world:setDebugDrawMask(cc.PhysicsWorld.DEBUGDRAW_ALL)和添加Player的代码,那我们可以得到如下的一个游戏效果:

补充

因为游戏中的Player、Heart、Airship、Bird都是刚体,所以现在把这些刚体放在同一个物理世界是很容易发生碰撞、反弹、旋转、被挤出场景等等问题的。所以,这里我们要补充的就是怎样有效的解决这些问题,当然,制定具体的解决方案还需要结合碰撞检测来做,这个我们下章会讲。

setDynamic(dynamic):如果你想你的刚体固定不动,那么你可以调用该函数。如游戏中的心心,它在物理世界中就是个相对固定不动的对象,所以我们可以设置它的刚体属性dynamic为false,即 body:setDynamic(false) 。

setRotationEnable(enable):如果你想你的刚体不旋转,那么你可以调用该函数。如 Player、Airship 和 Bird 对象,它们在物理世界中是 Dynamic(动态)的,但我们不希望它们在动的过程中重心不稳发生旋转,所以,我们可以给 Player 刚体添加这样的属性加以约束,即:body:setRotationEnable(false)。

好了,今天就说到这里吧,这两章说的有点啰嗦,下章我们会加快进度,给大家讲讲如何给游戏添加触摸事件,并编写碰撞检测的逻辑。

关于源代码,下一两周内我会整理了会放出来。各位稍安勿躁,( ̄艸 ̄”)!

转载请注明出自:http://shannn.com/archives/431

时间: 2024-10-23 01:51:17

Quick-Cocos2d-x初学者游戏教程(十) ---------------- 添加游戏障碍物的相关文章

Quick-Cocos2d-x初学者游戏教程(二) -------------------- Quick内部的代码结构及相应的原理

Quick-Cocos2d-x初学者游戏教程(二) 上一章我们已经了解了Quick的一些基础知识,所以本章我们将开始深入到Quick内部,了解它内部的代码结构,同时在解析的过程中学到相应的原理,并学会如何修改.添加相应的代码文件,比如实现屏幕的分辨率适配. 前面我们创建了一个叫做parkour的游戏项目,其意思就是本人本来打算要做一个跑酷游戏的,但是因为这几天玩了一款叫做<el>的飞行游戏,非常有意境,并且几乎零差评,所以请允许我任性一下,善变的我不想做跑酷游戏了,而是想要挑战下这种类型的游戏

Quick-Cocos2d-x初学者游戏教程(三) ---------------------------- 解析quick新建项目的代码文件

Quick-Cocos2d-x初学者游戏教程(三) 2.main.lua 在src目录下,除了 config.lua 文件外,还有一个 main.lua 文件,这个 main.lua 是 Quick 项目的通用入口文件,它类似于 Cocos2d-x 中的 AppDelegate.h/cpp 文件,同时也类似于一般 Windows 工程中的 main 文件. 打开 main.lua 文件,其内容如下所示: 1 2 3 4 5 6 7 8 9 10 function __G__TRACKBACK__

Quick-Cocos2d-x初学者游戏教程(四) --------------- 开发初探(添加背景,标题,动作,按钮)

Quick-Cocos2d-x初学者游戏教程(四) 前面我们已经大概的讲解完了Quick的框架和代码结构,接下来,本章开始我们将正式进入到游戏的开发.当然在开发的过程中,如果遇到值得一提的知识点和概念,我们还是会为大家详细讲解的. 哈哈,这章的内容我加它为——开发初探,因为我们将先来实现一些基础的内容.本章将实现的效果如下图所示: 菜单场景 从前面章节讲解的的知识点中,我们知道每个新建的 Quick 项目里都已经默认创建好了一个 mainScene 场景,所以下面我们将利用这个现成的场景,把它改

Quick-Cocos2d-x初学者游戏教程(一)--------------------Quick的一些基础知识

本文转自Quick-Cocos2d-x初学者游戏教程(一) 前言 虽然之前已经写过了很多 Cocos2d-x 相关的教程和文档,但本次却是我第一次接触 Quick,第一次接触 Lua,所以此次的教程本人将站在一个初学者的角度(看到这里是不是想白眼我了,哈哈,别切啊!尽管第一次,但我身边可是有很多 Quick 大神的,廖大大也在旁边办公室,没准撒个娇大神就把他知道的全部要点倾囊相授了啦!),全方位的解析 Quick 的学习过程,并同大家一起学习如何利用 Quick-Cocos2d-x 开发一款属于

Quick-Cocos2d-x初学者游戏教程(十三) ---------- 完善游戏功能

Quick-Cocos2d-x初学者游戏教程(十三) 本章将是本教程的最后一章,在这章我们将完善游戏功能,即给游戏添加粒子特效,音乐音效,和玩家的受伤动画等等. 添加受伤动画 首先,我们来添加玩家受伤动画. 玩家受伤动画是 Player 与障碍物或地面碰撞的时候播放的一个动画效果,它是一个独立的帧动画,帧序列图片如下: PS:该动画添加到玩家上是非常丑的,所以如果各位有更好地资源可以不用它.我的美术御用妹子前两周出车祸把手伤了,没人给我画,所以才迫不得已找了这个丑图来替代,看不下去的见谅! 我们

Quick-Cocos2d-x初学者游戏教程(六) --------------------- 游戏逻辑

Quick-Cocos2d-x初学者游戏教程(六) 上一章我 们介绍了开发中会用到的辅助工具,并创建了 GameScene 场景,接下来这章我们将继续 GameScene 的传(bai)奇(bi).不过在开始编写 GameScene 场景的代码之前,我们还是先来明确一下游戏的功能和实现方法.这样可以帮我们更好的理解并设计逻辑.下面是总结出的结论: 在 GameScene 场景中,我们将创建一个飞行的娃娃角色,这个角色是游戏的唯一主角.游戏初始状态下,这个角色有满满的生命值,但随着时间的推移,生命

Quick-Cocos2d-x初学者游戏教程(五) --------------------- 辅助工具和跳转场景

Quick-Cocos2d-x初学者游戏教程(五) 上一章我们创建了游戏的菜单场景,并讲解了一些基础元素的创建,接下来这章,我们会先让大家了解一些接下来游戏开发中需要用到的辅助工具,然后再教大家创建另一个游戏场景,并跳着到该场景中来. 工具介绍 在开始真真的写代码之前,其实早该讲讲以下这些辅助工具的.这些工具可以让我们更好更方便的实现程序中的某些功能,比如地图编辑工具.粒子编辑工具 等.尽管这些工具在我之前的教程中已经不厌其烦的讲了好多次了,但是为了做到真正的初学者教程,本小节还是先来简单的介绍

Quick-Cocos2d-x初学者游戏教程(十一) ------------------ 物体碰撞检测

Quick-Cocos2d-x初学者游戏教程(十一) 本章主要讲解物体碰撞检测之间的原理,以及具体的实现方法. 碰撞检测 本游戏使用物理引擎的一个重要目的是为了让碰撞检测更方便,使用物理引擎可以进行精确的碰撞检测,而且执行的效率也很高. 在 Quick 3.3final 版本中,所有事件均有事件派发器统一管理,物理引擎的碰撞事件也不例外.它由 cc.EventListenerPhysicsContact 的实例来监听. 监听事件分类 碰撞监听事件有以下几种: cc.Handler.EVENT_P

Quick-Cocos2d-x初学者游戏教程(八)----------------- 物理引擎和角色

Quick-Cocos2d-x初学者游戏教程(八) 续上章载入 TiledMap 背景后,接下来的这章我们将开始引入物理引擎相关的东西,并且会开始创建我们的游戏角色.游戏地图中各类障碍物和奖励品的创建则会留到下一章. 构建物理世界 首先,物理引擎是干什么的应该不用我说吧?好吧,还是说一下(百度的):物理引擎通过为刚性物体赋予真实的物理属性的方式来计算运动.旋转和碰撞反映.所以用它来模拟真实世界的飞行.掉落等功能是具有得天独厚的优势的,这也是为什么我们的游戏要使用它的原因. 然后,我们要怎样使用物