Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Creating an Intro Dialogue Script

In last week’s report, I made it easier for me to playtest and improved the interface when in the house screen of The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

I since set the work on creating a scripting system to get the intro going.

Sprints 26: Pre-production and initialization

Planned and incomplete:

  • Create introduction script

I envisioned the introduction roughly as follows:

  1. Dialogue involving the player’s main character and their friends in the Explorer’s Club.
  2. Player puts together a party for 1st quest: go get snacks.
  3. Go to kitchen, have dialogue involving parents, who send party to basement.
  4. While in basement, discover secret room with a secret ladder that leads to the dungeon.

To start, I needed to change from hardcoded scripts to something a bit more general purpose.

I created a few data structures to hold the text, the id of the speaker so I knew which character to render along with the dialogue box, and a collection of menu options. Those menu options would have commands that would run when selected, with “Continue” setting the next script ID as the current script.

That part was easy.

The trickier part was allowing the scripts to handle variables. Since I want the player to be able to customize the names and looks of the Explorer’s Club members, I couldn’t hardcode their names.

So instead of “My name is Francis”, for example, the script text is “My name is {{friend[0].name}}.”

I don’t normally do a lot of text parsing, so I wasn’t familiar with what text parsing utilities I could leverage. My plan was to keep it simple, using std::string and find() and substr().

If I wanted to separate the script into words separated by spaces, those functions would be great, but it seemed my code was going to be more complicated when using the curly braces and brackets. Was there something else I could do?

So of course as soon as I asked in a C++ IRC channel for advice, I thought of regular expressions, and by the time someone responded, they just confirmed I was on the right track with that line of thought.

What was really annoyingly helpful was that someone fed a similar question into a generative AI, and it popped out some code that was more or less what I was trying to write. In the past I’ve seen people share links to FAQs or forum posts, but this was the first time someone asked an AI and gave me the generated response. My initial reaction was to hate this new development in IRC question-answering, but I was very impressed with the results. The regex string the AI generated to match with the curly braces gave me a quick shortcut, so at least I didn’t spend too much time trying to create that regex myself.

In case you are wondering, the regex is “\\{\\{([^}]+)\\}\\}” and you can read it as “get me everything between the {{ and }}”. My initial attempts were nowhere near that string, by the way.

I wrote code to parse out the variable name, the array index, and the property name.

Once I had all of those, I could then throw it at a growing if-else statement for various variables I want to support. So in this case, I would see “friend” and check which array index and which property, and then the code would use std::regex_replace() to substitute the appropriate text.

So “{{friend[0].name}}” would get replaced with the result of gameData.getFriend(0).name, which is “Francis” by default, and “{{friend[0].nickname}}” would use a different code branch to use gameData.getFriend(0).nickname instead.

Besides “{{friend[]}}” variables, I also added support for “{{currentLocationName}}”.

So now I have the ability to create the first part of the dialogue, with the main characters having an Explorer’s Club meeting. They are inducting a new member, and then someone suggests getting snacks.

The Dungeon Under My House - intro script

Oh, and now that I can show different people talking, I found it frustrating with this placeholder art to know WHO was talking, so I added a label that shows the character’s name.

Eventually I would like to create a “quest” system, so upon finishing this first part of the intro, you get a new quest, with an initial objective to go to the kitchen to ask your parents for snacks, and new objectives getting added to go to the basement.

But for now, I needed a way to start the second part of the intro. Going into the kitchen should start a dialogue with the parents.

So I started working on a trigger system. A trigger has criteria, such as the player being in a particular location. If the criteria is met, then the trigger’s commands should get processed.

I decided that triggers should be either active or inactive. This way, the game isn’t constantly checking all potential triggers in the game, and it will be easier to manage if I only have to worry about accidentally meeting criteria or debugging wrongly successful criteria on fewer triggers.

For now, I have the one criteria, which I can use to detect if the player has made their way to the kitchen. I still need to have a way to enable or disable triggers, process active triggers, and process a triggered trigger’s commands.

But that’s work for the coming week.

