Search code examples
actionscript-3game-physicsflashdevelopgravity

AS3/Flashdevelop - Controlling a 2D character to move around a planet with gravity


With a little help I have managed to create a 2D planet with working gravity that constantly pulls a character towards its center. The only problem now is that I am completely stumped on how to make it so the user is able to make this character traverse the planet as one would expect rather than the simple up/down/left/right we are used to in natural platformers.

It should be noted the planet being traversed will have platforms/layers to jump and fall onto, so the moving and jumping should be in relation to the center of the planet, where the center of the planet acts as "down" would in a traditional platformer (which is why I seem to think I need a complicated way to create this kind of natural movement).

I had the idea of recalculating a new left and right direction to move in every time position is changed but the logic I have to work out to achieve this is beyond my knowledge.

Is this the only way to go or should I try tackling the problem differently? I hope not because I don't think I'd be able to achieve this otherwise.

This is my current code showing how the gravity works, with a simple placeholder for movement that just allows the character to move up/down/left/right on the screen:

public function moveChar(event:Event):void
    {
            if (leftPressed)
            {
                character.x -= mainSpeed;
            }
            if (rightPressed)
            {
                character.x += mainSpeed;
            }
            if (upPressed)
            {
                character.y -= mainSpeed;
            }
            if (downPressed)
            {
                character.y += mainSpeed;
            }
        }

public function gravity():void
{
    //tan2(planet.y - player.y, planet.x - player.x)
    angle = Math.atan2((planet1.y + 2245) - (character.y+5), (planet1.x+2245) - (character.x+5));
    gravityX = Math.cos(angle) * gravitationalAcceleration;
    gravityY = Math.sin(angle) * gravitationalAcceleration;

    //distance = Math2.Pythagoras(planet1.x + 50, planet1.y + 50, character1.x + 5, character1.y + 5);
    distance = Math.sqrt((yDistance * yDistance) + (xDistance * xDistance));

    //Calculate the distance between the character and the planet in terms of x and y coordinate
    xDistance = (character.x + 5) - (planet1.x + 2245);//320 to 50
    yDistance = (character.y + 5) - (planet1.y + 2245);//320 to 50

    //Make sure this distance is a positive value
    if (xDistance < 0) {
        xDistance = -xDistance;
    }
    if (yDistance < 0) {
        yDistance = -yDistance;
    }

    //Update the current velocity before new velocity is calculated
    initialXVelocity = finalXVelocity;
    initialYVelocity = finalYVelocity;

    //Send the character into the correct direction
    character.x += gravityX;
    character.y += gravityY;

    //Basic collision detection of the surface, basic stop of gravity
    if (distance <= planet1Radius) {
    trace("hit!");

    if (planet1.x - 2180 < character.x - 5) { //320 to 50
        character.x -= gravityX*1.025;
    }
    else {
        character.x += gravityX*1.025;
    }
    if (planet1.y - 2180 < character.y - 5) { //320 to 50
        character.y -= gravityY*1.025;
    }
    else {
        character.y += gravityY*1.025;
    }
    } else {
    trace(" no hit!");
    }

}


Solution

  • One idea would be to cause the world (except for the player) to rotate around the planet center when you press left/right rather than moving the character.

    If you don't want to do that you can use raycasts as outlined in the answer here.