INTRODUCTION

Already read this? Click here to jump to the latest update!

Im working on a game.

The Boring Basics Preamble (as of 12/26/23)
Figured it would be fun (and wise) to log my progress my learning as I slowly build a piece of a world that has been festering in the crevices of my imagination for years now. In general, I'm going to avoid talking about the story too much to avoid spoilers, and also since I'm still writing it as I work on the game itself. Therefore this blog is mainly going to be about me learning the ins and outs of creating a game from the ground up. This is my first time using Godot and my first time making a game in general, sans the shit I made in Scratch when I was 12. As I'm completely new to all this, I imagine I'm going to also make a lot of mistakes or stupid design decisions, so;
  1. Don't take this as an introduction to Godot or anything, I have no idea what the hell im doing

  2. If you do know what you're doing and are screaming at me through your screen, please feel free to reach out and call me a moron before I continue with a bad idea :)
      (my discord is @omnidisplay)

Without giving too much away to the story I'll try to establish the general theme, styling, and inspirations for this project; Design 1-bit dithering!!!
I wanted to create something akin to exploring a 3d version of this site, black and white 1-bit dithering with lots of heavy border lines for contrast. To start with the design I made a couple mockup moodboardy videos in After Effects to capture how this aesthetic would look in motion;


The second video I made had me exploring an offshoot of the story a bit in a code/conlang that will end up being pretty prevelant throughout the game ;). A script that the more venturous of you may have already noticed scattered around this website. If you managed to crack it you should reach out and tell me how you figured it out - im curious how well I did putting this all together.



The music choice for both of these videos was very purposeful too, I want to capture a very ethereal, sacred theme. I expanded on the music choice through a couple playlists to serve as placeholder music until we can make something original.



On top of this, I want other aspects of the games design to be very retro, i'm going to use billboarded sprites for a good ol' boomer-shooter vibe and have a UI designed like an evil original Macintosh. This is the same UI design idea that went into the windows on my new 404 page
Inspiration Naturally this aesthetic led me to explore The Return of the Obra Dinn as it's one of the most prominent examples of pushing a 1-bit dither effect into the realm of 3D. However, my taste in games and media in general is much more surreal, and I want the world of this game to reflect that. Below are some of the inspirational pieces of media and their aspect I hope to capture;

Disillusion

A first-person dungeon crawling RPG with turn-based combat and an emphasis on interacting with the characters around you. Heavily inspired by other games such as LSD dream emulator, eastern mind lost souls, amongst others. Appear with no memory in a land surrounding a bizarre tower drawing in all life with a strange urge to climb it. Climb the tower to gain an understanding of why you are here, the higher you go, the more you may understand. Branching paths and dialog can lead to different outcomes or uncover new areas to explore.
While the gameplay itself isn't anything revolutionary, I immediately fell in love with the music and aesthetic of this game. The main story of this world revolves around a lot of traditional Buddhist and Hindu stories while creating it's own unique world and lore. The main aspect of this game that I enjoyed and hope to take inspiration from is its mixing of both ethereal thought and surreal-whimsy. Many of the characters say hilarious one-liners or stuff that can geniunely be thought-provoking. While I think I'll take my world a bit more seriously, I do want to capture some of the whimsical surreality that brought me so much joy from this game.

Myst

Enter a world where nothing is as it seems... and adventure knows no bounds! Journey to an island world eerily tinged with mystery... where every rock, every scrap of paper, every fleeting sound holds a clue to an ancient mystery. Enter, if you dare, a starkly beautiful landscape shrouded in intrigue and injustice. Only your wits and imagination hold the power to unlock the shocking betrayal of ages past!
In all honestly I never finished Myst, but its surreal pre-rendered environments with that classic 90s dither is an instantly recognizable vibe. I could have put any late 90s point and click adventure/puzzle game with pre-rendered graphics but Myst is the only one I physically own and played when I was young so it feels appropriate.

Corru.observer
Corru is a browser game about jacking your brain into an alien biocomputer. It has everything I've already mentioned, dithered graphics, beautiful music and surreal yet often funny dialogue. However, one thing that this game does better than the two above is its worldbuilding and characters. Every aspect of this game is immersive and reflects the larger world that it takes place in, there are little popups about translations from alien languages, errors unique to the "mindspike" interface you use and more - I adore the level of detail. Additionally, despite being "aliens"?? the characters feel extremely fleshed out and memorable. I love this game and you should all play it right now.

