Node Socket.io object trouble - javascript

I'm having some trouble with Node Socket.IO
I have put all my code in pastebins
Server file
var io = require("socket.io").listen(1337);
io.set("log level", "0");
var particles = [];
var players = [];
var remove_loop;
var particle;
io.sockets.on("connection", function(socket) {
//connection
socket.emit("hello");
console.log("A new connection has been established");
//new player
socket.on("new_player", function() {
players.push(socket.id);
console.log("New player connected.");
console.log("ID: " + socket.id);
});
//new particle
socket.on("new_particle", function(data) {
particle = data;
socket.broadcast.emit("particles_data", particle);
});
});
Game file
window.onload = function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//display settings
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
setInterval(function() {
if(canvas.width != window.innerWidth || canvas.height != window.innerHeight) {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
}, 1000);
//remove cursor
document.getElementById("canvas").style.cursor = "none";
//server connection
var socket = io.connect("http://localhost:1337");
//variables
var update_loop;
var draw_loop;
var local_player;
var mouse_x;
var mouse_y;
var remote_players;
var particles;
var remove_loop;
var explosion;
var background_color;
init();
function init() {
//initialize
local_player = new Player();
background_color = "000000";
explosion = true;
remote_players = [];
particles = [];
draw_loop = setInterval(function() { draw(); }, 10);
update_loop = setInterval(function() { update(); }, 10);
//server
socket.on("hello", function() {
socket.emit("new_player");
});
socket.on("particles_data", function(data) {
particles.push(data);
});
};
function update() {
for(var i = 0; i < particles.length; i++) {
particles[i].move();
}
};
function draw() {
//background_color
ctx.fillStyle = "#" + background_color;
ctx.fillRect(0, 0, canvas.width, canvas.height);
//remove particles
setInterval(function() {
if(!remove_loop) remove_loop = setInterval(function() {
setTimeout(function() {
if(particles.length > 0) {
particles.shift();
}
}, 1);
}, 20);
}, 10);
//particles
for(var i = 0; i < particles.length; i++) {
if(particles[i].x < canvas.width &&
particles[i].y < canvas.width) {
if(particles[i].x < canvas.width &&
particles[i].y < canvas.height) {
particles[i].draw(ctx);
}
}
}
}
function newParticle() {
socket.emit("new_particle", new Particle(local_player.x, local_player.y, local_player.color));
particles.push(new Particle(local_player.x, local_player.y, local_player.color));
};
//move mouse
canvas.onmousemove = function(event) {
if(!event) event = window.event;
local_player.x = event.pageX;
local_player.y = event.pageY;
newParticle();
};
//touch mouse (phones/tables)
canvas.onmousedown = function(event) {
if(!event) event = window.event;
local_player.x = event.pageX;
local_player.y = event.pageY;
newParticle();
}
};
Player file
function Player() {
this.x = 0;
this.y = 0;
this.color = Math.floor(Math.random() * 999999);
while (this.color < 100000) {
this.color = Math.floor(Math.random() * 999999);
}
};
Particle file
function Particle(x, y, color) {
this.start_x = x;
this.start_y = y;
this.speed = Math.floor(Math.random() * 3 + 1);
this.x = x;
this.y = y;
this.size = Math.floor(Math.random() * 3 + 1);
this.color = "#" + color;
this.direction = Math.floor(Math.random() * 8);
this.move = function() {
this.speedDecreaseChance = Math.random(Math.random() * 100);
//Chance that the particle loses it's velocity like you would
//see with real particles
if(this.speedDecreaseChance > 3) { this.speed -= 0.5 };
//It's important that they move -AWAY- from X and Y.
this.subDirection = Math.floor(Math.random() * 2);
if(this.direction == 0) { //upper left
if(this.subDirection == 0) {
this.x -= this.speed;
} else if(this.subDirection == 1) {
this.y -= this.speed;
}
} else if(this.direction == 1) { //bottom right
if(this.subDirection == 0) {
this.x += this.speed;
} else if(this.subDirection == 1) {
this.y += this.speed;
}
} else if(this.direction == 2) { //upper right
if(this.subDirection == 0) {
this.x += this.speed;
} else if(this.subDirection == 1) {
this.y -= this.speed;
}
} else if(this.direction == 3) { //bottom left
if(this.subDirection == 0) {
this.x -= this.speed;
} else if(this.subDirection == 1) {
this.y += this.speed;
}
} else if(this.direction == 4) { //left
this.x -= this.speed/1.5;
if(this.subDirection == 0) {
this.y -= this.speed;
} else if(this.subDirection == 1) {
this.y += this.speed;
}
} else if(this.direction == 5) { //up
this.y -= this.speed/1.5;
if(this.subDirection == 0) {
this.x -= this.speed;
} else if(this.subDirection == 1) {
this.x += this.speed;
}
} else if(this.direction == 6) { //right
this.x += this.speed/1.5;
if(this.subDirection == 0) {
this.y -= this.speed;
} else if(this.subDirection == 1) {
this.y += this.speed;
}
} else if(this.direction == 7) { //down
this.y += this.speed/1.5;
if(this.subDirection == 0) {
this.x -= this.speed;
} else if(this.subDirection == 1) {
this.x += this.speed;
}
}
};
this.draw = function(ctx) {
ctx.beginPath();
ctx.shadowColor = this.color;
ctx.shadowBlur = 8;
ctx.arc(this.x, this.y, this.size ,0 ,2*Math.PI);
ctx.fillStyle = this.color;
ctx.fill();
ctx.shadowBlur = 0;
};
};
Now the problem is that there's an error in my traffic between the server and all sockets.
What I want to do is make it possible that when one has particle objects to send them to the server and the server sends them to everyone except the original sender.
I did this through socket.broadcast.emit();
This went successful.
However when the objects arrive at the other sockets I get this error:
Uncaught TypeError: Object #<Object> has no method 'move'
Uncaught TypeError: Object #<Object> has no method 'draw'
For every particle object that exists at that moment.
If anyone knows why my objects lose their methods and would be so friendly to help a programmer in distress I'd be absolutely delighted :)
Thanks in advance!