In the meantime, I have also been trying to create a prototype for the meaningful dialogue system I want to create. Instead of merely branching dialogue with “correct” or “incorrect” choices, I am toying with the idea of conversation threads based on topics. Threads can progress (instead of being static), can relate to other topics, and can be “loose” or “tied off.”

What if each time you talked to an entity in the dungeon, you could pick up where you left off in your conversation, rather than get a stock response each time? What if that entity is actually interested in you, and so it isn’t enough to simply read some text and dismiss it. You have to answer, and your answer matters. Being dismissive might be an option, but the consequence is that you are seen as dismissive. On the other hand, if you are enthusiastic or deceptive or get caught in a lie, there would be other appropriate consequences.

That’s what I’m going for, anyway. I know I’ll need to prototype this part and try to create something enjoyable and feasible. I anticipate needing a LOT of writing to make this work well, but I want the focus to be on the game play rather than the text.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Easier Playtesting and an Intro

In my previous report, I created an Android port with the intention of making it easier to hand someone a demo, then placed residents in the titular house of The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

I continued by making the ability for me and others to playtest a bit easier.

Sprints 25: Pre-production and initialization

Planned and complete:

  • Quit to main menu

Unplanned and complete:

  • Make house rooms into buttons

Unplanned and incomplete:

  • Create introduction script

One of the ways it would be easier to playtest the game is if I didn’t need to close it and restart it to try it from the beginning each time.

I added a way to quit to the main menu, which sounds simple, and mostly was, but part of the work involved thinking through the user interface a bit more. Up until now, the house view was basically a view of the room or house layout and some buttons on the side.

It’s still mostly the same, but I’m trying to anticipate what else I might want on the screen. For instance, the player’s party should be visible in some way. I also need room for buttons that might always be on the screen, and others that are contextual.

Which of course begs the question of what buttons I expect to need. I know I eventually want a button that lets the player see the map, and even though it hasn’t been implemented yet, I think the needs there are obvious. I also haven’t implemented dialogue/conversations yet, but in this case I don’t yet know what I want to provide the player.

So for now, I gave the background a color other than black, created a gear icon to represent “settings” and gave the settings modal the button to return to the main menu.

The Dungeon Under My House - UI work

The Dungeon Under My House - UI work

Next, I was tired of having the right side of the screen full of buttons representing each room in the house, so I created a button out of each room itself. It was fairly quick work.

Finally, I decided it was time to start talking.

That is, I’ve been thinking about how to design and implement the dialogue/conversation systems for a long time, but I need to start making something real. The current intro script has been nothing more than hardcoded menus, and I need to make it more general purpose so that more scripts can be more easily written.

As I’ve said before, my intention is not to merely create a simple dialogue tree like most games. If all I wanted was an NPC who repeats the same sentences until you choose the correct response option, it would be relatively simple and easy to implement. After all, my game Toytles: Leaf Raking (which, by the way, is on reverse sale this week, so feel free to check it out) features such dialogue, so I can always build on what I’ve already made.

Since The Dungeon Under My House will be a non-violent game, I wanted to have dialogue and interactions become more engaging and interesting to replace the otherwise compelling mechanics of hack and slash that is typically in a 1st person dungeon crawl. I don’t want to merely disguise hack and slash mechanics. I want conversations to be a completely different kind of game play.

Unfortunately, while I have a number of different ideas and directions to go in, there’s a lot of unknowns still.

For instance, should there be random encounters? It’s typical for this kind of game, and while it might be challenging to ensure these encounters are interesting and varied, it might make the dungeon feel more populated.

Alternatively, what if the encounters are with entities that you can see beforehand, that take up space in the dungeon? Then the player can choose when and where to engage with an entity, and my own work to write dialogue is limited to the characters I purposefully created.

I’m leaning heavily towards the latter, partly because I want conversations to be meaningful and impactful. If you talk to an entity who sticks around, you can build a relationship, whereas having random encounters results in a lot of interactions with strangers you never see again and won’t impact your life much.

I’m envisioning giving the player options to speak with a particular type of tone, to have different intents with messaging such as amusing or scaring or inspiring, to brush off, to merely listen intently, and to do any number of the kinds of things people actually do when they interact with others. I want NPCs to have memories of how they were treated, to have goals that dictate how they treat the player’s party members and others, and ways to influence and be influenced.