Yume Nikki
Yume Nikki needs no introduction. The main aspect of Yume Nikki I want to take with me into designing this game is of it's surreal worlds that work to tell the story, I want the environment to be as much a part of the story as the dialogue and design. The Universe/Theme From the components I pointed out from my inspiration it may be easy to piece together the general world I am trying to make.
Daemonveil places the player into an alternate version of the internet, one built using the realm of spirits, angels and daemons as the tunnel for communications. I want to explore what such a realm would look like if you were to be sucked into it, an amalgamation of technology and spirituality. Would such a technology respark a divine war? What happens when we use our metallic alchemy to get closer to the Gods previously imperceivable? I want the environments of this world to reflect the symbols we assign to beings beyond our understanding and how we comprehend phenomena beyond our control. Gameplay Right now I want to focus mainly on exploration and short Myst-like puzzles, but thats extremely up in the air for the moment. My main focus is to explore and develop this world through surreal environments, characters and dialogue.

ENTRY 12/30/23

Cool Lighting and Dialogue

The past few days I spent a lot of time fighting Godots lighting to create a cool volumetric light effect, I don't think this idea is too scalable but hopefully I can keep it in a few places because it looks COOL. Additionally, I worked on creating a nice typed-in dialogue system!

Quick Video Demo

The song is Eulenlieder from the Signalis OST

The Lighting

Achieving the volumetric lighting effect through the windows was an extremely painful experience, not for the reasons you may expect.
I initially got the idea after messing around with the WorldEnviorment settings on a different map, I realized that enabling VolumetricFog with the directional light I already had created a cool light effect that paired well with the dithering (rightside image). From this, I was inspired to test how this effect would look as a way to illuminate a building through windows with cool light streaks and a godray/dusty-air effect.
This is where the hell began. To start, for this new building I made the walls much thinner so the windows would look reasonable - I don't think theres many windowed buildings with meter-thick walls. Because of these thin walls, (to my knowledge) godot started to stroke out and display the "lit up" fog against the inside part of the wall, illuminated by the light on the other side. While this lit fog didnt traverse any further, it did stick to the inside of the building and essentially turn the wall gray - leading to pretty gross dithering artifacts on the walls;

To make a long story short, this effects every kind of light; directional, omnilight and spotlight. Spotlight however, was the least noticable for a couple reasons. First, I could concentrate the beam of the spotlight just on the window, so any weird lit fog was just a circle around the window. Second, after a lot of black magic (messing with sliders until shit looked okay) I was able to minimize the amount of the wall-fog that shows up, enough that it just looks like bloom from the window. I have no idea why this works but - if you set the range component really high the cast shadows suddenly get really-sharp and the residial fog mess dissipates mostly. Disadvantage of course being that I have to individually place and angle each light - not ideal! Maybe in the future ill come back to this mess but for a quick demo it looks good enough and COOL!

Dialogue UI

The dialog setup I made is based on this tutorial, with a fair amount of modification for the profile pictures and layout. I ended up designing this cute little 1-bit popup window design for the dialogue im quite happy with :D

There weren't too many issues with implementing the textbox except the mess that having several "await resized" causes;
func display_text(text_to_display: String, profile: Texture, speech_sfx: AudioStream): pfp.texture = profile text = text_to_display audio_player.stream = speech_sfx # calculate the width of the textbox before performing typewriter animation. label.text = text_to_display await resized custom_minimum_size.x = min(size.x, MAX_WIDTH) if size.x > MAX_WIDTH: label.autowrap_mode = TextServer.AUTOWRAP_WORD # we have to do it twice since the x and y change in seperate passes... await resized label.custom_minimum_size.x = min(size.x, MAX_WIDTH) await resized #await resized # THIS AWAIT DOESNT ALWAYS TRIGGER, CAUSING THE TEXTBOX CODE TO HANG. #custom_minimum_size.y = size.y
You have to essentially plop the text in the textbox prematurely, wait for it to resize and then grab that size to use for text-wrapping. However, the x and y resize events are seperate, meaning you have to await twice - but for text short enough to not cause any y displacement that additional resize signal never comes and the textbox initialization hangs. At the moment I don't know a nice solution to this, so the textbox nicely presizes horizontally but not vertically. Luckily this is just a cosmetic issue, the box expands live if the text lines go higher than the profile picture. Not the end of the world and another little thing to come back to.


I dont want all these logs to be mostly complaining about stuff that didnt work, but I think it's important to record the things I struggled with for my own sake - see how im improving when I inevitably figure these problems out :)

My next goal is to implement actual dialogue options and everything that comes with that; dialogue trees, having the NPCs trigger different events based on your choices etc. I'm excited to start work on that, I have an idea for the appearence of the dialogue option menu that im eager to show come next update!

