Make a basic running sprite effect - c#

I'm building my very first game with XNA and i'm trying to get my sprite to run.
Everything is working fine for the first sprite.
E.g : if I go right(D) my sprite is looking right , if I go left(A) my sprite is looking left and if I don't touch anything my sprite is the default one.
Now what I want to do is if the sprite goes Right, i want to alternatively change sprites (left leg, right leg, left leg etc..) xCurrent is the current sprite drawn xRunRight is the first running Sprite and xRunRight1 is the one that have to exchange with xRunRight while running right.
This is what I have now :
protected override void Update(GameTime gameTime)
{
float timer = 0f;
float interval = 50f;
bool frame1 = false ;
bool frame2 = false;
bool running = false;
KeyboardState FaKeyboard = Keyboard.GetState();
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if ((FaKeyboard.IsKeyUp(Keys.A)) || (FaKeyboard.IsKeyUp(Keys.D)))
{
xCurrent = xDefault;
}
if (FaKeyboard.IsKeyDown(Keys.D))
{
timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
if (timer > interval)
{
if (frame1)
{
xCurrent = xRunRight;
frame1 = false;
}
else
{
xCurrent = xRunRight1;
frame1 = true;
}
}
xPosition += xDeplacement;
}
Any ideas...? I've been stuck on this for a while..
Thanks in advance and let me know if you need any other part from the code.

You forgot to reset the timer, you could do this when you hit the timer interval condition. Also, 50ms seems a bit too small for an interval, maybe you could do like 400ms?
Other than that, looks good, it will do what you want.
Alternatively, you could look into making animated sprites for walking. What you do is make an image with the walking animation sprites one next to the other, of the same size. You draw only a portion of this image (one sprite) and move through them based on time.
Here is a quick code for what could be an animated texture:
class AnimatedTexture2D : Texture2D
{
int _numberOfImages;
int _currentImage = 0;
int _timeInterval;
int _spriteWidth;
public Rectangle DrawFromRectangle
{
get
{
return new Rectangle(_currentImage * _spriteWidth, 0, _spriteWidth, this.Height);
}
}
public AnimatedTexture2D(Texture2D entireImage, int spriteWidth, int numberOfImages, int timeInterval)
: base(entireImage.GraphicsDevice, entireImage.Width, entireImage.Height)
{
_numberOfImages = numberOfImages;
_timeInterval = timeInterval;
_spriteWidth = spriteWidth;
Color[] data = new Color[entireImage.Width * entireImage.Height];
entireImage.GetData<Color>(0, new Rectangle(0, 0, entireImage.Width, entireImage.Height), data, 0, entireImage.Width * entireImage.Height);
this.SetData<Color>(data);
}
public void Animate(GameTime gameTime)
{
int totalImageTime = _timeInterval * _numberOfImages;
int currentPoint = (int)gameTime.TotalGameTime.TotalMilliseconds % totalImageTime;
_currentImage = currentPoint / _timeInterval;
}
}
Usage is fairly simple:
1) declare it somewhere:
AnimatedTexture2D animatedTexture;
2) initiate it with your texture (i had a 2560x64 sequence of 40 64*64 images), where individual images are placed next to each other horizontally:
animatedTexture = new AnimatedTexture2D(Content.Load<Texture2D>(#"Textures\Loading"), 64, 40, 20);
3) in your Update() method, call:
animatedTexture.Animate(gameTime);
4) in your Draw() method, call:
SpriteBatch.Draw(animatedTexture, new Rectangle(20, 20, 64, 64), animatedTexture.DrawFromRectangle, Color.White);
Don't forget the DrawFromRectangle in part 4! (notice that the destination rectangle uses the declared individual part width, not the entire texture width which is in my test 2560 pixels)
Now, in your code you could forget the interval part, and the gametime part, and you could just use this instead of the default one!
Also, if you don't like my timing code (its ultra simple but lacks a way to reset the animation) change it so you have an elapsed time variable, and add to it like you do in your own code, and use that to change _currentImage. You could even make that variable public so you can use it to reset the animation (or set it to a specified point).
Of course, you could also make the default one an animated texture with only one frame so you can use the same code everywhere. Hope this helps!