For now, though, an intro script will likely look much more like a typical dialogue tree, introducing the player to the game world and getting them to their first goal as quickly as possible.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Games Marketing/Business

itch.io Summer Sale: Pay 50% MORE for Toytles: Leaf Raking!

itch.io is a very indie-friendly platform for game developers, writers, musicians, and artists in general, and they are having a summer sale.

And I decided to participate with another reverse sale.

You can pay 50% more than usual for Toytles: Leaf Raking, my leaf-raking business simulation game about responsibility and strategic thinking.

Toytles: Leaf Raking

I think the game’s original price is more than generous, and a temporary increase still puts it under the cost for a movie ticket or a monthly subscription to a streaming service.

If you want to get Toytles: Leaf Raking for Windows, Mac, and Linux, for the next week you get to support me even more by paying a bit extra.

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Little People in the House

In last week’s report, I finished working on doors (for now) and got ladders into The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

My intention for the next week was to make sure someone else can play the game, as it was a goal of mine for the quarter.

Sprints 24: Pre-production and initialization

Planned and complete:

  • Create Android version

Unplanned and complete:

  • Place family and friends in house

Unplanned and incomplete:

  • Quit to main menu

Creating the Android version was a lot more straightforward than I anticipated, mainly because I have the build scripts and everything I need.

All I had to do was create an app icon.

The Dungeon Under My House - App icon

It’s a temporary app icon, as eventually I want to get better, more permanent art into the game anyway, but I am wondering if there is a great icon for this game that isn’t a hallway or a door or the ladder.

Running the game on my Android phone, I found that the performance in the dungeon was not great. On the one hand, it worked. I could actually move about in the dungeon and my phone didn’t explode or burn up. But movement was a lot less smooth compared to my desktop.

I know my code wasn’t optimized, but I wonder if the issue is with the speed of the code or with the entire premise of raycasting as many columns as I have.

The final game might have a smaller viewport for the dungeon, which might make the game look a lot more blocky and pixellated than I want.

I didn’t end up sharing this version with anyone, but now I know that my game functions well enough on Android and can be easily built and shared going forward.

Next, I revisited the house. I wanted to get the Explorer’s Club and the parents into the game. While the dungeon is a 1st person view, the house is like a dollhouse seen from the side.

The Dungeon Under My House - friends and family in the house

The Dungeon Under My House - friends and family in the house

Eventually I want to replace this art, too, but I decided I needed to get the characters represented before I worry too much about how they look. So they have different faces over rectangle bodies, and they have different heights.

The Explorer’s Club is a group of kids who hunger for adventure in their sleepy suburban town, and I’m looking forward to exploring their world with them. I’ve written a bit of an intro to them, given them names and nicknames, and came up with the idea for their first quest: find some snacks.

By the end of the week, I found that I kept having to close the game and reopen it to start a new session so I can see my changes, and I decided that I needed to add a way to quit to the main menu from within the game, which required working on the in-game HUD a bit. Unfortunately, I ran out of time before I could do much, but after that task I’m looking forward to making it possible to interact with the Explorer’s Club in the coming week.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Doors, Doorways, and Ladders

I have been on a family trip for the last couple of weeks, but in my last sprint report I finally got the door to render properly and turned it into an obstacle that blocks your path in The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

I fleshed out the rest of the door implementations and then some in the time before and after my trip.

Sprints 22 & 23: Pre-production and initialization

Planned and complete:

  • Doors can be opened/closed

Unplanned and complete:

  • Put ladder back into dungeon

I realized that many similar games implement doors in a much simpler way. Instead of swinging open, they slide sideways into the wall, much like the doors in Star Trek.

Oh, well. I have doors that swing open and close, and now doors actually prevent movement through them.

The Dungeon Under My House - doors as obstacles

The code to handle doors as obstacles was a little messy. If you are facing a doorway, and the door is closed, it’s simple. You just can’t go through the doorway in either direction, either to leave the cell that the door is in or to enter it. If the door is open, then you can traverse between the two cells that were previously blocked from each other.