ENTRY 12/27/23

Getting started

I already did quite a bit of work on this game before deciding to make a blog, so this is going to be a large update/introduction to what I've done so far!

Quick video demo


The Maps

By reccomendation I am going to use Qodot + Trenchbroom to create the maps for Daemonveil. To my knowledge, this is the same setup that Cruelty Squad uses so thats cool.
Trenchbroom was extremely easy to get into and make some basic test maps with, im excited to become more immersed in its tools and I get further into this project. Right now I just have 2 very basic maps made for testing with a ton of random textures put on different walls for testing how they look after all the filters are applied.
Massive thanks to this tutorial

The Filters

Right now im simply using two existing shaders. For the Sobel-edge outlines around everything I am using this one by having a Quadmesh with a shader texture sitting in front of the player camera. I had to get very creative (jank) way to get the dither filter I found to work; I ended up nestling the entire 3D scene inside a container within a 2D scene. Since these containers can have an applied shader texture, it made it easier to apply a shader to the already rendered 3D scene output than to try and combine the work of dithering and Sobel-edge filtering in 3D.
Ideally, I would want to make something on my own thats a bit cleaner than this implementation. I don't know if i'll go as far as what was done for Obra Din (reading this post gave me a stroke), but hopefully I'll create something a bit more optimized to embrace the dithering and heavy lineart style. I made the flashlight part seen in the video to test how the dithering looked with variable light and in general I like how it looks, but the sobel filter often is janky or feels off so that may require the most work.



Mechanics and stuff

So far I've implemented a basic interaction system and a "dumb npc", one that just triggers a single one-liner response popup rather than a full dialogue-system. The plan for the future is that NPCs that have complex dialogue will summon a new 2d interface for going through dialogue choices. I want this complex dialogue system to have nice animations and a seperate UI, so it made sense for the "decorative" NPCs to just have a little textbox that doesn't fully disrupt the flow of gameplay.
Right now I have that implemented as a signal to an overarching "popup" item that causes it to summon with the passed signal. In the future ill also pass more information like an icon so the dialogue can have a little profile picture for our dumb NPC friends.
I programmed the popup-box to have a random offset every time a message is shown, so it has a more old-style "popup window" feeling to it with its random placement. A couple people have told me this feels obnoxious so I don't know if ill keep it that way.

I've also implemented the system for swapping out the current 3D scene. Since the scene is contained in a container, I can easily just "free", "load" and "append" to swap out the scenes. Of course fully "freeing" the old scene will purge it from memory, but at the moment I think that in combination with some global autoload stuff makes more sense then some sort of scene switching that preserves the state of each scene. This full purge also has the benefit of killing a bunch of the signals, so dialogue will reset when you switch between maps.
extends SubViewport var worlds = ["world", "realm_1"] var worldIndex = 0 # temp debug for cycling worlds var currentMap = null func swapToWorld(worldName): if currentMap != null: currentMap.free() # delete current world (should purge it from memory too!) var world = load("res://worlds/" + worldName + ".tscn") currentMap = world.instantiate() add_child(currentMap) func _ready(): swapToWorld(worlds[0]) func nextWorld(): worldIndex = (worldIndex + 1) % worlds.size() swapToWorld(worlds[worldIndex]) # Called every frame. 'delta' is the elapsed time since the previous frame. func _input(event): if Input.is_action_just_pressed("debug"): nextWorld() func _on_pause_menu_next_map(): nextWorld()
Ideally, I won't have that stupid array of world filenames at the topic of the config by the end of this, but it works for now while I test things.
Other than that I got some of the more boring stuff done; cute little colour overlay to change the highlight colour, pause menu, nice locomotion for the player and got things set up for the more complex components coming up.
Saving the most boring for last but the pause menu exists on the 2D scene that holds the world container (still following?). Because of this, I set up so the "Pausable" state for the 2D scene, which sounds jank but (I think) this will work out nicely, if I treat this 2D layer as the parent for all the 2D components of the game I can pause the 3D part of the game (physics n' all) when the player initiates the "complex" dialogue, opens any menus etc. - this makes it super easy to hand off control from the 3D environment to a the 2D one without a bunch of weird focus things set or if statements like "if paused".
Anyways, thats all that's really talking about for this first update! I'm excited to really dig my claws into this game and world, my mind is filled with ideas that I can't get out fast enough! Hopefully whoever reads this is as excited as I am. If anything, I've come to respect games a lot more as an art form and now realize how much fun it is to work on one - a game is a nice culmination of the things I enjoy doing!