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

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.

Related

JAVASCRIPT - Cannot read property 'show' of undefined

My code have a error help me!
I made a code to create a screen and then show the circles, but the code is giving error. Could someone help me with this error?
var blob;
var blobs = [];
var x;
var y;
window.onload = function(){
c = document.createElement('canvas');
width = 300;
height = 300;
c.width = width;
c.height = height;
ctx = c.getContext('2d');
document.body.appendChild(c);
setInterval(draw(), 1000/30)
blob = new Blob(width/2, height/2, 64);
}
function draw(){
ctx.rect(0, 0, width, height);
ctx.fillstyle = 'black';
ctx.fill();
blob.show();
}
function Blob(x, y, r){
this.pos = this.x, this.y = x, y;
this.r = r;
this.show = function(){
ctx.fillstyle = 'white';
ctx.fill();
ctx.ellipse(this.pos.x, this.pos.y, this.r*2, this.r*2);
}
}
<!DOCTYPE html>
<html>
<head>
<script></script>
</head>
<body>
</body>
</html>
This is the error: Cannot read property 'show' of undefined
you're invoking the method rather than passing a reference to a function
setInterval(draw(), 1000/30) //here the blob instance is still not created thus the error
change it to:
setInterval(draw, 1000/30)

HTML5 Moving Objects

I've read many posts and gone through several tutorials on HTML5 and the canvas specifically, but so far I have been unable to replicate my exact problem. If there is an answer for it already out there, please point me in the right direction.
My ultimate goal is to make a simple Pong game. I've drawn the basic objects using JavaScript and now I am trying to get the player (left) paddle to move. The problem I am running into with my current code is that instead of moving the paddle, it fills in the area it travels to. Through various trials and error of adapting and trying different methods I don't think the paddle is being elongated (adding pixels to the height), but it seems like a new paddle object is being created rather than the one being moved.
I've looked it over and over again (you guys aren't a first-ditch effort), but can't seem to figure out what's happening. Any help would be much appreciated.
// Requests a callback 60 times per second from browser
var animate = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) { window.setTimeout(callback, 1000/60) };
// Get canvas and set context
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.fillStyle = "white";
// Settle variables for canvas width and height
var canvas_width = 500;
var canvas_height = 400;
// Set varaibles for paddle width and height
var paddle_width = 15;
var paddle_height = 75;
// Initializes variables
var playerScore = 0;
var computerScore = 0;
var player = new Player();
var computer = new Computer();
var ball = new Ball((canvas_width/2),(canvas_height/2));
// Renders the pong table
var render = function() {
player.render();
computer.render();
ball.render();
};
var update = function() {
player.update();
};
// Callback for animate function
var step = function() {
update();
render();
animate(step);
};
// Creates paddle object to build player and computer objects
function Paddle(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.x_speed = 0;
this.y_speed = 0;
};
function Player() {
this.paddle = new Paddle(1, ((canvas_height/2) - (paddle_height/2)), paddle_width, paddle_height);
};
function Computer() {
this.paddle = new Paddle((canvas_width - paddle_width - 1), ((canvas_height/2) - (paddle_height/2)), paddle_width, paddle_height);
};
// Creates ball object
function Ball(x, y) {
this.x = x;
this.y = y;
this.radius = 10;
};
// Adds render functions to objects allowing them to be drawn on canvas
Ball.prototype.render = function() {
context.beginPath();
context.arc(this.x, this.y, this.radius, Math.PI * 2, false);
context.fillStyle = "white";
context.fill();
context.closePath();
};
Paddle.prototype.render = function() {
context.fillStyle = "white";
context.fillRect(this.x, this.y, this.width, this.height);
};
Player.prototype.render = function() {
this.paddle.render();
};
// Appends a move method to Paddle prototype
Paddle.prototype.move = function(x, y) {
this.y += y;
this.y_speed = y;
};
// Updates the location of the player paddle
Player.prototype.update = function() {
for(var key in keysDown) {
var value = Number(key);
if(value == 38) {
this.paddle.move(0, -4);
} else if (value == 40) {
this.paddle.move(0, 4);
} else {
this.paddle.move(0, 0);
}
}
};
Computer.prototype.render = function() {
this.paddle.render();
};
// Draws center diving line
context.strokeStyle = "white";
context.setLineDash([5, 3]);
context.beginPath();
context.moveTo((canvas_width/2), 0);
context.lineTo((canvas_width/2), canvas_height);
context.stroke();
context.closePath();
// Draws score on canvas
context.font = "40px Arial";
context.fillText('0', (canvas_width * .23), 50);
context.fillText('0', (canvas_width * .73), 50);
window.onload = function() {
animate(step);
};
var keysDown = {};
window.addEventListener("keydown", function(event) {
keysDown[event.keyCode] = true;
});
window.addEventListener("keyup", function(event) {
delete keysDown[event.keyCode];
});
My apologies: I cut the html/css code and meant to paste it, but forgot.
pong.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Pong</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas" width="500" height="400"></canvas>
<script src="main.js"></script>
</body>
</html>
style.css:
#canvas {
background-color: black;
}
The canvas itself has no "objects", it's just a bitmap, and anything you draw on it just changes the colours of certain pixels, making it look like it's drawing "on top" of what's already there but it doesn't even do that. It just flips pixel colours.
I don't see any code that "resets" the canvas for your next frames, so you're literally just drawing the same paddle at a different height value by colouring different pixels with the paddle's colours without recolouring the original pixels using the background colour.
The easiest solution here is to add a context.clearRect(0, 0, canvas.width, canvas.height); at the start of render():
var render = function() {
// clear the canvas so we can draw a new frame
context.clearRect(0,0,canvas.width,canvas.height);
// draw the frame content to the bitmap
player.render();
computer.render();
ball.render();
};
Note that this reveals you also need to draw your scores and center line every frame. Either that, or you need to make sure your paddles (and your ball) first restore the background colour on their old position, before drawing themselves on their new position, which would require considerably more code.

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.

Key detection in canvas 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){

Categories