I decided that my last year C# project would be a 'Monster Dash' like game, I would develop it using C# and XNA, and it would be targeted for PCs, I am using Microsoft Visual Studio 2010, and XNA Game Studio 4.0. The game would be a 2D game, not 3D.
Thinking on the development process, a few problems rise up:
First, I need to create a 'sort-of-platforms' which the player will run on and will have holes and gaps between them (which will appear randomly) and I have no idea how to do that! The only close thing I've found that might explain that is an sample code called 'Platformer' from microsoft, which I did not understand (it would be nice of someone could explain the method they use there, or a better / more simple way).
Second, I would need the player to jump (in order to avoid the gaps and holes and continue running) and I have no idea how to approach the physics part of that feature, I would be really happy if someone could suggest a way to handle that, or point to a useful piece of code.
Thanks ahead, iLyrical.
Make no mistake, just because it is 2D, a platformer is not an easy task. So i would suggest you use any third party library help you can get, using XNA and C# is already a good starting point. Next thing is, and this is where your questions come in, how to solve the physics? You could write it on your own, which is a nice learning experience but if time is crucial it can be difficult and frustrating. So i would suggest using a third party lib for that, like Farseer. Maybe this little tutorial comes in handy aswell.
But again, this is definitely not an easy task. Depending on your Skill, which i of course don't know, i would suggest an easier game, if it must be a game at all. Games are propably the most difficult programming task you can imagine.
Dealing with multiple subsystems simultaneously (Graphics, AI, Sound, Input, Physics); making them work together is already a huge task, but having the content (Sprites, Wavs, Music, Menu gfx, etc.) is another beast on its own.
A final advise is, if you don't understand the Platformer code; read it again, and again; if you don't understand certain parts read about them until you understand them. If you have problems with c# first learn it and never stop to learn it. Also read as many tutorials and code about games you can find. It is important to see how and why are other people solving problems the way they do.
The platformer example on the Microsoft website is a good place to start.
I made something similar a while back somewhat based on that example. Its a tiled based approach where you have a 2 dimensional list of "Tiles" (A list of lists of tiles List>) You set a static size for the tiles (say 16x16 pixels), then it's just a matter of looping through the list to draw/do collision detection, etc. Just something to think about, if I think about it I can post some code later if you wanted, it's at home.
A simple way I usually approach movement physics like that is to use 3 Vector2 objects, one for position, one for velocity and one for acceleration. If you're familiar with simple physics, position = velocity * deltaTime, velocity = acceleration * deltaTime. When a player jumps you just increase the players acceleration, then in the update loop, calculate the position:
// On Jump
player.acceleration += someConstant
// On Update
this.velocity += this.acceleration * deltaTime
this.position += this.velocity * deltaTime
Again, I'll post some real code later.
Hope this helps get you started
Edit:
Here's some movement code
public override void Update(GameTime gameTime)
{
float deltaTime = ((float)gameTime.ElapsedGameTime.Milliseconds) / 1000f;
currentState = Keyboard.GetState();
if (canMove)
{
// Input
if (currentState.IsKeyDown(Keys.Left))
Acceleration.X -= 1000;
if (currentState.IsKeyDown(Keys.Right))
Acceleration.X += 1000;
if (!airbourne && currentState.IsKeyDown(Keys.Space) && previousState.IsKeyUp(Keys.Space))
{
Acceleration.Y -= 25000;
airbourne = true;
}
// Friction in X to limit sliding
if (Velocity.X > 0)
{
Velocity.X -= X_FRICTION;
if (Velocity.X < 0)
Velocity.X = 0;
}
else
{
Velocity.X += X_FRICTION;
if (Velocity.X > 0)
Velocity.X = 0;
}
// Gravity
Acceleration.Y += 500;
}
Velocity += Acceleration * deltaTime;
if (Velocity.X > 0)
Velocity.X += speedMod;
else if (Velocity.X < 0)
Velocity.X -= speedMod;
// Move and check collisions in X
Position.X += Velocity.X * deltaTime;
if (game.checkCollisions(boundingBox()))
{
Position.X -= Velocity.X * deltaTime;
Velocity.X = 0;
}
// Move and check collisions in Y
Position.Y += Velocity.Y * deltaTime;
movingUp = Velocity.Y < 0;
if (game.checkCollisions(boundingBox()))
{
// If moving downwards, player not airbourne
if (Velocity.Y >= 0)
{
airbourne = false;
Position.Y = game.getCollisionDistance(boundingBox()) - 32;
}
else
{
Position.Y = game.getCollisionDistance(boundingBox()) + 32;
}
Velocity.Y = 0;
}
else
airbourne = true;
movingUp = false;
// Reset acceleration
Acceleration = Vector2.Zero;
previousState = currentState;
}
Related
I am trying to make a first-person game on Monogame and so far all I have come with or found on the internet didn't meet my standards.
this is how I am currently handling the mouse:
private void HandleMouse()
{
Vector2 mouseDifference;
mouseNow = Mouse.GetState();
if (mouseNow.X != mouseDefaultPos.X || mouseNow.Y != mouseDefaultPos.Y)
{
mouseDifference.X = mouseDefaultPos.X - mouseNow.X;
mouseDifference.Y = mouseDefaultPos.Y - mouseNow.Y;
leftrightRot += mouseSens * mouseDifference.X;
updownRot += mouseSens * mouseDifference.Y;
Mouse.SetPosition((int)mouseDefaultPos.X, (int)mouseDefaultPos.Y);
UpdateViewMatrix();
}
}
private void UpdateViewMatrix()
{
Matrix cameraRotation = Matrix.CreateRotationX(updownRot) * Matrix.CreateRotationY(leftrightRot);
Vector3 cameraOriginalTarget = new Vector3(0, 0, -1);
Vector3 cameraOriginalUpVector = new Vector3(0, 1, 0);
Vector3 cameraRotatedTarget = Vector3.Transform(cameraOriginalTarget, cameraRotation);
Vector3 cameraRotatedUpVector = Vector3.Transform(cameraOriginalUpVector, cameraRotation);
viewMatrix = Matrix.CreateLookAt(new Vector3(0,0,0), cameraRotatedTarget, cameraRotatedUpVector);
}
My problem is that while this solution works, it is extremely inconsistent when it comes to how far the camera should rotate.
for example, happens when I make circles with the mouse and see that sometimes the mouse randomly jumps more than expected.
My main assumptions inconsistencies in fps that cause the time between frames to change, thus affecting the distance the mouse can move within that time.
I don't know if this is the reason or if my assumption can even cause this, but I would like to find a way to get consistent mouse movement.
I can provide a video of the problem if needed.
Thank you in advance.
The mouse in Windows is updated 240 times per second. The game loop runs at 60 frames per second. The discrepancy can lead to large mouse deltas. The solution is to limit the change in the mouse delta:
Vector2 mouseDifference;
const float MAXDELTA = 6; // Set to the appropriate value.
mouseNow = Mouse.GetState();
if (mouseNow.X != mouseDefaultPos.X || mouseNow.Y != mouseDefaultPos.Y)
{
mouseDifference.X = Math.Min(MAXDELTA, mouseDefaultPos.X - mouseNow.X);
mouseDifference.Y = Math.Min(MAXDELTA, mouseDefaultPos.Y - mouseNow.Y);
leftrightRot += mouseSens * mouseDifference.X;
updownRot += mouseSens * mouseDifference.Y;
Mouse.SetPosition((int)mouseDefaultPos.X, (int)mouseDefaultPos.Y);
UpdateViewMatrix();
}
This is an old thread, but I figured I would share a solution. The solution that's worked for me to use the GameTime object to relate how much the player should rotate by. In other words, rotate by (delta * rotationSpeed * GameTime.ElapsedTime.TotalSeconds) so that each rotation is relative to how much time has passed since the last frame. This protects it against frame drops, which I've found has been the problem for me.
Recently I've been trying to make a 2D game in XNA, but I seem to have hit a dead end. No mater where I look on the internet, I can't seem to find any examples of how to make two objects collide in XNA. I know perfectly well about how to detect if something is colliding, just not what to put between the if statement.
In my case it's trying to make a player not pass through any blocks on the screen. I've tried several ways, but none of them seems to work. :(
Thanks in advance!
So, this is sort of a dirty solution, but you could save the position of where you are, move, and then if you collide, revert back to the original position.
Here's a code example, providing your method to check for collision is called doesCollide() and your method to do the game logic and move the player accordingly is called update().
Also, getX(), getY(), setX() and setY() are just methods to get/set the coordinates of the player.
int lastX = player.getX();
int lastY = player.getY();
player.update();
if(player.doesCollide()){
player.setX(lastX);
player.setY(lastY);
}
This method especially faces problems, when the player is moving at a high speed, because then the player might glitch through obstacles or not be able to get close to walls.
Here's a solution that fixes that, but it is even dirtier:
int lastX = player.getX();
int lastY = player.getY();
player.update();
int moveX = player.getX() - lastX;
int moveY = player.getY() - lastY;
player.setX(lastX);
player.setY(lastY); //we're basically figuring out where the player would move
int ratio = moveY / moveX;
for(int i = 0; i < moveX; i++){ //we move the player pixel by pixel
player.setX(lastX + i);
player.setY(lastY + (int) (i * ratio));
if(player.doesCollide()){ //we revert the last pixel move
player.setX(lastX + i - 1);
player.setY(lastY + (int) ((i - 1) * ratio));
}
}
I am trying to simulate a boat in Unity3D. What I need it to be able to do is wobble like a real boat would while in water whenever it hits something. I have the boat colliding already, and all of its axes are unlocked. However, this means the boat will rotate, and then keep driving at an odd angle (like facing to the sky).
Is there a way to make the boat try to return to its original rotaions, without snapping to the exact values, but simply "rocking" back and forth, and then slowing down to eventually stop at the correct rotations again?
Here is the code am attempting to use:
void FixedUpdate ()
{
wobble();
}
void wobble()
{
if (this.transform.eulerAngles.x < 270)
{
this.rigidbody.AddTorque((float)19, (float)0, (float)0, ForceMode.Force);
}
else if (this.transform.eulerAngles.x > 270)
{
this.rigidbody.AddTorque((float)-19, (float)0, (float)0, ForceMode.Force);
}
else{}
if (this.transform.eulerAngles.z < 0)
{
this.rigidbody.AddTorque((float)19, (float)0, (float)0, ForceMode.Force);
}
else if (this.transform.eulerAngles.z > 0)
{
this.rigidbody.AddTorque((float)-19, (float)0, (float)0, ForceMode.Force);
}
else{}
}
However, now when my object hits something, it just starts spinning out of control. Any ideas?
You can use tweening. A wonderful technique to change values smoothly be-tween two values. In this case you can tween from your awkward bouncing angles to your boats sitting rotation by tweening between the two. There are good plugins to use like iTween which is fantastic but I will show you some half pseudo - half super-cereal code to get you started on the concept for "rotation correction"
Lets say I have my boat hit a nice big wave and its pointing my boat upwards to a 20deg angle.
My euler angle on X is 20 and I can return this to 0 by increasing the decreasing the value at a constant rate. I'm just showing X here but you can repeat the process for Z-axis. I would exclude Y as you will use your direction of your boat on Y and you don't want to screw up your boats navigation.
Update()
float angleDelta;
// check if value not 0 and tease the rotation towards it using angleDelta
if(transform.rotation.X > 0 ){
angleDelta = -0.2f;
} elseif (transform.rotation.X < 0){
angleDelta = 0.2f;
}
transform.rotation.X += angleDelta;
}
This incredibly simple implementation does the job but has the wonderful perk of being incredibly "snappy" and "jittery". So we want to add some smoothing to make it a more lifelike boat.
We do this by adding in a variable to the angleDelta:
Vector3 previousAngle;
float accelerationBuffer = 0.3f;
float decelerationBuffer = 0.1f;
Update()
Vector3 angleDelta;
//assuming that x=0 is our resting rotation
if(previousAngle.X > transform.rotation.X && transform.rotation.X > 0){
//speed up rotation correction - like gravity acting on boat
angleDelta.X += (previousAngle.X - transform.rotation.X) * accelerationBuffer;
} elseif(previousAngle.X < transform.rotation.X && transform.rotation.X > 0
//angle returning to resting place: slow down the rotation due to water resistatnce
angleDelta.X -= (previousAngle.X - transform.rotation.X) * deccelerationBuffer;
}
//If boat pointing to sky - reduce X
if(transform.rotation.X > 0 ){
transform.rotation.X -= angleDelta.X * Time.deltaTime;
//If boat diving into ocean - increase X
} elseif (transform.rotation.X < 0){
transform.rotation.X += angleDelta.X * Time.deltaTime; //Must not forget to use deltaTime!
}
//record rotation for next update
previousAngle = transform.rotation;
}
This is an incredibly rough draft but it gets across the theory that I'm trying to explain - you will need to adjust your own code accordingly as you haven't included any of your own (pastebin a snippet to us and maybe we can elaborate more!)
Coding in c# and using the XNA 4.0 framework I am trying to develop for both keyboard and game controller input when it comes to player control.
My code for the game controller input is as follows;
GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
if(gamepadState.ThumbSticks.Left.X != 0 || gamepadState.ThumbSticks.Left.Y != 0)
{
//Handles rotation
angle += thumbsticksMove(gamepadState); //handles Left.X and Left.Y input
normalize(); //normalizes angle and sets normalizedAngle = angle
this.Rotate(normalizedAngle); //takes value and passes it through Math helper
//atan and pi*2
//Ends handles rotation
pos += (angle * speed);
//Implementing framerate adjustment just for this class
timeSinceLastFrame += (float)gameTime.ElapsedGameTime.Milliseconds;
if (timeSinceLastFrame > millisecondsPerFrame)
{
timeSinceLastFrame -= millisecondsPerFrame;
Animation();
}
}
This moves the player as expected and the sprite flips to the proper direction, but the animation piece does not work. The sprite is supposed to animate with player movement upon input. This works great when taking in input from the keyboard, see below;
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
input = Vector2.Zero;
input.X = 1;
//Handles rotation
angle.X = input.X;
normalize();
this.Rotate(normalizedAngle);
//Ends handles rotation
pos += (input * speed);
//Implementing framerate adjustment just for this class
timeSinceLastFrame += (float)gameTime.ElapsedGameTime.Milliseconds;
if (timeSinceLastFrame > millisecondsPerFrame)
{
timeSinceLastFrame -= millisecondsPerFrame;
Animation();
}
}
I'm having a hard time figuring out why it works for the keyboard input but not the game controller input. It almost looks as if it's trying to animate but never quite makes it past the 3rd animation cell or animates so fast to the point of looking as if it's barely animating. Any help would be hugely appreciated!
I ended up adding
if (gamepadState.IsConnected){//Gamepad code}
if (!gamepadState.IsConnected){//Keyboard code}
Reading the inputs separately seems to have fixed the issue.
Thanks for everyone's help though.
I have the model representing the player's ship gradually leaning when the player strafes. For instance, here's the code that leans the ship right:
In Update() of the Game class:
if (ship.rightTurnProgress < 1 && (currentKeyState.IsKeyDown(Keys.D)))
{
ship.rightTurnProgress += (float)gameTime.ElapsedGameTime.TotalSeconds * 30;
}
In Update() of the Ship class:
if (currentKeyState.IsKeyDown(Keys.D))
{
Velocity += Vector3.Right * VelocityScale * 10.0f;
RotationMatrix = Matrix.CreateRotationX(MathHelper.PiOver2) *
Matrix.CreateRotationY(0.4f * rightTurnProgress);
}
This is what I'm attempting to do to make it ease back out of the lean when it stops strafing:
In Update() of the Game class:
if (ship.rightTurnProgress > 0 && currentKeyState.IsKeyUp(Keys.D))
{
ship.rightTurnProgress -= (float)gameTime.ElapsedGameTime.TotalSeconds * 30;
}
In Update() of the Ship class:
if (currentKeyState.IsKeyUp(Keys.D) && rightTurnProgress > 0)
{
RotationMatrix = Matrix.CreateRotationX(MathHelper.PiOver2) *
Matrix.CreateRotationY(-0.4f * rightTurnProgress);
}
Since easing into the lean works no problem, I thought easing out of the lean would be a simple matter of reversing the process. However, it tends to not go all the way back to the default position after a long strafe. If you tap the key, it snaps all the way back to the full lean of the -opposite- direction. This isn't what I expected at all. What am I missing here?
I suggest you represent the rotation of you ship as a quaternion. That way you can use an interpolation function such as slerp. Simply have a second quaternion that represents you targeted lean angle and the ship will smoothly rotate until it achieves the targeted angle.
Here's a good tutorial on quaternions. If you want to avoid quaternions use MathHelper.Lerp to smoothly transition from the current value to the target.
if (currentKeyState.IsKeyDown(Keys.D))
{
ship.TurnProgress = MathHelper.Lerp(ship.TurnProgress, 1, somefloat * timeDelta);
}
else if (currentKeyState.IsKeyDown(Keys.a))
{
ship.TurnProgress = MathHelper.Lerp(ship.TurnProgress, -1, somefloat * timeDelta);
}
else (currentKeyState.IsKeyDown(Keys.D))
{
ship.TurnProgress = MathHelper.Lerp(ship.TurnProgress, 0, somefloat * timeDelta);
}
Edit: Also there is a GameDev stack overflow so check it out if you have more questions.
Unless you know how long the turn is or you have some kind of acceleration vector you will have to wait until the turn is stopped before returning the sprite angle to neutral, then what happens when the player turns left before the sprite has reached its neutral position? I assume that when you turn right using RightTurnProgress you also have a LeftTurnProgress I suggest you combine them into one variable to keep it smooth and avoid the snapping effect you are getting.
You are creating an 'absolute' rotation matrix so you don't need to flip the sign to -0.4f. Why not just have a variable called ship.lean and calculate the rotation matrix every update. Then you just need logic to ease ship.lean between -1 (left lean) and 1 (right lean) or 0 for no lean.