Work In Progress: TC.ADV Game Engine

I may have bitten off more than I can chew with this side-project, but I’m attempting to write a game engine for creating Adventure Games of the Visual Novel variety.

Timecode JS

What sparked this was that I was working on a little script for my own convenience that lets me apply CSS3 transition and transform animations to web page elements via Javascript using SMPTE-style time-code “mark-in” and “mark-out” points instead of having to figure out the animation “delay” and “duration” in milliseconds for myself in order to synchronize things (I WILL be releasing that sometimes soon on GitHub).  One of the goals of that project was also to let me do pretty much the same kind of synchronized media manipulation I used to do with SMIL, only do it with Javascript, HTML5, and CSS3.  That led me to write an extension/module for it that added typical media player controls (well, as much as current HTML5 allows).  Once I had it playing synchronized media I also thought it would be cool if you could define sequences similar to the “chapters” you have on DVDs, where you can “play all” or go back and play a chapter all by itself.  That lead me to create another module for building chapters onto the Timecode script.

While coding how the Chapters worked, and in particular the “play all” function, I realized there was no particular reason they HAD to play in a linear progression.  Any chapter could theoretically be linked to another, which meant it would be possible to create “story branches” of linked chapters and offer the user options for which branch to show.  Well, from there it was a short step to thinking about how it could be adapted for game play!

Visual Novels

My first experiences with computer games were games like “Zork,” “Hitchhiker’s Guide to the Galaxy,” “Oregon Trail,” and the “Bard’s Tale.”  Of course I played the arcade games too, but it was the text-adventures and RPGs that were slower paced, relaxing, and more akin to reading a book.  Actually playing these games was very much like those old “Choose Your Adventure” or “Which-Way” books.  However, once console gaming took off, though, those other kinds of computer games were mostly left behind.  At least here in the West they were.  That type of game has survived and even thrives in one place in particular: Japan.

Generally they are called “Visual Novels” (abbreviated “NVL”) if they are mostly text with little user interaction beyond clicking to advance the story.  If there’s more player interaction and decision making it would be classified as an “Adventure Game” (abbreviated “ADV”).  If there are even more game elements, such as managing inventories of items or building character stats it would be a “Role Playing Game” (abbreviated “RPG”), and in Japan there is one particularly popular sub-type known as a “Dating Simulation.”  In fact that last category was the only type I’d heard of because Dating Sims make appearances in various Anime series I’ve watched.  In Japan there are a lot of media tie-ins between Manga, Anime, and Visual Novels – often featuring the same characters, drawing styles, and “bishoujo” (literally “pretty girl”) themes – and, fair warning, that includes “adult” themes (which may seem odd to Western sensibilities, but only because comics, animation, and computer games are almost exclusively marketed to children here).  Most of the Japanese games never get translated into English and the entire category of Visual Novel games is virtually unheard of in America.  However, that doesn’t mean they’re completely unknown and many of the same people who are into Manga and Anime have also discovered these kinds of games and a few popular titles have been translated and published here.

One thing that may be hindering proliferation of such games in the English-speaking world is the lack of software available for creating them.  I thought I should probably do some research and find out what the conventions of such games are, which features players and publishers want, and so on.  So I started looking around online for both free games to try out and game creation software that makes them.  This is what the landscape of NVL and AVD game creation software looks like:

SOFTWARE CREATES LANGUAGE LAST RELEASE SOURCE CODE PLATFORMS
Kiri-Kiri NVL, ADV Japanese 2010 Open Windows
Kage-Kiri NVL, ADV English None Yet Open Windows
NScripter NVL, ADV Japanese 2012 Closed Windows
ONScripter-E NVL, ADV English 2013 Open SDL
PONScripter NVL, ADV Russian 2011 Open SDL
Wintermute ADV English 2010 Open Windows
AGS ADV English 2011 Closed Win/Mac/Linux
Coldstone ADV, RPG English 2002 Closed Mac
Ren’Py NVL, ADV, RPG Mutli 2013 Open Win/Mac/Linux

