Busty Barrister - Week 4
By Angus Cheng
A few weeks ago I talked about implementing a generic list of objects that conform to an interface in C. The code is not the nicest, but it’s working well enough and I think it’ll hold up until this game is done. This is what the EventData structure looks like at the moment.
typedef struct EventData {
int eventIndex;
int eventCount;
enum EventType eventTypes[1000];
int eventIndices[1000];
// Event lists
int showTextCount;
ShowText showTexts[1000];
int playMusicCount;
PlayMusic playMusics[100];
int setCharacterCount;
SetCharacter setCharacters[100];
int setAnimationCount;
SetAnimation setAnimations[100];
int setBackgroundCount;
SetBackground setBackgrounds[100];
int startSoundCount;
StartSound startSounds[100];
int greyFlashCount;
GreyFlash greyFlashes[100];
int queueAnimationCount;
QueueAnimation queueAnimations[100];
int screenShakeCount;
ScreenShake screenShakes[100];
int fadeEventCount;
FadeEvent fadeEvents[100];
int configMusicCount;
ConfigMusic configMusics[100];
int delayCount;
Delay delays[100];
int fadeMusicCount;
FadeMusicEvent fadeMusics[100];
int setBlackRectCount;
SetBlackRect setBlackRects[100];
int setChyronCount;
SetChyron setChyrons[1000];
} EventData;
It’s gettting a bit gross, every time I add a new EventType I add two properties for it. The only problem I’ve seen with this so far is in the Event creation functions. It’s very easy to accidentally write to the wrong array or count variable. Which will cause weird behaviour.
void add_fade_music(GamePlayData *data, float fromVolume, float toVolume, float duration) {
// Easy to increment the wrong variable when copy/pasting
int i = data->eventData.fadeMusicCount++;
EventData *eventData = &data->eventData;
// Easy to accidentally write to the wrong array.
eventData->fadeMusics[i].fromVolume = fromVolume;
eventData->fadeMusics[i].toVolume = toVolume;
eventData->fadeMusics[i].duration = duration;
add_event(eventData, FADE_MUSIC_EVENT, i);
}
Defining Levels
void opening(GamePlayData *data) {
add_character(data, CHARACTER_MIA);
add_character(data, CHARACTER_LARRY);
add_character(data, CHARACTER_JUDGE);
add_character(data, CHARACTER_PAYNE);
add_character(data, CHARACTER_PHOENIX);
add_character(data, CHARACTER_WELLINGTON);
add_set_chyron(data, true);
add_set_black_rect(data, false);
add_show_text(data, NULL, GREEN, CENTERED, "August 3, 9:47 AM", "District Court", "Defendent Lobby No. 2", TYPE_SLOW);
add_wait_for_user(data);
add_chyron_pause(data, .5);
add_set_background(data, "resources/backgrounds/courtroom_hall.png");
add_fade_event(data, FADE_IN, BACKGROUND, 1);
add_play_music(data, "resources/music/beginning_overture.mp3");
add_config_music(data, NO_CHANGE, 0.0);
add_fade_music(data, 0.0, 0.2, 2.0);
add_show_text(data, PHOENIX, SKYBLUE, LEFT, "(Boy am I nervous!)", NULL, NULL, TYPE_FAST);
add_wait_for_user(data);
add_chyron_pause(data, .5);
...
}
Write now I’ve only defined one cutscene. I re-implemented the opening scene from Ace Attorney. It’s okay at the moment, but I imagine pretty soon I’ll need to create some sort of data format. Possibly not JSON, I’d like to create something that’s less verbose and easier for someone working with me to define levels. There’s going to be a lot of text in this game and I’m not going to be the only person inputting text and other events into this game!
ADD_CHARACTER 'CHARACTER_MIA'
...
ADD_SET_CHYRON true
ADD_SET_BLACK_RECT false
ADD_SHOW_TEXT NULL, 'GREEN', 'CENTERED', 'August 3, 9:47 AM', 'District Court', 'Defendent Lobby No. 2', TYPE_SLOW
ADD_WAIT_FOR_USER
ADD_CHYRON_PAUSE 0.5
That looks somewhat reasonable, but I’ll hold off from doing this for a while. I want to get some court room levels defined as well as some investigation levels. Once those are ready I reckon I’ll have a really good idea how to structure the levels and the data format. One thing that’s missing from the level definition at the moment is conditional events. Those might be tricky to define in text.
Defining Animations
I found some ripped Ace Attorney assets at court-records.net. These included animation frames as well as animation configurations.
9 animations
* Animation 0
13 keyframes
Frame Duration
0 8
1 1
2 1
1 1
0 15
1 1
2 1
1 1
0 1
1 1
2 1
1 1
0 25
The above configuration defines Animation #0. It has thirteen key frames. Basically it says “Run frame #0 for 8 frame”. Assuming each game frame is 16 milliseconds that means run frame 0 for 128 milliseconds. “Then run frame #1 for 1 frame”.
// Animation 0
add_animation(
character,
counter++,
IDLE,
(int[100]) { 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, },
(int[100]) { 8, 1, 1, 1, 15, 1, 1, 1, 1, 1, 1, 1, 25, },
13
);
The animation above is actually an idle animation with a blink. So you can see most of the animation is on the first frame. Where the character has their eyes fully open. So far I’ve defined 5 characters, it took me a few hours to get the data into shape and into my engine.
Text Write Speed and Colour
In the image above, you can see there’s light blue text and one word of red text.
add_show_text(data, NULL, GREEN, CENTERED, "August 3, 9:47 AM", "District Court", "Defendent Lobby No. 2", TYPE_SLOW);
My engine doesn’t support that. It assumes all text in the dialog box is the same colour. Also the game likes to write in some text quickly and other text more slowly. This can be used to create a dramatic effect. Once again I don’t support speed changes in a dialog box. I’m thinking of removing add_show_text and replacing it with smaller sub-commands.
add_text()
set_text_color()
set_text_speed()
clear_text()
set_text_write_sound()
The cool thing about this is we can also play sounds and add delays while the text is writing in.
Court Stage
This week I’ll model the court room level data. This is where the user finally gets to make decisions and present evidence/character profiles. I can’t find the background assets, so I guess I just wont use them.
Modeling the tesimonial stage might be a bit tricky. It’ll use the cutscene engine, but it can be controlled by the player. I might split it into it’s own GameState.
Investigation Stage
The other half of Ace Attorney is an adventure game. The first game I ever made in 2010 was an Adventure Game, so I’m pretty familiar with how to create an engine for them. To be honest they’re mega easy to code. To build the engine I’ll use the data from case two in the first Ace Attorney game.
That’s what I’ve been up to in the last two weeks. I’ll update you again next week.