Rotating the "world" around a character?

Hi guys,

So lets say I have a ship (the player) which is facing north (ie pointing vertically at the top of the screen) in a top down view of the game world, as is the case in space invaders/asteroids etc. This ship in turn is controlled by a wheel. When the wheel is spun the ship turns.

Here is where I make it complicated. Instead of the ship itself turning I want the rest of the world (and its objects) to turn around the ship, so it always continues to face north. The math involved in this is confusing me. I tried inserting world objects into a display group and rotating it the opposite direction which the ship would be turning (if it could turn). This is fine until the physics objects within this display group start moving because the coordinate system rotates along with the whole group.

If someone could offer some help or point me towards a tutorial or something it would be great. I thought I saw a tutorial with a car racing around a track but I cant find it. Although I think the car just turned and the track stayed static. meh.

Any help would be much appreciated! :slight_smile:

Hi Graham,

I’m not aware of a module that features this. If your “world” is potentially an infinite size, with the ship going all over, then the math to handle the rotation will really depend on what you need to do.

I can comment on the general usage, however. Your approach of rotating the physics world (in a display group) is fine, except that you can NOT rotate the world group independently of the ship’s group, or collisions will not function properly. To solve this, you’ll basically need to rotate/move the ship as well (basically move/rotate ALL groups) then update the ship’s rotation/position in a Runtime loop, so that it stays centered and pointing north. Not sure that makes sense or not… I can provide a better description if you need.

Best regards,

Brent Sorrentino

So basically what you are saying is to have all objects in the same group, including my ship. Rotate this group with regards to the wheel rotation. Then once this rotation in complete; reset the ships position to screen centered and facing north, correct?

That makes sense I think, I’ll give it a shot and report back!

Yep, exactly so! A useful method for this is the “localToContent()” function. This inspects the local coordinates of the object, i.e. -810,-5623 or whatever, and then maps that to the content area coordinates, so you can easily reposition the object somewhere in the screen content area.

http://docs.coronalabs.com/api/type/DisplayObject/localToContent.html

[lua]

local shipLocalX, shipLocalY = ship:localToContent( 0,0 )

[/lua]

Ok so thats working fine. The group is rotating and the ship is resetting. Now I want to move objects, should I move them individually within the “world” group and leave that group centered on the player ship? and if so what is the math involved?

I obviously need to calculate the x and y components to plug into:

Body:setLinearVelocity( xVelocity, yVelocity )

using the current rotation of the world group to take into account direction. Ive tried this but its confusing me a bit. Here is what I was using originally:

local angle = math.rad(physics.world.rotation%360) local xComp = math.cos(angle)\*speed  -- the x component local yComp = math.sin(angle)\*speed   -- the y component      object:setLinearVelocity(-xComp,-yComp)

but it obviously doesnt cut it anymore

Hi Graham,

If you move the objects by physical means, they should update automatically (direction) when you rotate the world they’re contained in. Is this not happening for you? I would think, if this is an Asteroids type of world, the objects should just keep moving in their given direction no matter the rotation of the “camera”.

Brent

I would think, if this is an Asteroids type of world, the objects should just keep moving in their given direction no matter the rotation of the “camera”.

But the objects are moving in relation to the coordinate system within the group they are contained it. This coordinate system rotates along with the group. 

So if for example there is an object directly to the north of the player and the player is moving at speed. As the player is locked to the center of the screen I just move the object towards the player instead ie the opposite direction of what the player would be travelling. Now, if I rotate the world group so the object is directly south of the player, the object should start moving away from the player, rather than continue moving towards him, which it is doing currently. So surely I have to alter the object velocity to take into account that the coordinate system has been rotated?

In my game, I have two separate groups, and the world rotates around the character. I have game group and level group. Not sure what the issue is? In the case of a ship, you can use either a pivot joint onto the center of the screen, and rotate everything around that, or you can use a runtime listener to keep it there. In a game I was making, I had coins, and everything else going on and that worked out fine. 

I was using physics editor, which worked fine, and not the native shapes, not sure if that has any bearing on the situation or not.

-Nick

this sort of setup has worked fine for me with physics:

physicsLayer = display.newGroup()

– add your game objects to that layer

– but do NOT adjust the x,y,scale,rotation of this layer

cameraLayer = display.newGroup()

cameraLayer:insert(physicsLayer)

– do whatever you want to this layer, for example:

cameraLayer.rotation = 45

cameraLayer.xScale = 0.5

cameraLayer.yScale = 0.5

cameraLayer.x = your_x_scroll_value

cameraLayer.y = your_y_scroll_value

if you then move your ship in native world coordinates (those that have the fixed axes of the physicsLayer) then you can keep it centered by asking “where do i need to position the camera layer such that the physics layer within ends up with the ship coordinates at screen center?”

it’s not immensely hard, but I’ll leave it as an exercise for the reader :smiley:  you’ll just need a tiny bit of trig since your camera is (potentially) rotated and (potentially) scaled when figuring out the backwards math of “moving layer to the ‘left’ equals moving camera to the ‘right’” since you’ll want to be doing that along the scaled/rotated camera axes

hth

If I rotate the cameraLayer its all fine with the display object but their physics bodies do not rotate with them, this is a known limitation, and obviously isnt much good to me since I need the physics shapes lined up with the images of the display objects. Was this taken into account in your explanation? If so Im just finding it hard to figure out how to do what you said.

Is that statement based on the debug or hybrid draw mode?  If so, then you might need to check again.  Don’t expect physics draw modes to work, but that’s just a corona physics rendering quirk – if implemented correctly, physics WILL still properly “see” the world where you see it, despite what hybrid/debug (incorrectly) show.

