Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Sprite rotates but it is not always following direction it faces unless speed is fast?! — Gideros Forum

Sprite rotates but it is not always following direction it faces unless speed is fast?!

Seb7Seb7 Member
edited April 2014 in Game & application design
I have a sprite that is moving right and starts turning/rotating when on MOUSE_DOWN event. ENTER_FRAME then keeps turning and rotating sprite until we lift finger (MOUSE_UP). The sprite should travel in a direction it is facing. I have no box2d,just normal sprites (movieclip) and bitmaps.

two questions:

1. Is this method ok (wait for MOUSE_DOWN to set rotation flag, then rotate on ENTER_FRAME and set a "stop" flag for sprite to stop rotating on MOUSE_UP ) for when we want to *do something as long as someone keeps their finger pressed on screen" . It works but I am not sure if this is ok method.

2. The problem I have is that when the speed of sprite is slow then when I press the screen the sprite starts rotating BUT it still moves in the same direction until it reaches certain angle. Any idea why is that? If the speed is faster then the rotation and direction seems to be much more synchronized. I am guessing it is something with math (cos,sin etc) calculations? So it looks like when speed is high that the sprite changes direction in small angles (eg 1,2,3,4,5,..) so rotation and direction appear synchronized. But when sprite moves slow then it changes direction in "jumps" (eg only when it reaches angles like 5,10,15,...) but rotation remains smooth so it looks ugly - sprite has slightly rotated but still keeps moving in previous direction.

I am using standard rotation calculation that was recommended on this forum and is found on many forums on rotating/sprites following direction.

Here is the relevant code, modified so it wont be too much to read.

in Player:init() I call self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)

Below code is onenterframe.

self.turn is 0 in the beginning and on MOUSE_UP event so sprite stops turning. On MOUSE_DOWN we call Player:move() so self.angle will increase by 1 on every frame. Self.speed is just how fast sprite is moving.

Any idea why sprite rotation AND direction appear synchronized when the speed is high (eg 5 and up) but not when speed is low (1).
function Player:onEnterFrame(event)
if (self.angle > 360) then self.angle = 0 end
self.angle = self.angle + self.turn
 
	local cx, cy = self:getX() ,self:getY()   -- current x, y pos
	local xo,yo     					-- x, y offset
	self.speed = self.speed or 1    		-- movement speed / distance to move
	local Radtheta = self.angle * math.pi/180
 
	xo = math.cos(Radtheta) * self.speed 
	yo = math.sin(Radtheta) * self.speed 
	cx = cx + xo
	cy = cy + yo
	self:setRotation(self.angle)
	self:setPosition(cx,cy)
 
end
 
function Player:move()
self.turn = 1 --this is a flag 
end
 
function Player:stay()
	self.turn = 0
	self.mc1:gotoAndPlay(1)
end

