-
Notifications
You must be signed in to change notification settings - Fork 0
Scenes
Scenes are frames in a visual novel game. They typically contain a background image and character dialogue. In RenJava there are several types of scenes such as;
- AnimationScene - Contains a video instead of an image which plays in the background.
- AutoPlayScene - Automatically displays and runs the next scene after a set duration.
- ImageScene - Your standard visual novel scene. Background image and a textbox, both of which are optional.
- InteractableScene - A little more complex of a scene, does not automatically end.
- ChoiceScene - Contains choices for the player to select.
- InputScene. Contains an input field.
In order to use and display the scenes you will have to create a story first. The init()
function is then used to add scenes the story. I like to view stories as chapter and character events. Stories handle and map scenes to display and run them in the proper order. You will also have to map the story to the framework.
public class MyStory extends Story {
public MyStory(String id) {
super(id);
}
@Override
public void init() {
// Inside this function you need to add your scenes to the story.
this.addScene(RenScene scene);
}
}
To register and map the story to the framework, simply create an object instance of the class.
public class MyRenJavaClass extends RenJava {
...
@Override
public void createStory() {
new MyStory("my-story");
}
}
There are also generic scene functions which can be used to control how the scene plays.
/**
* Creates an event handler to execute when a scene starts.
* @param sceneInterface Code to execute.
* @return The modified RenScene.
*/
public RenScene onStart(SceneStartInterface sceneInterface) {
this.startInterface = sceneInterface;
return this;
}
/**
* Create an event handler to execute when a scene ends.
* @param endInterface Code to execute.
* @return The modified RenScene.
*/
public RenScene onEnd(SceneEndInterface endInterface) {
this.endInterface = endInterface;
return this;
}
/**
* Create an event handler to execute when a menu is built not rendered.
* @param buildInterface Code to execute.
* @return The modified RenScene.
*/
public RenScene onBuild(SceneBuildInterface buildInterface) {
this.buildInterface = buildInterface;
return this;
}
Here is some examples of how you can use these functions.
ImageScene scene = new ImageScene("1", nar, "After some struggle and rolling out of the bed. I make my way into the town.");
scene.onEnd(event -> {
// Prevents the engine from advancing to the next scene.
event.setAutoPlayNextScene(false);
// Start next story.
RenJava.getInstance().getPlayer().startStory("next-story");
});
scene.onStart(event -> {
// Start music to set the mood for the scene. Sometimes it is best to set music for when the story starts.
RenJava.getInstance().getTracks().play("happymusic.mp3", true);
});
Like said previously, the image scene is your standard VN scene. It contains an image and character dialogue. Note, both the image and dialogue can have null values.
Below is the current API documentation which explains some of the parameters needed to create an ImageScene. All RenScene's need to be in a story to be properly rendered and handled by the engine.
/**
* Creates an ImageScene object representing an image scene in the RenJava framework.
* An image scene is used to display an image and text associated with a character.
* Image scenes are typically used to present visuals and dialogue during gameplay or narrative progression.
*
* @param id The ID used to identify the scene.
* @param character The character who is talking. Pass null if no character is talking in the scene.
* @param dialogue The dialogue of the character. Pass null or an empty string if no one is talking.
* @param backgroundImage The background image loader for the scene.
*/
public ImageScene(String id, @Nullable Character character, String dialogue, @Nullable ImageOverlay backgroundImage) {}
Some of the parameters can be handled to accept null. Character and ImageOverlay can be null.
public void init() {
// The Character parameter is null which means the textbox nor the dialogue will be rendered.
addScene(new ImageScene("1", null, "Dialogue", new ImageOverlay("image.png")));
// The image is null which will result in a black box being rendered instead.
addScene(new ImageScene("2", character, "Dialogue", null));
// The image was not specified so the engine will use the previous valid image.
addScene(new ImageScene("1", null, "Dialogue"));
}
You will need to use an ImageOverlay to load an image onto a scene. Images should be located inside the images folder, /game/images/
. You can load images from a specific directory, but it's not recommended.
public void foo() {
// The string is the image path from the "images" directory.
ImageOverlay image = new ImageOverlay("image.png"); // The file location would be, 'MyGame/game/images/image.png'
image = new ImageOverlay("intro/image.png"); // The file location would be, 'MyGame/game/images/intro/image.png'
image = new ImageOverlay("game/other/", "image.png"); // The file location would be, 'MyGame/game/other/image.png'
}
AutoPlay scenes are the same as an ImageScene. Once the scene finishes playing which is set by the duration, the next scene is automatically played.
Below is an example of the API. It is the same as an ImageScene with the addition of a duration. The duration is the duration until the next scene is played. The duration is measured in milliseconds. 1000 milliseconds ~ 1 second.
/**
* Creates an AutoPlayScene which automatically plays the next scene once timer ends.
* The parameters are the same as an {@link ImageScene}.
*
* @param id The ID used to identify the scene.
* @param character The character who is talking. Pass null if no character is talking in the scene. If null, a textbox will not be rendered.
* @param dialogue The dialogue of the character. Pass null or an empty string if no one is talking.
* @param backgroundImage The background image loader for the scene. Pass null to render a black screen.
* @param duration The duration of the scene.
*/
public AutoPlayScene(String id, @Nullable Character character, @Nullable String dialogue, ImageOverlay backgroundImage, int duration) {}
Below is an example for how it would be implemented into a Story.
public void init() {
// First create the scene.
AutoPlayScene scene = new AutoPlayScene("1", character "Dialogue", new ImageOverlay("image.png", 3000)); // After 3 seconds the next scene would play.
// Add the scene to the story.
addScene(scene);
}
InteractableScene is a scene which the engine does not automatically handle. These events have to be ended by game logic. The point of these is to allow user interaction. A good example would be a map. A map may have different locations and areas. A player would have to click on a specific area to progress. These will be adapted to support mini games in the future.
The API is very bare bones as it's meant to be dictated by the developer. The only things required are an ID and a background image.
/**
* Creates an InteractableScene object representing an interactable scene in the RenJava framework.
* Interactable scenes are scenes that allow player interaction, such as maps and playable areas.
* These scenes typically enable players to move between locations and trigger character events.
* Unlike image scenes, InteractableScene does not automatically end. You need to add your own code to end these scenes and trigger events.
* To handle events, make use of the {@link me.piitex.renjava.events.EventListener} interface.
*
* <p>
* To create an InteractableScene, provide a unique identifier (id) and the background image for the scene.
* The id is used to identify the scene and can be used to retrieve the scene later.
* The background image sets the visual background for the scene.
* </p>
*
* <p>
* Example usage:
* <pre>{@code
* ImageLoader backgroundImage = new ImageLoader("background.png");
* InteractableScene scene = new InteractableScene("myScene", backgroundImage);
* }</pre>
* </p>
*
* @param id The unique identifier for the scene.
* @param backgroundImage The background image for the scene.
*
* @see RenScene
* @see Overlay
* @see EventListener
*/
public InteractableScene(String id, ImageOverlay backgroundImage) {}
UNDER CONSTRUCTION
UNDER CONSTRUCTION
Video scenes is the first animation implementation for the framework. They allow you to add pre-rendered animations in form of a scene. With the current state of JavaFX and even Java these have severe limitations.
Encoders: Encoders are the file format for media. Some media may have the same file extension but use different techniques to play. H.264 and H.265 have the same file extension '.mp4' but H.265 is an updated version of H.264.
All media here are in the form of video files.
Video scenes can only support a couple encoders which are outdated. To make things worse, different operating systems support different encoders.
Supported Encoders
- H.264 (AVC)
- H.265 (NEVC)
- VP6
The more supported encoder is H.264 but is outdated by the more commonly used HEVC. The issue with HEVC is it's not supported by Windows by default. I will be looking into other video libraries for better solutions. For now use H.264 and if you have media that is in a different format you can re-encode it using programs. ShutterEncoder is the one I use.
Creating a video scene is the same to most other scenes.
public void init() {
VideoScene scene = new VideoScene("id", "path/to/media.mp4", loop, fitToContainer);
// The 'path to media' works the same way as images. All media must be inside of the 'media' directory.
// If you want to the scene to loop pass true for the first boolean.
// 'fitToContainer' makes the video scale to the window size. Useful if the video does not match the resolution of the game.
VideoScene scene = new VideoScene("1", "vid.mp4", true, true);
// Video scenes can also have dialogue.
scene.setDialogue("This is dialogue inside of a video scene.");
scene.setCharacter(character); // You need a character or the dialogue won't render.
addScene(scene);
}
All media should be placed inside of the 'media' directory. You can create subfolders for better organization. For example, lets say you made an intro video, you can put this inside of `intro/intro.mp4'.
game
└─media
└─intro
└─intro.mp4
└─...
If passed to true, the video will be set to the window size. This is only useful if the video has a different resolution to the games resolution.