📜 ⬆️ ⬇️

Common Lisp SDL2 Tutorial

SDL2 is an excellent library, but there are not very many tutorials on it.
Common Lisp is a great language, but there are too few articles on it.
I think this is quite enough to write this series of articles.

Why did I choose generalized? Well, the taste and color as they say.
However, there are reasons:



In fact, this series is an adaptation of tutorials from Lazy Foo:
lazyfoo.net/tutorials/SDL/index.php
')
In this article I will not explain in detail how to put all the necessary software, but
if someone is really interested, please write about it
in comments.

To install SDL2, use the following tips: lazyfoo.net/tutorials/SDL/01_hello_SDL/index.php .

As for Lisp, I use the www.sbcl.org and www.quicklisp.org implementation .
At the moment, performance was tested only in it.

Next, I use the cl-sdl2 library: github.com/lispgames/cl-sdl2 .
It just so happened that the support of some functionality from SDL2, for example
surfaces, it is not fully implemented. But it does not matter, I finish
the necessary functionality as you move through the tutorials. Therefore not
install the quicklisp version, and immediately clone the master branch into ~/quicklisp/local-projects .

It is assumed that you minimally understand the syntax of the Lisp and not be afraid of the abundance of brackets.
As the main means of interaction with Lisp environments, I will use slime.
Have you tried spacemacs yet ? Then we go to you!

For those who do not need lyrics, but need a code: github.com/TatriX/cl-sdl2-tutorial

White screen life


Let's start with the fact that we just make SDL2 show us a window filled with white.

Obviously, we will need the cl-sdl2 library itself. Connect it:
 CL-USER> (ql:quickload :sdl2) 

We will not complicate the task and create a window of a fixed size.
To do this, we will declare global (and moreover special ) variables for the width and height of our window, because magic numbers are evil.
 (defparameter *screen-width* 640) (defparameter *screen-height* 480) 

Now we will create a function that will open a window for us, fill
its white color wait some time and close.

Just call our main function and add an optional one to it.
named parameter so that we can adjust the time through which
the window will close. The default is two seconds for our eyes.
 (defun main (&key (delay 2000)) 

Then we need to initialize sdl2, telling the libraries which
subsystems we want to use. To do this, cl-sdl2 provides us with a convenient macro:
  (sdl2:with-init (:video) 

We want to use only the graphics output subsystem, therefore
give the symbol: video. You ask, "as I should have known,
what needs to be transferred: video? "We answer: cl-sdl2 transforms
Sdl_ constants in corresponding characters. For example,
we can open the documentation for the SDL_Init method and see
available flags: wiki.libsdl.org/SDL_Init#Remarks
To get the required character, we cut off the name SDL_INIT_ and
convert the flag to lower case.

The beauty of with- macros is that they are mandatory
free all allocated resources, freeing us from the need
follow up on your own.

Ok, next we will create a window:
  (sdl2:with-window (window :title "SDL2 Window" :w *screen-width* :h *screen-height*) 

This is another macro. This time the first item in the list
the macro arguments will be the window symbol, through which in the body
macro, we will refer to the created window. Named
Parameters: title,: w,: h I think are quite obvious and do not need
explanations.

Everything is clear with the window, but now we want to fill the resulting window with white
color. One of the options for implementing the plan is to use
"Surfaces", they are surfaces. In essence, the surface is a structure.
containing pixels of a certain area, used in software
rendering. For example, we can get the surface of our window:
  (let ((screen-surface (sdl2:get-window-surface window))) 

and fill it with white:
  (sdl2:fill-rect screen-surface nil (sdl2:map-rgb (sdl2:surface-format screen-surface) 255 255 255)) 

The first argument is the rectangle that we want to fill. If its not
pass, we will fill the entire area. Why wretched #fff
write in such a complicated way? It's all about the variety of formats
pixels, screens and the like. And since the SDL2 library
cross platform for applying all necessary transformations
various functions are used, such as map-rgb in this case.

Pour the window filled, but this is not enough. Now we need to politely ask the library to update our window:
  (sdl2:update-window window) 

Considering that the entire process described for so long takes place in a split second,
but we still want to enjoy the result, ask sdl to wait a bit:
(sdl2: delay delay)
And most importantly:
 ))) 


That's all. It remains to run our creation, and hope that we will not fly into the debugger:
 CL-USER> (main) 




Just in case,
source fully
 (defparameter *screen-width* 640) (defparameter *screen-height* 480) (defun main (&key (delay 2000)) (sdl2:with-init (:video) (sdl2:with-window (window :title "SDL2 Window" :w *screen-width* :h *screen-height*) (let ((screen-surface (sdl2:get-window-surface window))) (sdl2:fill-rect screen-surface nil (sdl2:map-rgb (sdl2:surface-format screen-surface) 255 255 255)) (sdl2:update-window window) (sdl2:delay delay))))) 



Honestly, I planned in one article to tell right away about the first three tutorials, but somehow already so much text came out.

For the impatient, once again the link to the tutorial code (at the time of this writing, 16 pieces):
github.com/TatriX/cl-sdl2-tutorial

I hope it was interesting and informative.

Source: https://habr.com/ru/post/275651/


All Articles