Migrating to from glMatrix 1 to glMatrix 2 - javascript

I haven't been able to update these functions from an old application using glMatrix 1.2 to glMatrix 2.7:
calculateNormal() {
mat4.identity(this.normalMatrix);
mat4.set(this.modelViewMatrix, this.normalMatrix);
mat4.inverse(this.normalMatrix);
mat4.transpose(this.normalMatrix);
}
And the following function of multiplying a matrix by a 4-component vector doesn't exist:
calculateOrientation() {
mat4.multiplyVec4(this.matrix, [1, 0, 0, 0], this.right);
mat4.multiplyVec4(this.matrix, [0, 1, 0, 0], this.up);
mat4.multiplyVec4(this.matrix, [0, 0, 1, 0], this.normal);
}

In common the normal matrix is 3*3 matrix (mat3).
But anyway, glMatrix is well documented and according to the documentation of mat4 and vec4, your code can be ported like this:
calculateNormal() {
this.normalMatrix = mat4.clone(this.modelViewMatrix);
mat4.invert(this.normalMatrix, this.normalMatrix);
mat4.transpose(this.normalMatrix, this.normalMatrix);
}
May be it is not necessary to create the vectors in the following, but I don't kow if the vectors are existing in your case:
calculateOrientation() {
this.right = vec4.create();
vec4.set( this.right, 1, 0, 0, 0 );
vec4.transformMat4( this.right, this.right, this.matrix );
this.up = vec4.create();
vec4.set( this.up, 0, 1, 0, 0 );
vec4.transformMat4( this.up, this.up, this.matrix );
this.normal = vec4.create();
vec4.set( this.normal, 0, 0, 1, 0 );
vec4.transformMat4( this.normal, this.normal, this.matrix );
}

Related

Javascript Multidimensional Array complete column getting set

I am trying to make a game in Javascript. The game board is intialized to a zero-filled 2-D array. However, when I am setting the value of a single point, the complete column is getting set with that value. I think this is some issue with the way I am initializing the Array.
Method 1
# initialization
gameState = Array(6).fill(Array(7).fill(0))
# later in the game
gameState[2][4] = 1
# results in complete 4th index column to be assigned the value 1, like so -
0: (7) [0, 0, 0, 0, 1, 0, 0]
1: (7) [0, 0, 0, 0, 1, 0, 0]
2: (7) [0, 0, 0, 0, 1, 0, 0]
3: (7) [0, 0, 0, 0, 1, 0, 0]
4: (7) [0, 0, 0, 0, 1, 0, 0]
5: (7) [0, 0, 0, 0, 1, 0, 0]
Method 2
# initialization
let gameState = [];
for (let i=0; i<MAX_ROWS; i++) {
let row = []
for (let j=0; j<MAX_COLUMNS; j++) {
row.push(0)
}
gameState.push(row);
}
# again similar assignment
gameState[2][4] = 1
# results in correct state of the array
0: (7) [0, 0, 0, 0, 0, 0, 0]
1: (7) [0, 0, 0, 0, 0, 0, 0]
2: (7) [0, 0, 0, 0, 1, 0, 0]
3: (7) [0, 0, 0, 0, 0, 0, 0]
4: (7) [0, 0, 0, 0, 0, 0, 0]
5: (7) [0, 0, 0, 0, 0, 0, 0]
Can someone please explain what I am doing wrong here?
Your problem is pretty simple.
Array(6).fill(Array(7).fill(0))
Let's explain what this does.
Array(6)
creates a holey array with space for 6 items.
.fill(...)
will fill up these 6 holes with what ever you put in as argument.
Now comes the issue..
In Javascript, the arguments are evaluated before the execution of the function is run.
This means (in this exact case where .fill(...) is only ran once) your code is exactly the same as:
const innerArray = [0,0,0,0,0,0,0];
gameState = Array(6).fill(innerArray);
This means it fills the outer array with exactly the same array instance 6 times.
What you want is to create separate arrays each time. Just do this instead:
gameState = [...Array(6)].map(() => [...Array(7)].map(() => 0))

Javascript : Phaser call a method inside another method class

