Here’s this week’s progress report for new updates to Toytles: Leaf Raking, my family-friendly leaf-raking business simulation available for iPhones, iPads, and Android devices.
Learn how to get it at the Toytles: Leaf Raking page.
In my previous report, I once again lamented how little capacity I have as a very, very part-time indie game developer.
And yet, I still felt optimistic.
Last week’s sprint plan was:
- Make it clear from the map which neighbors are your clients, ex-clients, and prospects
This week I did 5.75 hours of game development. I had a few false starts, and in the end, I still don’t have the indicators in the game.
I started working on creating an animated sprite, which is basically just a regular sprite but with frames, where the frames have a length of time and an image that should show during that time.
Then I wondered if perhaps there were best practices or at least expected ways it should work, so I did a bit of research, and I remembered that CSS animations are a thing, too.
For a good part of the time, I was feeling fine. I designed and started to implement an animation system that works similarly to how the animation systems in CSS or Godot engine works. That is, if there is a property to change, I can setup “tracks” to change those properties over time. Position, scale, color, sprite image, etc, all of these can be changed independently and simultaneously.
And then I realized: my sprint goal is once again nowhere near done. I was spending a bunch of time creating a generic animation system when these indicators really just need to flip between a few frames and bob up and down.
So after a few hours (which as a reminder is over the course of half of the week) I stopped working on the generic animation player, and I went back to my animated sprite widget.
And now I’m at the point in which I am creating an animated sprite as an indicator if a neighbor is a client. That is, I am actually starting on the work that will actually get the sprint goals accomplished.
I can see a way to do all of the above in a hacky way. That is, I’m sure I could have quickly coded up what I needed to show indicators if I didn’t care about trying to ensure the code is supportable and maintainable in the future. And after three weeks of not getting the indicators into the game, it sure feels like I made the wrong choice.
Others might argue I made the wrong choice earlier by not using an existing game engine instead of writing all of the code myself.
But I need to remember that the last three weeks of amounted to a total of about 17 or 18 hours of work. That’s not a lot of time in the grand scheme of things, especially when those hours are broken up across entire days, making it difficult to keep focused.
And I also need to remember that I want to be able to support and maintain this project in the future.
One thing I’ve learned is that the game framework code library I’ve created and updated and modified over the last 10 years still has some inconsistencies, and so working to add animation on top of the existing sprite and widget code was more confusing than it needed to be.
For example, widgets are objects that I create once and then reuse across update/draw cycles. Widgets can not only be drawn, but they can also be made interactive/clickable.
IWidget is the base class that not only provides the interface for widgets but also handles drawing child widgets. That is, any derived widget automatically gets the ability to add and render child widgets, and all a derived widget needs to provide is a way to draw itself.
IWidget provides a setOnClick() function which allows you to specify the rectangle in which it should detect a click (usually the size of the widget) as well as what option/command should occur when a click occurs.
How does it know that you clicked it? Widgets have an update() function that takes the input (mouse button presses and mouse location). I have a ButtonControl class which IWidget takes advantage of.
What does this have to do with animation? Well, how do I make sure an animated sprite changes over time? I’d use a different update() function that takes a deltaTime in milliseconds.
So throughout GBLib, which is what I call my library of general code for all of my GBGames projects, I have some update() functions that handle input and some update() functions that handle the change in time. And IWidget provides an update() that handles input, and now that I have an AnimatedWidget that derives from IWidget, I also want an update() that handles the change in time.
And while most programming languages let me have two separate update() functions that take two different sets of arguments, I think it would be confusing and is just one example of the kind of lack of cohesive design to GBLib that makes me want to sit down and figure out what I actually want this code to look like.
But it doesn’t mean I’m going to do it just yet. I’m focusing on getting the indicators in with an AnimatedWidget, and if it means it is a bit awkward, then it is a bit awkward. I can fix awkward later, especially since I have an automated test suite to support the work.
And I can eventually make a more generic animation system. The optimistic developer in me was convinced I only needed a few more hours to finish the work I started the week on.
But the producer/delivery lead in me also recognized that after a few weeks, it would be nice if I had something to show for it. I thought I was working on a compromise between quick & dirty and generic & clean, but I realized I was still doing too much for future needs.
So I’m doing the simpler work now in order to get a new release out, and I can worry about generalizing the code when I have something that needs generalizing.
Thanks for reading!
Want to learn when I release updates to Toytles: Leaf Raking or about future games I am creating? Sign up for the GBGames Curiosities newsletter, and get the 24-page, full color PDF of the Toytles: Leaf Raking Player’s Guide for free!
One reply on “Toytles: Leaf Raking Progress Report – Animation False Starts”
[…] Toytles: Leaf Raking Progress Report – Animation False Starts […]