Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
object class and box2d — Gideros Forum

object class and box2d

peach303peach303 Member
edited January 2013 in General questions

i'm new to gideros and not the best in programming. I have some trouble to add physics to a class object. "scene3" gets called in main.lua by sceneManager. In Scene3:init() i want to add a "Puck" with physics behavior. But it does not work... Can someone help? Here is the code:

-- scene3.lua: ---------------------------------------

function Scene3:init(t)
self.world = b2.World.new(0, 10, true)


self:addEventListener("enterBegin", self.onTransitionInBegin, self)
self:addEventListener("enterEnd", self.onTransitionInEnd, self)
self:addEventListener("exitBegin", self.onTransitionOutBegin, self)
self:addEventListener("exitEnd", self.onTransitionOutEnd, self)

self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)

function Scene3:onEnterFrame()
self.world:step(1/60, 8, 3)

for i = 1, self:getNumChildren() do
local sprite = self:getChildAt(i)
if sprite.body then
local body = sprite.body
local bodyX, bodyY = body:getPosition()
sprite:setPosition(bodyX, bodyY)
sprite:setRotation(body:getAngle() * 180 / math.pi)

-- puck.lua: -------------------------------------------

Puck = Core.class(Sprite)

function Puck:init(xp, yp)
local puckArrow = Bitmap.new(Texture.new("puckArrow.png"))
local puckHalo = Bitmap.new(Texture.new("puckHalo.png"))
local puckBody = Bitmap.new(Texture.new("puck.png"))

puckArrow:setAnchorPoint(0.5, 1)




local body = self.world:createBody{type = b2.DYNAMIC_BODY}
body:setPosition(xp, yp)
body:setAngle(self:getRotation() * math.pi/180)
local circle = b2.CircleShape.new(0, 0, 50)
local fixture = body:createFixture{shape = circle, density = 1.0, friction = 0, restitution = 0.2}
self.body = body
self.body.type = "Puck"

The Error Message is:
puck.lua:20: attempt to index field 'world' (a nil value)

Makes sense 'cause world is a local in scene3:init. But i dont know how to do it right...


  • zvardinzvardin Member
    Accepted Answer
    Puck doesn't have any way to access the world variable you set in the scene. One thing you can do is add a variable to your init function to pass the world in, like such:
    function Puck:init(xp,yp,world)
      -- your code here

    Also, when posting code to the forums, you can wrap it with a tag to make it more readable, see: http://www.giderosmobile.com/DevCenter/index.php/Forum_FAQ#How_can_I_highlight_my_Lua_code_in_the_forum_post.3F
  • ar2rsawseenar2rsawseen Maintainer
    edited January 2013 Accepted Answer
    For someone who is not the best in programming you are doing quite great ;)

    Well in this case world is the property of Scene3 class, and it would make sense to pass that instance to Puck class (because you may want to get some other properties form scene class, not only world). So here's what we can do:
    function Puck:init(level, xp, yp)
         --self the reference to scene
         self.level = level 
         --all your other code goes here
         --and when you want to create a body using world instance:
         local body = self.level.world:createBody{type = b2.DYNAMIC_BODY}
         --and the rest of your code
    Now inside Scene3 class, you just create a Puck like this:
    --passing reference to Scene3 which is self
    But there are also other options, you can pass self.world directly, or make world instance global, or have a global object with world instance as property, etc.

    P.S ninjajed by @zvardin just don't tell anyone :D
  • peach303peach303 Member
    edited January 2013
    It works! Thx a lot!

    @ ar2rsawseen: just seen your comment. Thx a for help!

    These answers came really fast
  • Now im stuck with another problem.
    function Puck:onTouchesBegin(event)
    	if self:hitTestPoint(event.x, event.y) then
    		self.focus = true
    attempt to index field 'puckArrow' (a nil value)

    It's because puckArrow is a local in Puck:init() right?? Maybe i do hard to understand this. But puckArrow is a child of Puck. Why does it not work. I tried to make puckArrow global:
    local puckArrow
    function Puck:init(xp, yp, world)
    	puckArrow = Bitmap.new(Texture.new("puckArrow.png"))
    --    and so on
    but same Error Message
  • Do i have to pass puckArrow trough with a parameter? Like before the box2d world?
  • Ok, having self.puckArrow in your Puck class is fine. In fact, when you change it to local then it cannot be accessed at all outside of the class.

    your event handler should like something like this:
    self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
    I'm not sure where your event listener is added, but you could add this in the constructor (init function) of your Puck class.
    function Puck:onTouchesBegin(event)
    	if self:hitTestPoint(event.x, event.y) then
    		self.focus = true
    function Puck:init(xp, yp, world)
           self.puckArrow = Bitmap.new(Texture.new("puckArrow.png")
           self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
           --and so on
  • With the way OOP works in Gideros, you can basically think of local variables in your file like a static/constant for that class. So, if you can have more than one Puck, you really want to create the image and store it in self.puckArrow like I show above because the local variable will not have a separate instance for each puck you make.
  • Great! Now it works. Thx again for your help.
Sign In or Register to comment.