How to avoid a square to make an other one disappear an take his color when I animate in HTML5 inside a canvas tag? - html

I begin to animate a blue square in HTML5 inside a canvas tag, I add another red square as enemy; but when I move the blue square, the red one disappear and the blue one turn red. In fact, I want to keep the color of the blue square and I don't want the red one disappear, how can I solve this problem?
var x = 10;
var y = 360;
var xEnnemy = 190;
var yEnnemy = 10;
var v = 4;
var width = 400;
var height = 400;
var can = document.getElementById("can");
var ctx = can.getContext("2d");
ctx.fillStyle = "skyblue";
ctx.fillRect(x, y, 40, 40);
ctx.fillStyle = "red";
ctx.fillRect(xEnnemy, yEnnemy, 20, 20);
window.onkeydown = function direc(e) {
//Move left
if (e.keyCode == 37 && x > 0) {
x -= v;
}
//Move up
if (e.keyCode == 38 && y > 0) {
y -= v;
}
//Move right
if (e.keyCode == 39 && x < (width - 40)) {
x += v;
}
//Move down
if (e.keyCode == 40 && y < (height - 40)) {
y += v;
}
ctx.clearRect(0, 0, width, height);
ctx.fillRect(x, y, 40, 40);
}
function ennemy() {
ctx.fillStyle = "red";
ctx.fillRect(xEnnemy, yEnnemy, 40, 40);
}
#can {
border: 1px solid black;
}
<html>
<body>
<canvas id="can" width="400" height="400"></canvas>
</body>
</html>

Using ctx.clearRect(0, 0, width, height); clears the entire scene so you need to redraw everything.
You probably want to define a drawPlayer function similar to ennemy like:
function drawPlayer(){
ctx.fillStyle = "skyblue";
ctx.fillRect(x, y, 40, 40);
}
Then, after updating the game state you'd call:
ctx.clearRect(0, 0, width, height);
drawPlayer();
ennemy();
This will update the canvas with the new positions and with the appropriate colors.

Look at what you are doing in the: function direc(e) {
ctx.clearRect(0, 0, width, height);
ctx.fillRect(x, y, 40, 40);
That is effectively wiping the canvas and only drawing one rectangle...
Here is what I would do
var player = {x:10, y:100, v: 4}
var enemy = {x:190, y:10};
var can = document.getElementById("can");
var ctx = can.getContext("2d");
window.onkeydown = function direc(e) {
if (e.keyCode == 37 && player.x > 0)
player.x -= player.v; // Move left
if (e.keyCode == 38 && player.y > 0)
player.y -= player.v; // Move up
if (e.keyCode == 39 && player.x < (can.width - 40))
player.x += player.v; // Move right
if (e.keyCode == 40 && player.y < (can.height - 40))
player.y += player.v; // Move down
draw()
}
function draw() {
ctx.clearRect(0, 0, can.width, can.height);
ctx.fillStyle = "skyblue";
ctx.fillRect(player.x, player.y, 40, 40);
ctx.fillStyle = "red";
ctx.fillRect(enemy.x, enemy.y , 20, 20);
}
draw()
#can {
border: 1px solid black;
}
<canvas id="can" width="400" height="160"></canvas>
I consolidated all the drawing in one location function draw() any time we need to draw we can call that, at the moment you only have one event: onkeydown but as your game gets more complex very likely you will have more and they all will require drawing, we just call the same function.
Also I introduced objects player = {x:10, y:100, v: 4} that keep all the properties of the player in one object, that makes the code easier to read

Related

HTML canvas collision adjusting hitbox