I’d suggest building a tiny skeleton test app to play with - build some exterior walls to contain everything and a couple dozen simple rects to fall down, bounce off each other, settle on bottom… but no tweaks to the camera layer yet, just to make sure it all works as is.  Then, it’s a simple matter to test the camera layer by rotating it 45 degrees, and physics will continue to operate exactly as before, except your bottom “down” edge now appears oriented towards lower-right.  That is, the physics layer continue to operate as if it isn’t rotated, “down” to the physics engine is still it’s local +y, but the camera layer that contains it causes it to *appear* rotated on screen.

aside: if you want gravity to always act towards “camera down” instead of “world down” you can do that too, but you’ll have to manually revise gravity based on camera rotation, something like:

local theta = (90 - cameraLayer.rotation) / 180.0 * math.pi – correct for where “0” is versus “down”, inverted y-axis, and radians

physics:setGravity(9.8*math.cos(theta), 9.8*math.sin(theta))

hth

Hi Graham,

I’m not aware of a module that features this. If your “world” is potentially an infinite size, with the ship going all over, then the math to handle the rotation will really depend on what you need to do.

I can comment on the general usage, however. Your approach of rotating the physics world (in a display group) is fine, except that you can NOT rotate the world group independently of the ship’s group, or collisions will not function properly. To solve this, you’ll basically need to rotate/move the ship as well (basically move/rotate ALL groups) then update the ship’s rotation/position in a Runtime loop, so that it stays centered and pointing north. Not sure that makes sense or not… I can provide a better description if you need.

Best regards,

Brent Sorrentino

So basically what you are saying is to have all objects in the same group, including my ship. Rotate this group with regards to the wheel rotation. Then once this rotation in complete; reset the ships position to screen centered and facing north, correct?

That makes sense I think, I’ll give it a shot and report back!

Yep, exactly so! A useful method for this is the “localToContent()” function. This inspects the local coordinates of the object, i.e. -810,-5623 or whatever, and then maps that to the content area coordinates, so you can easily reposition the object somewhere in the screen content area.

http://docs.coronalabs.com/api/type/DisplayObject/localToContent.html

[lua]

local shipLocalX, shipLocalY = ship:localToContent( 0,0 )

[/lua]

Ok so thats working fine. The group is rotating and the ship is resetting. Now I want to move objects, should I move them individually within the “world” group and leave that group centered on the player ship? and if so what is the math involved?

I obviously need to calculate the x and y components to plug into:

Body:setLinearVelocity( xVelocity, yVelocity )

using the current rotation of the world group to take into account direction. Ive tried this but its confusing me a bit. Here is what I was using originally:

local angle = math.rad(physics.world.rotation%360) local xComp = math.cos(angle)\*speed  -- the x component local yComp = math.sin(angle)\*speed   -- the y component      object:setLinearVelocity(-xComp,-yComp)

but it obviously doesnt cut it anymore

Hi Graham,

If you move the objects by physical means, they should update automatically (direction) when you rotate the world they’re contained in. Is this not happening for you? I would think, if this is an Asteroids type of world, the objects should just keep moving in their given direction no matter the rotation of the “camera”.

Brent

I would think, if this is an Asteroids type of world, the objects should just keep moving in their given direction no matter the rotation of the “camera”.

But the objects are moving in relation to the coordinate system within the group they are contained it. This coordinate system rotates along with the group. 

So if for example there is an object directly to the north of the player and the player is moving at speed. As the player is locked to the center of the screen I just move the object towards the player instead ie the opposite direction of what the player would be travelling. Now, if I rotate the world group so the object is directly south of the player, the object should start moving away from the player, rather than continue moving towards him, which it is doing currently. So surely I have to alter the object velocity to take into account that the coordinate system has been rotated?

In my game, I have two separate groups, and the world rotates around the character. I have game group and level group. Not sure what the issue is? In the case of a ship, you can use either a pivot joint onto the center of the screen, and rotate everything around that, or you can use a runtime listener to keep it there. In a game I was making, I had coins, and everything else going on and that worked out fine. 

I was using physics editor, which worked fine, and not the native shapes, not sure if that has any bearing on the situation or not.

-Nick

this sort of setup has worked fine for me with physics:

physicsLayer = display.newGroup()

– add your game objects to that layer

– but do NOT adjust the x,y,scale,rotation of this layer

cameraLayer = display.newGroup()

cameraLayer:insert(physicsLayer)

– do whatever you want to this layer, for example:

cameraLayer.rotation = 45

cameraLayer.xScale = 0.5

cameraLayer.yScale = 0.5

cameraLayer.x = your_x_scroll_value

cameraLayer.y = your_y_scroll_value

if you then move your ship in native world coordinates (those that have the fixed axes of the physicsLayer) then you can keep it centered by asking “where do i need to position the camera layer such that the physics layer within ends up with the ship coordinates at screen center?”

it’s not immensely hard, but I’ll leave it as an exercise for the reader :smiley:  you’ll just need a tiny bit of trig since your camera is (potentially) rotated and (potentially) scaled when figuring out the backwards math of “moving layer to the ‘left’ equals moving camera to the ‘right’” since you’ll want to be doing that along the scaled/rotated camera axes

hth

If I rotate the cameraLayer its all fine with the display object but their physics bodies do not rotate with them, this is a known limitation, and obviously isnt much good to me since I need the physics shapes lined up with the images of the display objects. Was this taken into account in your explanation? If so Im just finding it hard to figure out how to do what you said.