Impulsing: #devtober Day 29

Today, I got the rest of the components converted over to KinematicBodies. I also fixed up the collision layers and masks. That wraps up that part of the recent changes.

I spent the rest of the time playing around with some levels. Nothing has come of it yet. What I find is that I have some ideas for level layout, which is interesting to look at, but which doesn’t have any puzzle elements to it. I’m hoping I’ll get better at this as I go along…

Here’s one, for example:

Sort of an upside-down butterfly. Fun to watch, but no real challenge. Yet.

Day 29: two days left.

Impulsing: #devtober Day 28

I worked a bit today on wrapping up the new physics-based dragging, and it’s working rather nicely. The main trick was to integrate the snapping into the movement, which initially didn’t work properly. It was snapping based on (at least one axis of) where the mouse was, not where the actual component was, which could be different if the component was blocked from following the mouse. It looked really odd (wrong) to see the component snap when the mouse was near a grid position far away.

The solution was to do two different move_and_slides. The first would try to move the component to the mouse. Then the component’s new position would be used to calculate a snapped position. Then the component would move_and_slide again to the snapped position. Either move_and_slide could end up blocked. The final snapped grid position would then be calculated from the ultimate world position of the component (either an actual grid coordinate or null if not within snapping distance of one).

There were a couple of minor things to fix (including changing the spherical collision shape to a cylindrical one, as snapping and setting into the sparse nodes would crash the code if there was already one there), but in the end, it seems to be working. Which makes me happy, especially given where I was a couple of days ago: on the verge of giving up and putting it off.

It’s hard to believe the month is almost up.

Day 28: four weeks in.

Impulsing: #devtober Day 27

I had some relatively amazing progress today. I had zero luck trying to move things myself in _physics_process. So I decided to play around a bit with Godot physics. Besides being fun, it worked out more or less how I wanted. It’s not perfect yet, but it’s a lot closer than it was before today.

I started out by changing the level boundaries from Areas to StaticBodies. Then I changed the Herbert from an Area to a KinematicBody. This caused a few things to break, but only because I had set “collide_with_bodies” to false in my raycast in a couple of places. Once I fixed that, I was happy to see that everything still worked the way it had before. Still no collisions (sadly), but my code generally worked despite it being a different type.

My first step at getting collisions working was to move the node in _physics_process, by simply setting the new translation as I had before. That didn’t work. So I tried reading up on move_and_slide and move_and_collide.

Both of them take a directional vector instead of a new position. So I tried simply taking the vector between the current position and where I wanted it to be. When I tried move_and_collide, it worked – except when it touched something. Then it started moving reeeeaaallllyy slowly. That’s because, I assume, move_and_collide stops the motion when it touches something.

That wasn’t going to work.

I tried move_and_slide next, since it sounded more like what I wanted, and it sort of did work, but it was slower in general. After some more reading and thinking, I decided to simply try multiplying the delta vector, and suddenly things started working much better. I’m not sure what the difference is (the docs mention taking delta into account or not), but I don’t really want there to be too much slop anyway. I just want it to meet the mouse position.

One interesting side effect is that the component with the cylinder collision object worked as I wanted, but the one with spherical collision object allowed the dragged component to slip up and over it. Fun to watch, but not what I want. I should be able to change the spherical shape to a cylinder one to solve it. Seeing this behavior though means that if I ever get into physics full time in a game, it’s going to be a lot of fun. (Maybe I can find a use for the “up and over” behavior.)

There is some quirkiness to work out, and I still have to re-enable the grid setting code (which wants to snap the position – that could be a lot of “fun”), but it’s an incredible breakthrough for me, and I’m happy to have learned something new today as well as move it closer to what I have been wanting.

Day 27: A glimpse of heaven.

Impulsing: #devtober Day 26

Not much today, but I did experiment a bit with moving a dragged object during the _physics_process. It worked, but it had a slightly different feel to it. It probably wouldn’t be bad, but it’s interesting that a delay of maybe a frame makes a cognitive difference.

More than that, I realized that my planned approach wasn’t going to work. A dragged object isn’t a single point moving to a single point. It’s a rectangle moving to a rectangle. You can’t do a single raycast. You need to work out the progress for the entire object.

I may have to put this on the back burner for now. It’s not critical, and I thought it might be a relatively straightforward win. It doesn’t look like it’s going to be, and there are more important things to get resolved and working.

Impulsing: #devtober Day 25

Sometimes it helps to step back and step away for a while. It can be tempting to keep at it, to just keep pushing. Work ethic… Just push through… But sometimes, giving yourself a break, even for a while, can give your brain a chance to work in the background.

