Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

MAKE YOUR OWN LASERDISC GAME WITH DAPHNE SINGE

by Karis (v1.0 – 10/2019)

Welcome !

This tutorial will show you how to create you own FMV game using Daphne SINGE. It is really simple
and quick. If you’ve got a simple 10 minutes movie ready, then you can probably be ready to play it
as a FMV in just a couple of hours ! You just need to tell Daphne where are the files and enter your
list of moves in my SINGE script.

A bit of History

Daphne is a laserdisc game emulator. It was created by Matt Ownby. It is called Daphne because it’s
the name of the princess in Dragon’s Lair. SINGE (which is the name of the dragon) is an add-on to
Daphne created by Scott Duensing (2006). It is a dll which allows, via a LUA script, to create new
Laserdiscs. A few games were ported by RDG. Mostly American Laser Games. But until now, nobody
released a new game from scratch (RDG did some, but never released them). Fire & Ice is the first of
its kind. I used a script from RDG and modified it in order to have all the needed ressources in one
single file. Now it’s your turn…

What do you need ?

- Windows : Daphne is available for OSX and Linux, but not the SINGE module at the present
time (and probably never).
- Daphne v1.14 (with SINGE module) included in Fire & Ice.
- A movie editing software (like Adobe Premiere) to edit your movies and check the frames.
- A text editor : Notepad is enough, but Sublime Text is better.

Files

- Format for the movies : m2v (MPEG2 with no sound)


- Format for the sounds : ogg (Ogg Vorbis)

General concepts

You game will be divided in Levels. Each Level will be divided in Scenes. In each scene you will declare
your moves, asking player to enter the correct move between frame X (Start), and frame Y (End). If
the player enters a wrong move (or no move), this will trigger a death scene and restart at the
beginning of the scene.
Limitations

- 65536 frames for all your videos. That means around 36 minutes at 30 FPS and around 45
minutes at 24 FPS.
- 10 Levels + 1 Secret Level.
- 10 Scenes in each Level (any number of moves within a level).
- 40 death scenes.

It is possible to have more of anything above (except frames), but it will require extra programming
so i won’t speak about this here.

Features

Your game will have these features without any programming (of course you are free to use them or
not) :

- Keyboard and Pad controls


- Movement Arrows and up to 3 Action buttons
- Special action MASH for button 1 : press repeatedly and fast the button to achieve this action
- Double actions for button 1 : you can ask the player to combine an arrow plus button 1
- Difficulty levels : Easy to Extreme. Easy mode has no MASH or DOUBLE ACTIONS. Harder
difficulty levels means less frames to enter your action and more mash to do.
- Selectable starting level and scene.
- Kid mode : No arrows, just button 1. The only input is the Action button.
- Movie Mode : just watch the movie without playing.
- Secret Level : a Special level, triggered in certain cases (does not count within the 10 level
limits).

Ok, i’m ready. Let’s go!

The creation of your game will be divided in 3 parts. Video editing, files preparation and SINGE
editing. In this tutorial i will cover the video editing part very slightly (there are plenty of good
tutorials for this all over the web).

Part 1: Video editing

Just a few notes and tips for this part. For a complete game you’ll need to create a few movies :

Title movie : this movie is the first one that will be played when you start the game. Of course
you can have just a static image than spans over a few frames. In Fire & Ice, this movie is called
title.m2v. Don’t make it too long because you can’t do anything while it’s playing.

Attract movie : it is a longer movie to present the story. It is longer because it will loop, waiting
for the player to start the game. You can have up to 3 different Attract movies (intro01.m2v and
intro02.m2v in Fire&Ice).

Menu movie : this movie will contain all the UI of the game

o A static frame for the option menu


o A static frame for victory
o A static frame for secret level (optional)
o A video for continuing the game
o A video for Game over (optionally a second one for « happy » game over)
o A video for announcing High Score
o A video for entering High Score
o An outro video for High Score

That’s a lot, but keep in mind that all of this is highly optional. You can have one 10s long static image
and use it for all these purposes. It will be nicer with some text and music though. Take a look at
menus.m2v in Fire and Ice.

Death movie : in FMV games, you die a lot ! All the death sequences are in this video. You need at
least one and up to 40. A good length for one death is around 60 frames, to give the player time to
breath between failures. Take a look at death.m2v in Fire&Ice.

