# How do I make a jumping dolphin rotate realistically?

I want to program a dolphin that jumps and rotates like a real dolphin. Jumping is not the problem, but I don't know how to make the rotation. At the moment, my dolphin rotates a little weird. But I want that it rotates like a real dolphin does.

How can I improve the rotation?

public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D image, water;
float Gravity = 5.0F;
float Acceleration = 20.0F;
Vector2 Position = new Vector2(1200,720);
Vector2 Velocity;
float rotation = 0;
SpriteEffects flip;
Vector2 Speed = new Vector2(0, 0);

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 720;
}

protected override void Initialize()
{
base.Initialize();
}

{
spriteBatch = new SpriteBatch(GraphicsDevice);
flip = SpriteEffects.None;
}

protected override void Update(GameTime gameTime)
{
float VelocityX = 0f;
float VelocityY = 0f;

float time = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardState kbState = Keyboard.GetState();
if(kbState.IsKeyDown(Keys.Left))
{
rotation = 0;
flip = SpriteEffects.None;
VelocityX += -5f;
}

if(kbState.IsKeyDown(Keys.Right))
{
rotation = 0;
flip = SpriteEffects.FlipHorizontally;
VelocityX += 5f;
}

// jump if the dolphin is under water
if(Position.Y >= 670)
{
if (kbState.IsKeyDown(Keys.A))
{
if (flip == SpriteEffects.None)
{
rotation += 0.01f;
VelocityY += 40f;
}
else
{
rotation -= 0.01f;
VelocityY += 40f;
}
}
}
else
{
if (flip == SpriteEffects.None)
{
rotation -= 0.01f;
VelocityY += -10f;
}
else
{
rotation += 0.01f;
VelocityY += -10f;
}
}

float deltaY = 0;
float deltaX = 0;

deltaY = Gravity * (float)gameTime.ElapsedGameTime.TotalSeconds;

deltaX += VelocityX * (float)gameTime.ElapsedGameTime.TotalSeconds * Acceleration;
deltaY += -VelocityY * (float)gameTime.ElapsedGameTime.TotalSeconds * Acceleration;

Speed = new Vector2(Speed.X + deltaX, Speed.Y + deltaY);
Position += Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
Velocity.X = 0;

if (Position.Y + image.Height/2 > graphics.PreferredBackBufferHeight)
Position.Y = graphics.PreferredBackBufferHeight - image.Height/2;

base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(water, new Rectangle(0, graphics.PreferredBackBufferHeight -100, graphics.PreferredBackBufferWidth, 100), Color.White);
spriteBatch.Draw(image, Position, null, Color.White, rotation, new Vector2(image.Width / 2, image.Height / 2), 1, flip, 1);
spriteBatch.End();

base.Draw(gameTime);
}
}


The code now works almost perfectly. I introduced the bool variable direction and made some tests with the angle. Jumping works now as it should. But I couldn't change two things:

1)At the beginning(you can see it in the video), the dolphin always looks up. I want that it looks at the right side, if possible. I tried to change the rotation but it didn't worked.

2)The second thing is a little bit strange. If I change the direction from left to right or right to left, the dolphin is rotated in the wrong direction during a short moment. How can I fix that? I made a new video: http://www.myvideo.de/watch/8881567

    public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D image, water;
float Gravity = 5.0F;
float Acceleration = 20.0F;
Vector2 Position = new Vector2(1200,720);
Vector2 Velocity;
float rotation = 0;
SpriteEffects flip;
Vector2 Speed = new Vector2(0, 0);
bool direction = false;
Vector2 prevPos;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 720;
}

protected override void Initialize()
{
base.Initialize();
}

{
spriteBatch = new SpriteBatch(GraphicsDevice);
flip = SpriteEffects.None;
}

