Moving image on canvas on the X axis only - javascript

The Problem
I am finding it rather difficult to get my head around this, I am attempting to move an image using the mouse along the X axis only. I am finding it hard to even move the image at all and the many tutorials I have looked at arnt really helping me. Here is what I am trying to say:
As you can see by my beautiful image above I only want to image to move left and right at the bottom of the page.
The Code and the Question
Here is my first attempt, when I try this all the images loaded on the canvas no longer appear making it very hard for me to understand why it isnt working.
<script type="text/javascript">
//Referencing the canvas
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var width = canvas.getAttribute('width');
var height = canvas.getAttribute('height');
//Images
var bggameImage = new Image();
var playerImage = new Image();
var enemyImage = new Image();
var projectileImage = new Image();
var livesImage = new Image();
//Canvas dimensions
var width = 480;
var height = 320;
//Loading in the backgroundImage
bggameImage.src = "Images/bggameImage.png";
bggameImage.onload = function(){
context.drawImage(bggameImage, 0, 0);
}
//Loading in the playerImage
playerImage.src = "Images/playerImage.png";
playerImage.onload = function(){
context.drawImage(playerImage, 165, 240);
}
//Loading in the projectileImage
projectileImage.src = "Images/projectileImage.png";
projectileImage.onload = function(){
context.drawImage(projectileImage, 65, 240);
}
var playerImage = {
x:176,
y:74,
}
function init() {
playerImage.src = "Images/playerImage.png";
//Moving player
myCanvas.addEventListener("mousemove", function (e) {
var bounding_box = myCanvas.getBoundingClientRect();
playerImage = (e.clientX - bounding_box.left) * (myCanvas.width / bounding_box.width) - playerImage.width / 2;
playerImage = (e.clientY - bounding_box.top) * (myCanvas.height / bounding_box.height) - playerImage.height / 2;
}
)
</script>
The whole "function init()" part is what I have just tried but I thought I would include this anyway, I understand that I am loading in the playerImage twice.

You're using the same variable name twice (playerImage), so your image is being overwritten. You're using it for the image and also to store the position. Change the playerImage that's storing x and y to be playerPosition or something like that. Update that variable on your mouse event and then render the image according to that variable's values.
Ultimately, you're going to have to look at a game loop using setTimeout or requestAnimationFrame. So, this will become crucial at that stage. And yes, you shouldn't be loading the player image twice either. Do all of that at the start and only start your game when all your assets have successfully loaded.
For instance...
var playerImage;
var alienImage;
var bulletImage;
var assetCount = 0;
function loadAssets() {
playerImage = new Image();
playerImage.onload = checkAssetsLoaded;
playerImage.src = "assets/images/Brush01.png";
alienImage = new Image();
alienImage.onload = checkAssetsLoaded;
alienImage.src = "assets/images/Brush02.png";
bulletImage = new Image();
bulletImage.onload = checkAssetsLoaded;
bulletImage.src = "assets/images/Brush03.png";
}
function checkAssetsLoaded(event) {
assetCount++;
console.log("An asset has loaded!: " + assetCount);
if (assetCount == 3) {
startGame();
}
}
function startGame() {
// Start your game initialization logic here.
console.log("Game starting!");
}

Related

Images not displaying the first time in this object program in JS

I am making a battleship game with polar coordinates. After the user chooses two points, a battleship should be drawn in the middle. My Battleship constructor looks like this:
function Battleship(size, location, source){
this.size = size;
//initializing the image
this.image = new Image();
this.image.src = source;
this.getMiddlePoint = function(){
//get midpoint of ship
...
}
this.distanceBetween = function(t1, t2){
//dist between two points
}
this.display = function(){
var point = [this.radius];
point.push(this.getMiddlePoint());
point = polarToReal(point[0], point[1] * Math.PI / 12);
//now point has canvas coordinates of midpoint
var width = this.distanceBetween(this.info[0][0], this.info[this.info.length-1][0]);
var ratio = this.image.width / width;
ctx.drawImage(this.image, point[0] - width/2, point[1] - this.image.height / ratio / 2, width, this.image.height / ratio);
//draws the image
}
}
The display method of each ship gets called at a certain point (after the user has chosen the location). For some reason, the images do not show the first time I do this, but when I run this code at the very end:
for(var i = 0; i<playerMap.ships.length; i++){
playerMap.ships[i].display();
}
All ships are displayed correctly (not aligned well, but they are displayed). I think there is a problem with loading the images. I am not sure how to fix this. I tried using image.onload but I never got that to work. I also tried something like this:
var loadImage = function (url, ctx) {
var img = new Image();
img.src = url
img.onload = function () {
ctx.drawImage(img, 0, 0);
}
}
but the same problem kept happening. Please help me fix this problem. Here is the game in its current condition. If you place ships, nothing happens, but after you place 5 (or 10) ships, they suddenly all load.
EDIT:
I solved the problem by globally defining the images. This is still very bad practice, since I wanted this to be in the battleship object. This is my (temporary) solution:
var sub = [];
for(var i = 1; i<5; i++){
sub[i] = new Image();
sub[i].src = "/img/ships/battleship_"+i+".png";
}

Pixi is not changing position when click on sprite

I was trying to create a sample pixi application. Where I had an image, when user clicks on the image, it should move its position.
var canvasWidth = window.innerWidth;
var canvasHight = window.innerHeight
var renderer = PIXI.autoDetectRenderer(canvasWidth, canvasHight);
document.body.appendChild(renderer.view);
var stage = new PIXI.Container();
PIXI.loader
.add('images/sample.png')
.add('images/background.jpg')
.load(setup);
function setup() {
var backGround = new PIXI.Sprite(
PIXI.loader.resources["images/background.jpg"].texture);
var steve = new PIXI.Sprite(
PIXI.loader.resources["images/sample.png"].texture);
backGround.hieght = canvasHight;
backGround.width = canvasWidth;
setPropertiesToSteve(steve);
stage.addChild(backGround);
stage.addChild(steve);
renderer.render(stage);
}
// Function just to set properties for steve
function setPropertiesToSteve(steve) {
steve.interactive = true;
steve.position.x = canvasWidth/2;
steve.position.x = canvasWidth/4;
steve.on('pointerdown',function(){
steve.position.x = steve.position.x + 10;
});
}
But when I click on the object nothing happening. I am very much new to pixijs.SO don't know how to handle this.
You need to render the stage again :)
Take a look at the official Pixi examples https://pixijs.github.io/examples/
They use the PIXI.Application class which sets up common things like a ticker that automatically re renders your stage