Level movies : this is where the game is played. You need at least 1, and up to 10. In those movies the
first part can be declared as an intro and skipped with the push of a button. It is useful to have an
intro clip to present the action, but it’s highly optional.

Note that you can perfectly use a single video for all of this. Daphne will treat all your files as a
Laserdisc, so 1 or 15 files, it doesn’t make a difference. That said, Daphne has a lot of problems to
treat movies with more than 15/20 minutes. That’s why i choosed to split.

Part 2 : Files preparation

So now, it’s time to prepare the files for Daphne and SINGE.

- Go into Daphne/singe/ and copy the fire_and_ice directory


- Paste it (still in singe).
- Rename it with the name of your game
- Go inside your game directory and erase setupgame.singe
- Rename setupgameblank.singe as setupgame.singe
- Go inside the « dvd » directory and remove everything.
- Put your movies and sound files here.
- Go into the Daphne directory and copy fire_and ice. Bat
- Paste it
- Rename it with the name of your game
- Right click and choose modify (it will open the notepad)
- Inside you will find twice the name « fire_and_ice ». Replace it with the name of your
directory and save.

Last thing, you need to tell Daphne the index of your laserdisc :

In your game directory, open fai.txt

Fai.txt is the index of your virtual laserdisc. It tells Daphne at which frame it will find each video.
Remember that the total limit is 65536 frames. Apart from this you’re totally free to assign any value
you want. For Fire & Ice, i had to stick everything together because i’m dangerously close to the limit
(my total is around 65520 frames) : so for me, each video starts after the frame the previous one
ends.
Example : in my fai.txt, title.m2v is the first video. It starts at frame 0. The lenght of title.m2v is 292
frames. So i start my next video (intro01.m2v) at frame 293 and so on.

If you’re more reasonable than me (less than 45 minutes of video), you can add any gap as it doesn’t
change anything. Just take care to avoid overlaps : each video must start after the previous one has
ended.

Note : the order of the videos within the file is not important. Note the values you put there, as SINGE
will use them too.

Part 3 : SINGE editing

Now you are ready to create your game. It will be done in 3 parts. Go into your game directory and
open setupgame.singe, this is where you’ll do everything.

1) General settings :

The first few lines of the files are for the general configuration of your game. Only a few lines are
important to edit :

MYDIR = "singe/fire_and_ice/"

This is the path to your game. Just replace the fire_and_ice part with the name of the directory you
created.

dofile(MYDIR .. "globals.singe")
dofile(MYDIR .. "main.singe")
dofile(MYDIR .. "hscore.singe")
dofile(MYDIR .. "service.singe")
dofile(MYDIR .. "toolbox.singe")

Don’t touch those lines. This is where the script calls the other files needed by the program.

MovieFPS = 23.976

Choose between 23.976 and 29.976 (or any other value) depending on your movie.

SCOREMOVE = 700
BUFFMOVE = 300
SCORESCENE = 10000
DEATHPENALTY = 1000
SCORELEVEL = 50000
SCOREGAME = 250000
SCORESECRET = 1

Scoring. For now, you don’t really need to change all of this.
finalstage = 6

It is important to tell SINGE where the game ends. If you’ve got only one level, put 1 and SINGE won’t
try to search for a level 2. You can put a value between 1 and 10.

bAllowSecret = true

True or false. It will tell SINGE if you’ve got a secret level. If you do not have one, put false.

There are 3 ways to launch the secret level :

- Finishing the game without losing any life


- Finishing the game with one credit
- Special combination of keys during the intro menu.

2) Starting and ending frames for the various elements of the game

Here you will tell SINGE where to find the videos.

offsetTitle = 0
offsetIntro01 = 293
offsetIntro02 = 63755
offsetIntro03 = 0
offsetLevel01 = 2300
offsetLevel02 = 8959
offsetLevel03 = 18312
offsetLevel04 = 26127
offsetLevel05 = 33240
offsetLevel06 = 46082
offsetLevelExt = 57955

These are the frames where the different movies start. The values are the same than in fai.txt.

Note that i only have 2 intro movies, so for Intro #3 i put the Title movie (starting at 0). Also note that
my secret level is incorporated at the end of level 6. So for this one, i calculated the frame where it
starts.

