Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Click to Move and onEnterFrame Events — Gideros Forum

Click to Move and onEnterFrame Events

twisttaptwisttap Member
edited June 2012 in General questions
Hello,
I am having some difficulties to understand the general flow of onEnterFrame event at the moment and structure of Physics bodies. I look thru some examples and I am wondering if there is an easier way to create physics bodies. What I do now for a physics body with an image representation is:

Create a img representation
Create a physics body
create a fixture
and attach all of those together, which seems quite complicated. Am I missing something ?
 
-- Img representtion for physics body
local Player = Bitmap.new(Texture.new("man.png"))
Player:setAnchorPoint(0.5,0.5)
Player:setPosition(x,y)
 
-- Body itself
local body = self.world:createBody{type = b2.DYNAMIC_BODY}
body:setPosition(Player:getX(), Player:getY())
body:setAngle(Player:getRotation() * math.pi/180)
local poly = b2.PolygonShape.new()
 
-- Fixture
 
poly:setAsBox(Player:getWidth()/2, Player:getHeight()/2)	
local fixture = body:createFixture{shape=poly, density=1.0, friction=1.0, restitution=0.8}
Player.body = body
Player.body.type = "Player"
 
self:addChild(Player)
Another issue I am having is with onEnterFrame events, While I can do this very easily on AS3 or some other platform
here I can not say I am successful.

what I don't understand is do I need to move image bodies separated from physics bodies ?
Isn't there a way to attach those to each other so when I move a physics body or change something physics related
the image rep. also moves ?

And lastly can anyone show me an example of click-to-go example , can't find in examples folder.

Thanks

+1 -1 (+3 / -0 )Share on Facebook

