有了上篇博客的基础,我们先来实现一下游戏的主要逻辑,让小车做圆周运动,运动的过程中做碰撞检测,在适当的时候响应用户的触摸事件。我们不打算一下子做完所有的工作,第一步我们先来实现一个圆周运动。如下图所示,小车的运动轨迹包括一个圆周运动一个直线运动,直线运动很简单,但是圆周运动在Cocos中并没有提供,这个时候就需要我们自己来实现一个圆周运动了。
我不打算在Lua层实现一个圆周运动,因为某些接口函数没有导出来,如果你可以在Lua层实现一个圆周运动,那么请给我提交一个PR,共享出来给大家学习。我使用的方法是在c++层实现圆周运动,然后导出接口给Lua使用。第一步就是在c++层实现一个圆周运动,具体实现我单独写了一篇文章,大家可以看看(自定义圆周运动),最后的源码请参照更新以后的源码。第二步是使用Lua-binding将c++层自定义的圆周运动导出给Lua使用,具体的导出方法请参照博客——绑定自定义类到Runtime(Lua-binding)。绑定的方法其实很简单,主要是明白绑定的原理,只要你成功导出一次,以后导出10分钟就搞定了。如果以上的倆步你都不会操作,没有关系,我把自己导出的桥接函数和圆周运动的源代码都上传了网盘,大家可以下载使用。具体的使用方法同样参照绑定Lua的文章,如果你新建工程没有选择显示c++层代码的选项,可以在IDE中如下操作,这样在工程的frameworks目录下就显示出c++层代码了。
好了,现在万事俱备只欠代码了。首先新建一个MainGameScene.lua文件,这个Lua文件作为我们游戏主场景的模块文件。第一步写一个主场景的模块,参照上篇博客这个应该不难吧。
2 | require ( "Cocos2dConstants" ) |
4 | local MainGameScene = class( "MainGameScene" , function () |
5 | return cc.Scene:create() |
9 | function MainGameScene:ctor() |
10 | self.size = cc.Director:getInstance():getWinSize() |
13 | function MainGameScene:create() |
15 | local mainGame = MainGameScene:new() |
16 | local layer = mainGame:createLayer() |
17 | mainGame:addChild(layer) |
上边的代码是形式,接下来我们在createLayer函数中写游戏的逻辑。
1 | function MainGameScene:createLayer() |
2 | local layer = cc.Layer:create() |
createLayer函数很简单,创建了一个layer,然后返回这个layer,中间的代码实现的功能分别封装到了不同的函数中去完成。首先是添加背景图片,addBg函数如下。
2 | function MainGameScene:addBg(layer) |
4 | local bg = cc.Sprite:create( "bg.png" ) |
5 | bg:setPosition(self.size.width/2,self.size.height/2) |
9 | local bg2 = cc.Sprite:create( "bg2.png" ) |
10 | bg2:setPosition(self.size.width/2,self.size.height/2) |
代码很简单不用多说,然后是mainLogic函数,在这个函数中我们需要添加小车运行轨道的背景图片,然后将红色和黄色的俩辆小车分别添加到轨道上,最后让他们运动起来。
2 | function MainGameScene:mainLogic(layer) |
4 | local track = cc.Sprite:create( "track.png" ) |
5 | track:setPosition(self.size.width/2,self.size.height/2) |
9 | self.track_size = track:getContentSize() |
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) |
15 | self.car_bottomy = car_red:getPositionY() |
16 | self.car_topy = self.track_size.height*0.95 |
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) |
24 | track:addChild(car_red) |
25 | track:addChild(car_yello) |
28 | self:runCar(car_yello) |
这里将轨道的大小作为本模块的一个成员保存了起来,因为接下来在其他的函数中我们会使用这个变量,同时我们也保存了上下俩条轨道的Y坐标,这里涉及到的坐标全部使用的是相对于轨道背景的大小,所以最后将小车添加到了轨道上,而不是层上。最后来看一下小车是如何运动的吧。
2 | function MainGameScene:runCar(car) |
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)) |
15 | local action_red = cc.RepeatForever:create(action1) |
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)) |
25 | local action_yello = cc.RepeatForever:create(action2) |
26 | action_yello:setTag(2) |
29 | if car:getActionByTag(1) ~= nil then |
30 | car:stopActionByTag(1) |
33 | if car:getTag() == 1 then |
34 | car:runAction(action_red) |
38 | if car:getActionByTag(2) ~= nil then |
39 | car:stopActionByTag(2) |
41 | if car:getTag() == 2 then |
42 | car:runAction(action_yello) |
红色小车和黄色小车的运行轨迹不同,所以创建了俩个动作系列。这里主要说明一下圆周运动,圆周运动是我自己导出的,我起了一个模块名叫做tt,所以我要访问这个接口的时候使用的就是tt模块名。使用create创建圆周运动的时候第一个参数是时间,第二个参数是圆心的位置,这个位置是相对于当前执行动作的节点的位置,是相对的,不是绝对的,最后一个参数是做圆周运动一共转过的度数,这里是180。创建第二个动作的时候因为是和小车1的动作相反,所以使用了reverse函数,最后不断的repeat,这样小车会不断的运行下去。我们在创建小车和动作的时候还给他们设置了tag,这个是为了方便以后对他们的操作。这样,整个代码就写完了,本篇博客我们简单的使用c++层导出的接口来让小车运动了起来,其他的逻辑并没有实现。在整个模块中,我把每一个功能都写到了各自不同的函数中,这样整个代码看起来会比较清晰,最后的源代码大家到github上下载吧。
gitHub地址:https://github.com/zaojiahua/DontCrash