Object Smooth Movement through path - javascript

I am coding a Pacman clone. The steps that I have accomplished are the floor, the maze, as also the pacman and the movement of pacman through wall paths.
The maze is in array format where the walls are represented as "x". Also the movement should go with wasd keys from the keyboard. Currently the movement of the object is smooth and can walk in the path and change directions correctly only if I have the good timing with the hit.
I have also read this post Relevant Post and I followed some of these techniques so that I can store the key presses. After I did that I don't think that something changed from the previous design. Also when I change to a direction that is not allowed it rotates to that direction and stops moving. I want to implement this like classic Pac-man game. Below is the code of my issue.
That's the handleKeyDown function where i check for key press.
function handleKeyDown(event) {
currentlyPressedKeys[event.keyCode] = true;
if (String.fromCharCode(event.keyCode) == "A") {
curr_key=temp;
curr_key="A";
memory_key = temp;
pacRot = 0;
}
if (String.fromCharCode(event.keyCode) == "D") {
curr_key=temp;
curr_key="D";
memory_key = temp;
pacRot = 180;
}
if (String.fromCharCode(event.keyCode) == "W") {
curr_key=temp;
curr_key="W";
memory_key = temp;
pacRot = 270;
}
if (String.fromCharCode(event.keyCode) == "S") {
curr_key=temp;
curr_key="S";
memory_key = temp;
pacRot = 90;
}
}
Now the function can_move(key) that checks if the object can move to a direction
function can_move(key){
if (key == "W") {
if (stage[Math.round(y) - 1][x] == "x") {
y = Math.round(y);
return false;
} else {
return true;
}
}
if (key == "A") {
if (stage[y][Math.round(x) - 1] == "x") {
x = Math.round(x);
return false;
} else {
return true;
}
}
if (key == "S") {
if (stage[Math.round(y) + 1][x] == "x") {
y = Math.round(y);
return false;
} else {
return true;
}
}
if (key == "D") {
if (stage[y][Math.round(x) + 1] == "x") {
x = Math.round(x);
return false;
} else {
return true;
}
}
}
And finally the main moving function move_conditions that is called inside tick() after drawScene()
function move_conditions(elapsed) {
if(can_move(curr_key)==true){
if(curr_key=="W"){
ySpeed = 5;
xSpeed = 0;
y -= (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(curr_key=="A"){
ySpeed = 0;
xSpeed = 5;
x -= (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
if(curr_key=="S"){
ySpeed = 5;
xSpeed = 0;
y += (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(curr_key=="D"){
ySpeed = 0;
xSpeed = 5;
x += (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
}else if(can_move(memory_key)==true){
if(memory_key=="W"){
ySpeed = 5;
xSpeed = 0;
y -= (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(memory_key=="A"){
ySpeed = 0;
xSpeed = 5;
x -= (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
if(memory_key=="S"){
ySpeed = 5;
xSpeed = 0;
y += (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(memory_key=="D"){
ySpeed = 0;
xSpeed = 5;
x += (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
}

Related

browser freezing when in while loop (snake game)

I'm making the popular snake game for js homework.
I have a function which is meant to ensure that after an apple is eaten it moves to a different location on the canvas while not being on any part of the snake,
the function without the loop works fine (though apples are placed on the snake too):
move() {
let onSnake = true;
let x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);;
let y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);;
this.x = x;
this.y = y;
this.draw();
}
the function though with the loop ends up freezing after a few apples are eaten (right before hitting an apple):
move() {
let onSnake = true;
let x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);;
let y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);;
while (onSnake) {
onSnake = false;
x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);
y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);
for (let index = 0; index < snake.parts.length; index++) {
if (x === snake.parts[index].x || y === snake.parts[index].y) {
onSnake = true;
break;
}
}
}
this.x = x;
this.y = y;
this.draw();
}
with getRandomNumber being:
getRandomNumber(min, max) {
let r = Math.floor(Math.random() * (max - min + 1)) + min;
r = r - (r % UnitSize);
return r;
}
this is my second question on SO, don't fry me please....
I didn't get a moment to test but I suspect it's as simple as the following evalutation.
if (x === snake.parts[index].x || y === snake.parts[index].y) {
onSnake = true;
break;
}
You are accepting either X or Y collision. Meaning the apple cannot share any X or Y coordinates with any of the snake pieces. What you want instead is and I believe. It's like saying we both live on the same house because we live on the same street. No, we need to also have the same address.
As a safety, you could add a limit to how many iterations of the loop can run in the event their is no more space remaining for an apple.
let counter = 0;
while (onSnake && counter < 5000) {
onSnake = false;
x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);
y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);
for (let index = 0; index < snake.parts.length; index++) {
if (x === snake.parts[index].x && y === snake.parts[index].y) {
onSnake = true;
break;
}
}
counter += 1;
}
if (counter == 5000) {
alert("Could not find space for any more apples!");
}

Why my agent collision doesn't work (javascript)

I have an agent called cube (cube its just the name, it is a square in reality). Every cube falls and stops on the ground, and I want them to detect the other cubes and stack up.
I am having problems with this method for detecting collision: https://www.youtube.com/watch?v=GY-c2HO2liA&list=PLRqwX-V7Uu6Zy51Q-x9tMWIv9cueOFTFA
I made 2 for loops and all but it doesn't work for some reason.
this is the main script:
var cubes = [];
var nb = 10; //number of cubes
var gravity = .1;
var sz = 10; //cube size
function setup() {
createCanvas(400, 400);
for (i = 0; i < nb; i++) {
cubes.push(new Cube());
}
}
function draw() {
background(51);
for (var i = 0; i < cubes.length; i++) {
cubes[i].show();
for (var j = 0; j < cubes.length; j++) {
if (i != j && !cubes[i].collide(cubes[j]) && !(cubes[i].pos.y + sz > height)) {
cubes[i].pos.y += gravity;
}
}
}
}
this is the cube function linked with p5.js in an HTML file:
function Cube() {
this.rx = (round((random(0, width - sz)) / sz) * sz);
this.ry = (round((random(sz, height - sz)) / sz) * sz);
this.pos = createVector(this.rx, this.ry);
this.show = function() {
fill(220);
noStroke();
rect(this.pos.x, this.pos.y, sz, sz);
}
this.collide = function(other) {
if (this.pos.y + sz == other.pos.y && this.pos.x == other.pos.x) {
return true;
} else {
return false;
}
}
}
I want the cubes to stack up when they hit the ground but they only pass through each other completely ignoring the collision I've set up.
I think your problem is coming from the fact that you are using ==, please try modifying this line :
if (this.pos.y + sz == other.pos.y && this.pos.x == other.pos.x) {
into
if (this.pos.y + sz > other.pos.y && this.pos.y <= other.pos.y+sz &&
this.pos.x < other.pos.x+sz && this.pos.x + sz > other.pos.x)

how can I detect collision in a 2D tile game map

I made this basic game where I drew a map and a player, the player can move anywhere but how can I make so that it wont move when its on the tile[1] in the map?
also when I try to check if the player.x is greater than 50 it could go left it works but than if I click 2 keys at once it goes through
const context = document.querySelector("canvas").getContext("2d");
var rgb = 'rgb(' + Math.random()*256 + ',' + Math.random()*256 + ',' + Math.random()*256 + ','+Math.random() + ')';
document.onload = Loop();
var width = 1500;
var height = 800;
function Loop(){
var width = 1500;
var height = 800;
context.canvas.height = height;
context.canvas.width = width;
this.interval = setInterval(Update, 1000/100);
}
const Player = function(x, y, w, h, color) {
this.x = x; this.y = y; this.w = w; this.h = h;
this.speedY = 0; this.speedX = 0;
this.Draw = function(){
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
};
this.Move = function(){
this.x += this.speedX;
this.y += this.speedY;
};
};<code>
var player = new Player(100,100,50, 50, rgb);
var Key = {};
function Update(){
context.clearRect(0, 0, width, height);
Map();
player.Draw();
player.Move();
onkeydown = onkeyup = function(e){
player.speedX = 0;
player.speedY = 0;
e = e || event;
Key[e.keyCode] = e.type == 'keydown';
if(Key[37] || Key[65]) {player.speedX -= 2}
if(Key[38] || Key[87]) {player.speedY -= 2}
if(Key[39] || Key[68]) {player.speedX += 2}
if(Key[40] || Key[83]) {player.speedY += 2}
if(Key[32]) {player.color = 'rgb(' + Math.random()*256 + ',' + Math.random()*256 + ',' + Math.random()*256 + ','+Math.random()*1 + ')';}
};
}
var map = [
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1
];
var row = 5;
var column = 5;
function Map(){
for(let y = -1; y < column; y++){
for(let x = -1; x < row; x++){
switch(map[((y*row) + x)]) {
case 0: context.fillStyle = player.color;
break;
case 1: context.fillStyle = "#ffffff";
break;
default: context.fillStyle = "#000000";
}
context.fillRect(x*50, y*50, 50, 50);
}
}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin: auto;
border: solid 1px white;
border-radius: 10px;
}
script {
display: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
void function() {
"use strict";
// Classes
function Camera(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
}
Camera.prototype = {
set: function(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
},
pan: function(x,y) {
this.x += x || 0.0;
this.y += y || 0.0;
}
};
var nextID = 0;
function Tile(colour) {
this.id = nextID++;
this.colour = colour || "black";
}
function Map(width,height) {
this.width = width || 1;
this.height = height || 1;
this.map = [];
this.map.length = this.height;
for (var y = 0; y < this.height; ++y) {
this.map[y] = [];
this.map[y].length = width;
for (var x = 0; x < this.width; ++x) {
this.map[y][x] = Math.random() < 0.2 ?
this.TILE_WALL:
this.TILE_GRASS;
}
this.map[y][0] = this.TILE_WALL;
this.map[y][this.width - 1] = this.TILE_WALL;
}
for (var x = 0; x < this.width; ++x) {
this.map[0][x] = this.TILE_WALL;
this.map[this.height - 1][x] = this.TILE_WALL;
}
}
Map.prototype = {
TILE_WIDTH: 32.0,
TILE_HEIGHT: 32.0,
INV_TILE_WIDTH: 0.0,
INV_TILE_HEIGHT: 0.0,
TILE_AIR: new Tile("#00000000"),
TILE_GRASS: new Tile("#00AA00FF"),
TILE_WALL: new Tile("#555555FF"),
set: function(x,y,tile) {
this.map[y][x] = tile;
},
scaleX: function(x) {
return (x * this.INV_TILE_WIDTH) | 0;
},
scaleY: function(y) {
return (y * this.INV_TILE_HEIGHT) | 0;
},
isColliding: function(x,y) {
return x > -1 && x < this.width
&& y > -1 && y < this.height
&& this.map[y][x].id > 1;
},
render: function(ctx,camera) {
for (var y = 0; y < this.height; ++y) {
for (var x = 0; x < this.width; ++x) {
var tile = this.map[y][x];
var _x = x * this.TILE_WIDTH - camera.x;
var _y = y * this.TILE_HEIGHT - camera.y;
ctx.fillStyle = tile.colour;
ctx.fillRect(_x,_y,this.TILE_WIDTH - 1,this.TILE_HEIGHT - 1);
}
}
}
};
Map.prototype.INV_TILE_WIDTH = 1.0 / Map.prototype.TILE_WIDTH;
Map.prototype.INV_TILE_HEIGHT = 1.0 / Map.prototype.TILE_HEIGHT;
function Player(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
this.dx = 0.0;
this.dy = 0.0;
this.isUp = false;
this.isDown = false;
this.isLeft = false;
this.isRight = false;
}
Player.prototype = {
WIDTH: 20.0,
HEIGHT: 20.0,
ACCELERATION: 1.0,
DEACCELERATION: 0.5,
MAX_SPEED: 3.0,
tick: function(map) {
// Movement
if (this.isUp) {
this.dy -= this.ACCELERATION;
if (this.dy < -this.MAX_SPEED) {
this.dy = -this.MAX_SPEED;
}
} else if (this.dy < 0.0) {
this.dy += this.DEACCELERATION;
if (this.dy > 0.0) {
this.dy = 0.0;
}
}
if (this.isDown) {
this.dy += this.ACCELERATION;
if (this.dy > this.MAX_SPEED) {
this.dy = this.MAX_SPEED;
}
} else if (this.dy > 0.0) {
this.dy -= this.DEACCELERATION;
if (this.dy < 0.0) {
this.dy = 0.0;
}
}
if (this.isLeft) {
this.dx -= this.ACCELERATION;
if (this.dx < -this.MAX_SPEED) {
this.dx = -this.MAX_SPEED;
}
} else if (this.dx < 0.0) {
this.dx += this.DEACCELERATION;
if (this.dx > 0.0) {
this.dx = 0.0;
}
}
if (this.isRight) {
this.dx += this.ACCELERATION;
if (this.dx > this.MAX_SPEED) {
this.dx = this.MAX_SPEED;
}
} else if (this.dx > 0.0) {
this.dx -= this.DEACCELERATION;
if (this.dx < 0.0) {
this.dx = 0.0;
}
}
// Collision
if (this.dx !== 0.0) {
var minY = map.scaleY(this.y);
var maxY = map.scaleY(this.y + this.HEIGHT);
var minX = 0;
var maxX = 0;
if (this.dx < 0.0) {
minX = map.scaleX(this.x + this.dx);
maxX = map.scaleX(this.x);
} else {
minX = map.scaleX(this.x + this.WIDTH);
maxX = map.scaleX(this.x + this.WIDTH + this.dx);
}
loop:
for (var y = minY; y <= maxY; ++y) {
for (var x = minX; x <= maxX; ++x) {
if (map.isColliding(x,y)) {
this.x = this.dx < 0.0 ?
(x + 1) * map.TILE_WIDTH:
x * map.TILE_WIDTH - this.WIDTH - 1;
this.dx = 0.0;
break loop;
}
}
}
}
if (this.dy !== 0.0) {
var minX = map.scaleX(this.x);
var maxX = map.scaleX(this.x + this.WIDTH);
var minY = 0;
var maxY = 0;
if (this.dy < 0.0) {
minY = map.scaleY(this.y + this.dy);
maxY = map.scaleY(this.y);
} else {
minY = map.scaleY(this.y + this.HEIGHT);
maxY = map.scaleY(this.y + this.HEIGHT + this.dy);
}
loop:
for (var y = minY; y <= maxY; ++y) {
for (var x = minX; x <= maxX; ++x) {
if (map.isColliding(x,y)) {
this.y = this.dy < 0.0 ?
(y + 1) * map.TILE_HEIGHT:
y * map.TILE_HEIGHT - this.HEIGHT - 1;
this.dy = 0.0;
break loop;
}
}
}
}
this.x += this.dx;
this.y += this.dy;
},
render: function(ctx,camera) {
camera.set(this.x,this.y);
ctx.lineWidth = 1;
ctx.strokeStyle = "black";
ctx.fillStyle = "darkred";
ctx.beginPath();
ctx.rect(this.x - camera.x,this.y - camera.y,this.WIDTH,this.HEIGHT);
ctx.fill();
ctx.stroke();
}
};
// Variables
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var ctx = null;
var camera = null;
var map = null;
var player = null;
// Functions
function onKeyDown(e) {
switch(e.key.toUpperCase()) {
case "W": player.isUp = true; break;
case "S": player.isDown = true; break;
case "A": player.isLeft = true; break;
case "D": player.isRight = true; break;
}
}
function onKeyUp(e) {
switch(e.key.toUpperCase()) {
case "W": player.isUp = false; break;
case "S": player.isDown = false; break;
case "A": player.isLeft = false; break;
case "D": player.isRight = false; break;
}
}
function loop() {
// Tick
player.tick(map);
// Render
ctx.fillStyle = "gray";
ctx.fillRect(-canvasWidth >> 1,-canvasHeight >> 1,canvasWidth,canvasHeight);
map.render(ctx,camera);
player.render(ctx,camera);
//
requestAnimationFrame(loop);
}
// Entry point (first to execute)
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");
ctx.translate(canvasWidth >> 1,canvasHeight >> 1);
camera = new Camera(0.0,0.0);
map = new Map(10,10);
player = new Player(40.0,40.0);
map.set(1,1,map.TILE_GRASS);
addEventListener("keydown",onKeyDown);
addEventListener("keyup",onKeyUp);
loop();
}
}();
</script>
</body>
</html>
Firstly, looking at your code, there are some things that are missing which is required to implement basic collision detection and those are:
The player's current direction that he/she is moving in. This is important because it allows the function determining the collision detection to distinguish which side it is checking for the collision (Up, down, left, or right) since a player can only collide with one side at a time.
The tile's position and size. This is also very important because like the first point, there is only one side of the tile that the player can collide with and knowing the size and position can determine if it is a collision or not based on the players size and position.
Also, since you mentioned it is a basic game, the implementation below is a basic collision detection. If you were to make a more complex and bigger game, you should try looking into quad trees for more efficient collision detection:
https://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space--gamedev-374
Now this is the function for detecting collision, for the sake of readability and shortness, p will represent the player object and t would represent the tile object. This function returns whether or not the player is colliding with a tile based on their direction of movement.
function isColliding(p, t){
if (p.direction == 'up') {
return p.y +(p.height/2)-p.speedY< t.y + t.height && p.y > t.y
&& p.x + p.width > t.x && p.x < t.x + t.width;
}
if (p.direction == 'down') {
return p.y + (p.height/2)+p.speedY > t.y && p.y < t.y
&& p.x + p.width > t.x && p.x < t.x + t.width;
}
if (p.direction == 'right') {
return p.x + p.width+p.speedX > t.x && p.x < t.x
&& p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
}
if (p.direction == 'left') {
return p.x -p.speedX< t.x + t.width && p.x > t.x
&& p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
}
return false;
}
You would probably want to put this in the player move function to constantly detect for tiles as it is moving. To do that, you'd want to modify your keydown detection so that with each different keydown, it would update the player's direction, here's a simple example:
document.onkeydown = function(event){
if (event.keyCode == 87)
player.up = true;
else if (event.keyCode == 65)
player.left = true;
else if (event.keyCode == 83)
player.down = true;
else if (event.keyCode == 68)
player.right = true;
}
and another simple example for every time the player moves (user presses a keydown):
const Player= function(/*Param stuff*/){
/*Property stuff*/
//tileArray is the array (or object, your choice) of all the current tiles in the map
this.move=function(tileArray){
//Go through all tiles to see if player is colliding with any of them
for(var t in tileArray){
if(this.up){
if(isColliding(this, tileArray[t]){
//functionality for when player collides
}else{
//functionality for when player doesn't collide
}
}
//check if player is going down, left, etc
}
}
}
These are just examples of how to implement the detection. You should use it as a reference to implement it relatively to how your code function because I didn't write it based on what you posted.
PS.
Make sure to also convert the directions to false after the user stops pressing the key.

How to make collision in HTML5 Canvas?

I'm making a game in JavaScript HTML5 Canvas. It is a 2D Minecraft-like game, but I can't figure out collision detection...
I have asked my brother for help, but he doesn't know how to
make collision detection in HTML5 Canvas JavaScript.
If someone can help me, I will be very grateful.
This is my game code:
var g = document.getElementById("canvas").getContext("2d");
setInterval(update, 1000/100);
window.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
window.addEventListener("keyup", function(e) {
delete keys[e.keyCode];
});
var keys = [];
var player = {
x: 0,
y: 0,
isFalling: true,
};
var up = true;
var left = true;
var right = true;
var w = 10;
var h = 10;
var block_size = 20;
var m = {};
for(var x = 0; x < w; x++) {
m[x] = {};
for(var y = 0; y < w; y++) {
m[x][y] = "sky";
}
}
generateWorld();
function isColl(x1,y1,w1,h1,x2,y2,w2,h2) {
return(x1 <= x2 && x1+w1 >= x2 && y1 <= y2 && y1+h1 >= y2 || x2 <= x1 && x2+w2 >= x1 && y2 <= y1 && y2+h2 >= y1);
}
function update() {
g.fillStyle = "rgb(255,255,255)";
g.fillRect(0,0,200,200);
var dx = player.x/block_size;
var dy = player.y/block_size;
for(var x = 0; x < w; x++) {
for(var y = 0; y < h; y++) {
if(m[x][y] == "grass") {
g.fillStyle = "rgb(0,200,0)";
g.fillRect(x*20,y*20,20,20);
} else if(m[x][y] == "sky") {
g.fillStyle = "rgb(100,100,255)";
g.fillRect(x*20,y*20,20,20);
} else if(m[x][y] == "dirt") {
g.fillStyle = "rgb(100,40,0)";
g.fillRect(x*20,y*20,20,20);
} else if(m[x][y] == "grass") {
g.fillStyle = "rgb(0,0,255)";
g.fillRect(x*20,y*20,20,20);
} else {
g.fillStyle = "rgb(200,50,200)";
g.fillRect(x*20,y*20,20,20);
g.fillStyle = "rgb(0,0,0)";
g.fillText("404", (x*20), (y*20)+15);
}
}
}
g.fillStyle = "rgb(255,50,0)";
g.fillRect(player.x,player.y,20,20);
if(keys[38] && player.y > 0 && up) {
player.y--;
player.isFalling = false;
} else {
player.isFalling = true;
}
if(keys[39] && player.x < 180 && right) {
player.x++;
}
if(keys[37] && player.x > 0 && left) {
player.x--;
}
if(player.isFalling && player.y < 180) {
player.y++;
}
}
Thanks!
I think this might help you a lot:
https://msdn.microsoft.com/en-us/library/gg589497%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
There are couple of ways of doing this.
Consider all of your objects as spheres and check if the distance between objects are below the radius of the said spheres.
Example:
function checkCollision_Sph(centerX,centerY,radius,centerX_2,centerY_2,radius_2){
distance = Math.sqrt((centerX_2 - centerX)^2 + (centerY_2 - centerY)^2)
if(distance <= (radius+radius_2)){
//Distance between spheres is less than the sum of theirs radius, colliding!
}
Consider all of your objects as rectangles and check if the rectangle's bounding boxes are overlapping each other.
Example:
function checkCollision_Rec(x1,w1,y1,h1,x2,w2,y2,h2){
//x1, x2 = Left
//x1 + w1, x2 + w2 = Right
//y1, y2 = Bottom
//y1 - h1, y2 - h2 = Top
if((y1 < y2) ||
((y1 - h1) > y2) ||
(x1 > (x2 + w2)) ||
((x1 + w1) < x2)
){
//Is not colliding!
}
else{
//Is colliding!
}
I found a good page that has similar examples that might help you to figure it out: Basic collision detection in 2d

Using EaselJS sprite sheet in existing code

I want to modify existing code which uses an image to animate, and use a sprite sheet instead. I'm using the EaselJS library for this.
The piece of code that creates the objects for animation:
function initStageObjects(){
car = new Car('img/car.png',canvas.width()/2,canvas.height()/2);
}
And this is the complete code:
$(window).load(function(){
$(document).ready(function(){
// Canvas Variables
var canvas = $('#canvas');
var context = canvas.get(0).getContext('2d');
var canvasWidth = canvas.width();
var canvasHeight = canvas.height();
// Keyboard Variables
var leftKey = 37;
var upKey = 38;
var rightKey = 39;
var downKey = 40;
// Keyboard event listeners
$(window).keydown(function(e){
var keyCode = e.keyCode;
if(keyCode == leftKey){
car.left = true;
} else if(keyCode == upKey){
car.forward = true;
} else if(keyCode == rightKey){
car.right = true;
} else if (keyCode == downKey){
car.backward = true;
}
});
$(window).keyup(function(e){
var keyCode = e.keyCode;
if(keyCode == leftKey){
car.left = false;
} else if(keyCode == upKey){
car.forward = false;
} else if(keyCode == rightKey){
car.right = false;
} else if (keyCode == downKey){
car.backward = false;
}
});
// Start & Stop button controlls
var playAnimation = true;
var startButton = $('#startAnimation');
var stopButton = $('#stopAnimation');
startButton.hide();
startButton.click(function(){
$(this).hide();
stopButton.show();
playAnimation = true;
updateStage();
});
stopButton.click(function(){
$(this).hide();
startButton.show();
playAnimation = false;
});
// Resize canvas to full screen
function resizeCanvas(){
canvas.attr('width', $(window).get(0).innerWidth);
canvas.attr('height', $(window).get(0).innerHeight);
canvasWidth = canvas.width();
canvasHeight = canvas.height();
}
resizeCanvas();
$(window).resize(resizeCanvas);
function initialise(){
initStageObjects();
drawStageObjects();
updateStage();
}
// Car object and properties
function Car(src, x, y){
this.image = new Image();
this.image.src = src;
this.x = x;
this.y = y;
this.vx = 0;
this.vy = 0;
this.angle = 90;
this.topSpeed = 5;
this.acceleration = 0.1;
this.reverse = 0.1;
this.brakes = 0.3;
this.friction = 0.05;
this.handeling = 15;
this.grip = 15;
this.minGrip = 5;
this.speed = 0;
this.drift = 0;
this.left = false;
this.up = false;
this.right = false;
this.down = false;
}
// Create any objects needed for animation
function initStageObjects(){
car = new Car('img/car.png',canvas.width()/2,canvas.height()/2);
}
function drawStageObjects(){
context.save();
context.translate(car.x,car.y);
context.rotate((car.angle + car.drift) * Math.PI/180);
context.drawImage(car.image, -25 , (-47 + (Math.abs(car.drift / 3))));
// context.fillRect(-5, -5, 10, 10);
context.restore();
}
function clearCanvas(){
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.beginPath();
}
function updateStageObjects(){
// Faster the car is going, the worse it handels
if(car.handeling > car.minGrip){
car.handeling = car.grip - car.speed;
}
else{
car.handeling = car.minGrip + 1;
}
// Car acceleration to top speed
if(car.forward){
if(car.speed < car.topSpeed){
car.speed = car.speed + car.acceleration;
}
}
else if(car.backward){
if(car.speed < 1){
car.speed = car.speed - car.reverse;
}
else if(car.speed > 1){
car.speed = car.speed - car.brakes;
}
}
// Car drifting logic
if(car.forward && car.left){
if(car.drift > -35){
car.drift = car.drift - 3;
}
}
else if(car.forward && car.right){
if(car.drift < 35){
car.drift = car.drift + 3;
}
}
else if(car.forward && !car.left && car.drift > -40 && car.drift < -3){
car.drift = car.drift + 3;
}
else if(car.forward && !car.right && car.drift < 40 && car.drift > 3){
car.drift = car.drift - 3;
}
if(car.drift > 3){
if(!car.forward && !car.left){
car.drift = car.drift - 4;
}
}
else if(car.drift > -40 && car.drift < -3){
if(!car.forward && !car.right){
car.drift = car.drift + 4;
}
}
// General car handeling when turning
if(car.left){
car.angle = car.angle - (car.handeling * car.speed/car.topSpeed);
} else if(car.right){
car.angle = car.angle + (car.handeling * car.speed/car.topSpeed);
}
// Use this div to display any info I need to see visually
$('#stats').html("Score: 0");
// Constant application of friction / air resistance
if(car.speed > 0){
car.speed = car.speed - car.friction;
} else if(car.speed < 0) {
car.speed = car.speed + car.friction;
}
// Update car velocity (speed + direction)
car.vy = -Math.cos(car.angle * Math.PI / 180) * car.speed;
car.vx = Math.sin(car.angle * Math.PI / 180) * car.speed;
// Plot the new velocity into x and y cords
car.y = car.y + car.vy;
car.x = car.x + car.vx;
}
// Main animation loop
function updateStage(){
clearCanvas();
updateStageObjects();
drawStageObjects();
if(playAnimation){
setTimeout(updateStage, 25);
}
}
// Initialise the animation loop
initialise();
});
});//]]>
// JavaScript Document
How could i replace the image being used by the sprite i created?
Even though you maybe could implement a createjs.SpriteSheet into a non-Createjs/non-EaselJS project I would strongly recommend you not to do that, EaselJS-classes where not designed to be used as single modular classes in any kind of project, they best work together in the framework. In the end you probably will need more time and probably end up with more code by trying get everything to work than with just converting your (yet still small) project to EaselJS all together. So learn something new today and refacture your project to EaselJS ;-)
but if you want more work, continue reading:
A createjs.SpriteSheet basically only handles SpriteSheet data and you can use mySpriteSheet.getFrame(int); to get the image and the source-rect to that frame so you can draw it to your canvas. But a SpriteSheet alone won't handle animations for you, so you would have to advance the "playhead" every frame yourself(go back to frame 0 if at the end ect...), or you can implement another createjs-class called createjs.BitmapAnimation - however, drawing this to your canvas would again require additional code or yet an additional createjs-class: you see where this is getting.

Categories

Resources