Quick Cocos 旋转子弹的实现中我学到的

self 在lua中相当于java中的this

lua中的任何变量在没有赋值前, 都可以看做是nil

lua变量有3种,
成员变量: 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
时间: 2024-11-05 20:39:43

Quick Cocos 旋转子弹的实现中我学到的的相关文章

quick cocos 或者 Cocos2dx 项目下的Android.mk文件的学习

android.mk文件的作用:编译需要的cpp文件,生成.so动态库,供android端调用. 先上一个android.mk文件: 第一次创建项目,在Android平台编译时,都需要通过android.mk文件编译整个cocos2dx的库(第一次编译我们需要等待很长的时间.....). 首先知道$(call import-module,dir_name)的作用,然后顺着lib/proj.android目录继续找对应目录下的android.mk文件 类似于递归一样,把所有目录下的android.

提高中职数学活动课教学实践水平的具体措施

一.中职数学活动课的基本特征和主要意义分析 过去应试教育模式下,中职数学教学以考试成绩作为风向标,完全忽视了学生的主观能动性. 而活动课则是让学生通过参加实践活动,了解数学与实际生活之间的密切联系, 加深对所学数学知识的理解和认识,并学会用数学知识解决实际问题,从而全面提高学生的数学素质. 中职数学活动课将"要我学"变为"我要学",让学生在实际生活中自主发现问题,并将实际问题抽象为数学模型,并对其进行分析解释,从而解决实际问题. 在这个发现问题.解决问题的过程中巩固

【LeetCode】Find Minimum in Rotated Sorted Array 找到旋转后有序数组中的最小值

本文原作者:大便一箩筐 文章原地址:http://www.cnblogs.com/dbylk/p/4032570.html 原题: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). Find the minimum element. You may assume no duplicate exist

quick cocos UIListView之isItemInViewRect方法修正

功能描述:一个滚动列表,当列表可视区域上部有内容时则上部出现向上箭头提示,当列表可视区域下部有内容则下部出现向下箭头提示. 功能实现:应用cocos studio1.6制作界面,上面放置一个背景,一个滚动列表,然后程序加载解析这个界面的json文件,应用quick3.3final下的UIListView的方法isItemInViewRect进行检测第一条与最后一条是否在可视区域内. 问题:当界面加载进来,坐标设置0,0时,isItemInViewRect方法判断都没问题,但当把界面调整位置时,i

quick cocos naja

local scheduler = require(cc.PACKAGE_NAME .. ".scheduler") local MainScene = class("MainScene", function() return display.newScene("MainScene") end) -- 相当于C++中的构造函数 function MainScene:ctor() -- 将背景设置为白色,而且这个作为当前场景的层,以便以后实现触摸事

BUG::Cocos V3.2 渲染类中为什么出现同样的两次排序,难道有什么不同吗?手误??----小心开源代码中的陷阱

{ // Don't sort _queue0, it already comes sorted std::sort(std::begin(_queueNegZ), std::end(_queueNegZ), compareRenderCommand); std::sort(std::begin(_queuePosZ), std::end(_queuePosZ), compareRenderCommand); } // helper static bool compareRenderComman

quick cocos 的scheduler 定时器

cocos2dx原生lua对于定时器的写法: 1.每帧调用: void scheduleUpdateWithPriority(int priority) void scheduleUpdateWithPriorityLua (int nHandler,int priority) 2.指定调用间隔时间的: unsigned int scheduleScriptFunc (unsigned int nHandler, float fInterval, bool bPaused) 3.取消定时器事件

cocos creator 学习02 --js中import和require区别

在研究react和webpack的时候,经常看到在js文件中出现require,还有import,这两个都是为了JS模块化编程使用.CSS的是@import 1.ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量. Require是CommonJS的语法,CommonJS的模块是对象,输入时必须查找对象属性. // CommonJS模块 let { stat, exists, readFile } = require('fs'); // 等同于 let

quick cocos table

local scheduler = require(cc.PACKAGE_NAME .. ".scheduler") local MainScene = class("MainScene", function() return display.newScene("MainScene") end) function MainScene:ctor() --add Plist display.addSpriteFrames("bandit.p