Canvas game Json function only works on web inspector - javascript

i'm making a HTML5 game and i'm using a matriz to store the map. But now i'm using $getJson to read that values through a json file and it works, but the problem is when a change the value of my matrix through the web inspector the map changes but when i call that function directly on code i get an error:
game.js:51TypeError: 'undefined' is not an object (evaluating 'levels.Level1')
line 51: mapa.loadMap(levels.Level1.board);
Why this only works when a call the function "mapa.loadMap(levels.Level1.board)" on web inspector?
function map(){
this.loadMap = function (l){
var j= 0;
for (var i = 0; i < l.length; i++) {
var object = l[i];
for (property in object) {
var value = object[property];
this.board[j][property] = value;
}
j++;
}
}
this.width = 10;
this.height = 8;
this.image = new Image();
this.image.src = "images/level1/tiles.png";
this.board = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 2],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[8, 0, 0, 0, 33, 1, 1, 1, 1, 1],
[8, 0, 0, 0, 0, 0, 0, 37, 0, 0],
[25, 26, 0, 0, 0, 0, 0, 38, 0, 0],
[27, 28, 5, 5, 6, 7, 0, 38, 0, 0],
[1, 1, 1, 1, 1, 9, 5, 39, 5, 5],
];
(...)
Forget that XD
My code is a mess because it's a sketch but i solved with:
$(document).ready(function(){
init();
});
$(window).load(function () {
console.log(levels.Level1.board);
mapa = new map();
render();
});
Thanks for helping :)
And sorry for my english XD

$(document).ready(function(){
init();
});
$(window).load(function () {
console.log(levels.Level1.board);
mapa = new map();
render();
});

Related

Javascript for loop odd behavior

I'm writing an algorithm to solve a sudoku puzzle and I'm getting some weird behavior. My first draft below did not give me an error, but it was modifying the array. Then I realized (because I am new to JavaScript) that I have to put let before the var in the for loop, so I changed it.
The weird behavior is that when I change it to let row and let col in the for loop it no longer modifies the puzzle param array. I do not understand how adding the let word to the for loop changes this?
test = [
[8, 0, 6, 0, 1, 0, 0, 0, 0],
[0, 0, 3, 0, 6, 4, 0, 9, 0],
[9, 0, 0, 0, 0, 0, 8, 1, 6],
[0, 8, 0, 3, 9, 6, 0, 0, 0],
[7, 0, 2, 0, 4, 0, 3, 0, 9],
[0, 0, 0, 5, 7, 2, 0, 8, 0],
[5, 2, 1, 0, 0, 0, 0, 0, 4],
[0, 3, 0, 7, 5, 0, 2, 0, 0],
[0, 0, 0, 0, 2, 0, 1, 0, 5]
]
let result = solve(test)
console.log(result)
printPuzzle(test)
function solve(puzzle) {
for (row = 0; row < 9; row++) {
for (col = 0; col < 9; col++) {
if (puzzle[row][col] === 0) {
for (number = 1; number < 9; number++) {
if (isValidPlacement(puzzle, number, row, col)) {
puzzle[row][col] = number
if (solve(puzzle)) {
return true
} else {
puzzle[row][col] = 0
}
}
}
return false
}
}
}
return true
}

How to create procedural array map (using arrays for tile maps)

