SDL stiff movement - c++

i am making a pong game, lPad is left pad and rPad is the right pad, but i have a problem when any pad is moving up and when i release the up button and press down the pad stops for a while and then goes down, the other thing is i can't move both pads when pressing both controls(only one is moving) with this setup:
if(e.type == SDL_KEYDOWN) {
switch(e.key.keysym.sym) {
case SDLK_s:
lPad.y += 8;
if(lPad.y >= s.SCREEN_HEIGHT - lPad.getHeight()) {
lPad.y = s.SCREEN_HEIGHT - lPad.getHeight();
}
break;
case SDLK_w:
lPad.y -= 8;
if(lPad.y <= 0) {
lPad.y = 0;
}
break;
case SDLK_DOWN:
rPad.y += 8;
if(rPad.y >= s.SCREEN_HEIGHT - rPad.getHeight()) {
rPad.y = s.SCREEN_HEIGHT - rPad.getHeight();
}
break;
case SDLK_UP:
rPad.y -= 8;
if(rPad.y <= 0) {
rPad.y = 0;
}
break;
default:
break;
}
}
Any idea how to fix this and make it smooth ?

It's better to use SDL_GetKeyboardState(NULL) as the function to get input. This way, you can get the entire state of the keyboard simultaneously and thus allow for parallel inputs. If you use the while loop, each event will get caught individually, and thus be choppy.
Here is some sample code on how to use it:
const auto * keys = SDL_GetKeyboardState(NULL);
while(!done) {
while(SDL_PollEvent(&e)) {
if(e.type == SDL_QUIT) {
done = true;
}
}
SDL_PumpEvents();
if (keys[SDL_SCANCODE_UP]) {
p1.set_speed(0, -60000 * delta.count());
}
if (keys[SDL_SCANCODE_DOWN]) {
p1.set_speed(0, 60000 * delta.count());
}
if (keys[SDL_SCANCODE_LEFT]) {
p1.set_speed(-60000 * delta.count(), 0);
}
if (keys[SDL_SCANCODE_RIGHT]) {
p1.set_speed(60000 * delta.count(), 0);
}
Also, might I suggest having a speed variable? Using pixels is not a good way to scale movement, as it depends on the resolution of the screen. Using something based on a time step is much more robust.

Related

advanced Collision detection?

Hi i'm currently making an RPG similar to Legend of Zelda. I have a feature in my game where when Player attacks enemy with his sword, the enemy is knocked back n units. i have a collision detection that sometimes works as intended, and other times the enemy goes through the wall and gets stuck on the other side, and then other times the enemy can simply walk right through the wall. If possible, making the enemy move toward player upon collision with wall would be one possible solution to this problem I believe, but I do not know how to implement this. Here is my current collision code:
// Enemy Collides with Wall
counter1 = 0;
for (iter4 = enemyArray.begin(); iter4 != enemyArray.end(); iter4++)
{
counter2 = 0;
for (iter15 = wallArray.begin(); iter15 != wallArray.end(); iter15++)
{
if (enemyArray[counter1].rect.getGlobalBounds().intersects(wallArray[counter2].rect.getGlobalBounds()))
{
enemyArray[counter1].isCollided = true;
//Hit Wall
if ((enemyArray[counter1].direction == 1 || enemyArray[counter1].rect.getPosition().y >= wallArray[counter2].rect.getPosition().y)) //up
{
enemyArray[counter1].canMoveUp = false;
enemyArray[counter1].canMoveLeft = false;
enemyArray[counter1].canMoveRight = false;
enemyArray[counter1].rect.move(0, 7);
}
else if ((enemyArray[counter1].direction == 2 || enemyArray[counter1].rect.getPosition().y <= wallArray[counter2].rect.getPosition().y)) //Down
{
enemyArray[counter1].canMoveDown = false;
enemyArray[counter1].canMoveRight = false;
enemyArray[counter1].canMoveLeft = false;
enemyArray[counter1].rect.move(0, -7);
}
else if ((enemyArray[counter1].direction == 3 || enemyArray[counter1].rect.getPosition().x >= wallArray[counter2].rect.getPosition().x)) //Left
{
enemyArray[counter1].canMoveLeft = false;
enemyArray[counter1].canMoveUp = false;
enemyArray[counter1].canMoveDown = false;
enemyArray[counter1].rect.move(7, 0);
}
else if ((enemyArray[counter1].direction == 4 || enemyArray[counter1].rect.getPosition().x <= wallArray[counter2].rect.getPosition().x)) //Right
{
enemyArray[counter1].canMoveRight = false;
enemyArray[counter1].canMoveUp = false;
enemyArray[counter1].canMoveDown = false;
enemyArray[counter1].rect.move(-7, 0);
}
}
counter2++;
}
counter1++;
}
//Knock Back enemy away from sword && sword2
counterKnockBack++;
counter2 = 0;
for (iter4 = enemyArray.begin(); iter4 != enemyArray.end(); iter4++)
{
if (enemyArray[counter2].knockback == true)
{
if (enemyArray[counter2].isCollided == false)
{
if ((Player1.rect.getPosition().y > enemyArray[counter2].rect.getPosition().y))
{
enemyArray[counter2].rect.move(0, -3); //up
}
else if ((Player1.rect.getPosition().y < enemyArray[counter2].rect.getPosition().y))
{
enemyArray[counter2].rect.move(0, 3); //down
}
if ((Player1.rect.getPosition().x > enemyArray[counter2].rect.getPosition().x))
{
enemyArray[counter2].rect.move(-3, 0); //left
}
else if ((Player1.rect.getPosition().x < enemyArray[counter2].rect.getPosition().x))
{
enemyArray[counter2].rect.move(3, 0); //right
}
if (counterKnockBack >= 20)
{
enemyArray[counter2].knockback = false;
}
}
}
counter2++;
}
//turn off collided counter
counterCollided++;
counter2 = 0;
for (iter4 = enemyArray.begin(); iter4 != enemyArray.end(); iter4++)
{
if (enemyArray[counter2].isCollided == true)
{
if (counterCollided >= 30)
enemyArray[counter2].isCollided = false;
}
counter2++;
}
I have no idea why the enemy is able to sometimes simply walk right through the wall without being knocked back. So how can I fix this, any ideas?
Without reading the code completely I can already tell you that your collision detection code is wrong. Mostly because you are moving your objects directly, probably without checking for collisions within your rect::move function.
It is possible that the rect::move function will move objects through the walls without triggering any collision reaction code. Consider the following scenario:
First frame:
enemyArray[counterX].rect.move(3, 0);
Second frame:
The enemy object is moved behind the wall and will not trigger the collision detection code.
My advise is (despite the obvious one: read some books): for each enemy store its previous location and check for collision not between the enemy and the wall's rectangle but between wall and a rectangle between two enemy positions. Something like that:
This is of course only one of the possible scenarios when your collision detection code would be error-prone.

Object movement in a 2D Array/Grid

I am trying to create a variation of the classic Snake game.
Basically what i am stuck on is how to restrict the snake movement to a 2D array whereby there will be a 20x20 grid.
At the moment, my snake head which is just a shape drawn with a midpoint, moves freely one pixel at a time within the game board. I require the snake to move one grid space at a time.
This is my snake code:
void Snake::move()
{
switch(direction_){
case Direction::North:
position_.y += 1;
break;
case Direction::East:
position_.x += 1;
break;
case Direction::South:
position_.y -= 1;
break;
case Direction::West:
position_.x -= 1;
}
if (position_.x < 6.4) position_.x = 44.8; else if (position_.x > 44.8) position_.x = 6.4;
if (position_.y < 0) position_.y = 38.4; else if (position_.y > 38.4) position_.y = 0;
}
void Snake::render(prg::Canvas& canvas) const
{
canvas.drawCircle(getPosition().x * 20, getPosition().y * 20,19.2,prg::Colour::GREEN);
}
void Snake::changeDirection(Direction new_direction)
{
direction_ = new_direction;
}
This is the code that handles keyboard input/movement
PlayerSnake::PlayerSnake()
{
prg::application.addKeyListener(*this);
}
PlayerSnake::~PlayerSnake()
{
prg::application.removeKeyListener(*this);
}
bool PlayerSnake::onKey(const prg::IKeyEvent::KeyEvent& key_event)
{
if(key_event.key_state == KeyEvent::KB_DOWN) {
switch(key_event.key) {
case KeyEvent::KB_LEFT_KEY:
changeDirection(Direction::West);
break;
case KeyEvent::KB_RIGHT_KEY:
changeDirection(Direction::East);
break;
case KeyEvent::KB_UP_KEY:
changeDirection(Direction::North);
break;
case KeyEvent::KB_DOWN_KEY:
changeDirection(Direction::South);
break;
}
}
return true;
}
I'm in desperate need of any suggestions and have been racking my brain trying to get the snake to move along a grid. I'm also new-ish to C++ so please understand.
Thanks :)
Don't think of the screen as the data. The screen is a representation of the data. This means that you have to figure out a way to map the data to it's visual equivalent.
If the grid is 20x20, but the screen rendering is 200x200, this implies a 1:10 ratio of pixels to cells. So, one possible method of drawing might look like this. (Sorry, using Processing syntax.)
In processing, one method of drawing a rectangle is using the command rect(int left, int top, int right, int bottom);
So, one implementation might look like this:
void draw_square(int cellx, int celly)
{
rect(cellx*10, celly*10, cellx*10+10, celly*10+10);
}

