Showing posts with label Find Your Car. Show all posts
Showing posts with label Find Your Car. Show all posts

09 January 2020

RNGesus is an unruly troublemaker who'll cause you all kinds of grief if you let him off his leash.

"Find Your Car" includes, unsurprisingly, a lot of procedural generation and in turn a lot of pseudorandom number generation. As with my prior article about pseudorandom numbers, I felt like taking a few minutes here to share my experiences wrangling the laws of mathematics to achieve my goals.
A major purpose of this game is acting as a demo for my procedural universe chunk system, particularly its versatility "out of the box." I accordingly designed it with as much modularity as possible and used preexisting utility scripts I'd already written wherever I could. I ended up needing to upgrade a few of these, but in so doing I was careful to keep them generic and thus reusable.
A notable example is my "Swap With Random Prefab" script, which when attached to an instance of a prefab will, once it is spawned, choose from a user-specified list of prefabs, instantiate it in place of itself, and then despawn itself (or, in the upgraded version, an optional "target" object). This has been useful to me in the past for, for example, spawning a placeholder tree and then swapping it with a random other tree to add variety, or having a zombie drop a random item when it is killed. In "Find Your Car," it is used for walls and floors to randomly replace them with a variety of walls or floors, e.g. a floor with a ramp or a wall with a door, when a chunk is refreshed. This way I could construct one template parking garage chunk and then have it adopt a large variety of configurations as it was instantiated throughout the garage.
Some readers may, assuming I'm explaining this well, see the problem already. With this level of encapsulation, the wall and floor instances have no idea what chunk they occupy and thus no connection with its random seed, but they do call upon the built-in random number generator - meaning that the random swaps they perform will be truly unpredictable and not deterministic. The user-facing side of this problem is that a player could leave an area, walk a decent distance away so that the corresponding chunks are unloaded, head back so that they get reloaded, and find that they have regenerated completely differently! There might be walls where there weren't any before, cavernous voids where there had been floor, and the car that had been left comfortably parked in an open space now lodged halfway inside a wall!
Ways to fix this didn't come easily. The most obvious solutions were to refactor all of my utility scripts to use interfaces such as "seedable random" or to move all of the random generation that needed to be deterministic into the chunk refresh function, sacrificing modularity in favor of a complex monolithic algorithm. As may be inferrable from my tone I wasn't excited about either of these. I did find a solution, but it involved sacrificing performance instead (and what I imagine is less than professional-grade code) by creating a helper script that would scan chunks for specific scripts and call non-randomized versions of their swap methods, which it would randomize itself based on the chunks' random seeds and positions - a bit of a midway point between the other two options that I considered a workable compromise.
The reason I bring this up isn't to brag about my hacky workarounds to my own buggy code though. The reason I bring this up is because I learned a valuable lesson and I want to pass it on to everyone else who tries to do something like this: be very careful when dealing with random number generators if you want deterministic results. If you don't make sure that any and all objects using them are strictly controlled so that your random seeds (or states, etc.) are properly enforced, the generators will bite you in the butt with no hesitation and happily run off generating all manner of decidedly non-deterministic, unpredictable values, the end result of which is an unstable game world. Unless that's what you want, keep them under control!

16 October 2019

Find Your Car Development Log 1: Wait What Now?

Any recent visitors to this blog may have noticed that I haven't posted anything in a few months. To oversimplify, I don't pride myself on my time management skills and I've had more than enough on my plate to overwhelm what little skill I do have without adding blogging to the mix.
ShipBasher is still in "active" development, i.e. not abandonware at this time, but I've flitted temporarily to another project.
Have you ever been lost in a parking garage, perhaps late at night, searching for your car? Did you walk for what felt like hours, through seemingly endless levels and zones, all starting to blend together and look the same, and none giving any clear indication whether you were getting closer to your car or just more lost?
While playing with a test build of my Procedural Universe chunk system, I and some of my contacts noted that it evoked a massive parking garage, and before long an idea took shape to capitalize on this in an art game that would double as a more entertaining demo, which for lack of a better candidate I have given the self-explanatory name "Find Your Car."
Originally I considered naming the game "The Interview" for reasons that become evident below, but unfortunately the name was taken by a game actually about an interview.
In "Find Your Car," the player is to spawn in a car (wow!) within an endless, procedurally generated parking garage. The advertised goal at this point is to find a nice parking space, anywhere the player likes. Once parked, the player leaves the car.
Upon leaving the car, the player is alerted that there is an important job interview about to start and must hurry to it, racing the other candidates on the way, which take the form of simple NPCs (i.e. zombies) that chase the player and move toward the interview location, which is an unknown point at some distance away from the player's parking space as determined by the game's difficulty setting (if a high difficulty is chosen, the interview is very far away).
Once the location is reached, lo and behold! The player gets the job immediately - but don't congratulate yourself just yet. In order to get home, you must find your car. This is when the "real" game starts: the player must now wander through the near-infinite parking garage, perhaps retracing steps, in search of the car. The player no longer has to worry about enemies, but will encounter a variety of distractions including the all-too-tropey "scenic vistas," various other cars, and Easter eggs such as perhaps exotic vehicles (how did a train get in here?), the remains of past wanderers who failed to find their cars, etc.
(We ride eternal on the highways of Valhalla! WITNESS ME)
So that's the design. So far a closed alpha build of the game exists, in which there is a fully functional procedural parking garage, basic (if unstable) controls for a car and player character, pop-up messages about goals, and a victory message indicating how long it took to find the player's car.
Still to do are adding "rival" NPCs, all the cool Easter eggs I mentioned above, a bunch of polish, and solving a few playability issues such as bad luck leading to spawning trapped in a small area or being physically obstructed from reaching the interview location and unpredictable generation conditions leading to having to walk for several kilometers to reach the interview location even on the easiest of difficulties... or at the other extreme, finding it right smack next to where you parked:
In this image the interview location is indicated by the brown door in the background.
Did I mention needing a lot of polish? As it turns out, a humongous modular building comprises a lot of meshes and in turn a lot of polygons, which give my pitiable 6-year-old integrated graphics chip a hard time unless I make everything as simple as possible. But if you join my Patreon... At some point, hopefully, soon, I'll be able to treat myself to a more powerful GPU that can handle prettier graphics at this scale.
All the same, whilst playtesting this I was surprised to find how well it captured the mood of my past experiences wandering despondently through parking garages, so in a way the project is already a success.

Next time I hope to have an open alpha (or beta) build available and perhaps do a post-mortem on what I learned in the course of making this, how my chunk system matured during the process, what I might do going forward, etc.

Sorry this isn't a real post :C

I've entered graduate school and, as I expected, suddenly become far busier than I had been before, leaving no time to maintain my blog,...