Images not rendering randomly on canvas - javascript

Image of the bug is appearing only at one place i.e. x = 0,y = 0.
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = canvas.getContext('2d');
var bugSmashed = 0;
//rendering background image
function renderImage()
{
var backImage = new Image();
backImage.src = "jungle.jpg"
backImage.onload = function(){
c.drawImage(backImage,0,0,canvas.width,canvas.height)}
}
renderImage();
//Making a bug
class Bug {
constructor(x,y){
this.x = x;
this.y = y;
}
renderBug(){
var bugImage = new Image();
bugImage.src = "bug.png";
bugImage.onload = function(){
c.drawImage(bugImage,this.x,this.y,65,65)}}
}
Trying to make the bug appear randomly on the canvas
var interval = setInterval(function(){
var x = 32+Math.random()*(canvas.width-64);
var y = 32+Math.random()*(canvas.height-64);
var aBug = new Bug(x,y);
aBug.renderBug();}, 2000);
I am sure I am missing something. Any help is appreciated. Thanks

I found your problem: this changes its meaning inside a function. So when you use:
function(){c.drawImage(bugImage,this.x,this.y,65,65)}
this no longer refers to aBug! (It will instead refer to the global Window object.) You can use fat-arrow syntax instead (which preserves this):
() => c.drawImage(bugImage,this.x,this.y,65,65)
Another really ugly way which I discourage you from using is by creating a new reference to this, and then using that reference in your function:
let that = this;
function(){ c.drawImage(bugImage, that.x, that.y, 65, 65); };
Or you can simplify your code to have it gloss over onload logic, allowing you to avoid wrapping c.drawImage in a function in the first place (note the square which appears is a publicly addressable image):
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = canvas.getContext('2d');
//Making a bug
let bugImg = new Image();
bugImg.src = "https://th.bing.com/th/id/OIP.pXD0MAw4LeAcVrt3qRiEfwAAAA?pid=ImgDet&rs=1";
class Bug {
constructor(x,y){
this.x = x;
this.y = y;
}
renderBug(){
c.drawImage(bugImg, this.x, this.y, 65, 65);
}
}
var interval = setInterval(function(){
var x = 32 + Math.random()* (canvas.width - 64);
var y = 32 + Math.random()* (canvas.height - 64);
var aBug = new Bug(x, y);
aBug.renderBug();
}, 500);
<canvas id="canvas" width="100" height="100"></canvas>

Related

Character doesn't move to the correct destination/wrong angle on mouse click - html canvas

EDIT: SOLVED
I'm making a game in which the character moves by right-clicking. The character is supposed to slowly move/walk (not teleport) to the destination you set by right-clicking on the canvas. The problem is I used some math to determine the angle the character should be heading towards and also wrote a function that draws a circle directly on the destination (attempting to debug). The thing is, I click on a position, the destination circle is displayed in another position and the character is walking towards another 3d position. I'm not experienced enough and I have no idea what's causing this. The math I used were pretty much copy-pasted because I don't really understand how they work so thats a problem too.
The problem is pretty much this image https://imgur.com/1lm2haM
Edit: And this image is what im trying to accomplish https://imgur.com/amQgGxM
//VARIABLES_________________________________
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var WIDTH = 640;
var HEIGHT = 360;
var CANVAS_WIDTH = 640;
var CANVAS_HEIGHT = 360;
var renderList = [];
var selfX = 250;
var selfY = 100
var frameX = 0;
var playerSpdX = 0;
var playerSpdY = 0;
var drawDest = false;
var destX;
var destY;
var Img = {};
Img.player = new Image();
Img.player.src = "Human_walk_spritesheet.png";
Img.map = new Image();
Img.map.src = "maptest.png";
Img.bullet = new Image();
Img.bullet.src = "bullet.png";
renderList.push({img: Img.player, spdX: playerSpdX, spdY: playerSpdY, currX: selfX, currY: selfY});
//CODE______________________________________
function render(){
ctx.clearRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT);
ctx.drawImage(Img.map, 0, 0);
for(i in renderList){
var renderObject = renderList[i];
renderObject.currX += playerSpdX;
renderObject.currY += playerSpdY;
selfX = renderObject.currX;
selfY = renderObject.currY;
ctx.drawImage(renderObject.img, frameX, 0, 120, 218, selfX, selfY, renderObject.img.width/31/8, renderObject.img.height/8);
}
if(drawDest)
ctx.drawImage(Img.bullet, destX, destY);
updateAnimation();
}
setInterval(render, 100);
document.onmousedown = function click(event){
if(event.button == 2){//right click
clickX = event.clientX;
clickY = event.clientY;
clickX -= selfX;
clickY -= selfY;
aimAngle = Math.atan2(clickY, clickX) / Math.PI * 180;
var spdX = Math.cos(aimAngle/180*Math.PI)*10;
var spdY = Math.sin(aimAngle/180*Math.PI)*10;
setPlayerSpeed(spdX, spdY);
drawDestinationDot(clickX, clickY);
}
}
document.oncontextmenu = function(mouse){
mouse.preventDefault();
}
function setPlayerSpeed(spdX, spdY){
playerSpdX = spdX;
playerSpdY = spdY;
}
function drawDestinationDot(x, y){
drawDest = true;
destX = x;
destY = y;
}
So after spending more than 3 entire days before and after my post combined, I finally found what the problem is. It's my fault in part that I didn't post all the code but as stack overflow suggests I tried to only post the relevant code to not confuse people who would be trying to help me and I didn't think this part I removed was relevant but it was. I'm pretty much a newbie. So the entire problem was the canvas resizing which I didn't pay any attention to. I replicated my code and just used simple rectangles instead of images and it worked perfectly because I also forgot to add the canvas resizing. That's it:
resizeCanvas();
function resizeCanvas(){
CANVAS_WIDTH = window.innerWidth - 4;
CANVAS_HEIGHT = window.innerHeight - 4;
let ratio = 16 / 9;
if(CANVAS_HEIGHT < CANVAS_WIDTH / ratio)
CANVAS_WIDTH = CANVAS_HEIGHT * ratio;
else
CANVAS_HEIGHT = CANVAS_WIDTH / ratio;
canvas.width = WIDTH;
canvas.height = HEIGHT;
canvas.style.width = '' + CANVAS_WIDTH + 'px';
canvas.style.height = '' + CANVAS_HEIGHT + 'px';
}
Thanks for helping Loïc.

