PDA

View Full Version : mc_teo's Game Making Tutorial



mc_teo
09-13-2009, 04:39 AM
mc_teo's Magic Game Making Tutorial
where I show anybody how to start off in making games!

Table of Contents
1. Preface
2. Game Logic
3. State Management
4. SCAR example
5. C#/XNA example
6. C/C++ example

Preface
For this tutorial i will go over basic Game-Making, and show some detailed examples of games I have made.

Since SCAR/Pascal-Scipt is the most common language around SRL, i will be adding working examples around the tutorial in SCAR-Script. (See Amethlion (http://www.amethlion.com/) for an example of a MMORPG written completely in SCAR-script)

Basic Game Logic
The basic Game Logic is, (as the name suggests) rather simple, and can be used for almost any platform and language.

It falls into Four categories:
The Initialising Method, The Update Method, The Draw Method, and of course the MainLoop.

The Initialising Method is called once, when the game is starting first, this loads all the sprites/bitmaps/models/textures/whatever.

The MainLoop is now called called to repeat the Update and Draw Methods.


SCAR Example



procedure MainLoop;
begin
Initialise;
repeat
Update;
Draw;
Wait(10);
until(false);
end;


The Update Method controls all the updating, including mostly Input and Variables.
I prefer to use a separate Method for updating input, and then call this first in the Update method.

The Draw Method contains the actually displaying of bitmaps/sprites/images.
N.B. If the game was a shooter, it would probably loop though an array of "enemies".

State Management

State Management means keeping track of all the various game states, and variables.

This lets you use things like pause menus, much easier menus(that you can exit to at any point), and much nicer transitions.

A State Manager is important, because when you pause the game you dont want a timer to be still running, or pressing enemies still moving, going to kill you.

The most basic way to implement this is with a switch case statement.

An Example in SCAR-Script (yuck ;P)



case CurrentState of
'menu':
begin
Update(Menu);
Draw(Menu);
end;
'game':
begin
Update(game);
Draw(game):
end;
'pause':
begin
Update(pause);
// you could draw the game here as well if you wanted to have the pause menu drawn as a popup, so you can still the game under it
Draw(pause);
end;
end;

and just make a call in Update to see if P is pressed, to set the CurrentState to pause.

As Ive said, this is the most basic way to do State Management. You could do much more advanced state management, with custom types for each State, that holds all the variable, etc.

And you should really try to use State Management from early on, because its quite hard to try and squish it in, later on.

SCAR Example
This is a full working example of a game in SCAR, it is a VERY simple Port of my car_game (with no state management).
(It is sort of limited, using SCAR's DebugImgBox, put when did i ever let limits stop me :P)


N.B. SCAR kept flickering for me, badly, so (thanks :>) yakman showed me how to buffer them to stop this, so thats why the current canvas is passed in nearly all the procedures.
EDIT: this method of buffering isnt the best, because its the equilivant of drawing on a memory buffer, taking a photo of this, and displaying this copy. this means if you try to rotate the bitmaps (i.e. for turning the car) you'll end up with a circular blur.



program car_game;

type
TSprite = record // custom type for a character in game. HP could be added here, etc
Position: TPoint; // current (X,Y) Position
MidPoint: TPoint; // The Centre Point of the sprite. (Useful for rotating and Collision Detection)
Width: Integer; // Width of the image, of course, Useful for collisions
Height: Integer; // Height of the image, ^^^
Image: Integer; // Contains the bitmap for the Sprite
end;
TSpriteArray = array of TSprite; // just handy i suppose

var
Sprites:TSpriteArray;
Car:TSprite; // Our Main Character
Buffer:Integer; // my buffer bitmap

// Wrapper for Displaying Bitmaps (robbed from MastaRaym0nds Movie i think :P)
procedure DisplayBitmap(Canvas:TCanvas; Bmp:Integer; Where:TPoint);
begin
try
SafeDrawBitmap(Bmp, Canvas, Where.X, Where.Y);
except
Writeln('Error in DebugBitmap');
end;
end;

// Just handy for debugging variable, making sure they are updating as they should, etc.
procedure Debug(ID:Variant; Name:String; Variable:TVariantArray);
var
Line:String;
I:Integer;
begin
Line := (ID + ': ' + Name+' = ( ');
for I := 0 to High(Variable) do
case VarType(Variable[I]) of
256 : Line := Line + Variable[I] + ' '; // + ' is a String Value');
3 : Line := Line + IntToStr(Variable[I]) + ' '; // + ' is an Integer Value');
5 : Line := Line + Variable[I] + ' '; // + ' is an Extended Value ');
11 : Line := Line + Variable[I] + ' '; // + ' is a Boolean Value ');
end;
WriteLn(Line + ')');
end;

// Does this really need an explanation?
procedure ClearCanvas(Canvas:TCanvas);
begin;
Canvas.Brush.Color := CLblack;
Canvas.Pen.Color := CLwhite;
Canvas.Rectangle(0, 0, 600, 600);
end;

// procedure to be called once, when the game starts
procedure Initialise;
var
I:Integer;
begin
DisplayDebugImgWindow(300, 300);
// Car.Image := LoadBitmap('C:\Users\mc_teo\Documents\car.bmp');
Car.Image := BitmapFromString(91, 49, GetPage('http://mcteo.talkflack.com/car.txt'));
Car.Position := Point(100,100);
GetBitmapSize(Car.Image, Car.Width, Car.Height);
Car.MidPoint := Point((Car.Position.X+(Car.Width/2)), (Car.Position.Y+(Car.Height/2)));
Buffer := BitmapFromString(300,300,'');
end;

// This handles all the input - supposedly arrows and WASD
procedure UpdateInput;
var
speed:Integer;
begin
speed := 10; // increment or decrement by this
if (IsKeyDown(#75) or IsKeyDown(#97)) then
begin
Car.Position.X := Car.Position.X - speed;
end else if (IsKeyDown(#77) or IsKeyDown(#100)) then
begin
Car.Position.X := Car.Position.X + speed;
end
else if (IsKeyDown(#72) or IsKeyDown(#119)) then
begin
Car.Position.Y := Car.Position.Y - speed;
end else if (IsKeyDown(#80) or IsKeyDown(#115)) then
begin
Car.Position.Y := Car.Position.Y + speed;
end;
end;

// This is the MainUpdate method
procedure Update;
begin
UpdateInput; // updates the input
Debug('1', 'Car.Position', [Car.Position.X, Car.Position.Y]); // Debugs the current sprite position
Car.MidPoint := Point((Car.Position.X+(Car.Width/2)), (Car.Position.Y+(Car.Height/2))); // Updates the MidPoint
end;

// Main Draw Method
procedure Draw(Canvas:TCanvas);
var
I:Integer;
sprite:TSprite;
begin
ClearCanvas(Canvas);
for I := 0 to High(Sprites) do
begin
// this is just a loop to draw/display all sprites in their position
// sprite := Sprites[I];
// DisplayBitmap(Canvas, sprite.Image, Point(sprite.Position.X, sprite.Position.Y));
end;
DisplayBitmap(Canvas, Car.Image, Point(Car.Position.X,Car.Position.Y)); // Displays the main character
Canvas.Ellipse((Car.MidPoint.X-2),(Car.MidPoint.Y-2),(Car.MidPoint.X+2),(Car.MidPoint.Y+2)); // draws a little circle in the center of the bitmap for debug purposes.
end;

// The MainLoop, duh :P
procedure MainLoop;
begin
Initialise; // Calls the Initialiser once
repeat
ClearDebug; // Clears the debug canvas
Update; // Updates everything
Draw(GetBitmapCanvas(Buffer)); // Draws to the buffer
CopyCanvas(GetBitmapCanvas(Buffer), GetDebugCanvas, 0, 0, 300, 300, 0, 0, 300, 300); // Displays the buffer on the DebugImg box
Wait(75); // A little wait cant hurt, can it?
until(false);
end;

begin
Mainloop;
end.


A C# Example (works on xbox 360 too)

I was bored one day so i decided to draw one of a little pixelated images in paint. The next thing, a car was made! When i showed my younger brother he wasnt impressed with this non-moving car. So I, you was dabling with XNA game studio at the time, said id animate it.
Just moving a car around the screen, didnt seem to bring much enjoyment, so I added the ability to collect coins for points. On the request of NxTitle, i added a Nitros like speed boost, that could be refilled by picking up special pickups.
Still improving my skills, i wanted to make a working State Manager, which would allow pause and resume functionality, as well as menu screens.

So here is the actual game http://mcteo.talkflack.com/car_game.php this has State Management in it as well. Quite advanced stuff to if i do say so my self (and i do as i borrowed some of the State Management stuff from a tutorial i read)

All made by me (with the exception of some of the State Management stuff, i got them from a tutorial :P)

p.s. the .rar contains an old release, but it autoupdates to the latest version after starting it a few times

*UPDATE*
For all you LinuxFags out there, I will be updating this soon, with a fully cross platform example, in C and C++.


MORE TO COME FOLKS...

caused
09-13-2009, 04:52 AM
Nicely put together :).

I always wanted to write tetris in scar :D. Maybe ill give it a go.

~caused

marpis
09-14-2009, 02:50 AM
Add a link to Amethlion (http://www.amethlion.com/) to the 1st post :)