2D Platformer fps/Independent- time based movement

Started by
5 comments, last by yewbie 11 years, 7 months ago
Hello, I am developing a 2d platform game with XNA and the starter kit plataformer of msdn.
The fact is that I could use the method of physics that brings the starter kit, (thought they were independent of fps) but to start porting the game to linux by monoGame and lowered fps (windows 63, Ubuntu / Kubuntu 57-59) I then checked that the player did not move properly.

The funny part is that the enemies are moving properly, it have only movement in the x axis.

Now being tested in windows disabling Vertical Sync by:


[source lang="csharp"] graphics.SynchronizeWithVerticalRetrace = false;
IsFixedTimeStep = false;[/source]


I leave the pieces of code relevant to them a look.
I believe that these method would be involved:

ApplyPhysics

[source lang="csharp"] public void ApplyPhysics(GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

Vector2 previousPosition = Position;

// Base velocity is a combination of horizontal movement control and
// acceleration downward due to gravity.
velocity.X += movement * MoveAcceleration * elapsed;
velocity.Y = MathHelper.Clamp(velocity.Y + GravityAcceleration * elapsed, -MaxFallSpeed, MaxFallSpeed);

velocity.Y = DoJump(velocity.Y, gameTime);


// Apply pseudo-drag horizontally.
if (IsOnGround)
velocity.X *= GroundDragFactor;
else
velocity.X *= GroundDragFactor;
//velocity.X *= AirDragFactor;

// Prevent the player from running faster than his top speed.
velocity.X = MathHelper.Clamp(velocity.X, -MaxMoveSpeed, MaxMoveSpeed);

// Apply velocity.
Position += velocity *elapsed;
Position = new Vector2((float)Math.Round(Position.X), (float)Math.Round(Position.Y));


// If the player is now colliding with the level, separate them.
HandleCollisions(gameTime);

// If the collision stopped us from moving, reset the velocity to zero.
if (Position.X == previousPosition.X)
velocity.X = 0;

if (Position.Y == previousPosition.Y)
{
velocity.Y = 0;
jumpTime = 0.0f;
}
}[/source]


I'm trying to simplify character movement putting it as the enemy,

[source lang="csharp"] Vector2 velocity = new Vector2((int)direction * MoveSpeed * elapsed, 0.0f);
position = position + velocity;[/source]

but then come the problems of collisions of the character in both axes (X, Y) ...

Attached to the post player and enemy classes of my project.

I would appreciate a little help from someone who is put in the subject, thanks in advance for your time and sorry for my bad English ;).
Advertisement
[s]Now, I could be wrong, but I am pretty sure that everything the GameTime class returns is going to be an int. To get the correct elapsed time, I would instead get the milliseconds and divide by 1000.[/s]

Edit:

I was mistaken! gameTime.ElapsedGameTime.TotalSeconds; does indeed return a floating point number. Will continue to look at the code to see if I can see anything!
Do you ApplyPhysics() every frame?

Also how are movement and MoveAcceleration defined?
ApplyPhysics () is executed in each Update() of Player.cs class which in turn runs on each Update() of Level.cs which in turn runs on each Update () of Game1.cs.
Yes, ApplyPhysics () is executed for every frame of the game.

movement keeps the direction in which the character moves (later is multiplied by moveAcceleration) -1 (left), 0 (not moving), 1 (right).
moveAcceleration keeps the acceleration, which later is multiplied by the number of seconds since the last frame.


[source lang="csharp"] /// <summary>
/// Current user movement input.
/// </summary>
private float movement;
public float Movement
{
set { movement = value; }
}

// For controling horizontal movement
private float MoveAcceleration = 15000.0f;
public float Move_Acceleration
{
get { return MoveAcceleration; }
}[/source]


You can download the two classes (Player, Enemy) from the link I put in the post (Attached Files) to see all the code.
I looked through your code and the only thing I am a little unsure of is:

float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

Does this return milliseconds as well or a just seconds?
IE: 0.0033 seconds or just 1 second, IE whats the resolution of this timer?

I would check the value of TotalSeconds on runtime on both platforms and see if you get similar results.

Also (correct me if I am wrong) gameTime.ElapsedGameTime.TotalSeconds is a XNA thing when you ported it over what did you change it to?
Note, the GameTime object stores the elapsed and total time as a TimeSpan:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.gametime_members.aspx
TimeSpan object store the units broken up in integer values:
http://msdn.microsoft.com/en-us/library/system.timespan.aspx
So the seconds property is a WHOLE number. It represents the current seconds as a part of the timespan. So a Timespan representing 2 mins, 30 secs, 123 milliseconds, would return 30 for seconds from the Seconds property... not 150.123.
If you want ALL the seconds as a fracitonal value you access the TimeSpan.TotalSeconds property, which is a double. There are also TotalMilliseconds, Minutes, Hours, and Days...
So the TotalSeconds property on the other hand would return 150.123 for the previously mentioned TimeSpan.

If you want ALL the seconds as a fracitonal value you access the TimeSpan.TotalSeconds property, which is a double. There are also TotalMilliseconds, Minutes, Hours, and Days...
So the TotalSeconds property on the other hand would return 150.123 for the previously mentioned TimeSpan.


I wasn't being authoritative with my response but thanks for the downvotes anyway. =)

You solved your problem by comparing the timing between two hardware platforms and determined that gameTime.ElapsedGameTime.TotalSeconds was running at a different speed because of the monitors refresh rate. (In case anyone else looks at this in the future)

This topic is closed to new replies.

Advertisement