I have a two-dimensional grid, in which all tiles are defined by two coordinates x and y. I'm storing the tiles in an array like this var tiles = [];. Each tile is an object with an x and y property:
Tile = {
x: ...,
y: ...
}
For drawing purposes (canvas) I want to find out which tiles are adjacent to each other. I could do that by looping through each element and check if it is adjacent. Since that would take n^n number of accesses I don't think this is the right way to do it. I think there would be a more efficient algorithm.
I also thought that maybe storing the data in a different way would help, but again, I wouldn't know how.
You have 2 ways to create a grid :
Using a 2 dimensional Array which must be the easier thing for a grid
Store adjacent Tile of a Tile in it with something like that :
var tile0 = {
x:0, y:1
}
var tile1 = {
x:1,y:1, tileLeft : tile0
}
It can be useful if you want to create Pentagonal or Hexagonal... grid, ofcourse create your grid automatically with a for loop.
EDIT
A two dimensional array is simply an Array of Array
var arr = new Array()
for(var i = 0 ; i < 10 ; i++){
arr[i] = new Array()
}
Now you can set value like in a grid, for example :
arr[0][2] = {x:2,y:2} //It's a bit useless since indexes can be use for x and y
In that case, i have 10 Array stored in one Array so :
arr[10][0]
Will return following error : Uncaught TypeError: Cannot set property '2' of undefined, because index of arr are only define between 0 and 9.
With your data construct I can't see a way to check for all adjacent tiles without accessing each tile.
The "tried and true" two dimensional grid data construct would be...a simple two dimensional array. Then you can access tiles directly by their coordinates.
Related
I've been trying to generate a two dimensional array of objects. Each object contains it's own internal position in the array in two variables called X and Y. When I instantiate the object, I can see through console logging that it's being instantiated with the proper X and Y values, this can also be validated through the fact that position in the array corresponds perfectly to those values.
However, when I log the final array after iterating through and saving each position in the array two an instance of the object, they have identical X coordinates, yet the Y coordinates are perfect.
let coordinates = Array(30).fill(Array(40)) // just creates an empty two dimensional array.
class Tile {
constructor(x,y){
this.x = x;
this.y = y;
}
}
for (let x = 0; x < coordinates.length; x++) {
for (let y = 0; y < coordinates[x].length; y++) {
console.log({x,y}) // logs {x: 0, y: 0} -> {x: 29, y:39}
coordinates[x][y] = new Tile(x,y)
}
}
console.log(coordinates) // logs two dimensional array with {x: 29, y:0} -> {x: 29, y:39}
I'm going mentally crazy trying to figure out why it does that. I've tried researching bindings, scope, objects instead of classes and I cannot find a way around it. I believe figuring this out will result in solving several of my problems, as I've run into other properties on the actual Tile class being randomly set despite not touching it at all. I am referring to creating a maze using deep traveling and recursion, and having each tile contain a property called "Visited" and setting it to true once it's been traversed once.
When doing that, I run into that my maze suddenly stops as it decides that every tile around it has been "visited" as they are all equal to true, yet I've never touched them.
Anything that you guys would have that would explain what I am running into would be helpful, it's no doubt something really simple and stupid.
Thank you in advance.
for (let y = 0; x < coordinates[x].length; y++) is your problem.
Your loop definitely cannot work if you are comparing to X for your Y loops, it won't ever get out.
I'm using R. Hill's Voronoi implementation to create polygons using an array of points:
sites=[{x:23, y:33}, {...}]
and also using an array with the canvas size:
box = {xl: 0, xr: 800, yt: 0, yb: 600}
Vornoi is generated with:
var diagram = voronoi.compute(sites, bbox);
The returned 'diagram' variable is a Javascript object with the following properties:
diagram.edges, diagram.cells, diagram.vertices
The object diagram.cells contains multiple cells each with 4 half-edges. Each half-edge has a lSite, rSite, va and vb objects containing x and y values.
However I am interested in obtaining an array of points (x,y) that form each polygon in the voronoi diagram and I have no idea how to do it.
Can anyone help please?
Found it: the method getStartpoint() can be applied to all the halfedges objects from within a cell object to obtain an array of points that form the polygon:
For example for cell 0:
var cellpoints=[];
for(e=0; e<diagram.cells[0].halfedges.length; e++){
cellpoints.push([diagram.cells[0].halfedges[e].getStartpoint().x, diagram.cells[0].halfedges[e].getStartpoint().y])
}
I want to store tiles (50x50 pixel rectangles, and later display them on canvas), but have no idea what data structure should I use.
I need to access it by x,y value, and also need to move them by changing the x,y value.
a single object would look like this:
tile = { x:1, y:2, color:1 }
I need hundreds of them.
I've considered simple array, however tiles[id].x is the only way to access them, so I need to know the ID first, before i can access them x.
2D array, seems better, since I can make tiles[y][x], but the values of the x,y coordinates where tiles are displayed are not necessarily the same numbers if the coordinates changed. aka: tile[1][2].x = 1.5 so, accessing the tile at x = 1.5 become tricky.
Objects in objects essentially the same problem as an array, since it requires to have a key so: tiles = { tile1:{x:1,y:2,color:1}, tile2:{x:3,y:4,color:2} } still have no way to access tiles at x1,y2 without knowing its under tile1 key.
I know I can use any of the above and loop trough them until I find the key, but is it really the only solution?
I've been reading tutorials today about javascript classes, and seems like its somewhat what I need, but haven't found a relevant example.
What would be the best way to store and access a tile's objects by x,y coordinate?
If you want O(1) (aka "very fast") lookup time the only option is to use a hashtable with a composed key of x andy:
const map = new Map;
for(const tile of tiles)
map.set(tile.x + "|" + tile.y, tile);
To get the tile at, e.g. x = 5, y = 6 you just do:
map.get(5 + "|" + 6)
When moving a tile however you also have to move it in the hashtable:
function moveTile(tile, toX, toY) {
map.delete(tile.x + "|" + tile.y);
tile.x = toX; tile.y = toY;
map.set(tile.x + "|" + tile.y, tile);
}
put all of your tiles in an array, and then use array.filter to get the tile(s) you want. Something like:
var tilesFilter = function(x,y) {
return this.x == 1 && this.y == 2;
}
var tiles = [...];
var myTile = tiles.filter(tilesFilter)[0];
I want to represent a board game in javascript and for that i need a bidimensional array.
I have different board sizes, so i need to initialize the array with the board size in the beginning. I am a java programmer so i know that in java when you want a bidimensional array you just do:
int board_size = 6;
String board = new String[board_size][board_size];
How can i achieve this with javascript? I have searched and found some ways of doing this, but all much less intuitive than this one.
It is not required like in Java or C#. The Javascript arrays grow dynamically, and they are optimized to work that way, so you don't have to set the size of your matrix dimensions upfront.
However, if you insist, you could do something like the following to pre-set the dimensions:
var board = [];
var board_size = 6;
for (var i = 0; i < board_size; i++) {
board[i] = new Array(board_size);
}
So to summarize you just have three options:
Initialization with a literal (like in #Geohut answer)
Initialization with a loop (like in my example)
Do not initialize upfront, but on-demand, closer to the code that access the dimensions.
With JavaScript it is not a static language like Java. It is dynamic. That means you can create the array without a need to preset the size of the array, but if you want you can procreate an array of the size you want.
var items = [[1,2],[3,4],[5,6]];
alert(items[0][0]); // 1
If you need to add to it just do
items.push([7,8]);
That will add the next element.
Code taken from old stack overflow post: How can I create a two dimensional array in JavaScript?
Edited to properly make I in items same as variable declaration.
Ive written a small game in JavaScript with the html5 canvas and am at the point of collision detection and getting rather confused.
I build my levels in tiled and then import the saved JSON file into the game.
In my level draw function i have a check to see if there are any layer properties and if the layer properties are collisions. If it does, that layer is returned and the loop carries on. When finished, the layer that was returned with collisions gets put through another loop so that the the tile values can be put into an array.
So in this array i have i have a series of arrays depending on how many rows of tiles there are in the layer, and these rows hold the data for that row for each tile.
What i would like to do is when the player x/y is in one of the tiles which doesn't equal 0, then collide.
How would i do this if all i have is the value that is in that tile space?
Here is a link to the live version of the game so you can see for yourself how the tiles are stored, i have put in some console.logs so you might want to use firebug or equivalent to look at that. To log in use
Username - guest
password - guest
TO clarify my question is: How do i create collisions between my player x/y and a tile value??
Thanks very much
UPDATE
Ok so i think im nearly there, my problem at the moment is how do i read the objects x and y out of the array and then check the collision, at the moment the collision detection on works with the last tile in the array (the bottom right of the screen), here is the code i implemented to go through the array:
this.check_coll = function(array,posX, posY){
var collided = false,
block_x,
block_y,
block_cx,
block_cy,
combined_hw = 32,
combined_hh = 32,
player_cx = posX+(32/2),
player_cy = posY+(32/2);
array.forEach(function(value,i){
//get obj x
block_x = value[1];
//get obj y
block_y = value[2];
block_cx = block_x+(32/2);
block_cy = block_y+(32/2);
collided = Math.abs(player_cx - block_cx)< combined_hw
&& Math.abs(player_cy - block_cy)< combined_hh;
});
return collided;
}
Any ideas guys??