self 在lua中相当于java中的this
lua中的任何变量在没有赋值前, 都可以看做是nil
lua变量有3种,
成员变量: self.变量名 =
局部变量: local 变量名 =
全局变量: 变量名 =
成员变量: self.变量名 =
局部变量: local 变量名 =
全局变量: 变量名 =
在一个游戏中和逻辑有关的动作最好不用transition 因为不可控且不稳定
物体的移动可以用update的方法实现:
设置一个角色每帧移动的项目距离,比如speed = 5,然后解析几何的方法算出 speedX,和speedY的分量。
在update里,local curPos = self._imgSpr:getPositionInCCPoint()得到当前的坐标。坐标+速度,然后再setPosition就移动了。
例如:
1 function Bullet:update() --总函数的update调用每个子弹的update 2 3 local imagex = self._imgSpr:getPositionX(); 4 local imagey = self._imgSpr:getPositionY(); 5 6 imagex = imagex - self._speedx 7 imagey = imagey + self._speedy 8 9 self._imgSpr:pos(imagex, imagey) 10 11 end
lua中类的创建:
1 local Bullet = class("Bullet", function() 2 return display.newNode() 3 end) 4 5 speed = 20 6 7 function Bullet:ctor() --构造函数 8 --bullet父对象是node 这里把sprite对象添加到node上 9 self._imgSpr = display.newSprite("img1.png") --添加bullet图片 10 self._imgSpr:pos(300,0) 11 self._imgSpr:scale(0.5) 12 self:addChild(self._imgSpr) 13 14 self._speedx = nil 15 self._speedy = nil 16 17 end 18 19 function Bullet:init( x,y ) 20 local mousex = x --bullet init传值 不推荐用构造函数传值 speed在这里计算出来后来直接调用即可 21 local mousey = y 22 local imagex = 300 23 local imagey = 0 24 25 local distance = math.sqrt((mousex - imagex)*(mousex - imagex)+(mousey - imagey)*(mousey - imagey)) 26 local degree = math.deg(math.asin((y - imagey)/distance)) 27 if(mousex < imagex) then 28 degree = 180 - degree 29 end 30 degree = 180 - degree 31 32 print(degree) 33 self._imgSpr:setRotation(degree) 34 35 self._speedx = speed*math.cos(math.rad(degree)) 36 self._speedy = speed*math.sin(math.rad(degree)) 37 38 print(self._speedx) 39 40 end
由上文可见此处的bullet类继承自node
ctor是构造函数,一般不建议传参数。若需要传参应新建一个函数 (如init)用于参数传递。
在main中新建实例时,首先要require声明此对象的文件。
例如新建bullet对象:
1 ClassBullet = require("app/object/Bullet") -- require相当于include 2 3 4 local bullet = ClassBullet.new() --bullet实例 5 bullet:init(x,y) --init bullet 6 self:addChild(bullet) --把bullet这个node添加到父节点中 7 table.insert(self._listBullet, bullet) --1开始 --把listBullet中对象insert到表中
第一版代码:
Bullet.lua
1 local Bullet = class("Bullet", function() 2 return display.newNode() 3 end) 4 5 speed = 20 6 7 function Bullet:ctor() --构造函数 8 --bullet父对象是node 这里把sprite对象添加到node上 9 self._imgSpr = display.newSprite("img1.png") --添加bullet图片 10 self._imgSpr:pos(300,0) 11 self._imgSpr:scale(0.5) 12 self:addChild(self._imgSpr) 13 14 self._speedx = nil 15 self._speedy = nil 16 17 end 18 19 function Bullet:init( x,y ) 20 local mousex = x --bullet init传值 不推荐用构造函数传值 speed在这里计算出来后来直接调用即可 21 local mousey = y 22 local imagex = 300 23 local imagey = 0 24 25 local distance = math.sqrt((mousex - imagex)*(mousex - imagex)+(mousey - imagey)*(mousey - imagey)) 26 local degree = math.deg(math.asin((y - imagey)/distance)) 27 if(mousex < imagex) then 28 degree = 180 - degree 29 end 30 degree = 180 - degree 31 32 print(degree) 33 self._imgSpr:setRotation(degree) 34 35 self._speedx = speed*math.cos(math.rad(degree)) 36 self._speedy = speed*math.sin(math.rad(degree)) 37 38 print(self._speedx) 39 40 41 end 42 43 function Bullet:update() --总函数的update调用每个子弹的update 44 45 local imagex = self._imgSpr:getPositionX(); 46 local imagey = self._imgSpr:getPositionY(); 47 48 imagex = imagex - self._speedx 49 imagey = imagey + self._speedy 50 51 self._imgSpr:pos(imagex, imagey) 52 53 end 54 55 return Bullet
MainScene.lua
local MainScene = class("MainScene", function() return display.newScene("MainScene") end) ClassBullet = require("app/object/Bullet") -- require相当于include intersectLine = {left = display.c_left, right = display.c_right , top = display.c_top, bottom = display.c_bottom} function MainScene:ctor() local layer = display.newLayer() layer:setTouchEnabled(true) --响应touch事件 layer:addNodeEventListener(cc.NODE_TOUCH_EVENT, --添加监听器 function(event) return self:onTouch(event.name, event.x, event.y, event.prevX, event.prevY) end ) layer:setTouchSwallowEnabled(false) self:addChild(layer) self._imgBack = display.newSprite("back.jpg") --添加背景图片 self._imgBack:setAnchorPoint(ccp(0,0)) self:addChild(self._imgBack) self._listBullet = {} --bullet table self._scheduler = require("framework.scheduler") --事件调度器 与update搭配使用 self._scheduler.scheduleGlobal(handler(self, self.update), 1/60) print(intersectLine.left,intersectLine.right) end function MainScene:update() for i,bullet in ipairs(self._listBullet) do --对listBullet表中的所有对象分别调用其update bullet:update() local bulletx = bullet:getPositionX() local bullety = bullet:getPositionY() print(bulletx,bullety) p = CCPoint(bulletx, bullety) ifHit = hitR2P(intersectLine, p) if ifHit == true then table.remove(self._listBullet, i) self:removeChild(bullet) print("delete") end end end TouchEventString = TouchEventString or {} --------鼠标事件名称 TouchEventString.began = "began" TouchEventString.moved = "moved" TouchEventString.ended = "ended" TouchEventString.canceled = "canceled" function MainScene:onTouch(name,x,y) if name == TouchEventString.began then local bullet = ClassBullet.new() --bullet实例 bullet:init(x,y) --init bullet self:addChild(bullet) --把bullet这个node添加到父节点中 table.insert(self._listBullet, bullet) --1开始 --把listBullet中对象insert到表中 end return true end function hitR2R(rect1,rect2) if rect1 and rect2 then if rect1.right > rect2.left and rect1.left < rect2.right and rect1.top > rect2.bottom and rect1.bottom < rect2.top then return true end end return false end function hitR2P(rect,pos) if pos.x <= rect.left or pos.x >= rect.right or pos.y <= rect.bottom or pos.y >= rect.top then return true end return false end return MainScene
此版代码可以实现基本的旋转和发射功能,但是并不能有效的remove飞出边界的bullet。
此处原因是对于Bullet的操作要注意不要直接操作class中的子节点,要以整个class为一个对象,在bullet层面上操作。
如此处update过程中
local imagex = self._imgSpr:getPositionX(); local imagey = self._imgSpr:getPositionY();
操作的是self._imgSpr这个精灵类,并非是bullet的position发生变化。所以在MainScene的update方法中
local bulletx = bullet:getPositionX() local bullety = bullet:getPositionY()
print(bulletx,bullety) 得到的数总是0.
修改方法:
self._imgSpr: 改成 self:
注意self. 和self:的区别。
心得:
在平时写代码的过程中要有意识的封装一些常用的函数。函数的复用性还是很高的。可以自己做一个functions.lua的文件。然后所有的通用函数都放这里,把这个文件require一下,就可以直接用里面的函数了。
出错的地方多写一些print帮助查错也是很有帮助的。
CCNode里的这些方法 setPosition,setScale,setRotation 等等这类的方法,只要不重新set,这些值是不会变的,有些不需要变的值,不用每次update都去set,比如角度如果定好了不变,就不需要每次都去set了。
另外。因为lua的特性。比如CCNode里有一个叫 aaa 函数,而你继承CCNode的时候,自己做了一个 self.aaa的变量。这样的话,父类的aaa函数就会失效了。。
所以我建议大家把类成员变量做一些特殊标记。比如我一般都会用 self._aaa
正确代码附录:
1 local Bullet = class("Bullet", function() 2 return display.newNode() 3 end) 4 5 speed = 20 6 7 function Bullet:ctor() --构造函数 8 --bullet父对象是node 这里把sprite对象添加到node上 9 self._imgSpr = display.newSprite("img1.png") --添加bullet图片 10 self._imgSpr:pos(300,0) 11 self._imgSpr:scale(0.5) 12 self:addChild(self._imgSpr) 13 14 self._speedx = nil 15 self._speedy = nil 16 17 end 18 19 function Bullet:init( x,y ) 20 local mousex = x --bullet init传值 不推荐用构造函数传值 speed在这里计算出来后来直接调用即可 21 local mousey = y 22 local imagex = 300 23 local imagey = 0 24 25 local distance = math.sqrt((mousex - imagex)*(mousex - imagex)+(mousey - imagey)*(mousey - imagey)) 26 local degree = math.deg(math.asin((y - imagey)/distance)) 27 if(mousex < imagex) then 28 degree = 180 - degree 29 end 30 degree = 180 - degree 31 32 print(degree) 33 self._imgSpr:setRotation(degree) 34 35 self._speedx = speed*math.cos(math.rad(degree)) 36 self._speedy = speed*math.sin(math.rad(degree)) 37 38 print(self._speedx) 39 40 41 end 42 43 function Bullet:update() --总函数的update调用每个子弹的update 44 45 46 local imagex = self:getPositionX(); --只修改了Bullet的update函数 47 local imagey = self:getPositionY(); 48 49 50 imagex = imagex - self._speedx 51 imagey = imagey + self._speedy 52 53 self:pos(imagex, imagey) 54 55 end 56 57 return Bullet