The last one on that list is really the only one worth looking at in my opinion.  “Ren’Py” is a cross-platform game engine that runs on the Python programming language and is, itself, built on top of the “Pygames” game engine.  The name “Ren’Py” is a play on that Japanese name for the Dating Simulation “romance” games known as “ren’ai” games.  It also features a simple scripting syntax for creating games, and of course the ability to extend it with other Python programs.  Apparently more than 500 games have been created with it so far, and the license allows you to sell the games you create with it (if you want and can).  Another nice feature is the ability to port those games to Android devices and sell them in the Google Play store.

As good as it may be my intention wasn’t to find software to make a game.  It was to build an extension/module to my Timecode script that would be capable of making a game.  So I downloaded Ren’Py and some of the free games to see how these things worked, and whether my thinking that Web Technologies could do this was even accurate.

Baby Steps

After a couple days of hacking away on my code I’ve got the first steps of something semi-functional, though not yet playable.  I downloaded the Ren’Py sample game called “Moonlight Walks” published by American Bishoujo which is actually a remake of one of the first games ever created with Ren’Py.  A good starting point, especially since the game itself is basically “open source” and the image assets (artwork created by someone known as Mugenjoncel) are not compiled.  That allowed me to see all the images and audio files inside the game assets folder, which gives me a much better idea how the game is put together.

So how far have I gotten with this project?  The working name for this game engine module is “TC.ADV” (TimeCode Adventure) and considering I’ve only been dabbling away at it for a few days bits of it are coming together.  Here is a short screencast of the opening title sequence (aka the “splashscreen”) of “Moonlight Walks”  showing the original Ren’Py version on the left and my web version on the right. I should also mention these are literally running out of the same folder using the same image assets:

TC So what works so far?

Partial Preferences Screen has Display Preferences and Audio Preferences working!  Everything else is disabled/placeholder right now.  I’m purposely trying to make it look as similar to the original as possible (both the game itself and the interface).  The menus can, of course, be styled to look however you want with CSS (and I should note that some of the Ren’Py games do have really nice looking menus).

The Display can be set to “Scale” the game to fit the window no matter how big or small it is, to “Fit” in the window (shrink if not enough space or show at original size if there is), “Stretch” to fill the screen disregarding aspect ratio (this is how Ren’Py does fullscreen and distorts 800×600 games on a widescreen monitor), or a “Fill” option which treats the game screen more like a web page where backgrounds scale but game controls don’t.  You can also set the intended game screen size either in the main stylesheet or change it via Javascript.  The scaling is actually handled by the Timecode script.

The Audio Preferences offer global control of all HTML5 <audio> elements, providing a “Mute”, “Volume Down,” “Volume Up,” “Max Volume,” and volume level output indicator.  This is because the way I implemented <audio> you could create multi-track sound, but the elements themselves are usually hidden along with their control interface so I created a custom volume function that can take control of however many audio elements there are and gangs them together under one master volume control.  Pretty neat!  I also had to tweak my Timeline script so that it will actually play the audio clips properly across Firefox, Chrome, and Safari (I’m coding this on a Mac right now so I don’t know yet if it works in IE10 or not).  The same timecode functions that sync audio also control HTML5 video, which opens up even more mixed-media possibilities for games.

I should probably mention that I had to copy and convert the audio clips form the original “Moonlight Walks” to MP3 so they’d work in Safari and for some reason the TrueType font file for “DeJaVu” wouldn’t work, but the same font is available as a @font-face kit, which got it working.  The opening title sequence text in the original is done with PNG images, but my web version uses the actual font, but the video I posted above doesn’t really show how much cleaner and clearer that text is in the web version.  Speaking of which my test file is also coded for “responsive” design, meaning it adapts to phone screens and is “orientation aware” of whether it is in portrait or landscape mode.  It’s also coded for “app view” if bookmarked to the home screen on an iPod Touch, iPad, or iPhone.  I happen to know from my Ryuzine e-publishing webapp that any TC.ADV game will also be really easy to bundle as a packaged or hosted app for Android, Firefox OS, and Chrome OS too.

