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));
}
}
Related
Okay so I've rolled this around in my brain, and while I would probably know what code to use if I could figure it out, I just can't decide what the best way to implement this is.
Basically, say I have a vector grid. This grid could have any number of blockaded areas that the item I am pushing around can't go to. The pushing of the object is done by an interact button using the "new" inputsystem package. I could have a dynamic rigidbody and let it be pushed around that way, but I want to use the interact button I have, in part because the first puzzle of this type is used in a tutorial to teach the player the game's commands.
Without knowing where the blockades are going to be, I'm not sure how to tell where the object can move at any given time. My current thought is use colliders, and keep them far enough away that there isn't an actual collision since I don't think I can place them perfectly enough to get collisions at the right times, and throw out raycasts at a short range to detect these colliders. (This gives me more "give" when placing the colliders.)
Does this sound right? Is there a more efficient way to do it? Even if it requires more complex code, I am interested in feedback because I want to learn "good coding" and how to do things in the best, most efficient way possible, rather than spaghetti coding my way through it.
The most efficient way? Forget Colliders. Basic old-school game dev skill: Working with arrays. Create a 2D array of boolean values, or integers set to 0 or 1 representing OPEN or CLOSED.
using UnityEngine;
public class TestObstacleGrid : MonoBehaviour
{
const int GRID_WIDTH = 8; //if you change this, you'll need to match the size of the grid, below.
int[,] grid = {
// -> +x
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,1,1,1,1,1},
{0,0,0,1,0,1,1,1},
{0,0,0,1,0,1,1,1},
{0,0,0,0,0,0,0,0},
{1,1,0,0,0,0,0,0},
{1,1,0,0,0,0,0,0}
//|
//V
//+z
};
const int OPEN = 0;
const int CLOSED = 1;
public Vector3 playerPos = Vector3.zero; //give player a start position via inspector.
//You need to drag/drop something like a Cube GameObject into here, via the inspector.
public GameObject playerGameObject;
Vector3 playerOffset = new Vector3(0.5f, 0.5f, 0.5f);
Texture2D tex;
void Start()
{
tex = new Texture2D(8, 8, TextureFormat.ARGB32, false);
tex.filterMode = FilterMode.Point; //makes texture crisp, not blurry
//assumes you are using a plane, not a quad.
this.transform.position = new Vector3(GRID_WIDTH / 2, 0, GRID_WIDTH / 2); //shift by half
this.transform.localScale = new Vector3(-GRID_WIDTH / 10f, 1f, -GRID_WIDTH / 10f); //Unity Planes are 10 units wide.
MeshRenderer renderer = this.GetComponent<MeshRenderer>();
renderer.material.mainTexture = tex;
playerGameObject.transform.position = playerPos;
//Only needs to be called once in Start() or Awake(), if grid doesn't change.
RenderGridToTexture();
}
void Update()
{
Vector3 motion = Vector3.zero;
if (Input.GetKeyDown(KeyCode.W))
motion += Vector3.forward;
if (Input.GetKeyDown(KeyCode.S))
motion += Vector3.back;
if (Input.GetKeyDown(KeyCode.A))
motion += Vector3.left;
if (Input.GetKeyDown(KeyCode.D))
motion += Vector3.right;
Vector3 proposedPos = playerPos + motion;
//prevent player leaving the grid.
proposedPos.x = proposedPos.x < 0 ? 0 : proposedPos.x;
proposedPos.x = proposedPos.x > GRID_WIDTH - 1 ? GRID_WIDTH - 1 : proposedPos.x;
proposedPos.z = proposedPos.z < 0 ? 0 : proposedPos.z;
proposedPos.z = proposedPos.z > GRID_WIDTH - 1 ? GRID_WIDTH - 1 : proposedPos.z;
if (grid[(int)proposedPos.z, (int)proposedPos.x] == CLOSED)
{
proposedPos = playerPos; //reset the proposed to the current position (stay there).
Debug.Log("Invalid attempted move from " + playerPos +
" to " + proposedPos);
}
else //OPEN
playerPos = proposedPos;
playerGameObject.transform.position = playerPos + playerOffset; //offset shifts the cube so it looks right.
//Uncomment this if the grid can change during play.
//RenderGridToTexture();
}
void RenderGridToTexture()
{
for (int z = 0; z < GRID_WIDTH; z++)
for (int x = 0; x < GRID_WIDTH; x++)
tex.SetPixel(x, z,
grid[z, x] == 1 ? Color.red : Color.black );
tex.Apply();
}
}
Create an empty GameObject, and attach to this script along with a MeshRenderer and MeshFilter; for the MeshFilter, give it a Plane mesh. Create a Cube GameObject and drag it onto the script's playerGameObject field in the inspector. The script will do the rest.
Using the keys, your player moves one full square at a time, but you'll want smooth movement in the end. That's fine; this is only a basis for your game. Later on, when you want smooth movement, you can figure it out using Mathf.Lerp() with coroutines to move your player smoothly from one space to another (as well as the object your player is pushing).
You'll need to figure out pushing - the principle is the same as already used here to check for collisions: Look at the grid and see if a non-zero value is there. Then look in front of the object to see if there is an obstacle. Use a different number in the grid, like 2, to represent a pushable object.
That's the best I can do in short form, hope it's enough. Adios and good luck.
I made this game with Python+Pygame, but it was slow, so I tried it with C# and its forms. It's even slower! I get only 20fps on a i5 radeon 6770m NTB millions of times faster than hardware I want this game to run and I haven't even finished the game yet, it's only rendering a map. It's a remake of a game that was run with slow several MHz processors. It's map containes 400x200 tiles and camera shows only 79*79. I also installed unity 4.5; is it worth learning it, would it bring me significant perfomance increase - if someone knows it how would I do a map consisting of 600*400 tiles randomly either dark tile or bright; it has to be "collidable"? Or I doing sth wrong in forms?
public void render()
{
Bitmap frame = new Bitmap(Game.CANVAS_WIDTH, Game.CANVAS_HEIGHT);
Graphics frameGraphics = Graphics.FromImage(frame);
TextureID[,] textures = Background.Blocks;
while (true)
{
//frameGraphics.FillRectangle(new SolidBrush(Color.Aqua), 0, 0, Game.CANVAS_WIDTH, Game.CANVAS_HEIGHT);
for (int x = 0; x < Game.AR_WIDTH; x++)
{
int xx = x * Game.TILE_SIDE - game.green_tank_pos[0] + Game.DIFF;
if (xx < 0) continue;
if (xx > Game.CANVAS_WIDTH) break;
for (int y = 0; y < Game.AR_HEIGHT; y++)
{
int yy = y * Game.TILE_SIDE - game.green_tank_pos[1] + Game.DIFF;
if (yy < 0) continue;
if (yy > Game.CANVAS_HEIGHT) continue;
switch(textures[x,y])
{
case TextureID.dark:
frameGraphics.DrawImage(tex_dark_gnd, xx, yy);
break;
case TextureID.bright:
frameGraphics.DrawImage(tex_bright_gnd, x * Game.TILE_SIDE - game.green_tank_pos[0] + Game.DIFF, y * Game.TILE_SIDE - game.green_tank_pos[1] + Game.DIFF);
break;
}
}
}
frameGraphics.DrawImage(tex_green_tank, Game.DIFF, Game.DIFF);
drawHandle.DrawImage(frame, 0, 0);
WinForms is a terrible platform for a game, even a 2D one. It was intended for line-of-business applications, and includes little to no hardware acceleration.
Plus the technology is just hard to write a game in, let alone an efficient one. You might get away with using WPF for a very simple game, but you will really want to learn XNA, MonoGame, Unity or some other actual game platform that can take advantage of DirectX (WPF does this as well, btw).
There are ways to get better performance drawing in winforms but for a game it's best to go with tools that better fit the job. (don't use a screwdriver to hit a nail).
The newer versions of Unity3D have built-in 2D tools. I'm personally building a 2D game in it and would highly recommend it.
EDIT: Removed my mention of XNA - I wasn't aware it was "dead".
Creating tiles in Unity3D can be done several ways
Place sprites into the scene manually. Their locations and settings will be saved along with the scene.
Place the sprites within the scene manually and create a prefab out of it. Thus, that set of tiles can be reused.
Create a prefab of a single tile, and instantiate multiples of that prefab in a Behavior that is attached somewhere in a scene.
As for the rendering Unity3D will take care of that for you.
EDIT2: I created a short Unity3D behavior that you can attach somewhere inside your scene. This uses the 3rd approach I outlined above and it will pick randomly from a set of prefabs applied. This script assumes randomly picking from tiles and that the width of the tiles are 1 game unit wide/high.
Attach the behavior to something in the scene (like the main camera)
Create your tiles as prefabs
Drag the prefabs in the editor into the "Tile Prefabs" array on the behavior you've attached.
Set the "Tiles High" to 400 and "Tiles Wide" to 600
Set TileMapTopLeft to the top-left position you want it to start.
Run your scene.
Here's the behavior:
using UnityEngine;
class TileCreator : MonoBehaviour
{
private static System.Random rng = new System.Random();
public GameObject[] TilePrefabs;
public int TilesWide;
public int TilesHigh;
public Vector3 TileMapTopLeft;
void Start()
{
for (int x = 0; x < TilesWide; x++)
{
for (int y = 0; y < TilesHigh; y++)
{
Instantiate(TilePrefabs[rng.Next(TilePrefabs.Length)], new Vector3(x + TileMapTopLeft.x, y + TileMapTopLeft.y, TileMapTopLeft.z), Quaternion.identity);
}
}
}
}
You'll probably need to look up a tutorial on how to import resources and create prefabs but this script should get you in the right direction.
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;
}
I'm sorry if question title was unclear, but with my cheap english, I cant find a way to ask it clearly.
But I can explain it in long way.
So I have realized if I design my world(and with world, I mean ENTIRE game, it will be one level) 10.000x10.000... it will be very enough, other than few another sprite(and I mean like 4 or 5 with maximum of 50x50, nothing big.)
So I thought, why dont I make my entire map as 10.000x10.000(or lets say tons of 512x512) picture ?
But I have one question, there is few things you can "interact". they will(with they, I mean the stuff that is in my "world.jpg") be always stay at same place, but player(which is actually a sprite as you know) will move, therefore my 10.000x10.000 will "move".
So look at picture below, there is black dot which is "player" and red dot, which is lets say, a door.
and world is always centered to black dot unless he goes to end of the world. as you can see, (look at picture part 1 and part 2) when he moves a little bit to east, red dot looks moved. but I just moved my 10.000x10.000 image. Thats what I meant with the stuff on 10kx10k pic will move.
Anyway, but as you can see in last part of pic, when he goes near red dot, I want to my "action"
How to do it ?
-part below is not really related to main question
Is it useful to use 10kx10 pic instead of another sprites appearing on world when he moves ? but If I want to do that, not just I will check if he is nearby, but I will also check his point to realize if I should or shouldnt show him sprite.
Will it be more useful if I show my stuff when he comes to coordinates I want, or is using one big picture is OK ?
Thanks.
I would suggest a structure of the map somewhat like this..
public class Map
{
public MapPoint[,] mapPoints; //the map
public Player player; //the player/user object
public Vector2 DrawHeroPosition;
//where at the screen the player is going to be drawn
public Vector2 RangeStart;
//what part of the map who is going to be drawn
public int SizeX; //number of mapPoints the screen can contain at one time
public int SizeY; //number of mapPoints the screen can contain at one time
//MapPoint represents a specific 512x512 point (mapPoint) its position at
//the map but also includes the sprite that is going to be drawn and objects
//that the player can interact with at that place (like the door)
//the player object includes reference to where in the world it is place
public Map(ContentManager theContentManager, int x, int y)
{
MapSizeX = x;
MapSizeY = y;
int ScreenSizeX = 9;
int ScreenSizeY = 9;
mapPoints = new MapPoint[MapSizeX , MapSizeY];
//ad code for generating/creating map...
//important that you store the MapPoints position inside each mapPoint
player = new Player(mapPoints[0,0]); //crate a player who knows where he is
}
public void Update()
{
//in the update method you do a lot of things like movement and so
//set what part of the map the game should draw if the game for example
//can show 9x9 512points at a single time
//give range value from the players position
RangeStart.X = player.PositionX;
//test if the maps position is in the left corner of the map
//if it is draw the map from the start..(RangeStart.X = 0)
if (player.PositionX - (ScreenSizeX / 2) < 0) { RangeStart.X = 0; }
//if not draw the hero in the mitle of the screen
else
{
RangeStart.X = player.PositionX - (ScreenSizeX / 2);
}
//if the hero is in the right corer, fix his position
while (RangeStart.X + ScreenSizeX > MapSizeX)
{
RangeStart.X--;
}
//the same thing for the Y axle
RangeStart.Y = player.PositionY;
if (player.PositionY - (ScreenSizeY / 2) < 0) { RangeStart.Y = 0; }
else
{
RangeStart.Y = player.PositionY - (ScreenSizeY / 2);
}
while (RangeStart.Y + ScreenSizeY > MapSizeY)
{
RangeStart.Y--;
}
//time to set the position of the hero...
//he works like the opposite of the range, if you move what part of the map
//you draw you dont change the heros draw position, if you dont move the range
//you have to move the hero to create the illusion of "moment"
//if you are in the left part you have to move the heros draw position..
if (player.PositionX - (ScreenSizeX / 2) < 0)
{ DrawHeroPosition.X = player.PositionX; }
//if you are in the right part
else if (player.PositionX+1 > MapSizeX - (ScreenSizeX / 2))
{
DrawHeroPosition.X = player.PositionX - (MapSizeX - ScreenSizeX);
}
//if you aint in a corner, just place the hero in the middle of the map
else
{
DrawHeroPosition.X = (ScreenSizeX / 2);
}
//the same thing for Y
if (player.PositionY - (ScreenSizeY / 2) < 0)
{ DrawHeroPosition.Y = player.PositionY; }
else if (player.PositionY+1 > MapSizeY - (ScreenSizeY / 2))
{
DrawHeroPosition.Y = player.PositionY - (MapSizeY - ScreenSizeY);
}
else
{
DrawHeroPosition.Y = (ScreenSizeY / 2);
}
}
public void Draw()
{
int x = (int)RangeStart.X;
int y = (int)RangeStart.Y;
for(int counterX = 0; x < ((MapSizeX)); x++, counterX++)
{
for (int counterY = 0; y < (MapSizeY); y++, counterY++)
{
if (mapPoints[x, y] != null)
{
mapPoints[x, y].Draw(spriteBatch, mapPoints[counterX,counterY].positonInMatrix);
//mapPoints[counterX,counterY] = where to draw
//mapPoints[x, y] = what to draw
}
}
y = (int)RangeStart.Y;
}
}
}
how i draw inside the MapPoint Class...
public void Draw(SpriteBatch theSpriteBatch, Vector2 positonOnScreen)
{
positonOnScreen = new Vector2(positonOnScreen.X * base.Scale * 16,
positonOnScreen.Y * base.Scale * 16);
//base.Scale is just a variable for have the ability to zoom in/out
//16 represents the original size of the picture (16x16 pixels)
theSpriteBatch.Draw(mSpriteTexture, new Rectangle((int)positonOnScreen.X,
(int)(positonOnScreen.Y), 64, 64),new Rectangle(0, 0, 16, 16), Color.White);
}
If you are asking for collision detection within a radius of your red dot. You can simply use the following test (pseudocode, I don't write C# :-)
if( (player.GetPosition() - point.GetPosition()).length() < radius )
{ /* Do code here */ }
This will detect if your player is within a certain radius of your dot, you can then perform whatever action you wish.
Hope this helps! :)
Ok, from what I understand of your question, you have a large image which contains different objects you want your player to interact with, yes? By which I mean, the image file itself has doors or hills or other things which the player would interact with.
This is a bad idea, honestly, so I hope I misunderstood. It is far better to have your background image just be something generic and make all interactive objects classes within your game. If you do this, then you can have your object classes contain behavior to intersect with each other either based on their distance (circle collision) or based on a bounding box you define for them.
Circle Collision:
if (Math.Abs(Vector2.Distance(player.Position - obj.Position)) < player.Radius + obj.Radius)
//do the action
Rectangle Collision:
if (player.Bounds.Intersects(obj.Bounds))
//do the action
Also, if you are planning on making a 10,000 x 10,000 pixel image, understand that the XNA Content Pipeline will not import an image greater than 4,000 pixels to a side.
If you are set on having the player interact with pixels in the background of the image, you can either make an array of interactive object locations manually or you can use the Texture2D.GetData() method to load in the colors of every single pixel in the image for processing-- but be aware that this will take a long time, especially for large or numerous textures.
I have a simple rectangle-tile collision scheme set up, and it works beautifully.
The only problem is when you start falling off of a ledge. Your speed reaches the point where the change in Y/X each frame is large enough for you to clip into solid objects and glitch about.
Basically my setup is as follows:
To start with, the player's position has its velocity added to it, so the player is now at the place he would be next frame if no collisions happen.
The list below is just a single function, checkIntersectTiles(Vector2 maskPos);
Calculate tiles around the character to check.
Loop through tiles, including those inside the bounding tiles.
Check the player's collision rectangle against each of these tiles.
If there's an intersection, move the largest offending axis out of the tile, then set that axis velocity to 0.
Continue checks.
When you clip into the ground, you jitter around inside, as my algorithm attempts to move you outside the tile that is most colliding with you.
My solution: Check each position from the player's pos, to the player's pos + velocity.
I'm stuck on that bit.
Can anyone give me a hand?
I assume that your code to move the player out of the colliding tile does so in a single step. So if the player collides with a tile you determine that the penetration depth is 5 in the Y direction you immediately adjust the player Y position by -5.
As you suggest, check the player position at each step. So if the Y velocity is 5 then you can adjust the players Y position by 1, check for collision and then repeat 4 more times. See later for calculations handling time stepping. The following is just some basic pseudo code and just in the Y direction.
player.Y += vel;
if (player.CheckCollisions())
{
// handle collision
}
Becomes
for (int i = 0; i < vel; ++i)
{
player.Y += 1;
if (player.CheckCollisions())
{
// handle collision
break;
}
}
That is the simple version if you are not adjusting for ellaped time. If you are, then you rather perform smaller time steps
So
player.Y += vel * elapsedTime;
if (player.CheckCollisions())
{
// handle collision
}
Becomes
float currentTimeStep = 0;
Position startY = player.Y;
while (currentTimeStep < elapsedTime)
{
currentTimeStep = Math.Min(currentTimeStep + stepDelta, elapsedTime); // You need to tune the stepDelta
player.Y = startY + vel * currentTimeStep;
if (player.CheckCollisions())
{
// handle collision
break;
}
}
In the above you will need to tune the time step delta to ensure that you balance performance with accuracy. You might event consider calculating the delta dynamically each frame to ensure that the adjustment is close to 1 pixel.