In this comment I want to write a bit more about some technical aspects of the visual novel game. So, let's go.
For multimedia apps, there are some DirectX plugins available, in particular for window management, rendering and audio. These have been utilized for all sample games, including the VN sample game.
I wanted the codebase to be reusable in future. Also, I wanted the scenes of the novel be easily and quickly writable. Hence, I decided to implement a scene manager script, along with a main script, that glues all together. This allows you to quickly alter the scenes, as well as derive new projects from these components.
A VN game basically consists of scenes and steps. A scene describes various steps, and should be used for a specific situational context. E.g. a scene in a restaurant, office scene, romance scene, etc. A scene consists of steps. Each step is implemented as a callback function. Once all steps of a scene are iterated upon, the next scene will be loaded. If all scenes are done, the game finishes. A main menu exists as well, which loads the initial scene upon user input. Very simple, indeed.
Source snippet from the scene manager:
function SCMGR_LoadScene void(sceneident string)
{
if ("%szCurrentScene", -nt, "") {
call Scene_%szCurrentScene_Unload() => void;
};
set bSwitchSceneOnce <= false;
set iCurrentSceneStepIteration <= 0;
set bCurrentSceneCustomDraw <= false;
set bCurrentSceneKeyPressEvents <= false;
set bCurrentSceneCustomMainLoop <= false;
array_resize arrSceneManagerRegisteredSteps 0;
call Scene_%sceneident_Load() => void;
call StrCopy("%sceneident") => szCurrentScene;
};
Source snippet from the classroom scene:
function Scene_Classroom_Step_Phrase6 void()
{
call SCMGR_SetCharacterColor(255, 100, 235, 255) => void;
call SCMGR_ShowCharacterFigure("zina", "smile", 700) => void;
call SCMGR_SetDialog("Zina", "But first, let me ask:|Do you already have any experience with AquaShell?");
call SCMGR_StartUserInteraction(300) => void;
call SCMGR_AddInteractionOption("Yes, I'm familiar with AquaShell.") => void;
call SCMGR_AddInteractionOption("No, this is the first time.") => void;
};
function Scene_Classroom_Step_Phrase7 void()
{
local iLastInteractionResult int;
call SCMGR_GetInteractionResult() => iLastInteractionResult;
call SCMGR_SetCharacterColor(255, 100, 235, 255) => void;
if (%iLastInteractionResult, -eq, 0) {
call SCMGR_ShowCharacterFigure("zina", "laugh", 700) => void;
call SCMGR_SetDialog("Zina", "That's great! Then you will most likely have an easy time today!");
call SCMGR_SoundEffect("zina-chuckle.wav", %GLOBAL_VOLUME) => void;
} else {
call SCMGR_ShowCharacterFigure("zina", "smug", 700) => void;
call SCMGR_SetDialog("Zina", "Ah, someone new to the matter...|Great! You will learn a lot today!");
call SCMGR_SoundEffect("zina-okay.wav", %GLOBAL_VOLUME) => void;
};
};
function Scene_Classroom_Load void()
{
for (phrcnt, 1, 16, -inc, -eq) {
call SCMGR_RegisterStep("Phrase%phrcnt") => void;
};
call SCMGR_SetSceneBackground("classroom.png") => void;
call SCMGR_SetMusicTheme("theme classroom.wav") => void;
call SCMGR_AddCharacterFigure("zina", "normal", 1011, 1145) => void;
call SCMGR_AddCharacterFigure("zina", "smile", 1011, 1145) => void;
call SCMGR_AddCharacterFigure("zina", "happy", 1011, 1145) => void;
call SCMGR_AddCharacterFigure("zina", "smug", 1011, 1145) => void;
call SCMGR_AddCharacterFigure("zina", "laugh", 1011, 1145) => void;
call SCMGR_QuerySoundEffect("zina-hello.wav") => void;
call SCMGR_QuerySoundEffect("zina-chuckle.wav") => void;
call SCMGR_QuerySoundEffect("zina-okay.wav") => void;
call SCMGR_QuerySoundEffect("zina-cu.wav") => void;
};
A scene script is put inside the src folder and must be prefixed with "sc_". So, if you have a scene "Office", the script file must be named "sc_office.dnys". Then you put just the name Office in the main.dnys' arrSceneList array.
array arrSceneList string 5 (
"Train",
"Classroom",
"Restaurant",
"Office",
"Outro"
);
You can also specify some configuration settings via the config.dnys (derived from the config.dnys.default):
# Game settings config script file const WND_RES_X int <= 1920; const WND_RES_Y int <= 1080; const WND_WINDOWED bool <= true; const INVALID_DX_HANDLE int <= -1; const KEY_RETURN int <= 13; const KEY_SPACE int <= 32; const KEY_MOUSE_NONE int <= 0; const KEY_MOUSE1 int <= 1; const KEY_MOUSE2 int <= 2; const GLOBAL_VOLUME int <= 10;
The VN framework can manage a lot of things for scene scripts:
- Dialogs
- Characters
- Interactions
- Sounds
- Custom key handling
- Custom drawing
- Background images
- Scene theme music
That's it for now. Feel free to check out further resources of the game:
Game page: https://danielbrendel.itch.io/aquanovel-game
Sourcecode: https://github.com/danielbrendel/aquanovel-game