cocos2dx 3.2之Lua打飞机项目

1创建lua打飞机项目

cocos new T32Lua -dE:\Installed\cocos2d-x-3.2\cocos2d-x-3.2\projects -l lua


2 项目代码

Common.lua

--用于打印日志信息

function cclog(...)

print(string.format(...))

end

function createBackMenu(node,callback)

-- 获得窗口的大小

local winSize = cc.Director:getInstance():getWinSize()

-- 创建菜单

local menu = cc.Menu:create()

-- node中加入菜单

node:addChild(menu)

--local function startGame()

-- cc.Director:getInstance():replaceScene(SceneMenu())

--end

-- 加菜单项

local menuItem = cc.MenuItemImage:create("btn_back_normal.png","btn_back_press.png")

-- 菜单中添加菜单项

menu:addChild(menuItem)

-- 注册处理函数

menuItem:registerScriptTapHandler(callback) -- 注册处理函数

-- menu的锚点默认是在屏幕正中间的,将它设置在屏幕右下角

menuItem:setAnchorPoint(cc.p(1,0))

-- 重新设置菜单项的位置

menuItem:setPosition(winSize.width/2,-winSize.height/2);

-- 设置缩放,在2.3中x方向和y方向上的缩放比例必须相同,但是在3.2中没有限制

menuItem:setScale(2)

end

-- 设置触摸事件

function regTouch(node,onTouchBegan,onTouchEnded,onTouchMoved)

local evListen = cc.EventListenerTouchOneByOne:create()

evListen:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN)

-- 如果onTouchEnded不为空

if onTouchEnded ~= nil then

evListen:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED)

end

-- 如果onTouchMoved不为空

if onTouchMoved ~= nil then

evListen:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED)

end

-- 如果

local evDisp = node:getEventDispatcher()

evDisp:addEventListenerWithSceneGraphPriority(evListen,node)

end

LayerScrollBackground.lua 滚动的背景

require "Common"

function LayerScrollBackground()

local layer = cc.Layer:create()

-- 获得屏幕的大小

local winSize = cc.Director:getInstance():getWinSize()

-- 加背景

local bg = cc.Sprite:create("background.png")

-- 层中添加作为背景的精灵

layer:addChild(bg)

-- 设置精灵的锚点

bg:setAnchorPoint(0,0)

-- 需要两个动作,一个动作向下移动,一个动作设置位置

local action1 = cc.MoveBy:create(10,{x=0,y=-winSize.height})

local action2 = cc.Place:create({x=0,y=0})

local action = cc.Sequence:create(action1,action2)

-- 执行动作

bg:runAction(cc.RepeatForever:create(action))

return layer

end

SceneMenu.lua 菜单

require "Common"

require "LayerScrollBackground"

require "SceneGame"

function SceneMenu()

local scene = cc.Scene:create()

local winSize = cc.Director:getInstance():getWinSize()

-- 滚动的背景

local bgLayer = LayerScrollBackground()

scene:addChild(bgLayer)

-- ScrollView

cc.SpriteFrameCache:getInstance():addSpriteFrames("chooselevel.plist")

local node = cc.Node:create()

for i = 1,5 do

local spriteName = "ChooseLevel" .. i .. ".png"

local spriteFrame = cc.SpriteFrameCache:getInstance():getSpriteFrame(spriteName)

local sprite = cc.Sprite:createWithSpriteFrame(spriteFrame)

node:addChild(sprite)

sprite:setPosition(winSize.width/2 + winSize.width*(i-1),winSize.height/2)

sprite:setTag(1000+i)

end

local scrollView = cc.ScrollView:create(winSize,node)

scene:addChild(scrollView)

scrollView:setContentSize(winSize.width*5,winSize.height)

scrollView:setDirection(0)

-- 增加Touch处理

local function onTouchBegan(touch,event)

return true

end

local function onTouchEnded(touch,event)

local sLoc = touch:getStartLocation()

local dLoc = touch:getLocation()

local d = {x=sLoc.x - dLoc.x,y=sLoc.y-dLoc.y}

local pt = node:convertToNodeSpace(sLoc)

if d.x*d.x+d.y*d.y < 25 then

for i=1,5 do

local sprite = node:getChildByTag(1000+i)

local rc = sprite:getBoundingBox()

if cc.rectContainsPoint(rc,pt) then

cc.Director:getInstance():replaceScene(SceneGame(i))

cclog("start new game " .. i)

end

end

end

end

regTouch(scene,onTouchEnded)