Javascript: Moving object on canvas (trying to learn object oriented programming)

So basicly I want to make a simple Snake game, but I'm stuck already at the moving part.
This is the code that works if I make a button onclick = "snake.show()" and as I click the button, the rectangle moves. (snake.show() is also in the body onload)
var width = 800;
var height = 400;
var x = width/2;
var y = height/2;
class Snake{
show(){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.rect(x, y, 20, 5);
ctx.fill();
x++;
}
//update(){}
}
let snake = new Snake();
but instead of that i want to make something like this:
var width = 800;
var height = 400;
var x = width/2;
var y = height/2;
class Snake{
show(){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.rect(x, y, 20, 5);
ctx.fill();
}
update(){
x++;
}
}
And call the update() function if I need to move the rectangle, but this does not work. Sorry for my bad english, thanks for the advices and for the help!
Declare the canvas and the context as global variables (only once).
A class need a constructor method.
I'm updating and showing again the snake on keydown the right arrow.
I hope it helps.
const c = document.querySelector("canvas");
const ctx = c.getContext("2d");
const width = (c.width = 800);
const height = (c.height = 400);
class Snake {
constructor() {
this.x = width / 2;
this.y = height / 2;
}
show() {
ctx.beginPath();
ctx.rect(this.x, this.y, 20, 5);
ctx.fill();
}
update() {
this.x+=20;
}
}
let snake = new Snake();
snake.show();
window.addEventListener("keydown", e => {
if (e.keyCode == 39) {
ctx.clearRect(0,0,width,height);
snake.update();
snake.show();
}
});
canvas{border:1px solid}
<canvas id="canvas"></canvas>

I wanted to draw a circle in javascript

