Tag Archives: sdl 1.2

Chapter 1a: Compilation and configuration of Lazarus (JEDI-SDL)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

Before you start following the instructions given here to install Lazarus make sure you really need it. The Lazarus package is completly independent of SDL. If you are not interested in a DELPHI-like RAD (Rapid Application Development) tool skip this chapter. You could come back later after you finished all SDL chapters :). This chapter isn’t required to do the following chapters.

Otherwise the combination of Free Pascal together with the SDL Library and Lazarus’ abilities can lead to a very flexible and highly powerful development environment. The advantages of Free Pascal, like OS independence, open source code, a license which allows you to develop commercial programs (license: LGPL), and so on apply for Lazarus, too! Furthermore you gain all advantages modern OS and IDE provide. The DOS-like IDE of the Free Pascal compiler is legendary but nowadays not too comfortable anymore. The Lazarus environment provides a flexible and comfortable IDE.

The following description on how to compile/install and configure Lazarus is for WINDOWS ONLY. I am sorry that I am currently not able to make such a description to linux users. Any reader is welcome to send me one, so I could publish it here (you would get full credit of course). Futhermore it is necessary that you have installed Free Pascal.

The following table describes what software you will need additionally to the Free Pascal compiler:

Software Version Size, MB Source Description
Lazarus source files Latest revision depends directly through SVN How to get them will be described next!
TortoiseSVN 1.4.7 ~2 http://tortoisesvn.net/ Download the latest version of SVN client (except you already have such a client).
fpcbuild-2.2.0.zip 2.2.0 ~38 http://www.Free Pascal.org Download the latest source files of the Free Pascal compiler. Go to “Download” and scroll down to “Source”.

Now let’s begin. First of all I want you to know that there are some binaries downloadable from the official Lazarus page. These binaries shouldn’t be used because they are very old and the resulting Lazarus environment is terribly unstable! The environment is much more improved and gets improved daily. So I advise you to get the latest development state through SVN (it’s like the outdated CVS). If you neither know SVN nor CVS here a short description: SVN provides the latest state of development and ensures that any of several hundreds developers of a project (like Lazarus) is working on the latest version. Whenever a developer is changing anything at the project SVN generates a new revision number. Today the revision number of Lazarus is 13688.

How to get the latest development state (revision) of lazarus then? – That is described very clearly and easy here: http://wiki.lazarus.FreePascal.org/index.php/Getting_Lazarus. Therefore I will just describe short how to get it.

1) get the mentioned SVN client (TortoiseSVN) for Windows and install it

2) create a directory where you want to have Lazarus installed later (e.g. C:\FPC\Lazarus)

3) right-click on the new created lazarus folder and chose “SVN Checkout…”; you get the following window

Lazarus SVN Checkout window4) type in field URL of repository: “http://svn.Free Pascal.org/svn/lazarus/trunk” (without quotationmarks) as shown in the picture above; if you use a command line client (e.g. Subversion you have to type “svn co http://svn.Free Pascal.org/svn/lazarus/trunk lazarus” (without quotationmarks))

5) click “OK”

6) another window pops up called “trunk – SVN Checkout…”; now it will take some minutes; after all files got downloaded you receive a window similar to this:

Lazarus finished checkout(you can go on reading while waiting)

The files you download through SVN aren’t binaries. That means you have to compile them. The compiler you use to do so is the Free Pascal compiler of course (that is why you should have it installed already).

7) If the downloading is finished you have to go to the folder where all the files are placed, e.g. C:\FPC\lazarus\.

8) Now you have to run a command line tool like “cmd”. Choose “Start” and then “Run…” from Windows’ start menu.

9) Enter “cmd” or “command.com” (latter only if “cmd” doesn’t work) in the next pop-up window and click “OK”. Now a window like this should pop up:

Command window cmd.exe for make procedure10) Go to the directory where you downloaded the Lazarus files. (Use the DOS commands “cd [directory]” and “cd..” to enter or leave directory.)

11) When you entered the directory (C:\FPC\lazarus\) just type “make” and the make.exe of your Free Pascal compiler will compile Lazarus for you. Now relax and wait some minutes.

If this doesn’t work for you, you should try to copy the make.exe from your Free Pascal compiler (located in bin directory) to the Lazarus directory (or you could check if you set the environment variable/user variable PATH=C:\FPC\2.2.0\bin\i386-win32 in system control)

12) After successful compilation there should be a Lazarus.exe and a Startlazarus.exe right in the lazarus directory. Use Startlazarus.exe to run your brand new RAD tool :). After passing some error messeges you should get something similar to this:

Lazarus editor if installed successfully13) close Lazarus

The next steps describe how to configure Lazarus together with JEDI-SDL. This includes telling Lazarus where to find Free Pascal compiler, where to find Free Pascal source files and where to find JEDI-SDL units. ATTENTION: It is necessary to have the source files of Free Pascal, otherwise Lazarus won’t run properly. If you installed Free Pascal and JEDI-SDL as described in Chapter 1 you don’t have the source files because they are not included in the binary package. Fortunately this doesn’t matter because you can download them separately. If you already have the source files for some reason you can skip step 14 and 15.

14) Download the latest source files of the Free Pascal compiler (usually it doesn’t matter if the version of the source files differ slightly from the version of actual compiler).

15) Now extract the file. It doesn’t matter where the source files are located but you may prefer a folder like “C:\FPC\2.2.0\source\”.

16) The extraction generates a folder “fpcbuild-2.2.0”. The whole path should be “C:\FPC\2.2.0\source\fpcbuild-2.2.0\”.

17) Now run Lazarus and skip any error message. Go to “Environment” in the menu.

Lazarus editor environment options
Choose “Environment options” from the tab. The following window should come up.

Environment options window18) The text field “Lazarus directory (default for all projects)” should be filled with your Lazarus path, if not do so. The text field “Compiler path (ppc386.exe)” should be filled with your Free Pascal compiler path, if not do so.

19) The text field “FPC source directory” is probably empty. The sources are needed for Lazarus to compile projects successfully. Fill in the path where you extracted the source files in step 15. If you followed my suggestion the correct path would be “C:\FPC\2.2.0\source\fpcbuild-2.2.0\fpcsrc\”. Confirm by clicking “OK”.

20) If you haven’t done any mistakes there shouldn’t be any error anymore if you close and restart Lazarus.

21) If you didn’t install SDL manually you can skip steps 21 and 22, you are finished then! Now let’s tell Lazarus where to find the JEDI-SDL units. Go to “Project” in menu.

Lazarus compiler optionsChoose “Compiler Options…” from the tab. The following window should come up but without any entry in the text field “Other Unit Files (-Fu) (Delimiter is semicolon);”.