local function Back()

cc.Director:getInstance():replaceScene(SceneStart())

end

createBackMenu(scene,Back)

return scene

end

SceneStart.lua

require "SceneMenu"

require "Common"

function SceneStart()

local scene = cc.Scene:create()

local winSize = cc.Director:getInstance():getWinSize()

cclog(winSize.width .. winSize.height)

-- 加背景图片

local bg = cc.Sprite:create("background.png")

scene:addChild(bg)

bg:setPosition(winSize.width/2,winSize.height/2)

-- 加菜单按钮

local menu = cc.Menu:create()

scene:addChild(menu)

local function startGame()

cc.Director:getInstance():replaceScene(SceneMenu())

end

-- 加菜单项

local menuItemStart = cc.MenuItemImage:create("btn1_normal.png","btn1_push.png")

menu:addChild(menuItemStart)

menuItemStart:registerScriptTapHandler(startGame) -- 注册处理函数

return scene

end

SceneGame.lua

require "Common"

require "LayerScrollBackground"

function SceneGame(idx)

--创建

local scene = cc.Scene:create()

local winSize = cc.Director:getInstance():getWinSize()

-- 滚动的背景

local bgLayer = LayerScrollBackground()

-- 场景中加上层

scene:addChild(bgLayer)

-- 数据结构,子弹的数组和敌机的数组

local bullets = {}

-- 添加敌机

local enemys = {}

-- 创建英雄战机

local plane = cc.Sprite:create("Player" .. idx .. ".png")

-- 场景中添加飞机

scene:addChild(plane)

-- 设置飞机的位置

plane:setPosition(winSize.width/2,plane:getBoundingBox().height)

-- 设置plane的ZOrder

plane:setLocalZOrder(100)

----- 加载战斗机的属性

local vm = cc.FileUtils:getInstance():getValueMapFromFile("planeinfo.xml");

plane.damage = tonumber(vm["planedamageamount" .. idx])

plane.hp = tonumber(vm["plane" .. idx .. "_hp"])

plane.cd = tonumber(vm["planeshootspeedrate" .. idx])

plane.curCD = 0;

cclog(plane.damage .. " " .. plane.hp .. " " .. plane.cd)

-- 显示分数和血的Label

local labelScore = nil

local labelHP = nil

local function createLabels()

-- 设置label

labelHP = cc.Label:createWithSystemFont("" .. plane.hp,"Arial",50)

-- 设置Label的锚点

labelHP:setAnchorPoint(cc.p(1,1))

-- 设置锚点的位置

labelHP:setPosition(winSize.width,winSize.height)

scene:addChild(labelHP)

labelHP:setLocalZOrder(1010)

labelScore = cc.Label:createWithSystemFont("0",50)

labelScore:setAnchorPoint(cc.p(0,1))

labelScore:setPosition(0,winSize.height)

scene:addChild(labelScore)

labelScore:setLocalZOrder(1010)

end

createLabels()

-- 移动飞机

-- 增加Touch处理

local function onTouchBegan(touch,event)

return true

end

local function onTouchMoved(touch,event)

local x,y = plane:getPosition()

local d = touch:getDelta()

plane:setPosition(x+d.x,y+d.y)

end

local function onTouchEnded(touch,event)

end

regTouch(scene,onTouchMoved)

------------------- shoot

-- angle参数代表的发射角度,delta表示子弹发射的起始位置和英雄战机的位置的偏移

local function shootOne(angle,delta)

cc.SimpleAudioEngine:getInstance():playEffect("m/bullet.wav")

local bullet = cc.Sprite:create("Bullet.png")

scene:addChild(bullet)

local x,y = plane:getPosition()

bullet:setPosition(x+delta.x,y+delta.y)

bullet:setRotation(angle)

-- math.rad(角度) 把角度转换成弧度

local dx = math.sin( math.rad(angle) ) * winSize.height

local dy = math.cos( math.rad(angle) ) * winSize.height

local moveBy = cc.MoveBy:create(5,cc.p(dx,dy))

bullet:runAction(moveBy)

-- 子弹保存在数组里

table.insert(bullets,bullet)

end

local function Shoot()

local sizePlane = plane:getContentSize()

if idx == 1 then

shootOne(0,cc.p(0,sizePlane.height/2))

elseif idx == 2 then

shootOne(0,sizePlane.height/2))

shootOne(0,cc.p(-sizePlane.width/4,sizePlane.height/4))

shootOne(0,cc.p(sizePlane.width/4,sizePlane.height/4))

