digitalmars.D.learn - Optimization when using a 2-dimensional array of objects
- Liam McGillivray (27/27) Mar 21 In the [game I am currently
- monkyyy (29/34) Mar 22 ```d
- Liam McGillivray (22/48) Mar 22 Well, none of the stuff you wrote closely resembles the code that
In the [game I am currently making](https://github.com/LiamM32/Open_Emblem/blob/master/oe-r ylib/source/app.d), I have a `Map` class (actually a combination of an interface & class template, but I'll call it a "class" for simplicity), in which there will probably be only one instance running at a time. In that map class is a 2-dimensional dynamic array of `Tile` objects called `grid`. What these `Tile` objects represent are like squares on a chessboard. Their placement in `grid` represents their location on the map. Whenever a function in the game has to pass a location on the map, I have a dilemma between passing a reference to the tile object, and passing it's grid coordinates through `struct Vector2i {int x; int y;}`. The functions that receive this information sometimes must access the Tile's variables to know it's properties, but may also need to know it's location so that it can find neighbouring tiles. The `Unit` class also has a 2-dimensional dynamic array of entities holding information on the unit's distance from that tile, and whether it can reach it during this turn. Is one option more efficient than the other? I already have the location of each tile cached as a pair of variables within each tile. To get a location from a Tile object, a call would be made to the member function `Vector2i location()`. To get a tile object from it's coordinates, a member function of `Map` `Tile getTile(Vector2i location)` would be called. Should I stick to one over the other? Is there a memory allocation technique that would make each tile's location in `grid` inferrable based on it's memory address? It would be nice if the two were interchangeable, so that I wouldn't have this dilemma. Not knowing which option is best has lead to a little bit of messy syntax. Right now I have multiple versions of the functions `getReachable` & `getAttackable` in the [`Unit`](https://github.com/LiamM32/Open_Emblem/blob/master/source/unit.d) class which return a different type, because I'm not sure which is better.
Mar 21
On Friday, 22 March 2024 at 02:19:07 UTC, Liam McGillivray wrote:In the [game I am currently making](https://github.com/LiamM32/Open_Emblem/blob/master/oe-r ylib/source/app.d), I have a `Map` class (actually a combination of an interface & class template, but I'll call it a "class" for simplicity), in which there will probably be only one instance running at a time. In that map class is a 2-dimensional dynamic array of `Tile` objects called `grid`. What these `Tile` objects represent are like squares on a chessboard. Their placement in `grid` represents their location on the map.```d enum tile{wall,field....} bool ispassable(tile t)=>... alias grid_=tile[maxhieght][maxwidth]; grid_ grid; ``` your not simplifying anything here with all them oo termsIs one option more efficient than the other?You should probaly do the lazyest thing, factor out your "ispassable" logic, like what your walking n of 3, n of 8, n of 15? so long as you dont do something insane it will be fast on a modern computer; allocating several dynamic array that are the size of your game world every frame could easily be not very sane. and if you really really wanted to care, you could precompute the "connected compoints" by flood filling across passable tiles with a "color" of 0, then finding an empty cell, flood filling with 1, etc.; and when you draw the overlay for where you can move you can do a heuristic check for a) they are in the same component, and b) the manhattan distances before c) doing a greedy checkIs there a memory allocation technique that would make each tile's location in grid inferrable based on it's memory address?Yes its called an array theres some details you need to know and you need to cast pointers; just try some trial and error with code like: ```d int[10] foo; &foo.print; &foo[1].print; (&foo[7]-&foo[0]).print; ``` with whatever casts you need to make it just work
Mar 22
On Friday, 22 March 2024 at 07:34:33 UTC, monkyyy wrote:Well, none of the stuff you wrote closely resembles the code that I have. There are 3 reasons why I put this kind of effort into optimization: - I'm obsessive. - For the learning experience. - Because things may get more demanding when I get further with the enemy AI system. One possibility is to have it make multiple copies of all the game objects which it will use to look ahead to the next 1-2 turns.Is one option more efficient than the other?You should probaly do the lazyest thing, factor out your "ispassable" logic, like what your walking n of 3, n of 8, n of 15? so long as you dont do something insane it will be fast on a modern computer; allocating several dynamic array that are the size of your game world every frame could easily be not very sane.and if you really really wanted to care, you could precompute the "connected compoints" by flood filling across passable tiles with a "color" of 0, then finding an empty cell, flood filling with 1, etc.; and when you draw the overlay for where you can move you can do a heuristic check for a) they are in the same component, and b) the manhattan distances before c) doing a greedy checkI barely understand any of this, though I know what a Manhattan distance is. Is this about measuring distances? Manhattan distances appear to be how distances are determined in Fire Emblem, though I'm using a slightly more intensive `abs(x) + abs(y) + max(abs(x) + abs(y))` whenever I need a quick estimate of distance that doesn't account for obstructions.But objects are reference by default. This means that they don't really 'live' in the array I put them in, doesn't it? Wouldn't the the array entries just be references on the same level as any other?Is there a memory allocation technique that would make each tile's location in grid inferrable based on it's memory address?Yes its called an array theres some details you need to know and you need to cast pointers; just try some trial and error with code like:```d int[10] foo; &foo.print; &foo[1].print; (&foo[7]-&foo[0]).print; ```This appears to be a different programming language. It isn't D.
Mar 22