Ren’Py uses some things they call “Recipes” for some of the special effects or add-ons.  So far I’ve implemented the “Splash Screen,” “TV Static” effect, “Flash of Light” effect, and the “Analog Clock” (which can be used for real-time or game time indication).  However there are some visual effects Ren’Py can do that are presently not available with just Javascript, CSS3, and HTML5 (though some of the image manipulations are available in “bleeding edge” versions of Google Chrome “Canary” and Microsoft has their own implementations in Internet Explorer, so they will probably be possible to support in the future).  However TC.ADV is already capable of doing a lot of different animation techniques AND it can perfectly time and synchronize things thanks to the core “timecode” script which means scene transitions, cut-scenes, or much more “animated” games are possible.

The way I’m setting up the “label,” “scene,” “show,” character and image definition, and dialog methods is intentionally similar to that used by Ren’Py.  The character constructor uses all the exact same arguments that do the same things as in Ren’Py – including “side images” and targeting the character name to display in another box.  I want to reduce the learning curve between Ren’Py and TC.ADV and frankly their scripting method is pretty clean and easy to understand.  Here’s a comparison example (the latter example’s syntax could still change before I ever release this though):

Ren’Py CODE:

image bg meadow = "meadow.jpg"
image bg uni = "uni.jpg"

image sylvie smile = "sylvie_smile.png"
image sylvie surprised = "sylvie_surprised.png"

define s = Character('Sylvie', color="#c8ffc8")
define m = Character('Me', color="#c8c8ff")

label start:
    scene bg meadow
    show sylvie smile

    "I'll ask her..."

    m "Um... will you..."
    m "Will you be my artist for a visual novel?"

    show sylvie surprised

    "Silence."
    "She is shocked, and then..."

    show sylvie smile

    s "Sure, but what is a \"visual novel?\""

TC.ADV CODE

var bg_meadow = "meadow.jpg";
var bg_uni = "uni.jpg";

var sylvie_smile = "sylvie_smile.png";
var sylvie_surprised = "sylvie_surprised.png";

var s = new Character('Sylvie',{color:'#c8ffc8'});
var m = new Character('Me',{color:'#c8c8ff'});

label.start = [
    'scene(bg_meadow)',
    'show(sylvie_smile)',

    ['',"I'll ask her..."],

    [m,"Um... will you..."],
    [m,"Will you be my artist for a visual novel?"]

    'show(sylvie_surprised)',

    ['',"Silence."]
    ['',"She is shocked, and then..."]

    'show(sylvie_smile)',

    [s,"Sure, but what is a \"visual novel?\""]
];

“Port Of” vs. “Inspired By”

TC.ADV is NOT really a web-technologies port of Ren’Py and because of differences in capability between Python and Javascript they won’t be able to support all of the same functions and features and TC.ADV will never be able to play games created with Ren’Py.  The “Timecode” project on which I’m basing it already has a “chapter” system that utilizes arrays to build a “timeline” of events. What I’m attempting to do is write a module/extension to to my “timeline” animation script that can provide similar functionality to Ren’Py in controlling Visual Novels, RPGs, etc.  In order to make converting games between Ren’Py and TC.ADV and reduce the learning curve if you know one or the other I’m trying to make the Javascript variables and functions have similar names and formats.

Regarding the “Moonlight Walks” game I’ve used in the example above, I do plan to faithfully reproduce the game as closely as possible in TC.ADV format, and the license on the game appears to allow repurposing the material, but I do not plan to actually release a TC.ADV version of the “Moonlight Walks” game.

 Stay Tuned!

Seriously, this is how far I got with it in less than a week.  But I have a three other higher-priority (paying) projects coming up so I’m going to have to step away from this for a while, but I’m feeling a lot more confident about it today than I was a week ago!  When I’ve got a buggy but functional version I’ll put it up on GitHub and post a big, fat announcement here.

