Key detection in canvas javascript - javascript

I tried to draw a simple rectangle and move it by keyboard. But the problem is that I think added everything I need in my code...Well i want to use arrows on keyboard. But before i tried JUST to get an alert....But it does not work.....Help me please... Any help will appreciated.
var canvas = document.getElementById("screen");
context = canvas.getContext("2d");
function Player() {
this.x=0, this.y = 0, this.w = 50, this.h = 50;
this.render = function (){
context.fillStyle = "orange";
context.fillRect(this.x, this.y, this.w, this.h);
}
}
var player = new Player();
player.x=100;
player.y= 460;
setInterval( function() {
context.fillStyle="black";
context.fillRect(0,0,canvas.width, canvas.height);
/*context.fillStyle = "white";
context.fillRect(100, 460, 30 , 30);*/
player.render();
//move all aliens & draw all aliens
for(var i = 0; i < 9; i++) {
aliens[i].move(),
aliens[i].draw(context);
}
}, 20);
document.addEventListener('keydown', function(event)){
var key_press = String.fromCharCode(event.keyCode);
alert(event.keyCode + " | " + key_press);
});
}

document.addEventListener('keydown', function(event)){
----------------------------------------------------^
You did put extra parentheses on this, remove it, the actual code would be
document.addEventListener('keydown', function(event){

Related

How can I use clearRect() without erasing other objects I have?

I have a moving object and so it doesn't leave a trail behind I am using the clearRect(). However I can't remove everything in the canvas because that would remove my other object (which is the goal for the player to collect.)
var playerX = 350;
var playerY = 450;
function coin(posX, posY, width, height) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'gold';
ctx.fillRect(posX, posY, width, height); //this is what I don't want to clear
}
function player() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.fillStyle = "gray";
ctx.fillRect(playerX, playerY, 50, 50);
ctx.closePath();
}
function random(min, max) {
var x = Math.floor(Math.random() * max) + min;
return x;
}
function moveLeft() {
playerX -= 5;
player();
window.requestAnimationFrame(moveLeft);
}
function moveRight() {
playerX += 5;
player();
window.requestAnimationFrame(moveLeft);
}
player();
coin(random(5, 650), random(5, 250), 50, 50);
</script>
Any help would be greatly appreciated.
One thing you can try is make a single animation function that would call itself recursively.
function animate(){
canvas.clearRect()
// draw everything here
window.requestanimationframe(animate)
}
animate()

How do I clear the canvas but keep the fill?

Right now my code works like I want it to but when I created my timer to redraw the triangle it overlayed a new triangle every time it was called, so to stop this I put clearRect in, but now it clears the entire canvas negating my fill of black that I have. How can I either add a new timer that still provides the same effect of moving triangles but that doesn't require clearRect or how can I fix what I have to have the background of the canvas stay black but not overlay new triangles every time? Any help is appreciated!
Edit: I also tried two different timers together instead of a timer for handleClick, but got weird results with the speed of the triangles, does anyone know why that is?:
timer = setInterval(init, 30);
timer = setInterval(Triangle, 30);
Code:
<html>
<head>
<script>
var canvas;
var context;
var triangles = [];
function init() {
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
resizeCanvas();
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
canvas.onclick = function(event) {
handleClick(event.clientX, event.clientY);
};
timer = setInterval(handleClick, 30);
}
function Triangle(x,y,color) {
this.x = x;
this.y = y;
this.color = color;
this.vx = Math.random() * 10 - 5; //5-3
this.vy = Math.random() * 10 - 5;
for (var i=0; i < triangles.length; i++) {
var t = triangles[i];
t.x += t.vx;
t.y += t.vy;
if (t.x + t.vx > canvas.width || t.x + t.vx < 0)
t.vx = -t.vx;
if (t.y + t.vy > canvas.height || t.y + t.vy < 0)
t.vy = -t.vy;
}
}
function handleClick(x,y) {
context.clearRect(0,0, canvas.width,canvas.height);
var colors = ['red','green','purple','blue','yellow'];
var color = colors[Math.floor(Math.random()*colors.length)];
triangles.push(new Triangle(x, y, color));
for(i=0; i < triangles.length; i++) {
drawTriangle(triangles[i]);
}
}
function drawTriangle(triangle) {
context.beginPath();
context.moveTo(triangle.x,triangle.y);
context.lineTo(triangle.x + 50,triangle.y + 50);
context.lineTo(triangle.x + 50,triangle.y - 50);
context.fillStyle = triangle.color;
context.fill();
}
function resizeCanvas() {
canvas.width = window.innerWidth-10;
canvas.height = window.innerHeight-10;
fillBackgroundColor();
for(i=0; i < triangles.length; i++) {
drawTriangle(triangles[i]);
}
}
function fillBackgroundColor() {
context.fillStyle = 'black';
context.fillRect(0,0,canvas.width,canvas.height);
}
window.onload = init;
</script>
</head>
<body>
<canvas id="canvas" width="500" height="500">
</body>
</html>
I spent a few minutes reading threw your code, and found one thing that stood out to me. To begin, when you call the timer = setInterval(handleClick, 30); the commands are run from top to bottom in the handleClick function. So when we look at that function, the first thing you draw is the black background. Then, you push out a brand new triangle. Following this, you draw all the triangles in the array using a loop. This is where the issue is. What you are doing is drawing all the past triangles, ontop of the refreshed black rectangle.
Try setting your code to something like this.
function handleClick(x,y) {
context.clearRect(0,0, canvas.width,canvas.height);
var colors = ['red','green','purple','blue','yellow'];
var color = colors[Math.floor(Math.random()*colors.length)];
triangles.push(new Triangle(x, y, color));
triangles.shift(); //This removes the first point in the array, and then shifts all other data points down one index.
for(i=0; i < triangles.length; i++) {
drawTriangle(triangles[i]);
}
}
Pleaase let me know if I miss interpreted any of your code, or if you have a follow up question.

canvas fillRect is not working

I have no idea what is wrong. This is being made on a completely new site, so there are no cache problems, and the javascript console isn't returning errors. The canvas spans over the whole page, and is tagged properly. Here is the script:
<script type = "text/javascript">
var game = document.getElementById("game");
var context = game.getContext("2d");
var gamePieces = []
function gamePiece(width, height, color, x, y){
this.width = width;
this.height = height;
this.x = x;
this.y = y;
update = function(){
context.fillStyle = color;
context.fillRect(this.x, this.y, this.height, this.width);
}
gamePieces[gamePieces.length] = this
}
var p1 = gamePiece(50, 50, "blue", 0, 0);
function update(){
context.clearRect(0, 0, game.width, game.height);
for(var i = 0; i < gamePieces.length; i++){
gamePieces[i].update();
}
}
</script>
Nevermind. I figured it out.
Everything is running smoothly, I just needed to add another context.fillstyle and context.fillRect() statement. derpyderp.

object.draw() shows last defined image on al object.draw() calls

i'm pretty new with javascript/ programming and i'm experimenting with some basic canvas game script i wrote. I'm trying to make 4 background images move left or right at a different speed on a key event. So far so good, it works fine.
The problem starts when i draw the 4 images on the canvas. Al the x,y and h,w settings work fine, accept the image itself. on de canvas it shows the same (last defined) image for al the drawings. I have now idea where i went wrong on this one.
Hope you guys can help me out!
Thnx in advance
<!DOCTYPE HTML>
<html>
<head>
<title>Canvas test game/ movement</title>
</head>
<body>
<canvas id="myCanvas" width="1600" height="1000"></canvas>
<footer></footer>
</body>
<script>
var canvas = document.getElementById('myCanvas'),
context = canvas.getContext('2d'),
img = new Image();
var newImage = function(){
this.image = function(name){
img.src="./images/" + name;
};
this.setSize = function(w, h){
this.w = w;
this.h = h;
};
this.setPosition = function(x, y){
this.x = x;
this.y = y;
};
this.setSpeed = function(speed){
this.speed = speed;
};
this.changePosition = function(direction){
if (direction){
this.x = this.x + this.speed;
} else {
this.x = this.x - this.speed;
}
};
this.draw = function(){
context.drawImage(img, this.x, this.y, this.w, this.h);
};
};
var move = function(direction){
achtergrond.changePosition(direction);
maan.changePosition(direction);
landschapAchter.changePosition(direction);
landschapVoor.changePosition(direction);
};
var achtergrond = new newImage();
achtergrond.image("galaxy.png");
achtergrond.setSize(1600, 1000);
achtergrond.setPosition(0, 0);
achtergrond.setSpeed(0);
var maan = new newImage();
maan.image("maan.png");
maan.setSize(400, 400);
maan.setPosition(200, 100);
maan.setSpeed(1);
var landschapAchter = new newImage();
landschapAchter.image("landschapAchter.png");
landschapAchter.setSize(3200, 500);
landschapAchter.setPosition(0, 450);
landschapAchter.setSpeed(2);
var landschapVoor = new newImage();
landschapVoor.image("landschapVoor.png"); // In the browser all 4 (achtergrond, maan, landschapAchter and landschapVoor) objects show this img on object.draw()
landschapVoor.setSize(4294, 400);
landschapVoor.setPosition(0, 600);
landschapVoor.setSpeed(3);
var checkKey = function(e){
e = e || window.event;
if (e.keyCode == '37') {
move(1);
} else if (e.keyCode == '39') {
move(0);
}
// Move images on key event
context.clearRect ( 0, 0 , 1600 , 1000 );
achtergrond.draw();
maan.draw();
landschapAchter.draw();
landschapVoor.draw();
};
window.onload = function(){
maan.draw();
landschapAchter.draw();
landschapVoor.draw();
achtergrond.draw();
}
document.onkeydown = checkKey;
</script>
</html>
I think you missed this with while specifying src tag :)
var newImage = function(){
this.image = function(name){
this.src="./images/" + name;
};
Try this.

Javascript canvas animation unable to be used more than once

I have an animation for a game that I am working on that won't seem to repeat. When the space bar is pressed, it triggers an event that "shoots" a circle to the top of a canvas. The problem is that when the key is pressed again it will not initiate the animation. Here is the sample code that I wrote:
var canvas, ctx,
spaceKey = false,
upKey = false,
downKey = false,
canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
shotX = 150, shotY = 280;
function loop() {
if (spaceKey) shoot();
}
function keyDown(e) {
if (e.keyCode == 32) spaceKey = true;
}
function keyUp(e) {
if (e.keyCode == 32) spaceKey = false;
}
function shoot() {
setTimeout(function() { if (shotY > 0) {
ctx.clearRect(shotX-5,shotY-5,600,20);
ctx.beginPath();
ctx.arc(shotX, shotY,4,0,Math.PI * 2, false);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
shotY = shotY - 1;
shoot();
} else
ctx.clearRect(shotX-5,shotY-5,600,20);
}, 100);
}
(function init() {
setInterval(loop, 10);
document.addEventListener('keydown', keyDown, false);
document.addEventListener('keyup', keyUp, false);
})();
//init();
The reason I use keyUp and keyDown is because I have other functions that use different keys. This code was modified to show only this feature. To make it easier to see what I'm talking about, I created a JSFiddle. The other features I have are similarly structured and work, the only difference being that its duration isn't directly controlled by a key press.
I don't find your code much re-usable. You should consider using objects to represents the entities on the canvas. I've created simple code which does your job, but it is also not much re-usable (though you can re-use it to create a simple entity like the ball you created). Check this jsFiddle.
The problem with your code is, when that yellow ball reaches the to of the screen, the shotY is 0, then you erase the ball from the screen, but don't reset the shotY and don't redraw the ball at its home (original position).
I've created a simple Ball object to get this done-
function Ball() {
this.x = 150;
this.y = 295;
}
Ball.prototype.draw = function(newx, newy) {
ctx.clearRect(this.x-5,this.y-5,600,20);
newx = newx || this.x;
newy = newy || this.y;
this.x = newx; this.y = newy;
var ball = this;
ctx.beginPath( );
ctx.arc(ball.x, ball.y,4,0,Math.PI * 2, false);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
}
Ball.prototype.shootUp = function() {
var ball = this;
inter = setInterval(function () {
if(ball.x <= 0) clearInterval(inter);
ball.draw(ball.x, ball.y-20);
}, 100);
}
and modified your shoot function -
function shoot() {
var currentBall = new Ball();
currentBall.draw();
currentBall.shootUp();
}
And once again, this was just a simple example. You can make a lot of improvements in it. First of all, you should have an input engine to manage all the inputs. Then you should have a generic entity class to represent all the objects you have on the canvas. Like the Ball. And finally you should have a game engine to bind all those things.
You only have one "bullet".
Your bullets should be separate objects that are instantiated on shoot().
The way that I usually handle "particles" is to create a singleton object to store each instance and update all of them in the main loop.
Here's a simple Bullet object:
function Bullet(){
this.x = 150;
this.y = 280;
this.velX = 0;
this.velY = -1;
this.update = function(){
this.y += this.velY;
};
this.draw = function(){
ctx.beginPath();
ctx.arc(this.x, this.y,4,0,Math.PI * 2, false);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
};
};
And here is a BulletRenderer singleton that handles the bullets:
BulletRenderer = function(){
var bullets = [];
this.push = function(bullet){
bullets.push(bullet);
};
this.render = function(){
for (var i in bullets){
if (bullets[i].active){
bullets[i].update();
bullets[i].draw();
} else {
delete bullets[i];
}
}
};
return this;
}();
In the example I'm just clearing the canvas each frame.
The shooting mechanism acts like a laser right now. Personally I would change this behavior.
http://jsfiddle.net/NAJus/18/

Categories