This tutorial shows the basic steps required to create a Phoenix application
You can download the source for this tutorial here.
Start with downloading and installing the 32bit version of Lazarus from the Lazarus downloads page.
The tutorials assumes the following directory structure
You can download a Template project for lazarus that contains the above folders and a project with the correct paths.
Next download the latest Phoenix release from the download page and extract it into the phoenix folder above.
You will also need SDL.dll and FreeImage.dll. Download this from here and put them in the Binary folder of the tutorial
You can also compile the projects using the standardlone FreePascal compiler.
If you are using the standardlone freepascal compiler you can use the batch script below. This assumes you have installed it in C:\FPC\2.6.2\.
C:\FPC\2.6.2\bin\i386-win32\FPC "-FU..\_Compiled" "-FE..\_Binary\" "-Fi..\..\..\Source" "-Fu..\..\..\Source" "-Fu..\..\..\Source\Providers\" "-Fu..\..\..\Source\Headers\" Tutorial01_Basic.dpr pause
Open the Main.pas pascal unit that is included in the template and add the basic Phoenix includes.
For a full list of all units see the api reference.
unit Main; interface // This includes the phoenix configuration file {$I phxConfig.inc} uses SysUtils, // Basic phoenix types phxTypes, // Contains phoenix utility classes phxClasses, // Math functions phxMath, // Device phxDevice, // Contains the application framework phxApplication, // Used for loading and manipulating graphic images phxGraphics, // Contains the canvas class for rendering 2D primitives phxCanvas, // Texture classes phxTexture; implementation end.
The next step is to create our own instance of the TPHXApplication class that is contained in the phxApplication unit.
type TGame = class(TPHXApplication) private public end;
There is four public procedures in the TPHXApplication class that we need to override in our own class:
Init | This function is called once on application startup, used for loading resources |
Update | This is called once every frame and should be used for updating the game loop |
Render | This is called once every frame and should be used for rendering |
Shutdown | This is called when the application exits, used for cleaning loaded resources |
Add these procedures to your application
TGame = class(TPHXApplication) private public procedure Init; override; procedure Update; override; procedure Render; override; procedure Shutdown; override; end;
Create empty implementations for the functions.
procedure TGame.Init; begin end procedure TGame.Update; begin end; procedure TGame.Render; begin end; procedure TGame.Shutdown; begin end;
This is the program file for the tutorial, this is included in the template and looks like this.
program Tutorial01_Basic; // Make shure we dont get a console window in freepascal {$APPTYPE GUI} // Include the resource file containing the application icon {$R *.res} uses Main; var Game: TGame; begin // Create the game instance and run it Game:= TGame.Create; Game.Run; Game.Free; end.
Now compile the program by pressing Ctrl+F9. You should not get any compilation errors.
This will create the application file in the parent output folder. Note that if you run the program now it will not show a window and you wont be able to terminate the program without using the task manager.
The next step is to create the device that is used for rendering the scene. The first thing we have to do is to select a provider, in this demo we are using OpenGL3.1 with SDL as window manager that is located in the phxOpenGL_SDL.pas unit. Add this to the uses clause.
uses phxOpenGL_SDL;
This provider should work on windows, linux and MacOS. If you need to target another platform it is possible to create a custom renderer by implementing the IPHXDevice interface.
Now add a device instance variable to our application
TGame = class(TPHXApplication) private Device : TPHXDevice; public procedure Init; override; procedure Update; override; procedure Render; override; procedure Shutdown; override; end;
And add code for creating the device
procedure TGame.Init; begin // Creates the device with the device from phxOpenGL_SDL.pas Device:= TPHXDevice.Create; // This loads a new icon for the window Device.Window.Icon:= ContentPath + 'Phoenix.bmp'; // Initialize the window with a width of 800 and a height of 600 pixels Device.Initialize('Phoenix Demo', 800, 600); end;
When you only have one provider included the TPHXDevice.Create function will use this provider. If you have more then one provider you will need to specify which provider to use with one of the overloaded constructors.
There are overloaded methods for the TPHXDevice.Initalize function for showing the window in fullscreen and setting other options.
We also have to update the device each frame and free it when the application shuts down.
procedure TGame.Update; begin Device.Update; end; procedure TGame.Shutdown; begin Device.Free; end;
In the render function we must first clear the back buffer (off-screen) then flip the front and back buffer to show the scene we are creating.
procedure TGame.Render; begin // Clear the off-screen buffer Device.Clear; // Flip the buffers to show the image Device.Flip; end;
Now we have a window with a blue background color, the next step is to initialize a canvas for rendering 2D primitives.
The timer is used to measure the time of each frame for frame rate independent movement as well as calculating the current FPS and the elapsed time of the game.
Add the timer variable to the game class.
TGame = class(TPHXApplication) private Device : TPHXDevice; Timer : TPHXTimer; public procedure Init; override; procedure Update; override; procedure Render; override; procedure Shutdown; override; end;
Create the timer in the Init procedure when the timer is created it will be automatically Reset so if you have long loading times you want to create the timer last.
procedure TGame.Init; begin ... // Create the timer Timer:= TPHXTimer.Create; end;
Also call the TPHXTimer.Update method from the game update method .
procedure TGame.Update; begin // Update the device Device.Update; // Update the timer Timer.Update; end;
The canvas class is used for rendering 2D primitives, it contains a pixel and vertex shader for textured or colored primitives the canvas is created using a factory function in the device, but first we must create a instance variable for it.
TGame = class(TPHXApplication) private Device : TPHXDevice; Canvas : TPHXCanvas; public procedure Init; override; procedure Update; override; procedure Render; override; procedure Shutdown; override; end;
Add the code for creating the canvas in the Init procedure, dont forget to free it in the Shutdown procedure.
// Create the canvas using the device factory function Canvas:= Device.CreateCanvas;
Now we can draw a rectangle by calling the Canvas.Rectangle function. This function adds the primitives required for drawing the rectangle to the internal buffer in the canvas. To show this to the screen we must call the Canvas.Flush procedure before flipping the device.
procedure TGame.Render; begin // Clear the back buffer Device.Clear; // Draw a rectangle Canvas.Rectangle(100, 100, 200, 200); // Flush the canvas Canvas.Flush; // Flip the front and back buffers to show the scene Device.Flip; end;
Now you should see this
To change the color of a primitive we can change the color property of the canvas, the next rendered primitive will be in that color.
// Change the color to white Canvas.Color:= clrWhite; // Draw a rectangle Canvas.Rectangle(100, 100, 200, 200); // Change the color to red Canvas.Color:= clrRed; // Draw a rectangle Canvas.Rectangle(300, 100, 400, 200);
For this part you will need to download this texture and save it as mud.png in the binary folder.
The next step is to add a texture to our rectangles. To do this we first have to declare a texture variable:
Texture: TPHXTexture;
We also need to provide a texture loading library, for instance the (FreeImage) loader. Note that you must copy FreeImage.dll to your output directory.
uses ... phxGraphics_FreeImage;
There are texture loaders for Vampyre and SDL_Image included in phoenix as standard.
It is also possible to create your own texture loader by overriding the TPHXGraphicFiler class. See one of the included loaders for an example on how to do it.
Then we have to create the texture and load it from our texture file.
// Create the texture using the device factory function Texture:= Device.CreateTexture; // Load the texture from a file Texture.LoadTexture('mud.png');
Note that the LoadFromFile is used to load a texture that is saved in the built in texture format and LoadTexture is used to import external textures using the texture filers.
Now we can assign this texture to the canvas and then draw a rectangle using it.
// Change back to white color Canvas.Color:= clrWhite; // Bind the texture Canvas.Texture:= Texture; // Draw a filled rectangle Canvas.FilledRectangle(100, 300, 200, 400); // Remove the texture Canvas.Texture:= nil;
Note that changing the texture for the canvas will flush all buffered verticies, to improve performance sort your draw calls using the texture.
You can also use the TPHXTextureList class to manage textures, by using this you dont have to free individual textures.