elseif idx == 3 then

shootOne(0,sizePlane.height/2))

shootOne(-30,sizePlane.height/2))

shootOne(30,sizePlane.height/2))

elseif idx == 4 then

shootOne(0,sizePlane.height/2))

shootOne(180,-sizePlane.height/2))

shootOne(90,cc.p(sizePlane.width/2,0))

shootOne(270,cc.p(-sizePlane.width/2,0))

elseif idx==5 then

shootOne(45,0))

shootOne(45+90,0))

shootOne(45+180,0))

shootOne(45+270,0))

end

end

local function tickShoot()

plane.curCD = plane.curCD + 1

if plane.curCD >= plane.cd then

Shoot()

plane.curCD = 0

end

end

local tickShootID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(tickShoot,false)

-- 检查子弹是否飞出窗口外

local function checkBulletAndEnemy()

-- 得到子弹数量

local n = table.getn(bullets)

for i = n,1,-1 do

local bullet = bullets[i]

-- 判断bullet是不是出了窗口

local x,y = bullet:getPosition()

if x<0 or y<0 or x>winSize.width or y > winSize.height then

bullet:removeFromParent()

table.remove(bullets,i) -- 从bullets数组中,删除下标为i的元素

cclog("bullet is out of window")

end

end

n = table.getn(enemys)

for i = n,-1 do

local enemy = enemys[i]

-- 判断enemy是不是出了窗口

local x,y = enemy:getPosition()

if y < -enemy:getContentSize().height/2 then

enemy:removeFromParent()

table.remove(enemys,i) -- 从enemys数组中,删除下标为i的元素

end

end

end

local tickCheckBullet = cc.Director:getInstance():getScheduler():scheduleScriptFunc(checkBulletAndEnemy,false)

-- 产生敌机的定时器

local function genEnemy(type)

-- 创建敌机精灵,加入到数组,加入渲染树

-- 增加敌机属性

-- 随机设置位置

local enemy = cc.Sprite:create("Enemy" .. type .. ".png")

table.insert(enemys,enemy)

scene:addChild(enemy)

-- 敌军飞机的额外属性

local hp = {10,30,100}

enemy.hp = hp[type]

local score = {1000,3000,10000}

enemy.score = score[type]

local speed = {150,100,50}

enemy.speed = speed[type]

enemy.type = type

-- 设置初始位置

local sizePlane = enemy:getContentSize()

math.randomseed(os.time())

local x = math.random(sizePlane.width/2,winSize.width-sizePlane.width/2)

local y = winSize.height + sizePlane.height/2

enemy:setPosition(x,y)

-- 设置飞机飞行动作

local distance = winSize.height + sizePlane.height + 5

local moveBy = cc.MoveBy:create(distance*1.0/enemy.speed,-distance))

enemy:runAction(moveBy)

end

local function genEnemy1()

genEnemy(1)

end

local function genEnemy2()

genEnemy(2)

end

local function genEnemy3()

genEnemy(3)

end

local tickGenEnemy1 = cc.Director:getInstance():getScheduler():scheduleScriptFunc(genEnemy1,false)

local tickGenEnemy2 = cc.Director:getInstance():getScheduler():scheduleScriptFunc(genEnemy2,3,false)

local tickGenEnemy3 = cc.Director:getInstance():getScheduler():scheduleScriptFunc(genEnemy3,10,false)

local function loadBoomAnimation()

local spriteFrameCache = cc.SpriteFrameCache:getInstance()

spriteFrameCache:addSpriteFrames("PFBoom.plist")

-- CCArray* arr = CCArray:create()

local spriteFrames = {}

for i = 1,18 do

local spriteFrame = spriteFrameCache:getSpriteFrame("Boom_" .. i .. ".png")

table.insert(spriteFrames,spriteFrame)

end

local animation = cc.Animation:createWithSpriteFrames(spriteFrames,0.05)

cc.AnimationCache:getInstance():addAnimation(animation,"ENEMYBOOM")

end

loadBoomAnimation()

local function removeEnemy(node,tab)

node:removeFromParent()

end

local function enemyBoom(idx)

local enemy = enemys[idx]

cc.SimpleAudioEngine:getInstance():playEffect("m/enemy" .. enemy.type .. "_down.wav")

-- 增加分数

local score = labelScore:getString()

score = tonumber(score) + enemy.score

labelScore:setString("" .. score)

table.remove(enemys,idx)

-- 执行爆炸动画,然后再调用removeFromParent

