Keep in mind im merely exploring the idea, im not saying "thats what im making right now".
Im trying to evaluate the feasibility of it and its worth, and youre really helping so thanks!
And that's precisely the reason why I'm saying all this. Not to discourage you, but to force you to think deeper than the surface.
Thinking "I'll make a game engine that will looks like this" is easy, but once you start, there's so many elements that appear, but that were forgot by your thoughts, or that were thought too superficially. So, I'm talking about them, for you to have a better idea.
Ok thats my bad here for using the word preview, i mostly meant a scene builder. If you're familiar, something like Tiled. But of course, more geared towards visual novels. And since most stuff would just be 2d images, text, buttons, etc., you can have "preview/idea" of how its going to look.
But isn't this a part of what limits the freedom offered to the creator ?
In order to offer a preview of the scene, you need to know what will be on that scene. This imply that those elements will be defined through hard coded values. They can eventually be chained and so not limited in number, but they'll still be limited in capability.
Take an average Ren'Py scene relying on sprites by example:
Python:
label whatever:
# Display the scene background
scene living room
MC "Finally at home, I can't wait to drop the news."
# Show one of the character, in casual clothes and neutral mood,
# place her at the right of the screen
show mother casual neutral at right
MOM "Hello baby, how was your day ?"
MC "Good, I've been promoted today."
# The mother is now happy
show mother casual happy
# The usual "shake the sprite to express joy"
with shake
MOM "Wow, it's marvelous, I'm so proud of you."
MC "Thanks mom."
# The sister enter, wearing casual clothes and wondering what happened,
# place her at the left of the screen
show sister casual wondering at left
SIS "Why such commotion ? What happened ?"
# Move the mother sprite to the middle of the screen, she come closer to her daughter.
show mother casual happy at slideToMidle
MOM "Your brother have been promoted."
# The player was previously offered the possibility to prank the sister. If he did, she's angry.
if sisAngry == True:
# Seeing her mother praise her brother, while she said nothing about the prank, trigger
# sister's jealousy.
$ sisJealous = True
# The sister is not delighted by the news
show sister casual angry
SIS "That idiot, promoted ?"
MOM "Come on girl, you should be happy, he's your brother..."
SIS "He's an idiot who did [whatever the prank was]. I'm out !"
# Remove the sister from the scene
hide sister
MOM "You know what, baby ? Let's go celebrate this. Restaurant tonight !"
# The player decided to not prank the sister.
else:
# The sister have no reason to be jealous.
$ sisJealous = False
# The sister is surprised by the news.
show sister casual surprised
SIS "Wow !!!!"
MOM "I know, he really deserve this. Tonight, restaurant to celebrate this."
SIS "I can't go to a restaurant dressed like this, I need to change."
# Remove the sister from the scene
hide sister
MOM "Really, baby, I need to say it again, I'm so proud of you."
MC "It's nothing mom."
MOM "No, no. Don't sell yourself short, it's not everyone who's promoted after only two months at work."
[and so on]
How do you intend to express this with your engine ?
The number of dialog lines between two changes in the scene isn't constant. There's a temporary variation in the scene depending on a condition, and a flag value change. And of course, the same can be done without sprites, but by changing the whole image.
I don't say that it's not doable, but relying on a script language will always offer more freedom than relying on objects that would describe all atoms of the scene. Because it's probably how it should be with your engine, at least as you visualize it actually, something like:
Code:
class Image
# Name of the asset to show
IMAGE asset
# Coordinate where to place the asset
INTEGER x, y
# Effects to apply when displaying the image.
ARRAY effects
class NextAtom
# Condition for this atom to apply
???? condition
# SceneAtom object to use if the condition is fulfilled
POINTER nextAtom
class SceneAtom
# List of image objects present in the scene at that instant
ARRAY visual
# Dialog line to display at that instant
STRING dialog
# List of possible next atoms
ARRAY nextAtom
# list of variable changes - Right now, I have no idea how to express it.
ARRAY changes
Whatever haven't be thought beforehand will not be permit, because there's no entries in the SceneAtom object for it. This while with Ren'Py, anything can be added, whatever it is, precisely because it's fully described by the script.
Of course, your engine can possibly rely on C++ code to add what haven't been thought beforehand. But then, how your engine will know what image are used ?
Plus, one of the possible difference in the Ren'Py script can be the use of dynamical images. Instead of something like
show mother casual neutral
it could be
show expression "mother_{}_neutral.png".format( motherClothes() )
.
Then, the shown sprite will use a set of clothes that will depend on the corruption level of the mother.
Just this basic change, that is easy to implement with Ren'Py, need that you rethink totally the way you deal with the images. "SceneAtom.visual" becoming then a list of condition->Images. Something that make the development heavier.
And of course, with Ren'Py it suffice to change the code for "motherClothes" to add or remove a clothes set, and the change will automatically apply to the whole game. This while, with your engine, all the SceneAtom objects would have to be updated to achieve the same result. Once again, there's ways to avoid having to change everything, by defining a "ClothesSet" class by example, but it need to be thought beforehand.
The dynamism that make Ren'Py easy to use would be what make your engine hard to use. At least as you visualize it.
Or else you rely on C++ code to do this, what is perfectly possible and would then make your engine as easy to use than Ren'Py. But in such case you've to forget about the scene preview, because you'll never know what elements are present in the scene.
And in the end your engine would still be heavier to use, because needing a recompilation in order to have the preview. It's also what happen with Ren'Py, but the "compilation" time is way shorter, and the console make it possible to quickly jump to the scene you want to test.
This too is something you've to think beforehand: How to branch to a given point of the game, in order to only test that particular part ?
You could also create dialogs with branching choices in the editor, and you can attach those dialogs to scenes, so when you load that scene that dialog plays and (waits or not) for player input. You could then also attach events to a line in the dialog (switch background, end scene, custom event, whatever) that gets triggered by advancing the dialog. And a whole lot more of features and conditions to help shape out a visual novel and what not.
Here's what is possible with Ren'Py ; background switch, conditioned sprite, conditioned dialog lines, and conditioned branching as outcome:
Python:
# Generic "enter a gril bedroom" entry point.
label girlRoom( girl ):
# Use the right girl bedroom as background for the scene.
scene expression "{}/bedroom.png".format( girl.name )
# Greet the girl.
MC "Hello [girl.name]"
# If the girl isn't in her bedroom
if not girl.location == "bedroom":
MC "Well, I looks like a fool talking to an empty room."
# Go to the label handling her room when empty - because there's clickables
jump expression "{}_bedroom_empty".format( girl.name )
# Show the girl doing what she's actually doing, wearing clothes that match her corruption level.
show expression "{}/{}_{}.png".format( girl.name, girl.action, clothingSet( girl ) )
if girl.mood == "angry":
girl.sayer "Go away !"
MC thinking "I should probably leave before she become angrier."
# Return to the right hallway.
return
else:
if today - girl.lastVisit > 10:
$ girl.anger += 1
$ girl.updateMood() # Can be implicit if /anger/ is a property.
girl.sayer "Oh, so you remember that I exist ?"
elif today - girl.lastVisit > 5:
girl.sayer "Long time not seen, I thought that you forgot about me."
elif today - girl.lastVisit == 0:
girl.sayer "Hello again, to what do I owe the pleasure this time ?"
else:
girl.sayer "Hello [mc.name]."
# Go to the label that serve as hub to switch between the available scene
# for that girl in her bedroom, and handle the default scene if there's no particular
# event right now.
jump expression "{}_bedroom_hub".format( girl.name )
Not as simple as it looks, right ?
Perfectly doable with C++ code, but not as easily as it seem.
I don't think what im describing here is crazy talk.
Still thinking that way ?
And I insist on the fact that I don't try to discourage you ; at most I temperate a bit your enthusiasm.
While not interesting for me, such game engine can still be interesting for others. But you must understand that, when I said that it would be either more limited or more heavier than Ren'Py, it wasn't just a way of saying.
I dont have everything thought of and figured yet of course, i started thinking about this yesterday lol, [...]
I think that for now you should forget about the notion of "game engine", and focus on a VN library. Then you would be able to focus on what you expect from a VN engine, and develop the code for it. Later, once you've that code and the logic behind its use, it would be easier to come with an editor-like to make it easier to use.
And you should also accept, to some extend, that users would be limited in what they can do with it.
The last example I gave for Ren'Py code is perfect for a VN with free roaming... But I'm not even sure that there's more than on game that do it that way. What I mean is that even with an engine like Ren'Py, that do marvels when it come to dynamism and context handling, what could considerably speed up the development time, people limits themselves. So, the fact that they would use an engine that have limited capabilities wouldn't be much a problem for half of them.
Plus, like you would have started by the library, the editor-like and compilation process should be naturally ready to handle any extension. What would then overcome most of the limits for anyone who can code the said extensions.
It would still be heavier than Ren'Py, but this too never stopped people. There's VN made with Unity, so...
Hmmm, you are right 100% on everything here. This is definitely a challenge. The biggest problem here (especially for newcomers) is the "preview" part in the editor without having to close and re-open and re-compile everything and etc anytime you make a change for something like you described without taking away freedom. At that point its either we just dont allow that and you have to make with whats offered in terms or transform/animation events, or the editor would need a very good preview scene and at that point, might just as well make the editor run the engine.
Or you forgot about "preview" the way you visualize it. After all, the only engine that offer a preview is RPG Maker, yet only because maps are easy to handle.
What if needed for an effect is just an image, two if it's a transition like with my example. You can perfectly offer two default images, and test the effects with them. Add the option for the user to select the two images when the effect must happen in a particular context, and it would be a good enough preview. Either the effect works and look good, or it don't and it's not by placing it in the whole context of the scene that it would change.
What would matters the most is what I talked about above, a way to branch to a particular part of the game, in order to test it. And here all depend on how you make the editor. And from my point of view, the need to rely on an external IDE for the code is an error. You should also edit the code (not necessarily a whole IDE), this would permit to offer a fully optimized (in time) compilation.
That way, each effect or extension could be a snippet, and could have its own library (linked to the base library). What mean that you don't have to recompile all the effects/extension, just the one that have been changed. The others being unchanged, their library don't need to be recompiled.
As for the game part itself, it would follow the same principle. There's the main common part, that have its library, and every scene would be an independent library. That way you can add a "context block" in top of a scene, and for testing you just have to compile the main part (if it changed), the context block and the tested scene. Not only the compilation time would be way shorter, but the game would only contain the scene to test.
Then, when it's time to build the game, you assemble all the code parts in order to have a single library.