I am facing a problem during my development in javascript with Phaser. I try to call a method inside a method of a class but I have an error.
Here is my class :
import Enemy from '../classes/Enemy';
import Turret from '../classes/Turret';
import Bullet from '../classes/Bullet';
class GameScene extends Phaser.Scene {
constructor() {
super({
key: 'GameScene'
});
}
preload()
{
this.load.image('turret', './www/assets/tour_simple.png');
}
drawGrid(graphics)
{
graphics.lineStyle(1, 0x0000ff, 0.8);
for(var i = 0; i < 8; i++)
{
graphics.moveTo(0, i * 64);
graphics.lineTo(640, i * 64);
}
for(var j = 0; j < 10; j++)
{
graphics.moveTo(j * 64, 0);
graphics.lineTo(j * 64, 512);
}
graphics.strokePath();
}
canPlaceTurret(i, j)
{
return this.map[i][j] === 0;
}
placeTurret(pointer)
{
var i = Math.floor(pointer.y/64);
var j = Math.floor(pointer.x/64);
if(this.canPlaceTurret(i, j)) {
var turret = this.turrets.get();
if (turret)
{
turret.setActive(true);
turret.setVisible(true);
turret.place(i, j);
}
}
}
damageEnemy(enemy, bullet)
{
// only if both enemy and bullet are alive
if (enemy.active === true && bullet.active === true) {
// we remove the bullet right away
bullet.setActive(false);
bullet.setVisible(false);
//todo mettre dans une classe constante
var BULLET_DAMAGE = 25;
// decrease the enemy hp with BULLET_DAMAGE
enemy.receiveDamage(BULLET_DAMAGE);
}
}
create() {
this.add.text(200, 230, 'good!', { fill: '#0f0' });
var graphics = this.add.graphics();
this.map = [[ 0,-1, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0,-1, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0,-1,-1,-1,-1,-1,-1,-1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0]];
//TODO creer une classe qui dessine le path
// the path for our enemies
// parameters are the start x and y of our path
this.path = this.add.path(96, -32);
this.path.lineTo(96, 164);
this.path.lineTo(480, 164);
this.path.lineTo(480, 544);
graphics.lineStyle(3, 0xffffff, 1);
// visualize the path
this.path.draw(graphics);
this.enemies = this.physics.add.group({ classType: Enemy, runChildUpdate: true });
this.nextEnemy = 0;
var graphics = this.add.graphics();
this.drawGrid(graphics);
this.turrets = this.add.group({ classType: Turret, runChildUpdate: true });
this.input.on('pointerdown', this.placeTurret);
this.bullets = this.physics.add.group({ classType: Bullet, runChildUpdate: true });
this.physics.add.overlap(this.enemies, this.bullets, this.damageEnemy);
}
update(time, delta) {
if (time > this.nextEnemy)
{
var enemy = this.enemies.get();
console.log(enemy);
if (enemy)
{
enemy.setActive(true);
enemy.setVisible(true);
// place the enemy at the start of the path
enemy.startOnPath();
this.nextEnemy = time + 2000;
}
}
}
}
export default GameScene;
And an error occurs during my game :
TypeError: this.canPlaceTurret is not a function
The error is from the placeTurret method where I call the canPlaceTurret method.
I have tried some things like adding an attribute to my class : self = this; and call my function with self.canPlaceTurret but there is always the problem. I think it is a scope problem but I don't know how to solve that.
Another important information : we are using Webpack
Thanks for reading :).
Try replacing:
this.input.on('pointerdown', this.placeTurret);
with:
this.input.on('pointerdown', pointer => this.placeTurret(pointer));
(slighthy edited following your comment below)
Basically, when you pass your method as a callback, it becomes a simple function reference. When that function is called later, this won't refer to the class instance you're expecting, because it's no longer called in the context of your class.
By using the fat arrow syntax, you create a specific callback instead, and explicitly tells it to call the method in the context of the current (as in, at the time said callback is defined) this.
Alternatively, you can also do:
this.input.on('pointerdown', this.placeTurret.bind(this));
Instead of creating a new anonymous function, this takes your method as a reference (like it was doing to begin with) but manually binds the current this to it.
Please refer to this post for a more detailed explanation.
Won't it work without using the this keyword at all in your placeTurret() method when calling the canPlaceTurret()?
placeTurret(pointer)
{
var i = Math.floor(pointer.y/64);
var j = Math.floor(pointer.x/64);
if(canPlaceTurret(i, j)) {
var turret = this.turrets.get();
if (turret)
{
turret.setActive(true);
turret.setVisible(true);
turret.place(i, j);
}
}
}

