利用工作之余学习了cocos2d-x lua,现在把之前学习的知识运用一下,做个小游戏,用的是cocos2d-x 3.2 lua 开发工具是 cocos ide
看看效果图
开始编写吧
1、项目结构
2、编写游戏的开始场景 StartGame.lua
--游戏启动场景 StartGame=class("StartGame",function () return cc.Scene:create() end) function StartGame:createScene() local scene=StartGame.new() scene:startMenu() return scene end function StartGame:startMenu() local layer=cc.LayerColor:create(cc.c4b(255,255,255)) self:addChild(layer) local size=cc.Director:getInstance():getWinSize() local start=cc.MenuItemFont:create("开始") start:setColor(cc.c3b(0,0)) start:setPosition(size.width/2,size.height/2) start:registerScriptTapHandler(function(sender) --跳到游戏场景 cc.Director:getInstance():replaceScene(GameScene:createScene()) end) local exit=cc.MenuItemFont:create("退出") exit:setScale(0.5) exit:setColor(cc.c3b(0,0)) exit:setPosition(size.width-50,50) exit:registerScriptTapHandler(function(sender) cc.Director:getInstance():endToLua() end) local menu=cc.Menu:create(start,exit) menu:setPosition(0,0) layer:addChild(menu) end return StartGame
开始场景只有一个开始按钮和结束按钮,比较简单
3、编写游戏中的 小黑人精灵,小黑人精灵是一个精灵动画,并为小黑人创建一个矩形的刚体,用于碰撞检测
Hero.lua
--英雄精灵 Hero=class("Hero",function () return cc.Sprite:create() end) function Hero:createHero() --- --@return cc.Sprite sp local sp=Hero.new() sp:init() return sp; end function Hero:init() local width = 50 local height = 55 --设置精灵的显示大小 self:setContentSize(width,height) -- self:setTexture(Res.hero) self:setScale(0.5) self:setName("hero") self:setTag(1) --创建一个矩形body local heroBody=cc.PhysicsBody:createBox(cc.size(width,height)) self:setPhysicsBody(heroBody) -- self:getPhysicsBody():setDynamic(false) self:getPhysicsBody():setRotationEnable(false) --设置不受重力的影响 -- self:getPhysicsBody():setGravityEnable(false) --设置碰撞掩码 heroBody:setCategoryBitmask(0x03) heroBody:setContactTestBitmask(0x01) heroBody:setCollisionBitmask(0x01) --加载小黑人纹理 local cache=cc.SpriteFrameCache:getInstance() cache:addSpriteFrames(Res.heroPlist,Res.heroPng) --小黑人动画 local animFrames={} for i=1,8 do local frame=cache:getSpriteFrame(string.format("hero_%d.png",i)) animFrames[i]=frame end local animation=cc.Animation:createWithSpriteFrames(animFrames,0.1) local animate=cc.Animate:create(animation) self:runAction(cc.RepeatForever:create(animate)) end return Hero
4、编写游戏中的障碍物
Block.lua
--障碍物精灵 Block=class("Block",function () return cc.Sprite:create() end) function Block:createBlock(blockSpeed) local sp=Block.new() sp:init(blockSpeed) return sp end function Block:init(blockSpeed) --随机障碍物的大小 local width = math.random(0,20) + 5 local height = math.random(0,100) + 20 --设置障碍物精灵在最最右边出现 -- self:setPositionX(cc.Director:getInstance():getVisibleSize().width) -- self:setContentSize(width,height) self:setTextureRect(cc.rect(0,width,height)) self:setColor(cc.c3b(0,0)) --设置为静态刚体 local blockBody=cc.PhysicsBody:createBox(cc.size(width,height)) self:setPhysicsBody(blockBody) self:getPhysicsBody():setDynamic(false) blockBody:setCategoryBitmask(0x03) --类别掩码 默认值为0xFFFFFFFF blockBody:setContactTestBitmask(0x02) --接触掩码 默认值为 0x00000000 blockBody:setCollisionBitmask(0x02) --碰撞掩码 默认值为0xFFFFFFFF self:scheduleUpdateWithPriorityLua(function(dt) --不断改变x的位置 self:setPositionX(self:getPositionX()-blockSpeed) if self:getPositionX() < 0 then --移除自身 self:unscheduleUpdate() self:removeFromParent() end end,0) end return Block
5、编写游戏中的宝石精灵
Gem.lua
--宝石精灵类 Gem=class("Gem",function () return cc.Sprite:create() end) function Gem:ctor() --宝石的移动速度 self.gemSpeed=1 end function Gem:cretateGem() local sp=Gem.new() sp:init() return sp end function Gem:init() local size=cc.Director:getInstance():getWinSize() self:setName("gem") --取整1、2、3 math.randomseed(os.time()) local index=math.floor(math.random(1,3)) local cache=cc.SpriteFrameCache:getInstance() --绿宝石 if 1 == index then self:setSpriteFrame(cache:getSpriteFrame("green.png")) self:setScale(0.25) self:setTag(21) --紫宝石 elseif 2 == index then self:setSpriteFrame(cache:getSpriteFrame("purple.png")) self:setScale(0.25) self:setTag(22) --红宝石 elseif 3 == index then self:setSpriteFrame(cache:getSpriteFrame("red.png")) self:setScale(0.25) self:setTag(23) end local gemBody=cc.PhysicsBody:createEdgeBox(cc.size(25,25)) gemBody:setCategoryBitmask(0x01) --类别掩码 默认值为0xFFFFFFFF gemBody:setContactTestBitmask(0x01) --接触掩码 默认值为 0x00000000 gemBody:setCollisionBitmask(0x01) --碰撞掩码 默认值为0xFFFFFFFF self:setPhysicsBody(gemBody) self:scheduleUpdateWithPriorityLua(function(dt) --不断改变x的位置 self:setPositionX(self:getPositionX()-self.gemSpeed) if self:getPositionX() < 0 then --移除自身 self:unscheduleUpdate() self:removeFromParent() end end,0) end --设置宝石移动的速度 function Gem:setGemSpeed(speed) self.gemSpeed=speed end function Gem:getGemSpeed(speed) return self.gemSpeed end return Gem
6、编写游戏中的控制类,这里控制了精灵的出现和碰撞
Control.lua
--控制精灵的动作 Control=class("Control") function Control:create(layer,positionY) local control=Control.new() control:init(layer,positionY) return control end function Control:ctor() self.size=nil self.layer = nil self.positionY=nil self.effectLabel=nil --移动的速度 self.blockSpeed=2 --控制什么时候创建 障碍物精灵 self.createBlockHero=nil self.nextBlockHero=nil --控制什么时候创建宝石 self.createGem=nil self.nextGem=nil end --- --@param cc.Layer layer function Control:init(layer,positionY) self.size=cc.Director:getInstance():getWinSize() self.layer=layer self.positionY=positionY --创建一个英雄精灵 local hero=Hero:createHero() print(self.positionY+hero:getContentSize().height / 2) hero:setPosition(50,self.positionY+hero:getContentSize().height / 2) self.layer:addChild(hero) --跳跃按钮 local itemControl=cc.MenuItemImage:create(Res.control_n,Res.control_p) itemControl:setScale(0.35) itemControl:setPosition( self.size.width-40,30) itemControl:registerScriptTapHandler(function() if hero:getPositionY() < hero:getContentSize().height + self.positionY then hero:getPhysicsBody():setVelocity(cc.p(0,500)) end end) local menu=cc.Menu:create(itemControl) menu:setPosition(0,0) self.layer:addChild(menu) --速度变化特效 self.effectLabel=cc.Label:createWithTTF("","fonts/Marker Felt.ttf",32) self.effectLabel:setColor(cc.c3b(0,0)) self.effectLabel:enableGlow(cc.c4b(0,0)) self.effectLabel:setPosition(self.size.width-50,self.positionY+self.size.height/2-self.effectLabel:getContentSize().height/2) self.layer:addChild(self.effectLabel) -- self.effectLabel:setVisible(false) --初始化计数参数 self:reset() end --- --@param touch cc.Touch --@param event cc.Event -- function Control:r(touch,event) -- -- end function Control:reset() self.createBlockHero=0 self.nextBlockHero=math.random(0,99)+120 end --创建障碍物精灵 score分数 function Control:updateBlock(score) --createBlockHero计数增加 self.createBlockHero=self.createBlockHero+1 -- 随机时间生成障碍物 if self.createBlockHero >= self.nextBlockHero then --控制障碍物移动的速度 --- --@param cc.Sprite blockSprite local blockSprite=Block:createBlock(self.blockSpeed) if score >=20 and score < 50 then print("blockSpeed:",self.blockSpeed) if self.blockSpeed < 3 then self:test("+3") self.blockSpeed=3 end elseif score >=50 and score < 80 then if self.blockSpeed < 3 then self:test("+5") self.blockSpeed=5 end elseif score >=80 and score < 100 then if self.blockSpeed < 5 then self:test("+6") self.blockSpeed=6 end elseif score >=100 and score < 150 then if self.blockSpeed < 6 then self:test("+7") self.blockSpeed=7 end elseif score >=150 and score < 180 then if self.blockSpeed < 7 then self:test("+8") self.blockSpeed=8 end elseif score >=180 and score < 250 then if self.blockSpeed < 8 then self:test("+10") self.blockSpeed=10 end elseif score >= 250 and score < 320 then if self.blockSpeed < 10 then self:test("+12") self.blockSpeed=12 end elseif score >= 320 and score < 400 then if self.blockSpeed < 12 then self:test("+15") self.blockSpeed=15 end elseif score >= 400 then if self.blockSpeed < 15 then self:test("+18") self.blockSpeed=18 end end --取整0、2 math.randomseed(os.time()) local index1=math.floor(math.random(0,1)) local positionX1=self.size.width local positionY1=math.random(self.positionY+120+10,self.size.height-35) if index1 >= 1 then for i=0,index1 do local gem=Gem:cretateGem() gem:setPosition(positionX1,positionY1) self.layer:addChild(gem) gem:setGemSpeed(1) positionX1=positionX1-25 end end --取整0、2 math.randomseed(os.time()) local index2=math.floor(math.random(0,2)) local positionX2=self.size.width; if index2 >= 1 then for i=0,index2 do local gem=Gem:cretateGem() gem:setPosition(positionX2,self.positionY+gem:getContentSize().height / 5) self.layer:addChild(gem) gem:setGemSpeed(self.blockSpeed) positionX2=positionX2+25 end end blockSprite:setPosition(positionX2+10,self.positionY+blockSprite:getContentSize().height / 2) self.layer:addChild(blockSprite) --重新计数 self:reset() end end function Control:test(effectType) self.effectLabel:setString(effectType) self.effectLabel:setVisible(true) print("effectLabel") self.effectLabel:runAction(cc.Sequence:create(cc.ScaleTo:create(1,2),cc.CallFunc:create(function(sender) sender:setVisible(false) end))) end function Control:setBlockSpeed(speed) self.blockSpeed=speed end function Control:getBlockSpeed() return self.blockSpeed end return Control
7、编写游戏层GameLayer.lua
GameLayer=class("GameLayer",function () return cc.LayerColor:create(cc.c4b(255,255)) end) function GameLayer:ctor() --控制类 self.control=nil self.score=0 self.gem=0 end function GameLayer:createLayer() local layer=GameLayer.new() layer:bg() return layer end --游戏背景图 function GameLayer:bg() local size=cc.Director:getInstance():getWinSize() --创建一个围绕屏幕四周的物理边界 local node=cc.Node:create() node:setPhysicsBody(cc.PhysicsBody:createEdgeBox(cc.size(size.width,size.height),cc.PHYSICSBODY_MATERIAL_DEFAULT,5)) node:setPosition(size.width/2,size.height/2+50) self:addChild(node) -- 地面(一条线) local edgeSprite=cc.Sprite:create() edgeSprite:setTextureRect(cc.rect(0,size.width,2)) edgeSprite:setColor(cc.c3b(125,125,0)) edgeSprite:setPosition(size.width/2,50) self:addChild(edgeSprite) --分数 local labelscore=cc.Label:createWithTTF("",20) labelscore:setColor(cc.c3b(0,0)) labelscore:setString(self.score) labelscore:setPosition(size.width-80,size.height-35) self:addChild(labelscore) --宝石个数 local labelGem=cc.Label:createWithTTF("",28) labelGem:setColor(cc.c3b(0,0)) labelGem:setString(self.gem) labelGem:setPosition(size.width-180,size.height-35) self:addChild(labelGem) --宝石 local cache=cc.SpriteFrameCache:getInstance() cache:addSpriteFrames(Res.gemPlist,Res.gemPng) self.control=Control:create(self,50) local spGem=cc.Sprite:createWithSpriteFrameName("green.png") spGem:setPosition(size.width-220,size.height-35) spGem:setScale(0.5) self:addChild(spGem) self:scheduleUpdateWithPriorityLua(function(dt) --分数 self.score = self.score + dt labelscore:setString(string.format("%#.2f",self.score)) self.control:updateBlock(self.score) end,0) --一个body的CategoryBitmask和另一个body的ContactTestBitmask的逻辑与的结果不等于0时,接触事件将被发出,否则不发送。 --一个body的CategoryBitmask和另一个body的CollisionBitmask的逻辑与结果不等于0时,他们将碰撞,否则不碰撞 --需要两个body相互位与运算的值都是大于0时才会发生碰撞检测和发送接触事件通知 -- 碰撞监听 local conListener=cc.EventListenerPhysicsContact:create(); conListener:registerScriptHandler(function(contact) print("---contact-碰撞了--") -- 处理游戏中精灵碰撞逻辑 local node1=contact:getShapeA():getBody():getNode() local name1=node1:getName() local tag1=node1:getTag() print("name1:",name1) local node2=contact:getShapeB():getBody():getNode() local name2=node2:getName() local tag2=node2:getTag() print("name2:",name2) --英雄碰到宝石 if name1 == "gem" then local x,y=node1:getPosition() self.gem=self.gem+1 labelGem:setString(string.format("%s",self.gem)) labelGem:runAction(cc.Sequence:create(cc.ScaleTo:create(0.2,1.5),cc.CallFunc:create( function (sender) sender:runAction(cc.ScaleTo:create(0.1,1)) end))) if nil ~= node1 then self:removeChild(node1,true) end -- node1:runAction(cc.Sequence:create(cc.Spawn:create(cc.MoveTo:create(0.1,cc.p(node1:getPositionX(),node1:getPositionY()+50)),cc.ScaleTo:create(0.1,0.5),cc.FadeOut:create(0.1)),-- cc.CallFunc:create(function(sender) -- self:removeChild(sender,true) -- end))) --英雄碰到障碍物死亡 elseif name1 == "hero" then local x,y=node2:getPosition() cc.Director:getInstance():replaceScene(StartGame:createScene()) elseif name2 == "hero" then local x,y=node2:getPosition() cc.Director:getInstance():replaceScene(StartGame:createScene()) end return true end,cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN) cc.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraPHPriority(conListener,self) end return GameLayer
8、编写游戏场景GameScene.lua
--游戏场景 GameScene=class("GameScene",function () return cc.Scene:createWithPhysics() end) function GameScene:createScene() local scene=GameScene.new() -- 设置调试 -- scene:getPhysicsWorld():setDebugDrawMask(cc.PhysicsWorld.DEBUGDRAW_ALL) scene:getPhysicsWorld():setGravity(cc.p(0,-1000)) local layer=GameLayer:createLayer() scene:addChild(layer) return scene end return GameScene
9、这里我用类把图片和加载的lua文件封装了
Require.lua 游戏加载的lua文件
--引入lua类 require("Cocos2d") require("Cocos2dConstants") require("bitExtend") require("src/game/res/Res") require("src/game/start/StartGame") require("src/game/scene/GameScene") require("src/game/scene/GameLayer") require("src/game/sprite/Block") require("src/game/sprite/Hero") require("src/game/sprite/Control") require("src/game/sprite/Gem")
Res.lua 游戏用到的图片资源
--图片资源类 Res={} --开始按钮 Res.start_n="qq_n.png" Res.start_p="qq_p.png" Res.heroPng="hero.png" Res.heroPlist="hero.plist" Res.control_n="control_n.png" Res.control_p="control_p.png" Res.gemPlist="gem.plist" Res.gemPng="gem.png"
10、修改main.lua
--引入lua文件 require "src/game/res/Require" -- cclog local cclog = function(...) print(string.format(...)) end -- for CCLuaEngine traceback function __G__TRACKBACK__(msg) cclog("----------------------------------------") cclog("LUA ERROR: " .. tostring(msg) .. "\n") cclog(debug.traceback()) cclog("----------------------------------------") return msg end local function main() collectgarbage("collect") -- avoid memory leak collectgarbage("setpause",100) collectgarbage("setstepmul",5000) cc.FileUtils:getInstance():addSearchPath("src") cc.FileUtils:getInstance():addSearchPath("res") cc.FileUtils:getInstance():addSearchPath("src/game/res") cc.FileUtils:getInstance():addSearchPath("src/game/start") cc.FileUtils:getInstance():addSearchPath("src/game/scene") cc.FileUtils:getInstance():addSearchPath("src/game/sprite") cc.FileUtils:getInstance():addSearchPath("res/game") cc.FileUtils:getInstance():addSearchPath("res/game/hero") cc.FileUtils:getInstance():addSearchPath("res/game/gem") cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(480,320,0) cc.Director:getInstance():setDisplayStats(false) --进入游戏场景 local scene = require("StartGame") local gameScene =scene:createScene() if cc.Director:getInstance():getRunningScene() then cc.Director:getInstance():replaceScene(gameScene) else cc.Director:getInstance():runWithScene(gameScene) end end local status,msg = xpcall(main,__G__TRACKBACK__) if not status then error(msg) end
11、这里发布到android上,ide提供了一键发布,非常的好用,需要设置下环境
然后选择项目打包
等待几分钟就会看到打包成功了
呵呵,是不是很方便? 小弟也是新手,很多地方写的可能不好,我也是刚学lua不久,学习学习了