利用工作之余学习了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,255))
self:addChild(layer)
local size=cc.Director:getInstance():getWinSize()
local start=cc.MenuItemFont:create("开始")
start:setColor(cc.c3b(0,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,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, 0, width, height))
self:setColor(cc.c3b(0, 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,0))
self.effectLabel:enableGlow(cc.c4b(0,0,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,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,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("","fonts/Marker Felt.ttf", 20)
labelScore:setColor(cc.c3b(0,0,0))
labelScore:setString(self.score)
labelScore:setPosition(size.width-80,size.height-35)
self:addChild(labelScore)
--宝石个数
local labelGem=cc.Label:createWithTTF("","fonts/Marker Felt.ttf", 28)
labelGem:setColor(cc.c3b(0,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不久,学习学习了