Implementing collision response, current implementation does too many checks

I don't know how I should handle my collision response when collision between two entities leads to second collision with third entity.
Blue arrow is velocity of the rightmost entity and numbers below are single collision response.
Single Collision
At the beginning leftmost and middle entities are not colliding with each others, but after rightmost entity collides with middle one, the velocity middle entity gains now causes it to collide with leftmost one
How end result should be
Or if the leftmost entity was a wall -> 0, 0, -v
Current implementation: check collisions until all are handled
Velocities before collision handling
0, 0, <-10
Collisions: 2&3
If entity velocity is changed due the collision do new check
After 1. collision check:
0, <-5, <-5
Collisions: 1&2
After 2. collision check:
<-2.5, <-2.5, <-5
Collisions: 2&3
After 3. collision check:
<-2.5, <-3.75, <-3.75
Collisions: 1&2
After 4. collision check:
<-3.125, <-3.125, <-3.75
Collisions: 2&3
After nth collision check:
<-3.33, <-3.33, <-3.33
No collisions
Continue
Question: As we clearly see, it takes way too many collision checks to fix even simple collisions this way. How should I improve this?
Sample code written with sfml:
I have 3 types of entities in my test case:
wall
pushable
passable
Entity, velocity and boundingRect:
Collision response:
wall <-> pushable: can't move inside wall, push pushable entity away
pushable <-> pushable: both are repelled from each others so they won't collide
wall<->wall: skip collision checks between walls and all checks with passable terrain
Controls in sample code
Arrow keys: move green entity
Left mouse button: spawn pushable entities
Right mouse button: spawn wall entities
Middle mouse button: spawn moving pushable entities
.
#include <SFML/Graphics.hpp>
#include <iostream>
const sf::Vector2f entitySize(16.f, 16.f);
bool isMovingUp = false;
bool isMovingDown = false;
bool isMovingRight = false;
bool isMovingLeft = false;
enum Category
{
wall,
pushable,
passable,
};
class Entity
{
public:
Entity(sf::Vector2f position, sf::Color color, Category type) : position(position), type(type)
{
shape.setSize(entitySize);
shape.setFillColor(sf::Color::Transparent);
shape.setOutlineColor(color);
shape.setOutlineThickness(1.f);
}
sf::Vector2f position;
sf::Vector2f velocity;
sf::Vector2f adjustedVelocity;
sf::Vector2f defaultVelocity;
sf::RectangleShape shape;
Category type;
};
void DrawEntity(sf::RenderWindow& window, Entity& entity)
{
entity.shape.setPosition(entity.position - entity.shape.getSize() / 2.f);
window.draw(entity.shape);
}
sf::FloatRect GetBoundingRect(const Entity& entity)
{
return sf::FloatRect(entity.position+entity.velocity - entitySize / 2.f, entitySize);
}
void HandleCollision(std::vector<Entity>& entities)
{
bool allCollisionsChecked = false;
while(!allCollisionsChecked)
{
allCollisionsChecked = true;
// Pair all possible combinations, but only once per pair
for (auto first = entities.begin(); first != entities.end(); ++first)
{
for (auto second = std::next(first); second != entities.end(); ++second)
{
if (first->type == Category::passable || second->type == Category::passable || first->type == Category::wall && second->type == Category::wall)
continue;
sf::FloatRect intersection;
if (GetBoundingRect(*first).intersects(GetBoundingRect(*second), intersection))
{
if (second->position == first->position)
second->position.x += entitySize.x;
sf::Vector2f direction = second->position - first->position;
sf::Vector2f offset;
// X collision
if (abs(direction.x) > abs(direction.y))
offset.x = ((direction.x<0)?-1:1)*intersection.width;
// Y collision
if (abs(direction.x) < abs(direction.y))
offset.y = ((direction.y<0)?-1:1)*intersection.height;
if(first->type == Category::pushable && second->type == Category::pushable)
{
first->velocity -= offset / 2.f;
second->velocity += offset / 2.f;
allCollisionsChecked = false;
}
else if(first->type == Category::pushable)
{
first->velocity -= offset;
allCollisionsChecked = false;
}
else if(second->type == Category::pushable)
{
second->velocity += offset;
allCollisionsChecked = false;
}
}
}
}
}
}
void handlePlayerInput(sf::Keyboard::Key key, bool isPressed)
{
switch(key)
{
case sf::Keyboard::Up:
isMovingUp = isPressed;
break;
case sf::Keyboard::Down:
isMovingDown = isPressed;
break;
case sf::Keyboard::Left:
isMovingLeft = isPressed;
break;
case sf::Keyboard::Right:
isMovingRight = isPressed;
break;
}
}
int main()
{
sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML Application");
window.setVerticalSyncEnabled(true);
std::vector<Entity> entities;
Entity player(sf::Vector2f(1280/2, 720/2), sf::Color::Green, Category::pushable);
entities.push_back(player);
size_t cols = 1280/int(entitySize.x);
size_t rows = 720/int(entitySize.y);
for (size_t i=0; i < cols*rows; ++i)
if (i%cols == rows/5 && i/cols > rows/6 && i/cols < rows*5/6 || i%cols >= rows/5 && i%cols <= rows*4/5 && (i/cols == rows/6 || i/cols == rows*5/6))
entities.push_back(Entity(sf::Vector2f(entitySize.x*(i%cols)+entitySize.x/2, entitySize.y*(i/cols)+entitySize.y/2), sf::Color::Yellow, Category::wall));
//else
//entities.push_back(Entity(sf::Vector2f(entitySize.x*(i%cols)+entitySize.x/2, entitySize.y*(i/cols)+entitySize.y/2), sf::Color::Transparent, Category::passable));
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::MouseButtonPressed)
{
sf::Vector2i pixel(event.mouseButton.x, event.mouseButton.y);
sf::Vector2f coord = window.mapPixelToCoords(pixel);
if (event.mouseButton.button == sf::Mouse::Left)
{
Entity pushable(coord, sf::Color::Blue, Category::pushable);
entities.push_back(pushable);
}
else if (event.mouseButton.button == sf::Mouse::Right)
{
Entity wall(coord, sf::Color::Yellow, Category::wall);
entities.push_back(wall);
}
else if (event.mouseButton.button == sf::Mouse::Middle)
{
Entity mover(coord, sf::Color::Magenta, Category::pushable);
mover.defaultVelocity.x = -1.f;
entities.push_back(mover);
}
}
switch (event.type)
{
case sf::Event::KeyPressed:
handlePlayerInput(event.key.code, true);
break;
case sf::Event::KeyReleased:
handlePlayerInput(event.key.code, false);
break;
case sf::Event::Closed:
window.close();
break;
}
}
if (isMovingUp)
entities[0].velocity.y -= 5.f;
if (isMovingDown)
entities[0].velocity.y += 5.f;
if (isMovingLeft)
entities[0].velocity.x -= 5.f;
if (isMovingRight)
entities[0].velocity.x += 5.f;
if (entities[0].velocity.x != 0.f && entities[0].velocity.y != 0.f)
{
entities[0].velocity.x /= std::sqrt(2.f);
entities[0].velocity.y /= std::sqrt(2.f);
}
HandleCollision(entities);
// Apply and reset velocities
for (Entity& e : entities)
{
e.position += e.velocity;
e.velocity = e.defaultVelocity;
}
// Draw
window.clear();
for (Entity& e : entities)
DrawEntity(window, e);
window.display();
}
}
Sample results
Magenta entities are moving to the left with constant speed and yellow entities are wall.
without checking collisions due the other collisions
Desired outcome:
Same scenario when checking collisions until all are resolved
How could I achieve this?

