I am currently developing a game and have a question regarding dragging sprites. I am fairly confident with how to use the touch events to drag a sprite according to the touch x,y coordinates, however I need to be able to constrain the possible motion of the sprite to a fixed path. More specifically I am looking to implement game mechanics in which the user can drag a sprite, but only in a circular motion (like turning a wheel). Is anyone aware of how I might implement this? Thanks for any information you can provide.
When you drag your finger on the display it just increments/decrements an angle variable (from 0 to 360). It then uses that angle to draw the ball at the angle and radius from the balls origin (if that makes sense) ;)
local touchX -- where the display was last touched
local ball = Bitmap.new( Texture.new("ball.png")) ball:setAnchorPoint(0.5, 0.5) ball.angle =0-- current angle ball.radii ={x =80, y =80}-- separate values so we can have ellipses (not just circles) ball.origin ={x =160, y =240}-- origin on screen ball.position ={x =0, y =0} stage:addChild(ball)
function ball:update()-- update balls position on screen localcos, sin, degToRad =math.cos, math.sin, math.pi/180
local a, o, r, p = self.angle, self.origin, self.radii, self.position
local x = r.x *sin(a * degToRad) + o.x -- calculate new position local y = -r.y *cos(a * degToRad) + o.y
self:setPosition(x, y)-- update on display
p.x, p.y = x, y end
localfunction onTouch(e)-- handle touch e:stopPropagation() touchX = e.touch.x -- only need to save x touch position end
localfunction onDrag(e)-- handle drag e:stopPropagation() local tX = e.touch.x local dX = touchX - tX -- how much we moved our finger since last time touchX = tX
ball.angle =(ball.angle - dX)%360-- update ball ball:update() end
perhaps it would be even more intuitive if you'd need to rotate your finger around the center of the wheel. for this you can check the angle defined by these 3 points: where touch begins, the center of the wheel and where touch move is currently registered. and then simply rotate your wheel with the same angle.
@keszegh I thought @augustino_fp wanted something you just dragged, not rotated. I think rotation would be pretty easy also, it's just a matter of determining what angle your finger is inside the circle in relation to the center if the circle, hmm.
So I thought about it a bit more and made another example. there are now two classes, Dial and Ball.
The dial is just a simple dial that you can twirl about as @keszegh suggested. It just uses setRotation() to do that but shows you how to find the touch angle inside a circle at least.
The Ball class is a little more complex and a ball can be either a "drag" ball which behaves like the first example, or a "dial" ball which behaves like @keszegh originally meant (I hope)
The code isn't too commented so yell out if you don't get anything in there :)
Thank you both for your answers! I am currently at work but will take a detailed look at all these when I can. I may not have explained myself properly but essentially I am moving angular blocks around in a circle, so I wouldn't be rotating the sprite itself, but rather rotating/dragging it around a fixed path at a certain radius from the "origin" of the circle, if that makes sense.
@augustino_fp if you will be dragging these blocks using a left/right drag of your finger on the device then the first example does that. If you want to rotate the block as it moves in it's circular path then change the update function to...
function ball:update()-- update balls position on screen localcos, sin, degToRad =math.cos, math.sin, math.pi/180
local a, o, r, p = self.angle, self.origin, self.radii, self.position
local x = r.x *sin(a * degToRad) + o.x -- calculate new position local y = -r.y *cos(a * degToRad) + o.y