offsetTitleend = offsetTitle + 291


offsetIntro01end = offsetIntro01 + 2005
offsetIntro02end = offsetIntro02 + 1760
offsetIntro03end = offsetTitle + 291

These are the frames where each intro video ends (in other terms, the lenght of the video). SINGE
needs to know this. Note that i shortened the actual lenght by 1 frame (for example Title video is
actually 292 frames but i put 291). It is because if you put the real last frame there will be a small
glitch. To avoid this glitch, shorten by 1

offsetLevel01Clipend = offsetLevel01 +1111


offsetLevel02Clipend = offsetLevel02 +2540
offsetLevel03Clipend = offsetLevel03 +128
offsetLevel04Clipend = offsetLevel04 +2058
offsetLevel05Clipend = offsetLevel05 +2829
offsetLevel06Clipend = offsetLevel06 +878
offsetLevelExtClipend = offsetLevelExt +815

These are the frames where the first part of each level ends. The purpose of this is to have a
cinematic clip introducing the events before the action. For example in my level 01, the cinematic
runs until frame 1111. During this time, a « skip » icon appears on the screen. If the player pushes the
action button, the program skips the part and goes directly to frame 1112. Of course if your movie
does not have a cinematic at the beginning, you can replace the value by « +0 ». In that case, the
action starts right away after the beginning of the level.

About frames : the program is written in terms of « relative frames ». Above, i spoke about frame
1111. That means « frame 1111 of the level 1 ». It is way more convenient if you have one video per
level, because when you will work with your movie editing software, you will see that the intro clip
ends at frame 1111. But for Daphne this is not really the frame 1111 (because of the index). Anyway,
just remind that you don’t need to calculate everything from the Daphne point of view, just put the
values indicated by your movie editor.

offsetMenus = 59955

This is the position of your menu movie (as in fai.txt).

frameOptions = offsetMenus +1

This the (relative) frame of the static image for the background of your option menu. When you call
this menu (Key 9), the program will seek the frame (59956 For Daphne, but 1 for you) of the menu
movie and stick on it until you exit the menu. Note that in the option menu you can change various
things like the starting level or difficulty.

frameCommands = offsetMenus +11

This is the (still relative, i will stop saying this now) frame of the static image showing the controls of
the game. When you hit « Action » during the menu, the program will seek the eleventh image of the
menu movie and stick on it for 15 seconds (showing a keyboard and a pad with the various
keys/buttons).

frameVictory = offsetMenus +21


This is the frame of the static image when you win the game. The program will stick a few seconds
there if you achieve the last level.

frameExtendedPlay = offsetMenus +29

This is the frame of the static image if you unlock the secret level (see above). The program will stick
there for a few seconds.

offsetContinue = offsetMenus +31


offsetContinueend = offsetMenus +285

These are the frames of the movie menu where the continue video (a countdown basically) is shown.
If you run out of lives the program will play this video and you can either push start to continue or do
nothing. In that case…

offsetGameOver = offsetMenus +286


offsetGameOverend = offsetMenus +536

These are the frames of the movie menu where the game over video is played. If you run out of lives
and choose not to continue then game over.

offsetGameOverAlt = offsetMenus +537


offsetGameOverAltend = offsetMenus +870

This is an alternate game over video (i call it the « happy one »). I use it for special case (victory, high
score). Of course if you’ve got only one game over just copy the same values as the previous item.

offsetNewHScore = offsetMenus +871


offsetNewHScoreend = offsetMenus +940

These are the frames of the movie menu where the high score is announced. Then it goes to the
following item.

offsetEnterHScore = offsetMenus +941


offsetEnterHScoreend = offsetMenus +1540

These are the frames of the movie menu where the high score is entered. Make it quite long to give
enough time to the player to enter his name. Then it goes to the following item.

offsetOKHScore = offsetMenus +1541


offsetOKHScoreend = offsetMenus +1614
These are the frames of the movie menu to validate the high score.

Notes about all those movies : in the menu movie, i use the terms « static images » and « videos ».
But if you look at my menu movie, you will notice that everything is made from static images. Some of
them are really short, some other very long (enter high score is just one image spanning over 600
frames). In fact the lenght of the video is a kind of timer. It could be a real video, but a static image
lasting many frames is ok too…