But if the door is open, the blocking behavior essentially gets turned to its side. A door on the north end of a cell that is opened is now blocking the west cell, and from the west cell you can’t enter the cell with the door in it. However, you should be able to enter the door’s cell from the east side.

But what happens if you are IN the cell that has a door, opened the door, and turned to the right? Should the door block you?

It was visible on the screen, and so it seemed intuitive that it would block you, but logically it made no sense.

I decided to not draw the door if it was too close to the camera, and it works out fine.

So now basic doors are more or less finished, and the game now has the ability to block or free access in a hallway by opening or closing a door.

At one point I had hardcoded a ladder to get back out of the dungeon and into the basement of the house, but that ladder disappeared as I worked on dungeon rendering.

So I decided to make it a full-fledged object in the game. I implemented it as a generic “portal”, with the idea that while doors allow you to move from one cell to another while providing a moving obstacle, portals teleport you to another location entirely.

So the ladder teleports you back to the house, but a different ladder or a stairway can take you to the next level of the dungeon.

The Dungeon Under My House - ladder

The Dungeon Under My House - ladder

The Dungeon Under My House - ladder

The Dungeon Under My House - ladder

I’m pleased with how the ladder looks from different angles, but clearly I need a new ceiling tile for locations with ladders to make it look like the ladder goes through somewhere.

For now, though, you can once again enter and exit the dungeon from the house.

I mentioned I was on a trip for a couple of weeks. I did not take my laptop, but I did want to spend some downtime thinking about and planning conversation systems. Since the game is meant to be non-violent, I need something to replace the typical hack & slash mechanics you would find in a 1st person dungeon crawler.

And I intend for that replacement to be as compelling and intricate. It won’t be enough to merely have a branching dialogue that let’s the player repeat conversations and try different options until they hit on the “correct” response.

That is, I want conversations to be meaningful and consequential.

But I am woefully ignorant of the state of the art in game dialogue and conversation design, and so I spent some time not only reading about the nature of dialogue and conversation but also trying to find examples of games that handle conversation differently.

I haven’t been terribly thorough, but so far it seems the state of the art is still just branching dialogue? With maybe some persistence of state to handle relationships or other consequences?

At least tabletop games have people performing improv.

My trip was good, but I hope I can dedicate a lot more time into figuring out how conversations should work.

But one of my goals for this quarter was to get a playable demo of my game into someone else’s hands, and to that end, making a mobile port is what I’ll focus on next.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Finally Drawing Doors Right

In last week’s report, I talked about the challenges I was facing with correctly rendering doors in The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

I finally made some breakthroughs this week.

Sprint 21: Pre-production and initialization

Planned and incomplete:

  • Doors can be opened/closed

After fighting with the math and code for so long, I am happy to say that the doors are visually correct now.

The Dungeon Under My House - door rendering

The fisheye effect I was seeing got eliminated as soon as I realized that the way I was trying to get the perpendicular distance was wrong. The current algorithm for rendering “things” such as a door (which can be effectively treated as 2D line segments) is to:

  1. Sort all things by distance from camera, so I can render them back to front.
  2. For each thing:
    1. Figure out the leftmost and right most columns to draw.
    2. For each column:
      1. Send out a ray from the camera to thing and figure out its intersection point, and use the relative distance along the line segment to determine which part of the source images to use when rendering.
      2. Then determine the distance from that point back to the camera plane (the perpendicular distance), which determines what height the thing should be drawn as and where vertically. Move onto the next column if this distance is greater than the distance to the nearest wall.
      3. Make various calculations to take into account the true height of the line based on whether part of it is cut off from being at the edges of the screen.
      4. Draw the column.

Part 2.ii was wrongly getting the perpendicular distance by trying to use the column to determine which position on the camera plane to shoot a ray out to the intersection point in Part 2.i. That ray was not perpendicular, unfortunately. Instead, I needed to project from the intersection point back to the camera plane. The position on the camera plane won’t have anything to do with the column I am currently drawing, which feels a bit counterintuitive to me, but after really digging deep and analyzing what was happening, it all made sense.

So the fisheye was removed, but there was still the phenomenon of the doors seemingly approaching the camera whenever the camera rotated between cardinal positions.