I have a game, (published BTW its here at https://juniorcpc.itch.io/dungeon-game and the download file for the code is there too), and it uses arrays to create tile maps. (0-4 numbers represent different tiles) The problem is i can only create maps and publish those, and i want to know how to have the code create those array maps for me. I cannot use other tutorials, as they only show how to with tile maps, or mazes, or something else, but mine uses arrays not other systems. If there is a way to make a procedural map with arrays that would be awesome, thanks!
BTW the arrays are 10x10 grids, 1 = wall, 0 = empty space, 3 = exit.
Example of array:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 2, 4, 1,
1, 2, 2, 0, 0, 2, 2, 2, 2, 1,
1, 1, 1, 2, 0, 2, 2, 2, 2, 1,
1, 2, 2, 0, 0, 2, 2, 2, 4, 1,
1, 0, 0, 0, 2, 2, 2, 3, 2, 1,
1, 0, 2, 2, 2, 2, 2, 2, 2, 1,
1, 0, 2, 1, 1, 2, 0, 0, 0, 1,
1, 0, 2, 2, 2, 2, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
],
Here is how it draws them: ( i have a canvas in my HTML with a width of 300px and a height of 300px)
function mapM() {
var ctx = document.getElementById("canv").getContext('2d');
ctx.fillStyle = "red";
var mapOnX = -1;
var mapOnY = 0;
var l = map[0].length + 1;
for (i = 0; i < l; i++) {
if (i % 10 == 0) {
var mapOnX = 0;
mapOnY++;
} else {
mapOnX++;
}
if (map[level][i] == 1) {
ctx.fillStyle = "red";
} else {
if (map[level][i] == 0) {
ctx.fillStyle = 'blue';
} else {
if (map[level][i] == 3) {
ctx.fillStyle = 'gold';
} else {
if (map[level][i] == 2) {
ctx.fillStyle = 'black';
} else {
ctx.fillStyle = 'lightBlue';
}
}
}
}
ctx.fillRect(mapOnX * 25, mapOnY * 25, 25, 25);
ctx.fillStyle = 'purple';
ctx.fillRect(mapX * 25, mapY * 25, 25, 25);
}
}
Dont worry about other numbers i can do that. Thanks!

Javascript - Optimal way to get maximum sum of arrays in an array

I have the following array:
arr = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 0, 0, 1, 1, 0 ],
[ 1, 0, 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 1, 0, 0, 2 ],
[ 1, 0, 0, 1, 0, 2, 4 ],
[ 0, 0, 0, 0, 2, 4, 4 ],
[ 0, 0, 0, 0, 4, 4, 0 ],
[ 1, 1, 1, 0, 0, 0, 0 ],
[ 1, 1, 0, 2, 0, 0, 2 ],
[ 1, 0, 0, 4, 0, 2, 0 ],
[ 0, 0, 0, 4, 2, 0, 0 ],
[ 0, 0, 2, 0, 0, 0, 1 ],
[ 0, 2, 4, 0, 0, 1, 2 ],
[ 2, 4, 4, 2, 1, 2, 4 ],
[ 4, 4, 0, 0, 2, 4, 0 ]
]
Currently, I'm getting the max array sum in arr i.e 19 like this
function getMaxSum(arr) {
return arr.map(e => e.reduce((a, b) => a + b, 0)).sort((a,b) => a - b)[arr.length - 1];
}
I need to know is there any better way to achieve this?
I'm using array length of the original array to get the last element of resulting array because in this case, length of original array and resulting array is same. If the scenario is different then how can I use the length of the resulting array here:
return arr.map(e => e.reduce((a, b) => a + b, 0)).sort((a,b) => a - b)[HERE - 1];
Not a huge improvement, but it seems a little more literal to spread the values into Math.max
const data = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 0, 0, 1, 1, 0 ],
[ 1, 0, 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 1, 0, 0, 2 ],
[ 1, 0, 0, 1, 0, 2, 4 ],
[ 0, 0, 0, 0, 2, 4, 4 ],
[ 0, 0, 0, 0, 4, 4, 0 ],
[ 1, 1, 1, 0, 0, 0, 0 ],
[ 1, 1, 0, 2, 0, 0, 2 ],
[ 1, 0, 0, 4, 0, 2, 0 ],
[ 0, 0, 0, 4, 2, 0, 0 ],
[ 0, 0, 2, 0, 0, 0, 1 ],
[ 0, 2, 4, 0, 0, 1, 2 ],
[ 2, 4, 4, 2, 1, 2, 4 ],
[ 4, 4, 0, 0, 2, 4, 0 ]
]
function getMaxSum(arr) {
return Math.max(...arr.map(e => e.reduce((a, b) => a + b, 0)))
}
console.log(getMaxSum(data))
As #Rajesh points out, Math.max is faster that a sort:
const numbers = Array(10000).fill().map((x,i)=>i);
const max = numbersIn => Math.max(...numbersIn);
const getMaxViaSort = numbersIn => numbersIn
.sort((a, b) => a > b ? -1 : 1)[0]
console.time('max');
max(numbers);
console.timeEnd('max');
console.time('max via sort');
getMaxViaSort(numbers);
console.timeEnd('max via sort');
The optimal strategy should be one where we need the least interaction with the arrays.
In my method i test the array products individually and compare that with a variable inside my loop. In this way i don't need to run a new implied loop to have Math.max check all my entries again, netting a speed boost.
This also saves on memory management as i don't need to map and return a new array of results for Math.max.
At the end of the loop i simply return the variable.
var data = [
[1, 1, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 1, 1, 0],
[1, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 2],
[1, 0, 0, 1, 0, 2, 4],
[0, 0, 0, 0, 2, 4, 4],
[0, 0, 0, 0, 4, 4, 0],
[1, 1, 1, 0, 0, 0, 0],
[1, 1, 0, 2, 0, 0, 2],
[1, 0, 0, 4, 0, 2, 0],
[0, 0, 0, 4, 2, 0, 0],
[0, 0, 2, 0, 0, 0, 1],
[0, 2, 4, 0, 0, 1, 2],
[2, 4, 4, 2, 1, 2, 4],
[4, 4, 0, 0, 2, 4, 0]
];
function getMaxSum1(arr) {
//The original method
return arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }).sort(function (a, b) { return a - b; })[arr.length - 1];
}
function getMaxSum2(arr) {
//From https://stackoverflow.com/a/51704254/5242739
return Math.max.apply(Math, arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }));
}
function sumArray(arr) {
var val = 0;
for (var index = 0; index < arr.length; index++) {
val += val;
}
return val;
}
function getMaxSum3(arr) {
//My method
var max;
for (var i = 0; i < arr.length; i++) {
var val = sumArray(arr[i]);
if (max === void 0 || val > max) {
max = val;
}
}
return max;
}
//TEST
//parameters
var runs = 10;
var tests = 100000;
//output area
var out = document.body.appendChild(document.createElement("pre"));
//test functions
function simulate1() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum1(data);
}
out.textContent += 'getMaxSum1 took: ' + (Date.now() - dt) + "ms\n";
requestAnimationFrame(simulate2);
}
function simulate2() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum2(data);
}
out.textContent += 'getMaxSum2 took: ' + (Date.now() - dt) + "ms\n";
requestAnimationFrame(simulate3);
}
function simulate3() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum3(data);
}
out.textContent += 'getMaxSum3 took: ' + (Date.now() - dt) + "ms\n\n";
if (runs--) {
requestAnimationFrame(simulate1);
}
}
//start
simulate1();
pre {
max-height: 200px;
overflow-y: scroll;
background-color: #eee;
}
I included OliverRadini's answer to compare the relative speed boosts.