offsetDeath = 61571

This is the position of your death movie (as in fai.txt)

offsetDeath01 = offsetDeath
offsetDeath01end = offsetDeath +58

These are the frames of the death movie where the Death #1 is played. You can have up to 40 death
(in that case you need to declare them all the same way), and you need at least one. Note that i
shortened by 1 here too to avoid glitches. For the length, avoid to make it too short (because players
need to realize their mistake) or too long (because you die a lot in those games).

3) List of moves for each level, scene by scene

So, here comes the funny part. This is where your game comes to life. In this section, you will declare
all the legal moves, level by level and scene by scene. Remember that the limitation is 10 levels max
and 10 scenes per level (any number of moves per scene). What is a scene ? A scene is basically a
subpart of your level. When you die, you come back at the beginning of the scene. If you make all the
moves of a scene, you go to the next scene and and you won’t replay the previous scene in case of
death. We begin with level 1 of course…

TotalScenesLevel01 = 3

This is the number of scenes that will be played in level 1 in Fire and Ice. There are 3 scenes. Basically,
it tells the program not to search for a scene 4 if you don’t have one. Remember that you can have
up to 10 scenes.

function setupLevel01(thisSegment)

Don’t touch this line ! This is the function managing level 1

if thisSegment == SEGMENT01 then

Don’t touch this line ! This is the beginning of segment 1 (aka scene 1)
segmentStart = offsetLevel01Clipend + 1

This is where scene 1 starts. It always starts at the end of the intro clip so you don’t have to change
this value.

segmentEnd = offsetLevel01 + 3018

This is the end of the scene 1. When the program reach that frame, he will skip to scene 2 of the level
1.

totalMoves = 13

This is the number of moves within the scene 1.

move = nil; move = {}

Don’t touch this line.

move[1] = {}; move[1] = {1352, 1374, BUTTON1, 1, 0, 0}


move[2] = {}; move[2] = {1620, 1645, LEFT, 1, 0, 0}
move[3] = {}; move[3] = {1930, 1950, BUTTON1, 1, 0, 0}
move[4] = {}; move[4] = {2078, 2097, BUTTON1, 1, 0, 0}
move[5] = {}; move[5] = {2105, 2125, BUTTON1, 2, 0, 0}
move[6] = {}; move[6] = {2229, 2248, RIGHT, 2, 0, 0}
move[7] = {}; move[7] = {2280, 2310, LEFT, 2, 0, 0}
move[8] = {}; move[8] = {2363, 2383, ACTRIGHT, 2, 0, 0}
move[9] = {}; move[9] = {2560, 2575, RIGHT, 2, 0, 0}
move[10] = {}; move[10] = {2755, 2771, RIGHT, 2, 0, 0}
move[11] = {}; move[11] = {2870, 2890, LEFT, 2, 0, 0}
move[12] = {}; move[12] = {2900, 2920, LEFT, 2, 0, 0}
move[13] = {}; move[13] = {2980, 3015, MASH, 3, 0, 0}

This is the list of the 13 moves of the scene 1. Now let’s have a closer look for the first line and you’ll
know everything you need to know.

move[1] = {}; move[1] = {1352, 1374, BUTTON1, 1, 0, 0}

So this is a move. It is a kind of table, containing all the informations needed by Daphne.

.
move[1] = {}; move[1] =

This part tells that this is the move 1. Obviously you’ve got to fill this in order, and don’t forget there
are two « 1 » to put.
{1352, 1374, BUTTON1, 1, 0, 0}

This part is the detailed move. Every slot is separated by a comma.

- The first figure (1352) tells the program at which frame the move starts. The second figure
(1374) at which frame the move ends. So the player will have to do something between
those frames.
- BUTTON1 is the action the player needs to do (uppercase is important). So, here, between
frame 1352 and frame 1374, the player need to push button 1. If he fails to do so or push
anything else (or even does nothing) he will lose one life.
- The fourth figure (1), tells the program which death scene to play if there is a failure. Here
we play death #1 which was defined earlier. So it means that for each move you can define a
different death.
- The last two figures (0,0) have to stay like this. Just ignore them.

Possible moves

- UP: it means up arrow (or stick up on a pad)