From what I know Socket.IO expected JSON data as 2nd parameter for the emit function. JSON data format doesn't support function as values according to http://www.json.org/
You are sending a javascript object and expecting the object to be created from the json on a different client. This is not how Socket.IO communication works.
Instead of doing that you should send the data required to construct the object and use that to construct the object on the client.
You could do some thing like the following
Change this line
socket.emit("new_particle", new Particle(local_player.x, local_player.y, local_player.color));
to
socket.emit("new_particle", {x:local_player.x, y:local_player.y, color:local_player.color});
and then the event listener
socket.on("particles_data", function(data) {
particles.push(data);
});
to handle the creation of object from the data
socket.on("particles_data", function(data) {
particles.push(new Particle(data.x, data.y, data.color));
});

When an object is serialized to JSON, it loses all type information. This is what socket.io is transmitting.
var particle = new Particle(1, 2, 'ccc');
console.log(JSON.stringify(particle)); // {"start_x":1,"start_y":2,"speed":3,"x":1,"y":2,"size":3,"color":"#ccc","direction":5}
You can't tell if it's a particle or a monkey or something else.
When you receive this object, you need to convert it to a Particle first.
socket.on("particles_data", function(data) {
var particle = ...;
particles.push(particle);
});
You could define a constructor and create it again:
var particle = new Particle(data.x, data.y, data.color);
Or you could change its prototype:
var particle = $.extend(new Particle(), data); // here using jQuery helper method

Related

Why isnt collision detection working? (p5 js frame work)