Update 7/13/13

I stole a little more time to work on this project and think I’ve pretty much hashed out all the corresponding TC.ADV methods of doing the Ren’Py type stuff.  So here is where it is at now in addition to the stuff mentioned above:

The original “Timecode” script uses either a function with a series of “keyframe” calls and a “play” control or it loads a “chapter” array of animation calls and then plays through them.  The TC.ADV module, however, generally needs to iterate through the array one item at a time in response to user interaction, which leads to:

Click-Throughs – typically these sorts of games display a line of dialog, change an image, etc. and advance through the script as the player clicks to load the next item.  I have that function mostly working now so it loads the dialog and changes the images as you click through, but it doesn’t always go where it is supposed to at the end of a “label” section so I need to fix that.  This is really the core function of such a game.

Game Logic – Ren’Py supports regular Python code for setting and retrieving variables and other Python functions.  TC.ADV, of course, can do the same thing in Javascript, but implementing it within the “label” and “menu” blocks isn’t very intuitive in that it requires dealing with the same sorts of functions but the syntax is necessarily different, but if there’s a cleaner way to accomplish it it hasn’t dawned on me yet.  The main point is that it works.

So what’s left?  Well I need to get the core “click through” function going where it is supposed to, and make sure my menu “jumps” are actually working properly too (they’re kind of part of the same thing).  I’ve got the “scene,” “show,” and “hide” shortcut functions so they’ll actually show or hide the named image but none of the transitions are in place yet (though they can also be called directly via the underlying “Timecode” animation functions so it’s mostly a matter of creating a function that calls another function properly).  I also need to get back to the “Preferences” screen and get the rest of those items that are currently placeholders to actually work.  But it’s coming along!

Update 7/15/13

Not too much time to work on this project right now but sometimes the best way to shake an idea out of your head is to just get it down and see if it works.  On that note I now have a functioning “Text Speed” option on the Preferences section that works in a very similar fashion to the Ren’Py one.  Deconstructing a text string into component characters is trivial, but I wanted some way to keep any text styling (bold, italics, underline, etc.).  The solution I employed was to duplicated the string, strip all the HTML tags out of the duplicate, deconstruct and incrementally display the duplicate’s characters, then replace the reconstructed string with the stored one that still has HTML tags in it.  So while it’s building the dialog string it’s just text, but when it’s done it applies any styling back to the string.  Feels like a hack, but it works.  However if Text Speed is set at “max” it doesn’t bother tearing the dialog strings apart only to instantly reassemble them (what would be the point?).  That’s all for today!

Update 7/19/13

I figure if I keep plugging away at this and try to get at least one piece working eventually I’ll have something playable.  Well I finally got the “Menu” choices that appear within the dialog flow to work.  What made it particularly tricky was that I wanted to support a syntax as similar to Ren’Py as possible.  As a point of reference here is what a Ren’Py menu block would look like:

menu menu_1 :
     "I go left"
     jump went_left

     "I go right"
     jump went_right

While I did get it to work it’s technically not a menu object it’s just a menu-like array pattern similar to the Label Block pattern:

