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.