I created a collision detection between Snake and BasicEnemy. I created a for loop to make five different enemies but the collision detection doesn't get called on any of the enemies that were created from the for loop. The collision only works with the one BasicEnemy object. Why isn't collision function being called for all of the enemies inside the array? Thank you.
Sketch.js
var snake;
var food;
var basicEnemy;
var scl = 20;
var enemies = [];
function setup() {
createCanvas(600, 500);
snake = new Snake();
basicEnemy = new BasicEnemy();
//** CREATE FIVE ENEMIES **
for (var i = 0; i < 5; i++) {
enemies[i] = new BasicEnemy();
}
}
// **FUNCTION WHEN SNAKE HITS ENEMY**
function collision() {
console.log("hit!");
}
function draw() {
background(51);
//Draw snake
snake.update();
snake.show();
//Draw basicEnemy
basicEnemy.update();
basicEnemy.show();
//** LOOP THROUGH ENEMIES AND UPDATE AND SHOW **
for (var i = 0; i < enemies.length; i++) {
enemies[i].show();
enemies[i].update();
if (enemies[i].hits(snake)) {
collision();
}
}
}
function keyPressed() {
if (keyCode === UP_ARROW){
snake.dir(0, -1);
} else if (keyCode === DOWN_ARROW) {
snake.dir(0, 1);
} else if (keyCode === LEFT_ARROW) {
snake.dir(-1 , 0);
} else if (keyCode === RIGHT_ARROW) {
snake.dir(1 , 0);
}
}
BasicEnemy.js
function BasicEnemy() {
this.x = random(700);
this.y = random(700);
this.velX = 15;
this.velY = 15;
}
//** FUNCTION TO CHECK IF ENEMY AND SNAKE ARE IN THE SAME LOCATION **
this.hits = function (pos) {
var = d = dist(this.x, this.y, pos.x, pos.y);
if(d < 1) {
return true;
} else {
return false;
}
}
this.show = function () {
fill(255, 0, 100);
rect(this.x, this.y, scl, scl);
}
Snake.js
function Snake() {
this.x = 0;
this.y = 0;
this.xspeed = 1;
this.yspeed = 0;
this.update = function() {
this.x = this.x + this.xspeed * scl;
this.y = this.y + this.yspeed * scl;
this.x = constrain(this.x, 0, width - scl);
this.y = constrain(this.y, 0, height - scl);
}
this.show = function() {
fill(255);
rect(this.x, this.y, scl, scl);
}
this.dir = function (x , y) {
this.xspeed = x;
this.yspeed = y;
}
}
Because you're essentially checking for the distance between the top left corners of the snake and the enemy, this'll only return true, if they completely overlap.
Use an AABB collision detection instead:
return this.x + scl >= pos.x && this.x <= pos.x + scl && this.y + scl >= pos.y && this.y <= pos.y + scl;
This returns true, if the first rectangle contains the second rectangle.
MDN says:
One of the simpler forms of collision detection is between two rectangles that are axis aligned — meaning no rotation. The algorithm works by ensuring there is no gap between any of the 4 sides of the rectangles. Any gap means a collision does not exist.

I don't want my "player" to leave the screen, how do I prevent this?