menu.menu_1 = [
     ['','I go left'],
     "jump(went_left)",

     ['',I go right'],
     "jump(went_right)"
]

The script recognizes it as a menu by inference, but it can’t actually be certain the pattern really is a menu.  That kind of annoys me so I also added a Menu() constructor that takes an array in the same pattern.  The advantage of the latter is that it actually IS an instance of the “Menu” object so the script can always be absolutely certain when it encounters one that it is, indeed, a menu.  As you can see the syntax is still pretty similar:

menu.menu_1 = new Menu([
     ['','I go left'],
     "jump(went_left)",

     ['','I go right'],
     "jump(went_right)"
])

It feels kind of convoluted just to get a syntax similar to the “Label” blocks and, of course, similar to the Ren’Py Python code, but in the end it does work.  However it is making me wonder if I should just abandon trying to make coding similar to Ren’Py and do things in whatever way makes the most sense in Javascript.  I’ve often heard it said that people too often try to make Javascript conform to the conventions of some other language and I’m starting to feel guilty of that myself.

I also got part of the “Auto-Advance Time” option on the Preferences Screen working.  It takes the setting and I have a function that will step through the “Label” block on an interval.  But it doesn’t presently stop when it hits either a Menu Block or the end of a Label Block.  I started working on it before I tackled the Menu Block so now that I have that in place (and know what to detect) I should be able to get the Auto-Forward Time function to also recognize a Menu and stop.  But that’s a brain-teaser for another day.

Update 7/24/13

I suddenly realized that the core of this thing requires a browser that supports HTML5 and CSS3.  So there’s really no point in thinking about backwards-compatible code for older browsers.  I also remembered that HTML5 introduced an input type=”range” for making settings sliders and so I updated the Preferences Screen so it has sliders for Volume, Text Speed, and Auto-Advance Time (just like Ren’Py has) and thankfully the functions they target also became much, much simpler too.  Next step is to update the Menu Constructor so you can define slider controls in addition to the list options it already supports for “transient” menus.  I know these slider controls don’t work in Android 2.x or iOS 4.x but those are approaching “legacy” status now and I tested the sliders in iOS 5.x and they work (did get them to slide on Android 4.x with some difficulty and it didn’t seem to activate the function – need to investigate further).  I’m also in the process of overhauling the default HTML document structure around the Ren’Py model of a “Master Layer,” “Transient Layer,” and “Overlay” layer.  But, of course, now it’s back to the real world to work on other stuff. 😉

Update 7/28/13

When I’m working through an idea like this I’ll often just create a <script> block in the HTML and work with Global variables because, well, it doesn’t really matter when you’re just screwing around and it also eliminates any scope issues.  But once I get code that is working and want to organize things better I move them into a name-spaced object and try not to pollute the Global space.  But it’s also easy to get a bit of tunnel vision and no longer see the forest for the trees in this process.  Which is how I completely missed the fact that I had associated the publicly-exposed “Menu” object with an anonymous function that, in turn, called the actual (private) Menu Constructor function.  When I called this from another script outside the name-space the arguments would pass through the anonymous function to the private object.  So when my arguments passed through the anonymous function the scope of “this” was lost and defaulted to the Global space – thus polluting it with my Menu instance objects.  Once I realized what was going on (which unfortunately took me all day and a ton of unnecessary reading on scoping “this” with bind, apply, call, and curry) I restored the scope of “this” to the actual Menu Object I was creating and I can move forward again.

Update 7/30/13

Added functionality for “Ruby Text” (the small text above or to the left of kanji that provide the pronunciation or description).  In the process I also updated the say() function so it allows you to target dialog or dialog menus to any in-page container with an ID.  I’m not sure of the usefulness of it, but I’ve seen one game that involved a secondary screen that represented text messages sent to the player by characters in the game and this alternative targeting could definitely be used for something like that.  Also created a “hpunch” and “vpunch” animation that can be applied to any element you want to shake.  It can also be called inside the loopAnimation() function if you want to create an earthquake and extended the loop function to allow durations after which it automatically stops looping (I felt that duration was more useful and flexible than number of loops since some animation sequences may be longer than others).  Exactly how I’m pulling animations into scene() or show() in the context of a “transition” (which is how they’re used in Ren’Py) is a problem for another day.  Still no idea how close (or far) I am from having something playable to post online.

Update 8/14/13

I just found out someone else HAS actually gone down this road before and created a Visual Novel Javascript inspired by Ren’Py called “JS-VINE.” In fact the the Ren’Py sample game “The Question” has already been reproduced with it.  If you are just doing a basic game and are fairly comfortable with Javascript code this may be of use to you and I see some game devs are already using it for demos on their websites (and, of course, this is available on GitHub right now, I’ve yet to drop any TC.ADV code people can use).

However I think JS-VINE and TC.ADV are approaching this concept from slightly different directions.  The JS-VINE “readme” file says, in part, “It is not meant as a replacement for Ren’py, nor is it intended to do everything that Ren’py does. I have tried to make it general enough to do a variety of simple VNs, but my main purpose was to adapt a single visual novel to the web.” In contrast I am trying to make TC.ADV do everything Ren’Py does (as nearly as is possible given they are different languages and Javascript does not have file system access).  It also appears that (aside from audio) JS-VINE is more focused on vanilla CSS and JS with accommodations for legacy browser while I’m targeting modern browsers to leverage HTML5 and CSS3 effects.  And, lastly, I am going out of my way to make the TC.ADV syntax as close as possible to Ren’Py to make adapting a project to/from more a more straight-forward process.  Hopefully the Internet is big enough for two such projects 😉

Update 8/17/13

After picking through the JS-VINE code I’ve already pulled one good idea.  So I rewrote my version of the Character Constructor so it can now take a second parameter as an object holding the arguments.   Then I added in the property that lets you use an already defined character as a template when creating a new one.  What this means is you can define a character’s arguments two different ways – the following two lines are equal:

var s = new Character('Sylvie',{color:'#c8ffc8',show_two_screen='true'});
var s = new Character('Sylvie','#c8ffc8','','true');

The empty quotes in the second example are because this isn’t defining the “side_image” argument.  The “object” method (top example) is more flexible but more verbose.  The “string” method (bottom example) is less flexible but requires less typing.

Update 8/31/13

Decided to focus on recreating the Ren’Py sample game “The Question” and am a bit further along in having an actual playable game.  At least you can click through to incrementally load the dialog and the “scene” and “show” functions are now partially working (they currently won’t let you target custom layers).  I still haven’t written the “jump” function, so the in the Test Video below it goes up to the point of the first choice menu and, while each option does trigger the “jump” function that function is currently empty so it doesn’t actually DO anything yet.

TCADV_480p

(In the video I just ran the Ren’Py app next to TC.ADV running in Safari and clicked back and forth between them while recording a screencast)

As I had initially been building off of the “Moonlight Walks” game I had assumed that player choices appeared in the dialog box by default.  Apparently in Ren’Py the default is for them to appear as buttons in the middle of the screen.  Obviously, from the video above, I got TC.ADV to do the same thing but I’m not very happy with how convoluted it is within the game script.  The Menu call has to be nested inside of an anonymous function to prevent the choice buttons from being created in the “centermenu” container as soon as the “label” is loaded so it ends up looking like this:

label.start = [
. . .
	function() {
		menu.menu1 = new Menu([
		['',"... to ask her right away."],
		'jump("rightaway");destroy("menu1")',

		['',"... to ask her later."],
		'jump("later");destroy("menu1")'

		],'centermenu','menu','','menu1');
	},
. . .
]

Instead of looking like this:

label.start = [
. . .
	menu.menu1 = new Menu([
	['',"... to ask her right away."],
	'jump("rightaway")',

	['',"... to ask her later."],
	'jump("later")'
	]);
	},
. . .
]