protected override void Update(GameTime gameTime)
{
float VelocityX = 0f;
float VelocityY = 0f;

float time = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardState kbState = Keyboard.GetState();
if(kbState.IsKeyDown(Keys.Left))
{
flip = SpriteEffects.FlipHorizontally;
VelocityX += -5f;
direction = false;
}

if(kbState.IsKeyDown(Keys.Right))
{
flip = SpriteEffects.None;
VelocityX += 5f;
direction = true;
}

if (direction == false)
{
rotation = -((float)Math.Atan2(Position.X - prevPos.X, Position.Y - prevPos.Y) + MathHelper.PiOver2);
prevPos = Position;
}
if (direction == true)
{
rotation = -((float)Math.Atan2(Position.X - prevPos.X, Position.Y - prevPos.Y) + MathHelper.Pi + MathHelper.PiOver2);
prevPos = Position;
}

// jump if the dolphin is under water
if(Position.Y >= 670)
{
if (kbState.IsKeyDown(Keys.A))
{
if (flip == SpriteEffects.None)
{
VelocityY += 40f;
}
else
{
VelocityY += 40f;
}
}
}
else
{
if (flip == SpriteEffects.None)
{
VelocityY += -10f;
}
else
{
VelocityY += -10f;
}
}

float deltaY = 0;
float deltaX = 0;

deltaY = Gravity * (float)gameTime.ElapsedGameTime.TotalSeconds;

deltaX += VelocityX * (float)gameTime.ElapsedGameTime.TotalSeconds * Acceleration;
deltaY += -VelocityY * (float)gameTime.ElapsedGameTime.TotalSeconds * Acceleration;

Speed = new Vector2(Speed.X + deltaX, Speed.Y + deltaY);

Position += Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;

Velocity.X = 0;

if (Position.Y + image.Height/2 > graphics.PreferredBackBufferHeight)
Position.Y = graphics.PreferredBackBufferHeight - image.Height/2;

base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(water, new Rectangle(0, graphics.PreferredBackBufferHeight -100, graphics.PreferredBackBufferWidth, 100), Color.White);
spriteBatch.Draw(image, Position, null, Color.White, rotation, new Vector2(image.Width / 2, image.Height / 2), 1, flip, 1);
spriteBatch.End();

base.Draw(gameTime);
}
}

• While I'm sure "rotates a little weird" is clear to everyone else, I'm a bit slow. Can you explain to me what's happening like I'm 5? I love pictures and animated pictures are da-bomb. – MichaelHouse Dec 8 '12 at 16:56
• @Byte56 please go easy on newbies. You might scare them off otherwise. – ashes999 Dec 8 '12 at 17:17
• Well it was intended to be joking, so I was going easy. – MichaelHouse Dec 8 '12 at 17:27
• The first part of the movement(jumping) is different than the second part. Ascending looks different than descending. But I want that ascending and descending look equal. I don't know how to fix that. – Johnny Dec 8 '12 at 19:23
• I edited my code and made a new video. In addition, it almost works perfectly. My new video: myvideo.de/watch/8881567 – Johnny Dec 11 '12 at 21:08

# Intuition

A jumping dolphin's rotation is related to the direction it's moving.

The blue is water.
The dots are dolphin positions at each time tick.
The arrows are the direction the dolphin is rotated to face.

That bottom one is a radioactive dolphin with gravity powers.

# Implementation

You could get the same effect with something like this:

function dolphin.onPositionChange ()
dolphin.sprite.rotation = directionFromTo(dolphin.prevPos, dolphin.pos)
prevPos = pos
end


That's only illustrative pseudocode of course. Here's what it does in English:

Every time the dolphin's position changes
The angle from its previous position to new position becomes its rotation
The current position is saved as the old one, for use again next step


Finding the direction from point A to point B is a little bit of geometry. XNA might have a function that does this for you. If it does, use that!

# Theory

If it doesn't (or if you just want to understand what's going on), here's the geometry for you:

Love2D (my favourite game framework) doesn't have a function to calculate the direction from point to point. Here's how I made one:

-- Vector direction
-- Angle in radians, clockwise from up i.e. straight up is 0, right is
-- pi/2, down is pi, etc.
function directionFromTo(a,b)
return math.atan2( (b.x - a.x) , (b.y - a.y) )
end

-- Test; should print 135
a = {x = 0, y = 0}
b = {x = 1, y = -1}
print( directionFromTo(a,b) / math.pi*180) -- (division to convert to degrees)

• I edited my question with additional information and code. – Johnny Dec 10 '12 at 21:19
• +1 for your very complete answer. It shows a lot of effort. – petervaz Dec 11 '12 at 12:35