That is, if I was facing north, the doors all looked fine. And if I was facing east, the doors looked fine. But in between, the doors looked like they were separating from the walls/floors/ceilings and getting closer and then receding back.

After some more debugging and analyzing, I realized something: the way I was interpolating between the orientation vectors was linear.

My orientation vector was (0, -1) if I was facing north, and it was (1, 0) if I was facing east, but when I was facing north-east, it was (0.5, 0.5). The first two vectors are unit vectors, but the ones between them are shorter.

Shorter unit vectors for the orientation vector means that doors appear to get closer to the camera.

Once I changed from linearly interpolating between vectors to linearly interpolating between angles and deriving the orientation vector from that angle, suddenly not only did the doors seem to move in sync with the rest of the dungeon elements but the dungeon in general seems to render more correctly.

I will admit that I kind of liked how the walls and such looked when turning before I made this fix. It was a little off, but not so much that you might think there was something obviously wrong.

But it is amazing how there is one algorithm for the ceilings and floors, another for the walls, and a third of “things”, and they all use the orientation vector, but only one looked wrong if the orientation vector wasn’t a unit vector.

But now that doors render correctly, the next step was to make them solid. Up until now I could walk through them, which made it easy to debug the rendering code so I can see what they looked like on their reverse without having to go out of my way to walk around doors.

But now they block your way. I made a custom message for what you try to walk through a door.

The Dungeon Under My House - door rendering

Next was to ensure the menu changed to let you try to open a closed door.

The Dungeon Under My House - door rendering

And then I ran out of time for the week.

The remaining work on doors is to animate them opening when you click open, to allow you to close a door again, and to also let an open door block your path. That is, if you are facing north, and the hinge is on the left, a closed door blocks your path north, but an opened door blocks your path west.

Since doors can be part of a grid cell but can block movement both out of the grid cell and into it, my obstacle detection code feels a bit long. I need to check if you are trying to leave a grid cell through a door or if you are entering a grid cell through a door, and now I need to check if those doors are similarly blocking adjacent directions if they are opened.

But I am fairly pleased to finally be working on something more interesting than merely drawing the door.

At least, I hope I’m done with that effort.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Rendering Doors, Incorrectly

Last time, I reported how door rendering was trickier than anticipated for The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

The tricks just kept coming.

Sprints 19 & 20: Pre-production and initialization

Planned and incomplete:

  • Doors can be opened/closed

I’ll admit that I’m a bit frustrated. I’ve been working on rendering doors for way too long. Granted, in terms of actual hours, it is less than a week’s worth of full-time effort, but since I’m working on this project part-time, it has taken almost a month of effort according to the calendar on the wall.

Basically, I have doors rendering in the correct horizontal position, but vertically they seem to appear to be too close to the camera or too far, and while I am sure it has to do with a math error somewhere, I’m struggling to find that error.

When it came to drawing walls, I remember having a strange issue with how the walls were appearing until I figured out that I needed to truncate a value to an integer. Then suddenly a lot of things looked perfect.

And I suspect that there is something similar going on here.

The Dungeon Under My House - door rendering

I tinted the door and the entryway with a red color so it is easier to see how it doesn’t line up with the walls/floors, especially when seen at the edges of the view.

The Dungeon Under My House - door rendering

Even weirder is that if you turn to face a different direction, the doors seem to slide much closer to the camera before receding back to their only slightly wrong position.

The Dungeon Under My House - door rendering

Why can’t I just use the wall rendering code? That code is taking shortcuts, with the assumption that walls are aligned with grid edges. Calculating the distance a ray travels to a wall involves incrementally adding to a value until you know how far along the grid that ray has traveled.

In this case, a “thing” can be a line segment that does not align cleanly with the edges of a grid cell, and so calculating the distance is done more directly. If I calculate the distance to a door from the player’s position, I’ll get a fisheye effect. Weirdly, as my calculations take that into account by trying to find the perpendicular distance instead of the direct distance, I still get a fisheye effect, but it is less severe.

And it still doesn’t explain why the doors seem to move closer when turning, whether I am calculating the distance directly or not.

I’m sure I’ll figure it out, but it would be nice if I could do so more quickly.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Rendering Doors and Things