Get index on click with jquery

I am trying to develop a 2 player checkers game, for my college, but I am stuck at getting the index of the 2D array when I click on the piece.
I divided my HTML code in:
table - the game board
row - each row is the height of the array
cell - each cell is a piece and the width of the array
Then I setted a default array to start the game:
var board = [
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[2, 0, 2, 0, 2, 0, 2, 0],
[0, 2, 0, 2, 0, 2, 0, 2],
[2, 0, 2, 0, 2, 0, 2, 0],
];
Where the:
- 0 - empty cell
- 1 - Player 1 pieces
- 2 - Player 2 pieces
To get the position I am using this code
function getPosition() {
$('.row').on('click', function() {
console.log( $('.row').index(this) );
});
$('.cell').on('click', function() {
console.log( $('.cell').index(this) );
});
}
Get the height array position which should be between 0 and 7 are ok, but the cell from the row should be between 0 and 7 too, but using this I am getting from 0 to 63, using this parameters I have no idea how to start the next comparisons of the game.
Here is the code from codepen
http://codepen.io/michaelthompson/pen/jVdrav
In each instance you can simply use $(this).index() which will return the index within the element's siblings
But since clicking on a row always means clicking a cell you could combine them and do
$('.cell').on('click', function() {
var $cell = $(this),
columnIndex = $cell.index(),
rowIndex = $cell.parent().index();
});
What $('.cell').index(this) is doing is taking the whole collection of the class within the page and that's why you are getting 0-63

How to fill a one-dimensional array grid with various blocks

I have a grid stored in a one-dimensional array. The grid can be of variable size. I now have different blocks (2x2,2x3,2x4,3x3,3x4,3x5, 4x4 and so forth).
How do I fill the grid in now? It can have unused spaces left in the end but what is the fastest way here without looping through the array over and over trying out sizes?
For instance with this 5x5 grid.
var g1 = [
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
]
You could use a backtracking algorithm to solve this type of problem:
function process(var blockstate) {
if(gridIsFullOfBlocks(blockstate))
return true;
if(canPlaceBlock(blockstate)) {
blockstate = placeLargestBlock(blockstate);
return process(blockstate);
}
return false;
}
function fillBlocks(int size) {
var blockstate = new Array(size);
if(process(blockstate))
displayBlockstate(blockstate);
else
displayError(blockstate);
}

How to place values in a multidim array - like 6 queens on a chessboard - javascript

I have an array that looks like this
board = [
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0]
];
Is there any way, just by using 2 for loops, like this
for(var i = 0; i < 7; i++){
for(var j = 0; j < 7; j++){
//actions here
}
}
to place 6 values of 1, first value of 1 to replace the first 0 in the array and the next 5 to be placed using the same rules for placing a queen on a chessboard. The result should look like this
board = [
[1, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 1, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 1 ,0, 0, 0],
[0, 1, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 1, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 1, 0],
[0, 0, 0, 0, 0 ,0, 0, 0],
[0, 0, 0, 0, 0 ,0, 0, 0]
];
I'm new to javascript and I have no clue on how to start this. Could someone please give me some hints.
board[xCord][yCord] = ValueToInsert;
I may have misread your question, so here is some more info.
You can "push" another array into a 1d array.
myArr.push([]);
Then you push the value like this:
myArr[Xcord].push(YValue);
You need to make a function to check whether placing a queen on xy coordinates is valid. The function would check whether there is a queen in that row, column or diagonals. You can also make those three sub-functions of the main function.
Then, as you go through the loop, use that function for each field and if it returns true, place the queen. If false, move on.
Of course, there will be many solutions in the end, so you might want to keep/store all of them in an array.
Also, think of ways to optimize the algorithm: for example, if you set a queen in a row, there's no need to check any other fields in that row, etc.
And when you decide to really go advanced with your skills, try using recursive functions to generate the solutions.

Categories

Resources