Lazarus compiler options window22) Enter the path to the JEDI-SDL units. If you installed JEDI-SDL as mentioned in Chapter 1 you should enter “C:\FPC\2.2.0\units\JEDI\SDL\Pas”. Now you are ready to write Free Pascal programs in Lazarus using JEDI-SDL. Note: The environment settings are saved for any project but the compiler settings (steps 20-22) are just related to the current project so you have to set the unit path to JEDI-SDL units separate for each project.

Now you have a brand new RAD tool installed. Well done! This tool you can use to write just plain Free Pascal or/and Free Pascal/SDL programs. You also can combine these programs with the features typical RAD kits provide but to learn how to use those features is described anywhere else. Have fun.

Chapter 6: Event handling (JEDI-SDL)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

Whenever the user of your program is doing something related to it, for instance if the user is moving the mouse, pressing/releasing a button on the keyboard or pressing/releasing the fire key on the joystick, then you speak of events. Further events are resizing a window or switching between several applications. For games though the events described first are much more important. SDL provides a quite easy way to notice and react to such events, which is called event handling.

Each event has a special structure, for example a pressed key is an event or a moved mouse is an event. SDL differs altogether sixteen such events (check the table below). Every event stores different information depending on its kind. For example the key board event stores the information which key was pressed. The mouse motion event stores the information to which position the mouse got moved. If you get a mouse motion event you can’t read out key information, and from a key pressed event you can’t read out its mouse coordinates, and so on. Therefore you have the following general structure to the event data: event.eventstructure.data. The following list will give you an overview of all possible eventstructures in SDL:

eventstructure Description
SDL_NOEVENT Whenever the user is not raising an actual event.
SDL_ACTIVEEVENT Notices if application is active or inactive (for example when you switch to another windowed application and your applications gets into the background or gets minimized).
SDL_KEYDOWN Both have the same record structure (tSDL_KEYBOARDEVENT) which stores the triggering key with state SDL_PRESSED or SDL_RELEASED
SDL_KEYUP
SDL_MOUSEMOTION Notices the movement of the mouse cursor and stores it position and the relative movement from former origin.
SDL_MOUSEBUTTONDOWN Both have the same record structure (tSDL_MOUSEBUTTONEVENT) which stores the triggering mouse and its key with state SDL_PRESSED or SDL_RELEASED. Futhermore the position is stored.
SDL_MOUSEBUTTONUP
SDL_JOYAXISMOTION Notices the usage of the stick of a joystick.
SDL_JOYBALLMOTION Notices the usage of a joyball and the relative movement from its origin.
SDL_JOYHATMOTION Notices the triggering joystick and its hat. Furthermore one of the nine positions is stored (1=up, 2=right upper corner, 3=right and so on; 0=center).
SDL_JOYBUTTONDOWN Both have the same record structure (tSDL_JOYBUTTONEVENT) which stores the triggering joystick and its key with state SDL_PRESSED or SDL_RELEASED.
SDL_JOYBUTTONUP
SDL_VIDEORESIZE Notices when apllication window gets resized and stores the new height and width.
SDL_QUITEV Notices when user quits the application (by clicking application’s X-button at right upper corner)
SDL_USEREVENT Unedfined event which can be definied by user.
SDL_SYSWMEVENT Notices system window manager events.

The event handling subsystem is automatically initialized along with the video subsystem. Since all the events are related to the program’s window there is no sense of intilizing it individually from the video subsystem. Here is the code of the program all at once.

Okay, let’s right start with the first part.

The first part to be discussed doesn’t contain a lot of new things. The program is called chap6_1, it uses the SDL unit and the screen variable is defined. New is the event variable test_event which is of pointer type pSDL_EVENT. We will create a second variable of boolean type just to control the while loop. Then SDL is initialized and the program’s window set with the width and height of 200 pixels. Finally the event variable gets allocated.

We want to check if any event occured and if so, we want to know which kind of event happened. So we make a while loop which will run until loopstop gets true. This will be if the user presses the application’s X (right upper corner) or pressing ESC key.

The command SDL_POLLEVENT(parameter), or more precise SDL_POLLEVENT(event: pSDL_EVENT): INTEGER, checks if there are pending events and if so it will take the oldest and save it to parameter which is an event record of pSDL_EVENT type. For example if the user presses (then releases) left mouse button, then presses (then releases) space button on keyboard and finally moves the mouse there are altogether five events: 1. left mouse button pressed, 2. left mouse button released, 3. space key pressed, 4. space key released, 5. mouse moved. If you poll for events now you will get the first event (left mouse button pressed) and saved it’s properties to the event variable we specified as parameter. The next poll will save the properties of next event (left mouse button released) to event variable and so on. SDL_POLLEVENT(parameter) will return 1 if it has found pending event or 0 if there isn’t any pending event.

So, if SDL_POLLEVENT has an event, then the program writes “pending event:” and after that will add the type of event found. Notice that therefore write instead of writeln has been used here. The actual event is determined as follows:

Fortunately you don’t have to check manually for every event which is made by the user. In general by event^.eventtype you can easily check which type of event you got. The event is stored in test_event and the type is checked by type_ so the expression is test_event^.type_. Whatever event is stored in test_event, the corresponding string expression is then added to the previous “pending event:” string. For the example described before the returned event types would be SDL_MOUSEBUTTONDOWN, 2. SDL_MOUSEBUTTONUP, 3. SDL_KEYDOWN, 4. SDL_KEYUP, 5. SDL_MOUSEMOTION. It is senseful to check for the event type by using the CASE command.

You may have noticed that in case of SDL_KEYDOWN not just a string gets added. Actually in this case also the corresponding SDLKey code is determined and given. Furthermore if the pressed key is the escape key (Esc) the program should stop. An keyboard event record contains a field called keysym. Keysym is a record of SDL_KEYSYM. It contains four fields. Scancode which is a hardware dependent scancode and should be avoided if you want to make hardware independent programs. It is usually an INTEGER variable. Next is sym which stores the SDLKEY. These SDL keys are independent and it is strongly recommended to use them! In the example we want break up if the escape key gets pressed. Its SDL key code is 27. If you want to know what SDL keys are defined look up in the table page. The variable modifier stores modifier keys (like shift, ctrl,…) pressed and stores SDLMod. SDL modifier keys can be found at table page as well. The fourth variable is unicode which may be used to read out unicode characters which is enabled by function SDL_ENABLEUNICODE(enable: INTEGER): INTEGER. 1 enables and 0 disables the unicode translation, however by default it is turned off.

To read out or compare the key the user pressed we must use the expression test_event^.key.keysym.sym. test_event^ is the event, the event structure is defined as an key event by key and the data we want to know is the key pressed contained in keysym.sym. The key code is printed to th screen but if it corresponds to the code for the ESC key, it sets loopstop to TRUE meaning the the while loop will be stopped and finally stop the program.

In the case SDL_POLLEVENT finds no event all the checking for event is skipped and just “no pending events” is written. To slow down the program the known SDL_DELAY is used.

Finally the event and the screen are disposed and SDL as well as the program are quit.