Programming 16 bit adder in javascript from gates

I am following the course nand2tetris and doing the exercises but not with there software. Instead I'm trying todo everything in javascript. The purpose is to build a nand gate and from that you create all your chips/gates.
I wrote for every gate unit tests and they pass but for my 16 bit adder they fail and I don't really know why.
function Adder() {
this.halfAdder = function(a, b) {
var gate = new Gate();
var sum = gate.XOR(a, b);
var carry = gate.AND(a, b);
return [sum, carry];
};
this.fullAdder = function(a, b, c) {
var gate = new Gate();
var out1 = this.halfAdder(a, b);
var out2 = this.halfAdder(c, out1[0]);
var result = gate.OR(out1[1], out2[1])
return [out2[0], result];
};
this.Adder16 = function(a, b) {
/*
HalfAdder(a=a[0],b=b[0],sum=out[0],carry=carry1);
FullAdder(a=a[1],b=b[1],c=carry1,sum=out[1],carry=carry2);
FullAdder(a=a[2],b=b[2],c=carry2,sum=out[2],carry=carry3);
FullAdder(a=a[3],b=b[3],c=carry3,sum=out[3],carry=carry4);
FullAdder(a=a[4],b=b[4],c=carry4,sum=out[4],carry=carry5);
FullAdder(a=a[5],b=b[5],c=carry5,sum=out[5],carry=carry6);
FullAdder(a=a[6],b=b[6],c=carry6,sum=out[6],carry=carry7);
FullAdder(a=a[7],b=b[7],c=carry7,sum=out[7],carry=carry8);
FullAdder(a=a[8],b=b[8],c=carry8,sum=out[8],carry=carry9);
FullAdder(a=a[9],b=b[9],c=carry9,sum=out[9],carry=carry10);
FullAdder(a=a[10],b=b[10],c=carry10,sum=out[10],carry=carry11);
FullAdder(a=a[11],b=b[11],c=carry11,sum=out[11],carry=carry12);
FullAdder(a=a[12],b=b[12],c=carry12,sum=out[12],carry=carry13);
FullAdder(a=a[13],b=b[13],c=carry13,sum=out[13],carry=carry14);
FullAdder(a=a[14],b=b[14],c=carry14,sum=out[14],carry=carry15);
FullAdder(a=a[15],b=b[15],c=carry15,sum=out[15],carry=carry16);
*/
var sum = [];
var carry;
sum[0] = this.halfAdder(a[0], b[0])[0];
carry = this.halfAdder(a[0], b[0])[1];
for (var i = 1; i <= 15; i++) {
sum[i] = this.fullAdder(a[i], b[i], carry)[0];
carry = this.fullAdder(a[i], b[i], carry)[1];
}
return sum;
}
}
My gates looks like the following:
function Gate() {
this.NAND = function(a, b) {
if (a == 1 && b == 1) return 0;
else return 1;
};
this.NOT = function(a) {
return this.NAND(a, a);
};
this.AND = function(a, b) {
return this.NOT(this.NAND(a, b));
};
this.OR = function(a, b) {
return this.NOT(this.AND(this.NOT(a), this.NOT(b)));
};
this.XOR = function(a, b) {
return this.OR(this.AND(a, this.NOT(b)), this.AND(this.NOT(a), b));
};
}
My half adder and full adder work, they passed all the unit tests provided by the creators of the course but for my 16 bit adder not. The unit tests are these:
describe('adder 16 bit tests', function() {
it('adder of a = 0000000000000000 and b = 0000000000000000 should be out = 0000000000000000', function() {
var adder = new Adder();
var a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var out = adder.Adder16(a, b);
var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
assert.deepEqual(result, out);
});
it('adder of a = 0000000000000000 and b = 1111111111111111 should be out = 1111111111111111', function() {
var adder = new Adder();
var a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var b = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
var out = adder.Adder16(a, b);
var result = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
assert.deepEqual(result, out);
});
it('adder of a = 1111111111111111 and b = 1111111111111111 should be out = 1111111111111110', function() {
var adder = new Adder();
var a = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
var b = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
var out = adder.Adder16(a, b);
var result = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0];
assert.deepEqual(result, out);
});
it('adder of a = 1010101010101010 and b = 0101010101010101 should be out = 1111111111111111', function() {
var adder = new Adder();
var a = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0];
var b = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1];
var out = adder.Adder16(a, b);
var result = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
assert.deepEqual(result, out);
});
it('adder of a = 0011110011000011 and b = 0000111111110000 should be out = 0100110010110011', function() {
var adder = new Adder();
var a = [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1];
var b = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0];
var out = adder.Adder16(a, b);
var result = [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1];
console.log(out);
assert.deepEqual(result, out);
});
it('adder of a = 0001001000110100 and b = 1001100001110110 should be out = 1010101010101010', function() {
var adder = new Adder();
var a = [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0];
var b = [1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0];
var out = adder.Adder16(a, b);
var result = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0];
assert.deepEqual(result, out);
});
});
The unit tests for the other gates and adders pass.