In last week’s report, I started work on designing and implementing doors for The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

I got doors to render quite soon after publishing that report, but there were a few tricky things happening that I needed to address.

Sprints 18: Pre-production and initialization

Planned and incomplete:

  • Doors can be opened/closed

The floors and ceilings render one way, the walls render another way, and then I have “things” like doors, which kinda need to act like walls, only they aren’t necessarily at grid edges the way walls are.

It took a little effort, but I was able to render doors in the arbitrary location I wanted them to be in.

The Dungeon Under My House - door rendering

The Dungeon Under My House - door rendering

The Dungeon Under My House - door rendering

The Dungeon Under My House - door rendering

Things need to render from back to front, and so they needed to pay attention to a depth buffer.

Then I needed to make sure that if the door was seen from an angle that it looked like it took space at an angle.

The Dungeon Under My House - door rendering

The Dungeon Under My House - door rendering

This involved interpolating a transform calculation between the hinge side of the door to the far side of the door.

I tried to make sure that the door was not taking up the entire height of the wall, since there is supposed to be a doorframe, and my math never quite worked out, but then I decided to just make the source image for the door itself with transparent pixels at the top to make it easier on me.

The Dungeon Under My House - door rendering

I had some weird glitches in which the door should be behind the player but still sometimes seemed to render in front of the player taking up the entire render area. I am sure there was some math I was not doing right, but at the moment my solution has been partially to hack in exceptions to when it should draw the door. I’m not happy with it, but sometimes it is easier to detect the problem than it is to figure out why the problem was happening.

One remaining challenge has been to fix the fisheye effect I was seeing when the door was drawn from an angle, an effect that was very obvious when the camera turned, since the walls don’t have the same effect.

I recognized that it was happening as a direct result of how I was interpolating the calculated distance between the hinge side and the far side of the door. I needed to use the perpendicular distance to the camera plane rather than the distance directly to the point source of the ray.

Drawing walls involves shooting rays from the leftmost column to the rightmost column, stepping through the grid cells until a wall is hit, then rendering that vertical slice of the wall.

When drawing doors, I can determine which column to start drawing from and which column to end drawing on, and then I interpolate both the source image vertical slices and the target vertical slice to draw it to, but I think I’ll need to modify how those rays are cast to similarly use the camera plane whereas at the moment I don’t.

Another thing I need to do is draw the door from the other side. The code technically could draw it in reverse, and in fact it did, but one of my hack/fixes prevents it now, so I will need to address it.

And of course, making the door functional will be key. There’s no point in having doors if they can’t be opened and closed. Ideally they should animate swinging open. And they should block movement through them in either orientation.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: How to Design a Door

Last week, I reported that I finally figured out what I was doing wrong and could render the floors and ceilings for The Dungeon Under My House, my second Freshly Squeezed Entertainment project.

So next up was getting doors into the game.

Sprints 17: Pre-production and initialization

Planned and incomplete:

  • Doors can be opened/closed

Sometime back, I remember reading about a game design exercise called The Door Problem. A quick search online helped me find Liz England’s The Door Problem from 2014, which talks about how a seemingly mundane part of a game can actually be surprisingly complex to design.

A few years ago, Vox did a piece on the challenges of designing doors in games, and months later The Verge did their own piece on how universal is the challenge of implementing mundane things, even in major games such as The Last of Us II.

And I was aware of these thoughts when I started last week’s efforts, and I still thought, “Ok, but it won’t be that bad.”

After all, my game isn’t trying to look realistic. I “just” want doors that can be opened or closed after a menu selection.

Hmm, doors have hinges, and they can be on either side, so I should have doors that can open to the right or to the left based on where the hinge should be.

Eventually, I do want non-player characters to also be able to open and close doors.

And when a door is open, I want it to act as a barrier, which might be a strategic move the player can make.

And naturally there should be a way to block a door from being opened or closed, perhaps by putting a large object on one side of it.

Wait, let’s step back. There were a lot of things I am trying to anticipate and worry about. Let’s go slow.

I’m not making a sci-fi game, so the doors can’t just swish open like in Star Trek. They should swing out.

I expect such a door to be in a frame, which means that it won’t take up the entirety of a wall.