Now I will present a command without showing its appliance at any code since it is easy to understand and very important. Imagine you open any text editor and just hold pressed any letter on the keyboard. What will happen? First the letter will be written to the text editor once and after a short break the letter will be written in a loop (without break). – You may want to change this behaviour, especially for action games and such. The command SDL_ENABLEKEYREPEAT(DELAY, INTERVAL), or more precise SDL_ENABLEKEYREPEAT(delay: INTEGER; interval: INTEGER): INTEGER, is used for changing this behaviour. If delay is set to 0 the key repetition is completly disabled and a held pressed key will just trigger ONCE. If you enable the the delay by setting it to 1 and setting an interval in ms the pressed key will trigger anytime the set interval has passed. E.g. SDL_ENABLEKEYREPEAT(1,1000) will trigger the key any second if pressed. Note: When using this command the specific text edior behaviour is removed and the first triggering will happen immediatly. To get back to the common behaviour use SDL_DEFAULT_REPEAT_DELAY and SDL_DEFAULT_REPEAT_INTERVAL.

Now we will discuss mouse handling. Since it is rather similar to keyboard handling I will keep it short. Here we go:

Anyhow this code looks complicated, it is not.

This is exactly the same code as for the first part of this chapter, however a PROCEDURE mouse_check is created which will be used several times later. You can read out the position of the mouse (relative to your program window!) by test_event^.motion.x and test_event^.motion.y. The relative movement which means the difference from the actual position compared to last polled position you can get by test_event^.motion.xrel and test_event^.motion.yrel. Furthermore it is possbile to return the pressed buttons by test_event^.motion.state. All this data belongs to tSDL_MOUSEMOTIONEVENT record. All these information are just printed out by the mouse_check PROCEDURE later.

Function SDL_EVENTSTATE(type_: UInt8; state: INTEGER): UInt8 allows you to enable/disable certain event structures. For example in the code SDL_ACTIVEEVENT got disabled by SDL_EVENTSTATE(SDL_ACTIVEEVENT, SDL_DISABLE). That is why you never will receive a note about an active or inactive application even though the status may change when you run the program. The same result you get by using SDL_IGNORE instead of SDL_DISABLE. You can reenable the event structure by SDL_ENABLE.

This part now looks also very similar to the code of the first part of this chapter. Since we are only treating mouse handling here all the other possible events are not treated in the CASE block. The SDL_ACTIVEEVENT event is just introduced here to demonstrate that it is succesfully disabled by SDL_EVENTSTATE as discussed right before.

The SDL_KEYDOWN event is introduced to make sure the user can exit the program by pressing the ESC key.

Similar to the handling of keyboard events the mouse key events are handled. It also provides the possibility to return the pressed button by test_event^.button.button. It has the very same meaning as test_event^.motion.state! Don’t confuse it with test_event^.button.state which here means to check if a button is pressed (SDL_PRESSED) or released (SDL_RELEASED). This data belongs to the tSDL_MOUSEBUTTONEVENT record. Whatever the user is doing with the mouse, moving or clicking, the mouse_ckeck PROCEDURE already discussed is entered and the corresponding data written to the screen.

By the way, you should check what happens if you combine several mouse buttons or use the mouse wheel. Some button combinations lead to the same button index as the usage of the mouse wheel and so on.

With this chapter you got introduced into a major concept of game programming.

This file contains the source code: chap6_1.pas (right click and “save as”)
This file is the executable: chap6_1.exe (right click and “save as”)
This file contains the source code: chap6_2.pas (right click and “save as”)
This file is the executable: chap6_2.exe (right click and “save as”)

The final result should look and behave like this: While being with the mouse onto the SDL application window any event from the keyboard is recognized and it is said what exactly happened (button down, up, …)

Result of JEDI-SDL Chapter 6, keyboard handling

The final result should look and behave like this: While being with the mouse onto the SDL application window any event from the mouse is recognized and its (x/y) position, the difference between last recognized position and new position (dX and dY) and if a button is pressed or released and the corresponding button’s index is shown.

Result of JEDI-SDL Chapter 6, mouse handling

Chapter 4: Drawing pixels (JEDI-SDL)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

Okay. Maybe you think, why to learn how to display pictures first and then learning about the more basic feature to draw single pixels to the screen? – First of all blitting is one of the key features whereas drawing of single pixels to the screen is quite rarely used in applications and games. Though this chapter will get a little bit longer because several things have to be explained more detailed to impart a fully understanding.

We have to know about the meaning of pixels. The physical screen consists of many small units. Every unit consists itself of three different coloured lights. These colours are red, green and blue. If you mix them (additive) you can get every other colour. For example if you mix red and green you get yellow. For three colours that can be mixed with each other there are eight combinations possible which lead to different colours (RGB, RG, RB, R, GB, G, B, all lights off). Some of you may say RGB (white) and all lights off (black) are no colours. That is right but doesn’t matter here and to keep simpliness I will talk of colours even if I talk of black and white.

Did you get confused? Your screen definitvly has more than eight colours, doesn’t it? The reason is, your screen isn’t just able to switch lights on or off. Besides it is able to differ the intensities of the lights. The more intensity levels you have the more colours you can display. The case that you have eight colours as discussed before means that you just have one intensity level. If your screen is in 8 bit mode every pixel on the screen has the possibility to display 2 power 8 colours. That are 256 different colours. Every of the three lights has therefore a certain amount of different intensity levels. If you have 16 bit mode you have 2 power 16 and that are 65536 colours. Each light therefore has the appropriate amount of intensity levels. Since we prefer 32 bit mode, we have 4.29 billion different colours!

All the examples will be at 32 bit mode. If you want to write directly to the screen surface it is possibly necessary that you lock it before performing direct pixel manipulations. We work in software mode (SDL_SWSURFACE) so we can leave locking the screen surface. However, other modes will require you to lock it. Not shown in the example code you can check it by function SDL_MUSTLOCK(surface:pSDL_SURFACE):BOOLEAN. If it evaluates to FALSE or 0 you don’t need to worry about locking. Otherwise you have to lock the surface by function SDL_LOCKSURFACE(surface:pSDL_SURFACE):INTEGER for direct pixel manipulations. It will return 0 if locking was succesful and -1 if locking failed. After pixel manipulations you have to unlock the surface by procedure SDL_UNLOCKSURFACE(surface:pSDL_SURFACE) straight forward.

Now the whole example code is presented. The goal is to have 200 x 200 pixels wide black surface. A single yellow pixel will start to move from the top-left corner along the surface from left to right and line by line until it reaches the bottom of the surface. It then will restart at the top-left corner.

Now we will go through the whole code step by step. Especially direct pixel manipulations are often misunderstood by newcomers to SDL.

