I'm starting to make a game and I'm putting together a little "game engine" to do stuff easily and not type so repetitively. I have a sprite function that loads the image and an update function which draws it. The problem is it won't draw, and no errors have been reported in the console.
jsfiddle
var canvas = document.createElement("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.position = "absolute";
canvas.style.right = "0px";
canvas.style.top = "0px";
document.body.appendChild(canvas);
var c = canvas.getContext("2d");
var Squares = [];
var Square = function(x,y,w,h,color="black") {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
Squares.push(this);
return this
}
var Sprites = [];
var Sprite = function(x,y,w,h,src) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.src = src;
this.img = new Image();
this.img.onload = function() {
}
this.img.src = this.src;
this.img.width = this.w;
this.img.height = this.h;
return this
}
function Clear(x,y,w,h) {
c.clearRect(x,y,w,h);
}
function Update() {
Clear(0,0,canvas.width,canvas.height);
for(var square in Squares) {
c.fillStyle = Squares[square].color;
c.fillRect(Squares[square].x,Squares[square].y,Squares[square].w,Squares[square].h);
}
for(var sprite in Sprites) {
console.log(Sprites[sprite].img)
Sprites[sprite].img.onload = function() {
c.drawImage(Sprites[sprite].img);
}
}
}
var ground = new Square(0,0,canvas.width,canvas.height,color="forestgreen");
var player = new Square(10,10,6,6,color="red");
var Mtn = new Sprite(50,50,50,50,"mountain.png");
console.log(Mtn.img)
function Logic() {
}
function Main() {
Logic();
Update();
}
setInterval(Main,2);
Related
I was successful in generating enemies (out of one image) with an array, however, I'm stuck in trying to generate enemies out of more than one image (e. g. 5 different images, thus 5 different enemies)
Here is my code that works:
Enemies (enemyImg - one image) are generated
/** #type {HTMLCanvasElement} */
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const backgroundImg = document.getElementById("background");
const playerImg = document.getElementById("player");
const enemyImg = document.getElementById("enemy");
canvas.width = 800;
canvas.height = 500;
const enemies = [];
class Enemy {
constructor(x, y, w, h, speed) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.speed = speed;
}
draw() {
ctx.drawImage(enemyImg, this.x, this.y, this.w, this.h);
}
update() {
this.x = this.x - this.speed;
}
}
function spawnEnemies() {
setInterval(() => {
let w = 100;
let h = 40;
let x = canvas.width;
let y = Math.random() * Math.abs(canvas.height - h);
let speed = 5;
enemies.push(new Enemy(x, y, w, h, speed));
}, 1000);
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, canvas.width, canvas.height);
enemies.forEach((enemy) => {
enemy.draw();
enemy.update();
});
}
animate();
spawnEnemies();
Here is the code, that does not work. I do not get any error message at all:
I have 6 images in one folder, named enemy_1.png to enemy_6.png) and I want them to be generated;
/** #type {HTMLCanvasElement} */
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const backgroundImg = document.getElementById("background");
const playerImg = document.getElementById("player");
const enemyImg = document.getElementById("enemy");
canvas.width = 800;
canvas.height = 500;
let enemies = [];
class Enemy {
constructor(img, x, y, w, h, speed) {
this.img = img;
(this.x = x),
(this.y = y),
(this.w = w),
(this.h = h),
(this.speed = speed);
}
draw() {
ctx.drawImage(img, this.x, this.y, this.w, this.h);
}
move() {
this.x = this.x - this.speed;
}
}
function createEnemies() {
setInterval(() => {
let w = 40;
let h = 72;
let x = 300;
let y = Math.random() * Math.abs(canvas.height - h);
let speed = 5;
enemies.length = 6;
for (let i = 1; i < enemies.length; i++) {
enemies[i] = new Image();
enemies[i].src = "./images/enemy_" + i + ".png";
enemies.push(new Enemy(enemies[i], x, y, w, h, speed));
}
}, 2000);
}
function createGame() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
enemies.forEach((enemy) => {
enemy.draw();
enemy.move();
});
requestAnimationFrame(createGame);
}
createGame();
createEnemies();
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const backgroundImg = document.createElement('img');
const playerImg = document.createElement('img');
canvas.width = 500;
canvas.height = 200;
// load your images:
const imagesCount = 0; // I have not this images, so its zero for me
const enemyImages = [];
for (let i = 1; i < imagesCount; i++) {
const img = new Image();
img.src = "./images/enemy_" + i + ".png";
enemyImages.push(img);
}
// I have not your images so i take some random pictures:
const enemyImage1 = new Image();
enemyImage1.src = 'https://pngimg.com/uploads/birds/birds_PNG106.png';
const enemyImage2 = new Image();
enemyImage2.src = 'https://purepng.com/public/uploads/large/purepng.com-magpie-birdbirdsflyanimals-631522936729bqeju.png';
const enemyImage3 = new Image();
enemyImage3.src = 'https://www.nsbpictures.com/wp-content/uploads/2018/10/birds-png.png';
enemyImages.push(
enemyImage1,
enemyImage2,
enemyImage3,
);
const enemies = [];
class Enemy {
constructor(x, y, w, h, speed, img) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.speed = speed;
// Self image:
this.img = img;
}
draw() {
// Draw self image:
ctx.drawImage(this.img, this.x, this.y, this.w, this.h);
}
update() {
this.x = this.x - this.speed;
}
}
function spawnEnemies() {
setInterval(() => {
let w = 60;
let h = 50;
let x = canvas.width;
let y = Math.random() * Math.abs(canvas.height - h);
let speed = 5;
enemies.push(new Enemy(x, y, w, h, speed,
// Pick random image from array:
enemyImages[Math.floor(Math.random()*enemyImages.length)]
));
}, 1000);
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, canvas.width, canvas.height);
enemies.forEach((enemy) => {
enemy.draw();
enemy.update();
});
}
animate();
spawnEnemies();
<canvas id=canvas></canvas>
I make the game with html canvas.I need to move the image sprite but my code only redraw the image on the same position.Where is problem?The code is here
class Duck{
constructor(x,y){
this.x = x;
this.y = y;
this.skin = 'img/path/';
}
draw() {
var img = new Image();
img.src = this.skin;
img.onload = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img,this.x, this.y);
ctx.restore();
}
}
move(){
this.x+=10;
this.y+=10;
}
}
var canvas = document.getElementById("canv");
var ctx = canvas.getContext("2d");
var d = new Duck(0,0);
//this function called from another file and it works
function mainLoop() {
d.move();
d.draw();
requestAnimationFrame(mainLoop);
}
Here is your code fixed:
You don't need ctx.restore();
You need to store this context in the draw method, for reference in the img.onload callback
class Duck {
constructor(x, y) {
this.x = x;
this.y = y;
this.skin = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTEyIDUxMjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggc3R5bGU9ImZpbGw6I0ZGREU3NjsiIGQ9Ik00MzMuNjYxLDIzNy44MzdjLTQuNDk3LTYuMjE0LTQuODgtMTQuNDQtMS4yMjUtMjEuMTg0YzExLjM2NS0yMC45NjcsMTcuNzczLTQ1LjAxNCwxNy42NTEtNzAuNTY2DQoJQzQ0OS43MDEsNjQuODY5LDM4Mi41NjQtMS4wMzcsMzAxLjM1MiwwLjAxMmMtODAuMTgzLDEuMDM2LTE0NC44NjQsNjYuMzU5LTE0NC44NjQsMTQ2Ljc4OGMwLDMyLjU1MywxMC41OTUsNjIuNjMsMjguNTI2LDg2Ljk3Mg0KCWM3Ljc1MywxMC41MjYsNy4yMTMsMjUuMS0xLjU0MywzNC44MDhjLTEzLjI5NywxNC43NDEtNDEuOTM1LDI0LjMwNi0xMDIuNTk1LTE2LjI3N2MtNi42NTItNC40NS0xNC40NjItNi44NjQtMjIuNDY1LTYuODY0bDAsMA0KCWMtMTkuOTQ3LDAtMzYuODMzLDE0LjYyOC0zOS43NzYsMzQuMzU3QzcuODg5LDM1MS44MTYsNi41Miw1MTIsMjA2Ljk2Niw1MTJoNzEuMDgzQzQ2Ni4wNSw1MTIsNTE2LjEyNywzNTEuODAxLDQzMy42NjEsMjM3LjgzN3oiLz4NCjxnPg0KCTxwYXRoIHN0eWxlPSJmaWxsOiNGRkI2NDE7IiBkPSJNMTgzLjQ3LDI2OC41ODJjLTMuOTMsNC4zNTctOS4yMDIsOC4yNjEtMTYuMjQ0LDEwLjU1MmMyNC40NjksNS44ODIsMzguODItMS4zMTksNDcuMTQ5LTEwLjU1Mg0KCQljOC43NTctOS43MDgsOS4yOTYtMjQuMjgxLDEuNTQzLTM0LjgwOGMtMTcuOTMtMjQuMzQyLTI4LjUyNi01NC40Mi0yOC41MjYtODYuOTczYzAtNzUuODMzLDU3LjUwMy0xMzguMjI2LDEzMS4yODEtMTQ1Ljk4DQoJCWMtNS42ODktMC42MDEtMTEuNDY3LTAuODg0LTE3LjMyMy0wLjgwOWMtODAuMTgzLDEuMDM2LTE0NC44NjQsNjYuMzU5LTE0NC44NjQsMTQ2Ljc4OGMwLDMyLjU1MywxMC41OTUsNjIuNjMsMjguNTI2LDg2Ljk3Mw0KCQlDMTkyLjc2NiwyNDQuMywxOTIuMjI2LDI1OC44NzMsMTgzLjQ3LDI2OC41ODJ6Ii8+DQoJPHBhdGggc3R5bGU9ImZpbGw6I0ZGQjY0MTsiIGQ9Ik00OS41MzksMjc5Ljc5NmMyLjEzNy0xNC4zMTcsMTEuNjE4LTI1Ljk0MiwyNC4yODItMzEuMjQ1Yy00Ljg2Ni0yLjAyMi0xMC4wOTEtMy4xMS0xNS40MTItMy4xMQ0KCQlsMCwwYy0xOS45NDcsMC0zNi44MzMsMTQuNjI4LTM5Ljc3NiwzNC4zNTdDNy44ODksMzUxLjgxNiw2LjUyLDUxMiwyMDYuOTY2LDUxMmgzMC45MDVDMzcuNDI1LDUxMiwzOC43OTQsMzUxLjgxNiw0OS41MzksMjc5Ljc5NnoNCgkJIi8+DQoJPHBhdGggc3R5bGU9ImZpbGw6I0ZGQjY0MTsiIGQ9Ik04MC41MTgsMzQ0LjMzNmMtOC43NjYsOC42NTYtMTAuMjc3LDIyLjI2OC0zLjU5OCwzMi42MTkNCgkJYzE5LjUwNCwzMC4yMjcsNjguMzUxLDg2LjI4MywxNjIuMzcyLDg2LjI4M2M1Ny4yNTYsMCwxMTcuNzkxLTM1LjgwOSwxMjkuMDY0LTk1LjA5N2M5LjMxLTQ4Ljk2Ni0xOS4yNDYtMTA4LjgyMS03NS4zMy0xMDYuMjQ3DQoJCWMtNDEuMDk3LDEuODg3LTY1LjEzNSwzNy40MTUtOTkuODY1LDUzLjg0MWMtMjQuMzk4LDExLjU0LTUwLjg0NCwxOC42NTEtNzcuNjg3LDIxLjMwNw0KCQlDMTAyLjY5OCwzMzguMzA2LDkwLjgwNSwzMzQuMTc4LDgwLjUxOCwzNDQuMzM2eiIvPg0KPC9nPg0KPHBhdGggc3R5bGU9ImZpbGw6IzM4NDg0QTsiIGQ9Ik0zODguMzk0LDExMC44MzNjLTMuNTAyLDAtNi42NzQtMi4zOTYtNy41MTMtNS45NTFsLTMuNzE1LTE1LjczDQoJYy0wLjk4MS00LjE1MywxLjU5MS04LjMxNSw1Ljc0My05LjI5NWM0LjE1Mi0wLjk3OSw4LjMxNSwxLjU5MSw5LjI5NSw1Ljc0M2wzLjcxNSwxNS43M2MwLjk4MSw0LjE1My0xLjU5MSw4LjMxNS01Ljc0Myw5LjI5NQ0KCUMzODkuNTgsMTEwLjc2NSwzODguOTgyLDExMC44MzMsMzg4LjM5NCwxMTAuODMzeiIvPg0KPHBhdGggc3R5bGU9ImZpbGw6I0ZGQjY0MTsiIGQ9Ik00MjcuNjE4LDY4Ljk5NGMwLDAsMy4xOTgsNDUuODMyLTE4LjAzMyw2Ni41OTFjLTIxLjIzMSwyMC43NTksMTQuMTU0LDUzLjMxNCw1Ni4xNDUsMjIuNjQ2DQoJYzYuMDMyLTQuNDA1LDEyLjE0My03LjIwNCwxOC4xODQtOC43NjhjNy43NzctMi4wMTIsMTMuMjQzLTguOTY3LDEzLjI0My0xNi45OTlsMCwwYzAtNy43MjQtNS4wMzEtMTQuNTk3LTEyLjQzOC0xNi43ODYNCgljLTQuOTI1LTEuNDU2LTExLjE4LTIuMzI1LTE4LjUxNi0xLjMyNWMwLDAsMjUuMzkzLTIyLjEzOCwxOS4xMTktNDcuNzUzYy0yLjAyNy04LjI4LTExLjg1Ni0xMS43MjYtMTguODM2LTYuODMyDQoJQzQ1Ny40NjEsNjYuMDk0LDQ0My40NTQsNzIuNzY0LDQyNy42MTgsNjguOTk0eiIvPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=';
}
draw() {
var img = new Image();
img.src = this.skin;
const that = this;
img.onload = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, that.x, that.y);
}
}
move() {
this.x += 10;
this.y += 10;
}
}
var canvas = document.getElementById("canv");
var ctx = canvas.getContext("2d");
var d = new Duck(0, 0);
//this function called from another file and it works
function mainLoop() {
d.move();
d.draw();
requestAnimationFrame(mainLoop);
}
mainLoop();
<canvas id="canv" height="600px" width="600px"></canvas>
I have a function that clears all drawings off of the background image in canvas when a button is clicked, but when you go to draw again, the old (previously cleared drawings) reappears. How can I make a hard delete so that I can draw again without reloading the page
'use strict';
function initCanvas() {
let bMouseIsDown = false;
let canvas = document.getElementById('cvs');
let ctx = canvas.getContext('2d');
let convert = document.getElementById('convert');
let sel = 'png';
let imgs = document.getElementById('imgs');
let imgW = 300;
let imgH = 200;
let background = new Image();
background.crossOrigin = '';
background.src = "http://i.imgur.com/yf6d9SX.jpg";
background.onload = function(){
ctx.drawImage(background,0,0,600,400);
}
bind(canvas,ctx,convert,sel,imgs,imgW,imgH,bMouseIsDown);
};
initCanvas()
function bind (canvas,ctx,convert,sel,imgs,imgW,imgH,bMouseIsDown) {
let iLastX = 0;
let iLastY = 0;
let iX;
let iY;
canvas.onmousedown = function(e) {
bMouseIsDown = true;
iLastX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
iLastY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
}
canvas.onmouseup = function() {
bMouseIsDown = false;
iLastX = -1;
iLastY = -1;
}
canvas.onmousemove = function(e) {
if (bMouseIsDown) {
iX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
iY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
ctx.moveTo(iLastX, iLastY);
ctx.lineTo(iX, iY);
ctx.stroke();
ctx.strokeStyle = "blue";
ctx.lineJoin = "round";
ctx.lineWidth = 5;
iLastX = iX;
iLastY = iY;
}
};
document.getElementById('clear').addEventListener('click', function() {
rerenderImg();
});
function rerenderImg() {
iY = [];
iX=[];
initCanvas()
}
};
You need to call ctx.beginPath(); before drawing on the canvas again.
The logical place to put this is just before your call to ctx.moveTo.
An explanation of why this is needed is given here.
You should actually run clearRect on the canvas:
ctx.clearRect(0, 0, canvas.width, canvas.height);
I'm trying to create background for every created particle.
Canvas pattern is not working properly. I'm getting this error >> "SyntaxError: An invalid or illegal string was specified"
HTML
<canvas id="canvas"></canvas>
JS
(function(){
window.onload = function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d'),
particles = {},
particleIndex = 0,
particleNum = 1;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.width);
function Particle(){
this.x = canvas.width / 2;
this.y = 0;
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
this.gravity = 0.2;
particleIndex++;
particles[particleIndex] = this;
this.id = particleIndex;
this.test = 0;
this.maxLife = 100;
}
Particle.prototype.draw = function(){
this.x += this.vx;
this.y += this.vy;
this.vy += this.gravity;
this.test++;
if ( this.test >= this.maxLife ) {
delete particles[this.id];
};
var img = new Image();
img.src = 'img/aaa.png';
var pattern = ctx.createPattern(img,'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(this.x, this.y, 20, 20);
};
setInterval(function(){
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < particleNum; i++) {
new Particle();
};
for(var i in particles) {
particles[i].draw();
}
},30)
}})();
I was trying to do this also with ctx.drawImage(), but picture was displayed one time only.
Any tips?:)
Fiddle
I think the issue is the image being loaded later than its used.
Inside your draw() you have:
var img = new Image();
img.src = 'img/aaa.png';
var pattern = ctx.createPattern(img,20,20);
It is a bad idea to create new images everytime you want to draw. I strongly suggest you create the img variable outside of the draw loop. Once you set the .src of an image, you have to wait until it is loaded to use it. There is an onload event you can use to let you know when its ready.
Here is an example:
var imgLoaded = false;
var img = new Image();
img.src = 'img/aaa.png';
img.onload = function() { imgLoaded = true; };
function draw() {
...
if (imgLoaded) {
var pattern = ctx.createPattern(img, 'repeat');
...
}
...
}
i am trying to display three playing cards on the screen and for some reason everytime i run the code a type error appears and i have tried everything to try to fix it but nothing has worked. I think that the problem is in the array/object constructor but i think that everything is right inside of those.
"use strict";
function main(){
var cvs = document.getElementById("foo");
var ctx = foo.getContext("2d");
function Card(posX, posY, imgX, imgY){
this.posX = posX;
this.posY = posY;
this.imgX = imgX;
this.imgY = imgY;
this.width = 97;
this.height = 129;
}
Card.img = new Image();
Card.img.src = "allcards.png";
var cards = [new Card(0,0,0,0), new Card(400,400,194,258), new Card(200,200,291,387)];
var greaterX = false;
var lessX = false;
var greaterY = false;
var lessY = false;
var offsetX;
var offsetY;
setInterval(draw, 10);
function draw(){
ctx.fillStyle="rgb(0,255,255)";
ctx.clearRect(0,0,600,600);
ctx.drawImage(Card.img,cards[1].imgX,cards[1].imgY,Card.width,Card.height,cards[1].posX, cards[1].posY);
ctx.drawImage(Card.img,cards[2].imgX,cards[2].imgY,Card.width,Card.height,cards[2].posX, cards[2].posY);
}
}
var ctx = foo.getContext("2d");
should this not be
var ctx = cvs.getContext("2d");
You seem to have confused the static properties of the Card function object with those of the Card instances - the width and height properties are instance properties.
var cvs = document.getElementById("foo");
var ctx = cvs.getContext("2d");
function Card(posX, posY, imgX, imgY){
this.posX = posX;
this.posY = posY;
this.imgX = imgX;
this.imgY = imgY;
}
// default values/methods, accessible and overwritable on all instances:
Card.prototype.width = 97;
Card.prototype.height = 129;
Card.prototype.draw = function() {
ctx.drawImage(Card.img, this.imgX, this.imgY, this.width, this.height, this.posX, this.posY);
};
// static property:
Card.img = new Image();
Card.img.src = "allcards.png";
Card.img.onload = draw;
var cards = [new Card(0,0,0,0), new Card(400,400,194,258), new Card(200,200,291,387)];
function draw(){
ctx.fillStyle="rgb(0,255,255)";
ctx.clearRect(0,0,600,600);
for (var i=0; i<2; i++)
cards[i].draw();
};