I was making a dice gamein Javascript.
Someone told me to break that problem into many functions and create each app for each function.
So, I am now breaking the whole dice game into various functions such as drawing circles etc.
So, i like to create a circle (The dots on the dice), and for that; i used the initial source code and kept the useful code that helps me to draw an arc, ... but that is not working. Can anyone figure out why?
I think I missed some values to pass in the function, but I don't know if it is the problem?
I have tried to pass values inside the draw1() but that is not working
var cwidth = 400;
var cheight = 300;
var dicex = 50;
var dicey = 50;
var dicewidth = 100;
var diceheight = 100;
var dotrad = 6;
var ctx;
function init() {
draw1();
}
function draw1() {
var dotx;
var doty;
ctx.beginPath();
dotx = dicex + 0.5 * dicewidth;
doty = dicey + 0.5 * diceheight;
ctx.arc(dotx, doty, dotrad, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
init();
I want the same program to make a small circle
You had a few problems with your initial code, mostly down to variables being undefined. When you declare a variable, it's only defined if you give it a value. That means that code such as:
var ctx;
Creates a variable called ctx, but its value is undefined. This means that when you try and do things like
ctx.beginPath();
You'll get an error, because undefined doesn't have a property beginPath.
What you need to do in order to fix this is initialise variables as you declare them. In fact, it's rarely a good idea to define a variable without initialising it.
I've added a function here to create a canvas, and you can then use that canvas object to initialise your ctx variable. Here's how that might look:
var cwidth = 400;
var cheight = 300;
var dicex = 50;
var dicey = 50;
var dicewidth = 100;
var diceheight = 100;
var dotrad = 6;
function init() {
draw1();
}
function addCanvas(width, height) {
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
document.body.appendChild(canvas);
return canvas;
}
function draw1() {
var dotx;
var doty;
var canvas = addCanvas(cwidth, cheight)
var ctx = canvas.getContext("2d");
ctx.beginPath();
dotx = dicex + 0.5 * dicewidth;
doty = dicey + 0.5 * diceheight;
ctx.arc(dotx, doty, dotrad, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
init();
<html>
<head>
<title>die</title>
</head>
<body onLoad="draw1()">
<canvas id="canvas"width="400"height="300" style="border:1px solid #000000;">
nope unsp browser
</canvas>
<script>
var cwidth = 400;
var cheight = 300;
var dicex = 50;
var dicey = 50;
var dicewidth = 100;
var diceheight = 100;
var dotrad = 6;
var c = document.getElementById('canvas');
var ctx = c.getContext('2d');;
function draw1() {
var dotx;
var doty;
ctx.beginPath();
dotx = dicex + 0.5 * dicewidth;
doty = dicey + 0.5 * diceheight;
ctx.arc(dotx, doty, dotrad, 0, Math.PI * 2, true);
ctx.fill();
ctx.stroke();
ctx.closePath();
}
</script>
</body>
</html>

HTML 5 canvas DrawImage only working after refresh

I have an issue with drawing to the canvas, I have an array of image information that i loop through and create image objects from. On each images onload event i draw it to the canvas, however this will only work after a refresh (once the images are in the cache it seems).
Here is a snippet from my code
var image = new Image();
image.src = img.src; //got from elsewhere, need to draw a background image first
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
img.parentNode.replaceChild(canvas, img);
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0, canvas.width, canvas.height);
context.globalCompositeOperation = 'source-over';
//looping through my image info
for (var index in anaglyphs){
var anaglyph = anaglyphs[index];
if (anaglyph === undefined) continue;
//If x, y, height and width values are set in Image then set in mask
//otherwise use defaults
var x = 0;
if (anaglyph.x !== undefined) x = anaglyph.x;
var y = 0;
if (anaglyph.y !== undefined) y = anaglyph.y;
var width = canvas.width;
if (anaglyph.width !== undefined) width = anaglyph.width;
var height = canvas.height;
if (anaglyph.height !== undefined) height = anaglyph.height;
var alpha = new Image();
//Use of an intimidate function to stop javascripts closure
//overriding the variables before the onload event fired. Creating
//temporary variables in the intimidate function, which executes
//immediately, and storing the desired values inside them for callback.
(function (){
var xPos = x;
var yPos = y;
var maskWidth = width;
var maskHeight = height;
alpha.onload = function () {
context.drawImage(this, xPos, yPos, maskHeight, maskWidth);
};
})();
alpha.src = "data:"+anaglyph.content+";base64,"+encode64(anaglyph.data);
}
};
After a refresh it works fine and it will continue to work fine if I open the webpage using that script again, however it will fail again if I clear the cache and reopen the page. It only needs to work in the latest version of Firefox.
Thanks
Try putting alpha.src inside your closure:
(function (anaglyph,x,y,width,height){
var xPos = x;
var yPos = y;
var maskWidth = width;
var maskHeight = height;
alpha.onload = function () {
context.drawImage(this, xPos, yPos, maskHeight, maskWidth);
};
alpha.src = "data:"+anaglyph.content+";base64,"+encode64(anaglyph.data);
})(anaglyph,x,y,width,height);
BTW, why use a closure?
How about just a simple image loader with callback instead (just an example):
// callback -- after all images are loaded
function draw(images){
// or whatever you want in your callback
context.drawImage(images.image1, 10, 10, 50,50 );
context.drawImage(images.image2, 10, 100, 50,50);
}
var images = {};
var URLs = {
image1: 'ship.jpg',
image2: 'houseicon.png'
};
LoadImages(URLs, draw );
function LoadImages(URLs, callback) {
var loaded = 0;
var needed = 0;
for(var url in URLs) { needed++; }
for(var url in URLs) {
images[url] = new Image();
images[url].onload = function() {
if(++loaded >= numImages) {
callback(images);
}
};
images[url].src = URLs[url];
}
}

Javascript array and object/classes

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();
};

Categories

Resources