The program is called chap4. As known from previous chapters unit CRT is needed here for a simple input handling and unit SDL is needed for SDL support. The screen variable is known from previous chapters as well and will contain the content which is displayed at the physical screen later. The pixellocation variable is a pointer type variable indicated by the tilde (^). Furthermore the space it’ll point at needs to be of size for a Longword value. The two variables pixelcolor and i are common Longword variables.

The SDL program is initilized as known and the display surface is of size 200 x 200 px and has 32 bit. Except from the pointer variable pixellocation there is nothing new up to here.

In the first line of this part of the code the pointer pixellocation gets some space by the common Free Pascal function NEW(pointer).

Next the pitch value of the surface is printed. Please note, if you create a surface of a certain width and height the true surface can be a little bit wider. In our example this means you have a window of width and height of 200 pixels displayed but there could be an additional unvisible piece of surface. Maybe its true width is 210, so the moving pixel wouldn’t restart at a new line after 200 cycles but 210 cycles. To solve problems caused by this pitch to the surface you can read the pitch out. The data type pitch will allow you to do this (e.g. screen^.pitch). Unfortunately the pitch is not given in pixels (as the width value) but in bytes so you have to devide its value by the BytesPerPixel value which is for our 32 bit surface format usually 4. This value can be read out by screen^.format^.BytesPerPixel. You will see that in our example the width and the pitch are equal (both 200) which means there is no exceeding surface part.

Counter variable i is set to 0. Then the repeat loop is entered. Variable i is increased by 1 each cycle until it reaches 39999. It controls the position of the dot. When i reaches 39999 exactly 40000 cycles are done and the dot should restart at the top-left corner.

Now it gets interesting.

Let’s first consider the second line concerning the colour of pixels. If you want to add colour to a single pixel you need to know the corresponding pixel value defining the colour of it. The function SDL_MAPRGB(format:pSDL_PIXELFORMAT; r:UInt8; g:UInt8; b:UInt8):UInt32 or in short SDL_MAPRGB(pixel format, red, green, blue) will make it easy for you to find it out. Just add the pixel format of the surface which is stored in the surface’s format field. For the example surface the expression is screen^.format. A RGB triple of (0,0,0) will lead to black, all lights off (which is also the background colour of the surface). The expected variable type for the RGB triple values are of UInt8 meaning an unsigned 8 bit integer which corresponds to a Free Pascal Byte type variable with a range from 0 to 255. The function will return an unsigned 32 bit integer (UInt32) value which corresponds Free Pascal’s Longword type variable.

Now we are concerned about the actual allocation of a colour to a specific pixel. Every surface provides the possibility to access its pixels, for example by screen^.pixels. The marker pixels is of type Pointer and points to a certain pixel of the surface. By adding to or substraction from it you can easily access any pixel on the surface. So any pixel’s coordinate on the screen can be accessed by using ONE number instead of a pair of (x,y) values. This is an important concept. The integer value screen^.pixels is pointing at represents the colour of this specific pixel. So, don’t confuse these two values. The value of the pixels pointer itself determines the pixel addressed, the value it is pointing at determines the pixel’s colour. The following diagram may help to explain this.

Diagram explaining pixel locationFor our 32 bit surface all the pixels are of size Uint32 (unsigned integer 32 bit which equals Longword). That is why we initially made variable pixellocation of type Pointer which will point at values of size Longword. In the first cycle i has the value of 1. So from the first line we see that pixellocation points at the colour value of the screens first pixel. This pixel is black. In the second line the colour value for a black pixel is generated and given to pixelcolor. The third line allocates the black colour value to the first pixel. This actually doesn’t change anything.

If you compare these three lines of code with the previous ones you will see just minor differences. In the first line pixelcolor additionally is increased by 1 which means we refer here to the pixel next to the previous one. The pixel colour defined here (line 2) is another one, it is yellow. Therefore red has to be 255, green has to be 255 and blue has to be 0. The third line is identical.

Now you get a clear picture of what actually is happening to get the effect of a moving pixel. For each cycle the yellow pixel from the previous cycle is overdrawn by a black pixel and then the very next pixel is drawn yellow. This leads to the impression of a moving pixel.

When all pixel manipulations are done the screen has to be refreshed as known by SDL_FLIP. To be able to recognize all the pixel movement the loop has to be slown down by known SDL_DELAY. The loop is left if the user presses a key. Finally the allocated memory of the Pointer variable pixellocation and the screen surface are free’d by known DISPOSE and SDL_FREESURFACE. The SDL system is quit by known SDL_QUIT and the program stopped by END.

This file contains the source code: chap4.pas (right click and “save as”)
This file is the executable: chap4.exe (right click and “save as”)

If you didn’t check the demo03.pas program from last chapter you really should check it now. It demonstrates how you can use the pixel by pixel manipulation to create nice effects and the basis for a simple game.

This file contains the source code: demo03.pas (right click and “save as”)
This file is the executable: demo03.exe (right click and “save as”)

The final result should look and behave like this: You have to look quite carefully to recognize a single yellow pixel moving from the left top corner, line by line down until it reaches the right bottom corner.

Result of JEDI-SDL Chapter 4

Chapter 3: Displaying a picture (JEDI-SDL)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

Working with the video subsystem assumes that you understand the concept behind. In SDL the surface is a central concept. Surfaces are parts of the memory (RAM) where an image is saved. Every surface can have its own size (pixels x pixels, e.g. 640 x 480) and properties (e.g. with or without alpha channel for transparency effects). You can copy(=blit) a part or the whole surface to any other surface. This is the second very important concept and is called blitting

There is a special surface: the display surface. Everything that got blit to this surface gets displayed on the physical screen (monitor) after refreshing (SDL_FLIP(…), SDL_UPDATERECT(…))!

For example in demo03.pas / demo03.exe from a modified SDL4Free Pascal demo file the ball, the paddle and the black background (display surface background color) are surfaces. The ball and the paddle are copied(=blitted) onto the black screen surface again and again slightly moved up. So the ball and the paddle seem to move.

left: ball and paddle erased between each frame; right: ball and paddle not erased between framesIf you think carefully about this or check the source code you will notice that between every blitting process the ball and paddle of the previous frame have to be overdrawn by black rectangles erasing them (left), otherwise the result would look like the right example.

diagram showing path from image file to displaySo our task is to create a display surface. Furthermore we need a surface that contains a picture. Eventually the picture should get copied onto the display surface. After that the picture should be displayed at the physical screen. The whole code looks like this.

Now we need a command to create a display surface. Creating a surface is always introduced by setting up a surface variable. The variable type is pSDL_SURFACE and is kind of pointer type as indicated by the “p” in front of it. pSDL_SURFACE is used for the display surface and any other surface.

The first line determines the program name. Then we again define that we want to use the SDL unit to be loaded. We introduce the CRT unit which is a basic Pascal unit (check Chapter 2 for more details on CRT). It is needed to detect in a simple way when the user presses a key to stop the repeat/until loop (in Chapter 6 we will learn how SDL handles keyboard interactions). Finally we decide to set up two surfaces. The display surface (screen) has some special properties that can be set. The surface “picture” will store the picutre from a bitmap file. The two variabes “source_rect” and “destination_rect” will be used later to define some rectangles. More details on this later in this chapter.

