Sunday, March 1, 2015

Variable Graphics

Mention to any group of RPG Maker VX Ace users that you want to learn how to write scripts (which give you unparalleled power over customizing the game above and beyond what limited options the program hands to you), and they'll tell you to learn Ruby - the programming language that RPG Maker VX Ace is coded in. It's not that this isn't good advice, but a little primer on how the RPG Maker program actually works would be a lot more immediately useful - especially to those of us who have some programming experience, but simply don't know this particular language (yet).

Well, after a year of searching in vain (and, yes, I have finally made the decision to learn Ruby properly), I did recently come across a brief introductory tutorial to coding specifically for RPG Maker VX Ace, and, even with its limited scope, it has had an enormous impact on my understanding of at least some of the basics of what's going on in the code, but most importantly, on my confidence in being able to learn how to manipulate code, and the promise of what kind of things I'll have control over once I do. It's been the most useful external RPG Maker resource I've read since that eventing guide that enlightened me to the fact that I was doing "cutscenes" all wrong.

Graphic Equipment

In any programming environment, there is often more than one solution to every problem. Some solutions are simpler and more elegant than others, though those generally require some amount of experience and insight to discover. Sometimes the difference between one or another solution is simply a matter of approach, and your specific requirements will lead you to decide which ones are more or less desirable, and which ones may not be usable at all. For at least the last year or so, I've been looking for a way to implement optional alternate outfits, or, more crucially, equipment-dependent character graphics, in my game. It's one of those superficial features that doesn't impact the gameplay too terribly much, but is the sort of thing that makes the game a little more interactive and, I think, makes it a little bit more fun to play.

I toyed with the idea of using "Equip Events" (a handy script courtesy of Hime Works), which allows you to run versatile Common Events whenever the player equips or un-equips ("dequips") a character with a certain piece of equipment (weapons or armor). The Database in RPG Maker lets you run Common Events when items are used, but not when weapons and armor are equipped - this script fixes that discrepancy. With Equip Events, I can assign a unique Common Event to each piece of equipment, that will change the "actor" (RPG Maker terminology for playable character)'s character and face graphic to whatever I wish.

But, as you might be thinking, this could become rather cumbersome if I have a lot of pieces of equipment associated with custom graphic changes (that would turn out to be a lot of Common Events!). Moreover, this would work fine if each piece of equipment could only be used by one character (and thus is assigned a unique graphic change), but if I want a particular piece of equipment to change different graphics depending on who is equipping it, I'm out of luck, since I have no way (through this script or in the default program, that I know of) to know which character is the one being equipped!

So instead of using Equip Events for this specialized purpose, I found something better - a different script especially designed to change character graphics on equip - Jeneeus Guruman's Graphic Equip Ace. With this script I can simply add a little note in the corner (in the "notetag" area) of each piece of equipment's stats page in the Database, and the script automatically changes the actor graphic without having to do it through a Common Event. Better yet, I can assign different graphic changes to different characters for a single piece of equipment! And I can also assign a default graphic to each character for when they're not equipped with anything! As far as I can tell, this script works just as I need it to.

Variable Graphic Scripts

But there remains a little snag, which results from giving the player control over the actors' graphical appearances. There are two times at which I, as the developer, need to know what image an actor is being represented by: 1) when I display a message window accompanied by the actor's face, and 2) when I create temporary duplicates of actors to manipulate during cutscenes. Theoretically, this would simply be an issue of accessing data (which images are associated with which actors) that I know the program has a hold of. But the default program doesn't give you a command with which to access this data, and so this is an example of one of those situations where scripting can give you a simple solution that is not possible through eventing.

Now, presumably, you could get over this hurdle by assigning values to variables that correspond to actors' graphical appearances, that are updated every time those graphics are changed. And indeed, this is how I thought I was going to have to do it for a long time. But then I'd have to use the more cumbersome Equip Event solution above, rather than the more streamlined Graphic Equip Ace solution, since the latter isn't designed to update variables, but the former utilizes Common Events within which I can update variables. But then we come across the problem of having way too many Common Events, when I know there's a much simpler solution - if I could only access the data I know is hiding in the code somewhere.

(You might recall that I had this same problem with accessing the random encounter values, and it resulted in a similarly elegant solution.)

But first, a very small detour (only because this is the order in which I figured these things out). One thing that I discovered during my work on Ascension, that wasn't immediately apparent to me, was the difference between player and actor graphics. Actor graphics are stored in the program and correspond to specific actors (again, when I say "actor" I'm referring to playable characters). The "player" is the actual sprite you move around on screen, which is usually displayed in the form of the graphic of whichever actor is at the head of your party (and which will change if you change the order of your party). But here's the interesting thing - you can change the player graphic (which is, in a sense, more "temporary" than the actor graphics), without changing the graphic associated with any actor.

(I exploited this in Ascension by creating special graphics that denote which difficulty level you're playing on, that are viewable on the load/save game screen, but that don't affect the look of the character you control in the actual game.)

