I hope to make these blog posts consistently from now, but for starters, a quick update to the upload schedule: I’m going to be doing one video per month, and blog posts in the weeks between those videos. I don’t want to post videos with little content in them (which is what happened with devlog #2). Thank you for the feedback and support on devlog #3! For #4, I’m trying a new format where I record as I develop, instead of creating the videos when I’m done with all of the content shown in the video.
From the time devlog #3 was released, I have been hard at work. I’ve adopted a new schedule, in which my days begin at 5am, and end at around 10:30pm — it has been an adjustment, but it’s been working well for me. I am mostly productive in the morning, and it follows that waking up early maximizes my productivity.
I have also adopted a “sprint” development schedule, a schedule popular in professional development. I have a rough idea of what needs to be completed by which months (in the grand scale of the project), and as those times approach, I break down those big ideas into individual tasks. In Notion, I assign the priority, due date, and point value for each task. Points refer to the amount of time it takes to complete a task, where one point is roughly equivalent to half of a work day (4 hours) or less.
Every two weeks, I plan what tasks will be completed in the following two weeks — this two-week period is referred to as a sprint. With the point system, I can take on tasks and have confidence that I will have time to finish those tasks. Then, once a sprint has been completed, any tasks that are leftover (if any) will be transferred over to the next sprint, and the process repeats.
This may seem like an excessive amount of planning for someone who is working alone, but I have always had trouble in deciding what to do next. In my previous projects (Crevis, a sandbox game), instead of starting the content for the game after I had completed the engine, I would keep going back to perfect systems — a classic case of over-engineering. Scope creep was also a big issue (the scope of the game gradually becoming bigger and bigger).
This new system of planning what tasks to work on tells me exactly what I have to do next, so there is no room for me to go back and revamp systems. When I want to add/revamp a feature, I don’t get to work on it in the middle of the sprint — I have to finish everything planned for that sprint first. Then, I would need to create a new task in Notion, and put that task in the backlog. Then, in the next sprint, I can decide if it will be worked on. It keeps me accountable, and it’s easy to check if I’m on-task or not. I plan to post these sprint boards in the Discord, but I would probably have to blur some stuff out if it were content-related (a note: I’m not really sure how to draw the line between showing too much and showing too little of the game).
Tile Saving Issues
Recently, I went on a vacation to Hawaii and brought my laptop to work on the game in the early mornings. I created a new tile set, and voila — the level tiles broke!
What’s happening here is that the newly created tile set and the one that should be used have swapped. GameMaker assigns all assets (including tile sets) an index at runtime. Crucially, these indices are volatile. but when I was creating the tile save system over a year ago, I neglected that fact. So, despite the indices remaining static for over a year with no problems, it inevitable that they would eventually change.
The solution that I have conceptualized is quite simple. I will have a simple JSON object with the names of the tilesets as the key, and the my own static index as the value. These will never change (unless I change them myself) and this file will grow automatically with any additional tilesets. You may be wondering — and reasonably so — why not just save the tileset as a string, and use
asset_get_index() to get the GameMaker index? This is because each layer in a level saves two grids: one that holds the tile set index of a cell, and the tile index of a cell, the distinction being that the tile index is the tile within the specified tile set. These grids are then saved as buffers for additional performance.
To make this work with strings, level files would be larger and deserializing the buffers would take longer (in theory). Another solution could be to restrict each layer to one tile set, but I don’t want to do that. I value having multiple tile sets on one layer, and the lack of this feature in the native room editor was very irritating.
There are definitely more optimal solutions to the problem I’m dealing with, most of which would involve rewriting my save system. But a crucial point is that it’s already good enough. It doesn’t need to be re-engineered, because it already works! This is the same problem I would always fall into in my previous projects — I would convince myself that I couldn’t build upon poorly designed systems, and that they undoubtedly needed to be redesigned. In my early projects, this may have been true, but it made every project an unfinished pipe dream. And that is something that Nesus will not be.
So, I will be proceeding with this solution, and in doing so, I will also have to write a converter script to convert levels in the old format to the new format.
Time for me to get to it! I’m not sure if anyone has read this far, and if nobody has, that’s perfectly fine — these posts are more of a development journal. Perhaps I’ll post later this week about basic in-level scripting (sort of) which is a feature that I’ve been very excited about.
Until next time!