(二)Lua小游戏别撞车——实现圆周运动

发表于2015-06-27
评论0 2.5k浏览

有了上篇博客的基础,我们先来实现一下游戏的主要逻辑,让小车做圆周运动,运动的过程中做碰撞检测,在适当的时候响应用户的触摸事件。我们不打算一下子做完所有的工作,第一步我们先来实现一个圆周运动。如下图所示,小车的运动轨迹包括一个圆周运动一个直线运动,直线运动很简单,但是圆周运动在Cocos中并没有提供,这个时候就需要我们自己来实现一个圆周运动了。

Lua小游戏别撞车——实现圆周运动

我不打算在Lua层实现一个圆周运动,因为某些接口函数没有导出来,如果你可以在Lua层实现一个圆周运动,那么请给我提交一个PR,共享出来给大家学习。我使用的方法是在c++层实现圆周运动,然后导出接口给Lua使用。第一步就是在c++层实现一个圆周运动,具体实现我单独写了一篇文章,大家可以看看(自定义圆周运动),最后的源码请参照更新以后的源码。第二步是使用Lua-binding将c++层自定义的圆周运动导出给Lua使用,具体的导出方法请参照博客——绑定自定义类到Runtime(Lua-binding)。绑定的方法其实很简单,主要是明白绑定的原理,只要你成功导出一次,以后导出10分钟就搞定了。如果以上的倆步你都不会操作,没有关系,我把自己导出的桥接函数和圆周运动的源代码都上传了网盘,大家可以下载使用。具体的使用方法同样参照绑定Lua的文章,如果你新建工程没有选择显示c++层代码的选项,可以在IDE中如下操作,这样在工程的frameworks目录下就显示出c++层代码了。

Lua小游戏别撞车——实现圆周运动

好了,现在万事俱备只欠代码了。首先新建一个MainGameScene.lua文件,这个Lua文件作为我们游戏主场景的模块文件。第一步写一个主场景的模块,参照上篇博客这个应该不难吧。

1require("Cocos2d")
2require("Cocos2dConstants")
3 
4local MainGameScene = class("MainGameScene",function()
5    return cc.Scene:create()
6end
7)
8 
9function MainGameScene:ctor()
10    self.size = cc.Director:getInstance():getWinSize()
11end
12 
13function MainGameScene:create()
14    --new函数的作用是调用了构造函数ctor,然后将表FlashScene的所有元素复制到了一张新的表中,最后返回这张表
15    local mainGame = MainGameScene:new()
16    local layer = mainGame:createLayer()
17    mainGame:addChild(layer)
18 
19    return mainGame
20end
21 
22return MainGameScene

上边的代码是形式,接下来我们在createLayer函数中写游戏的逻辑。

1function MainGameScene:createLayer()
2    local layer = cc.Layer:create()
3 
4    --添加背景图片
5    self:addBg(layer)
6 
7    --运行游戏主逻辑
8    self:mainLogic(layer)
9 
10    return layer
11end

createLayer函数很简单,创建了一个layer,然后返回这个layer,中间的代码实现的功能分别封装到了不同的函数中去完成。首先是添加背景图片,addBg函数如下。

1--添加背景图片
2function MainGameScene:addBg(layer)
3    --bg
4    local bg = cc.Sprite:create("bg.png")
5    bg:setPosition(self.size.width/2,self.size.height/2)
6    layer:addChild(bg)
7 
8    --bg2
9    local bg2 = cc.Sprite:create("bg2.png")
10    bg2:setPosition(self.size.width/2,self.size.height/2)
11    layer:addChild(bg2)
12end

代码很简单不用多说,然后是mainLogic函数,在这个函数中我们需要添加小车运行轨道的背景图片,然后将红色和黄色的俩辆小车分别添加到轨道上,最后让他们运动起来。

