So, with this repository I want to make a clone of the Duck Hunt game, using a mouse pointer to control the target with. My aim is to be able to make use of mouse controls in C++ using SFML, and to make use of animations. For this I have chosen to instantiate the frames as a singleton, that all the animator class instances can then use. That way we'd only have to load the frame assets once, and use it as a flyweight. It was also good to learn more about how you might instantiate a singleton in C++... but then actually also abandoning that architectural approach.
A word on some struggles. This game can actually feel pretty complex to create. There are a lot of states to take into account, and missing strict conditions to ensure transitions from one to the next is easy, because sometimes they depend on time, sometimes on the behaviour of the player and sometimes on the behaviour of the ducks. Fly away and flown away states for instance, was tricky to distinguish between. Another tricky thing is displaying the ducks shot. You might have to sort and tally at the end of the round, because there's no intuitive way to display them concisely on the go.
Oeh! What a homecoming! I wanted to make this for 30 years but couldn't figure things out and/or couldn't be bothered. Now - yes, with the aid of ChatGPT as well - I saw it through. I actually really liked the production process and going all punk on graphical assets, coming up with silly sounds to play as well - like the dog barking as a nod to the original game. Felt good to finally do this.
So having finished the whole setup of the game, how do I look back on that process? It was actually very awesome to develop a game like this in such a relatively short period of time with ChatGPT guiding me through setting up all the classes and helping out on details of compiler issues, SFML implementations, tools to use, and when I got into syntax trouble. It really only took three weeks in total!
One thing I definitely might reconsider is how to draw graphics. Right now, I just draw them and there is no order except for the order in which they just occur. I actually took out the main player class from my pool of actors so that I could draw that animation at the right time. Whether or not that is the right way to treat the actor - @igorski claimed it is actually a part of the UI so its representation should be handled by the UI class - can be debated. But to have the drawing hierarchy depend on the order in which elements are handled seems a little naive. I should probably stage all of these drawing actions, use a queue like I do for the sounds. Actually, you can use a priority queue and enqueue all the graphical assets with a "z-index" for priority, then dequeue the whole thing once the scene is set up in priority-order.
On SFML and SDL2: I feel like I had to convert a lot between float, long, int, size_t, all sorts of casting going on, when I was using SFML in this case. Somehow SDL2 felt a little easier on the conversions. Plus, it seems Web Assembler doesn't play at all with SFML, so that's a pitty. Probably on next tryouts I'll stick to SDL2. I do wonder if I cast more than I needed to had I gotten some of the compatibility of the variable types right from the beginning. Probably drawing this all out does help before you dive into it.
I would probably also add some more tools to make things neater and more precise, like Clang-Tidy or Cppcheck. I'd do this early on, so that you kind of can keep up with the suggested changes, much like in the case of the IWYU tool. I'd also set up a Docker instance and run it with the ability to monitor the memory leaks. Clang-Tidy and Cppcheck prove tricky at times though, and annoyingly Cppcheck doesn't seem capable of applying the changes it suggests. I'd probably also set up a Docker image so I can monitor memory allocation and spot mem-leaks in runtime if they occur. I'll save it all for a next project.
I haven't bothered to put it all in the proper folders to build it and have it shippable, so you can run it from the command line (on a macOS at least:)
$ ./install-dependencies.sh # gets cmake, IWYU and the SFML stuff
$ ./build.sh # kicks CMake into gear and starts the app after build
- Refine mouse controls
- Add screens:
- Title screen
- Background
- Add double-buffer layer
- Add ducks
- Refactor game loop out to play module
- Add collision
- Add text module
- Add listener on red window button
- Refine gameplay lifecycle:
- Title screen state
- Begin round state
- Reset state
- Ready state
- Running state
- Shot state
- Fly away state
- Flew away state
- Round beat state
- Game over state
- Game beat state
- Finalize shot animations
- Make sure falling speed is independent of moving speed
- Add UI
- Add time between last duck shot / missed and final "you beat the round" message
- Maybe reorder READY and RESET states.
- Manage round configuration
- Display 'ducks shot / ducks left / ducks missed' properly in the UI
- Garbage collect deactivated agents
- Cut up steps in UI module
- Refactor out handlers
- Include tallying mechanism at the end of the round
- Display target in the UI
- Add score animation
- Add sounds
- Add left-facing variant of the flying duck animation
- Implement background / foreground distinctions
- Take the player out of the agents pool
- Adjust starting baseline for new duck spawning
- Figure out how to stop all or somes sound playback prematurely
- Substitute and expand sounds:
- For Title screen (music)
- For start round (music)
- For round won (music)
- For round lost (music)
- For game won (music)
- For shot
- For duck flying
- For duck hit
- For duck falling
- For duck fallen
- Substitute assets and expand animations:
- Background
- Duck animations
- Fix first duck animation (inner wing should be white)
- Title screen
- Bullet, crosshairs and duck symbols