Using a variable to change the name of another variable in the code

I have tried to search the forum and google but do not really know what to ask for so apologies if this have been answered before.
var currentLevel = 2;
var Level = function(layout, ColRow) {
this.layout = layout;
this.ColRow = ColRow;};
var level1 = new Level ([ 1, 2, 1, 2, 2,
1, 1, 3, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1],
[5, 4]);
var level2 = new Level ([ 1, 2, 1, 2, 2,
1, 1, 3, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1],
[2, 2]);
var drawTrack = function () {
id = 0;
for (var col = 0; col < level1.ColRow[0]; col ++) {
tile[col] = [];
for (var row = 0; row < level1.ColRow[1]; row++) {
id = col + row*level1.ColRow[0];
tile[col][row] = {x:0, y:0, type:"asphalt"};
image (tiles[level1.layout[id]], col * 256, row * 256);
}
}
};
In the example above I would like to change level1 in the code at the bottom to something like level(currentLevel).ColRow[0].
Is that possible or is there any other best practice to do this?
*edit
The array solution solved my problem, thanks!
The suggested link I did find before but could not see how it could change the variable within the code? Maybe I missed something.
How about creating an array of levels?
var levels = [
new Level ([1, 2, 1, 2, 2,
1, 1, 3, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1],
[5, 4]),
new Level ([1, 2, 1, 2, 2,
1, 1, 3, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1],
[2, 2])
];
Then to access:
levels[currentLevel].ColRow;

Categories

Resources