Which creates a choice menu that does and says exactly the same things, but appears within the dialog box where the rest of the game text appears. I think what I may need to do is rewrite the Menu Constructor (yet again) so the actual building of the menu into the DOM doesn’t occur inside the constructor but via some separate function that can be called on demand.  Obviously Game UI menus created with it (like the one on the Start Screen) would be instantiated immediately, but the Choice Menu within the game needs to be instantiated only when the user action calls for it.

Initially I had also thought the At() function was just going to be a dummy stand-in for the Ren’Py “at” syntax, but it ended up having an actual purpose.  The scene() and show() functions run all calls through it to “normalize” any position parameter to the CSS syntax for positioning background images.  The Ren’Py syntax is pretty much the reverse, and also its default positioning translates to “center bottom” whereas the default CSS positioning is “left top” and Ren’Py uses “truecenter” which equals “center center” in CSS.  So the At() function now resolves any Ren’Py positioning syntax to CSS.  Oh, and it also automatically calculates positioning by percentages to pixels.  One of my personal annoyances with CSS background positioning is that using percentages doesn’t work the way you intuitively think it should work.  Not only do percentage positions change the reference point, more often than not they won’t actually change the position of the image at all.  Seriously, if you don’t know what I’m talking about take a look at this page, which is about the best explanation I’ve seen written about it.  I don’t think I really need an additional function to calculate out the reference point since you could just use the Timecode.JS existing “track” animation (which uses CSS3 “translate” and takes other reference points as the “origin” parameter).