Hello first time asking a question and I would appreciate any help as I code just for fun. I'm making a simple game in canvas and need help to adjust the hitbox on two objects. I read several other threads that touch on the subject but couldn't find one that answers my question.
Example of what is happening
As seen from the image the hitbox of the smiley face extends beyond the actual image that is drawn. The actual image in the game will be more complex than a smiley face. However using the bounding box method does not account for what the user does not see so on screen, as the images do not look like they are colliding but in reality they are. I thought of trying to clip the image by drawing a triangle within the hitbox and then doing some calculations based on the area. This is what I came up with so far.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var player = {
x: 0,
y: 0,
width: 100,
height: 100
}
var obstacle = {
x: 150,
y: 100,
width: 100,
height: 100
};
document.addEventListener("keydown", keyDownHandler);
function keyDownHandler(e) {
ctx.clearRect(0,0,canvas.width,canvas.height);
if(e.keyCode === 37) {
player.x -= 10;
}
else if(e.keyCode === 38) {
player.y -= 10;
}
else if(e.keyCode === 39) {
player.x += 10;
}
else if(e.keyCode === 40) {
player.y += 10;
}
function drawTriangle(){
ctx.beginPath();
ctx.moveTo(player.x+player.width,player.y+player.height-40);
ctx.lineTo(player.x+player.width-40,player.y+player.height);
ctx.lineTo(player.x+player.width,player.y+player.height);
ctx.closePath();
ctx.fillStyle="orange";
ctx.fill();
}
function drawObstacle(){
ctx.beginPath();
ctx.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height);
ctx.closePath();
}
function colorChange(){
var color = "black";
var triArea = (player.y+player.height-40)*(player.x+player.width-40)/2;
if(player.x+player.width >= obstacle.x &&
player.x <= obstacle.x+obstacle.width &&
player.y <= obstacle.y+obstacle.height &&
player.y+player.height >= obstacle.y){
if(triArea <= 5500 && triArea != 5250){
color = "red";
}
else {
color = "green";
}
document.getElementById("playerArea").innerHTML = ((player.x+player.width)*(player.y+player.height));
document.getElementById("triangleArea").innerHTML = triArea;
}
else{
color = "black";
}
ctx.fillStyle = color;
}
ctx.strokeRect(player.x,player.y,player.width,player.height);
colorChange();
drawObstacle();
ctx.closePath();
drawTriangle();
}
https://codepen.io/brucelin82/pen/aqQLxW?editors=1010
The obstacle will change to red if a collision has occurred but not past the triangle. Once the collision extends beyond the triangle the obstacle will turn to green. The code is still a work in progress but I was just wondering if I'm on the right track or if there is an easier method to account for the empty space within the image. Thank you in advance for any direction you can give me.

Canvas, animate line to move up and down

I have created a horizontal line in HTML5 Canvas. I want to animate the line to move infinity up and down. Is it possible?
function horizontal_line() {
context.beginPath();
context.moveTo(100, 100);
context.lineTo(5000, 100);
context.strokeStyle = "Green";
context.stroke();
}
For an animation you will need to have a way to draw different frames, and in each frame you have to delete the previous one, calculate the new position of the line, and then draw the line again:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "Green";
var posY = 0;
var lineLength = 10;
var speed = 2;
function drawLine() {
ctx.beginPath();
ctx.moveTo(10, posY);
ctx.lineTo(10, posY+lineLength);
ctx.stroke();
}
function moveLine () {
posY += speed;
if (posY < 0 || posY > canvas.height) {
speed = speed * -1;
}
}
function loop() {
// clear old frame;
ctx.clearRect(0,0,canvas.width, canvas.height);
moveLine();
drawLine();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
<canvas id="canvas"></canvas>
In this example requestAnimationFrame is what provides you the frames you need, so the function loop() gets called over and over again. In there we clear the old frame with clearRect(), calculate the new position, and then we draw the new Line with drawLine().

Sprites Blinking

So basically i had some code of a car that has speed and everything, now i want another one with the same properties. So i duplicated the whole code and changed the other cars url and all of the variables for it. I get 2 cars on my canvas but they keep blinking. I dont know why that is happening.
You can see it for yourself on JsBin:
http://jsbin.com/fekutakime/3/edit
The car code that i duplicated is:
//Setting the canvas and context
var canvas = document.getElementById('gameCanvas');
var context = canvas.getContext('2d');
//Uploading car
var car = new Image();
car.src = "http://images.clipartpanda.com/car-top-view-clipart-red-racing-car-top-view-fe3a.png";
//Setting properties of car
var x = 450;
var y = 730;
var speed = 10;
var angle = 990;
var mod = 0;
//Event listeners for keys
window.addEventListener("keydown", keypress_handler, false);
window.addEventListener("keyup", keyup_handler, false);
//Interval for animation
var moveInterval = setInterval(function () {
draw();
}, 30);
//Drawing the car turning and changing speed
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
x += (speed * mod) * Math.cos(Math.PI / 180 * angle);
y += (speed * mod) * Math.sin(Math.PI / 180 * angle);
context.save();
context.translate(x, y);
context.rotate(Math.PI / 180 * angle);
context.drawImage(car, -(car.width / 2), -(car.height / 2));
context.restore();
}
//Setting the keys
function keyup_handler(event) {
if (event.keyCode == 38 || event.keyCode == 40) {
mod = 0;
}
}
//Setting all of the keys
function keypress_handler(event) {
console.log(x, y);
if (event.keyCode == 38) {
mod = 1;
}
if (event.keyCode == 40) {
mod = -1;
}
if (event.keyCode == 37) {
angle -= 5;
}
if (event.keyCode == 39) {
angle += 5;
}
}

