Sidescroller jumping/collision (Not Java, but Javascript)

'ello guys,

So I have a question about some jumping and collision stuff in a sidescroller, so here goes:

I’m making a sidescroller for my bachelor project(A game for helping kids learn sequences of numders, such as 3,6,9 … 27, 30)

What I’m doing is exactly this(Couldn’t figure out a neat way of writing this, without pasting my HORRIBLE code)


Player.prototype.update = function(entities) {
	if(Keyboard.isPressed(Keyboard.D)) {
		this.velocity.x = 10;
	} else if(Keyboard.isPressed(Keyboard.A)) {
		this.velocity.x = -10;
	} else {
		this.velocity.x = 0;
	}

	if(!this.isJumping && Keyboard.isPressed(Keyboard.SPACE)) {
		this.isJumping = true;
		this.velocity.y = -this.jumpSpeed;
	}

	var move = (Math.abs(this.velocity.x) > Math.abs(this.velocity.y)) ? Math.abs(this.velocity.x) : Math.abs(this.velocity.y);

	for(var i = 0; i < move; i++) {
		var lastX = this.x,
			lastY = this.y;

		var nx = this.x + (this.velocity.x / move),
			ny = this.y + (this.velocity.y / move);

		var colX = false,
			colY = false;

		for(var x = 0; x < entities.length; x++) {
			if(entities[x].passable) {
				continue;
			}

			this.setX(nx);
			this.setY(ny);

			if(this.intersects(entities[x])) {

				this.setY(lastY);
				if(this.intersects(entities[x])) {
					nx = lastX;
					colX = true;
				}

				this.setX(nx);
				this.setY(ny);
				if(this.intersects(entities[x])) {
					ny = lastY;
					colY = true;
				}
			}
		}

		if(this.velocity.y > 0 && colY && !colX) {
			this.isJumping = false;
		}

		this.sprite.position.x = this.x;
		this.sprite.position.y = this.y;
	}

	if(this.velocity.y < this.grav) {
		this.velocity.y += this.grav;
	}
};

This sorta kinda works, except that you’re able to “cling” to walls, because … Well, I’m not perfectly sure, tbh, but I’m assuming that it’s somehow finding that it doesn’t collide with the wall on the side, but it collides with the wall piece below it.

(I’m aware that the code isn’t exactly epic, but it’s currently just for trying to get it do behave as it should, cleanup comes later, if there’s time for it)

Any clever tips would be most appreciated! :slight_smile:

I find that I have to do the horizontal move, check for a horizontal collision, then do the vertical movement and check for vertical collision. I’m not sure you can do both at the same time and get the desired result. I can see you’re trying to achieve that, but try doing it as 2 totally separate operations and see if that helps.

Edit: nvm, must learn to read title.

Just so you know, Javascript is VERY different from Java.

LiquidNitrogen has the right idea. Even better if you separate the hor/ver movement into moving left/right up/down.

Additionally, looping through all entities to check for collisions isn’t really efficient at all in the long run - but hey, if it works it works.

There are some things you can do to make this kind of stuff easier to handle.
For once you should start to think in vectors.
http://www.mathsisfun.com/algebra/vectors.html

You can use vectors to represent a position, velocity, acceleration, etc.
It usually simplifies your code if you make mathematical entities - e.g. vectors - immutable.
That means you don’t ever change such an object, instead you always create new ones.

Here is an example for a 2d vector.

function Vec2D(x,y) {
    this.x = x;
    this.y = y;
};

Vec2D.prototype.dotProduct = function(v) {
    return this.x*v.x+this.y*v.y;
};
Vec2D.prototype.crossProduct = function(v) {
    return this.x*v.y-this.y*v.x;
};
Vec2D.prototype.getLength = function() {
    return Math.sqrt(this.x*this.x+this.y*this.y);
};
Vec2D.prototype.add = function(v) {
    return new Vec2D(this.x+v.x, this.y+v.y);
};
Vec2D.prototype.addX = function(dx) {
    return new Vec2D(this.x+dx, this.y);
};
Vec2D.prototype.addY = function(dy) {
    return new Vec2D(this.x, this.y+dy);
};
Vec2D.prototype.withX = function(x) {
    return new Vec2D(x, this.y);
};
Vec2D.prototype.withY = function(y) {
    return new Vec2D(this.x, y);
};
Vec2D.prototype.sub = function(v) {
    return new Vec2D(this.x-v.x, this.y-v.y);
};
Vec2D.prototype.mul = function(m) {
    return new Vec2D(this.x*m, this.y*m);
};
Vec2D.prototype.div = function(d) {
    return new Vec2D(this.x/d, this.y/d);
};
Vec2D.prototype.neg = function() {
    return new Vec2D(-this.x, -this.y);
};
Vec2D.prototype.toString = function() {
    return "("+this.x+", "+this.y+")";
};
Vec2D.prototype.equals = function(v) {
    return this.x === v.x && this.y === v.y;
};

Another useful strategy is to seperate your code into several small pieces and put every piece into it’s own function.
Unfortunately due to JavaScripts bad design, that can be a little tricky.

Player.prototype.update = (function() {
  var oldPos, _this;
  
  var move = function(v) {
    oldPos = _this.pos;
    _this.pos = _this.pos.add(v);
  };
  
  var moveBack = function() {
    _this.pos = oldPos;
  };
  
  var checkCollision = function(entities) {
    for(var i = 0; i < entities.length; i++) {
      if(!entities[i].passable && _this.intersects(entities[i])) return true;
    }
    return false;
  };
  
  var tryToMove = function(d, entities) {
    move(d);
    if(checkCollision(entities)) {
      moveBack();
      return true;
    }
    return false;
  };
  
  var update = function(entities) {
    _this = this;
    if(Keyboard.isPressed(Keyboard.D)) {
      this.velocity = this.velocity.withX(10);
    } else if(Keyboard.isPressed(Keyboard.A)) {
      this.velocity = this.velocity.withX(-10);
    } else {
      this.velocity = this.velocity.withX(0);
    }
    if(!this.isJumping && Keyboard.isPressed(Keyboard.SPACE)) {
      this.isJumping = true;
      this.velocity = this.velocity.addY(-this.jumpSpeed);
    }
    if(this.velocity.y < this.grav) {
      this.velocity = this.velocity.addY(this.grav);
    }
    var steps = Math.max(this.velocity.x, this.velocity.y);
    var distance = this.velocity.div(steps);
    var isColliding = false;
    for(var i = 0; i < move && !isColliding; i++) {
      isColliding = tryToMove(distance, entities);
    }
  }
  return update;
})();

Changed to do this, even if it burns my soul a little, seeing as it’s now 2n instead of just n in runtime. But it works, and it’ll have to do for now. :slight_smile:

It’s always a good idea to actually read stuff :stuck_out_tongue:

I’m well aware, as I’m writing in both languages. However this is the only forum I am on, that has anything to do with gaming, and seeing as collision detection is a general term, then I deemed it was okay to post it here(Someone correct me if I’m wrong) and I did write in the title that it was Javascript problem and not Java. :slight_smile:

Looks like lots of good stuff, I’ll have to take a closer look at it later! :slight_smile:

31g0YE61PLQ

D’oh! I thought you were using Html+Javascript. palm