Update 11/27/13

I wish I had more time to work on this project and I know I should really get all the core functionality working before I start thinking about bells and whistles, but I’ve been playing around with the idea of adding a 3D option.  Over on the YouTube website they’ve been offering 2D to 3D conversion of short videos for a while now (meaning the original source material doesn’t need to have been shot in 3D).  I thought it would be neat to add similar capabilities to TC.ADV, just because I can ;).

Cross-Eye 3D

The first shot at this was the easiest – good ol’ “cross-eyed” 3D where you create the illusion of depth by viewing two similar images side-by-side.  Here is the test image (click to see full size):

questionCrossEye

Any of these 3D viewing methods will require one image for the left eye and another for the right.  The layers are already subdivided into a foreground and background, but due to the limitations of CSS a “dissolve” requires using two sub-layers, so the background has a “bg0” and a “bg1” DIV inside it.  Each of those can then just be used for the left eye, but a “bg0r” and a “bg1r” need to be created for the right eye and anything that happens in the one has to be echoed into the other – though slightly offset (one direction for the background and the other way for the foreground).  If/when I add a 3D viewing option the program would handle all this behind the scenes – programmatically creating the additional layers with offsets and echoing the contents and effects to them (contents is easy, echoing the effects may be another matter).  The dialog and menu items would also need to be echoed to new layers.  In this example the text isn’t actually offset at all, which maintains its readability.  The nice things about this method is it’s full color and the depth-effect is awesome and it works across browsers and platforms.  The downside is that your eyes will go buggy if you look at stuff cross-eyed too long.

Anaglyphic 3D

So what about old-fashioned anaglyphic 3D (the red/blue glasses kind)?  That’s fairly easy to pull off as well, using CSS3 Filter effects.  That’s right, the images below are the exact same images in the examples above, with the 3D filter effects being applied by the browser on-the-fly.  The downside is that those are pretty new and only the latest WebKit-based browsers can use them, plus all the other downsides of anaglyph images – mainly the color-shifting and the fact color images don’t work very well for the effect in the first place.  Nonetheless here is the result (again, click for full size):

Question3DChrome

This method actually gets a little more complicated because now you need THREE layers: left (red), right (blue), and the original.  The color layers are created by applying CSS Filters like this:

#bg0 {
-webkit-filter: grayscale(1) contrast(1000%);
}
#bg0-left {
-webkit-filter: sepia(1) hue-rotate(180deg) saturate(10) opacity(.5);
left: -1.25%;
}
#bg0-right {
-webkit-filter: sepia(1) hue-rotate(300deg) saturate(10) opacity(.5);
left: 1.25%;
}
#fg0 {
-webkit-filter: grayscale(1) contrast(1000%);
}
#fg0-left {
-webkit-filter: sepia(1) hue-rotate(180deg) saturate(10) opacity(.5);
left: .5%;
}
#fg0-right {
-webkit-filter: sepia(1) hue-rotate(300deg) saturate(10) opacity(.5);
left: -.5%;
}
#dialog p {
text-shadow: 3px 0 rgba(255,0,0,0.5), -3px 0 rgba(0, 204, 255, .75);
}

