Reputation: 7118
I'm currently developing a game with a top down map and units on it with Vue3. I have a Unit Store where I keep all my unit objects in an array and each unit is placed on the map based on its coordinates. I have a method in my store to retrieve all units on the same coordinates:
public getUnitsAt(coordinates: Coordinates): Array<Unit> {
return this.state.units.filter((unit) => unit.coordinates.x === coordinates.x && unit.coordinates.y === coordinates.y);
}
In most cases this is enough to display these units in a list. Now I introduced towns with their own town view component and I want to display the units that are "outside" of the town, but still on the same coordinates. So I use this:
const outsideUnits = computed(() => unitStore.getUnitsAt(town.coordinates));
So far so good, but now I want to be able to sort these outsideUnits, by telling a specific unit to move to the front. The problem is that this array is already a filtered array copy from the store. So I can probably sort this computed property, but as soon another unit is added to the store this gets recomputed and my order is lost. Any ideas how I can still have an up to date array of units, but be able to sort?
If a unit moves from a nearby field to the same field, it should automatically be in front.
Upvotes: 0
Views: 1178
Reputation: 35734
Based on your comment about memory being a minor concern, I would think of this problem/solution like a document store noSQL DB where the optimization is targeted toward reads, that means that more work is done up-front on the write (updating sometimes the same data at multiple places) because the idea is that the writes happen less frequently than the reads.
some things to keep in mind
getUnitsAt
, the result doesn't get cached, so every time you call it it will run the function.I would suggest using a computed value that stores all the relevant tiles' information in an object.
For example unitOrder['12_6']
would return [unit6, unit3, unit4]
, where 12_6
would be the x and y coordinates. (But would be better to abstract the index lookup through a method like posToKey = (x,y)=> [x,y].join('_')
)
The trick is to maintain the unit order, so anytime there is a change of position on any unit, the previous and last position need to be updated. Optimizations can be made where only tiles that have more than one unit are tracked, and the lookup is abstracted by a method that would handle missing position keys. It might also be worthwhile to limit use of Vue's reactivity, since it may add overhead that's not needed(YMMV); for example, if you're relying on a change, instead of making the unitOrder
reactive, you could do a reactive outsideUnitsChanged = ref(0)
variable that keep incrementing whenever there's a substantive change. This would prevent triggering multiple updates (when you remove unit from one position and again when you add it)
Hope that makes sense.
TSU, I'd keep the data structures non-reactive, and only utilize Vue as a way representing the the data.
Upvotes: 1