[3 Days] How we created NALE's Mode7 street race mode in RPGMaker MV!
NALE Chapter 3′s out soon, and we’re continuing our daily blogposts in the run-up to launch! Today, it’s time to pound a can of Monster and limber up my typing fingers, as this is gonna be a long one - how did we do the racing sequences?
NOTE: before I get into this; this one’s aimed at people who are interested in RPG Maker, or game development. It might be a bit “dry” for a general-interest audience.
To start us off, here's a video of one of the later races in Chapter 3. In this race, Nina already has some of her special race abilities unlocked.
From the moment that we planned out that Chapter 3 would be about touge racing anime like Initial D, it was clear that, just like the Dragon Fantasy Arena Card Game-style minigame in Chapter 2, we were going to need to make it possible for Nina to actually race.
We also didn’t want to introduce a huge amount of custom scripting, so the race mode would be made almost entirely with regular eventing.
Now, similar to Chapter 2, NALE is a visual novel/graphic adventure - not a combat or true racing game - so the minigame wouldn’t have to be something that could stand up on its own merit; rather, it’s a tool, like the courthouse segments, to continue the story - and we needed to make sure that we could use it as a vehicle to present narrative in a fun way. We also knew that like NALE C2, the race mode would have an accessibility feature which would allow players to auto-win, and we expect that most players will use this; so having genuinely taxing difficulty wasn’t high on our agenda; the skill ceiling should be relatively low.
Despite all that, we didn’t actually know how it was going to work when we made NALE C2′s final “next time on...” cutscene, which is kinda terrifying, but then life’s no fun without a little risk.
Due to all this, the racing minigame was actually the very first thing we built for C3, even before we’d fully finalised the game’s story - because if we couldn't make it work, then we were going to have to ditch the whole idea and try something else.
This is NALE’s race test area, which is inaccessible in the final game, but can be accessed via debug using the editor. This was the first C3 location to be built. If you play C3, you’ll see that the Rostro Vista Parking Lot is heavily based on this location, though that final map is much bigger.
Once we knew we were doing this kind of thing, we evaluated a bunch of different approaches. These included...
- an actual real-time racing mode, using some kind of real-time movement plugin designed for Zelda-style movement
- a mainly text-based mode, where the whole thing is done with sound effects and “theatre of the mind”
- a third-person mode using sprite scaling and tasking the player to dodge/make inputs at critical moments, conceptually similar to something like RoadBlasters/Road Avenger for Mega-CD
Each of these approaches had their appeal, and we produced paper prototypes of all three. In the end, though, all of them had problems; the first being scope, the second being whether it fit with the rest of NALE, and the third one being too budget-heavy (though elements of the third can still be seen in the pose for Nina’s art during the races).
We stepped back and thought again about what we had, and what the mode was designed to achieve, and thought that maybe we’d lost sight of something. The racing isn’t just about driving, it’s a narrative device. We thought about how other media has approached this; a classic example was in the Monkey Island games by Lucasarts, which had a sword-fighting minigame, but the game wasn’t actually the sword-fighting, rather it was about the insults and verbal barbs the characters threw at each other.
Initial D’s racing is kinda similar. The first seasons were more about the mechanics of racing, grip, drifting etc. (in a fictionalised way), whereas the later seasons recast this idea as more about having the spirits of the two drivers clash. This is a Japanese cliche, seen in everything from Dragonball to Beyblade, and it made perfect sense given what the rest of NALE is about.
Additionally, around this point we’d settled on what Nina’s emotional journey for C3 would be, so it made perfect sense to go with this approach.
So, we focused on what we knew could work. That means that the very first version of NALE C3′s race mode is that cutscene from C2, which looked like this:
In the editor, that map looks like this:
The cars are set in motion (i.e. “move right and repeat route”) and the camera follows them as the map loops horizontally. It was quite effective, so much so that it seemed a foregone conclusion that this would form the basis of the mode.
With that as a base, the next step was to see what we could do with this visually, mainly because we knew that the racing would need to be visually striking/interesting or the idea probably wouldn't work. The result was similar to this gif, which was from a different in-game location, but one that we "forked" at around this point.
Huge props here goes to the UltraMode7 plugin off the RPGMaker forums, that allows us to lower the camera and get parallax going with the trees and objects. The overhead version of the mode looked okay but this was an enormous improvement.
We originally wanted to have dynamic lighting from the car headlights, and investigated about 5 ways to do this, but none of them gave an acceptable result, and in the end, we just stuck with simple coloured lighting.
Once we had something similar to the above, we knew that on a purely visual sense, we were probably going to get something acceptable, so the next job was to try and figure out what would be involved in the gameplay.
Defining the Rules
Right away, it seemed sensible that we would have the player and the rival “clash” in the race, and ultimately, the winner at the end of the race would be the person with the highest score at the end (this is actually what’s happening when you see the cars move back and forth in the race; it’s actually a “score” value beneath - the position of the cars is just theatre). A nod to racing here was to think of the course as divided up into corners, and that the winner is actually the person who wins the most corners.
We also wanted to keep it simple, so we thought about extremely simple games. Many examples sprung to mind, but the main one was rock-paper-scissors (aka “Janken”).
The next step was to prototype this on paper, with dice and a couple of toy cars.
Quickly, it was evident that the “janken” element alone would be too monotonous, so, we looked at adding a gambling element, and settled on something akin to evens-and-odds. That was too random. The solution then was to include both - so players win a “clash” (janken) then they do a face-off (higher-or-lower).
Another go at the paper prototype revealed this to be quite fun, so it was go-time.
So players would clash repeatedly then face-off, winning or losing corners, and the winner would be the one with the highest score (=furthest in front) at the end of the course. We also added a few other wrinkles to the rules; e.g. it’s impossible to draw a race in NALE (if you would be at a draw at the last straight, the game lets the player win).
Quickly, when testing this, we found that it felt really bad to get a “draw” in the clash, so we flipped this emotion by making it good to draw, by using that to charge the player’s special abilities.
Bringing it into MV
So that’s the theory, but how does it work in practice?
This is what the race map looks like. The top road is used for the race, the lower road is only shown when crossing the finish line. The circled event is the “race manager”.
The race mode uses a single master event, called the “race manager”, which is an autorun event. This functions like a state machine, and the race is composed of a series of states, and logic to transition between them. Each of these states is a page in the manager.
They are, as follows...
- Race loop
- Face-off (player is on offensive)
- Face-off (AI is on offensive)
- Corner state
- Finish state
- Event disabled state
The pre-race makes sure everything is initialised correctly, sets up the camera, plays the right music, selects the right AI opponent, etc. then sets the cars moving. It transitions to the race loop as soon as the race is up-and-running, and never comes back.
The race loop is the default state. In this state, each time the page runs, the cars “move” down the track, i.e. there’s a value of the length of the track & the distance to the finish line and a “speed” value for the cars, and we decrement the distance by the speed of the cars each loop (plus a little randomness). The race loop has checks in it, so it always knows when the next clash will be, and when the next corner will be; when we reach these marks, we switch to those pages.
The clash state handles the clashes. This poses the question for the player about making their choice for the clash (or to choose auto-race or a special ability). Once complete, this state either transitions into a face-off or back into the race loop state.
There are two face-off states. Originally there was only 1, but we found it was boring for the player to watch the AI perform the face-off with the full interface. Instead, we split this into two pages and made the AI’s face-offs really fast; this was just the cleanest way to do it.
The corner state is activated when the race loop state detects it’s time for a corner. Firstly, this performs logic to work out who is meant to be the winner, then it does all of the audio-visual stuff for the corner, signals win/lose for the player, increments the winning car’s score, and adjusts the positions of the two cars to match the score. The corner serves another vital purpose, in that it fires off common event which, with variables, triggers much of the in-race dialogue.
The finish state comes up when the race loop detects the race is over. The race loop actually does one more clash at the finish (which might just allow the player to win a losing race). This darkens the screen, teleports the cars to the lower road, and then performs the finish line bit, which I guess is like a cutscene.
This all seems quite simple when I break it down like that, but there are a lot of little touches. For instance, the auto-race functionality needs to be able to do all of this stuff automatically, meaning that many of the pages have two flows; one for “when autorace is off” and another for “when autorace is on”.
Another important part of this is the UI/HUD, without which the racing would be confusing. This is always updating, every frame, and uses interpolation so everything moves smoothly.
The HUD has many moving elements; energy bars, a corner warning indicator, pips for special ability charge, dynamic character portraits, the progress indicator at the top of the screen, the cut-in images, the special ability images...
These are all managed by a HUD manager, which is a parallel process event that reads all of the necessary qualities (stored as variables) and responds with the info on the HUD.
This HUD manager is entirely reactive, not pro-active. It instigates nothing. It just takes in information and displays it (nothing in the game “waits” for the HUD). This removes dependency; so the game would actually be entirely functional without the HUD, it’d just be confusing! A slight concern here is that I believe the HUD assumes a timestep of 1/60th a second, i.e. it has hard-coded frame-times. This would be a no-no if this was an action game, but doesn’t really affect NALE.
But the point here is that all of the Race HUD is entirely done with RPG Maker’s picture functions and robust eventing. There’s no custom plugin coding in the HUD.
Though bear in mind that not all the logic is contained in the map; much of it is in common events (about 30), mainly to do often-used tasks like fetch certain bits of information.
(on a related RPG Maker note here; I really wish that you could “pass” common events data, and have them “return” data when complete - there are workarounds, but I digress)
The plan for corners actually changed in the midst of implementation.
The original plan was to fade to black, then show a static image of two generic cars taking a corner, randomly picked from a pool (in fact, the earliest version just used a load of screenshots of Initial D that we planned to replace). However, whilst it worked in a fashion, it felt kinda flat, and we wanted to do something more fun.
In the final version, we actually rotate the camera and move it in, by animating the values used as part of the Mode7 plugin. As the cars only have one sprite (sideways, left-facing) this has the side-effect of giving the impression that the drivers are turning in for a drift. We then black out the screen and play SFX for the corner, and hopefully the player's imagination fills in the rest.
This was actually my wife's idea, after she saw the cars in this position due to an early bug I was trying to fix.
It’s a shame that you don’t actually see the cars go around a corner... But then, if you’ve been following this, you can probably see why. I tried a few ideas, but ultimately, it was better to have the cars turn in, black out the screen, play the corner audio, have the screen fade back in, then have the cars turn out. Your imagination fills in the bit in-between better than anything I could produce.
A little touch here is that those fences actually switch to a “corner sprite” when the camera moves. That took all evening to get right.
Once all that was up and running, it was time to wrangle it into something to be used in-game.
A common event was written so that when a race starts, the game is supplied with an “opponent index” variable, which causes the game to select the correct difficulty values for the opponent (there are about 16 variables which collectively control enemy difficulty).
Additionally, an event exists to play dialogue, which, when called at the correct corners/opponent indices, would play all of the conversations that you see in the final game.
To begin with, we wrote about 6 races, with different opponent types. This required some back and forth to the stage pages in the manager, adding a bit of logic here-and-there, to make sure we could realise all of the opponents we wanted.
Once this was all done, we had a “demo” we could play, where Nina raced a succession of 6 opponents, starting with a tutorial opponent. A few tweaks, and it was finally good to form the basis of the racing in game.
This process took around three months.
Then, we shelved the race mode, and got on to writing the rest of the chapter. Until the first pass of everything was complete, when Nina went to race, she would just automatically win (the screen would go black, then gameplay would just resume).
Once the chapter was mostly done, we integrated the races with the story, but this led to a problem - Nina’s auto-races are guaranteed to win, but when on auto, Nina’s choices at every point were random, meaning that visually, she would actually lose. We then had to re-engineer all of the auto-race flow to make it so Nina would visually nearly always win in auto-race (even though she always wins regardless). This took about a week.
What we learned
The main takeaway we got from this is that MV’s eventing is far more robust and powerful than we previously realised. Prior to undertaking this, we never realised that something with so much logic would work in MV; we thought it would creak under the strain and issues would arise, but it works well.
Are there problems with it? Certainly. I think, if I’m honest, that if you were going to make a whole game out of this sort of minigame, you would need significantly “more” in terms of player choice. Right now it can be a bit limiting, and if you do a dozen races in a row, can become a bit monotonous. Fortunately, the auto-race functionality exists and, as stated before, the mode was never intended to stand on its own.
The main thing is that it’s visually distinct, looks cool, and conveys the narrative beats that we needed it to convey - so from that perspective, it’s a success. Nina and the other racers can "banter", which fills out the story.
If you intend to try and do something like this (and I recommend it; it’s been very rewarding), all I can say is to make sure that you have a very solid plan up-front, before you get going. That applies in general for RPGMaker (and, hell, all game development and maybe life in general!) but doubly so for this sort of thing.
Thanks for reading this! Nina Aquila: Legal Eagle, Chapter III: Legal Stage will be released on November 6th, where it will launch at $3.99!
Pre-orders are open now, at a 25% discount, so get in early for a lower price!
We're marking the run-up to launch of Chapter III with a rtange of daily blogposts:
... and our t-shirt giveaway from early in this calendar is still running - you can enter over on Twitter for a chance to win a NALE shirt!
If you want to be sure you don't miss the rest, you can follow us in various places:
Come back tomorrow for a devlog about Koahri1, the creator of many of NALE's fantastic illustrations!
Get Nina Aquila: Legal Eagle, Chapter III: "Legal Stage"
Leave a comment
Log in with itch.io to leave a comment.