So, I have a furthest back layer that I’m desaturating and bumping up the contrast 500% gives a nice grayscale manga look and 1000% looks like line-art (you don’t have to do this, of course, but it makes the depth-effect more pronounced since the overlays are kind of milky, and full-color anaglyphs kinda suck).  Then I duplicate the content on two layers above it, each set to half-opacity.  The hue-rotate adjusts the sepia color overlay effect to another color – in this case a magenta-red and a light blue (you could easily adjust these rotations to best match the other anaglyphic color sets commonly used for this sort of 3D – I admit these colors might not be spot-on, I just ball-parked them.  Some fine-tuning might improve the effect.).  So you have a black and white image at the back and slightly offset, semi-transparent blue and red versions overlaying (and by experimentation the red layer needs to be on top of the blue layer or the effect isn’t as pronounced).  The direction and amount of the offset determines the depth-effect, and could easily be tied to a slider range control so end-users could fine-tune the effect to their liking.  As you can see the offsets are not very much – just .5% – 1.25% is enough.

I haven’t actually implemented any of this in the TC.ADV code yet.  Setting up the architecture of the HTML to accommodate it isn’t a problem, and if 3D-mode was enabled it could even build the 3D layers on demand.  I’ll have to see how intercepting the animation commands and duplicating them to the those layers with the proper filter effects applied actually works.  I also don’t know whether this should be a feature the players can enable or if the availability of it should be part of the publisher’s configuration – and I have no clue if there is even any interest in such a feature.  But if there is it’s far easier to anticipate it at this point than to try and retrofit it later.

Update 02/22/2016

Ok, obviously I haven’t revisited this little project in YEARS.  Part of that was because of a massive rewrite of my “Ryuzine” publishing platform project and then some paying gigs after.  Given that I don’t even play ADV/NVL games I don’t personally have a lot of motivation to complete TC:ADV, but I would like to do so at some point.

In the meantime other people more motivated than I have moved ahead, not just with HTML5-based ADV/NVL engines, but ones that specifically ease the conversion process from Ren’Py.  Go check out the LemmaSoft Forums for details, especially if you need something workable today.

Actually one of the things that contributed to my halting work on TC:ADV was questioning whether or not I should even bother trying to make the syntax in any way similar to Ren’Py.  Would it be helpful to someone familiar with Ren’Py in programming a TC:ADV game, or – because it would be similar but not the same – just end up confusing people?  It started to feel like a round peg in a square hole problem – I was trying to force Javascript to act like Python and there is really no good reason to do that!

Technically it would be a lot easier to just write a “converter” that would take in the script in one format and output it in another.  For example, an extension for Ren’Py that could rectify the special effects that can’t translate from Python to CSS3 and output the TC:ADV files, or conversely read in a TC:ADV Javascript and convert it to Python for Ren’Py.  It should also be possible to create a converter for TC:ADV that could output Python, but it would need a server-side technology to write any files.

Ah, but I’m getting ahead of myself again!  What I really need to concentrate on is getting TC:ADV up and running so it can create a playable NVL or ADV game (and worry about RPG and DS functions later).

Ren’Py still requires that you use a text/code editor to actually put your game together, so I would also like to create an authoring webapp for it that has a dead simple “drag and drop” UI and makes it possible to create a game without having to know how to code anything (but, of course, still offer raw code editing to those who do).

My biggest barrier against moving ahead on TC:ADV, though, is that it’s hard to justify the time and work it needs when there’s literally no money in it.  Nobody is paying me to make it and with free, open-source options out there (like Ren’Py) it’s unlikely there’s any money to be made on the authoring program either.  Monetizing webapp games presents it’s own challenges, though I do have some ideas about how that might be implemented.  But I have to build and test the game engine first.  In my spare time.  For “fun.”

In other words, it is going to be a while. :/

← Previous post

Next post →

1 Comment

  1. kmhcreative

    On a related note, just how seriously do some people take these sorts of games? This article will give you a glimpse: http://www.huffingtonpost.com/2014/01/21/loveplus-video-game_n_4588612.html?utm_hp_ref=technology

Leave a Reply


Menu




Search

Posts

About

Comment1

Contact

Share

Share this On:

Google+ Reddit Stumble It Digg this! LinkedIn Pinterest RSS Feed E-mail Link!