Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Point-Based gravity

This thread is locked; no one can reply to it. rss feed Print
Point-Based gravity
DuncanShine
Member #17,479
March 2020

i'm not sure if this is too complicated for allegro, but what i'm trying to achieve is a character being able to walk round a circle while remaining upright relative to the circle, and be able to jump up and down on it.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

F = MA

A point gravity well is just that. A point in space that attracts other matter. This means in technical terms that it creates a gravity vector. Gravity is an acceleration based on Mass and Distance. If you want gravity to be constant that is fine too.

First you need to know how to get the angle of a vector given two points. These two points will be the gravity center and the position of the center of mass of the player.

To get a vector from a start and end point simply subtract the components. The start point will be your character and the end point will be the center of gravity.

int dx = x2 - x1;
int dy = y2 - y1;
double dzsq = dx*dx + dy*dy;/// The square root of this is the distance between them.
double dz = sqrt(dzsq);

Now you have a positional vector. What you need is a force vector. First normalize the positional vector by multiplying it by the inverse of its magnitude.

double DX = dx/dz;
double DY = dy/dz;

Now DX and DY hold the normalized direction vector in the direction of the player to the gravity.

Define gravity, in terms of pixels per second squared.

double G = 9.6;

Gravity is our acceleration, and it is in the direction we just figured out.

All you need to do now is multiply this acceleration times the delta time to get the change in velocity. Velocity times the delta time is the delta position.

Then you have to consider collision detection, and jumping, and orientation.

Make sure you understand this much first.

gillius
Member #119
April 2000

If you are doing like a little planet type thing, and the planet is a perfect circle, you can probably treat the player as a single point, then clamp that point's distance from the center. The physics get a bit harder if the objects need "shape". If you go that far you might want to start looking at a physics engine. I think if the planet is irregularly shaped instead, it might be complicated to figure out if the player is "standing" on a surface or "sliding" down a "side" of something, if your objects are large relative to the planet.

Gillius
Gillius's Programming -- http://gillius.org/

DuncanShine
Member #17,479
March 2020

planets are perfectly round, no need to overcomplicate things!
However i did wonder about how i would do the orientation of the player relative to the planet that didnt make sense

Chris Katko
Member #1,881
January 2002
avatar

However i did wonder about how i would do the orientation of the player relative to the planet that didnt make sense

[90 degrees] plus [the angle from the center of the planet to the player].

To get that angle, use an angle formula.

double angle = atan2(y2 - y1, x2 - x1); //in radians

where x1,y1 are one point (say, the planet), and x2,y2 are the other point (say the player).

then you just rotate a bitmap relative to that angle using al_draw_rotated_bitmap() by plugging that angle into that function.

Since al_draw_rotated_bitmap is already in radians, you don't need to convert the angle to degrees first.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

DuncanShine
Member #17,479
March 2020

This all seems to make sense, but i can't figure out the collision detection for the objects. I've written something that's supposed to trigger a message when the character enters the circle/planet, but it's only working for certain parts of it and i don't know why

    float distance = sqrt(
      pow((x - playerX), 2) +
      pow((y - playerY), 2)
      );
    if (distance <= planetRadius + runningPlayerWidth) {
      isColliding = true;
      cout << "collision" << endl;
    }
    else {
      isColliding = false;
      cout << "no collision" << endl;
    }

picture attached of where it starts to collide

torhu
Member #2,727
September 2002
avatar

I've written something that's supposed to trigger a message when the character enters the circle/planet, but it's only working for certain parts of it and i don't know why

That code looks ok, but aren't you calculating the distance between the upper left corners of the player and planet bitmaps? Try calculating and using the distance between the center points of both instead. And compare to half the planet bitmap width plus somewhere in between half player width and height.

DuncanShine
Member #17,479
March 2020

good news on that front - i changed some x and y values and now it pretty accurately detects whether the player is in the circle, but it really starts to get screwy outside of it

torhu
Member #2,727
September 2002
avatar

Right, maybe you could post the new code?

DuncanShine
Member #17,479
March 2020

so i created some variables that are supposed to be the centre of the bottom of the character bitmap, here:

  int playerBottomX = playerX += (al_get_bitmap_width(idle) / 2);
  int playerBottomY = playerY += 64;

however, i checked and these values dont ever change, and if i put them in the while loop it goes crazy and continually changes them forever, so the collision detection breaks when i do this

[EDIT] nevermind i accidentally included an '=' after the addition and subtraction it works now.

My only problem now with regards to collisions is making the character actually collide, and not being able to move through the object. any pointers? (pun intended)

Go to: