Detecting collision on canvas border - javascript

I am making a little game with my friends but i am trying to detect the collision when bumping in the the walls of the canvas, and I made it work but when i hit the wall my caracter gets stuck.. and i dont know how to find out a way to make him move again. Do you think any of you guys could help me out with this one. Thanks for all help!
Javascript / jQuery:
function Player() {
this.w = 50;
this.h = 60;
this.x = (cW / 2) - (this.w / 2);
this.y = (cH / 2) - (this.h / 2);
this.name = username.value;
this.nw = ctx.measureText(this.name).width; // username.clientWidth + 1;
this.src = playerImage;
this.dx = 0;
this.dy = 0;
this.render = function() {
ctx.drawImage(this.src, this.x, this.y, this.w, this.h);
ctx.fillStyle = 'orange';
ctx.font = '15px Arial, sans-serif';
// fixa x-värdet
ctx.fillText(this.name, (this.x + this.w / 2) - (this.nw / 2), (this.y - 6));
}
}
var player = new Player();
function animate() {
if(player.x > 0 && player.y > 0 && player.x + player.w < cW && player.y + player.h < cH) {
player.x += spd * player.dx;
player.y += spd * player.dy;
}
else {
// Need code here to release player from wall
}
ctx.save();
ctx.clearRect(0, 0, cW, cH);
ctx.drawImage(bg, 0, 0);
player.render();
ctx.rotate(-.4);
raining();
ctx.restore();
}
var animateInterval = setInterval(animate, 1000/60);
document.addEventListener('keydown', function(e) {
var key_press = String.fromCharCode(e.keyCode);
switch(key_press) {
case 'W':
player.dy = -1;
break;
case 'A':
player.dx = -1;
break;
case 'S':
player.dy = 1;
break;
case 'D':
player.dx = 1;
break;
default:
break;
}
});
document.addEventListener('keyup', function(e) {
var key_press = String.fromCharCode(e.keyCode);
switch(key_press) {
case 'W':
player.dy = 0;
break;
case 'A':
player.dx = 0;
break;
case 'S':
player.dy = 0;
break;
case 'D':
player.dx = 0;
break;
default:
break;
}
});

The problem you are having is the following:
Suppose your character is moving at the speed of 10 pixels per frame, the character position is currently 595px (the right side of the character) and the canvas width is 600.
On the current frame you are checking if there is a collision: there's none so you add the speed to the current position and you get 605px. Now on the next frame the character is out the bounds and you cannot move him anymore because the player.x + player.width > canvas.width
What you can do:
1: You check for the collision and move the character back inside the viewport:
if (player.x + player.width > canvas.width) {
player.x = canvas.width - player.width;
}
Because the collision check fails now, you can move him wherever you want.
You should do this check for all the sides, but the logic is different for each side, this is sample code for collision with the left wall:
if (player.x < 0) {
player.x = 0;
}
2: In your if statement you should add the speed in your calculations and not move the character if the player.x + player.vx exceeds canvas.width, but I prefer the first method as you can actually be at the side of the viewport
Tip with working with canvas positions: always round off your positions at the render level:
this.render = function() {
ctx.drawImage(this.src, Math.round(this.x), Math.round(this.y), this.w, this.h);
...
}

Related

If statement inside requestanimationframe continues even if parameters aren't met

