I want to animate 2 figures on my page. Therefore I use Javascript. The problem is that I can't define which "sprite" he has to take. Because I can't add some Parameters like the object "animation" to the gameLoop()-method, because of the requestAnimationFrame. Any idea how I can solve this?
var animation,
image,
canvas,
stopAtLastFrame = false,
amountAnimation = 0,
amountAnimated = 1;
image = new Image();
function sprite (options) {
var that = {},
frameIndex = 0,
currentRow = 0,
currentColumn = 0,
tickCount = 0,
rowOfLastFrame = 0,
columnOfLastFrame = 0,
ticksPerFrame = options.ticksPerFrame,
numberOfFrames = options.numberOfFrames,
numberOfColumns = options.totalColumns,
numberOfRows = options.totalRows,
widthOfOneFrame = options.width/numberOfColumns,
heightOfOneFrame = options.height/numberOfRows;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
rowOfLastFrame = numberOfRows-1;
columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);
that.render = function () {
that.context.save();
that.context.scale(0.5,0.5);
// Clear the canvas
that.context.clearRect(0, 0, that.width, that.height);
// Draw the animation
that.context.drawImage(
that.image,
currentColumn * widthOfOneFrame,
currentRow * heightOfOneFrame,
widthOfOneFrame,
heightOfOneFrame,
0,
0,
widthOfOneFrame,
heightOfOneFrame);
that.context.restore();
if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
{
stopAtLastFrame=true;
}
};
that.update = function () {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
if (frameIndex < numberOfFrames-1) {
frameIndex++;
currentColumn++;
if (currentColumn == numberOfColumns) {
currentRow++;
currentColumn = 0;
}
}else{
amountAnimated++;
frameIndex=0;
currentColumn=0;
currentRow=0;
}
}
};
return that;
}
function gameLoop () {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
window.requestAnimationFrame(gameLoop);
animation.update();
animation.render();
}
}
function startAnimation(canvas, imageUrl, amount){
canvas = document.getElementById(canvas);
canvas.width = 7680/4;
canvas.height = 2880/4;
image.src = imageUrl;
amountAnimation=amount;
animation = sprite({
context: canvas.getContext("2d"),
width: 7684,
height: 2880,
image: image,
numberOfFrames:16,
totalRows : 4,
totalColumns: 4,
ticksPerFrame: 5
});
gameLoop();
}
startAnimation("imageAnimation", "img/16.png", 3);
startAnimation("imageAnimation2", "img/32.png", 5);
In this example I pretend that my spritesheets are the same size and columns, just to test the code.
This doesn't work of course, but this is what I need:
function gameLoop (animation) {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
window.requestAnimationFrame(gameLoop(animation));
animation.update();
animation.render();
}
}
requestAnimationFrame function is not allowed to pass your own parameter, one solution/trick is bound that gameLoop function to sprite object, so that we can access this as sprite object.
as example: http://jsfiddle.net/XQpzU/6110/
Your code can be modified as:
var animation,
image,
canvas,
stopAtLastFrame = false,
amountAnimation = 0,
amountAnimated = 1;
image = new Image();
function sprite (options) {
var that = {},
frameIndex = 0,
currentRow = 0,
currentColumn = 0,
tickCount = 0,
rowOfLastFrame = 0,
columnOfLastFrame = 0,
ticksPerFrame = options.ticksPerFrame,
numberOfFrames = options.numberOfFrames,
numberOfColumns = options.totalColumns,
numberOfRows = options.totalRows,
widthOfOneFrame = options.width/numberOfColumns,
heightOfOneFrame = options.height/numberOfRows;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
rowOfLastFrame = numberOfRows-1;
columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);
that.render = function () {
that.context.save();
that.context.scale(0.5,0.5);
// Clear the canvas
that.context.clearRect(0, 0, that.width, that.height);
// Draw the animation
that.context.drawImage(
that.image,
currentColumn * widthOfOneFrame,
currentRow * heightOfOneFrame,
widthOfOneFrame,
heightOfOneFrame,
0,
0,
widthOfOneFrame,
heightOfOneFrame);
that.context.restore();
if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
{
stopAtLastFrame=true;
}
};
that.update = function () {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
if (frameIndex < numberOfFrames-1) {
frameIndex++;
currentColumn++;
if (currentColumn == numberOfColumns) {
currentRow++;
currentColumn = 0;
}
}else{
amountAnimated++;
frameIndex=0;
currentColumn=0;
currentRow=0;
}
}
};
that.gameLoop = gameLoop.bind(that);
return that;
}
function gameLoop () {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
// this will be your sprite
window.requestAnimationFrame(this.gameLoop);
animation.update();
animation.render();
}
}
function startAnimation(canvas, imageUrl, amount){
canvas = document.getElementById(canvas);
canvas.width = 7680/4;
canvas.height = 2880/4;
image.src = imageUrl;
amountAnimation=amount;
animation = sprite({
context: canvas.getContext("2d"),
width: 7684,
height: 2880,
image: image,
numberOfFrames:16,
totalRows : 4,
totalColumns: 4,
ticksPerFrame: 5
});
animation.gameLoop();
}
startAnimation("imageAnimation", "img/16.png", 3);
startAnimation("imageAnimation2", "img/32.png", 5);
Related
I've tried making a sprite animation of a rotating book but it doesn't work. The canvas works fine, and another script works but the book script isn't working. The rest of the page works completely fine but I omitted the extra code since they do not need any corrections.
What is the problem? Thank you in advance
function myFunction() {
document.getElementById("changeBox").style.backgroundColor = "black";
document.getElementById("changeBox").style.fontSize = "40px";
document.getElementById("changeBox").style.textAlign = "center";
document.getElementById("showDate").innerHTML = Date();
}
function bookAnimation() {
var book,
bookImage,
canvas;
var c = document.getElementById("Book");
function gameLoop() {
window.requestAnimationFrame(gameLoop);
book.update();
book.render();
}
function sprite(options) {
var that = {},
frameIndex = 0,
tickCount = 0,
ticksPerFrame = options.ticksPerFrame || 0,
numberOfFrames = options.numberOfFrames || 1;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
that.update = function() {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
if (frameIndex < numberOfFrames - 1) {
frameIndex += 1;
} else {
frameIndex = 0;
}
}
};
that.render = function() {
that.context.clearRect(0, 0, that.width, that.height);
that.context.drawImage(
that.image,
frameIndex * that.width / numberOfFrames,
0,
that.width / numberOfFrames,
that.height,
0,
0,
that.width / numberOfFrames,
that.height);
};
return that;
}
canvas = document.getElementById("bookAnimation");
canvas.width = 100;
canvas.height = 100;
bookImage = new Image();
book = sprite({
context: canvas.getContext("2d"),
width: 1000,
height: 100,
image: bookImage,
numberOfFrames: 10,
ticksPerFrame: 4
});
bookImage.addEventListener("load", gameLoop);
bookImage.src = "E:\Second Year\cwd2018\Book Sprite.png";
}
<div style="background-color:black">
<div style="text-align:center;">
<input type="button" value="Welcome to Login Page" id="changeBox" onclick="myFunction()">
<p id="showDate"></p>
<canvas id="Book" width="200" height="200" style="background-color: yellow"></canvas>
</div>
</div>
I got an agar.io clone from online and I am trying to remove the Quadtree in the corner (acts as a map) completely! I try to delete everything associating with the quadtree but i end up with a gray screen. Could someone please remove the map from the top right corner for me or tell me which lines to remove?
Here is my HTML:
<div id="viewport">
<canvas id="canvas1"></canvas>
<canvas id="canvas2"></canvas>
<canvas id="canvas3" width="250px" height="250px"></canvas>
</div>
Here is my javascript:
var MouseHandler = (function() {
var x = 0;
var y = 0;
var mouseIn = false;
var init = function(eventSrc) {
eventSrc.addEventListener('mousemove', onMouseMove);
eventSrc.addEventListener('mouseout', onMouseOut);
eventSrc.addEventListener('mouseover', onMouseOver);
};
var onMouseOut = function() {
mouseIn = false;
};
var onMouseOver = function() {
mouseIn = true;
};
var onMouseMove = function(e) {
x = e.clientX;
y = e.clientY;
};
var getPos = function() {
return {
x: x,
y: y
};
};
var isMouseIn = function() {
return mouseIn;
};
return {
init: init,
getPos: getPos,
isMouseIn: isMouseIn
};
}());
Quadtree.MAX_OBJECTS = 5;
Quadtree.MAX_LEVEL = 5;
function Quadtree(lvl, bnds) {
var level = lvl;
var bounds = bnds;
var objects = [];
var nodes = [];
var xMiddle = bounds.x + (bounds.width / 2);
var yMiddle = bounds.y + (bounds.height / 2);
var clear = function() {
objects = [];
nodes = [];
};
var split = function() {
nodes[0] = new Quadtree(level+1, {x: xMiddle, y: bounds.y , width: bounds.width/2, height: bounds.height/2});
nodes[1] = new Quadtree(level+1, {x: bounds.x, y: bounds.y, width: bounds.width/2, height: bounds.height/2});
nodes[2] = new Quadtree(level+1, {x: bounds.x, y: yMiddle, width: bounds.width/2, height: bounds.height/2});
nodes[3] = new Quadtree(level+1, {x: xMiddle, y: yMiddle, width: bounds.width/2, height: bounds.height/2});
};
var getIndex = function(rec) {
var top = (rec.y > bounds.y && (rec.y+rec.height) < yMiddle);
var bottom = (rec.y > yMiddle && (rec.y+rec.height) < (bounds.y+bounds.height));
if(rec.x > bounds.x && (rec.x+rec.width) < xMiddle) {
if(top) {
return 1;
} else if(bottom) {//LEFT
return 2;
}
} else if(rec.x > xMiddle && (rec.x+rec.width) < (bounds.x+bounds.width)) {
if(top) {
return 0;
} else if(bottom) {//RIGHT
return 3;
}
}
return -1;
};
var insert = function(ent) {
var rec = ent.getBounds();
var index = getIndex(rec);
var len = 0;
var i = 0;
if(nodes[0] && index !== -1) {
nodes[index].insert(ent);
return;
}
objects.push(ent);
if(objects.length > Quadtree.MAX_OBJECTS && level < Quadtree.MAX_LEVEL) {
if(!nodes[0]) {
split();
}
len = objects.length;
while(i < objects.length) {
index = getIndex(objects[i].getBounds());
if(index !== -1) {
nodes[index].insert(objects[i]);
objects.splice(i, 1);
} else {
i += 1;
}
}
}
};
var retrieve = function (list, ent) {
var rec1 = bounds;
var rec2 = ent.getBounds();
if(rec2.x < (rec1.x+rec1.width) && (rec2.x+rec2.width) > rec1.x &&
rec2.y < (rec1.y+rec1.height) && (rec2.y+rec2.height) > rec1.y) {
for(var o in objects) {
if(objects[o] !== ent) {
list.push(objects[o]);
}
}
if(nodes.length) {
nodes[0].retrieve(list, ent);
nodes[1].retrieve(list, ent);
nodes[2].retrieve(list, ent);
nodes[3].retrieve(list, ent);
}
}
return list;
};
var drawTree = function(ctx) {
draw(ctx);
if(nodes[0]) {
nodes[0].drawTree(ctx);
nodes[1].drawTree(ctx);
nodes[2].drawTree(ctx);
nodes[3].drawTree(ctx);
}
};
var draw = function(ctx) {
var entAttr = null
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.strokeRect(bounds.x/20, bounds.y/20, bounds.width/20, bounds.height/20);
ctx.fillStyle = 'gray';
for(o in objects) {
entAttr = objects[o].getAttr();
ctx.fillRect(entAttr.x/20, entAttr.y/20, 3, 3);
}
};
var toString = function() {
return '('+bounds.x+','+bounds.y+')'+'['+bounds.width+','+bounds.height+']';
};
return {
clear: clear,
insert: insert,
retrieve: retrieve,
drawTree: drawTree,
toString: toString,
};
}
function Circle(attr) {
attr = attr || {};
var x = attr.x || 0;
var y = attr.y || 0;
var mass = attr.mass || 500;
var color = attr.color || 'white';
var borderColor = attr.borderColor || 'black';
var velX = attr.velX || 0;
var velY = attr.velY || 0;
var droplet = attr.droplet || false;
var maxVel = 80 * (80 / Math.sqrt(mass));
var radius = Math.sqrt( mass / Math.PI ); //1 unit of area === 1 uni of mass
var getAttr = function() {
return {
x: x,
y: y,
mass: mass,
radius: radius,
color: color,
velX: velX,
velY: velY,
maxVel: maxVel
};
};
var setAttr = function(attr) {
x = (attr.x !== undefined)? attr.x: x;
y = (attr.y !== undefined)? attr.y: y;
mass = (attr.mass !== undefined)? attr.mass: mass;
color = (attr.color !== undefined)? attr.color: color;
velX = (attr.velX !== undefined)? attr.velX: velX;
velY = (attr.velY !== undefined)? attr.velY: velY;
};
var incMass = function(dMass) {
mass += dMass;
maxVel = 100 * (100 / Math.sqrt(mass));
radius = Math.sqrt( mass / Math.PI );
};
var intersects = function(ent2) {
var ent2Attr = ent2.getAttr();
var dX = Math.abs(ent2Attr.x - x);
var dY = Math.abs(ent2Attr.y - y);
var totalRadius = ent2Attr.radius + radius;
return (dX < totalRadius && dY < totalRadius);
};
var draw = function(ctx, cam) {
var camSize = cam.getSize();
var rPos = cam.getRelPos(getAttr());
//if outside Cam view
if((rPos.x + radius) < 0 || (rPos.y + radius) < 0 || (rPos.x - radius) > camSize.width || (rPos.y - radius) > camSize.height) {
return;
}
ctx.fillStyle = color;
ctx.strokeStyle = borderColor;
ctx.lineWidth = 5;
ctx.beginPath();
ctx.arc(rPos.x, rPos.y, radius, 0, 2 * Math.PI, false);
ctx.fill();
ctx.stroke();
};
var update = !droplet && function(dTime) {
x += velX * dTime;
y += velY * dTime;
};
var getBounds = function() {
return {
x: x-radius,
y: y-radius,
width: radius*2,
height: radius*2,
};
};
return {
getBounds: getBounds,
getAttr: getAttr,
setAttr: setAttr,
incMass: incMass,
intersects: intersects,
draw: draw,
update: update
};
}
var gameManager = (function() {
var canvasGrid = null;
var canvasEnt = null;
var canvasQuadtree = null;
var ctxGrid = null;
var ctxEnt = null;
var ctxQuadTree = null;
var dTime = 1 / 60;
var player = null;
var entityBag = [];
var qTree = null;
var drwQuad = 0;
var addEntity = function(ent) {
entityBag.push(ent);
};
var removeEntity = function(ent) {
var len = entityBag.length;
var i = 0;
for(i=0; i<len; i+=1) {
if(ent === entityBag[i]) {
entityBag.splice(i, 1);
return;
}
}
};
var init = function(cvsGridId, cvsEntId, cvsQuadtree) {
canvasGrid = document.getElementById(cvsGridId);
canvasEnt = document.getElementById(cvsEntId);
canvasQuadtree = document.getElementById(cvsQuadtree);
ctxGrid = canvasGrid.getContext('2d');
ctxEnt = canvasEnt.getContext('2d');
ctxQuadtree = canvasQuadtree.getContext('2d');
fitToContainer(canvasGrid);
fitToContainer(canvasEnt);
ctxGrid.fillStyle = '#F0FBFF';
ctxGrid.strokeStyle = '#BFBFBF';
ctxGrid.lineWidth = 1;
MouseHandler.init(document);
qTree = new Quadtree(0, {x:0, y:0, width:5000, height:5000});
player = new Circle({
x: 50,
y: 50,
color: 'red',
mass: 1000,
velX: 500,
velY:500
});
Camera.init(ctxEnt, player);
addEntity(player);
gameloop();
};
var handleInput = function() {
if(MouseHandler.isMouseIn() === false) {
player.setAttr({ velX: 0, velY: 0 });
return;
}
var pAttr = player.getAttr();
var rPlyrPos = Camera.getRelPos(player.getAttr());
var mPos = MouseHandler.getPos();
var dX = mPos.x - rPlyrPos.x;
var dY = mPos.y - rPlyrPos.y;
var vLength = Math.sqrt( (dX*dX) + (dY*dY) );
var normX = dX / vLength;
var normY = dY / vLength;
var newVelX = normX * (pAttr.maxVel * vLength / 50);
var newVelY = normY * (pAttr.maxVel * vLength / 50);
player.setAttr({
velX: newVelX,
velY: newVelY
});
};
var drawGrid = function() {
var camPos = Camera.getPos();
var camSize = Camera.getSize();
var start = Math.floor(camPos.x / 40);
var relX = Camera.getRelPos({x: (start*40), y: 0}).x;
var numLines = camSize.width / 40;
var i = 0;
ctxGrid.fillRect(0, 0, canvasGrid.width, canvasGrid.height);
for(i=0; i<numLines; i+=1) {
ctxGrid.beginPath();
ctxGrid.moveTo(relX + (40 * i), 0);
ctxGrid.lineTo(relX + (40 * i), camSize.height);
ctxGrid.stroke();
}
start = Math.floor(camPos.y / 40);
var relY = Camera.getRelPos({x: 0, y: (start * 40)}).y;
numLines = camSize.height / 40;
for(i=0; i<numLines; i+=1) {
ctxGrid.beginPath();
ctxGrid.moveTo(0, relY + (40 * i));
ctxGrid.lineTo(camSize.width, relY + (40 * i));
ctxGrid.stroke();
}
};
var handleCollisions = function() {
var possibleColl = [];
var collisions = [];
var coll = null;
var ent = null;
var plyMass = player.getAttr().mass
var entMass = 0;
qTree.clear();
for(ent in entityBag) {
qTree.insert(entityBag[ent]);
}
possibleColl = qTree.retrieve([], player);
while(ent = possibleColl.pop()) {
if(player.intersects(ent)) {
entMass = ent.getAttr().mass;
if(plyMass > (1.5 * entMass)) {
removeEntity(ent);
player.incMass(entMass);
}
}
var entAttr = ent.getAttr();
ctxQuadtree.fillStyle = 'red';
ctxQuadtree.fillRect(entAttr.x/20, entAttr.y/20, 3, 3);
}
};
var fitToContainer = function(canvas) {
canvas.style.width='100%';
canvas.style.height='100%';
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
};
var gameloop = function() {
var len = entityBag.length;
var i = 0;
var ent = null;
handleInput();
Camera.update();
drawGrid();
if(drwQuad === 5) {
ctxQuadtree.fillStyle = 'white';
ctxQuadtree.fillRect(0, 0, 250, 250);
qTree.drawTree(ctxQuadtree);
drwQuad = 0;
}
drwQuad += 1;
ctxEnt.clearRect(0, 0, canvasEnt.width, canvasEnt.height)
for(i=0; i<len; i+=1) {
ent = entityBag[i];
if(ent.update) {
ent.update(dTime);
}
if(ent.draw) {
ent.draw(ctxEnt, Camera);
}
}
handleCollisions();
setTimeout(gameloop, dTime * 1000);
};
return {
init: init,
addEntity: addEntity,
removeEntity: removeEntity
};
}());
var Camera = (function() {
var x = 0;
var y = 0;
var width = 0;
var height = 0;
var ctx = null;
var player = null;
var init = function(_ctx, plyr) {
ctx = _ctx;
player = plyr;
width = ctx.canvas.width;
height = ctx.canvas.height;
};
var update = function() {
width = ctx.canvas.width;
height = ctx.canvas.height;
var plyrAttr = player.getAttr();
x = (plyrAttr.x - width / 2);
y = (plyrAttr.y - height / 2);
};
var getRelPos = function(entAttr) {
var relX = entAttr.x - x;
var relY = entAttr.y - y;
return {
x: relX,
y: relY
};
};
var getPos = function() {
return {
x: x,
y: y
};
};
var getSize = function() {
return {
width: width,
height: height
};
};
return {
init: init,
update: update,
getRelPos: getRelPos,
getPos: getPos,
getSize: getSize
};
}());
var i = 0;
var space = 70;
for(i=0; i<400; i+=1) {
gameManager.addEntity(new Circle({
x: 100 + Math.random() * 4850,//(i%20) * space,
y: 100 + Math.random() * 4850,//Math.floor(i/20)*space,
color: ['red', 'blue', 'green', 'yellow', 'purple', 'brown', 'violet'][Math.floor(Math.random()*7)],
droplet: true
}));
}
gameManager.init('canvas1', 'canvas2', 'canvas3');
And last but not least, my css:
html, body {
background: gray;
width: 100%;
height: 100%;
margin: 0px;
}
#viewport {
position: relative;
width: 100%;
height: 100%;
}
#viewport canvas {
position: absolute;
}
canvas {
background-color: transparent;
}
I am implementing a webgl magnifier which works fine .
But it distorts when I apply zoom using mousewheel.
I am using fabric.js and fcanvas.getZoom() returns the current zoom level that I am using to scale the magnifier.
Here's the codepen .
Can anyone check why it doesn't work while zooming in using mousewheel.
Code :
`
MainCanvas = (function() {
function MainCanvas(image, WIDTH, HEIGHT) {
var err;
this.image = image;
this.WIDTH = WIDTH != null ? WIDTH : 128;
this.HEIGHT = HEIGHT != null ? HEIGHT : 128;
this.mouseout = bind(this.mouseout, this);
this.mouseover = bind(this.mouseover, this);
this.mousemove = bind(this.mousemove, this);
this.render = bind(this.render, this);
zoomcanvas = $(document.createElement('canvas'));
zoomcanvas.css({
'position': 'absolute',
'width': this.WIDTH,
'height': this.HEIGHT,
'z-index': '1000',
'border': '3px solid rgba(0,0,0,0.4)',
'border-radius': '50%',
'box-shadow': '2px 2px 16px 2px #223',
'pointer-events': 'none'
});
$('#canvases').append(zoomcanvas);
med = [0.5, 0.5];
this.scaled = 1;
try {
this.gl = zoomcanvas[0].getContext("experimental-webgl") || zoomcanvas[0].getContext("webgl");
} catch (_error) {
err = _error;
console.log(err.message);
alert(err.message);
}
this.gl.clearColor(0.8, 0.8, 0.8, 1.0);
this.mouse = {
x: .5,
y: .5
};
this.mvMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
this.pMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
this.data = {};
this.initShaders();
this.initBuffers();
this.initImages();
this.render();
this.image.mousemove(this.mousemove);
this.image.mouseover(this.mouseover).mouseout(this.mouseout);
}
MainCanvas.prototype.initShaders = function() {
var fragmentShader, vertexShader;
fragmentShader = this.getShader('shader-fs');
vertexShader = this.getShader('shader-vs');
this.shaderProgram = this.gl.createProgram();
this.gl.attachShader(this.shaderProgram, vertexShader);
this.gl.attachShader(this.shaderProgram, fragmentShader);
this.gl.linkProgram(this.shaderProgram);
if (!this.gl.getProgramParameter(this.shaderProgram, this.gl.LINK_STATUS)) {
console.log('Não pode inicializar shaders!');
}
this.gl.useProgram(this.shaderProgram);
this.data.vertexPositionAttribute = this.gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
this.gl.enableVertexAttribArray(this.data.vertexPositionAttribute);
this.data.textureCoordAttribute = this.gl.getAttribLocation(this.shaderProgram, "aTextureCoord");
this.gl.enableVertexAttribArray(this.data.textureCoordAttribute);
this.data.samplerUniform0 = this.gl.getUniformLocation(this.shaderProgram, "sampler0");
this.data.medUniform = this.gl.getUniformLocation(this.shaderProgram, "med");
this.data.scaledUniform = this.gl.getUniformLocation(this.shaderProgram, "scaled");
};
MainCanvas.prototype.setMatrixUniforms = function() {
var normalMatrix;
this.gl.uniformMatrix4fv(this.data.pMatrixUniform, false, this.pMatrix);
this.gl.uniformMatrix4fv(this.data.mvMatrixUniform, false, this.mvMatrix);
normalMatrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
return this.gl.uniformMatrix3fv(this.data.nMatrixUniform, false, normalMatrix);
};
MainCanvas.prototype.getShader = function(id) {
var k, shader, shaderScript, str;
shaderScript = document.getElementById(id);
if (shaderScript === null) {
return false;
}
str = '';
k = shaderScript.firstChild;
while (k) {
if (k.nodeType === 3) {
str += k.textContent;
}
k = k.nextSibling;
}
if (shaderScript.type === "x-shader/x-fragment") {
shader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
} else {
shader = this.gl.createShader(this.gl.VERTEX_SHADER);
}
this.gl.shaderSource(shader, str);
this.gl.compileShader(shader);
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
console.log(this.gl.getShaderInfoLog(shader));
return false;
}
return shader;
};
MainCanvas.prototype.initBuffers = function() {
return this.bufferPlane();
};
MainCanvas.prototype.bufferPlane = function() {
var buffer, colors, indices, normais, uv, vertices;
vertices = [-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0];
buffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(vertices), this.gl.STATIC_DRAW);
buffer.itemSize = 3;
buffer.numItems = 4;
this.data.vertexPositionBuffer = buffer;
normais = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1];
buffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(normais), this.gl.STATIC_DRAW);
buffer.itemSize = 4;
buffer.numItems = 4;
this.data.vertexColorBuffer = buffer;
uv = [0, 0, 1, 0, 0, 1, 1, 1];
buffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(uv), this.gl.STATIC_DRAW);
buffer.itemSize = 2;
buffer.numItems = 4;
this.data.vertexTextureCoordBuffer = buffer;
indices = [0, 1, 2, 2, 3, 1];
buffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, buffer);
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), this.gl.STATIC_DRAW);
buffer.itemSize = 1;
buffer.numItems = 6;
return this.data.vertexIndexBuffer = buffer;
};
MainCanvas.prototype.handleTexture = function(texture) {
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, canvas);
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
this.gl.bindTexture(this.gl.TEXTURE_2D, null);
this.scaled = Math.max(this.WIDTH / this.image.width(), this.HEIGHT / this.image.height());
return this.scaled / (fcanvas.getZoom());
};
MainCanvas.prototype.initImages = function() {
this.data.texture0 = this.gl.createTexture();
this.handleTexture(this.data.texture0);
};
MainCanvas.prototype.render = function(t) {
this.gl.viewport(0, 0, zoomcanvas[0].width, zoomcanvas[0].height);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
this.gl.uniform1f(this.data.scaledUniform, this.scaled / fcanvas.getZoom() / 2);
this.gl.uniform2f(this.data.medUniform, parseFloat(med[0]) , parseFloat(med[1]));
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.data.vertexPositionBuffer);
this.gl.vertexAttribPointer(this.data.vertexPositionAttribute, this.data.vertexPositionBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.data.vertexTextureCoordBuffer);
this.gl.vertexAttribPointer(this.data.textureCoordAttribute, this.data.vertexTextureCoordBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
this.gl.activeTexture(this.gl.TEXTURE0);
this.gl.bindTexture(this.gl.TEXTURE_2D, this.data.texture0);
this.gl.uniform1i(this.data.samplerUniform0, 0);
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.data.vertexIndexBuffer);
this.setMatrixUniforms();
return this.gl.drawElements(this.gl.TRIANGLES, this.data.vertexIndexBuffer.numItems, this.gl.UNSIGNED_SHORT, 0);
};
MainCanvas.prototype.mousemove = function(e) {
var o2, x, y;
o2 = this.image.offset();
x = (e.offsetX + o2.left);
y = (e.offsetY + o2.top);
zoomcanvas.css({
'left': parseInt(x - this.WIDTH * 0.5),
'top': parseInt(y - this.HEIGHT * 0.5)
});
med[0] = (((e.offsetX - imageAttrs.left) ) / (oImg.width));
med[1] = (1.0 - (((e.offsetY - imageAttrs.top)) / (oImg.height)));
$('body').css('cursor', 'none');
return this.render();
};
MainCanvas.prototype.mouseover = function(e) {
return zoomcanvas.show();
};
MainCanvas.prototype.mouseout = function(e) {
return zoomcanvas.fadeOut("fast");
};
return MainCanvas;
})();
window.requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
return window.setTimeout(callback, 40);
};
window.onload = function(e) {
var mainCanvas;
console.clear();
console.log(Date.now());
var width = $("#sampler0")[0].width; var height = $("#sampler0")[0].height;
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d');
var AR = calculateAspectRatio(width, height);
ctx.drawImage($("#sampler0")[0], 0, 0, AR.renderableWidth, AR.renderableHeight);
var scaleX = AR.renderableWidth / width;
var scaleY = AR.renderableHeight / height;
oImg = new fabric.Image(canvas,
{
selectable : false,
width : width,
height : height,
lockUniScaling: true,
centeredScaling: true,
scaleX : scaleX,
scaleY : scaleY,
alignX : "mid",
alignY : "mid",
});
fcanvas.add(oImg);
///bring image to center
fcanvas.centerObject(oImg);
/////////////////////////////////////////////////////////
///scale image back to default
oImg.scaleX = 1;
oImg.scaleY = 1;
///get left and top for zooming correctly.
imageAttrs.scaleX = scaleX;
fcanvas.zoomToPoint({ x: oImg.left, y: oImg.top }, scaleX);
oImg.on('mouseout', function(event) {
zoomcanvas.fadeOut("fast");
});
oImg.on('mouseover', function(event) {
zoomcanvas.show();
});
imageAttrs.left = oImg.left;
imageAttrs.top = oImg.top;
fcanvas.renderAll();
applyZoom();
return mainCanvas = new MainCanvas($("#canvases"), 256, 256);
};
var calculateAspectRatio = function (width, height) {
var imageAspectRatio = width / height;
var canvasAspectRatio = windowWidth / windowHeight;
var renderableHeight, renderableWidth, xStart, yStart;
var AR = new Object();
/// If image's aspect ratio is less than canvas's we fit on height
/// and place the image centrally along width
if(imageAspectRatio < canvasAspectRatio) {
renderableHeight = windowHeight ;
renderableWidth = width * (renderableHeight / height);
xStart = (windowWidth - renderableWidth) / 2;
yStart = 0;
}
/// If image's aspect ratio is greater than canvas's we fit on width
/// and place the image centrally along height
else if(imageAspectRatio > canvasAspectRatio) {
renderableWidth = $(window).width()
renderableHeight = height * (renderableWidth / width);
xStart = 0;
yStart = ( windowHeight - renderableHeight) / 2;
}
///keep aspect ratio
else {
renderableHeight = windowHeight ;
renderableWidth = windowWidth;
xStart = 0;
yStart = 0;
}
AR.renderableHeight = renderableHeight;
AR.renderableWidth = renderableWidth;
return AR;
}
/**
* Used to apply Zooming on the canvas.
*/
var applyZoom = function () {
var canvasarea = document.getElementById("canvases");
if (canvasarea.addEventListener) {
// IE9, Chrome, Safari, Opera
canvasarea.addEventListener("mousewheel", zoom, false);
// Firefox
canvasarea.addEventListener("DOMMouseScroll", zoom, false);
}
// IE 6/7/8
else canvasarea.attachEvent("onmousewheel", zoom);
return this;
}
function zoom(e) {
var evt=window.event || e;
var delta = evt.detail? evt.detail*(-120) : evt.wheelDelta;
var curZoom = fcanvas.getZoom(), newZoom = curZoom + delta / 4000,
x = e.offsetX, y = e.offsetY;
//applying zoom values.
fcanvas.zoomToPoint({ x: x, y: y }, newZoom);
if(e != null)e.preventDefault();
return false;
}
}).call(this);`
Thanks
This is a game I am making. I cant figure out why it is not working. I have the JS fiddle here http://jsfiddle.net/aa68u/4/
// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
bgReady = true;
};
bgImage.src = "http://6269-9001.zippykid.netdna-cdn.com/wp-content/uploads/2013/11/Woods-Wallpaper.jpg";
// Ship image
var shipReady = false;
var shipImage = new Image();
shipImage.onload = function () {
shipImage = true;
};
shipImage.src = "http://s29.postimg.org/3widtojzn/hero.png";
// Astroid image
var astroidReady = false;
var astroidImage = new Image();
astroidImage.onload = function () {
astroidReady = true;
};
astroidImage.src = "http://s29.postimg.org/4r4xfprub/monster.png";
// Game objects
var ship = {
speed: 256;
};
var astroid = {};
var health = 100;
window.keyStates = {};
addEventListener('keydown', function (e) {
keyStates[e.keyCode || e.key] = true;
e.preventDefault();
e.stopPropagation();
}, true);
addEventListener('keyup', function (e) {
keyStates[e.keyCode || e.key] = false;
e.preventDefault();
e.stopPropagation();
}, true);
var reset = function () {
astroid.width = 10;
astroid.height = 10;
astroid.x = 32 + (Math.random() * (canvas.width - 64));
astroid.y = 32 + (Math.random() * (canvas.height - 64));
ship.speed = 256;
for (var p in keyStates) keyStates[p]= false;
};
// Update game objects
function update (modifier) {
if (keyStates[38] ==true) { // Player holding up
astroid.x -= ship.speed * modifier;
}
if (keyStates[40]==true) { // Player holding down
astroid.x += ship.speed * modifier;
}
if (keyStates[37]==true) { // Player holding left
astroid.y -= ship.speed * modifier;
}
if (keyStates[39]==true) { // Player holding right
astroid.y += ship.speed * modifier;
}
if (astroid.width) < 200{
astroid.width +=10;
astroid.height += 10;
}
if (astroid.width) > 200{
reset();
}
// Are they touching?
if (keyStates[32] == true && ship.x <= (astroid.x + 32) && astroid.x <= (ship.x + 32) && ship.y <= (astroid.y + 32) && astroid.y <= (ship.y + 32)) {
monstersCaught += 1;
reset();
}
};
// Draw everything
var render = function () {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
}
if (shipReady) {
ctx.drawImage(heroImage, hero.x, hero.y);
}
if (astroidReady) {
ctx.drawImage(monsterImage, monster.x, monster.y);
}
// Score
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "24px Helvetica";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText("Your Health: " + health, 32, 32);
};
// The main game loop
var main = function () {
var now = Date.now();
var delta = now - then;
if (delta > 20) delta = 20;
update(delta / 1000);
render();
then = now;
};
// Let's play this game!
reset();
var then = Date.now();
setInterval(main, 1); // Execute as fast as possible
The game is supposed to be a ship(shoe image) that is avoiding astroids that get bigger(ants) but when you move your ship(shoe) stays in the same place and the astroids(ants) move. The ants/astroids also get bigger like you are going close to them.
var ship = {
speed: 256;
};
Remove the ; after the value.
if astroid.width < 200{
and
if astroid.width > 200{
Need parentheses around the if conditions.
The error console is helpful! But now it's just stuck in an infinite loop of monsterImage is not defined. Just... go back, write your code more carefully, and use the error console! It's there for a reason!
I'm trying to make a simple (or so I thought) memory game. Unfortunately it does not update state of cards when user clicks on them. I'm running out of ideas, probably because it's my first javascript game. I suppose there is a problem with game loop. Could anyone at least point me in the right direction and help me understand what needs to be changed/rewritten?
//HTML5 Memory Game implementation
//main variables
var cards = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8];
var exposed = [makeArray("false",16)];
var first_card = 0;
var second_card = 0;
var moves = 0;
var WIDTH = 800;
var HEIGHT = 100;
var state = 0;
var mouseX = 0;
var mouseY = 0;
//creating canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = WIDTH;
canvas.height = HEIGHT;
document.getElementById("game").appendChild(canvas);
//filling empty array with number,character,object
function makeArray(value, length) {
var newArray = [];
var i = 0;
while (i<length) {
newArray[i] = value;
i++;
}
return newArray;
}
//shuffling algorithm
function shuffle(array) {
var copy = [];
var n = array.length;
var i;
while (n) {
i = Math.floor(Math.random() * n--);
copy.push(array.splice(i, 1)[0]);
}
return copy;
}
//where user clicks
function getClickPosition(event) {
var X = event.pageX - canvas.offsetLeft;
var Y = event.pageY - canvas.offsetTop;
return mouse = [X, Y];
}
//read click position
function readPos(event) {
mousePos = getClickPosition(event);
mouseX = mousePos[0];
mouseY = mousePos[1];
}
//initializing
function init() {
state = 0;
moves = 0;
exposed = [makeArray("false",16)];
cards = shuffle(cards);
}
//drawing cards
function draw() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i in cards) {
if (exposed[i] === true) {
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "50px Courier New";
ctx.fillText(cards[i], (i*50+12), 65);
} else {
ctx.strokeStyle = "rgb(250, 0, 0)";
ctx.fillStyle = "rgb(0, 0, 250)";
ctx.fillRect(i*50, 0, 50, 100);
ctx.strokeRect(i*50, 0, 50, 100);
}
}
};
//update cards
function update() {
if (exposed[parseInt(mouseX / 50)] === false) {
if (state == 0) {
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else if (state == 1) {
state = 2;
second_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else {
if (cards[first_card] != cards[second_card]) {
exposed[first_card] = false;
exposed[second_card] = false;
}
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
}
}
}
addEventListener('click', readPos, false);
setInterval(function() {
update();
draw();
}, 16);
I would check your addEventListener method: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener
I also recommend you look into using jQuery.
After copy and pasting your code I found a couple of things:
You didn't add an event listener to anything, you should add it to something so I added it to document.
You initialize the exposed array with values "false" and later check if they are false. These are not the same, the string "false" isn't the Boolean false.
You initializes the exposed array as a multi dimensional array [[false,false,false ...]] this should be a single dimension array because later you check exposed[1] (1 depending on the mouse x position.
No need to call draw and update every 16 milliseconds, you can call it after someone clicked.
Wrapped the whole thing up in a function so there are no global variables created.
Here is the code after changing these obvious errors. There might be room for optimization but for now I've gotten the problems out.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<div id="game"></div>
<script type="text/javascript">
(function(){
//HTML5 Memory Game implementation
//main variables
var cards = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8];
var exposed = makeArray(false, 16);
var first_card = 0;
var second_card = 0;
var moves = 0;
var WIDTH = 800;
var HEIGHT = 100;
var state = 0;
var mouseX = 0;
var mouseY = 0;
//creating canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = WIDTH;
canvas.height = HEIGHT;
document.getElementById("game").appendChild(canvas);
//filling empty array with number,character,object
function makeArray(value, length) {
var newArray = [];
var i = 0;
while (i < length) {
newArray.push(value);
i++;
}
return newArray;
}
//shuffling algorithm
function shuffle(array) {
var copy = [];
var n = array.length;
var i;
while (n) {
i = Math.floor(Math.random() * n--);
copy.push(array.splice(i, 1)[0]);
}
return copy;
}
//where user clicks
function getClickPosition(event) {
var X = event.pageX - canvas.offsetLeft;
var Y = event.pageY - canvas.offsetTop;
return mouse = [X, Y];
}
//read click position
function readPos(event) {
mousePos = getClickPosition(event);
mouseX = mousePos[0];
mouseY = mousePos[1];
update();
draw();
}
//initializing
function init() {
state = 0;
moves = 0;
exposed = makeArray(false, 16);
cards = shuffle(cards);
}
//drawing cards
function draw() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i in cards) {
if (exposed[i] === true) {
ctx.fillStyle = "rgb(150, 150, 150)";
ctx.font = "50px Courier New";
ctx.fillText(cards[i], (i * 50 + 12), 65);
} else {
ctx.strokeStyle = "rgb(250, 0, 0)";
ctx.fillStyle = "rgb(0, 0, 250)";
ctx.fillRect(i * 50, 0, 50, 100);
ctx.strokeRect(i * 50, 0, 50, 100);
}
}
};
//update cards
function update() {
if (exposed[parseInt(mouseX / 50)] === false) {
if (state == 0) {
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else if (state == 1) {
state = 2;
second_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else {
if (cards[first_card] != cards[second_card]) {
exposed[first_card] = false;
exposed[second_card] = false;
}
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
}
}
}
document.body.addEventListener('click', readPos, false);
init();
draw();
})();
</script>
</body>
</html>
Your overall logic was good.
The point that was 'bad' was the way you handle the event :
the event handler should store some valuable information that
the update will later process and clear.
Here you mix your update with event handling, which cannot work
especially since the event will not fire on every update.
So i did a little fiddle to show you, the main change is
the click event handler, which update the var last_clicked_card :
http://jsfiddle.net/wpymH/
//read click position
function readPos(event) {
last_clicked_card = -1;
mousePos = getClickPosition(event);
mouseX = mousePos[0];
mouseY = mousePos[1];
// on canvas ?
if ((mouseY>100)||(mouseX<0)||(mouseX>WIDTH)) return;
// now yes : which card clicked ?
last_clicked_card = Math.floor(mouseX/50);
}
and then update is the processing of this information :
//update cards
function update() {
// return if no new card clicked
if (last_clicked_card == -1) return;
// read and clear last card clicked
var newCard = last_clicked_card;
last_clicked_card=-1;
// flip, store it as first card and return
// if there was no card flipped
if (state==0) { exposed[newCard] = true;
first_card = newCard;
state = 1 ;
return; }
// just unflip card if card was flipped
if ((state = 1) && exposed[newCard]) {
exposed[newCard]=false ;
state=0;
return;
}
// we have a second card now
second_card = newCard;
exposed[second_card] = true;
draw();
// ... i don't know what you want to do ...
if (cards[first_card] == cards[second_card]) {
alert('win'); }
else {
alert('loose'); }
exposed[first_card]=false;
exposed[second_card]=false;
state=0;
}