After using surfaces you have to clean the memory if you don’t need them anymore. Therefore you use the procedure SDL_FREESURFACE(surface:pSDL_Surface) which you have to call for any surface (including the display surface).

After initializing SDL as seen in the previous chapter already we now go into details on the set up of the display surface. The function to define a surface as display surface is SDL_SETVIDEOMODE(width,height,bpp:INTEGER; flags:UInt32):pSDL_SURFACE and returns NIL if an errors occurs meaning no pointer for a display surface could be set up. The first parameter determines the width, the second one the height in pixels. The third parameter determines the colordepth in bits (32 bit for now) and the last one the appearance (windowed or fullscreen, with or without border) and space handling (software or hardware memory used). The first three parameters are of integer type, the last one UInt32 (check Chapter 2 for more details on UInt32). There are some very interesting flags. The chosen one, SDL_SWSURFACE, is used if you want to store the surface in system memory (RAM). Alternatively you could chose SDL_HWSURFACE what causes a storage in video memory. Both will create windowed screens that cannot be resized. SDL_NOFRAME would create a windowed screen without a frame. Eventually there is SDL_FULLSCREEN which leads to a fullscreen display. You also can combine several flags by “OR” keyword. So setting up this same window without a frame would be screen:=SDL_SETVIDEOMODE(200,200,32,SDL_SWSURFACE OR SDL_NOFRAME).

Direct loading of a picture to the screen surface is impossible so it is necessary to create another surface that contains the picture. Fourtunately there is a function called SDL_LOADBMP(filename:pCHAR):pSDL_SURFACE. Make sure you give the FULL path for “filename”; relative pathes are not allowed. If you drew something onto the screen and would like to save it as a bitmap file the corresponding function is called SDL_SAVEBMP(surface:pSDL_SURFACE; filename:pCHAR):INTEGER. The surface you want to save doesn’t have to be necessarily the screen surface. It returns 0 on success and -1 on error. Incidentally there is no such import/export feature for other graphic formats (that doesn’t mean there are no other easy ways to use other important graphic formats ;), check Chapter 3a for details on this).

Free Pascal meets SDL sample image bmp format
download (right click and “save as”)

This picture (8 bit) is the one that will be copied to the screen. The pictures width and height are both exactly 200 pixels.

The surface is named “picture” here and the file fpsdl.bmp is located at the given directory, “C:\FPC\2.0.4\test”. As already known from setting of the screen variable the SDL_LOADBMP(path) function returns NIL if something is wrong. The path has to be of type pCHAR.

Actually we now could copy the loaded picture from the picture surface to the display surface. Remember: This process is called blitting. But to demonstrate another quite usable feature strongly related to picture blitting we will now define some rectangles. Instead of blitting the whole image we are then also able to blit just parts of the source image.

Now let’s have a look at the code. We define the rectangles called source_rect and destination_rect which store what part of the source image will be copied to what position at the destination surface (here: display surface). The command NEW(pointer) is a common Pascal command and should be known. source_rect and destination_rect are of type pSDL_RECT and are simple records which store a (x,y) and a (width, height) pair. The values set for both rectangles are identical. They are further exactly of the same size as our display surface and our image. The coordinates of x and y relate to the corresponding surface so (x/y) is (0/0) here for both rectangles and corresponds to the left upper corner. From this point to the right direction the width is 200 pixels. The height is from this point 200 pixels down to the bottom side of the display surface. The following image may explain this.

The display surfaceNext we will enter the repeat/until loop.

SDL_BLITSURFACE(src:pSDL_SURFACE; srcrect:pSDL_RECT; dst:pSDL_SURFACE; dstrect:pSDL_RECT):INTEGER is the needed command for blit processes. For successful blitting (copying) four parameters are requested. The first determines the source surface, the third the destination surface. The second and the fourth parameter can be NIL. Then the whole source surface is blitted to the (0,0) position (upper left corner) of the destination surface. If you want to blit the source surface to any other position on the destination surface (which is usually the case) you have to provide the coordinates by usage of the pSDL_RECT record. In the first run the content of surface “picture” within the defined rectangle of “source_rect” (x/y)=(0/0) and (w/h)=(200/200) is blitted to the display surface within the defined rectangle of “destination_rect” (x/y)=(0/0) and (w/h)=(200/200). Actually this means the complete content of the “picture” surface is blitted to the display surface.

After the blit process is finished the display surface has to be refreshed. Procedure SDL_UPDATERECT(screen:pSDL_SURFACE; x,y:SInt32; w,h:UInt32) or function SDL_FLIP(screen:pSDL_SURFACE):INTEGER are doing that. The SDL_FLIP(screen surface) command you use if you want to refresh the whole screen surface and furthermore if you want to use double buffering. For most applications and games therefore the SDL_FLIP(screen surface) is much more common. It is equal to SDL_UPDATERECT(screen surface,0,0,0,0) if double buffering is disabled. In comparision to SDL_UPDATERECT, SDL_FLIP furthermore returns an error value, 0 if successful and -1 on error.

The SDL_UPDATERECT command requests five parameters. The first parameter determines which surface has to be refreshed (usually the display surface). The next four ones determine a rectangel with: x-position, y-position (from top to bottom), width (relative to x,y-position), height (relative to x,y-position). If all of these paramters are “0” the whole surface will get updated.

In the example for any further cycle though the x, y, w and h values get incremented or decremented as shown. The destination-x and y values get incremented by one each cycle so it is progressing to the right bottom corner. This leads to the impression that the picture is slipping to the right bottom corner. The width and height values are fit respectivly.

The new introduced SDL_Delay(msec: UInt32) procedure works the same way as the common delay command of the CRT unit in Pascal. It delays the run of the program for the given time in milli seconds. This is a key procedure for nearly any program. If you would remove the delay procedure the program is running so fast, you wouldn’t be able to recognise the shifting but see some flickering. Since this sometimes even leads to abortions of the program I do not advise you to try it out.

ATTENTION: For a fast and clean blitting you should note that both surfaces (source and destination surface) should have the same bit depth! In our example we use a 32 bit screen surface (screen) and blit an 8 bit source surface (picture) onto it (because we loaded an 8 bit image file (fpsdl.bmp) to this surface). This is just an example and therefore it is okay, but you should avoid this especially if you plan to create games or applications where the FPS (frames per second) count is important.

The Repeat loop shrinkens the source rectangle from bottom right corner. At the same time the position at the destination surface is increased at the same rate. When the rectangles are of size 1 all values get restored.

When any key is pressed the loop is exited.

The allocated memory of the picture and the display surface and of both rectangles get disposed. Finally SDL has to be quit and so has the program.