How to move relatively to the angle?

I keep looking up on the internet how to move from point A to point B on an angle with a specified distance. When I tried to code it, however, the camera just gets messed up and I'm moving in random directions. I am using SDL/OpenGL with c++ and this is my player function. Right now, I'm trying to get the player to move forwards along the angle.
void player_action()
{
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_MOUSEMOTION:
{
player.rotxl = (screen->w)/2;
player.rotxd = event.motion.x - player.rotxl;
player.rotx = player.rotx + (player.rotxd/4);
if (player.rotx < 0)
{
player.rotx = player.rotx + 360;
};
if (player.rotx > 360)
{
player.rotx = player.rotx - 360;
}
};
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_w:
{player.zvel = 8.0f;}; break;
case SDLK_a:
{player.xvel = 8.0f;}; break;
case SDLK_s:
{player.zvel = -8.0f;}; break;
case SDLK_d:
{player.xvel = -8.0f;}; break;
case SDLK_ESCAPE:
{running = false;}; break;
default: break;
}; break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_w:
{player.zvel = 0.0f;}; break;
case SDLK_a:
{player.xvel = 0.0f;}; break;
case SDLK_s:
{player.zvel = 0.0f;}; break;
case SDLK_d:
{player.xvel = 0.0f;}; break;
default: break;
};
break;
};
};
player.x = player.x + float(player.zvel*cos((double)player.rotx));
player.z = player.z + float(player.zvel*sin((double)player.rotx));
glRotatef(player.rotx, 0.0f, 1.0f, 0.0f);
glTranslatef(player.x, player.y, player.z);
SDL_WarpMouse((screen->w/2), (screen->h/2));
};
If I'm correct the math functions sin and cos both take angles in radians, not degrees as player.rotx seems to be. Try the following:
player.x = player.x + float(player.zvel*cos((double)player.rotx*0.0174532925));
player.z = player.z + float(player.zvel*sin((double)player.rotx*0.0174532925));
We're multiplying player.rotx by pi/180, which is how we convert degrees to radians.
Not sure if this is your only problem, but it certainly appears to be one of them.
Two possible sources of the issue I see:
The standard C++ cos/sin function take a function in radians instead of degrees (one radian = 180/pi degrees).
While I'm not familiar with SDL a quick look at the docs makes me think you should be using event.motion.xrel instead of .x. You'll have to change your rotx calculation which should not need the screen width.