html5 canvas animation. leaving a trail and reset button

I'm pretty new to this and I got the animation working by watching a youtube tutorial.
Here is a canvas animation of a keyboard controlled car.
http://jsfiddle.net/unn9P/
canvas = document.getElementById('canvas');
c = canvas.getContext('2d');
c.clear = function() {
this.clearRect(0,0,1500,1500) };
function wait(fn) {
window.setTimeout(fn, 250) }
function repeat(fn) {
if (requestAnimationFrame) {
var advance = function() {fn(); requestAnimationFrame(advance);};
requestAnimationFrame(advance);
} else window.setInterval(fn, 50);
}
var dx = 0, dy = 0, mousex = 0, mousey=0, mouseclicks = 0;
document.onkeydown = function(e) {
var key = e.keyCode;
if (key == 37) dx=-1;
else if (key == 38) dy=-1;
else if (key == 39) dx=1;
else if (key == 40) dy=1;
else return true;
return false;
};
document.onkeyup = function(e) {
var key = e.keyCode;
if (key == 37 || key == 39) dx=0;
else if (key == 38 || key == 40) dy=0;
else return true;
return false;
};
canvas.onmousemove = function(e) {
var rect = canvas.getBoundingClientRect();
mousex = e.clientX - rect.left;
mousey = e.clientY - rect.top;
};
canvas.onmousedown = function(e) {mouseclicks++;};
a = new Image();
a.src = 'http://o.ooli.ca/car_top.png';
wait(function(){
x = 50;
y = 50;
angle = 0;
repeat(function() {
angle = angle + dx;
x = x - dy * Math.cos(angle * Math.PI / 180);
y = y - dy * Math.sin(angle * Math.PI / 180);
c.clear();
c.translate(x, y);
c.rotate(angle * Math.PI / 180);
c.translate(-37, -19);
c.drawImage(a, 0, 0);
c.setTransform(1, 0, 0, 1, 0, 0); //reset
});
});
Now I would like to add trail behind the car as it moves along and create a reset button inside the canvas which can help me clear the trail, and bring the car to its initial position.
I have read some tutorials but i can't seem to find what I want.
Is there any idea/suggestion on how I should do this?
Simply record your points when moving:
Modified fiddle here
repeat(function () {
angle = angle + dx;
x = x - dy * Math.cos(angle * Math.PI / 180);
y = y - dy * Math.sin(angle * Math.PI / 180);
/// record point
pts.push([x, y]);
c.clear();
/// render points (see below)
renderTrail(pts, c);
c.translate(x, y);
...
Then have a function to render the recorded points:
function renderTrail(pts, c) {
if (pts.length > 1) {
c.beginPath();
c.moveTo(pts[0][0], pts[0][1]);
for(var i = 1, pt; pt = pts[i]; i++) {
c.lineTo(pt[0], pt[1]);
}
c.stroke();
}
}
To reset just clear the point array:
pts = [];
You can do this on a mouse-click event on the canvas where you chose to draw your button or just put a html button on top of canvas (above it, literally on top will reduce the performance of canvas).

Canvas Animation. Solo Pong

This is my first Web development class and I'm having trouble with functions and knowing which to call. My teacher gave us the following code:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Canvas Animation</title>
<!-- include the jQuery UI stylesheet -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.19 /themes/base/jquery-ui.css">
<!-- include the jQuery and jQuery UI JavaScript files -->
<script src="jquery.min.js"></script>
<script src="jquery-ui.js"></script>
<style>
canvas {
border: 1px solid black;
}
</style>
Solo Pong
Finish this game by:
When the ball hits the paddle, it should bounce back (in a direction dependent on where on the paddle it hits).
When the ball hits the left-most wall, the player loses.
Prevent the paddle from moving out of the top/bottom of the screen.
bonus (2pts): Provide buttons "faster" and "slower" (outside of the canvas) which increase/decrease the speed of the ball.
<canvas id="mycanvas" width="300" height="300"> d </canvas>
<script>
// global variables
var context;
// width/height of the canvas
var width;
var height;
// position and direction of the ball
var x = 100;
var y = 180;
var dx = 2;
var dy = 2;
// paddle
var paddley; // y location
var paddleh; // height
var paddlew; // width
// keyboard input
var upPressed = false; // is the user pressing up?
var downPressed = false; // is the user pressing down?
// setup canvas and animation timer
function init() {
context = $("#mycanvas")[0].getContext("2d");
width = $("#mycanvas").width();
height = $("#mycanvas").height();
return setInterval(draw, 10); // every 10 milliseconds, draw will be called.
}
// called when a key is pressed
function onKeyDown(evt) {
if (evt.keyCode == 38) upPressed = true; // 38 is code for up button
else if (evt.keyCode == 40) downPressed = true; // 40 is code for down button
}
//called when a key is released
function onKeyUp(evt) {
if (evt.keyCode == 38) upPressed = false;
else if (evt.keyCode == 40) downPressed = false;
}
// attaches the key methods to the document.
$(document).keydown(onKeyDown);
$(document).keyup(onKeyUp);
// clear the screen to prepare for drawing a new frame
function clear() {
context.clearRect(0, 0, width, height);
}
// draw a circle at x,y with radius r
function circle(x,y,r) {
context.beginPath();
context.arc(x, y, r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}
// draw a filled rectangle at x,y with width,height
function rect(x,y,w,h) {
context.beginPath();
context.rect(x,y,w,h);
context.closePath();
context.fill();
}
// init location and size of paddle
function init_paddles() {
paddley = 100;
paddleh = 75;
paddlew = 10;
}
// draw a single frame of the game
function draw() {
clear();
// draw circle
circle(x, y, 10);
// update paddle location
if (upPressed) paddley -= 5;
else if (downPressed) paddley += 5;
// draw paddle
rect(10, paddley, paddlew, paddleh);
// ball hit a wall!
if (x + dx > width || x + dx < 0)
dx = -dx; // flip x direction
if (y + dy > height || y + dy < 0)
dy = -dy; // flip y direction
// move ball
x += dx;
y += dy;
}
init();
init_paddles();
</script>
</body>
I just need help with when the ball hits the paddle, it bounces off in the opposite direction. So would it be something like:
if(x + dx > paddley || x + dx >paddleh)
dx = -dx;
Considering that the paddle is on the right size of the screen and that the position of the ball is its center, and the position of the paddle is the top left corner :
// Collision on the y and x axis
var onY = (y + dy < paddley + paddleh) && (y - dy > paddley);
var onX = (x + dx > width - paddlew);
if (onX && onY)
{
// A factor that depends on the distance from the collision point to
// the paddle's center.
var delta = abs(y - (paddley + paddleh/2))/paddleh;
// We change dx and dy such that the speed (dx² + dy²) stays the same
dx = -dx*sqrt(1 - delta);
dy = sqrt(pow(dy, 2) + pow(dx,2)*delta);
}
You should add a factor to delta and change it until the ball bounces as you want.