This file contains the source code: chap3.pas (right click and “save as”).
This file contains the executable: chap3.exe (right click and “save as”).

Hope you are successful and have fun. The final result should look and behave like this: The blue box with the text “Free Pascal meets SDL” is slipping to the right bottom corner. When it disappears the scene is reset.

Result of example program

Chapter 2: First steps using SDL (JEDI-SDL)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

You should be slightly experienced in programming Free Pascal. That means you should be familiar with procedures, functions, loops and usual commands of Free Pascal. If this is not the case you may have problems because this tutorial deals with the features and usage of the SDL library and will not explain basic concepts of Pascal programming. Here I have to set the CRT unit off which was provided along with Turbo Pascal and is also available for Free Pascal by default. It was used in Turbo Pascal for screen and keyboard handling. In many chapters this unit will be used becaused it allows a simple way to recognize if a user pressed a key by a REPEAT … UNTIL keypressed statement. However, this unit is not related to SDL. SDL’s own advanced keyboard handling described in Chapter 6 is not used to keep the code short.

In the original SDL library there are several standard units (called headers in C/C++) whereas in JEDI-SDL all of them got merged to only one unit called “SDL”. To prepare your Free Pascal program for the usage of SDL you just have to call this unit at the uses clause. The SDL unit is the heart of every SDL application!

The different features of SDL (screen handling, audio handling, keyboard handling, cdrom handling, and so on) have to be initilized using the SDL_INIT(flags:UInt32):INTEGER function. You may wonder about the variable type UInt32 of “flags”. The U stands for “unsigned” (values greater or euqal zero only!), the Int stands for “integer” and the number stands for the bit value. So it is an 32 bit unsigned integer (which corresponds to Free Pascal’s longword). Such integer types (which we will see in other chapters again) originate from the original C/C++ SDL code, and for an easier translation to Pascal they were kept.

In the first example we want to initialize the SDL video subsystem for screen handling. The following code example shows the frame of a SDL application.

Instead of SDL_INIT_VIDEO you could initilize the respective subsystem by using SDL_INIT_AUDIO, SDL_INIT_CDROM, SDL_INIT_JOYSTICK, SDL_INIT_TIMER, SDL_INIT_NOPARACHUTE, SDL_INIT_EVENTTHREAD, SDL_INIT_EVERYTHING. So if you want to use the features provided by the library for sound handling you should initialize it by using SDL_INIT_AUDIO. If you use SDL_INIT_EVERYTHING all subsystems are initialized. You also can combine several components by the OR keyword, e.g. “SDL_INIT(SDL_INIT_VIDEO OR SDL_INIT_AUDIO)” to initilize video and audio support. If you are running some subsystems already but need to load further ones you would use SDL_INITSUBSYSTEM(flags:UInt32):INTEGER respectivly.

If you look at the exact definition carefully you may wonder about the integer value the function returns. You shoud notice that every SDL function usually returns an error value for you to check if the function runs properly at runtime. There is no general rule what values correspond to which status. Usually values like 0 and 1 correspond to a status “function runs successfully”, values 0 and -1 correspond to a status “function couldn’t be run, something is wrong”. For SDL_INIT the function is run successfully if it returns 0, otherwise there is something wrong. However, in most cases I won’t do error checking to keep code examples short but will mention the error values to be expected.

Every SDL program has to be closed by SDL_QUIT. It cleans up your system. Never forget it! This procedure ensures that all subsystems initilized get unloaded. There is a corresponding procedure to unload specific subsystems defined as SDL_QUITSUBSYSTEM(flags:UInt32 ). The same arguments you use to load subsystems you can use here to unload them.

Now you can try the example program.

Well, we have initilized the video subsystem and released it afterwards. Simple Directmedia Layer deserves its name, isn’t it?

Chapter 6: Event handling (SDL4FP)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

If the user is moving the mouse, pressing/releasing a button on the keyboard or pressing/releasing the fire key on the joystick then you speak of events. Further events are resizing a window or switching between several applications. For games though the events described first are much more important. SDL provides a quite easy way to notice and react to such events, which is called event handling.

First of all using event handling means to understand the concept of event handling. Events have a special structure you should know about. For example an pressed key is an event or a moved mouse is an event. SDL differs altogether fourteen such events. Every event stores different information depending on its kind. For example the key board event stores the information which key was pressed. The mouse motion event stores the information to which position the mouse got moved. If you got a mouse motion event you can’t read out key information and so on. Therefore you have the following general structure to the event data: event.eventstructure.data.

To make event handling possible you have to include the unit SDL_EVENTS. The event handling subsystem is automatically initialized along with the video subsystem.

We have to create an event variable which is of pointer type pSDL_EVENT. We will create a second variable of boolean type just to control the while loop.

We want to check the program if any event occured and if so, we want to know which kind of event happened. So we make a while loop which will run until loopstop gets true.

The command SDL_POLLEVENT(parameter) checks if there are pending events and if so it will take the oldest and save it to parameter which is an event record of pSDL_EVENT type. For example if the user presses (then releases) left mouse button, then presses (then releases) space button on keyboard and finally moves the mouse there are altogether five events: 1. left mouse button pressed, 2. left mouse button released, 3. space key pressed, 4. space key released, 5. mouse moved. If you poll for events now you will get the first event (left mouse button pressed) and saved it’s properties to the event variable we specified as parameter. The next poll will save the properties of next event (left mouse button released) to event variable and so on. SDL_POLLEVENT(parameter) will return 1 if it has found pending event or 0 if there wasn’t any pending event.

Fortunately you don’t have to notice any event which is made by the user ;). By event^.eventtype you can easily check which type of event you got. In the case described before it would be 1. SDL_MOUSEBUTTONDOWN, 2. SDL_MOUSEBUTTONUP, 3. SDL_KEYDOWN, 4. SDL_KEYUP, 5. SDL_MOUSEMOTION. It should be senseful to check for the event kind by using the case command.

Actually you shouldn’t try this source as it is written there because it will end up in an endless loop. The DELAY command is used because otherwise you won’t notice any pending events because they are polled too fast and it seems as if there would never be any pending events (just remove DELAY to confirm).

We now want to try the program to read out which key the user pressed on the keyboard. If the key is the escape-key (Esc) the program should stop. We already check the type of the event we polled. So if the event is a keyboard event the further checking should proceed. In our case especially if a key gets pressed. An keyboard event record contains a field called keysym. Keysym is a record of SDL_KEYSYM. SDL_KEYSYM is defined in SDL_KEYBOARD unit. It contains four fields. Scancode which is hardware dependent scancode should be avoided if you want to make hardware independent programs. It is usual integer variable. Next is sym which stores SDLKEY. These SDL keys are independent and it is strongly recommended to use them! In the example we want break up if escape key gets pressed. Its SDL key code is 27. If you want to know what SDL keys are defined look up in the table page. The variable modifier stores modifier keys (like shift, ctrl,…) pressed and stores SDLMod. SDL modifier keys can be found at table page as well. The fourth variable is unicode which may be used to read out unicode characters but to use this you have to enable it what is not described in this tutorial.

