On Saturday, 23 March 2024 at 22:37:06 UTC, Liam McGillivray wrote:
...a tick system would go hand-in-hand with making animations happen in a separate thread, but it sounds like you're talking about the same thread. Are you suggesting a fixed framerate?
I have done both ways. If you're new to programming, I think the single thread would be better since your game logic is fairly simple. Simply update your world, then draw everything then sleep. Steven Schveighoffer does a lot of entry-level games so hopefully he will respond if he disagrees. You can have a bool flag you set when an action happens that requires the win condition to be checked and then if that flag is set, check the win condition at the end of the loop, assuming only one player can achieve a win condition at a time.

This is during the Unit's constructor, where it gives the `Tile` object a reference to itself. What exactly is wrong with this? Can memory addresses change when a constructor completes? I assumed that objects come into existence at the beginning of the constructor function.

I think the idea is the object is not ready to use until the constructor is complete and if you leak a reference, someone else who doesn't know could use it and they might have expectations about it's state that are not upheld midway through the constructor. I used to do this a lot and never had a problem with it. In an application where you're the only developer and it's single threaded, it won't be a problem. It's just bad practice because on a team you want to be able to trust that a reference to an object is of a completely constructed object and you don't want to have to check it's constructor every time.
Anyway, I can change this by calling `Unit.setLocation` after creating a new `Unit` object.
That's a good plan


I suppose the current system for setting up objects from a `JSONValue` is messy because much of the data applies to the base `Tile` & `Unit` objects, but then some of it needs to be in `VisibleTile` & `VisibleUnit` because it has sprite information.
That's fine. I would move the code out because I only care about it when I'm working on loading from JSON, so it wouldn't be helpful to see it all the time when I'm working on game logic. The value comes in having less to see and think about at a time but it will work just the same (assuming you don't break it when you move it :). If you like it there, then leave it.
Do you really think it would be better if I removed `Unit.currentTile`, and just used `Unit.xlocation` & `Unit.ylocation` as parameters for `Map.getTile` instead?
Go with your gut. If you start having problems with them getting out of sync, then I would separate them. Most of my suggestions boil down to: if you have problems and the fix breaks something else and that fix breaks something else or it's just hard to understand, then my suggestion will probably help. If it ain't broke, don't fix it.

I have considered doing a rewrite of the rendering system, in which all the rendering, and possibly input during game are handled by a new `Renderer` object, which may have it's own array with all the units in it. This sounds a little like my idea of the `Renderer` object, in which the state of what's on screen would be updated by calling it's methods, but having a log of the UI wasn't what I had in mind.
I like the renderer idea. I would keep it in the same thread for now unless you really want to make a separate thread.

Before going with the current approach, I intended to have a module called `loadData` which would read JSON files and make objects out of them
I think you made the right call. A generic json file loader is overkill at this point. If you make a second game, make a generic and reusable json loader. I try to never make things generic unless I have multiple actually use cases that I can design against or if it's pretty obvious.

//Always set destroy to false when calling from the Unit destructor, to avoid an infinite > loop. I was just doing some work on the AI system, and I had a segfault every time the enemy was in reach to attack a unit. It turns out this was because the destructor was called. I replaced destroy(unit) with map.deleteUnit(unit), and it solved the problem. Nevermind. It turns out this was because the call to the Unit destructor was missing in Map.deleteUnit. The segfault happens whenever a unit is destroyed.
This is exactly the kind of problem circular references cause. You're not quite sure what makes the bug or when to consider it done, especially when there's multiple entry points into the cycle.

In this case, how should I handle safe destruction of units, given that there are multiple arrays that contain references to it?
Here are my options, in inverse preference order (neglecting the time it would take):
1. Keep it like you have it
2. Switch to the tick system. At the end of your updating the world phase, clean up and for each unit that has alive = false, remove it from all the things. 3. Move the combat logic out of the unit and either have receiveDamage return whether they are still alive or check their hitpoints after each attack. If they are dead, then clean them up there instead of in the unit. Make the change I suggested to set the occupant of the tile outside of the constructor. Do not save the faction on the unit.

It just occurred to me that this must be what you were suggesting here.
That's very similar to what I was suggesting. All you would have to do is track which tick you processed the event. When you add random numbers, you'd want to use a deterministic random number generator and save your seed. It's a great idea.

Reply via email to