You need to keep the last time Update(..) was called, and the interval should be... well.. an interval, that is, the difference between ElapsedGameTime and last call to update ElapsedGameTime.
Do it with a new member of your class (LastElapsedGameTimeUpdateCalled) or a static member of your sub.

If you know that every animation is going to have the same number of frames you could keep 3 variables per sprite (encapsulate in class for best results).
BaseFrame is an integer to hold a global animation number.
SubFrame is an offset in to the animation that holds which frame you are currently on.
FrameAccumulator to hold timing information.
Each time update is called, add the number of ms since the last update to the accumulator. Once the accumulator goes above your animation timing, increment SubFrame, and reset the accumulator. Check to see if subFrame is greater than the number of frames for each animation, and if it is, set it back to 0. You can get the real frame index from this by adding BaseFrame + Subframe. When you need to display a different animation just change the BaseFrame.
Lets say that each animation has 3 frames, and you have 2 total animations. You would have 6 total frames. RunLeft would be BaseFrame 0, and RunRight would be BaseFrame 3. That should easily give you the frame number to draw.

Related

Mouse Drag - C# bot

First time doing this. I am currently building a bot using C# and want my bot to be able to move the mouse to a given point in a way that looks human. By this I am referring to the dragging of the mouse when a human moves the cursor to a point they are trying to click on. Currently my C# bot moves the mouse instantly to the location which doesn't look human.
private static Point[] FindColor(Color color)
{
int searchValue = color.ToArgb();
List<Point> result = new List<Point>();
using (Bitmap bmp = GetScreenShot())
{
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
if (searchValue.Equals(bmp.GetPixel(x, y).ToArgb()))
result.Add(new Point(x, y));
}
}
}
return result.ToArray();
}
// FUNCTIONS OCCUR BELOW
// Error message if program could not find bitmap within screenshot show error message
Color myRgbColor = new Color(); // Creates new colour called myRgbColor
myRgbColor = Color.FromArgb(51, 90, 9); // This colour equals the RGB value
Point[] points = FindColor(myRgbColor); // Create an array called points which list all the points found in the screen where the RgB value matches.
if (points.Length > 0)
{
Cursor.Position = points[2]; // Move mouse cursor to first point (Point 0)
Thread.Sleep(0200);
MouseClick();
}
if (points.Length == 0)
{
MessageBox.Show("No matches!"); // Return error
goto checkore;
}
You're going to want to use some kind of Timer with a callback, to move the mouse incrementally, step by step. As for the movement itself, you have a world of possibilities, but it's all maths.
So, let's decompose the problem.
What is a natural mouse movement?
Position change rate
It doesn't necessarilly looks like it, but when you move your mouse, you're simply setting its position multiple times per seconds.
The amount of times the position changes per second is equivalent to the polling rate of your mouse. The default polling rate for USB mice is 125Hz (or 125 position changes per second, if you will). This is the value we'll use for our Timer: its callback will be called 125 times per second.
var timer = new Timer(1000 / 125d);
timer.Elapsed += MoveMouse;
void MoveMouse(object sender, ElpasedEventArgs e) { }
Speed and acceleration
When you move your mouse, the distance between two cursor positions is not constant, because you're fast when you start moving your mouse, but you slow down when you get close to the item you want your cursor to be on.
There are also two ways I personally usually move my mouse depending on the context/mood:
One fast uniform movement to get close to the destination, then one slow to correct and get on it (I'll usually go past the destination during the first move)
One medium-slow movement with a small deceleration, follow by a stronger deceleration at the end
The overall speed of the movement also depends on three factors:
The distance between your cursor and the destination
The size of the destination area
Your personal speed
I have absolutely NO IDEA how to work out the formula based on these factors, that's gonna be a work of trial and error for yourself.
This one is purely math and observation based, and will be tricky to get perfectly right, if ever; every person moves their mouse a different way.
The solution I can offer you is to simply forget about deceleration, correction and so on, and just divide your movement into equal steps. That has the merit of being simple.
using System;
using System.Timers;
using System.Drawing;
public class Program
{
static int stepCount = 0;
static int numberOfSteps = 0;
static float stepDistanceX = 0;
static float stepDistanceY = 0;
static PointF destinationPoint;
static Timer timer;
public static void Main()
{
int timerStepDurationMs = 1000 / 125;
PointF currentPoint = Cursor.Position;
destinationPoint = new PointF(2000, 1800); // or however you select your point
int movementDurationMs = new Random().Next(900, 1100); // roughly 1 second
int numberOfSteps = movementDurationMs / timerStepDurationMs;
stepDistanceX = (destinationPoint.X - currentPoint.X) / (float)numberOfSteps;
stepDistanceY = (destinationPoint.Y - currentPoint.Y) / (float)numberOfSteps;
timer = new Timer(timerStepDurationMs);
timer.Elapsed += MoveMouse;
timer.Start();
while (stepCount != numberOfSteps) { }
}
static void MoveMouse(object sender, ElapsedEventArgs e)
{
stepCount++;
if (stepCount == numberOfSteps)
{
Cursor.Position = destinationPoint;
timer.Stop();
}
Cursor.Position.X += stepDistanceX;
Cursor.Position.Y += stepDistanceY;
}
}
Note that I haven't tested with "Cursor", but with some PointF variable instead. It seems to work fine here: dotnetfiddle.

Interrupting a Jump Animation in windows form

So far, I have a jump animation. It uses an integer "jump" to loop through an array of images that create a jump animation, additionally, depending on what number "jump" is,the height "PositionY" will be increased or reduced and when jump hits 10, the animation ends..... this is jump animation code
public Bitmap Jump_Frame2Draw()
{
Jump_Frames = new Bitmap[] { Jump_1, Jump_2, Jump_3, Jump_4, Jump_5, Jump_6, Jump_7,Jump_7,
Jump_8, Jump_8 };
if (jump < Jump_Frames.Length)
{
if (jump <= 3)
{
PositionY -= 30;
}
else if (jump == 8 || jump == 10)
{
PositionY += 0;
}
else
{
PositionY += 24;
}
jumpFrame = Jump_Frames[jump];
jump++;
if (jump == 10)
{
jumpTimer.Stop();
isJumping = false;
jump = 0;
standTimer.Start();
Invalidate();
}
}
tracer = jumpFrame.GetPixel(1, 1);
jumpFrame.MakeTransparent(tracer);
isJumping = true;
return jumpFrame;
}
By using a timer and a paint event, I'm able to simply call this method every x seconds inorder to draw it when I press my designated jump key... Now my problem is lets say I'm in the middle of the jump animation, and I want to go back up .How do I do I go about that. Think of it as a double jump. Also, the jump and height(PositionY) are directly correlated. So if jump is 0,1,2 or 3, then height is 214 - (jump + 1) * 30). Else if jump is (5-9) height is 94 + (jump - 4) * 24). So the maximum height that any images will ever be drawn is 94.(its windows form so up is down and down is up... (0,0) is located at top left).
///////////
For a visual perspective, this is similar to my jump animation. This one is a little shorter in terms of time but it the best I could find.
Jump animation: https://media.giphy.com/media/wXervlFEqohO0/giphy.gif
now imagine this guy was ironman, he uses his jet boosters to jump up, but now while still in the air, he decided to just go straight up.
I think you'd save yourself alot of trouble if you move most of the animation-specific code to a dedicated JumpAnimation class. Pass all information required for the specific animation in the constructor:
class JumpAnimation
{
public JumpAnimation(int howHigh)
{
...
}
}
Responding to a click on the space bar, you know you have to create a JumpAnimation. But while your timer is ticking, you don't want to deal with the specifics of a jump or jetpack animation - you want an IAnimation interface that allows you to continue the animation whatever it was. And when you acitvate the jetpack, you just want to replace whatever animation is currently active with a JetPackAnimation:
In your form:
private IAnimation currentAnimation = null;
And the IAnimation interface:
public interface IAnimation
{
// get the bitmap at the time relevant to the animation start
Bitmap GetBitmapAt(int time);
}
You can reuse alot of the code you shared in your question when you implement IAnimation in your JumpAnimation.
Now instead of returning just the Bitmap, you can create a class that holds more information about the "current step in the animation:
public class AnimationStep
{
public Bitmap Bitmap { get; set; }
// the y-offset
public int OffsetY { get; set; }
// indicates whether this was the last step of the animation
public bool Completed { get; set; }
// a jump animation can be interrupted by a jetpack animation, but a DieAnimation cant:
public bool CanBeInterrupted { get; set; }
...
}
I hope you get the idea. I'm not claiming this is the only or best way to tackle your problem, but sometimes another person's view on the matter helps thinking outside the box.

