Home
Memoirs of a Gamer
Movies I watched
Guidebook
Code Projects
Links
The game outlined in this article can be found in the "Sample Game" folder inside the Gorgon GDK repo.
Let's get your first game up and running! This assumes you've already gotten some art assets packed into the res1 and res2 files. The res3 and res4 files only need to exist before selecting the appropriate sound device in the startup menu or command line parameters.
The first file we'll want to start with is GAME.CNS...
The root game script only needs one event to get your game up and running, and that is the start event. We'll get into the nuances of events later, but if you're familiar with functions in other programming languages, imagine events as being very similar, except there are no parameters or return value. If that doesn't mean anything to you yet, don't worry. Just know that events are how Gorgon handles running your game specific logic.
We'll open a new text file and call it game.gs (for gorgon script). Open it up and enter the following code:
:: This is our master game script which :: will kick off all other game logic Title "My First Game" define MY_FIRST_ROOM 1 event start = sys.Score,0 = sys.MaxScore,10 loadroom MY_FIRST_ROOM endevent |
:: This is our master game script which ::will kick off all other game logic |
The first two lines are examples of comments. That is, anything after the double colons "::" will be ignored by the Scriptor compiler. If you're not familiar with code comments, they're just ways for developers to add human readable statements into their code to assist in other developers (or sometimes even just their own future selves) in making sense of what the code is doing.
Title "My First Game" |
The next line is the Title command. The string that follows the title command is what will appear when the player presses F1 or calls the Version Info box while in game. NOTE: Although every script file may contain a Title, only the one found in game.cns is used by Gorgon.
define MY_FIRST_ROOM 1 |
Now we've got our first define! Defines are used to replace numeric values with a name that conveys it's meaning in the code somewhat better. These can also be centralized in an external file to help maintain code cohesion, but we'll worry about that later. For now, just know that define commands are followed by a name and a numeric value. When the compiler finds this name, it will replace it with the numeric value before processing.
event start |
Finally we're at our start event. Events can be named anything by following event with a string, but the start keyword marks the event to be run upon loading the script file in game. We've got the start keyword here so this event will run the moment GAME.CNS is loaded into memory.
= sys.Score,0 = sys.MaxScore,10 loadroom MY_FIRST_ROOM |
The next 3 lines are instructions. Instructions are the individual commands that control the Gorgon Virtual Machine. They can load files, set registers, or even call other events. These specific commands are 2 assignment statements that are setting the system's Score and MaxScore registers to 0 and 10 respectively, and then loading our first room script, which we reference with our define. See how it all fits together?
endevent |
And lastly we need to close out our event with an "endevent" command. This tells the compiler that no further instructions will be contained in this event.
Now that we've got our game script, let's compile it by opening a command terminal, navigating to our folder and typing:
scriptor game.gs |
I'm sure some of you were thinking "hey, wait a minute! You keep talking about game.cns but we wrote game.gs. What gives?" CNS files are compiled byte code files used by Gorgon. The Scriptor compiler creates them as an output file upon successful compilation.
So let's run our game! BUT WAIT! We don't have a room script written yet! We even explicitly load room index 1! If Gorgon can't find a room script file it'll crash out, so we better write one first!
The game script sets a lot of parameters for the virtual machine. Things like the game's title, global events, and save file sizes are dictated by the information gleaned from the game script, but the room scripts are the primary driving force of the Gorgon Engine. Everything comes down to 3 events: the start event, the "tick" event, and the "said" event. So let's create a new file called "room001.txt", open it and write it as follows:
:: This is our first room script which :: will handle the primary events :: fired during gameplay. event start = sys.Spr_Id,0 sprite.setseq 0,0 sprite.setseq 1,1 sprite.setseq 2,2 sprite.setseq 3,3 sprite.setloc 40,115 sprite.vis true screen.load 0,true screen.present map 0 mask 1 = sys.Typing,true = sys.Controlled,true = sys.Physics,true endevent event "tick" if (== sys.Spr_Map,2) exit endif endevent event "said" if (said "look") msgbox "This is a simple room script." msgbox "Simply walk to the door on the right." msgbox "Walking to the door will exit the game." else msgbox "Command not understood!" endif endevent |
We now know what comments are so we'll skipp those.
event start |
So we have our start event definition. This one looks a bit bulkier than Game.csn's start event. We'll take this as three blocks, the first block primes our player sprite, and then we get our screen initialized, and finally we configure the player's input.
= sys.Spr_Id,0 |
Sprites are affected by assigning values to registers and executing instructions one sprite at a time. What sprite is currently being configured or tested is governed by the system register Spr_Id. Here we are setting the active sprite ID to 0, which is a special sprite, as this is the one the system lets the player control with the arrow keys.
sprite.setseq 0,0 sprite.setseq 1,1 sprite.setseq 2,2 sprite.setseq 3,3 |
Sprites have 4 directions that can be assigned animation sequences independently. Those for are in order:
We are assigning each direction a sequence which just happens to share their ordinality.
sprite.setloc 20,100 |
Now we're setting our location. Sprites can be places anywhere on the screen, and even off the screen. The screen's coordinate space is 0-159 horizontal and 0-199 vertical.
sprite.vis true |
And finally we're making our sprite visible.
screen.load 0 |
First we'll load our color space specific screen art from the res1 file associated with our selected video device. Some 16 color EGA / Tandy 1000 art is down below to help get you started.
screen.present |
Now that our background art is loaded and our player sprite is ready, let's present the scene. This will force a striped screen refresh.
map 0 |
Let's load our physics map from "res1.dat". These maps offer 15 zone colors and index 0 (or black if we're looking at the image as an EGA 16 color graphic) acts as our barrier. This is not visible usually in game, but it controls where the player sprite may go, assuming the system register "Physics" is set to true.
mask 1 |
Lastly we'll load the priority map from an image in "res1.dat". This map is used to govern the screen's layers for clipping sprite graphics. If that sounds a bit weird, just know that when the player sprite moves, the physics map will assign the sprite's priority register automatically. When the sprite is drawn to the screen it's priority is tested against the associated pixel in the priority map, thus giving the effect of a Sierra-Online style 3D space, despite the inherently 2D coordinate system.
= sys.Typing,true |
We'll activate the player's type input prompt.
= sys.Controlled,true |
Activate the player sprite's movement.
= sys.Physics,true |
And activate the player sprite's physics. This will enforce index 0 = blocking in the physics map.
endevent |
With that, we'll close our start event!
event "tick" |
Events can be assigned a human readable name in the form of a string. Two such events Gorgon is wired to search for in the room script are "tick" and "said". "tick" is run literally every game tick, of which there are usually 35 per second. Keep in mind that if the game is run on a very low end computer, say less than 10MHz, slow down will occur. 35Hz tick rate is only enforced as a maximum cap speed.
if (== sys.Spr_Map,2) |
Let's test if our sprite is standing on a zone 2 pixel.
exit |
If we are, we'll execute a graceful shutdown of the Gorgon environment.
endif |
Let's close out our IF block.
endevent |
And close out the "tick" event entirely.
event "said" |
The primary work horse of the Gorgon Engine is the text type command input system. When the player presses the enter key, their input is prepared and each word typed is tested against the DICTION.DAT string table. If all words pass the test Gorgon then searches for the currently loaded room script's function called "said". If none is found, Gorgon returns control to the player. If it is found, execution begins.
if (said "look") |
Let's see if the player typed in the word "look".
msgbox "This is a simple room script." msgbox "Simply walk to the door on the right." msgbox "Walking to the door will exit the game." |
If yes, we print our 3 text boxes to the screen. We could have written these all out as a single msgbox command, but web pages can be twitchy about text width, so for the sake of readability we'll split them up. Feel free to experiment with how much text you can fit on a single text box!
else |
Let's run some code in the case that the player didn't type in the word "look".
msgbox "Command not understood!" |
A message box saying we don't know what the player was trying to do. A default message of some kind telling the player that what they typed in wasn't an expected command is imperitive. Player feed back should always be thought of as required. Regardless of what the player tried to do, do or say something to let the player know the game handled what they attempted. Even if it wasn't valid input.
endif |
Close out the if block
endevent |
Close out the event!