I'm making a little video game, where the background (platform) moves down with my character (square) jumps. On line 113 I have tried different strategies to implement this thought, and that is the closest it has gotten to work. The issue is that even when the square velocity is 0, the platform velocity isn't. I have been stuck for a week now, and feels like javascript is the problem (even though I know it isn't).
canvasmain.width = window.innerWidth;
canvasmain.height = window.innerHeight;
//CHARACTER:
const square = {
height: 75,
jumping: true,
width: 75,
x: canvasmain.width / 2,
xVelocity: 0,
y: canvasmain.height / 2,
yVelocity: 0
};
//floor
const platform = {
height: 30,
width: 100,
x: square.x,
xVelocity: 0,
y: square.y + square.height,
yVelocity:0
}
//MOVEMENT:
const controller = {
left: false,
right: false,
up: false,
keyListener: function (event) {
let key_state = (event.type == "keydown") ? true : false;
switch (event.keyCode) {
case 37: // left arrow
controller.left = key_state;
break;
case 38: // up arrow
controller.up = key_state;
break;
case 39: // right arrow
controller.right = key_state;
break;
}
}
};
const loop = function () {
if (controller.up && square.jumping == false) {
square.yVelocity -= 30;
square.jumping = true;
}
if (controller.left) {
square.xVelocity -= 0.5;
}
if (controller.right) {
square.xVelocity += 0.5;
}
square.yVelocity += 1.5;// gravity
square.x += square.xVelocity;
square.y += square.yVelocity;
square.xVelocity *= 0.9;// friction
square.yVelocity *= 0.9;// friction
// if square is falling below floor line
if (square.y > canvasmain.height - 75) {
square.jumping = false;
square.y = canvasmain.height - 75;
square.yVelocity = 0;
}
// if square is going off the left of the screen
if (square.x < 0) {
square.x = 0;
} else if (square.x > canvasmain.width - 75) {// if square goes past right boundary
square.x = canvasmain.width - 75;
}
// Creates the backdrop for each frame
context.fillStyle = "#394129";
context.fillRect(0, 0, canvasmain.width, canvasmain.height); // x, y, width, height
// Creates and fills the cube for each frame
context.fillStyle = "#8DAA9D"; // hex for cube color
context.beginPath();
context.rect(square.x, square.y, square.width, square.height);
context.fill();
// Creates the "ground" for each frame
context.fillStyle = "#202020";
context.beginPath();
context.rect(platform.x, platform.y, platform.width, platform.height)
context.fill();
// call update when the browser is ready to draw again
window.requestAnimationFrame(loop);
//platform
platform.y += platform.yVelocity;
console.log(square.yVelocity)
if (square.yVelocity > 0.1 ) {
platform.yVelocity = 1.5
};
if (square.yVelocity < 0 ) {
platform.yVelocity = -1.5
};
}
window.addEventListener("keydown", controller.keyListener)
window.addEventListener("keyup", controller.keyListener);
window.requestAnimationFrame(loop);
You're not reseting the value of yVelocity.
Got it guys, thx #Teemu, I just needed to set it to 0 if it wasn't the if's. Dang, really took a while. if (square.yVelocity > 0 ) {platform.yVelocity = 1.5} else{ platform.yVelocity = 0}; if (square.yVelocity < 0 ) {platform.yVelocity = -1.5} else { platform.yVelocity = 0} }
edit: frick, it only moves the platform when the cube is going up, not down ;-;

Grid system needed to fix a position issue on canvas?

I am trying to create a simple snake game. My problem is, most of the times when the snake meets the food, the position of the snake is not how it should be.
For a better understanding, please look at this screenshot where the snake (white) meets the food (green):
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
x = 0,
y = 0,
speed = 3;
x_move = speed,
y_move = 0,
food_position_x = Math.floor(Math.random() * canvas.width) - 20;
food_position_y = Math.floor(Math.random() * canvas.height) - 20;
// Drawing
function draw() {
requestAnimationFrame(function() {
draw();
});
// Draw the snake
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.closePath();
// Draw the food
ctx.beginPath();
ctx.rect(food_position_x, food_position_y, 20, 20);
ctx.fillStyle = "lightgreen";
ctx.fill();
ctx.closePath();
// Increase the value of x and y in order to animate
x = x + x_move;
y = y + y_move;
}
draw();
// Key Pressing
document.addEventListener('keydown', function(event) {
switch(event.keyCode) {
case 40: // Moving down
if (x_move != 0 && y_move != -1) {
x_move = 0;
y_move = speed;
}
break;
case 39: // Moving right
if (x_move != -1 && y_move != 0) {
x_move = speed;
y_move = 0;
}
break;
case 38: // Moving top
if (x_move != 0 && y_move != 1) {
x_move = 0;
y_move = -speed;
}
break;
case 37: // Moving left
if (x_move != 1 && y_move != 0) {
x_move = -speed;
y_move = 0;
}
break;
}
});
canvas { background-color:red }
<canvas id="canvas" width="600" height="400"></canvas>
So it seems like I would need a simple grid system but how would I go ahead on this to fix this issue?
I can't see the code for your collision. But I think you have a mistake in your origin. The origin of your squares is not in the middle, it is on the top left corner.

Have a dot follow a path selected path

What i am trying to do is to click a position on a canvas and have a dot follow a path directly to the position i have selected.
this is my code so far.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var rect = canvas.getBoundingClientRect()
//
var clickedChords = {
x: 0,
y: 0
};
var player = {
x: 100,
y: 100
};
canvas.addEventListener("mousedown", getChords, false);
function getChords(e) {
clickedChords.x = e.pageX - rect.left;
clickedChords.y = e.pageY - rect.top;
}
function draw() {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle= 'black';
ctx.beginPath();
ctx.arc(clickedChords.x,clickedChords.y,3,0,360);
ctx.arc(player.x,player.y,3,0,360);
ctx.fill();
if(player.x > clickedChords.x && player.x !== clickedChords.x){
player.x -= 1;
}
if(player.x < clickedChords.x && player.x !== clickedChords.x){
player.x += 1;
}
if(player.y < clickedChords.y && player.y !== clickedChords.y){
player.y += 1;
}
if(player.y > clickedChords.y && player.y !== clickedChords.y){
player.y -= 1;
}
}setInterval(draw, 10);
Right now all i have managed to do was to get the dot to follow a 45 degree angle then hit and follow the x or y value of my clicked position. I have tried to use the slope formula but i am clueless on how to implement it into my code.
Thank you for helping as i am truly stuck.
You can use interpolation for this:
var t = 0, // will be in range [0.0, 1.0]
oldPlayerX, // need these for interpolation
oldPlayerY;
function getChords(e) {
clickedChords.x = e.pageX - rect.left;
clickedChords.y = e.pageY - rect.top;
oldPlayerX = player.x, // copy these as we need them as-is
oldPlayerY = player.y;
draw();
}
function draw() {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle= 'black';
ctx.beginPath();
ctx.arc(clickedChords.x,clickedChords.y,3,0,360);
ctx.arc(player.x,player.y,3,0,360);
ctx.fill();
if (t <= 1) {
player.x = oldPlayerX + (clickedChords.x - oldPlayerX) * t;
player.y = oldPlayerY + (clickedChords.y - oldPlayerY) * t;
t += 0.05; // determines speed
requestAnimationFrame(draw); // use this instead of setInterval
}
}
The interpolation itself happens on these lines:
player.x = oldPlayerX + (clickedChords.x - oldPlayerX) * t;
player.y = oldPlayerY + (clickedChords.y - oldPlayerY) * t;
It basically do a difference between new and old position. t will determine how much of that difference is added to the original position, ie. if t=0 then nothing, if t=1 then full difference is added to old position which obviously equals the new position. Anything in between (for t) will add a percentage of that allowing you to animate the point.
requestAnimationFrame allow you to sync the animation to monitor refresh. A setInterval value of 10 ms is way to short for the browser to handle (minimum is 16.7ms for a screen refresh # 60 Hz).
Hope this helps!
We can just use some basic trigonometry:
var angle = Math.atan2(clickedChords.y - player.y, clickedChords.x - player.x);
player.x += Math.cos(angle);
player.y += Math.sin(angle);
Here is a fiddle:
http://jsfiddle.net/AniHouse/w2vCc/1/

Limit the rectangle to be drawn only once using javascript

I want to draw the rectangle using the mouse down event only when the button is clicked. I have added the javascript code for a button event but its not working as it start drawing when the checkbox is clicked but keeps drawing even if the check box is unchecked. I want this to draw only when the button is checked. can I limit the rectangle to be drawn only once.
My fiddle is : http://jsfiddle.net/G6tLn/7/
I am modifying the simonsaris code for the selection handles using the mouse events.
Please help.
<html>
<head>
<title>Canvas Demo</title>
<style type="text/css">
hr{margin:0px; padding:0px;}
form, table {display:inline; margin:0px; padding:0px;}
.ck-button {
margin:4px;
background-color:#8080FF;
border-radius:4px;
border:1px solid #D0D0D0;
overflow:auto;
float:left;
}
.ck-button:hover {
background-color:#B2B2FF;
}
.ck-button label {
float:left;
width:4.0em;
}
.ck-button label span {
text-align:center;
padding:3px 0px;
display:block;
}
.ck-button label input {
position:absolute;
top:-20px;
}
.ck-button input:checked + span {
background-color:#0000FF;
color:white;
}
#container2 {
position: relative;
}
#canvas2 {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="canvas2"
width="450"
height="450"
style="border:2px solid black">
Your browser does not support the HTML5 canvas tag.
</canvas>
<div class="ck-button">
<input type="checkbox" id="btnROI" value="ROI" onclick="CallRoi()">
<span>ROI</span>
<input type="checkbox" id="btnMetric" value="Metric" onclick="CallMetric()">
<span>Metric</span>
</div>
<script type="text/javascript">
// holds all our boxes
var boxes2 = [];
// New, holds the 8 tiny boxes that will be our selection handles
// the selection handles will be in this order:
// 0 1 2
// 3 4
// 5 6 7
var selectionHandles = [];
// Hold canvas information
var canvas;
var ctx;
var WIDTH;
var HEIGHT;
var INTERVAL = 20; // how often, in milliseconds, we check to see if a redraw is needed
var isDrag = false;
var isResizeDrag = false;
var isCreationDrag = false;
var expectResize = -1; // New, will save the # of the selection handle if the mouse is over one.
var mx, my, startMx, startMy; // mouse coordinates
// when set to true, the canvas will redraw everything
// invalidate() just sets this to false right now
// we want to call invalidate() whenever we make a change
var canvasValid = false;
// The node (if any) being selected.
// If in the future we want to select multiple objects, this will get turned into an array
var mySel = null;
// The selection color and width. Right now we have a red selection with a small width
var mySelColor = '#CC0000';
var mySelWidth = 2;
var mySelBoxColor = 'darkred'; // New for selection boxes
var mySelBoxSize = 6;
// we use a fake canvas to draw individual shapes for selection testing
var ghostcanvas;
var gctx; // fake canvas context
// since we can drag from anywhere in a node
// instead of just its x/y corner, we need to save
// the offset of the mouse when we start dragging.
var offsetx, offsety;
// Padding and border style widths for mouse offsets
var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
// Box object to hold data
function Box2() {
this.x = 0;
this.y = 0;
this.w = 1; // default width and height?
this.h = 1;
this.fill = '#444444';
}
// New methods on the Box class
Box2.prototype = {
// we used to have a solo draw function
// but now each box is responsible for its own drawing
// mainDraw() will call this with the normal canvas
// myDown will call this with the ghost canvas with 'black'
draw:function (context, optionalColor) {
if (context === gctx) {
context.fillStyle = 'black'; // always want black for the ghost canvas
} else {
context.fillStyle = this.fill;
}
// We can skip the drawing of elements that have moved off the screen:
if (this.x > WIDTH || this.y > HEIGHT) return;
if (this.x + this.w < 0 || this.y + this.h < 0) return;
context.fillRect(this.x, this.y, this.w, this.h);
// draw selection
// this is a stroke along the box and also 8 new selection handles
if (mySel === this) {
context.strokeStyle = mySelColor;
context.lineWidth = mySelWidth;
context.strokeRect(this.x, this.y, this.w, this.h);
// draw the boxes
var half = mySelBoxSize / 2;
// 0 1 2
// 3 4
// 5 6 7
// top left, middle, right
selectionHandles[0].x = this.x - half;
selectionHandles[0].y = this.y - half;
selectionHandles[1].x = this.x + this.w / 2 - half;
selectionHandles[1].y = this.y - half;
selectionHandles[2].x = this.x + this.w - half;
selectionHandles[2].y = this.y - half;
//middle left
selectionHandles[3].x = this.x - half;
selectionHandles[3].y = this.y + this.h / 2 - half;
//middle right
selectionHandles[4].x = this.x + this.w - half;
selectionHandles[4].y = this.y + this.h / 2 - half;
//bottom left, middle, right
selectionHandles[6].x = this.x + this.w / 2 - half;
selectionHandles[6].y = this.y + this.h - half;
selectionHandles[5].x = this.x - half;
selectionHandles[5].y = this.y + this.h - half;
selectionHandles[7].x = this.x + this.w - half;
selectionHandles[7].y = this.y + this.h - half;
context.fillStyle = mySelBoxColor;
for (var i = 0; i < 8; i++) {
var cur = selectionHandles[i];
context.fillRect(cur.x, cur.y, mySelBoxSize, mySelBoxSize);
}
}
} // end draw
}
//Initialize a new Box, add it, and invalidate the canvas
function addRect(x, y, w, h, fill) {
var rect = new Box2;
rect.x = x;
rect.y = y;
rect.w = w
rect.h = h;
rect.fill = fill;
boxes2.push(rect);
invalidate();
}
function CallRoi(){
var oROI = document.getElementById("btnROI");
console.log(oROI.checked);
if (oROI.checked) {
init2();
}
}
function CallMetric(){
var oMetric = document.getElementById("btnMetric");
console.log(btnMetric.checked);
if (oMetric.checked) {
init1();
console.log("hello");
}
}
// initialize our canvas, add a ghost canvas, set draw loop
// then add everything we want to intially exist on the canvas
function init2() {
canvas = document.getElementById('canvas2');
HEIGHT = canvas.height;
WIDTH = canvas.width;
ctx = canvas.getContext('2d');
ghostcanvas = document.createElement('canvas');
ghostcanvas.height = HEIGHT;
ghostcanvas.width = WIDTH;
gctx = ghostcanvas.getContext('2d');
//fixes a problem where double clicking causes text to get selected on the canvas
canvas.onselectstart = function () {
return false;
}
// fixes mouse co-ordinate problems when there's a border or padding
// see getMouse for more detail
if (document.defaultView && document.defaultView.getComputedStyle) {
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
}
// make mainDraw() fire every INTERVAL milliseconds
setInterval(mainDraw, INTERVAL);
// set our events. Up and down are for dragging,
// double click is for making new boxes
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
canvas.ondblclick = myDblClick;
canvas.onmousemove = myMove;
// set up the selection handle boxes
for (var i = 0; i < 8; i++) {
var rect = new Box2;
selectionHandles.push(rect);
}
}
function init1() {
canvas = document.getElementById('canvas2');
HEIGHT = canvas.height;
WIDTH = canvas.width;
ctx = canvas.getContext('2d');
ghostcanvas = document.createElement('canvas');
ghostcanvas.height = HEIGHT;
ghostcanvas.width = WIDTH;
gctx = ghostcanvas.getContext('2d');
//fixes a problem where double clicking causes text to get selected on the canvas
canvas.onselectstart = function () { return false; }
// fixes mouse co-ordinate problems when there's a border or padding
// see getMouse for more detail
if (document.defaultView && document.defaultView.getComputedStyle) {
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
}
// make mainDraw() fire every INTERVAL milliseconds
setInterval(mainDraw, INTERVAL);
// set our events. Up and down are for dragging,
// double click is for making new boxes
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
canvas.ondblclick = myDblClick;
canvas.onmousemove = myMove;
// set up the selection handle boxes
for (var i = 0; i < 8; i ++) {
var rect = new Box2;
selectionHandles.push(rect);
}
// add custom initialization here:
// add a large green rectangle
addRect(50,180,50,50, 'green');
}
//wipes the canvas context
function clear(c) {
c.clearRect(0, 0, WIDTH, HEIGHT);
}
// Main draw loop.
// While draw is called as often as the INTERVAL variable demands,
// It only ever does something if the canvas gets invalidated by our code
function mainDraw() {
if (canvasValid == false) {
clear(ctx);
// Add stuff you want drawn in the background all the time here
// draw all boxes
var l = boxes2.length;
for (var i = 0; i < l; i++) {
boxes2[i].draw(ctx); // we used to call drawshape, but now each box draws itself
}
// Add stuff you want drawn on top all the time here
canvasValid = true;
}
}
// Happens when the mouse is moving inside the canvas
function myMove(e) {
if (isDrag) {
getMouse(e);
mySel.x = mx - offsetx;
mySel.y = my - offsety;
// something is changing position so we better invalidate the canvas!
invalidate();
} else if (isResizeDrag) {
// time ro resize!
var oldx = mySel.x;
var oldy = mySel.y;
// 0 1 2
// 3 4
// 5 6 7
switch (expectResize) {
case 0:
mySel.x = mx;
mySel.y = my;
mySel.w += oldx - mx;
mySel.h += oldy - my;
break;
case 1:
mySel.y = my;
mySel.h += oldy - my;
break;
case 2:
mySel.y = my;
mySel.w = mx - oldx;
mySel.h += oldy - my;
break;
case 3:
mySel.x = mx;
mySel.w += oldx - mx;
break;
case 4:
mySel.w = mx - oldx;
break;
case 5:
mySel.x = mx;
mySel.w += oldx - mx;
mySel.h = my - oldy;
break;
case 6:
mySel.h = my - oldy;
break;
case 7:
mySel.w = mx - oldx;
mySel.h = my - oldy;
break;
}
invalidate();
}
getMouse(e);
// if there's a selection see if we grabbed one of the selection handles
if (mySel !== null && !isResizeDrag) {
for (var i = 0; i < 8; i++) {
// 0 1 2
// 3 4
// 5 6 7
var cur = selectionHandles[i];
// we dont need to use the ghost context because
// selection handles will always be rectangles
if (mx >= cur.x && mx <= cur.x + mySelBoxSize &&
my >= cur.y && my <= cur.y + mySelBoxSize) {
// we found one!
expectResize = i;
invalidate();
switch (i) {
case 0:
this.style.cursor = 'nw-resize';
break;
case 1:
this.style.cursor = 'n-resize';
break;
case 2:
this.style.cursor = 'ne-resize';
break;
case 3:
this.style.cursor = 'w-resize';
break;
case 4:
this.style.cursor = 'e-resize';
break;
case 5:
this.style.cursor = 'sw-resize';
break;
case 6:
this.style.cursor = 's-resize';
break;
case 7:
this.style.cursor = 'se-resize';
break;
}
return;
}
}
// not over a selection box, return to normal
isResizeDrag = false;
expectResize = -1;
this.style.cursor = 'auto';
}
}
// Happens when the mouse is clicked in the canvas
function myDown(e) {
if (document.getElementById('btnROI').checked === false) return;
getMouse(e);
//we are over a selection box
if (expectResize !== -1) {
isResizeDrag = true;
return;
}
clear(gctx);
var l = boxes2.length;
for (var i = l - 1; i >= 0; i--) {
// draw shape onto ghost context
boxes2[i].draw(gctx, 'black');
// get image data at the mouse x,y pixel
var imageData = gctx.getImageData(mx, my, 1, 1);
var index = (mx + my * imageData.width) * 4;
// if the mouse pixel exists, select and break
if (imageData.data[3] > 0) {
mySel = boxes2[i];
offsetx = mx - mySel.x;
offsety = my - mySel.y;
mySel.x = mx - offsetx;
mySel.y = my - offsety;
isDrag = true;
invalidate();
clear(gctx);
return;
}
}
// havent returned means we have selected nothing
// mySel = null;
addRect(mx, my, 0, 0, 'rgba(220,205,65,0.7)');
mySel = boxes2[boxes2.length - 1];
// console.log("box", box);
offsetx = mx - mySel.x;
offsety = my - mySel.y;
mySel.x = mx - offsetx;
mySel.y = my - offsety;
isResizeDrag = true;
expectResize = 7;
// getMouse(e);
// startMx = mx;
// startMy = my;
// clear the ghost canvas for next time
// clear(gctx);
// invalidate because we might need the selection border to disappear
// invalidate();
}
function myUp(e) {
isDrag = false;
isResizeDrag = false;
expectResize = -1;
if (isCreationDrag) {
// alert("end creation drag");
getMouse(e);
isCreationDrag = false;
addRect(startMx, startMy, mx - startMx, my - startMy, 'rgba(220,205,65,0.7)');
}
}
// adds a new node
function myDblClick(e) {
getMouse(e);
// for this method width and height determine the starting X and Y, too.
// so I left them as vars in case someone wanted to make them args for something and copy this code
var width = 50;
var height = 50;
addRect(mx - (width / 2), my - (height / 2), width, height, 'green');
}
function invalidate() {
canvasValid = false;
}
// Sets mx,my to the mouse position relative to the canvas
// unfortunately this can be tricky, we have to worry about padding and borders
function getMouse(e) {
var element = canvas, offsetX = 0, offsetY = 0;
if (element.offsetParent) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// Add padding and border style widths to offset
offsetX += stylePaddingLeft;
offsetY += stylePaddingTop;
offsetX += styleBorderLeft;
offsetY += styleBorderTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY
}
</script>
</body>
</html>
Add this line
if(!$("#btnROI").is(":checked") || boxes2.length > 0) return;
at the beginning of the myDown function (line 336 of the fiddle) to allow only one box to be drawn, and only when ROI is checked.
Updated fiddle: http://jsfiddle.net/G6tLn/21

Multiple setInterval in a HTML5 Canvas game

I'm trying to achieve multiple animations in a game that I am creating using Canvas (it is a simple ping-pong game). This is my first game and I am new to canvas but have created a few experiments before so I have a good knowledge about how canvas work.
First, take a look at the game here.
The problem is, when the ball hits the paddle, I want a burst of n particles at the point of contact but that doesn't came right. Even if I set the particles number to 1, they just keep coming from the point of contact and then hides automatically after some time.
Also, I want to have the burst on every collision but it occurs on first collision only. I am pasting the code here:
//Initialize canvas
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
W = window.innerWidth,
H = window.innerHeight,
particles = [],
ball = {},
paddles = [2],
mouse = {},
points = 0,
fps = 60,
particlesCount = 50,
flag = 0,
particlePos = {};
canvas.addEventListener("mousemove", trackPosition, true);
//Set it's height and width to full screen
canvas.width = W;
canvas.height = H;
//Function to paint canvas
function paintCanvas() {
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, W, H);
}
//Create two paddles
function createPaddle(pos) {
//Height and width
this.h = 10;
this.w = 100;
this.x = W/2 - this.w/2;
this.y = (pos == "top") ? 0 : H - this.h;
}
//Push two paddles into the paddles array
paddles.push(new createPaddle("bottom"));
paddles.push(new createPaddle("top"));
//Setting up the parameters of ball
ball = {
x: 2,
y: 2,
r: 5,
c: "white",
vx: 4,
vy: 8,
draw: function() {
ctx.beginPath();
ctx.fillStyle = this.c;
ctx.arc(this.x, this.y, this.r, 0, Math.PI*2, false);
ctx.fill();
}
};
//Function for creating particles
function createParticles(x, y) {
this.x = x || 0;
this.y = y || 0;
this.radius = 0.8;
this.vx = -1.5 + Math.random()*3;
this.vy = -1.5 + Math.random()*3;
}
//Draw everything on canvas
function draw() {
paintCanvas();
for(var i = 0; i < paddles.length; i++) {
p = paddles[i];
ctx.fillStyle = "white";
ctx.fillRect(p.x, p.y, p.w, p.h);
}
ball.draw();
update();
}
//Mouse Position track
function trackPosition(e) {
mouse.x = e.pageX;
mouse.y = e.pageY;
}
//function to increase speed after every 5 points
function increaseSpd() {
if(points % 4 == 0) {
ball.vx += (ball.vx < 0) ? -1 : 1;
ball.vy += (ball.vy < 0) ? -2 : 2;
}
}
//function to update positions
function update() {
//Move the paddles on mouse move
if(mouse.x && mouse.y) {
for(var i = 1; i < paddles.length; i++) {
p = paddles[i];
p.x = mouse.x - p.w/2;
}
}
//Move the ball
ball.x += ball.vx;
ball.y += ball.vy;
//Collision with paddles
p1 = paddles[1];
p2 = paddles[2];
if(ball.y >= p1.y - p1.h) {
if(ball.x >= p1.x && ball.x <= (p1.x - 2) + (p1.w + 2)){
ball.vy = -ball.vy;
points++;
increaseSpd();
particlePos.x = ball.x,
particlePos.y = ball.y;
flag = 1;
}
}
else if(ball.y <= p2.y + 2*p2.h) {
if(ball.x >= p2.x && ball.x <= (p2.x - 2) + (p2.w + 2)){
ball.vy = -ball.vy;
points++;
increaseSpd();
particlePos.x = ball.x,
particlePos.y = ball.y;
flag = 1;
}
}
//Collide with walls
if(ball.x >= W || ball.x <= 0)
ball.vx = -ball.vx;
if(ball.y > H || ball.y < 0) {
clearInterval(int);
}
if(flag == 1) {
setInterval(emitParticles(particlePos.x, particlePos.y), 1000/fps);
}
}
function emitParticles(x, y) {
for(var k = 0; k < particlesCount; k++) {
particles.push(new createParticles(x, y));
}
counter = particles.length;
for(var j = 0; j < particles.length; j++) {
par = particles[j];
ctx.beginPath();
ctx.fillStyle = "white";
ctx.arc(par.x, par.y, par.radius, 0, Math.PI*2, false);
ctx.fill();
par.x += par.vx;
par.y += par.vy;
par.radius -= 0.02;
if(par.radius < 0) {
counter--;
if(counter < 0) particles = [];
}
}
}
var int = setInterval(draw, 1000/fps);
Now, my function for emitting particles is on line 156, and I have called this function on line 151. The problem here can be because of I am not resetting the flag variable but I tried doing that and got more weird results. You can check that out here.
By resetting the flag variable, the problem of infinite particles gets resolved but now they only animate and appear when the ball collides with the paddles. So, I am now out of any solution.
I can see 2 problems here.
your main short term problem is your use of setinterval is incorrect, its first parameter is a function.
setInterval(emitParticles(particlePos.x, particlePos.y), 1000/fps);
should be
setInterval(function() {
emitParticles(particlePos.x, particlePos.y);
}, 1000/fps);
Second to this, once you start an interval it runs forever - you don't want every collision event to leave a background timer running like this.
Have an array of particles to be updated, and update this list once per frame. When you make new particles, push additional ones into it.

Categories

Resources