How to fade text in Unity

Heyo, I'm trying to make my GUI fade when not in use. Specifically, for a Minecraft-style tool bar, I want it to pop in when a player uses the scroll wheel and fade away in a few seconds after they're done scrolling. The GUI is working perfectly, but I can't get this fading thing to work. I assume once I get the selection text working, the sprites will follow easily, so I'll just talk about the selection text for now. The inventoryText starts the game at full white.
protected void OnGUI()
{
if (isInvGUIDirty)
{
// Update selection text
controllerInterface.inventoryText.CrossFadeAlpha(255f, 0, false);
controllerInterface.inventoryText.CrossFadeAlpha(0.1f, 2, false);
^ This results (when I move the scrollwheel) in the inventory text going full-white, and two seconds later shifting to a light grey. There is no sleek transition, and it is still clearly visible. This repeats every time I move the scrollwheel.
controllerInterface.inventoryText.CrossFadeAlpha(255f, 0, false);
controllerInterface.inventoryText.CrossFadeAlpha(0f, 2, false);
^ This results (when I move the scrollwheel) in the inventory text going full-white, and two seconds later shifting to invisible. This repeats every time I move the scrollwheel. Apparently 0.1 alpha makes all the difference o_O
controllerInterface.inventoryText.color = Color.white;
controllerInterface.inventoryText.CrossFadeAlpha(0.1f, 2, false);
^ This results in the inventory text slowly fading to a light grey, but no change on scrollwheel.
Any ideas on why CrossFadeAlpha() isn't working as expected?
Sorry, wasn't getting email updates from here :/. So what I ended up doing that worked was to write my own coroutine at the most basic level, which seemed to work...for some reason. Honestly, not sure why the previous didn't work. This operates on a CanvasGroup instead of the individual items too.
private void FadeInventoryGroup(float alpha, float delay)
{
if (fader != null)
StopCoroutine(fader);
fader = StartCoroutine(EFadeOutInventory(alpha, delay));
}
private IEnumerator EFadeOutInventory(float alpha, float delay)
{
yield return new WaitForSeconds(delay);
float progress = 1f - Mathf.Abs(inventoryGroup.alpha - alpha);
float start = inventoryGroup.alpha;
while (progress < 1f)
{
progress += Time.deltaTime;
inventoryGroup.alpha = Mathf.Lerp(start, alpha, progress);
yield return 0;
}
}

XNA - Play Animation at place when collide and delete when reach last frame

In my pong game I'm making I have two paddles and a ball. I'm trying to make so when the ball collides with the paddle, an effect/animation is shown. I have a spritehseet and a working animation. I use this to detect when the animation plays (please notice that I havent fixed the position of the effect yet, so it plays on 400, 300 just to see if it works)
public bool BallHitEffect()
{
if (gPaddle.gpRect.Intersects(ball.ballRect))
{
return true;
}
else { return false; }
And in my Draw:
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
if (BallHitEffect())
{
animatedSprite.Draw(spriteBatch, new Vector2(400, 250));
}
}
Now it appears when it collide, but only for a short millisecond, because when the ball leaves the paddle, it disappears. I'm aware that it's coded to only appear when it is colliding with the paddle, but in what way could I possibly make it only disappear only when it's animation ends?
You can easily used elapsed time and some makeshift timers to do this. I assume your spritesheet is a series of frames, and that you already have rendering set up.
You will need some variables to start out:
double frameTimePlayed; //Amount of time (out of animationTime) that the animation has been playing for
bool IsPlaying; //Self-Explanitory
int frameCount; //Frames in your sprite, I'm sure you already handle this in your animation logic, but I just threw it in here
int animationTime = 1000; //For 1 second of animation.
In your update method you need to
Check if the ball is intersecting, and set IsPlaying to true
If the animation IsPlaying, increment the frameTimePlayed by the elapsed time
If the frameTimePlayed is equal to or greater than the animationTime, stop the animation by setting IsPlaying to false
In your draw method you need to
Draw the animation, if IsPlaying
Here is some example code:
protected override void Update(GameTime gameTime)
{
//If it is not already playing and there is collision, start playing
if (!IsPlaying && BallHitEffect)
IsPlaying = true;
//Increment the frameTimePlayed by the time (in milliseconds) since the last frame
if (IsPlaying)
frameTimePlayed += gameTime.ElapsedGameTime.TotalMilliseconds;
//If playing and we have not exceeded the time limit
if (IsPlaying && frameTimePlayed < animationTime)
{
// TODO: Add update logic here, such as animation.Update()
// And increment your frames (Using division to figure out how many frames per second)
}
//If exceeded time, reset variables and stop playing
else if (IsPlaying && frameTimePlayed >= animationTime)
{
frameTimePlayed = 0;
IsPlaying = false;
// TODO: Possibly custom animation.Stop(), depending on your animation class
}
}
And for drawing, pretty easy, just check is IsPlaying and draw if that is the case.
I made sure to comment the code good, so hopefully this will help you understand and work better.
You could also use a double and use TotalSeconds instead of milliseconds if needed, and calculate elapsed time with float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

XNA 2D Camera doesnt keep sprite centered

I've been working on a kind of spaceship game in which you take a lander and take off from the ground and fly up as high as you can get until you come crashing down. The problem I've been running into is that the camera that I've tried to implement doesn't keep the lander in the center, the lander eventually gets faster then the camera and goes off screen. I don't understand why and I've tried everything to make it work. I created a test case in which I used the camera on a simple program where a sprite moved in four directions. That one worked fine, but when I implemented the camera on my main game, it doesn't work correctly. Any help would be appreciated.
This is the camera class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace WindowsGame4.Main
{
class Camera
{
public Matrix transform;
Viewport view;
Vector2 centre;
public Camera(Viewport newView)
{
view = newView;
}
public void Update(GameTime gameTime, Game1 lander, Lander _lander)
{
centre = new Vector2(_lander.Position.X + (lander.lander.Width / 2) - 455, _lander.Position.Y + (lander.lander.Height/2)-910);
transform = Matrix.CreateTranslation(new Vector3(-centre.X - _lander.Velocity.X, -centre.Y - _lander.Velocity.Y, 0));
}
}
}
This is the main update method in Game1:
// Creates the handler to allow the use of the keyboard inputs
KeyboardState keyboard = Keyboard.GetState();
// Sets up the launch position to allow for scoring and height determining
startPos = 700f;
// Mainly for debug, allows for leaving the game whenever desired
if (keyboard.IsKeyDown(Keys.Escape))
{
Exit();
}
// The logic for the thruster, checks for if the space key is down and if
// the lander has any fuel remaining. If there is no fuel the thrusters
// will not work.
if (keyboard.IsKeyDown(Keys.Space) && !empty)
{
_lander.Accelerate(_thruster.GetAcceleration(), gameTime.ElapsedGameTime);
// Turns on the thruster
_thruster.Active = true;
// Tells the program that the lander has taken off, allowing the gravity to kick in
landed = false;
// Keeps track of the amount of fuel you have
if (_lander.Fuel > 0)
{
// Subtracts 1 from the fuel for every second that the 'SPACE' key is down
_lander.Fuel--;
}
else if (_lander.Fuel <= 0)
{
empty = true;
endPos = _lander.Position.Y;
}
}
if (keyboard.IsKeyUp(Keys.Space) || empty)
{
// Turns off the thruster as long as the player is not pressing 'SPACE'
_thruster.Active = false;
}
// This is the logic structure for the landing portion of the game, it sets up a
// level area in which the player can land on, which in turn then checks the Position.X value
// to see how many points to give based on their close proximity to the landing site.
// ** Could possibly add depth or different levels based on location, like landing on a mountain
// ** Or landing in the bottom of a crater
if (_lander.Position.Y >= 800)
{
landed = true;
// If you have died or Failed a mission 3 times then the game is over
if (_lander.Lives == 1)
{
currentGameState = GameState.GameOver;
}
// As long as you have a life left the game will continue
// This logic also is only applied if the player has landed on the ground
// ** Add a rotational fixer as to make the lander stand straight up as opposed to the way its oriented
// ** Upon landing
else if (_lander.Lives > 0)
{
// Sets the landers position to the current position that its landed at, thus stopping the gravity
// Resets the velocity, thus making sure it doesnt continue to fall
_lander.Position = new Vector2(_lander.Position.X, _lander.Position.Y);
_lander.Velocity = new Vector2();
// Sets up the first landing site, this particular one is the highset value landing site is almost right
// On top of the flag that is placed to indicate where to land.
// *** Will Not Use In Final Version, Will Substitue With Logic For Height And Cash Gained ***
if ((_lander.Position.X >= 600 && _lander.Position.X <= 650) || (_lander.Position.X <= 600 && _lander.Position.X >= 550))
{
// *** Will be implemented to display a "YOU HAVE FAILED THE MISSION" screen. ***
failure = false;
// This is for debugging purposes only, will change to be automatic once all functions are complete
if (keyboard.IsKeyDown(Keys.Enter))
{
// (1) -- Resets the position of the lander back to its original position and Velocity
// (2) -- Add 150 points to the score based on the location that the lander set down at
// (3) -- Continues on to the next level
_lander.Position = new Vector2(graphics.PreferredBackBufferWidth / 2, 100); // (1)
_lander.Velocity = new Vector2(); // (1)
_lander.Score += 150; // (2)
currentGameState = GameState.Level2; // (3)
}
}
// Sets up the second landing site, this particular one is the second highest value landing site that is
// A large circle surrounding the landing site above
else if ((_lander.Position.X >= 651 && _lander.Position.X <= 750 ) || (_lander.Position.X <= 549 && _lander.Position.X >= 450))
{
// *** Will be implemented to display a "YOU HAVE FAILED THE MISSION" screen. ***
failure = false;
// This is for debugging purposes only, will change to be automatic once all functions are complete
if (keyboard.IsKeyDown(Keys.Enter))
{
// (1) -- Resets the position of the lander back to its original position and Velocity
// (2) -- Add 50 points to the score based on the location that the lander set down at
// (3) -- Continues on to the next level
_lander.Position = new Vector2(graphics.PreferredBackBufferWidth / 2, 100); // (1)
_lander.Velocity = new Vector2(); // (1)
_lander.Score += 50; // (2)
currentGameState = GameState.Level2; // (3)
}
}
// Sets up the final landing site, this particular one is the failing portion of the map that is
// A large area that encompasses the rest of the map.
else if ((_lander.Position.X >= 751 && _lander.Position.X <= 850) || (_lander.Position.X <= 449 && _lander.Position.X >= 0))
{
// You get no points so it does not only need to done once, it can be done as many times as needed
// And it will not change the data
_lander.Score = 0;
// *** Will be implemented to display a "YOU HAVE FAILED THE MISSION" screen. ***
failure = true;
// This is for debugging purposes only, will change to be automatic once all functions are complete
if (keyboard.IsKeyDown(Keys.Enter))
{
// (1) -- Resets the position of the lander back to its original position and Velocity
// (2) -- Takes away one of your lives as a result of the players failure to land correctly
_lander.Position = new Vector2(graphics.PreferredBackBufferWidth / 2, 100); // (1)
_lander.Velocity = new Vector2(); // (1)
_lander.Lives--; // (2)
}
}
// This is just a loop that gives a visual representation of refueling before the next level begins.
for (double i = _lander.Fuel; i < 500; i++)
{
_lander.Fuel += .05;
}
}
}
// A very simple call to the Gravity and Lander classes that simulates gravity as long as the
// lander has not landed
else if (!landed)
{
_lander.Accelerate(_gravity.GetAcceleration(), gameTime.ElapsedGameTime);
}
// Moves the lander according to gravity calculated by the lander class
_lander.DoMovement(gameTime.ElapsedGameTime);
// Calculates the height achieved based off of starting height and ending height
height = startPos - endPos;
// This will rotate the lander when the keys are pressed down
// They will also check to make sure if it is landed or not
// If it's landed then it will not allow the lander to rotate.
if (keyboard.IsKeyDown(Keys.Left) && landed == false)
{
// (1) -- This will also change the angle of rotation for the thruster as to all for movement in
// That specific direction.
// Example: if you rotate to the left and turn on the thrusters you will starting moving
// to the left
rotation -= 0.1f;
_lander.Rotation = rotation;
_thruster.Rotation = rotation; // (1)
}
if (keyboard.IsKeyDown(Keys.Right) && landed == false)
{
// (1) -- This will also change the angle of rotation for the thruster as to all for movement in that specific direction.
// (2) -- This will also change the angle of rotation for the lander as to all for movement in that specific direction.
// Example: if you rotate to the right and turn on the thrusters you will starting moving
// to the right
rotation += 0.1f;
_lander.Rotation = rotation; // (2)
_thruster.Rotation = rotation; // (1)
}
// Calls the camera class to allow the screen to move with the player
camera.Update(gameTime, this, _lander);
If you guys need more code I can upload anything else you guys need
Why do you need to use a translation for a 2D camera? It's a very complicated way for something that can be done a lot simpler. A 2D camera in my opinion should just be a vector corresponding to the upper-left corner of the camera's viewport. Then just subtract the camera vector from any sprite position and it will move along with the camera.
So in your case, just set the camera vector to be at the center point minus half of the screen width and height:
Camera = SpriteCenter - new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
For every drawing call, subtract the Camera vector from the actual position of a sprite.
And there you go, your sprite will always be centered.
If you are doing something special that doesn't allow this to function, then I am unable to understand your actual question. I hope this helps.
I disagree with #Sarkilas, I think using a transformation will simplify your code, not needing to specify the camera each time.
You can use this code as a base for position, origin, zoom, and rotation.
return Matrix.CreateTranslation(new Vector3(-Position, 0.0f)) *
Matrix.CreateTranslation(new Vector3(-Origin, 0.0f)) *
Matrix.CreateRotationZ(Rotation) *
Matrix.CreateScale(Zoom, Zoom, 1) *
Matrix.CreateTranslation(new Vector3(Origin, 0.0f));
The issue is that the lander is not your origin, it should be your position, while the origin should be half of your viewport size like so
Position = lander.Position;
Origin = new Vector2(view.Width / 2, view.Height / 2);
You will probably have to add half your lander position back to the origin or position if it looks a bit off.

Categories

Resources