To read out or compare the key the user pressed we must use the expression test_event^.key.keysym.sym. Do you remember the general structure of an event (event.eventstructure.data)? – test_event^ is the event, the event structure is defined as an key event by key and the data we want to know is the key pressed contained in keysym.sym.

Actually this is easy, isn’t it?

This file contains the source code: chap6_1.pas (right click and “save as”)
This file is the executable: chap6_1.exe (right click and “save as”)

ATTENTION: This is just the first part. The second part will describe mouse handling, which is much easier.

Chapter 3: Displaying a picture (SDL4FP)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

Working with the video subsystem assumes that you understand the concept behind. The screen is supposed to be a surface (everything on this surface gets displayed on the physical screen!). Every object you want to display on the screen can be an own surface. Every object can be copied to the screen surface. Surfaces can be manipulated.

For example in the demo03.pp from the SDL4Freepascal files the ball, the paddle and the black background (screen) are surfaces. The ball and the paddle are copied onto the screen surface again and again slightly moved up. So the ball and the paddle are giving the impression that they are moving.

So our task is to create a screen surface. Furthermore we need a surface that contains a picture. Eventually the picture should get copied onto the screen surface. After that the picture should be displayed at the physical screen.

That is where we stopped last chapter. Now we need a command to create a screen surface. Creating a surface is always introduced by setting up a surface variable. The variable type is pSDL_SURFACE and is kind of pointer type as indicated by the “p” in front of it.

The screen surface is a special kind of surface. It has some special properties that can be set. You can set appearance, height, width and colordepth that is displayed by it. The command to make a surface to a screen surface is SDL_SETVIDEOMODE(parameters).

Similar to the SDL_QUIT procedure, after using surfaces you have to clean the memory if you don’t need them anymore. Therefore you use SDL_FREESURFACE(surface).

The function to set the screen surface returns nil if an errors occurs. The first parameter determines the width, the second one the height. The third parameter determines the colordepth (8 bit for now) and the last one the appearance (video mode) and space handling. The first three parameters are longint typ, the last one Uint32, where the U stands for “unsigned” (values greater or euqal nil only!), the int stands for “integer” and the number stands for the bit per pixel count. So it is an 32 bit unsigned integer. There are some very interesting values. The chosen one, SDL_SWSURFACE, is used if you want to store the surface in system memory (RAM). Alternatively you could chose SDL_HWSURFACE what causes a storage in video memory. Both will create windowed screens that cannot be resized. SDL_NOFRAME would create a windowed screen without a frame. Eventually there is SDL_FULLSCREEN which leads to a fullscreen display. There are some other possibilities which may be told about in further chapters.

If you run the program you see a black window because nothing is located on the screen surface.

It is necessary to create another surface that contains the picture. Then we need a possibility to load the picture to the surface. Fourtunately there is a command called SDL_LOADBMP(file). The corresponding command is called SDL_SAVEBMP(surface,file) if you drew something onto the screen and would like to save it as a bitmap file. Incidentally there is no such import/export feature for other graphic formats (that doesn’t mean there are no other easy ways to use other important graphic formats ;)).

Free Pascal meets SDL sample image bmp format
download (right click and “save as”)

This picture (8 bit) is the one that will be copied to the screen. The pictures width and height are both exactly 200 pixels.

The surface is named “picture” here and the file fpsdl.bmp is located in the same directory as the source file. As already known from setting of the screen variable the SDL_LOADBMP command returns nil if something’s wrong.

In the end we need to copy the loaded picture from the picture surface to the screen surface. This process is called blitting and is made by this command: SDL_BLITSURFACE(parameters).

After the blit process the screen surface has to be refreshed. SDL_UPDATERECT(parameters) is doing that.

For successful blitting four parameters are requested. The first determines the source surface, the third the destination surface. The second and the fourth parameter can be used if you don’t want to blit the whole surface but a certain rectangle. So you could determine that you want to blit just the upper left quarter of the picture surface (second parameter). Furthermore you could want it copied to the lower right quarter of the screen surface (fourth parameter). If these parameters are nil it means the whole surface is blitted.

As you can see the SDL_UPDATERECT command requests five parameters. The first of them determines which surface has to be refreshed. The next four determine a rectangel with: x-direction, y-direction (from top to bottom), width (relative to x,y-position), height (relative to x,y.position). If all of these paramters are “0” the whole surface will get updated.

This file contains the source code: test.pas (right click and “save as”). The file and the graphic file have to be in the same folder.

Hope you are successful and have fun.

Chapter 5: Writing and using fonts (SDL4FP)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

What you need:

Software Source Description
sdl_ttf.pp http://cvs.sourceforge.net/viewcvs.py/sdl4fp/extras/
Downloads
Unit file to handle fonts.
SDL_ttf.dll http://www.freetype.org/index2.html
Windows: http://gnuwin32.sourceforge.net/packages/freetype.htm
This is the corresponding dynamic link library file.

This chapter will introduce you on how to load fonts and write to the screen. There are two things to do for preparation. First of all we have to change the compiler settings because a new unit, called SDL_TTF, gets included. This unit uses the “result” command to return values of functions. This is a command from Object Pascal. So the compiler has to support it’s syntax otherwise he won’t accept this command. To let the compiler support the Object Pascal syntax go to “Options” and then “Compiler…” A new window will pop up. From “Syntax” mark the option “Object pascal support”. Now SDL_TTF can be used.

In version 1.2.0.0 of SDL4Freepascal this unit isn’t included. It has to be separately downloaded. You can download it here: http://cvs.sourceforge.net/viewcvs.py/sdl4fp/extras/ or from the download section. The file “sdl_ttf.pp” has to be copied to the sdl unit folder where all the other sdl units are located (e.g. C:\FPC\units\).

Analogous to SDL.dll in chapter 1 you have to download the last stable release of FreeType which can be found here: http://www.freetype.org/index2.html (Windows: http://gnuwin32.sourceforge.net/packages/freetype.htm ). You should extract the file and get two files. A text file and the important SDL_ttf.dll. These files you copy to the system32-folder.

Now let’s begin with the interessting part. The goal is to get a text with a certain font and colour to the screen. Of course we need the screen surface again and a surface onto which can be written. Furthermore the new unit has to be loaded.

To initialize the TTF (True type font) system you have to use TTF_INIT which returns -1 if something goes wrong. Notice that the whole true type support is an own additional project to the SDL library, so this has not to be initilized by the SDL_INIT command.

