I have a function which generates six random numbers (areacanvas.length is 6)
And then paints it on canvas as a array of dots. What I need to do is to write those canvas values in my HTML file using .innerHTML
I don't know how to do it,because the window.generatedNumber is different after single iteration,how I am supposed to save all six values and then write them on HTML?
function generateDotMap() {
for (let index = 0; index < areacanvas.length; index++) {
var canvas = document.getElementById(areacanvas[index]);
var ctx = canvas.getContext('2d');
// generate random number
window.generatedNumber = (Math.floor(Math.random() * 89) + 10).toString();
This is my table:
<table style="width:100%">
<tr>
<th>Answers from input :</th>
<td id ="one"></td>
</tr>
<tr>
<th>Answers from method :</th>
<td id="two"></td>
</tr>
</tr>
</table>
I use the method below to write in HTML values from my textboxes in order to compare the generated values and guessed by user ( daltonism test)
function checkHumanInput() {
clearTimeout(humanInputCheckTimeout);
if (parseInt(document.getElementById('HUMAN_INPUTT').value) == 1) {
let liczba1 = document.getElementById('HUMAN_INPUT_1').value;
let liczba2 = document.getElementById('HUMAN_INPUT_2').value;
let liczba3 = document.getElementById('HUMAN_INPUT_3').value;
let liczba4 = document.getElementById('HUMAN_INPUT_4').value;
let liczba5 = document.getElementById('HUMAN_INPUT_5').value;
let liczba6 = document.getElementById('HUMAN_INPUT_6').value;
document.getElementById('one').innerHTML="Values given by user " + liczba1 +"," + liczba2 +","+ liczba3 +","+ liczba4 +","+ liczba5 +","+ liczba6 +"." ;
document.getElementById('two').innerHTML="And random numbers? " + +"." ;
document.getElementById('HUMAN_INPUT_BOX').style.borderColor = '#00A000';
} else {
document.getElementById('HUMAN_INPUT_BOX').style.borderColor = '#A00000';
}
The whole genereateDOtMap method looks like that:
function generateDotMap() {
for (let index = 0; index < areacanvas.length; index++) {
var canvas = document.getElementById(areacanvas[index]);
var ctx = canvas.getContext('2d');
// white background
ctx.globalAlpha = 1;
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, parseInt(canvas.width), parseInt(canvas.height));
var canvasCenter = {
x: Math.floor(canvas.width / 2) - 20,
y: Math.floor(canvas.height / 2) - 20
};
// dots array
var dots = [];
// generate random number
window.generatedNumber = (Math.floor(Math.random() * 89) + 10).toString();
// number as black text
ctx.font = 'italic bold ' + (canvasCenter.y + Math.floor(canvas.height / 5)) + 'px "Comic Sans MS"';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = '#000000';
ctx.fillText(window.generatedNumber, canvasCenter.x - Math.floor(canvasCenter.x / 7), canvasCenter.y - Math.floor(canvasCenter.y / 16));
for (var i = 0; i < DOTS_TO_RENDER; i++) {
var x, y, radius, j;
// loop
do {
// get point inside of a cricle
var point = getRandomPointInCircle();
// radius
var radius = getGaussianRandom(DOT_SIZE_mean, DOT_SIZE_var);
j = 0;
for (; j < i; j++) {
if (distanceCheck([point.x, point.y, radius], dots[j])) {
break;
}
}
} while (j != i);
// get canvas coordinates
var hX = point.x * canvasCenter.x + canvasCenter.x;
var hY = canvasCenter.x - point.y * canvasCenter.y;
var overNumber = ctx.isPointInPath(hX, hY);
// ctx.getImageData(point.x,point.y,ctx.width,ctx.height);
// [redColor, greenColor, blueColor, alpha]
var overNumber = (ctx.getImageData(hX, hY, 1, 1).data[0] == 0);
if (overNumber) {
color = hsvToRgb(HUE_NUMBER + Math.random() * HUE_VARIANCE, SATURATION, VALUE + 10);
} else {
color = hsvToRgb(HUE_BACKGROUND + Math.random() * HUE_VARIANCE, SATURATION, VALUE);
}
dots.push([point.x, point.y, radius, overNumber, color]);
}
// powiększanie kropek (wypełnienie)
// sortowanie od najmniejszej do największej, małe powiększane najpierw
dots.sort(function (a, b) { return a[2] - b[2] });
for (var pass = 0; pass < 2; pass++) {
for (var j = 0; j < dots.length; j++) {
var small_d = 99999;
for (var k = 0; k < dots.length; k++) {
if (j == k) {
continue;
}
var d = distanceCalc(dots[j], dots[k]) - (dots[j][2] + dots[k][2] + MIN_DISTANCE);
if (d < small_d) {
small_d = d;
}
}
if (small_d > 0) {
dots[j][2] += small_d;
}
}
dots.sort(function (a, b) { return a[2] - b[2] });
}
window.saved_dots.push(dots)
}
Based on what I understand, I have commented out the parts that we do not have information for (i.e. HTML) and I have added the insertion of random numbers to a specified div with id of randomNumDiv
This should be good enough to help you
function generateDotMap() {
var randomNumDiv = document.getElementById("randomNumbers");
for (let index = 0; index < 6 /*areacanvas.length*/ ; index++) {
//var canvas = document.getElementById(areacanvas[index]);
//var ctx = canvas.getContext('2d'); // generate random number
var generatedNumber = (Math.floor(Math.random() * 89) + 10).toString();
randomNumDiv.innerHTML = randomNumDiv.innerHTML + " " + generatedNumber;
}
}
generateDotMap();
<div id="randomNumbers"></div>
Related
This is the code of the paint bucket tool in my drawing app using the p5.js library. The function self.floodFill always get "Maximum Call Stack Size Exceeded" because of recursion and I want to know the way to fix it. I am thinking if changing the function to a no recursion function would help or not. Any help would be appreciated.
function BucketTool(){
var self = this;
//set an icon and a name for the object
self.icon = "assets/bucket.jpg";
self.name = "Bucket";
var d = pixelDensity();
var oldColor;
var searchDirections = [[1,0],[-1,0],[0,1],[0,-1]];
var pixelsToFill = [];
var positionArray = new Array(2);
self.checkBoundary = function(currentX, currentY, localOldColor) {
if (self.getPixelAtXYPosition(currentX,currentY).toString() != localOldColor.toString() || currentX < 0 || currentY < 0 || currentX > width || currentY > height || pixelsToFill.indexOf(currentX+" "+currentY) != -1) {
return false;
}
return true;
};
self.floodFill = function(currentX, currentY, localOldColor, localSearchDirections) {
if (self.checkBoundary(currentX, currentY, localOldColor)){
pixelsToFill.push(currentX+" "+currentY);
} else {
return;
}
for (var i = 0; i < searchDirections.length; i++){
self.floodFill(currentX + searchDirections[i][0], currentY + searchDirections[i][1], localOldColor, localSearchDirections);
}
};
self.getPixelAtXYPosition = function(x, y) {
var colour = [];
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
// loop over
index = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[index];
colour[1] = pixels[index+1];
colour[2] = pixels[index+2];
colour[3] = pixels[index+3];
}
}
return colour;
}
self.drawTheNeededPixels = function(){
for(var i = 0; i < pixelsToFill.length; i++){
positionArray = pixelsToFill[i].split(" ");
point(positionArray[0],positionArray[1]);
}
}
self.draw = function () {
if(mouseIsPressed){
pixelsToFill = [];
loadPixels();
oldColor = self.getPixelAtXYPosition(mouseX, mouseY);
self.floodFill(mouseX, mouseY, oldColor, searchDirections);
self.drawTheNeededPixels();
}
};
}
This problem is well documented on the wikipedia page and the shortfalls of the different types of algorithms to perform flood filling. You've gone for the stack-based recursive implementation.
To prevent a stackoverflow — Maximum Call Stack Exceeded — the first step would be to use a data structure. Using queues/stacks rather than having the function call itself.
The code below creates an empty stack where we put a new object containing the x and y where the user has chosen to fill. This is then added to the pixelsToFill array. We then loop the stack until it's completely empty, at which point we are ready to display the filled pixels.
In the while loop we pop an element off the stack and then find its children — the directions up, down, left, right denoted by the searchDirections array you created. If we've not seen the child before and it's within the boundary we add it to the pixelsToFill array and add it to the stack to repeat the process:
self.floodFill = function (currentX, currentY, localOldColor, localSearchDirections) {
let stack = [];
stack.push({ x: currentX, y: currentY });
pixelsToFill.push(currentX + " " + currentY);
while (stack.length > 0) {
let current = stack.pop();
for (var i = 0; i < searchDirections.length; i++) {
let child = {
x: current.x + searchDirections[i][0],
y: current.y + searchDirections[i][1],
localOldColor,
};
if (self.checkBoundary(child.x, child.y, localOldColor)) {
pixelsToFill.push(child.x + " " + child.y);
stack.push(child);
}
}
}
};
This code may stop the stackoverflow but there are still a lot of optimisations that can be made. Once again, it's worth checking out the Wikipedia page and potentially take a look at Span filling.
let bucketTool;
function setup() {
createCanvas(400, 400);
bucketTool = new BucketTool();
}
function draw() {
background(220);
strokeWeight(5);
circle(width / 2, height / 2, 100);
frameRate(1);
bucketTool.draw();
}
function BucketTool() {
var self = this;
//set an icon and a name for the object
// self.icon = "assets/bucket.jpg";
// self.name = "Bucket";
var d = pixelDensity();
var oldColor;
var searchDirections = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];
var pixelsToFill = [];
var positionArray = new Array(2);
self.checkBoundary = function (currentX, currentY, localOldColor) {
if (
self.getPixelAtXYPosition(currentX, currentY).toString() !=
localOldColor.toString() ||
currentX < 0 ||
currentY < 0 ||
currentX > width ||
currentY > height ||
pixelsToFill.indexOf(currentX+" "+currentY) != -1
) {
return false;
}
return true;
};
self.floodFill = function (currentX, currentY, localOldColor, localSearchDirections) {
let stack = [];
stack.push({ x: currentX, y: currentY });
pixelsToFill.push(currentX + " " + currentY);
while (stack.length > 0) {
let current = stack.pop();
for (var i = 0; i < searchDirections.length; i++) {
let child = {
x: current.x + searchDirections[i][0],
y: current.y + searchDirections[i][1],
localOldColor,
};
if (self.checkBoundary(child.x, child.y, localOldColor)) {
pixelsToFill.push(child.x + " " + child.y);
stack.push(child);
}
}
}
};
self.getPixelAtXYPosition = function (x, y) {
var colour = [];
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
// loop over
index = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[index];
colour[1] = pixels[index + 1];
colour[2] = pixels[index + 2];
colour[3] = pixels[index + 3];
}
}
return colour;
};
self.drawTheNeededPixels = function () {
for (var i = 0; i < pixelsToFill.length; i++) {
positionArray = pixelsToFill[i].split(" ");
point(positionArray[0], positionArray[1]);
}
};
self.draw = function () {
if (mouseIsPressed) {
pixelsToFill = [];
loadPixels();
oldColor = self.getPixelAtXYPosition(mouseX, mouseY);
self.floodFill(mouseX, mouseY, oldColor, searchDirections);
console.log(pixelsToFill.length);
self.drawTheNeededPixels();
}
};
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
<script src="sketch.js"></script>
</body>
</html>
Shameless plug, but relevant: I've created a blog comparing the different flood fill algorithms using p5.js.
I have a function that wraps textboxes in FabricJS so that they don't become too wide, (it is automatically line breaking when the the maximum width is reached). However it is causing the text cursor to get pushed behind by 1 character every time it adds a new line.
Look at this gif to fully see the problem in play a gif
I am using the following function to automatically line break the text box. To give some context, it checks if the length of a textLine exceeds the maxWidth, and if it is the case with the last word included but doesn't exceed if the last word is not included, then it adds a new line by entering \n and somewhere here it causes the problem.
function wrapCanvasText(t, canvas, maxW, maxH) {
let initialFormatted = t.text
if (typeof maxH === "undefined") {
maxH = 0;
}
var words = t.text.split(" ")
var formatted = '';
// clear newlines
var sansBreaks = t.text.replace(/(\r\n|\n|\r)/gm, "");
// calc line height
var lineHeight = new fabric.Text(sansBreaks, {
fontFamily: t.fontFamily,
fontSize: t.fontSize
}).height;
// adjust for vertical offset
var maxHAdjusted = maxH > 0 ? maxH - lineHeight : 0;
var context = canvas.getContext("2d");
context.font = t.fontSize + "px " + t.fontFamily;
var currentLine = "";
var breakLineCount = 0;
for (var n = 0; n < words.length; n++) {
console.log(words[n])
var isNewLine = currentLine == " ";
var testOverlap = currentLine + ' ' + words[n] + ' ';
// are we over width?
var w = context.measureText(testOverlap).width;
if (w < maxW) { // if not, keep adding words
currentLine += words[n] + ' ';
formatted += words[n] += ' ';
} else {
// if this hits, we got a word that need to be hypenated
if (isNewLine) {
var wordOverlap = "";
// test word length until its over maxW
for (var i = 0; i < words[n].length; ++i) {
wordOverlap += words[n].charAt(i);
var withHypeh = wordOverlap + "-";
if (context.measureText(withHypeh).width >= maxW) {
// add hyphen when splitting a word
withHypeh = wordOverlap.substr(0, wordOverlap.length - 2) + "-";
// update current word with remainder
words[n] = words[n].substr(wordOverlap.length - 1, words[n].length);
formatted += withHypeh; // add hypenated word
break;
}
}
}
n--; // restart cycle
if (words[n+1] !== '') {
formatted += '\n';
breakLineCount++;
}
currentLine = "";
}
if (maxHAdjusted > 0 && (breakLineCount * lineHeight) > maxHAdjusted) {
// add ... at the end indicating text was cutoff
formatted = formatted.substr(0, formatted.length - 3) + "...\n";
break;
}
}
// get rid of empy newline at the end
formatted = formatted.substr(0, formatted.length - 1);
return formatted;
}
You can try out this snippet it is an approximate version of what I have, most importantly, it does have the same cursor problem. To try out the problem, edit the text directly in the canvas after initialization.
var canvas = new fabric.Canvas('c');
canvas.backgroundColor = "#F5F5F5";
var textArea = document.getElementById('addNote');
function checkForChange() {
var activeObject = canvas.getActiveObject();
let formatted1 = wrapCanvasText(activeObject, canvas, 400, 2000);
activeObject.text = formatted1;
}
function wrapCanvasText(t, canvas, maxW, maxH) {
let initialFormatted = t.text
if (typeof maxH === "undefined") {
maxH = 0;
}
var words = t.text.split(" ")
var formatted = '';
// clear newlines
var sansBreaks = t.text.replace(/(\r\n|\n|\r)/gm, "");
// calc line height
var lineHeight = new fabric.Textbox(sansBreaks, {
fontFamily: t.fontFamily,
fontSize: t.fontSize
}).height;
// adjust for vertical offset
var maxHAdjusted = maxH > 0 ? maxH - lineHeight : 0;
var context = canvas.getContext("2d");
context.font = t.fontSize + "px " + t.fontFamily;
var currentLine = "";
var breakLineCount = 0;
for (var n = 0; n < words.length; n++) {
console.log(words[n])
var isNewLine = currentLine == " ";
var testOverlap = currentLine + ' ' + words[n] + ' ';
// are we over width?
var w = context.measureText(testOverlap).width;
if (w < maxW) { // if not, keep adding words
currentLine += words[n] + ' ';
formatted += words[n] += ' ';
} else {
// if this hits, we got a word that need to be hypenated
if (isNewLine) {
var wordOverlap = "";
// test word length until its over maxW
for (var i = 0; i < words[n].length; ++i) {
wordOverlap += words[n].charAt(i);
var withHypeh = wordOverlap + "-";
if (context.measureText(withHypeh).width >= maxW) {
// add hyphen when splitting a word
withHypeh = wordOverlap.substr(0, wordOverlap.length - 2) + "-";
// update current word with remainder
words[n] = words[n].substr(wordOverlap.length - 1, words[n].length);
formatted += withHypeh; // add hypenated word
break;
}
}
}
n--; // restart cycle
if (words[n + 1] !== '') {
formatted += '\n';
breakLineCount++;
}
currentLine = "";
}
if (maxHAdjusted > 0 && (breakLineCount * lineHeight) > maxHAdjusted) {
// add ... at the end indicating text was cutoff
formatted = formatted.substr(0, formatted.length - 3) + "...\n";
break;
}
}
// get rid of empy newline at the end
formatted = formatted.substr(0, formatted.length - 1);
return formatted;
}
$("#addNote").keyup(function(e) {
var activeObject = canvas.getActiveObject();
if (activeObject && activeObject.type == 'textbox') {
activeObject.text = textArea.value
let formatted1 = wrapCanvasText(activeObject, canvas, 400, 2000);
activeObject.text = formatted1;
while (activeObject.textLines.length > 1 && canvas.getWidth() * 0.8 >= activeObject.width) {
activeObject.set({
width: activeObject.getScaledWidth() + 1
})
}
canvas.renderAll();
} else {
var textSample = new fabric.Textbox(textArea.value, {});
textSample.left = 0
textSample.splitByGrapheme = true
textSample.lockRotation = true
textSample.editable = true
textSample.perPixelTargetFind = false
textSample.hasControls = true
textSample.width = canvas.getWidth() * 0.8
textSample.height = canvas.getHeight() * 0.8
textSample.maxWidth = canvas.getWidth() * 0.8
textSample.maxHeight = canvas.getHeight() * 3
canvas.add(textSample);
canvas.setActiveObject(textSample);
canvas.renderAll();
}
canvas.on('text:changed', checkForChange)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js"></script>
<textarea id="addNote"></textarea>
<canvas id="c" width="400" height="400"></canvas>
I've got a small web app in development to simulate the Ising model of magnetism. I've found that the animation slows down considerably after a few seconds of running, and it also doesn't loop after 5 seconds like I want it to with the command:
setInteval(main, 500)
I've added start and stop buttons. When I stop the animation, and then restart it, it begins fresh at the usual speed, but again slows down.
My question is: what steps can I take to troubleshoot and optimize the performance of my canvas animation? I hope to reduce or mitigate this slowing effect.
JS code:
window.onload = function() {
var canvas = document.getElementById("theCanvas");
var context = canvas.getContext("2d");
var clength = 100;
var temperature = 2.1;
var playAnim = true;
canvas.width = clength;
canvas.height = clength;
var imageData = context.createImageData(clength, clength);
document.getElementById("stop").addEventListener("click",function(){playAnim=false;});
document.getElementById("start").addEventListener("click",function(){playAnim=true;});
function init2DArray(xlen, ylen, factoryFn) {
//generates a 2D array of xlen X ylen, filling each element with values defined by factoryFn, if called.
var ret = []
for (var x = 0; x < xlen; x++) {
ret[x] = []
for (var y = 0; y < ylen; y++) {
ret[x][y] = factoryFn(x, y)
}
}
return ret;
}
function createImage(array, ilen, jlen) {
for (var i = 0; i < ilen; i++) {
for (var j = 0; j < jlen; j++) {
var pixelIndex = (j * ilen + i) * 4;
if (array[i][j] == 1) {
imageData.data[pixelIndex] = 0; //r
imageData.data[pixelIndex+1] = 0; //g
imageData.data[pixelIndex+2] = 0; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//black
} else if (array[i][j] == -1) {
imageData.data[pixelIndex] = 255; //r
imageData.data[pixelIndex+1] = 255; //g
imageData.data[pixelIndex+2] = 255; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//white
}
}
}
}
function dU(i, j, array, length) {
var m = length-1;
//periodic boundary conditions
if (i == 0) { //top row
var top = array[m][j];
} else {
var top = array[i-1][j];
}
if (i == m) { //bottom row
var bottom = array[0][j];
} else {
var bottom = array[i+1][j];
}
if (j == 0) { //first in row (left)
var left = array[i][m];
} else {
var left = array[i][j-1];
}
if (j == m) { //last in row (right)
var right = array[i][0];
} else {
var right = array[i][j+1]
}
return 2.0*array[i][j]*(top+bottom+left+right); //local magnetization
}
function randInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
var myArray = init2DArray(clength, clength, function() {var c=[-1,1]; return c[Math.floor(Math.random()*2)]}); //creates a 2D square array populated with -1 and 1
function main(frame) {
if (!playAnim){return;} // stops
window.requestAnimationFrame(main);
createImage(myArray, clength, clength);
context.clearRect(0,0,clength,clength);
context.beginPath();
context.putImageData(imageData,0,0);
for (var z = 0; z < 10*Math.pow(clength,2); z++) {
i = randInt(clength-1);
j = randInt(clength-1);
var deltaU = dU(i, j, myArray, clength);
if (deltaU <= 0) {
myArray[i][j] = -myArray[i][j];
} else {
if (Math.random() < Math.exp(-deltaU/temperature)) {
myArray[i][j] = -myArray[i][j];
}
}
}
}
var timer = setInterval(main, 500);
}
For a fun little project I decided to program conway's game of life in javascript. My logic seems to make sense and each individual function does its job however I still dont get my intended result. I have an array called grid, which stores the value of all the cells, and if they are alive or dead. I check each individual cell, then check all 8 surrounding cells to count neighbors, repeat for every other cell. At some point my grid no longer stores the correct value and resets. At this point I'm starting to think it's a javascript problem.
<body>
<style>
* {
padding: 0;
margin: 0;
}
body {
overflow: hidden;
}
canvas {
background: #FFFFFF;
display: block;
margin: 0 auto;
}
</style>
<canvas id="canvas" style="border:1px solid #000000;"></canvas>
</body>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var Game = {};
var nextGrid, emptyGrid, grid;
Game.horCells = 30;
Game.cellSize = canvas.width / Game.horCells;
Game.verCells = Math.floor(canvas.height / Game.cellSize);
Game.startLives = 80;
config();
//setInterval(run, 1000);
function config() {
console.log("in config");
emptyGrid = newGrid(Game.horCells, Game.verCells);
grid = emptyGrid;
nextGrid = emptyGrid;
//Manual Setup
for (var i = 0; i < Game.startLives; i++) {
//grid[getRandomInt(0, Game.horCells - 1)][getRandomInt(0, Game.verCells - 1)] = true;
}
grid[0][3] = true;
grid[1][3] = true;
grid[2][3] = true;
}
function run() {
console.log("gread" + grid[3][3]);
draw();
update();
}
function draw() {
console.log("Draw");
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < Game.horCells; i++) {
for (var j = 0; j < Game.verCells; j++) {
if (grid[i][j] === false) {
ctx.fillStyle = "#FFFFFF";
} else if (grid[i][j] === true) {
console.log("drawing live");
ctx.fillStyle = "#000000";
}
ctx.fillRect(i * Game.cellSize, j * Game.cellSize, Game.cellSize, Game.cellSize);
}
}
}
function update() {
for (var p = 0; p < Game.horCells; p++) {
for (var k = 0; k < Game.verCells; k++) {
nextGrid[p][k] = survival(p, k);
}
}
}
function survival(x, y) {
var neighbours = 0;
for (var l = 0; l < 3; l++) {
for (var m = 0; m < 3; m++) {
var sx = (x - 1) + l;
var sy = (y - 1) + m;
//Check bounds
if (inBounds(sx, sy) === true && grid[sx][sy]) {
neighbours++;
}
}
}
if (grid[x][y]) {
neighbours--;
if (neighbours === 2 || neighbours === 3) {
return true;
} else if (neighbours < 2 || neighbours > 3) {
console.log("DIED");
return false;
}
} else if (grid[x][y] === false && neighbours === 3) {
return true;
} else {
console.log("DIED");
return false;
}
}
function inBounds(x, y) {
return (x >= 0 && x < Game.horCells && y >= 0 && y < Game.horCells);
}
function newGrid(xCells, yCells) {
var gridd = new Array(xCells);
for (var i = 0; i < xCells; i++) {
gridd[i] = new Array(yCells);
}
for (var j = 0; j < xCells; j++) {
for (var k = 0; k < yCells; k++) {
gridd[j][k] = false;
}
}
return gridd;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
emptyGrid = newGrid(Game.horCells, Game.verCells);
grid = emptyGrid;
nextGrid = emptyGrid
Creates 1 grid, then assigns grid and nextGrid to the same object. Again, grid and nextGrid are the same object. Any changes you make to 1 will happen to the other.
Create 2 separate grids so they can be changed independently:
grid = newGrid(Game.horCells, Game.verCells);
nextGrid = newGrid(Game.horCells, Game.verCells);
Or, to neaten it up slightly:
var g = () => newGrid(Game.horCells, Game.verCells);
grid = g();
nextGrid = g();
Just to clear up the question in the comments:
var g = () => newGrid(Game.horCells, Game.verCells);
Is (basically) the same thing as:
var g = function() {
return newGrid(Game.horCells, Game.verCells);
}
It's known as a "fat-arrow" function.
Both bits do the same thing though: they create a function that returns a new grid. This has the benefit of not needing to write newGrid(Game.horCells, Game.verCells); twice.
I used an arrow function instead of the function keyword because the latter is giant and ugly, which takes away from the goal of cleaning up the code.
I made a puzzle game in javascript. I have made objects to keep some attributes relevant to the each pazzle squares. I want to get the object id which is relevant to the onclick.(not the div id). How to get the specific object id relevant to the clicked div?
window.onload = function() {
createDivs();
objects();
random();
onclickeventHanlder(event);
};
var getId;
var x = 3;
var counting = 0;
var tileSize = 600 / x;
var array2 = [];
var object = [];
function createDivs() {
var count = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
var id = i + "" + j;
var element = document.createElement('div');
element.setAttribute("class", "pieces");
element.setAttribute("id", id);
element.style.width = 600 / x + "px";
element.style.height = 600 / x + "px";
element.style.margin = "0px auto";
element.style.overflow = "hidden";
element.setAttribute("onclick", "onclickeventHanlder(this)");
if (count > 0) { // to break row-wise
if (i == count && j == 0) {
element.style.clear = "both";
}
}
element.style.float = "left";
document.getElementById('puzzle-body').appendChild(element);
}
count++;
}
}
function objects(){
var count = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
var objName = new Object();
objName.position = -(j * tileSize) + "px" + " " + -(i * tileSize) + "px";
objName.divID = document.getElementById(i + "" + j);
objName.id = count;
if(count<x*x-1){
objName.state = true; // if image is there
}else{
objName.state = false; // if image isn't there
}
object[count] = objName;
count++;
}
}
}
function reset(){
var looping = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
var obj = object[looping];
if(obj.id<8){
var urlString = 'url("../images/Golden.jpg")';
obj.divID.style.backgroundImage = urlString;
obj.divID.style.backgroundPosition = obj.position;
}
looping++;
}
}
}
function random(){
var array = [];
while (array.length < ((x * x) - 1)) {
var randomnumber = Math.floor(Math.random() * ((x * x) - 1));
var found = false;
for (var i = 0; i < array.length; i++) {
if (array[i] == randomnumber) {
found = true;
break;
}
}
if (!found) {
array[array.length] = randomnumber;
}
}
var looping = 0;
for (var i = 0; i < x; i++) {
for (var j = 0; j < x; j++) {
if (looping < x * x-1) {
var random = array[looping];
var obj = object[random];
var obj2 = object[looping];
if(obj.id<8){
var urlString = 'url("../images/Golden.jpg")';
obj.divID.style.backgroundImage = urlString;
obj.divID.style.backgroundPosition = obj2.position;
}
}
looping++;
}
}
}
function onclickeventHanlder(event) {
var pos = event;
}