But I wasn’t sure how detailed it needed to be simulated. Can I get away with a flat line, or should the door have a little depth so that if it is seen from the side it doesn’t look like it disappears?

Should it swing, or just instantly open or close?

I think it makes the most sense to assign doors to a grid cell. I suppose I could have had doors in arbitrary locations within a cell, but I decided that they should be attached to the four potential walls in a cell.

The Dungeon Under My House - door design notes

The Dungeon Under My House - door design notes

At some point I decided that I just needed to start getting something into the game. My first task was to get a closed door implemented.

So I mocked up a door and then a new wall type that has a door frame:

The Dungeon Under My House - door mock-up

The Dungeon Under My House - door frame mock-up

Since my game is using raycasting, a door introduces the technical challenge that the rays up until now have stopped when they hit something like a wall. After all, if there is a wall, you are going to see that wall, and and you would see nothing behind it, which would probably just be a wall that is farther away and thus would be occluded anyway.

If a door can be open or closed, and presumably animated in between, then I need to draw not just the door but also behind the door, especially since a door isn’t always a perfect rectangle shape. And even if there is no door, the door frame wall type means that I should see what’s drawn behind it, too.

With my raycasting code, the algorithm currently draws all floors, all ceilings, and then draws the walls.

To draw things like doors and other objects, such as windows, that might need to draw the world behind them, my plan is to sort all of these kinds of objects by distance from the player, then draw back to front.

Unfortunately I ran out of week before I finished this implementation, so I am hoping that I can get doors visible in the game early this coming week.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!

Categories
Game Design Game Development Geek / Technical

Freshly Squeezed Progress Report: Finally Rendering Floors and Ceilings

In my previous report, I had started working on raycasting the floor.

Sprints 15 & 16: Pre-production and initialization

Planned and complete:

  • Move player in dungeon view

Unplanned and complete:

  • Walls block movement

I was out of town last week and so I didn’t have a report for last Monday, but it would have just been me saying that I was running into trouble rendering floors correctly.

I was surprised because I was combing through my rendering code backwards and forwards, but I couldn’t find anything wrong, yet clearly something was wrong since the floors kept showing up as horizontal lines.

The Dungeon Under My House - in-dungeon floor rendering with horizontal lines

The Dungeon Under My House - in-dungeon floor rendering with horizontal lines

Basically, I suspected three things could potentially be wrong:

  • I was calculating the location of the source pixels incorrectly
  • I was putting the color of the source into the wrong target pixel buffer
  • I was updating the target image with the buffer incorrectly

I spent a lot of time looking at how SDL_Surface and its pixel formats could work.

I did find out that my source image was somehow the only one of my images that was loading as RGB and not RGBA, so I fixed that, and I found out that my original texture was not a perfect square of 1024×1024, so I fixed that, too.

I made sure that the pixel formats between the source and target textures were the same.

I tried to experiment with the pitch values to see when and if I should use them.

I tried to figure out if I was using the wrong byte size, or using the wrong values as an index through my pixel buffer when it should represent the bytes.

At the suggestion of the fantastically helpful Joel Davis, I tried smaller test images that were easier to work with. So instead of a 1024×1024 image that I was trying to map to the bottom half of my rendering target, I used a 16×16 test image and tried to map it to a different 16×16 target, then a 32×32 target.

The Dungeon Under My House - trying to copy pixels from a test image to an arbitrary image

So after a bunch of experiments and tests, I was able to determine that the code that updates my texture’s pixel buffer using the texture’s pitch is most likely fine.

And I was able to determine that my target pixel calculations were straightforward and easy. For a pixel buffer that is a one-dimensional array, the current target pixel index = current row * width of target + current column.

But I was seeing strangeness with my calculated source pixel index. It looked like only a subset of the source pixels were being checked.

And after rechecking and rechecking my rendering code, I found a line that wasn’t doing anything.

See, I recently changed a very basic data structure in my code base so that it was easier to work with.

GBLib::Point is represented as three floating point values: x, y, and z.

And if I wanted to make a new point that represented an offset of an existing point, I used to have to do something like this:

Point newPoint(oldPoint);
newPoint.moveBy(x, y, z);