To load a certain font you use TTF_OPENFONT(font,point size). This command is a function that returns a usual pointer! The parameters are the path to the font (e.g. C:\WINDOWS\fonts\arial.ttf) and the point size which detemines the size of the letters. Furthermore as SDL surface has to be free’d and SDL system has to be quit so has TTF system. The commands TTF_CLOSEFONT(font) and TTF_QUIT have to be used to do this.

So next we have to determine the colour of the letters and the messege itself. The colour is determined by a pSDL_COLOR record, which is of course kind of pointer. In pSDL_COLOR record there are three elements (actually four, but the forth is unused) which can be accessed by .r,.g and .b and determine as common the shares of red, green and blue colour. You will agree that writing a function for this can be senseful, especially if you have to handle many different colours. The fact that pSDL_COLOR is a pointer type we have to set up it by NEW command and free it finally by DISPOSE. This commands you should familiar with because they are usual Pascal commands.

Now we use TTF_RENDERTEXT_SOLID which returns a pSDL_SURFACE. We return it to fontface. The parameters are the used font as pointer (loaded_font), the messege string and the colour as value of pSDL_COLOR (colour_font).

Finally we have to blit the fontface surface, on which now the messege is written, to the screen surface and update the screen surface.

Now you are able to write ;).

This file contains the source code: chap5.pas (right click and “save as”)
This file is the executable: chap5.exe (right click and “save as”)

[Downloads transferred from old website]

sdl_ttf.zip; FOR OUTDATED SDL4FP PACKAGE! Unit file for font support. (right click and “save as”)

Chapter 4: Drawing pixels (SDL4FP)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

Okay. Maybe you think, why to learn how to display pictures first and then learning about the more basic feature to draw single pixels to the screen? – In chapter 3 you learned beside displaying a picture how common SDL programs are strctured. Furthermore this chapter will get a little bit longer because several things have to explained more detailed to impart a fully understanding. In chapter 3 that was not necessary.

So here we go. First of all we have to know about the meaning of pixels. The physical screen consists of many small units. Every unit consists itself of three different coloured lights. These colours are red, green and blue. If you mix them (additive) you can get every colour. For example if you mix red and green you receive yellow. For three colours that can be mixed with each other there are eight combinations possible which lead to different colours (RGB, RG, RB, R, GB, G, B, all lights off). Some of you may say RGB (white) and all lights off (black) are no colours. That is right but doesn’t matter here and to keep simpliness I will talk of colours even if I talk of black and white.

Did you get confused? Your screen definitvly has more than eight colours, doesn’t it? The reason is, your screen isn’t just able to put on or off lights. Besides it is in position to differ the intensities of the lights. The more intensity levels you have the more colours you can display. The case that you have eight colours as discussed before means that you just have one intensity level. If your screen is in 8 bit mode every pixel on the screen has the possibility to display 2 power 8 colours. That are 256 different colours. Every of the three lights has therefore a certain amount of different intensity levels. There are the red and the green light with eight intensity levels each and the blue light with four intensity levels. If you have 16 bit mode you have 2 power 16 and that are 65536 colours. Each light therefore must have the appropriate amount of intensity levels.

All the examples will be made in 8 bit mode. If you want to write directly to the screen surface it is possibly necessary that you lock it. We work in software mode (SDL_SWSURFACE) so we can leave locking the screen surface. The screen surface is a RECORD of many different data types. To read or write pixels of or to a surface there is a typ marker called “pixels” which is of pointer type. It points at some pixel of the surface. The location gets allocated to a pointer of WORD, namely “pixellocation” we define.

It is unknown to us where to the surface it is pointing. This may not matter now; this we will treat later. Before we should allocate a colour to the pixel. Up to now we just have handed over the location to “pixellocation”. Yellow is the pixel colour we want to get. Red has to be 255, green has to be 255 and blue has to be 0 to get yellow. The function SDL_MAPRGB(pixel format, red, green, blue) is used to transform that input values into one longinteger (Uint32) code. The pixel format is given by the screen surface. We will use its pixel format by using screen^.format what contains the pixel format information of the screen surface. The calculated “colour code” is handed over to a new defined variable called “pixelcolor”.

So you have stored the location of the pixel to manipulate in variable pixellocation. You have stored the information of the colour you want to receive in pixelcolor. Eventually you have to allocate the pixel colour to the pointed pixel at the surface. That’s it. Of course we have to update the screen surface after the drawing.

If you look careful to the screen (when running program) you may see the pixel (left upper corner). After this success we want to see the pixel run along the screen! That will help you understand easily how the positioning of the pixel works, probably better as if I try to explain. We define a repeat-unitl loop what will delete old pixel (colour: black) and write a new one exaktly moved up by one pixel.

So the position which is pointed by pixels pointer is set by adding to or substratcing from the position before. As can be seen in the program the pixel position is increased by one and so is the value of where screen^.pixels pointer is pointing at.

If you create a surface of width and height of 200 pixels as in the example the true surface can be a little bit wider. This means you have a window of width and height of 200 pixels displayed but there is an additional unvisible piece of surface. Maybe its width is 210, so the moving pixel in the last example would restart a few lines before end of window. To solve problems cause by this pitch to the surface you can read it out. The data type pitch will allow you to (e.g. screen^.pitch).

This file contains the source code: chap4.pas (right click and “save as”)
This file is the executable: chap4.exe (right click and “save as”)

Chapter 2: First steps using SDL (SDL4FP)

This is an SDL 1.2 chapter. SDL 1.2 is obsolete since it has been replaced by SDL 2.0. Unless you have good reasons to stay here you may prefer to go for the modern SDL 2.0 :-).

You should be slightly experienced in programming Freepascal. That means you should be familiar with the usual commands of Freepascal. If this is not the case you may have problems because this tutorial deals with the features of the usage of the SDL library.

Now let us begin. There are several units given that can be used. If you want to use SDL library you must include the unit “SDL”. It is needed to initialize any other component of the library. For example there are units called “SDL_audio”, “SDL_video”, “SDL_keyboard” and so on. You can draw conclusions on their meaning from their names. So let us start with the initialization of the SDL video system. The command needed to initialize any component is SDL_INIT(component);

Instead of SDL_INIT_VIDEO you could initilize the respective component by using SDL_INIT_AUDIO, SDL_INIT_CDROM, SDL_INIT_JOYSTICK, SDL_INIT_TIMER, SDL_INIT_NOPARACHUTE, SDL_INIT_EVENTTHREAD, SDL_INIT_EVERYTHING. So if you want to use the features provided by the library for sound handling you should init it SDL_INIT_AUDIO. If you use SDL_INIT_EVERYTHING all subsystems are initialized.

There is another very important command: SDL_QUIT. Every program have to be closed by using this command. It cleans up your system! Never fotget it. This procedure ensures that all subsystems initilized get unloaded. There is a corresponding command to unload specific subsystems called SDL_QUITSUBSYSTEM(component).

Well, we have initilized the video subsystem and released it after that. Simple Directmedia Layer deserves its name, isn’t it?