Character Graphics

Now consider that you're trying to design a cutscene where the player changes appearance (use your imagination - let's say the player is transformed into a toad), but by the end of the cutscene, the player must be returned to its usual appearance. You could change the actor graphic associated with the actor at the head of the player's party (which always changes the player graphic accordingly), and then change it back at the end of the cutscene. But if you let the player change the order of his team around, how will you know which actor graphic to change? Well, you can figure that out using event commands, by storing the numerical ID of the party leader in a variable, but then you'll need to use a conditional branch to determine the value of that variable, or else change everybody's graphic every single time.

If you know precisely which graphic you're going to use during the cutscene (if, say, it doesn't depend on who the character is), you can change the player graphic without mucking about with the actor graphics, but you're still going to need to use a variable and run a conditional branch to figure out which actor to turn the player back into at the end of the cutscene (depending on which actor is at the head of the party). And if there are different possibilities for graphical appearance for each of the actors, then you'll have to run even more conditional branches on the variables you've (hopefully!) been updating every time somebody changes their appearance. Or, you could just run this little script, right there in your event (look for the Script button on the third page of Event Commands), at the beginning of the cutscene:
$game_variables[x] = 
$game_player.character_name
$game_variables[y] = 
$game_player.character_index
to store the graphic associated with the player (whatever it is) in two variables x and y (replace with numbers, and make sure you use variables that aren't being used for something else - you'll probably also want to label them in the event window like you do all your other variables). Note that "character_name" refers to the filename of the image file (not including the extension) and "character_index" refers to the index of the image set within that file (if you've done any work on sprites and graphics in RPG Maker, you've undoubtedly noticed that image files usually contain eight different sprite sets, indexed from 0-7). Then, at the end of the cutscene, run this script:
$game_player.set_graphic(
$game_variables[x], $game_variables[y])
with the same variables from before, and it will automatically restore the player graphic to what it was before the cutscene! It's like you took a snapshot of the player, and then reverted it to the snapshot after changing it in the body of the event!

Alternatively, if you want to set the player graphic to that of a specific actor, but you don't know which graphic that actor is going to be using, and you don't want to keep a running tally every time the actor changes its appearance (resulting in a cascade of conditional branches), then just type this into a script box within your event:
$game_player.set_graphic(
$game_actors[x].character_name, 
$game_actors[x].character_index)
where x is the number of the actor as it appears in the Database. Additionally, if you want to set an event's graphic to that of an actor, rather than the player (useful if you're designing a cutscene where multiple actors in addition to the player are present), run this script:
$game_map.events[x].set_graphic(
$game_actors[y].character_name, 
$game_actors[y].character_index)
This time y is the number of the actor as it appears in the Database, and x refers to the ID of an event on the current map, whether it's the event calling the script, or another one entirely (make sure your ID refers to an event that actually exists on the map, though). Are you getting the hang of it yet? The next script will turn an event into a clone of the player, no matter what the player looks like!
$game_map.events[x].set_graphic(
$game_player.character_name, 
$game_player.character_index)
Go ahead, try it in your project! Note, however, that if you're trying to make an exact copy, you'll have to run a separate command to make the event face whichever direction you want it to face. You can, however, do this simply with a Set Move Route event command (try "Turn toward Player"), without having to use scripts at all.

Face Graphics

The other problem is the one involving the face graphic, which is used in message windows, and is unfortunately a little bit trickier. Now, you can use the same principles with the face graphic that we used above on the character graphic, just replacing every instance of "character" with "face". But remember that neither the player nor events have a face - only the actors do - and that face graphics are only used in message windows (and on the menu screen, but we're not concerned with that here).

Where it gets messy is using the script version of the Show Text event command. The script version gives us a little bit more power, in that we can assign a face graphic using a variable, like so:
$game_message.face_name = 
$game_actors[x].face_name
$game_message.face_index = 
$game_actors[x].face_index
$game_message.background = 0
$game_message.position = 2
$game_message.add("Text")
"Background" and "position" refer to the correlating options in the Show Text event command, each one indexed from 0-2 (Normal, Dim, Transparent; and Top, Middle, Bottom). "Text" is the actual text that will show up in the message window.

Presumably, we could use this solution just fine (on the other hand, there may be further difficulties, I haven't used it very much), but we no longer get the nice GUI accompanying the corresponding event command, which allows us to preview how the text will look (and thus fit it neatly into the text boxes). I'm looking into a more complicated script that digs into the code and adds a bunch of new features to the message windows that can be used right there in the event command - Yanfly's Ace Message System. It seems to do exactly what I want it to do, but as with most of these gourmet scripts, it also includes a whole lot of extra features that I don't really need. I might try to see if I can pare it down a bit to just the essentials that I want. The important thing is that it looks like what I want to do is not only doable, but I'm actually doing it!

No comments:

Post a Comment