I am working on a basic 2D game from an overhead/fake isometric perspective. Arrow keys move the camera left/right/up/down. The trouble occurs when I tried to add rotation.

I want the player to be able to rotate the camera (or map?) around the camera's center. The sprite positions should move during the rotation, but the sprite graphics should not rotate. For example, the sprites will always point "up" even as their position rotates around the screen.

I thought this was would be easy. Just keep track of the X, Y, and rotation of the camera. However, I am having some issues. Here is a snippet of my code (Go with the Pixel 2d library):

if win.Pressed(pixelgl.Key1) {
    camRot += camRotSpeed * dt
if win.Pressed(pixelgl.KeyLeft) {
    camX += camSpeed * dt
// similar for other key presses...

// Draw objects
for i, entity := range entities {
    sin := math.Sin(camRot)
    cos := math.Cos(camRot)
    adjustedCamX := camX*cos - camY*sin
    adjustedCamY := camX*sin + camY*cos
    adjustedMatrix := matrices[i].Moved(pixel.V(camX, camY)).Moved(pixel.V(adjustedCamX, adjustedCamY))
    entity.Draw(win, adjustedMatrix)

There are two issues: (1) after rotating, using the arrow keys now moves the camera at an angle instead of up/down/left/right and (2) I do not know how to rotate around the screen's center rather than whatever the current orientation is (0,0 in the bottom left?).

Note: The Pixel library makes use of transformation matrices rather than pure coordinates. At first I thought this was good (I can just do a rotation on the entire screen!) but then the graphics rotate as well. As such, I just try to emulate using pure coordinates and ignore the matrix (see the line with adjustedMatrix, the matrices[i] is just that entities' X Y position).

An example of what I am trying to achieve can be seen in the first few seconds of this video


Now that you've disconnected the Modelview/Projection coordinates from the World coordinates, you have to put the camera rotation back when you move the character (to have them move relative to the camera instead of the world).

This is accomplished by extending your movement from:

if win.Pressed(pixelgl.KeyLeft) { camX += camSpeed * dt } to
if win.Pressed(pixelgl.KeyLeft) { camX += camSpeed * dt * cos(camRot) camY += camSpeed * dt * sin(camRot) }

The up/down will swap which cos/sin is used for x/y.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.