I’m creating a 2D app that needs to show several individual images lied up in rows and columns . When the user touches on each of these images, I want to do a 3D spinning animation - flipping it in 360 degrees over Y axis. How can I do that without having to convert the entire app to do everything in 3D mode?
Thanks a lot @dave1707 . This is very helpful.
A simple way to do this without taking 3D perspective and the camera into account is to just reduce the sprite x scale to 0, then increase it to 1. I flip a sprite 180 degrees using tween animation in the example below. I also include a value that switches from +1 to -1 on each flip and is multiplied by the x scale value (so the sprite is drawn as flipped when needed), and a Boolean so that taps will be ignored while the object is flipping.
To spin 360 degrees, flip it twice using nested tweets or a tween sequence: reduce the sprite x scale to 0, then increase to 1, then reduce to 0, and finally increase to 1 again.
-- Flip Example
function setup()
object = {}
object.sprite = "Cargo Bot:Crate Green 2"
object.scaleX = 1 -- scale value from 0 to 1
object.flipX = -1 -- flip value is either +1 or -1 to draw flipped sprite
object.flipTime = 0.25 -- time for half a flip to occur
object.flipping = false -- is object in the process of flipping
print("Tap screen to flip object")
end
function draw()
background(0)
pushMatrix()
translate(WIDTH/2,HEIGHT/2)
scale(2) -- doubles size of object just to see it better
scale(object.scaleX,1)
sprite(object.sprite,0,0)
popMatrix()
end
function touched(touch)
if touch.state == ENDED then
if object.flipping == false then -- if object is not flipping
object.flipping = true -- set object to flipping
tween(object.flipTime,object,{scaleX = 0},{easing = tween.easing.cubicIn},function() tween(object.flipTime,object,{scaleX = 1 * object.flipX},{easing = tween.easing.cubicOut}, function() object.flipping = false end) object.flipX = object.flipX * -1 end)
end
end
end
@mindless Nice use of Tweens. I originally tried something like I show below, but I didn’t like the way the flipping looked. Your use of Tweens makes the flipping look better.
displayMode(FULLSCREEN)
function setup()
img=readImage("Cargo Bot:Crate Green 2")
w=img.width
h=img.height
size=5
v=-3
z=w
end
function draw()
background(0)
z=z+v
if z>w or z<-w then
v=v*-1
end
for x=1,3 do
for y=1,3 do
if x==2 and y==2 then
sprite("Cargo Bot:Crate Green 2",x*210,y*210,z*size,h*size)
else
sprite("Cargo Bot:Crate Green 2",x*210,y*210,w*size,h*size)
end
end
end
end
Do you have a 3D object of what you want to spin. Is it the same 3D object for each image or a different object for each image.
The only thing that I have for each image is the image object itself. Each image is different from one another. I don’t have any 3D object. My understanding is that an image is internally represented with mesh, which is used for 3D drawing. I was trying to do
rotate(deg, 0, 1, 0)
But it didn’t rotate the images, rather it clips off left and right side of the image. Then when I turn on 3D drawing by
perspective()
Then the rotate command works but now I have to draw everything (all images, not just the spinning one) in 3D coordinates (instead of just plain 2D x and y) which makes everything more complicated. Also, the images are not displayed the same size I intended them to be on screen anymore because there’s camera settings involved.
I think 2d mode is just a specific projection, but it’s still using the 3d under the hood. So potentially you can do it in 2d mode, but rather than using the spriting image stuff you need your image to be a mesh.
If that’s not doable, you can actually do both. So in your main method draw first the 2d stuff, then do your perspective() call, and then draw the ones that need to be 3d. which should work. I did something a long time ago using this approach so it would draw the hud in 2d mode, and some spaceship kind of stuff in 3d. Or you can do it the other way and perspective() and do 3d first, then ortho() and do the 2d stuff…
@tsukit Here’s something I threw together. It’s kind of a mess, but I didn’t want to spend more time on it if it’s not what you’re after. Tap a sprite to select, tap outside the sprites to deselect.
supportedOrientations(LANDSCAPE_ANY)
function setup()
xx,yy=0,0
w,h=42,42 -- sprite sizes are 42x42
tab={ "Cargo Bot:Crate Blue 1","Cargo Bot:Crate Blue 2","Cargo Bot:Crate Yellow 3",
"Cargo Bot:Crate Yellow 3","Cargo Bot:Crate Green 2","Cargo Bot:Crate Green 1",
"Cargo Bot:Crate Red 2","Cargo Bot:Crate Yellow 3","Cargo Bot:Crate Red 1"}
m=mesh()
m:addRect(0,0,w*4,h*4)
ang,ss=0,0
end
function draw()
background(0)
p=0
for x=1,3 do
for y=1,3 do
p=p+1
if p~=ss then
sprite(tab[p],x*w*2+WIDTH/2-w*4,y*h*2+HEIGHT/2-h*4,w*2,h*2)
end
end
end
if ss>0 then
if xx+yy>0 then
translate(-168*xx+168*2,168*yy-168*2)
end
perspective(90, WIDTH/HEIGHT)
camera(0,0,-800,0,0,0, 0,1,0)
rotate(ang,0,1,0)
m.texture=tab[ss]
ang=ang+10
m:draw()
end
end
function touched(t)
if t.state==BEGAN then
s,ss=0,0
xx,yy=0,0
for x=1,3 do
for y=1,3 do
s=s+1
if t.x>x*w*2+WIDTH/2-w*5 and t.x<x*w*2+WIDTH/2-w*3 and
t.y>y*h*2+HEIGHT/2-h*4-h and t.y<y*h*2+HEIGHT/2-h*4+h then
ss=s
xx=x
yy=y
end
end
end
end
end
Thanks a lot @spacemonkey.
@dave1707 that’s exactly what I need!. Really appreciated. If you could, can you explain a bit more on why we have
perspective(90, WIDTH/HEIGHT)
camera(0,0,-800,0,0,0, 0,1,0)
and
translate(-168xx+1682,168yy-1682)
Thanks so much again.
@tsukit The perspective command just sets the viewing angle for the camera. The camera command (x,y,z,x,y,z,x,y,z) sets where you’re viewing from (x,y,z) and where you’re looking (x,y,z) and which axis is up (x,y,z). See the documentation for more info. The translate command just moves the spinning sprite to the location of the sprite that was touched. A lot of the code was just tweeked to make things fit where they needed. When you modify the code for your use, a lot of the values will probable need changing.
@dave1707 thanks for the info. Sorry that I didn’t make myself clear. In particular, my questions are these:
perspective(90, WIDTH/HEIGHT)
Why do we choose 90 degree viewing, instead of the default 45 degree?
camera(0,0,-800,0,0,0, 0,1,0)
Why are the eye Z is set at -800? Why not -700, -500 or not some other numbers? I tried making this a parameter and I don’t see differences when setting to a different value. Is it -800 a magic number?
translate(-168xx+1682,168yy-1682)
Why do we need a different coordinate when drawing in 3D? Is this because of the camera command above? Also I notice that the higher/lower the Y is, the angle of the flipping image look increasingly distorted (as if you’re looking from under or above it).
Sorry if my questions sound ignorant. I’m not familiar with 3D stuff.
@tsukit A lot of the values I picked was because they worked OK. There wasn’t anything special for them. The -800 was used because I wanted to be far away from the spinning object. The closer you got to the image, the more it looked like you were viewing it from either side or above or below it. For translate, I needed to shift the spinning image far enough to fill the position of the tapped image. 3D and 2D doesn’t work together easily, at least with what I was trying to do. As I said above, if you try to use the code, you’ll have to tweak the values to get it to work with whatever you want to do.
Thanks, @dave1707. Tweens can be a little strange in that sometimes they don’t work as expected, so I’ve learned to nest them and/or use function calls to get them to do what I want. It can get a little ridiculous and hard to read, but it works. I figure why write code to animate when it’s already there?