Comments

  • Seb7Seb7 Member
    btw, I thought we highlight lua code with pre tag. Has this changed? How to display lua code in colors here?
  • ar2rsawseenar2rsawseen Maintainer
    About highlight:
    http://members.giderosmobile.com/knowledgebase.php?action=displayarticle&id=41

    1) the method is completely ok and probably the best one there is :)

    2) will need to play with it and will be right back ;)
  • ar2rsawseenar2rsawseen Maintainer
    edited April 2014
    I don't know but it looks ok for me even with self.speed = 1
    Looks a lot like Roomba :D
    Player = Core.class(Sprite)
     
    function Player:init()
    	local bmp = Bitmap.new(Texture.new("ball.png", true))
    	bmp:setAnchorPoint(0.5, 0.5)
    	self:addChild(bmp)
    	self.angle = 0
    	self.turn = 0 
    	self:setPosition(100, 100)
    	self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
    	self:addEventListener(Event.MOUSE_DOWN, self.move, self)
    	self:addEventListener(Event.MOUSE_UP, self.stay, self)
    end
     
    function Player:onEnterFrame(event)
    if (self.angle > 360) then self.angle = 0 end
    self.angle = self.angle + self.turn
     
    	local cx, cy = self:getX() ,self:getY()   -- current x, y pos
    	local xo,yo     					-- x, y offset
    	self.speed = self.speed or 1    		-- movement speed / distance to move
    	local Radtheta = self.angle * math.pi/180
     
    	xo = math.cos(Radtheta) * self.speed 
    	yo = math.sin(Radtheta) * self.speed 
    	cx = cx + xo
    	cy = cy + yo
    	self:setRotation(self.angle)
    	self:setPosition(cx,cy)
     
    end
     
    function Player:move()
    	self.turn = 1 --this is a flag 
    end
     
    function Player:stay()
    	self.turn = 0
    end
     
    stage:addChild(Player.new())
    And here is the result:
    http://www.screenr.com/embed/X2dN
  • Seb7Seb7 Member
    edited April 2014
    Hi ar2rsawseen . First, thank yo for taking the time and test it, you are extremely helpful! I tried your example and it works perfectly :)

    Second, it now seems that the problem is somewhere completely different than I though. Calculations are ok, the problem is somewhere with sprite or maybe setting anchorpoint of sprite (I am using your gideromadeeasy lua file).

    Please replace your init code with this one (I have 3 PNGs but I replaced it with one ball.png so no need for 3 pics):
    function Player:init()
     
    	self.velocity = 0
    	self.angle = 0
    	self.turn = 0 -- for how much the angle will change
    	self.speed = 1	
    		self.mc1 = MovieClip.new{
    		{1, 20, Bitmap.new(Texture.new("ball.png")),true},
    		{20, 40, Bitmap.new(Texture.new("ball.png")),true},
    		{40, 60, Bitmap.new(Texture.new("ball.png"),true)},
    		}
    		-- Set looping of mc1
    	self.mc1:setGotoAction(60, 1)
     
    	self:addChild(self.mc1)
    	self.mc1:play()
    	self.mc1:setAnchorPoint(0.5,0.5)
    	self.mc1:setPosition(0, 0)
    	self.mc1:setRotation(90)
     
    	self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
    	self:addEventListener(Event.MOUSE_DOWN, self.move, self)
    	self:addEventListener(Event.MOUSE_UP, self.stay, self)
    end
    and the problem is as I described it. Funny thing, if you set self.mc1:setPosition(0, 0) to maybe 0,50 then the sprite rotates even more weirdly! There seems to be some problem with incorrect anchor? It is set to 0.5,0.5 though.

    any idea why this might be? I would like my main character be a sprite ,not just bitmap, so I can do other manipulations, like animation etc.

    one more time thank you.

  • Seb7Seb7 Member
    edited April 2014
    ok, something is even weirder. I tried your code again that was working perfectly just before and I had the same problem like in my code!

    I finally figured it out: it is GiderosCodingEasy.lua that is causing the problem! Try adding GiderosCodingEasy.lua (just adding is enough!) to your example and you will get the same problem. This is so strange - is GiderosCodingEasy.lua overwritting soem function or something? Remove the file from the project and everything starts working in your example.

    I will test it a little more tommorow because I am not sure if it is only GiderosCodingEasy.lua or also something with sprites.

    Without GiderosCodingEasy I cant set the sprite anchor though :(


  • ar2rsawseenar2rsawseen Maintainer
    Accepted Answer
    Aha I see
    its all due to rounding for some reason.

    Basically if in GiderosCodingEasy you find the method:
    function Sprite:set(param, value)
    And comment out two roundings:
    -- in x branch
    --value = math.round(value)
     
    --and in y branch
    --value = math.round(value)
    it should work as expected

    I will have to reexamine the purpose and error of the roundings later
  • Seb7Seb7 Member
    edited April 2014
    I seem to always follow the same routine : enthusiastically try doing something with Gideros, get frustrated after hour of not figuring it out, do something else, come back to gideros after a week then repeat the same cycle. :(

    So I tried to continue making this game and the moment I moved the position of the sprite it didn't rotate around itself anymore but around x-100 or something like that for some reason - anchor point seems to stay behind the sprite:
    self.mc1:setPosition(100, 100)
    any idea why? anchor of the sprite is set to 0.5,0.5. - I only changed starting position of the sprite.

    I tried your solution here :
    http://giderosmobile.com/forum/discussion/3888/universal-spritesetanchorpoint0-5-0-5/p1
    but it produces the same result (maybe i'm doing it wrong?). I loaded 3 bitmaps then set this (the rest remains the same):
    	local bit1 = Bitmap.new(Texture.new("ball.png"))
    	local bit2 = Bitmap.new(Texture.new("ball.png"))
    	local bit3 = Bitmap.new(Texture.new("ball.png"))
    	-- set them in iddle, for anchoir point
    	bit1:setPosition(-bit1:getWidth()/2, -bit1:getHeight()/2)
    	bit2:setPosition(-bit2:getWidth()/2, -bit2:getHeight()/2)
    	bit3:setPosition(-bit3:getWidth()/2, -bit3:getHeight()/2)
     
    		self.mc1 = MovieClip.new{
    		{1, 20, bit1,true},
    		{20, 40, bit2,true},
    		{40, 60, bit3,true},
    		}
    removed giderosmadeeasy and sprite anchoring and it is the same or similar problem.

    any ideas? This also completely messes up TNT collision detection when checking collision with another sprite but I'm gonna leave this out for now,maybe this will automatically solve if I can solve this problem first. Thanks for any help.


  • ar2rsawseenar2rsawseen Maintainer
    How about not setting an anchor point to a sprite or movie clip, and instead simply doing this:
    local bit1 = Bitmap.new(Texture.new("ball.png"))
    local bit2 = Bitmap.new(Texture.new("ball.png"))
    local bit3 = Bitmap.new(Texture.new("ball.png"))
    -- setting anchorpoint here
    bit1:setAnchorPoints(0.5, 0.5)
    bit2:setAnchorPoints(0.5, 0.5)
    bit3:setAnchorPoints(0.5, 0.5)
    self.mc1 = MovieClip.new{
    	{1, 20, bit1,true},
    	{20, 40, bit2,true},
    	{40, 60, bit3,true},
    }
  • Seb7Seb7 Member
    edited April 2014
    I tried this but it had the same problem.

    However then I made a new project with only 1 file and it worked! I tried it again with giderosmadeeasy and setting anchorpoint to movieclip/sprite it also worked.

    So this means the problem is elsewhere.I have cut down the unnecessary code and the only problem I can think of lies in game.lua file/sprite that hold the player sprite. But why? I did not set any anchor or anything in the game file. Here is my game file:
    Game = Core.class(Sprite)
     
    function Game:init()
     
    application:setBackgroundColor(0x99CDFF);
     
    self.player = Player.new()
    self:addChild(self.player)
     
    --create timer
    self:addEventListener(Event.MOUSE_UP, self.onMouseRelease, self)
    	self:addEventListener(Event.MOUSE_DOWN, self.onMouseTouch, self)
    end
     
    function Game:onMouseTouch(event)
    self.player:move()
    end
     
    function Game:onMouseRelease(event)
    	self.player:stay()
    end
    I dont see anything there that could mess up anchor point of child player sprite. I also have a main.lua file but there I only load scene manager and change scene to "Game".

    So if I have only player sprite in main.lua and run it then everything works. But when I put player in player.lua and then make game.lua and call player from there then this problem happens. In short, sprite game holds sprite player and when I set position of player then the anchorpoint doesnt move with player.

    I have read some forum posts here about child sprites and anchor points but I don't really understand it how this applies to my case. Should I set rotate my Game sprite? But that would make no sense, game is just a holder for all sprites.

  • Seb7Seb7 Member
    edited April 2014
    ok, I just constructed everything from the start (basically a copy of project that doesnt work) - new project, added scenemanager, easing, player, game and main lua files and it works! What gives.. this is so bizarre. I have few other files like config and button but this is too weird. I will investigate and report here..
  • Seb7Seb7 Member
    edited April 2014
    dammit, I finally figure it out in case anyone will have the same problem (I am now using giderosaeasy again, not your last solution (setting acnhors of bitmaps).

    BTW, is setting bitmap anchorpoints better solution than using giderosmadeeasy and setting sprite or movieclip anchorpoints?

    the problem was that I set the position of movieclip (which is wrong)
    self.mc1:setPosition(100, 100)
    instead of player sprite (correct)
    self:setPosition(100, 100)
    I still don't really understand why exactly is that - why does moving movieclip mess up anchorpoint of movieclip in this example:
    -- load bitmaps into bitmap variables
    	local bit1 = Bitmap.new(Texture.new("ball.png"))
    	local bit2 = Bitmap.new(Texture.new("ball.png"))
    	local bit3 = Bitmap.new(Texture.new("ball.png"))
     
    		self.mc1 = MovieClip.new{
    		{1, 20, bit1,true},
    		{20, 40, bit2,true},
    		{40, 60, bit3,true},
    		}
    		-- Set looping of mc1
    	self.mc1:setGotoAction(60, 1)
     	self:setPosition(100, 150)
    	self:addChild(self.mc1)
    	self.mc1:play()
    	self.mc1:setAnchorPoint(0.5,0.5)
    so self:setPosition(100, 150) is ok but self.mc1:setPosition(100, 150) messes everything up.



  • ar2rsawseenar2rsawseen Maintainer
    Most probably because the anchorpoint implementation is not perfect :)
    I have an idea of more elegant, efficient and easy way of anchor point implementation, but unfortunately not enough time to try, if it has any consequences or road blocks. Hopefully will dedicated an evening to try it out :)
Sign In or Register to comment.