- DOWN: it means down arrow (or stick down on a pad)
- LEFT: it means left arrow (or stick left on a pad)
- RIGHT: it means right arrow (or stick right on a pad)
- BUTTON1: it means Left Ctrl key (or A button on a pad)
- BUTTON2: it means Space key (or B button on a pad)
- BUTTON3: it means Left Alt key (or C button on a pad)
- ACTUP: it means up arrow + button 1 (or stick up + A on a pad)
- ACTDOWN: it means down arrow + button 1 (or stick down + A on a pad)
- ACTLEFT: it means left arrow + button 1 (or stick left + A on a pad)
- ACTRIGHT: it means right arrow + button 1 (or stick right + A on a pad)
- MASH : it means you need to hit Left Ctrl key (or A button on a pad) repeatedly and fast
- SKIP: it means that you can skip this part of the movie by pushing anything (optional).

If you check my program, you’ll notice that i don’t use BUTTON2 and BUTTON3. But as you may need
them (for example there’s a button for hand and a button for feet in Cliffhanger), here they are. The
SKIP action is special. You d on’t need to achieve this particular move. It’s only used to skip a part of
the movie where there is no action (for example a speech). The MASH action asks the player to bash
the button 1 really quickly.

Timing

What is a good timing for your moves ? Actually, that ‘s tricky cause you don’t really decide (the
animators did it for you, not knowing you’ll then transform their movie into a game). Let’s say that in
Dragon’s Lair a typical move is around 15 frames. So i’d say

- 30 frames is really easy


- 25 frames is easy
- 20 frame is medium
- 15 frame is difficult
- 10 frame is very difficult
I do not advise you to go below 9 or 10 frames unless you want to utterly frustrate the player. But, as
i said, there are cases where you don’t have the choice if you want to include the move in the list.

For MASH actions you need to give at least 25 frames to the player (30 is better), otherwise it will be
very difficult to hit the key enough time to achieve the move. If there are less than 25 frames, don’t
use MASH.

Also keep in mind that the difficulty level (chosen in the menu) will lower the number of frames you
enter here (that’s minus 2 frames for each slot above normal). The difficulty level also adds some
difficulty to the MASH (+1 per slot above normal). So, be conservative or your players will cry !

Last thing : it’s not a good idea to put moves too close from each other. Try to put at least 1 « off »
frame between the end of a move and the beginning of the next one (for example if move 1 ends at
frame 1374, it’s better to begin move 2 at least at frame 1376). If you don’t do this, the program will
sometimes lose the track.

Feeling

There is another thing which is more important than the difficulty : player’s feeling. You want to give
to the player the illusion that he is actually controlling the character. In the real world, in laserdisc
games, when you push a button at the right moment, you just prevent the movie from stopping
(reading a death scene instead of continuing). But if your moves are placed cleverly, this is like
magic : the player has the illusion that the character is moving because of your action and instead of
a memory/reflex-based game you create an interactive movie. That’s the most difficult task in my
opinion and i won’t pretend i achieved this, but you’ll need a lot of external testing to decide which
frame is the best one.

Generally, when placing my moves, i start by the last frame of the move and tend to choose the very
last possible moment before the actual move takes place (or even the first frame where the actual
movement takes place). Then i go backward to decide when the move begins. Going backward i just
try not to go too far (15 frames ideally).

Debugging

When testing your game, you may have a few problems. As LUA is a script, most of those problems
will be caused by syntax errors. Here are some examples :

- List of moves not consistent : you might forget a number and if your move 5 is followed by
move 7 then the program will not understand
- Bad number of scenes : remember that the number of scenes has to be consistent with the
number declared at the beginning of the function.
- Bad number of moves: remember that the number of moves has to be consistent with the
number declared at the beginning of the scene.
- Overlapping : if the end frame of one move is superior to the begin frame of next move i twill
cause some bugs (usually no more moves on screen)
- Syntax error within a move : if you forget a comma for instance or write button1 instead of
BUTTON1 (uppercase is important).
And so on…

That’s it ! Now you just have to define each move for each scene and for each level. If you have
doubts you may contact me, or have a look at my setupgame.singe file (which contains a lot of
comments). Good luck to you ! I hope i will play your game someday.

You might also like