Early in this project, I decided to finally change Point so that it worked more like this:

Point newPoint = oldPoint.moveBy(x, y, z);

So oldPoint stays the same, and moveBy() returns a new Point object with the values.

Joel Davis says that it is a confusing name, and I think I agree, because I completely missed a line of code that was doing nothing:

theFloor.moveBy(floorStep);

Basically, theFloor represented which part of the floor a ray was hitting, and this line was supposed to change it so that each column pointed at a different part. But it was not changing things at all, which explains why I was always getting horizontal lines rendered.

The code should have been:

theFloor = theFloor.moveBy(floorStep);

The Dungeon Under My House - in-dungeon floor rendering

The Dungeon Under My House - in-dungeon floor rendering

The Dungeon Under My House - in-dungeon floor rendering

The Dungeon Under My House - in-dungeon floor rendering

After banging my head against this for so long, I was worried I was going to need to give up on this raycasting experiment and either switch to a true 3D engine (and probably use Godot instead of trying to write my own from scratch) or give up on a 1st-person perspective altogether.

But I quickly got the ceiling rendering in, which required both flipping the perspective upside down so that it projected backwards instead of looking like a second floor AND making sure that it rotates correctly. I had a trippy experience in which the ceiling rotated the wrong way initially, and I really should write down how these bugs make cool effects because doing it on purpose might come in handy some day.

The Dungeon Under My House - in-dungeon floor and ceiling rendering

In the end, I spent much longer on this raycasting rendering code than I would have liked, and I now feel like I need to defend myself for continuing to use my own GBLib codebase instead of switching to something like Godot. If I’m going to be struggling with idiosyncratic code, why not something more established with better documentation and lots of other developers who can help each other?

And, yes, if I was starting out, or more specifically if I was giving advice to someone who was starting out, I would say without hesitation, “Learn Godot.” In fact, if you are someone I am giving advice to, go here: https://godotengine.org/

But why don’t I take my own advice? Because I’m not the target audience of that advice.

I’ve been working with my code base for a very long time. I’m excited about this raycasting code because it does not require more than merely USING my existing code, give or take the effort to access SDL2’s functionality that I need. I don’t need to implement an entire 3D engine, and if I needed a true 3D engine, I think I would in fact use an existing game engine rather than roll my own (unless…no…I mean, if I went for a simple, retro look…no…).

Anyway, call me stubborn or silly, but I’m sticking with GBLib.

Once I got walls, floors, and ceilings rendering correctly, my next task was to make sure that movement in the dungeon respected walls. That is, instead of allowing movement through walls as if they weren’t there, I needed to prevent movement if there was a wall.

If you recall from a previous update, I opted to represent the dungeon grid cells in a way that allows for more flexibility. Most tutorials have a cell as either empty or solid, which makes rendering and obstacle avoidance easy: if cellType == SOLID, then doSomething().

My code needed to determine that a wall was an obstacle only if the movement would go through that wall in particular. That is, if I am in a cell facing east and attempted to move forward into a target cell, an eastern wall of the original cell should prevent that movement, but a western wall in the original cell wouldn’t.

That seemed simple enough. But I also then tried to think ahead to what else counts as an obstacle. Walls are internal to a given cell, but what if there was a large object or entity blocking the way? Those kinds of obstacles would be in the target cell, since if they were in the original cell, the player wouldn’t be occupying it. So checking for obstacles would first check for walls preventing movement out of an origin cell and then check for things blocking the way in the target cell.

Before I thought too hard about how to make such an obstacle check elegant, I reminded myself that there are no objects or entities in the game yet, so I only checked for walls for now.

But I liked the idea of knowing what type of obstacle was preventing movement. I wanted to give the player feedback based on the type of obstacle, and so I added the first dialogue script in-game based on whether or not you tried to walk through a wall:

The Dungeon Under My House - dialogue when trying to walk into a wall

Which reminded me that I wanted to replace the art for the party members in the game.

Also, the dialogue/script code is very much hardcoded at the moment, and I eventually want to make it less so.

I now want to populate the dungeon with things, like doors, ladders/stairs, and items.

Thanks for reading!

Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!