My_first_sdl2

by Steven Binns: Y12 Age ~18

Introduction

You can see from his very thorough comments that Steven has written this program to help other students to get started with SDL2. He developed his program in Lazarus, which (once you have set it up for SDL2) is easier to use than the Free Pascal IDE on which the tutorials at Freepascal meets SDL are based. The following screenshot shows the compiler options in Lazarus after the necessary changes. We include the SDL2 folder and its contents in my_first_sdl2.zip. To run the program, unzip the downloaded file into a convenient folder and double click on My_first_sdl2.exe.

Compiler options

Compiler options

The Program

program My_first_sdl2;
{
    Copyright (c) 2014 Steven Binns

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}
{$apptype gui}

uses
  Classes, SDL2;

var
  { Something new in SDL2 compared to SDL1.2 is the idea of windows and renderers.
    These new types are used for the new support of hardware acceleration
    to directly use the graphics card, allowing for much faster processing as the
    graphics card is almost entirely devoted to doing the graphical calculations
    rather than sharing processing time with the other programs and processes.}

  scene: pSDL_Window;
  renderer: pSDL_Renderer;
  i: integer; //basic count variable
  rect: pSDL_Rect; //An sdl rectangle structure

begin
  Randomize;

  { Dedicate some memory space for pointers ahead of time so we don't end up with incongruous
    memory spaces (which cause some nasty errors) }
  new(scene);
  new(rect);

  {Start up SDL video mode and check that it starts correctly.}
  if SDL_INIT(SDL_INIT_VIDEO) < 0 then
  begin
    HALT; //If SDL_INIT fails for some reason, it will return a value less than 0, in which
          //case we need to stop the program.
  end;

  { Now we need to create our window and check whether that has started correctly.
    This function creates the window we are going to render to.
    The name at the front is what appears in the window heading by default, unless you change it specifically.
    The first two numerical values are the offsets of the window from the top left of your monitor (in pixels).
    The second two numerical values are the width and height of the window respectively.
    The final parameter is a flag for the type of window. We don't need to know about this for this
    tutorial so use the default SDL_WINDOW_SHOWN. }
  scene := SDL_CreateWindow('My First SDL2', 100, 100, 400, 400, SDL_WINDOW_SHOWN);

  if scene = nil then
    halt; //If the window creation fails then scene has a nil value.

  { Now we need to create our renderer and check whether that has started correctly.
    This function creates the renderer, which is the equivalent of and sdl1.2 surface; it's what
    we do all our drawing on.
    The first value is the SDLWindow object you want this renderer to render to. This implies
    that you can have multiple screens open through SDL2 at a time!
    The numbers in here do fancy things that we don't need for this tutorial so just leave
    them at these default values.}
  renderer := SDL_CreateRenderer(scene, -1, 0);
  if renderer = nil then
    halt; //If the renderer creation fails then renderer has a nil value.

  { Set the drawing colour for future primitive or pixel drawing functions using the
   renderer object and R,G,B,A values.}
  SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

  { In sdl2, you don't have to draw a black rectangle to the screen every time you want
    to clear it. There's now a function on the renderer that does it for you: }
  SDL_RenderClear(renderer);

  SDL_RenderPresent(renderer); //Also, sdl_flip has been replaced with sdl_RenderPresent

  SDL_Delay(100); //Give ourselves a moment before we begin.

  { In this next section of code, we're going to draw 10 expanding squares on top of
    each other, one after another.}
  for i := 0 to 9 do
  begin
    rect^.x := 200; //These 4 lines set the properties of our rectangle object.
    rect^.y := 200; //The properties are, in order: x position, y position, width and height.
    rect^.w := 0;
    rect^.h := 0;
    { Each rectangle is going to be a random colour so pick random values for each colour
      component: red, green and blue}
    SDL_SetRenderDrawColor(renderer, random(256), random(256), random(256), 255);
    repeat
      rect^.x -= 1; //These 4 lines expand the rectangle by 1 pixel in every direction.
      rect^.w += 2;
      rect^.y -= 1;
      rect^.h += 2;
      SDL_RenderDrawRect(renderer, rect); SDL_RenderPresent(renderer);
      { Be careful here since this function draws an outline of a rectangle. It only works
        because we are expanding one pixel at a time, meaning it is more efficient this way.
        To draw a filled rectangle you'd use SDL_RenderFillRect, which is what you'd need
        if you wanted to change the incrementing values. }

      SDL_Delay(5);
    until rect^.w = 400; //Once the rectangle fills the screen we can move onto the next one so
                         //we exit the repeat loop.
    SDL_Delay(5);
  end;
  SDL_Delay(2000); //When we're done, give us a few moments to take it all in before exiting.

  {Now we need to free all of our assets we used and quit SDL. This allows the memory space
   to be easily used again by other applications and doesn't fragment as much.}
  SDL_DestroyWindow(scene);
  SDL_DestroyRenderer(renderer);
  SDL_Quit;
end.
Programming - a skill for life!

Seven programs including ALifeSim, Invader, My_first_sdl2 and PlatformDemo by Steven Binns