I created render method after canvas image x or y is changed. But only one image is drawn after changing position, the second one isn't drawn. It also depends in what order I add that images on the screen.
App.js
my_Doge = game.addSprite("Doge", "mydoggy", 0, 700, 100, 100);
my_Cat = game.addSprite("Cat", "mycat", 0, 0, 100, 100);
function update(){
game.setPos(my_Cat, my_Cat.xcoord+=2, my_Cat.ycoord+=2);
game.setPos(my_Doge, my_Doge.xcoord+=2, my_Doge.ycoord-=2);
}
Library.js
moopleGame.prototype.setPos = function(sprite, newX, newY)
{ // Set new sprite position
sprite.xcoord = newX;
sprite.ycoord = newY;
for(var i = 0; i < this.addedSprites.length; i++)
{
this.sprite_index = 0;
if(sprite.id == this.addedSprites[i].id) // Find index of that image in array
{
this.sprite_index = i;
}
}
this.render(this.sprite_index, sprite.width, sprite.height, sprite.xcoord, sprite.ycoord);
}
moopleGame.prototype.render = function(index, width, height, x, y) // Draw image to screen
{
ctx = this.ctx;
this.fillCanvas();
this.addedSprites[index].x = x;
this.addedSprites[index].y = y;
var w = new Image();
w.src = this.addedSprites[index].src;
ctx.drawImage(w, this.addedSprites[index].x,
this.addedSprites[index].y,
this.addedSprites[index].width,
this.addedSprites[index].height);
}
Preview
Related
I found these two pieces of code and I'm quite new to Java. Essentially I'd like to be able to select the image from a file selector (like the first piece of code) instead of specifying the url of an image. Also, is there a way that I could output a list of all the coordinates to the console pr ideally create a txt file with the coords in?
I've left links to jsfiddle for both
thank you!!
http://jsfiddle.net/edprattt/m2a1j8yf/
https://jsfiddle.net/edprattt/8xqo71Lk/
##1
function showImage(src, target) {
var fr = new FileReader();
fr.onload = function(){
target.src = fr.result;
}
fr.readAsDataURL(src.files[0]);
}
function putImage() {
var src = document.getElementById("select_image");
var target = document.getElementById("target");
showImage(src, target);
}
##2
var canvas = document.getElementById('Canvas');
var context = canvas.getContext("2d");
var mapSprite = new Image();
mapSprite.src = "http://www.retrogameguide.com/images/screenshots/snes-legend-of-zelda-linkto-the-past-8.jpg";
var Marker = function () {
this.Sprite = new Image();
this.Sprite.src = "http://www.clker.com/cliparts/w/O/e/P/x/i/map-marker-hi.png"
this.Width = 12;
this.Height = 20;
this.XPos = 0;
this.YPos = 0;
}
var Markers = new Array();
var mouseClicked = function (mouse) {
// Get corrent mouse coords
var rect = canvas.getBoundingClientRect();
var mouseXPos = (mouse.x - rect.left);
var mouseYPos = (mouse.y - rect.top);
console.log("Marker added");
var marker = new Marker();
marker.XPos = mouseXPos - (marker.Width / 2);
marker.YPos = mouseYPos - marker.Height;
Markers.push(marker);
}
canvas.addEventListener("mousedown", mouseClicked, false);
var firstLoad = function () {
context.font = "15px Georgia";
context.textAlign = "center";
}
firstLoad();
var main = function () {
draw();
};
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw map
// Sprite, X location, Y location, Image width, Image height
// You can leave the image height and width off, if you do it will draw the image at default size
context.drawImage(mapSprite, 0, 0, 700, 700);
// Draw markers
for (var i = 0; i < Markers.length; i++) {
var tempMarker = Markers[i];
// Draw marker
context.drawImage(tempMarker.Sprite, tempMarker.XPos, tempMarker.YPos, tempMarker.Width, tempMarker.Height);
// Calculate postion text
var markerText = "Postion (X:" + tempMarker.XPos + ", Y:" + tempMarker.YPos;
// Draw a simple box so you can see the position
var textMeasurements = context.measureText(markerText);
context.fillStyle = "#666";
context.globalAlpha = 0.7;
context.fillRect(tempMarker.XPos - (textMeasurements.width / 2), tempMarker.YPos - 15, textMeasurements.width, 20);
context.globalAlpha = 1;
// Draw position above
context.fillStyle = "#000";
context.fillText(markerText, tempMarker.XPos, tempMarker.YPos);
}
};
setInterval(main, (1000 / 60)); // Refresh 60 times a second
I'm doing a little game on JavaScript and have a problem, Example: I have my square move randomly and one red square always standing (not move), when my square touch the red square, it will automacally find the way avoid the red square, but i don't know how to make my square find its way through the red square. I'm using canvas withmethod canvas.drawRect.
imgur.com/a/7e93Xn6, Here is my square, i want it move up or down automacaly to avoid the red square, but don't know how to make it, Thanks
This is actually not too complicated you just have to continually check if those two squares will touch if one of them is moving. This can be calculated using it's screen positions and size. If those are about to collide move sideways as long as moving forward would still lead into the other square.
Here's a quick example:
var canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 300;
document.body.appendChild(canvas);
var context = canvas.getContext("2d");
var Squares = function(xPos, yPos, wid, hei, col) {
this.x = xPos;
this.y = yPos;
this.width = wid;
this.height = hei;
this.color = col;
this.speed = 0;
}
var redSquare = new Squares(200, 100, 40, 40, "#ff0000");
var blueSquare = new Squares(0, 100, 40, 40, "#0000ff");
blueSquare.speed = 3;
var squares = [redSquare, blueSquare];
function loop() {
if (blueSquare.x + blueSquare.width + blueSquare.speed > redSquare.x && blueSquare.y + blueSquare.height > redSquare.y) {
blueSquare.x = redSquare.x - blueSquare.width;
blueSquare.y -= blueSquare.speed;
} else {
blueSquare.x += blueSquare.speed;
}
if (blueSquare.x > canvas.width) {
blueSquare.x = 0;
blueSquare.y = 100;
}
context.clearRect(0, 0, canvas.width, canvas.height);
for (var a = 0; a < squares.length; a++) {
context.fillStyle = squares[a].color;
context.fillRect(squares[a].x, squares[a].y, squares[a].width, squares[a].height);
}
}
var interval = setInterval(loop, 20);
I made a Canvas with 32x32 tiles. I wanted to stroke the tile the mouse is on, this is what I made (Thanks to some tutorials and adjustments)
First, I create cPush and cUndo. cPush is called when I draw something, to memorize it. For cUndo, you'll see later. I also call my ctx var and I call my canvas var.
var canvas = document.getElementById('canvas');
var cPushArray = new Array();
var cStep = -1;
var ctx = canvas.getContext('2d');
function cPush() {
cStep++;
if (cStep < cPushArray.length) { cPushArray.length = cStep; }
cPushArray.push(document.getElementById('canvas').toDataURL());
}
function cUndo() {
if (cStep > 0) {
cStep--;
var canvasPic = new Image();
canvasPic.src = cPushArray[cStep];
canvasPic.onload = function () { ctx.drawImage(canvasPic, 0, 0); }
}
}
I will skip some parts because they are not necessary.
Here, I'm calling the onmousemove function :
canvas.onmousemove = function(e) {
let rects = [], i = 0, r;
let jk = 0;
for(var nb = 0, l = map.terrain.length ; nb < l ; nb++) {
var ligne = map.terrain[nb];
var y2 = nb * 32;
for(var j = 0, k = ligne.length ; j < k ; j++, jk++) {
rects[jk] = {lignej: ligne[j], x: j * 32, y: y2, w: 32, h: 32};
}
}
This first part is made to get every tiles of the map and store it into rects[x] This will be useful for me later, when I will need specific tiles.
Now, I call a function :
map.test = function(linewidth) {
this.tileset.dessinerTile(r.lignej, context, r.x, r.y);
ctx.lineWidth = linewidth;
ctx.strokeRect(r.x, r.y, 32, 32);
}
This is made to redraw the Tile i'm on with a stroke. (r. = rects var, you'll see later)
Here's the rest :
var rect = this.getBoundingClientRect(),
x = e.clientX - rect.left,
y = e.clientY - rect.top;
while (r = rects[i++]) {
ctx.beginPath();
ctx.rect(r.x, r.y, 32, 32);
if (ctx.isPointInPath(x, y) == true) {
cPush();
map.test(2);
} else {
cUndo();
}
}
};
The var Rect is made to check the mouse's position.
Now, there's a while. For each tiles we'll check if isPointinPath is true. (x and y are the mouse's positions).
So, if that's true, the function map.test will draw the tile with a 2 lineWidth stroke as mentioned.
If not, it will Undo the last stroke.
What I wanted to do here :
If the mouse is on a tile, it stroke the tile. If the mouse move, it undo the last stroke and stroke the new one.
What it does :
If the mouse is on a tile, it stroke the tile before doing an undo of the stroke because it check the other ones. So the stroke only last 0.5s instead of being permanent until I move the mouse.
I think the problem is that I'm using a "onmousemove" function ? Do I need to change to a "onmousehover" or something like that ? I'm quite lost...
Thanks for the help !
RECORD OF THE PROBLEM (Sorry for the low FPS it's a gif)
http://recordit.co/GokcSAoMv6
Here I'm trying to draw squares with the same opacity, side by side.
Even though each squares x position is exactly the width of a square apart, they look as though there are more semi transparent squares being drawn on top of them. The first square having the higher opacity level, and less so on the last one, which creates this gradient of squares effect.
I have console logged out the number of squares being rendered and it is as expected. So I dont believe there are extra squares being rendered on top of them.
I'v also checked the x positions to see if there is any overlap, which there isn't. So what could be causing the squares to have different transparencies?
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const canvas = document.getElementById("app-canvas");
canvas.width = windowWidth;
canvas.height = windowHeight;
canvas.style.position = "absolute";
canvas.style.backgroundColor = "grey";
canvas.style.zIndex = 1;
document.body.appendChild(canvas);
class Scene {
constructor() {
this.orbs = [];
this.squares = [];
this.context = canvas.getContext("2d");
}
addOrb(orb) {
this.orbs.push(orb);
}
addSquare(square) {
this.squares.push(square);
}
render() {
this.context.clearRect(0, 0, windowWidth, windowHeight);
this.squares.forEach(square => {
square.draw(this.context);
});
}
}
class Square {
constructor(options) {
this.options = options;
}
draw(ctx) {
let x = this.options.x;
let y = this.options.y;
let width = this.options.width;
let height = this.options.height;
ctx.moveTo(x,y);
ctx.rect(x, y, width, height);
ctx.fillStyle = "rgba(255,255,255,.1)";
ctx.fill();
}
};
let squares = [];
let squareWidth = 200;
let squareHeight = 200;
let x = 0;
let y = 0;
for (let i = 0; i < windowWidth; i+=squareWidth) {
x += squareWidth;
let square = new Square({
x, y: 0, width: squareWidth, height: squareHeight
});
console.log(square)
squares.push(square);
}
console.log(squares.length);
let scene = new Scene();
squares.forEach(square => scene.addSquare(square));
scene.render();
You need a call to ctx.beginPath() before every rectangle. Otherwise, the calls to .rect() are just adding to the path, and fill() fills the whole thing.
draw(ctx) {
let x = this.options.x;
let y = this.options.y;
let width = this.options.width;
let height = this.options.height;
ctx.beginPath(); // <========= this
ctx.moveTo(x,y);
ctx.rect(x, y, width, height);
ctx.fillStyle = "rgba(255,255,255,.1)";
ctx.fill();
}
You might also consider just using .fillRect().
I'm trying to implement a flip image with canvas, like this but the animation is weird from the middle
update
This is only a part of the image, the final result is
From
transition
To
but am having trouble, for I am creating a small buffer for each animation and then replaced them with a time interval
// globals
animations = [];
handler;
// Main canvas, the user see this
context;
canvas;
function flip(x, y, width, height) {
// getBuffer returns {cv: canvas, cx, context }
var buffer = getBuffer(canvas.width, canvas.height),
// getNextImage return a Image object ready for use
img = getNextImage(),
ready = false,
interval;
buffer.cx.drawImage(img, x, x);
newImage = buffer.cx.getImageData(x, y, width, height);
for (var i = 5; i > 0; i--) {
smallBuff = getBuffer(width, height);
scale = -(1/i);
smallBuff.cx.translate(width / 2, 0);
smallBuff.cx.scale(scale, 1);
smallBuff.cx.putImageData(newImage, x, y);
animations.push(smallBuff);
ready = (1 === i);
};
interval = setInterval(function() {
console.log("Are you ready: ", ready);
if (ready) {
clearInterval(interval);
handler = setInterval(function() {
animation(x, y, width, height);
}, 200);
}
}, 100);
}
function animation(x, y, width, height) {
if(animations.length > 0) {
var anim = animations.pop();
anim.cx.fillstyle = '#000';
anim.cx.clearRect(x, y, width, height);
context.drawImage(anim.cv, x, y);
console.log("left:", animations.length);
} else {
clearInterval(handler);
}
}