Comments

  • I have this:

    local player = self:player(100,100) -- Creates player object at 100,100
    player:addEventListener(Event.MOUSE_DOWN, onMouseDown, player)

    function onMouseDown(self, event)
    print(event.x, event.y)
    print(self:getX())
    self:setX(event.x)
    end

    but setX does not work while, getX() works.
  • twisttaptwisttap Member
    edited June 2012
    Main.lua
     
    application:setOrientation(Application.LANDSCAPE_LEFT)
    require "box2d"
     
    scene = Core.class(Sprite)
     
    function scene:init()
    self.world = b2.World.new(0,10,true)
    local screenW = application:getContentWidth()
    local screenH = application:getContentHeight()
     
    self:wall(0,screenH/2,10,screenH)
    self:wall(screenW/2,0,screenW,10)
    self:wall(screenW,screenH/2,10,screenH)
    self:wall(screenW/2,screenH,screenW,10)
     
    local player = Player.new(100,100, self.world)
    local enemy = Player.new(200,100, self.world)
     
    -- Debug Draw
    local debugDraw = b2.DebugDraw.new()
    self.world:setDebugDraw(debugDraw)
    self:addChild(debugDraw)
     
     
    self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
     
    stage:addChild(player)
    stage:addChild(enemy)
     
    end
     
     
     
    function scene:wall(x,y,width,height)
    	local wall = Shape.new()
     
    	wall:beginPath()
     
    	wall:moveTo(-width/2,-height/2)
    	wall:lineTo(width/2, -height/2)
    	wall:lineTo(width/2, height/2)
    	wall:lineTo(-width/2, height/2)
    	wall:closePath()
    	wall:endPath()
    	wall:setPosition(x,y)
     
     
    	--create box2d physical object
    	local body = self.world:createBody{type = b2.STATIC_BODY}
    	body:setPosition(wall:getX(), wall:getY())
    	body:setAngle(wall:getRotation() * math.pi/180)
    	local poly = b2.PolygonShape.new()
    	poly:setAsBox(wall:getWidth()/2, wall:getHeight()/2)
    	local fixture = body:createFixture{shape = poly, density = 1.0, 
    	friction = 0.1, restitution = 0.8}
    	wall.body = body
    	wall.body.type = "wall"
     
    	--add to scene
    	self:addChild(wall)
     
    	--return created object
    	return wall
     
    end
     
     
     
    function scene:onEnterFrame() 
    	-- edit the step values if required. These are good defaults!
    	self.world:step(1/60, 8, 3)
    end
     
     
     
    local mainScene = scene.new()
    stage:addChild(mainScene)
    Player.lua
     
    Player = Core.class(Sprite)
     
    function Player:init(x,y,world)
     
    local Player = Bitmap.new(Texture.new("./man.png"))
    self:addChild(Player)
    Player:setAnchorPoint(0.5,0.5)
    Player:setPosition(x,y)
     
     
    local body = world:createBody{type = b2.DYNAMIC_BODY}
    body:setPosition(Player:getX(), Player:getY())
    body:setAngle(Player:getRotation() * math.pi/180)
     
     
    local poly = b2.PolygonShape.new()
    poly:setAsBox(Player:getWidth()/2, Player:getHeight()/2)
     
    local fixture = body:createFixture{shape=poly, density=1.0, friction=1.0, restitution=0.8}
    Player.body = body
    Player.body.type = "Player"
     
    self:addEventListener(Event.MOUSE_DOWN, self.onTouch)
    self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
     
     
    return Player
     
     
    end
     
     
    function Player:onEnterFrame(event) 
    	--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)
    		end
    	end
    end
     
     
    function Player:onTouch(event)
    --local x,y = self:getPosition()
    --print(self:getX())
    --print(self:getX())
     
    end
    Is this a good approach ? Passing physic worlds as variables, or is there an easy way for that (like AS3 root or _parent) and also what is wrong with the last part of the code that I can not set x & y of the player.


    Thanks
  • MikeHartMikeHart Guru
    edited June 2012
    Without running your code, it basically looks fine. I don't understand the "I can not set x& y" part? You have uncommented the world:step command which is need to calculate the physics. Can you attach the project with images to this post so we can have a looks at the running code?
    And lastly can anyone show me an example of click-to-go example , can't find in examples folder.
    The question is what you want to have. Control the movement via lua or via Box2D. That would be different approaches. With the first one you would need to update the physics body position and rotation and just use Box2D for collisions. The second one there you would need to calculate the angle and force you have to give your object so it moves into the right direction. But then you need to determine where you have to stop your object and check for it manually.
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    Here is why you can't change x and y.

    Because you are changing x and y coordinates of a sprite and sprite is attached to physical body, in your code:
    function Player:onEnterFrame(event) 
    	--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)
    		end
    	end
    end
    So sprite is going anywhere where physical body goes. Physical body is controlled by world.
    You set x coordinate for sprite and on next enterframe call it changes back where physical body was.

    So if you want to move an object, you should move it's physical body. Then sprite would follow it.

    Like this:
    function Player:onTouch(event)
    	self.body:setPosition(event.x, event.y)
    end
    About other question, well you can create methods, which create physical bodies, but in the end it all goes down to get representing image, create shape, create fixture, etc.

    And yes you need to hook up sprites/images to physical bodies, but I see, you already done that. :)

    And there is a global object as in AS, it's called stage. But using it would not be a best practice. It's better to choose the lesser possible scope to store variables, which in your case is scene class. So yes, I guess the way you handle variables now looks ok.
  • I am uploading the files so you guys maybe see what happens and tell me what to do.
    I am quite confused about using of self, it looks like the .this of AS3 but I think it is not.
    zip
    zip
    Gideros02.zip
    5K
  • ar2rsawseenar2rsawseen Maintainer
    Edited your project to make it work.

    Main difference is that I saved Player object, not as local object (which would be visible only inside init function), but as class property self.Player, so it would be accessible from all class methods.
    Then I rewrote definition of Touch handler, so it is a class method Player:onTouch(event), thus self.Player would be accessible from it.

    And the when adding touch event handler, I passed self parameter, to make it reference as a class, again so self.Player would be accessible from it.

    Here are some links for basic examples to create classes, uses properties in class methods, passing data to event handler and difference between . and :

    http://www.giderosmobile.com/forum/discussion/comment/6137
    http://www.giderosmobile.com/forum/discussion/926/how-to-pass-variables-through-event-listeners-039attempt-to-index-a-nil-value039
    http://www.giderosmobile.com/forum/discussion/comment/6033
    http://www.giderosmobile.com/forum/discussion/comment/1836

    ;)



    zip
    zip
    for_twisttap.zip
    6K

    Likes: twisttap

    +1 -1 (+1 / -0 )Share on Facebook
  • One more thing to ask, I am passing b2.world as a parameter to the Constructor as seen:
    function Player:init(x,y,world)
    is it possible to reach the world without passing it as a parameter ?
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    well there are other ways to do it, but for now yours seems better.

    You could define world as global variable, but it pollutes the scope and may lead to memory issues.

    You could create physical body inside scene class, after returning the instance and adding player to the scene. But this would only lead to writing more code and not reusing existing.

    You could use Sprite:getParent() method to get scene, where you added player and get world through that, but again it's a complex chain of commands and not much of a code is reused.

Sign In or Register to comment.