@Mells yes I think you are right, since sprites are usually bind to bodies it would make sense to use tweening on body and not sprite.
On the other hand it might not make sense to tween the bodies at all, as in, they are there for a physics purpose, and tweening might only disrupt it. But of course there can always be specific cases.
But it's actually not getX/Y needed for tweening, but just general get/set methods
I'll talk about it with @atilim, but in the mean time, you can probably do something like this:
function b2.Body:set(param, val)local x, y = self:getPosition()if param =="x"then
x = val
self:setPosition(x, y)elseif param =="y"then
y = val
self:setPosition(x, y)elseif param =="rotation"then
self:setAngle(math.rad(val))endendfunction b2.Body:get(param)local x, y = self:getPosition()if param =="x"thenreturn x
elseif param =="y"thenreturn y
elseif param =="rotation"thenreturnmath.deg(self:getAngle())endendfunction b2.Body:getX()return self:get("x")endfunction b2.Body:getY()return self:get("y")endfunction b2.Body:setX(x)
self:set("x", x)endfunction b2.Body:setY(y)
self:set("y", y)end
By the way what is the correct way to require the libs in init.lua?
-- ------------------------- REQUIRE-- -----------------------require"box2d"--Required in Box2dEasy?require"Box2dEasy"require"GiderosCodingEasy"-- ------------------------- SET BOX2D WORLD-- -----------------------
world = b2.World.new(0, 9.8, true)function createWorld()local worldb2Draw = world:getDebug()-- ######## attempt to call method 'getDebug' (a nil value) ########return worldb2Draw
end
worldb2Draw = createWorld()
@atilim I was looking for a way to move my bodies on loop (ex moving platforms that go up and down, gravityScale = 0, etc), maybe this method to tween anything could be used to tween the linear velocity?
I will have to search more.
Edit : I required "Box2dEasy" before "box2d" and it worked. Should I remove the require("box2d") line?
Sets the specified property of this sprite instance by its name. These names are supported:
"x"
"y"
"rotation"
"scaleX"
"scaleY"
"scale"
"alpha"
"redMultiplier"
"greenMultiplier"
"blueMultiplier"
"alphaMultiplier"
I see that we have a getWidth/setWidth method available. Maybe it's worth adding "width" and "height" to the list of properties above?
"width"
"height"
@ar2rsawseen yes if everything (gravityScale, linearDamping, localCenter, mass) was accessible through body:set(param, value) we could for example tween the gravityScale for all objects on screen for a nice slow motion effect, etc...
@Mells yes tweening velocity probably makes much more sense
BTW there is no setWidth method, only getWidth as the width of Sprite is determined by its contents. Thus you can't adjust nor tween it. Same for height. But adjusting/tweening scale should provide similar effect.
And yes to your last comment, I'm adding this to GCE
Also I will fix so Box2dEasy would work if required after box2d. So it won't matter where you require box2d completely
I think I've found a way to provide any setter/getter (current or future) method through set/get function dynamically. And it even seems to work, I've updated the repo.
BTW @Mells your provided tween gives an awesome dancing box effect
@ar2rsawseen wow that was fast and it works great, thank you
What do you think about the following :
elseif param =="worldVector"thenlocal x, y =-- 0, 0?return self:getWorldVector(x, y)elseif param =="localPoint"thenlocal x, y =-- 0, 0?return self:getLocalPoint(x, y)elseif param =="localVector"thenlocal x, y =-- 0, 0?return self:getLocalVector(x, y)
I don't see how useful it would be (I've never used it and have no idea of a specific case where it is relevant) but that would make everything accessible from the get/set methods?
A modified version of the physics example provided with Gideros.
--[[
This code is MIT licensed, see <a href="http://www.opensource.org/licenses/mit-license.php" rel="nofollow">http://www.opensource.org/licenses/mit-license.php</a>
(C) 2010 - 2011 Gideros Mobile
]]require"box2d"require"Box2dEasy"require"GiderosCodingEasy"require"easing"
b2.setScale(20)local sky = Bitmap.new(Texture.new("sky.png"))
stage:addChild(sky)local grass = Bitmap.new(Texture.new("grass.png"))
grass:setY(400)
stage:addChild(grass)-- this table holds the dynamic bodies and their spriteslocal actors ={}-- create worldlocal world = b2.World.new(0, 9.8)-- this function creates a 80x80 physical box and adds it to the stagelocalfunction createBox(x, y, name)local body = world:createBody{type= b2.DYNAMIC_BODY, position ={x = x, y = y}}
body.name = name
local shape = b2.PolygonShape.new()
shape:setAsBox(40, 40)
body:createFixture{shape = shape, density =1, restitution =0.2, friction =0.3}local sprite = Bitmap.new(Texture.new("box.png"))
sprite:setAnchorPoint(0.5, 0.5)
stage:addChild(sprite)
actors[body]= sprite
-- -------------------------------- Tween Body Properties-- ------------------------------local tween1 = GTween.new(body, 1, {gravityScale =0}, {autoPlay =false})local tween2 = GTween.new(body, 1, {linearVelocityY =0}, {ease = easing.outQuintic, autoPlay =false})local tween3 = GTween.new(body, .3, {gravityScale =1}, {ease = easing.inExponential, autoPlay =false})
tween1.nextTween = tween2
tween2.nextTween = tween3
tween3.nextTween = tween1
tween1:setPaused(false)end-- create ground bodylocal ground = world:createBody({})
ground.name ="ground"local shape = b2.EdgeShape.new(-200, 400, 520, 400)
ground:createFixture({shape = shape, density =0})-- create two boxes
createBox(140, -30, "box1")
createBox(180, 300, "box2")localfunction onBeginContact(event)-- you can get the fixtures and bodies in this contact like:local fixtureA = event.fixtureA
local fixtureB = event.fixtureB
local bodyA = fixtureA:getBody()local bodyB = fixtureB:getBody()print("begin contact: "..bodyA.name.."<->"..bodyB.name)if bodyA.name =="box1"and bodyB.name =="box2"or
bodyB.name =="box1"and bodyA.name =="box2"then
GTween.pauseAll =true
bodyA:set("gravityScale", 1)
bodyB:set("gravityScale", 1)print("All tweens paused")endendlocalfunction onEndContact(event)-- you can get the fixtures and bodies in this contact like:local fixtureA = event.fixtureA
local fixtureB = event.fixtureB
local bodyA = fixtureA:getBody()local bodyB = fixtureB:getBody()--print("end contact: "..bodyA.name.."<->"..bodyB.name)endlocalfunction onPreSolve(event)-- you can get the fixtures and bodies in this contact like:local fixtureA = event.fixtureA
local fixtureB = event.fixtureB
local bodyA = fixtureA:getBody()local bodyB = fixtureB:getBody()--print("pre solve: "..bodyA.name.."<->"..bodyB.name)endlocalfunction onPostSolve(event)-- you can get the fixtures and bodies in this contact like:local fixtureA = event.fixtureA
local fixtureB = event.fixtureB
local bodyA = fixtureA:getBody()local bodyB = fixtureB:getBody()--print("post solve: "..bodyA.name.."<->"..bodyB.name)end-- register 4 physics events with the world object
world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
world:addEventListener(Event.END_CONTACT, onEndContact)
world:addEventListener(Event.PRE_SOLVE, onPreSolve)
world:addEventListener(Event.POST_SOLVE, onPostSolve)-- step the world and then update the position and rotation of spriteslocalfunction onEnterFrame()
world:step(1/60, 8, 3)for body,sprite inpairs(actors)do
sprite:setPosition(body:getPosition())
sprite:setRotation(body:getAngle()*180/math.pi)endend
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
About the other options, well both getter and setter is needed to tween something, and I actually don't know why most of them has only getters, maybe its a box2d limitation.
Btw how to scale a body? I have found that fixtures need to be destroyed and recreated. Are there alternatives? I would like to tween the scaling.
For example in the collision sample provided with Gideros (and modified above), how would you scale both the crate and it's body? That sounds trivial but I have no idea how to do it.
Well I don't know how efficient that is, but I've implemented a scaleBody property. Unfortunately you can't really scale x or y separate in most cases, thus there is only one scaleBody property.
I tried running @Mells example code above in a new GIderos project. I copied in the image assets from CollisionDetection. I downloaded GCE just now and added all of it's lua files to my new project. I then copied the code from above into a new main.lua file and ran. I get a stack overflow on Texture.__new(...). After looking at @ar2rsawseen code (line 1161 in GidereosCodingEasy.lua) I don't understand the intention. I totally understand the S/O error but I'm not follwoing why the recursive call to Texture.__new(...). Is it intended to call into a different module or namespace of some sort? (I'm aware that this could totally be a configuration error on my part but brand new to GCE and Gideros so bear with me.)
Ah wait, I see now. It's not a recursive call as there is only 1 "_" in the name caling to the original implementation I guess. I still don't understand why I get a S/O...
@ar2rsawseen Wha? Ok, I think I see it now. I'm bouncing between ZeroBrane and Gideros Studio and I didn't see anyway to change project properties in ZB but I am able to open the gproj file directly and add excludeFromExecution="1" to the file tag for GCE. I guess this is the way to do what you said. Here goes nothing...
Comments
On the other hand it might not make sense to tween the bodies at all, as in, they are there for a physics purpose, and tweening might only disrupt it. But of course there can always be specific cases.
But it's actually not getX/Y needed for tweening, but just general get/set methods
I'll talk about it with @atilim, but in the mean time, you can probably do something like this:
Likes: Mells
thank you!
By the way what is the correct way to require the libs in init.lua?
I will have to search more.
Edit : I required "Box2dEasy" before "box2d" and it worked. Should I remove the require("box2d") line?
Btw @atilim I see in the docs : I see that we have a getWidth/setWidth method available.
Maybe it's worth adding "width" and "height" to the list of properties above?
yes if everything (gravityScale, linearDamping, localCenter, mass) was accessible through body:set(param, value) we could for example tween the gravityScale for all objects on screen for a nice slow motion effect, etc...
BTW there is no setWidth method, only getWidth as the width of Sprite is determined by its contents. Thus you can't adjust nor tween it. Same for height.
But adjusting/tweening scale should provide similar effect.
And yes to your last comment, I'm adding this to GCE
Also I will fix so Box2dEasy would work if required after box2d. So it won't matter where you require box2d completely
BTW @Mells your provided tween gives an awesome dancing box effect
What do you think about the following :
For those who want to see how to use it :
A modified version of the physics example provided with Gideros.
About the other options, well both getter and setter is needed to tween something, and I actually don't know why most of them has only getters, maybe its a box2d limitation.
Btw how to scale a body? I have found that fixtures need to be destroyed and recreated.
Are there alternatives? I would like to tween the scaling.
For example in the collision sample provided with Gideros (and modified above), how would you scale both the crate and it's body?
That sounds trivial but I have no idea how to do it.
Unfortunately you can't really scale x or y separate in most cases, thus there is only one scaleBody property.
Updated the repo