SFML Sprite moving violently down on 2nd tick

I am working on an SFML game and for some reason after spawning the player, the player gets teleported down. On the first tick he is correctly positioned, but after wards, he is moved down. Any idea on how to diagnose this problem? I set up breakpoints in the move mechanism, the only place where the player's co-ordinates change, and it seems to happen right after the function ends. This is the main function:
int main(){
App.ShowMouseCursor(false);
mainch.mainchinventory.read();
while (App.IsOpened())
{
sf::Event Event;
while (App.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
App.Close();
}
float time = App.GetFrameTime();
mainch.move(time);
App.Clear();
drawall();
App.Display();
}
return EXIT_SUCCESS;
}
Mainch.move(t):
void cmainchar::move(float t){
if (App.GetInput().IsKeyDown(sf::Key::S)) mainchinventory.save();
if (App.GetInput().IsKeyDown(sf::Key::R)) mainchinventory.read();
if (App.GetInput().IsKeyDown(sf::Key::A)) A = true;
else A = false;
if (App.GetInput().IsKeyDown(sf::Key::D)) D = true;
else D = false;
if(grounded)
if (App.GetInput().IsKeyDown(sf::Key::W)) first = true;
if ((App.GetInput().IsKeyDown(sf::Key::I)) && (keyreleased)){
if (mainchinventory.drawmain){
mainchinventory.drawmain = false;
mainchinventory.press(mainchinventory.selectionx, 3);
}
else{
mainchinventory.drawmain = true;
}
keyreleased = false;
}
else if (!App.GetInput().IsKeyDown(sf::Key::I))
keyreleased = true;
if(!mainchinventory.drawmain){
if(App.GetInput().IsKeyDown(sf::Key::Num1)) mainchinventory.press(0, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num2)) mainchinventory.press(1, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num3)) mainchinventory.press(2, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num4)) mainchinventory.press(3, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num5)) mainchinventory.press(4, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num6)) mainchinventory.press(5, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num7)) mainchinventory.press(6, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num8)) mainchinventory.press(7, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num9)) mainchinventory.press(8, 3);
else if(App.GetInput().IsKeyDown(sf::Key::Num0)) mainchinventory.press(9, 3);
if(App.GetInput().IsMouseButtonDown(sf::Mouse::Button::Left)){
mainchinventory.dockitems[mainchinventory.selectionx].use();
spells.push_back(cspell());
}
}
else if ((App.GetInput().IsMouseButtonDown(sf::Mouse::Button::Left)) && (mainchinventory.drawmain) && (buttonreleased)){
mainchinventory.checkmouse();
buttonreleased = false;
}
else if (!App.GetInput().IsMouseButtonDown(sf::Mouse::Button::Left))
buttonreleased = true;
int xmap = (View.GetCenter().x - 320) / 40;
int ymap = (View.GetCenter().y - 240) / 40;
if ((xmap != xmapold) || (ymap != ymapold))
maps.read();
xmapold = xmap;
ymapold = ymap;
collisions();
for(std::list<cspell>::iterator i = mainch.spells.begin(); i != mainch.spells.end(); i++)
if (i->move(t))
spells.erase(i);
if (A && left){
animate(2, t);
you.Move(-160 * t, 0);
}
if (D && right){
animate(1, t);
you.Move(160 * t, 0);
}
if (!D && !A)
animate(0, t);
if (up){
if(grounded && first){
jump = 1.25;
first = false;
}
if (jump > 0){
you.Move (0,-250 * t * jump);
jump = jump - 1 * t;
}
if (jump <= 0){
jump = 0.f;
}
}
else{
first = false;
jump = 0.f;
}
if (down){
fall = fall + 10 * t;
you.Move(0, 25 * fall * t);
grounded = false;
}
else{
fall = 0.f;
grounded = true;
}
if(teleport){
mainchinventory.spawn = true;
fall = 0.f;
jump = 0.f;
maps.changemap(maps.nxtmap);
teleport = false;
}
moveview();
}
You don't show the code where you're manipulating the sf::Sprite object, so I (or anyone else, really) can't say for certain, but...that said, I have a strong guess as to what's happening.
I've been familiarizing myself with SFML recently, too, and I encountered this issue myself. What I think is happening is you're calling sf::Sprite::Move(x,y) to move the sprite to position (x,y). This is incorrect; what you should be calling is sf::Sprite::SetPosition(x,y). (Both these functions take will take a 2d vector as an argument instead, btw).
I'm operating under the assumption you're using SFML 1.6, yes? Looks that way...version 2.0 changes the API somewhat, so in case you're using that Sprite::Move() becomes Sprite::move() and Sprite::SetPosition() becomes Sprite::setPosition().
Anyways, to wrap this up: the difference between Move(x,y) and SetPosition(x,y) is that Move adjusts the sprite's position relative to its current position, whereas SetPosition moves the sprite to a new position regardless of where it was before.
Again, this is a blind guess since the relevant code was not included...so was my shot in the dark correct?
Unfortunately, you haven't provided enough code for a straightforward diagnosis. With what you provided however, my best guess is that your fall variable hasn't been initialized. If it hasn't been initialized, its values can be completely random, likely being much larger than expected. This would explain your 'teleporting' behavior.