1--主逻辑
2function MainGameScene:mainLogic(layer)
3    --添加主逻辑的背景图片,也就是小车运行的轨道
4    local track = cc.Sprite:create("track.png")
5    track:setPosition(self.size.width/2,self.size.height/2)
6    layer:addChild(track)
7 
8    --轨道长宽
9    self.track_size = track:getContentSize()
10 
11    --创建一个红色小车
12    local car_red = cc.Sprite:create("car.png")
13    car_red:setPosition(self.track_size.width*0.45,self.track_size.height*0.063)
14    car_red:setTag(1)
15    self.car_bottomy = car_red:getPositionY()
16    self.car_topy = self.track_size.height*0.95
17 
18    --创建一个黄色小车
19    local car_yello = cc.Sprite:create("car2.png")
20    car_yello:setPosition(car_red:getPositionX()+car_red:getContentSize().width,self.track_size.height*0.063)
21    car_yello:setTag(2)
22 
23    --将车添加到轨道上
24    track:addChild(car_red)
25    track:addChild(car_yello)
26    --让小车动起来
27    self:runCar(car_red)
28    self:runCar(car_yello)
29 
30end

这里将轨道的大小作为本模块的一个成员保存了起来,因为接下来在其他的函数中我们会使用这个变量,同时我们也保存了上下俩条轨道的Y坐标,这里涉及到的坐标全部使用的是相对于轨道背景的大小,所以最后将小车添加到了轨道上,而不是层上。最后来看一下小车是如何运动的吧。

1--小车运动起来
2function MainGameScene:runCar(car)
3    --小车运动的时间
4    local tm = 1
5 
6    --创建第一个动作
7    local circle1 = tt.CircleBy:create(tm,{x=0,y=self.track_size.height*0.445},180)
8    local circle2 = tt.CircleBy:create(tm,{x=0,y=-self.track_size.height*0.445},180)
9    local action1 = cc.Sequence:create(
10        cc.MoveTo:create(tm,cc.p(self.track_size.width*0.245,self.car_bottomy)),
11        cc.Spawn:create(circle1,cc.RotateBy:create(tm,180)),
12        cc.MoveTo:create(tm,cc.p(self.track_size.width*0.745,self.car_topy)),
13        cc.Spawn:create(circle2,cc.RotateBy:create(tm,180))
14    )
15    local action_red = cc.RepeatForever:create(action1)
16    action_red:setTag(1)
17 
18    --创建第二个动作
19    local action2 = cc.Sequence:create(
20        cc.MoveTo:create(tm,cc.p(self.track_size.width*0.745,self.car_bottomy)),
21        cc.Spawn:create(circle1:reverse(),cc.RotateBy:create(tm,-180)),
22        cc.MoveTo:create(tm,cc.p(self.track_size.width*0.245,self.car_topy)),
23        cc.Spawn:create(circle2:reverse(),cc.RotateBy:create(tm,-180))
24    )
25    local action_yello = cc.RepeatForever:create(action2)
26    action_yello:setTag(2)
27 
28    --如果存在正在执行的动作,先停止动作的执行
29    if car:getActionByTag(1) ~= nil then
30        car:stopActionByTag(1)
31    end
32    --满足条件执行动作1
33    if car:getTag() == 1 then
34        car:runAction(action_red)
35    end
36 
37    --如果正在执行动作2,停止正在执行的动作
38    if car:getActionByTag(2) ~= nil then
39        car:stopActionByTag(2)
40    end
41    if car:getTag() == 2 then
42        car:runAction(action_yello)
43    end
44end

红色小车和黄色小车的运行轨迹不同,所以创建了俩个动作系列。这里主要说明一下圆周运动,圆周运动是我自己导出的,我起了一个模块名叫做tt,所以我要访问这个接口的时候使用的就是tt模块名。使用create创建圆周运动的时候第一个参数是时间,第二个参数是圆心的位置,这个位置是相对于当前执行动作的节点的位置,是相对的,不是绝对的,最后一个参数是做圆周运动一共转过的度数,这里是180。创建第二个动作的时候因为是和小车1的动作相反,所以使用了reverse函数,最后不断的repeat,这样小车会不断的运行下去。我们在创建小车和动作的时候还给他们设置了tag,这个是为了方便以后对他们的操作。这样,整个代码就写完了,本篇博客我们简单的使用c++层导出的接口来让小车运动了起来,其他的逻辑并没有实现。在整个模块中,我把每一个功能都写到了各自不同的函数中,这样整个代码看起来会比较清晰,最后的源代码大家到github上下载吧。

gitHub地址:https://github.com/zaojiahua/DontCrash


如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引