This is my JavaScript. Near the bottom you will see an addEventListener, for the keydown event. In that function, the keydown code is there. That code is wrapped in an if function, what goes in the if function, to stop the player from leaving the canvas.
function initCanvas() {
var canvas = document.getElementById('my_canvas');
var ctx = canvas.getContext('2d');
var cW = ctx.canvas.width;
var cH = ctx.canvas.height;
var dist = 10;
function Player() {
this.x = 0, this.y = 0, this.w = 50, this.h = 50;
this.render = function() {
ctx.fillStyle = "orange";
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
var player = new Player();
player.x = 100;
player.y = 225;
function animate() {
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
player.render();
}
var animateInterval = setInterval(animate, 30);
document.addEventListener('keydown', function(event) {
var key_press = String.fromCharCode(event.keyCode);
if (//I don't know what should go here) {
if (key_press == "W") {
player.y -= dist;
} else if (key_press == "S") {
player.y += dist;
} else if (key_press == "A") {
player.x -= dist;
} else if (key_press == "D") {
player.x += dist;
}
}
});
}
window.onload = initCanvas();
document.addEventListener('keydown', function(event) {
var key_press = String.fromCharCode(event.keyCode);
if (//I don't know what should go here) {
if (key_press == "W" && player.y >= dist) {
player.y -= dist;
} else if (key_press == "S" && player.y <= (cH - dist)) {
player.y += dist;
} else if (key_press == "A" && player.x >= dist) {
player.x -= dist;
} else if (key_press == "D" && player.x < (cW - dist)) {
player.x += dist;
}
}
});
The extra checks will check that he is not at the edge of the canvas neither at a distance < dist from the edge. Assuming the upper left corner is (0,0).
Note that it would be nicer to move the user to the edge of the canvas when he is at a distance < dist from it. I'll leave this up to you.

Processing js jump system

I`m trying to make a jump system in processing.js and its done, but not quite what I wanted. The thing is that like this, the jump height depends on how long the key is pressed. What I wanted is the same height regardless how long the key is pressed.
Here is my code:
var keys = [];
void keyPressed() {
keys[keyCode] = true;
};
void keyReleased() {
keys[keyCode] = false;
};
var Player = function(x, y) {
this.x = x;
this.y = y;
this.g = 0;
this.vel = 2;
this.jumpForce = 7;
this.jump = false;
};
Player.prototype.draw = function() {
fill(255,0,0);
noStroke();
rect(this.x, this.y, 20, 20);
};
Player.prototype.move = function() {
if(this.y < ground.y) {
this.y += this.g;
this.g += 0.5;
this.jump = false;
}
if(keys[RIGHT]) {
this.x += this.vel;
}
if(keys[LEFT]) {
this.x -= this.vel;
}
//preparing to jump
if(keys[UP] && !this.jump) {
this.jump = true;
}
// if jump is true, than the ball jumps... after, the gravity takes place pulling the ball down...
if(this.jump) {
this.y -= this.jumpForce;
}
};
Player.prototype.checkHits = function() {
if(this.y+20 > ground.y) {
this.g = 0;
this.y = ground.y-20;
jump = false;
}
};
Var Ground = function(x, y, label) {
this.x = x;
this.y = y;this.label = label;
};
Ground.prototype.draw = function() {
fill(0);
rect(0, 580, width, 20);
};
var player = new Player(width/2, height/2);
var ground = new Ground(0, 580, "g");
void draw() {
background(255,255,255);
player.draw();
player.move();
player.checkHits();
ground.draw();
}
Any help would be aprreciated.
What are you doing here is like: "If this(the Player) isn't touching the ground then, if (in addition) key UP is pressed, jump!". So it will allow the player jumping even if he is in the air... increasing the jump height
You should do something like: "if player is touching the ground allow to jump (if key UP pressed), otherwise you are already jumping!".
Something like this:
if(this.y < ground.y) {
this.y += this.g;
this.g += 0.5;
this.jump = true;
}
else{
this.jump = false;
}
if(keys[UP] && !this.jump) {
this.jump = true;
this.y -= this.jumpForce;
}

Collision detection not working for canvas

I've been trying to make a game but there are obstacles. I have a (ball) player and a square (obstacle) and I can't figure out how to make a collision detection thing to work. Here's my code so far:
<!DOCTYPE html>
<html>
<head>
<title>Ball Race</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
<canvas id="canvas" width="800" height="200"></canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
var circle = function (x, y, radius, fillCircle) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
};
var drawRect = function (x, y) {
ctx.fillRect(x, y, 20, 20)
}
var Object = function () {
this.x = width / 4;
this.y = height / 4;
}
// The Ball constructor
var Ball = function () {
this.x = width / 2;
this.y = height / 2;
this.xSpeed = 5;
this.ySpeed = 0;
};
// Update the ball's position based on its speed
Ball.prototype.move = function () {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 11) {
this.x = 11;
} else if (this.x > width - 11) {
this.x = width - 11;
} else if (this.y < 11) {
this.y = 11;
} else if (this.y > height - 11) {
this.y = height - 11;
}
};
// Draw the ball at its current position
Ball.prototype.draw = function () {
circle(this.x, this.y, 10, true);
};
Object.prototype.draw = function () {
drawRect(this.x, this.y)
}
//collision types
Object.prototype.checkCollision = function () {
var col1 = this.x == ball.x && this.y == ball.y;
var col2 = this.x + 1 == ball.x && this.y == ball.y;
var col3 = this.x + 2 == ball.x && this.y == ball.y;
var col4 = this.x + 3 == ball.x && this.y == ball.y;
if (col1 || col2 || col3 || col4) {
alert("COLLISION!");
}
}
// Set the ball's direction based on a string
Ball.prototype.setDirection = function (direction) {
if (direction === "up") {
this.xSpeed = 0;
this.ySpeed = -5;
} else if (direction === "down") {
this.xSpeed = 0;
this.ySpeed = 5;
} else if (direction === "left") {
this.xSpeed = -5;
this.ySpeed = 0;
} else if (direction === "right") {
this.xSpeed = 5;
this.ySpeed = 0;
} else if (direction === "stop") {
this.xSpeed = 0;
this.ySpeed = 0;
}
};
// Create the ball object
var ball = new Ball();
var object = new Object();
// An object to convert keycodes into action names
var keyActions = {
32: "stop",
37: "left",
38: "up",
39: "right",
40: "down"
};
// The keydown handler that will be called for every keypress
$("body").keydown(function (event) {
var direction = keyActions[event.keyCode];
ball.setDirection(direction);
});
// The animation function, called every 30 ms
setInterval(function () {
ctx.clearRect(0, 0, width, height);
ball.draw();
ball.move();
object.draw();
ctx.strokeRect(0, 0, width, height);
}, 30);
setInterval(function () {
object.checkCollision();
}, 1)
</script>
</body>
</html>
How would you code this? Please give an example similar to mine.
It seems like most of the functionality is there you're just missing the correct logic in the checkCollision. I would change it to something like:
Object.prototype.checkCollision = function() {
var colx = (ball.x-ball.radius<this.x&&ball.x+ball.radius>this.x)||(ball.x-ball.radius<this.x+20&&ball.x+ball.radius>this.x+20);
var coly = (ball.y-ball.radius<this.y&&ball.y+ball.radius>this.y)||(ball.y-ball.radius<this.y+20&&ball.y+ball.radius>this.y+20);
if(colx&&coly){
console.log('collision');
}
}
colx checks the x collision, to see if the ball is in between the objects position. coly does the same thing but for the y variable. If both are true then there is a collision.
I added radius variable to Ball
var Ball = function() {
this.x = width / 2;
this.y = height / 2;
this.xSpeed = 5;
this.ySpeed = 0;
this.radius = 10;
};
Here is a fiddle

Remove object on collision with ball

I know you can fillRect right? And you can clearRect. But what happens if there's an animation and you have to remove an object although it would be redrawn from setInterval. How would you remove the fillRect?
Here's an example:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
var circle = function (x, y, radius, fillCircle, color) {
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
};
var drawRect = function (x, y, color) {
ctx.fillStyle = color;
ctx.fillRect(x, y, 20, 20)
}
var Object = function (xPos, yPos) {
this.x = xPos;
this.y = yPos;
}
// The Ball constructor
var Ball = function () {
this.x = width / 2;
this.y = height / 2;
this.xSpeed = 0;
this.ySpeed = 0;
this.radius = 10;
};
// Update the ball's position based on its speed
Ball.prototype.move = function () {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 11) {
this.x = 11;
} else if (this.x > width - 11) {
this.x = width - 11;
} else if (this.y < 11) {
this.y = 11;
} else if (this.y > height - 11) {
this.y = height - 11;
}
};
// Draw the ball at its current position
Ball.prototype.draw = function () {
circle(this.x, this.y, 10, true, "Black");
};
Object.prototype.draw = function () {
drawRect(this.x, this.y, "Black")
}
Object.prototype.drawKey = function (color) {
drawRect(this.x, this.y, "Yellow")
}
Object.prototype.checkCollision = function (direction) {
return (ball.x-ball.radius < this.x + 20)
&& (ball.x+ball.radius > this.x)
&& (ball.y-ball.radius < this.y + 20)
&& (ball.y+ball.radius > this.y)
;
}
function draw() {
ctx.clearRect(0, 0, width, height);
ball.draw();
object1.draw("Blue");
object2.draw();
object3.draw();
object4.draw();
object5.draw();
key.drawKey();
ctx.strokeRect(0, 0, width, height);
}
function simulate() {
for (z = 0; z < 5; z++) {
var prev_ball_x = ball.x;
var prev_ball_y = ball.y;
ball.move();
// handle collision here
if (object1.checkCollision() || object2.checkCollision() || object3.checkCollision() || object4.checkCollision() || object5.checkCollision()) {
ball.setDirection('stop');
// reset ball's position so they do not overlap
ball.x = prev_ball_x;
ball.y = prev_ball_y;
}
if (key.checkCollision()) {
ball.x = prev_ball_x;
ball.y = prev_ball_y;
}
}
$("body").keyup(function (event) {
ball.setDirection('stop');
})
}
setInterval(function () {
// separate drawing and simulating phases
simulate();
draw();
}, 30);
// Set the ball's direction based on a string
Ball.prototype.setDirection = function (direction) {
if (direction === "up") {
this.xSpeed = 0;
this.ySpeed = -1;
} else if (direction === "down") {
this.xSpeed = 0;
this.ySpeed = 1;
} else if (direction === "left") {
this.xSpeed = -1;
this.ySpeed = 0;
} else if (direction === "right") {
this.xSpeed = 1;
this.ySpeed = 0;
} else if (direction === "stop") {
this.xSpeed = 0;
this.ySpeed = 0;
}
};
// Create the ball object
var ball = new Ball();
var object1 = new Object(50, 0);
var object2 = new Object(50, 20);
var object3 = new Object(50, 40);
var object4 = new Object(50, 60);
var object5 = new Object(50, 80);
var key = new Object(70, 70);
// An object to convert keycodes into action names
var keyActions = {
37: "left",
38: "up",
39: "right",
40: "down"
};
// The keydown handler that will be called for every keypress
$("body").keydown(function (event) {
var direction = keyActions[event.keyCode];
ball.setDirection(direction);
});
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
<canvas id="canvas" width="800" height="200"></canvas>
You move around a ball with your arrow keys. When I collide with the yellow block, I want it to disappear. Using clearRect would not work simply because it would be redrawn in the setInterval. How would I make it disappear?
Generally when you have several items in a game you place them into a sort of objects array, then when you draw you loop through and call .draw() on each item. Doing it this way allows you to remove items you do not want (such as key), and as such it will no longer be drawn. In your case one thing we could do (assuming there is only a single key) is give your ball a hasKey property. And on collision set it from false to true. Then inside draw, if you wish to also remove the collisions you would do !ball.hasKey && key.checkCollision() inside your collision conditional for the key:
if(!ball.hasKey) key.drawKey();
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
var circle = function (x, y, radius, fillCircle, color) {
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
};
var drawRect = function (x, y, color) {
ctx.fillStyle = color;
ctx.fillRect(x, y, 20, 20)
}
var Object = function (xPos, yPos) {
this.x = xPos;
this.y = yPos;
}
// The Ball constructor
var Ball = function () {
this.x = width / 2;
this.y = height / 2;
this.xSpeed = 0;
this.ySpeed = 0;
this.radius = 10;
this.hasKey = false;
};
// Update the ball's position based on its speed
Ball.prototype.move = function () {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 11) {
this.x = 11;
} else if (this.x > width - 11) {
this.x = width - 11;
} else if (this.y < 11) {
this.y = 11;
} else if (this.y > height - 11) {
this.y = height - 11;
}
};
// Draw the ball at its current position
Ball.prototype.draw = function () {
circle(this.x, this.y, 10, true, "Black");
};
Object.prototype.draw = function () {
drawRect(this.x, this.y, "Black")
}
Object.prototype.drawKey = function (color) {
drawRect(this.x, this.y, "Yellow")
}
Object.prototype.checkCollision = function (direction) {
return (ball.x-ball.radius < this.x + 20)
&& (ball.x+ball.radius > this.x)
&& (ball.y-ball.radius < this.y + 20)
&& (ball.y+ball.radius > this.y)
;
}
function draw() {
ctx.clearRect(0, 0, width, height);
ball.draw();
object1.draw("Blue");
object2.draw();
object3.draw();
object4.draw();
object5.draw();
if(!ball.hasKey) key.drawKey();
ctx.strokeRect(0, 0, width, height);
}
function simulate() {
for (z = 0; z < 5; z++) {
var prev_ball_x = ball.x;
var prev_ball_y = ball.y;
ball.move();
// handle collision here
if (object1.checkCollision() || object2.checkCollision() || object3.checkCollision() || object4.checkCollision() || object5.checkCollision()) {
ball.setDirection('stop');
// reset ball's position so they do not overlap
ball.x = prev_ball_x;
ball.y = prev_ball_y;
}
if (!ball.hasKey && key.checkCollision()) {
ball.x = prev_ball_x;
ball.y = prev_ball_y;
ball.hasKey = true;
}
}
$("body").keyup(function (event) {
ball.setDirection('stop');
})
}
setInterval(function () {
// separate drawing and simulating phases
simulate();
draw();
}, 30);
// Set the ball's direction based on a string
Ball.prototype.setDirection = function (direction) {
if (direction === "up") {
this.xSpeed = 0;
this.ySpeed = -1;
} else if (direction === "down") {
this.xSpeed = 0;
this.ySpeed = 1;
} else if (direction === "left") {
this.xSpeed = -1;
this.ySpeed = 0;
} else if (direction === "right") {
this.xSpeed = 1;
this.ySpeed = 0;
} else if (direction === "stop") {
this.xSpeed = 0;
this.ySpeed = 0;
}
};
// Create the ball object
var ball = new Ball();
var object1 = new Object(50, 0);
var object2 = new Object(50, 20);
var object3 = new Object(50, 40);
var object4 = new Object(50, 60);
var object5 = new Object(50, 80);
var key = new Object(70, 70);
// An object to convert keycodes into action names
var keyActions = {
37: "left",
38: "up",
39: "right",
40: "down"
};
// The keydown handler that will be called for every keypress
$("body").keydown(function (event) {
var direction = keyActions[event.keyCode];
ball.setDirection(direction);
});
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
<canvas id="canvas" width="800" height="200"></canvas>

Categories

Resources