I started out this morning playing around with Godot areas, looking to see how I could determine the bounds for a collision. The player can move items around, but it’s important they not be able to move them just anywhere. In particular, we don’t want the pieces to leave whatever is the main area for a level. I also want to have a puzzle mechanic where components can be limited to certain parts of the level or forced to move along certain paths. It’s not something I have worried about so far (apart from overlapping components) because I just don’t do goofy things. But ultimately, players will probably be trying just about anything, and it won’t be considered goofy at all.

My plan was to check for overlapping areas as the component moves. If the component being dragged impacts a boundary or otherwise solid area, it should not be allowed to pass through. This something that is normally handled in Godot with physics, but I’m not using physics. I would need to determine how a component can move and keep it from moving where it’s not supposed to. I even set up a new unit test to begin working it through.

Then I went out in the garden and did some other work, including building a planter box (really a planter “U” since it butts up against a brick wall).

Later, when pondering things a bit more, I realized that my approach has some issues. It would only really work if the player doesn’t move a component too quickly. If they do, they could – in theory – manage to get a component through a wall and to the other side without having a collision be detected. Not likely, but possible. And if you get enough people hitting something, the possible happens.

What came to me instead is the thought that as I’m moving a component, I have its old position and new one. If I can do a raycast, I can see if there is anything between those two positions. And then go from there to force the component to not pass through if there is. It’s more about travel than instantaneous position.

This caused me to shift gears, especially since the raycast functions are supposed to happen during the “process physics” phase. This means I’ll probably need to capture the mouse position, remember it for the next physics phase, and then have that code update the component as it can. At least that’s the theory.

Unless some more ideas occur to me between now and then. Maybe I’ll run into a wall. Then I’d have to see the best way to proceed, to get around it. Maybe I can just go over.

Day 25: Avoiding acting too soon.

Impulsing: #devtober Day 24

Today was one of those days.

After having some success the past couple of days, I hit a bit of a wall. When it comes to writing code or making something work behaviorally, I’m right there. When it comes to how things should look, I’m less so. I keep hoping something will coalesce, come together in a scheme. But perhaps it doesn’t work that way. Perhaps you have to actually make it happen. It ended up just being frustrating, almost to the point of wondering if you can even do it in the end.

I spent some time looking at 3D tile sets, many of which were nice.

I tried a couple of things in the game itself, including some block CG meshes, a stab at hexagonal tiles (won’t work for numerous reasons) and even just having a straight up texture behind the level.

Looks nice, but I’m not sure if it’s what I want. I’m not really interested in having either the same texture behind everything or just random ones not tied to some sort of purpose. But I don’t know what the purpose is yet.

Hexagonal tiles pose some interesting problems. First, you have to be really careful to make sure they meet up properly, which involves some mathematics that may not end up precise. Whereas rectangular tiles are really straightforward. The main problem with hex tiles, though, is UV mapping. The default mapping of a texture is… well, let’s just say it’s interesting. And unusable. And I haven’t worked out either how I’d want it to be or how to do what I don’t know yet. Overall, it adds complication with no perceivable benefit.

The game graph is on a hex grid, but there is absolutely no reason that the environment needs to be as well. And keeping them separate that way (in terms of different methodologies) helps to reinforce how unnatural the game’s “machine” is.

I had planned on exploring restricting node dragging, but I didn’t get to that experimentation. I did go through the 2D game and document all the levels I have so far, because those are the sort of “training” levels so far, and it will be important to have those, but also to have them organized properly. At least now I know what I’m starting with.

Day 24: time to sleep, perhaps to dream. Aye, there’s the rub. Where’s your muse when you need one?

Impulsing: #devtober Day 23

With the extension of the sparse nodes yesterday to allow a much larger working space, I set out to try recreating one of the more extensive levels today. For the most part, it worked nicely, but it did expose some things I needed to fix.

Fortunately, they were small.

First, I remembered (when it happened) that an item selected from the editor palette was being dropped near 0, 0 in the level – no matter where you were looking at the time. That obviously is not desirable, and I was able to fix it fairly quickly.

Another issue is that the Soojin node wasn’t serializing its “locked” property. Again, it didn’t take long to fix.

Both of those were nice in that the system more or less worked, and where it didn’t, I had all I need at my fingertips to make it work. It’s really satisfying when you have built a system enough that it eventually starts to make your life easier. You put in the work, and it pays off at some point.

There was another issue, but it’s not something affecting the level design at the moment. I did try it out, and it failed at first and then did something weird. The case was where you save a level when you’re not at camera position 0, 0. It does serialize the values, but there is no code positioning the camera on load. Then when I went to move, it whipped me off to where it should have been. That should be an easy enough fix, but I haven’t done it yet. A new card for the Trello board perhaps.

The new level shows up a glaring problem, though: I have no idea what I want these things to look like. And some of the nodes are really dark, even when on a bright background:

On a darker background (where the sidewalk ends), it’s even worse:

So I need to work out what these will look like, as that will determine what the nodes will look like. Or I’ll need to good layouts that work with the existing nodes, possibly with colors tweaked.

Still, exciting to be able to bring the level together and see it work. Progress is being made. If only I had more of an artistic vision for this.

(For contrast – and for fun – here’s what the 2D version looked like:

Perhaps even something simple like that could work.)

Day 23 – Friday before a Saturday!

Impulsing: #devtober Day 22

I decided today to take a stab at making the sparse nodes truly sparse. And I had a bit of inspiration about how to do it that didn’t seem too onerous (using a simple dictionary with key of x combined with z). I did some reading about performance, and it didn’t sound too bad. The code ended up being fairly easy as well, after I got past an initial issue where, despite looking like integers (and even printing as such), the calculated indices weren’t, and they subtly didn’t equate. Quite frustrating until I threw an “int” cast around the index calculation, and things became sane again.

The idea is that all levels will have the same virtual space, which more or less defines the coordinates, but only the points used get recorded. Quite sparse. I just have to pick a good max size that will work with all levels. (Although… since the dimensions are stored, they could be made to vary per level without breaking old levels.)

Sometimes I wonder if I’m doing this to avoid working on levels. But actually, this stuff needs to be worked out now. In fact, I’m going to have to recreate the (few) levels I have so far, as the format has changed. I wouldn’t want to have to migrate a lot of them.

Once that is all in place, I’ll be ready to start recreating some of the more expansive levels from the 2D game.

Progress on day 22.

Impulsing: #devtober Day 21

It all came together today, which was nice. At least, the part I have been working on did. So I can now edit a level’s “space” (the number of steps you can scroll in any direction). And rather than inputting numbers, it uses a more visually intuitive way, which I’m happy about. It works nicely. I might still show the values at some point, if that makes sense, but for now it doesn’t seem to need it.

You can see the new controls in the following screen shot:

When you’re on the edge of the world in edit mode, you can click the “+” to add more space in that direction. Then the navigation arrow appears. When you’re not on an edge, you get the navigation arrow and, when in edit mode, you get a “-” button that makes the world space one smaller in that direction. The arrows update appropriately.

It works more spatially than, say, entering the bounds as numeric values.

The only niggle for me is the use of the “-” button when not one away from the edge of the world. If the world space is, say, three steps away, hitting the “-” will make it one smaller in that direction, but you won’t see any change (since you’re still not on the edge). The alternative, which might make more sense in the way it’s going to be used, is that the “-” simply removes all space in that direction. (Basically, why would you only want to delete only one in a direction if you’re not on the edge?) I’ll keep that in mind as I move forward as an option. Have to see how it all feels!

In the process of implementing the above, I created some new mechanisms that I’m happy about. A scene when loaded notifies the editor (if it exists). This is handy as things are quite stable at that point, so the game state will exist with loaded data.

The edit buttons are now in their own separate component. Nice and self contained.

Good stuff like that.

I had a thought last night when I was lying in bed “not sleeping” (which occurred when I should have been not “not sleeping” – or, as it’s known more positively, “sleeping”) about a new use for an existing potential component that I only had one use for before. I wasn’t going to bother with it, even though it seemed cool, as I could only think of one use, in one puzzle. But last night, I realized that the new Soojin component behavior opened the door to another use for this other component, which is really cool. Makes it worth implementing.

On a walk tonight, I had a small breakthrough in terms of how the “overworld” could be structured. I have been struggling with this for a while. I knew there would be puzzle levels, but how are they all hooked together? How do you get back to a level (something I wanted)? How are you constrained in the beginning and then set free once you get past the initial training levels? I don’t have all of that worked out, but I have the germ of an idea now, which is quite exciting.

Day 21: This game jam can party now!

Impulsing: #devtober Day 20

This was one of those days where you do a certain amount of work, and then it ends up not feeling like much. The goal was to get the buttons hooked up for adding and removing space from a level. In the end, I spent all my time getting the button signals set up only to realize they were in the wrong place (the main game controls scene instead of the editor scene).

I moved the buttons (easy enough) and the code (also easy enough), but then I found I had no way to trigger the updates. I then spent the rest of my time plumbing in a new signal to fire when the camera moves. That worked well in the level base scene itself.

The editor raised an interesting problem. It is a Godot “autoload” scene, which means it gets loaded once into the overall tree (outside any loaded level). But its “_ready” method is only called once, when it gets initially added at game startup. As such, I can’t hook the editor up to the game state at that point because there is none.

What I need is some sort of signal saying “level has been loaded”. I haven’t found something like that yet in Godot, which means I’ll probably end up doing it myself – which is annoying, as I have to sort of force it in certain places and hope I have caught them all.

I’ll keep looking. Maybe there is what I need. Otherwise, I know what I’ll be doing tomorrow…

Day 20. The month is flying by.