local animation = cc.AnimationCache:getInstance():getAnimation("ENEMYBOOM")

local animate = cc.Animate:create(animation)

local callfunc = cc.CallFunc:create(removeEnemy)

local seq = cc.Sequence:create(animate,callfunc)

enemy:runAction(seq)

-- enemy:removeFromParent()

end

local function collision()

local nEnemy = table.getn(enemys)

local rcPlane = plane:getBoundingBox()

for i = nEnemy,-1 do

local enemy = enemys[i]

local rcEnemy = enemy:getBoundingBox()

local bEnemyBoom = false

-- 如果敌机和英雄战机碰撞,rcEnemy,rcPlane

if cc.rectIntersectsRect(rcEnemy,rcPlane) then

plane.hp = plane.hp - enemy.hp

labelHP:setString("" .. plane.hp)

if plane.hp <= 0 then

cc.Director:getInstance():replaceScene(SceneMenu())

break

end

enemyBoom(i)

bEnemyBoom = true

end

-- 跟子弹进行碰撞检测

if bEnemyBoom == false then

local nBullet = table.getn(bullets)

for j = nBullet,-1 do

local bullet = bullets[j]

-- 如果子弹和敌机碰撞

local ptBullet = cc.p( bullet:getPosition() )

if cc.rectContainsPoint(rcEnemy,ptBullet) then

bullet:removeFromParent()

table.remove(bullets,j)

enemy.hp = enemy.hp - plane.damage;

if enemy.hp <= 0 then

enemyBoom(i)

break -- 表示这个敌机不再和下一个子弹做碰撞检测

end

end

end

end

end

end

local tickCollisionID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(collision,false)

local function Back()

cc.Director:getInstance():replaceScene(SceneMenu())

end

createBackMenu(scene,Back)

-- 注销定时器

local function onNodeEvent(event)

if "enter" == event then

cclog("OnEnter")

cc.SimpleAudioEngine:getInstance():playMusic("m/game_music.wav",true)

end

if "exit" == event then

cc.SimpleAudioEngine:getInstance():stopMusic()

cc.Director:getInstance():getScheduler():unscheduleScriptEntry(tickShootID)

cc.Director:getInstance():getScheduler():unscheduleScriptEntry(tickCheckBullet)

cc.Director:getInstance():getScheduler():unscheduleScriptEntry(tickGenEnemy1)

cc.Director:getInstance():getScheduler():unscheduleScriptEntry(tickGenEnemy2)

cc.Director:getInstance():getScheduler():unscheduleScriptEntry(tickGenEnemy3)

cc.Director:getInstance():getScheduler():unscheduleScriptEntry(tickCollisionID)

end

end

scene:registerScriptHandler(onNodeEvent)

return scene

end

main.lua

--引入lua的方式是通过require

require "Cocos2d"

require "Cocos2dConstants"

-- cclog 打印日志的方式

cclog = function(...)

print(string.format(...))

end

-- for CCLuaEngine traceback lua中连接字符串的方式是通过 .. 实现的

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)

-- initialize director lua中定义局部变量的是通过local的方式

local director = cc.Director:getInstance()

local glview = director:getOpenGLView()

if nil == glview then

glview = cc.GLView:createWithRect('HelloLua',cc.rect(0,768/2,1280/2))

director:setOpenGLView(glview)

end

-- 设置设计分辨率,这个就是图片的实际大小

glview:setDesignResolutionSize(768,1280,cc.ResolutionPolicy.NO_BORDER)

--turn on display FPS

director:setDisplayStats(true)

--set FPS. the default value is 1.0/60 if you don't call this

director:setAnimationInterval(1.0 / 60)

-- 设置加载的文件包

cc.FileUtils:getInstance():addSearchPath("src")

cc.FileUtils:getInstance():addSearchPath("res")

--support

local targetPlatform = cc.Application:getInstance():getTargetPlatform()

if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or

(cc.PLATFORM_OS_ANDROID == targetPlatform) or (cc.PLATFORM_OS_WINDOWS == targetPlatform) or

(cc.PLATFORM_OS_MAC == targetPlatform) then

cclog("result is ")

--require('debugger')()

end

-----------------------------------------------

-- 自定义的文件的require必须在 addSearchPath之后,2.2.3没有这个问题

require "SceneStart"

cc.Director:getInstance():runWithScene(SceneStart())

end

local status,msg = xpcall(main,__G__TRACKBACK__)

if not status then

error(msg)

end

运行结果:


相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...