Uncaught TypeError: Cannot set property 'onclick' of null. Tried window.onload

So, I'm relatively new to Javascrip. Though what I want to do is give a moving image on my canvas an id, so that I can ultimately use onclick to use the image as a clickable image, so I can redirect the user to another page, which is what would happen when the image is clicked. Here is my code so far. I need help. If you need any more clarification I will try to explain further.
var ctx;
var imgBg;
var imgDrops;
var x = 0;
var y = 0;
var noOfDrops = 50;
var fallingDrops = [];
function drawBackground(){
ctx.drawImage(imgBg, 0, 0); //Background
}
function draw() {
drawBackground();
for (var i=0; i< noOfDrops; i++)
{
ctx.drawImage (fallingDrops[i].image, fallingDrops[i].x, fallingDrops[i].y); //The rain drop
fallingDrops[i].y += fallingDrops[i].speed; //Set the falling speed
if (fallingDrops[i].y > 1000) { //Repeat the raindrop when it falls out of view
fallingDrops[i].y = -25 //Account for the image size
fallingDrops[i].x = Math.random() * 10000; //Make it appear randomly along the width
}
}
}
function setup() {
var canvas = document.getElementById('canvasRegn');
if (canvas.getContext) {
ctx = canvas.getContext('2d');
imgBg = new Image();
imgBg.src = "http://images.susu.org/unionfilms/films/backgrounds/hd/space-jam.jpg";
setInterval(draw, 36);
for (var i = 0; i < noOfDrops; i++) {
// Charles Barkley
var fallingDr = new Object();
fallingDr["image"] = new Image();
fallingDr.image.src = 'http://xenboards.ignimgs.com/external_data/attachments/8/8795-f09b907a01726a25ca2fbd2f588e3f0e.jpg';
fallingDr["x"] = Math.random() * 10000;
fallingDr["y"] = Math.random() * 5;
fallingDr["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr);
// Bugs bunny
var fallingDr2 = new Object();
fallingDr2["image"] = new Image();
fallingDr2.image.src = 'http://i.imgur.com/zN2CSAf.png'
fallingDr2["x"] = Math.random() * 10000;
fallingDr2["y"] = Math.random() * 5;
fallingDr2["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr2);
// Michael Jordan
var fallingDr3 = new Object();
fallingDr3["image"] = new Image();
fallingDr3.image.src = 'http://i.imgur.com/XxvJiGg.png'
fallingDr3["x"] = Math.random() * 10000;
fallingDr3["y"] = Math.random() * 5;
fallingDr3["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr3);
// Daffy duck
var fallingDr4 = new Object();
fallingDr4["image"] = new Image();
fallingDr4.image.src = 'http://i.imgur.com/QZogw2L.png'
fallingDr4["x"] = Math.random() * 10000;
fallingDr4["y"] = Math.random() * 5;
fallingDr4["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr4);
fallingDr4.image.id = "Daffy";
}
}
}
setup();
window.onload = function(){
document.getElementById("Daffy").onclick=function(){
alert("Hello World");
}
}
Try:
fallingDr4.image.onclick=function(){
alert(this.id);
}
should alert "Duffy".
Your problem is that you're trying to catch the click event on an element that is not in the document and hence, not clickable by the user.
When you call var img = new Image() a new <img> element is created, with all its properties that you can already modify in your javascript. But this element is only available to your scripts, and is not displayed into the page until you call document.anyElement.appendChild(img). So it's better to consider this as an imageObject more than to an element (even if it actually also is).
What is in your document, and accessible to your user, is the <canvas> element. So if you want to know if the user has clicked, you will have to attach the eventListener to this canvasElement.
But the canvasElement doesn't know what it does represent. When you call context.drawImage(), you're just applying the pixels from the imageSource to the ones of the canvas, and all reference to the original imageObject are lost.
To workaround this, you'll then have to store the position of your drawn image into the canvas, and then check if the click event you caught was inside these positions.
Click events' clientX and clientY properties of the Event passed as arguments of you handler will give you the position of the cursor when the event occurred. But the positions are relative to the top-left corner of the window. So you'll also need to make these relative to the top-left corner of your canvas, which can be done by calling the getBoundingClientRect() method of the canvasElement.
Here is a simplified example :
// this function will be called at image's load
var init = function() {
// a reference to our "in-screen" canvasElement
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// "kitty" will be the js object that will help us know if we clicked on our image
// "this" refers to the imageObject
var kitty = {
width: this.width,
height: this.height,
// random positions
left: Math.random() * (canvas.width - this.width),
top: Math.random() * (canvas.height - this.height),
};
// draw our image at the random positions we created
ctx.drawImage(this, kitty.left, kitty.top, kitty.width, kitty.height);
// here we're listening to mousemove event,
// but click event shares the same clientX & clientY properties
var moveHandler = function(evt) {
// in the "evt" object passed, we can get the x and y positions relative to the window
// so we make these relatives to the canvas ones
var canvasRect = canvas.getBoundingClientRect();
var x = evt.clientX - canvasRect.left;
var y = evt.clientY - canvasRect.top;
// now we've got our relative positions, we can check if we were inside the image
if (x >= kitty.left && x <= (kitty.left + kitty.width) && y >= kitty.top && y <= (kitty.top + kitty.height) ) {
// we are over the image, do something
canvas.style.cursor = 'pointer';
document.body.style.backgroundColor = 'lightblue';
} else {
canvas.style.cursor = 'default';
document.body.style.backgroundColor = 'transparent';
}
};
// attach this event handler to the canvasElement
canvas.addEventListener('mousemove', moveHandler);
};
// this will create an imageObject, which will stay "off-screen" (never appendded to the document)
var img = new Image();
// wait that the image has loaded before trying to make any magic
img.onload = init;
img.src = "http://lorempixel.com/200/70/cats";
body {
width: 100vw;
text-align: center;
}
canvas {
margin: 0 auto;
position: relative;
}
<canvas id="canvas" width="500" height="500"></canvas>
(you may need to scroll to actually see the image, or go fullscreen)

Fabric.js add images order

I'm trying to add images to canvas strictly, but images are added randomly.
What's the problem?
Here is my simple code.
var canvas = new fabric.Canvas("preview");
var imgs = ['bgBottom','bgTop', 'bgLevel', 'bgCircle'];
for (var i=0; i<imgs.length;i++){
var url = imgs[i]+'.png';
fabric.Image.fromURL(url, function (oImg) {
canvas.add(oImg)
})
}
fabric.Image.fromURL loads the image in the background and runs the anonymous function you pass to it once image load is complete which adds it to the canvas. The order that the browser loads the images will vary and you can't rely on it being in a specific order.
Check out this jsfiddle that shows loading an array of images and making sure they're displayed in a set order. This works by adding the image to the canvas before it's loaded; it just doesn't render until the image is available to be displayed.
The code from the jsfiddle:
var SelfLoadingImage = fabric.util.createClass(fabric.Object, {
initialize: function(src) {
this.image = new Image();
this.image.src = src;
this.image.onload = (function() {
this.width = this.image.width;
this.height = this.image.height;
this.loaded = true;
this.setCoords();
this.fire('image:loaded');
canvas.renderAll();
}).bind(this);
},
_render: function(ctx)
{
if (this.loaded) {
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
}
}
});
var canvas = new fabric.Canvas("preview");
var imgs = [
'http://icons.iconarchive.com/icons/fasticon/ifunny/128/dog-icon.png', // dog
'http://33.media.tumblr.com/avatar_14ee6ada72a4_128.png', // cat
'http://upload.wikimedia.org/wikipedia/commons/b/bc/Nuvola_devices_mouse.png' // mouse
];
for (var i=0; i<imgs.length;i++){
var url = imgs[i];
var img = new SelfLoadingImage(url);
canvas.add(img);
}

why aren't my images showing up

Hi I'm trying to learn how to use the EaselJS libraries, eventually combining with some of the EXTJS libs butt I'm having trouble putting all my code in the .Js files. My js file looks like this
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
function init() {
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
this doesn't work, but if I comment out the whole document.createElement('canvas') section and I apply
<body onLoad="init();">
<canvas id="demoCanvas" width="1000" height="1000">
alternate content
</canvas>
to my index.html file It will start working :( I included the .js within the body tag of te index html
Edit:::::::::::::::::::::: this is my current code, still not showing anything unless I add the canvas to the html page :(
window.onload = function (){
var demoCanvas = document.createElement('canvas');
//document.body.appendChild(democanvas);
demoCanvas.height = "400";
demoCanvas.width = "600";
}
var stage;
function init() {
stage = new createjs.Stage("demoCanvas");
var text = new createjs.Text("Hello World", "bold 86px Arial", "#ff7700");
stage.addChild(text);
stage.update();
}
init();
Another thing - since you are using image paths, and not fully loaded images as Bitmaps sources, its possible the images are not ready when you update the stage. You can either put onload handlers on your image(s) to update the stage, or preload them first.
var image = new Image();
image.onload = handleLoad;
image.src = "src.jpg";
function handleLoad(event) { stage.update(); }
// You can also use the Bitmap
var bitmap = new createjs.Bitmap("src.jpg");
bitmap.image.onload = handleLoad;
You can also tick the stage to update it constantly. This is a quick way to see if thats the problem.
createjs.Ticker.addEventListener("tick", stage);
// OR
createjs.Ticker.on("tick", stage);
try the below :
document.body.onload = function(){
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
function init() {
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
init();
}
Firstly you need to use the console of your navigator to see javascript's errors before any question.
You will see this error : Uncaught TypeError: Cannot call method 'appendChild' of null
That because you load document.body.appendChild(democanvas); before the html is load so your document.body is null.
This is the way:
function init() {
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
I had the same problem and I solved it by using a preloader.
You can use the PreloadJS preloader like this:
var preloader = new createjs.LoadQueue(true);
preloader.addEventListener("complete",this.handleComplete.bind(this));
var manifest = [
{src:"./images/yourIMAGE.PNG"},
//another image
];

Categories