Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/interkosmos/fortran-sdl2
Fortran 2008 interface bindings to SDL 2.0
https://github.com/interkosmos/fortran-sdl2
fortran fortran-package-manager fpm game-development gamedev opengl sdl sdl2
Last synced: 7 days ago
JSON representation
Fortran 2008 interface bindings to SDL 2.0
- Host: GitHub
- URL: https://github.com/interkosmos/fortran-sdl2
- Owner: interkosmos
- License: isc
- Created: 2018-02-28T21:53:47.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-08-12T20:14:25.000Z (over 1 year ago)
- Last Synced: 2024-01-29T14:45:02.737Z (10 months ago)
- Topics: fortran, fortran-package-manager, fpm, game-development, gamedev, opengl, sdl, sdl2
- Language: Fortran
- Homepage:
- Size: 2.78 MB
- Stars: 33
- Watchers: 8
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# fortran-sdl2
A collection of ISO C binding interfaces to
[Simple DirectMedia Layer 2.0](https://www.libsdl.org/) (SDL 2.0), for
2D and 3D game programming in Fortran. SDL versions tested against:Library | Version
-----------|---------
SDL2 | 2.28.2
SDL2_image | 2.6.3
SDL2_mixer | 2.6.3
SDL2_ttf | 2.20.2For bindings to
[SDL2_gfx](https://www.ferzkopp.net/Software/SDL2_gfx/Docs/html/index.html),
see [fortran-sdl2_gfx](https://github.com/freevryheid/fortran-sdl2_gfx).## Build Instructions
If not present already, install SDL 2.0 with development headers (and
optionally: [SDL_image 2.0](https://www.libsdl.org/projects/SDL_image/),
[SDL_mixer 2.0](https://www.libsdl.org/projects/SDL_mixer/), and/or
[SDL_ttf 2.0](https://www.libsdl.org/projects/SDL_ttf/)). On FreeBSD, run:```
# pkg install devel/sdl20 graphics/sdl2_image audio/sdl2_mixer graphics/sdl2_ttf
```Either use GNU/BSD make, [xmake](https://xmake.io/) to build *fortran-sdl2*, or
the [Fortran Package Manager](https://github.com/fortran-lang/fpm) (fpm).### Make
Run `make sdl2` to compile the static library `libsdl2.a`:
```
$ git clone --depth 1 https://github.com/interkosmos/fortran-sdl2
$ cd fortran-sdl2/
$ make sdl2
```On Microsoft Windows, you have to set `LIBGL` and `LIBGLU`:
```
$ make all LIBGL=-lopengl32 LIBGLU=-lglu32
```On macOS, replace `-lGL -lGLU` with `-framework OpenGL`. You can override the
default compiler (`gfortran`) by passing the `FC` argument, for example:```
$ make all FC=/opt/intel/bin/ifort
```Link your Fortran project with `libsdl2.a` and (optionally) `libsdl2_*.a`, or
simply with `libfortran-sdl2.a`:| Library | Compilation | Linking |
|-------------------|---------------------|-----------------------------------------------------------------|
| SDL2 | `make sdl2` | `libsdl2.a -lSDL2` |
| SDL2_image | `make sdl2_image` | `libsdl2.a libsdl2_image.a -lSDL2 -lSDL2_image` |
| SDL2_mixer | `make sdl2_mixer` | `libsdl2.a libsdl2_mixer.a -lSDL2 -lSDL2_mixer` |
| SDL2_ttf | `make sdl2_ttf` | `libsdl2.a libsdl2_ttf.a -lSDL2 -lSDL2_ttf` |
| *all* | `make all` | `libfortran-sdl2.a -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf` |### xmake
Build all static libraries with:
```
$ xmake
```Build a particular library with:
```
$ xmake build
```The default output directory is `build/`.
## Example
The following example shows how to fill a rectangle, using the hardware renderer.
```fortran
! example.f90
program main
use, intrinsic :: iso_c_binding, only: c_associated, c_null_char, c_ptr
use, intrinsic :: iso_fortran_env, only: stdout => output_unit, stderr => error_unit
use :: sdl2
implicit noneinteger, parameter :: SCREEN_WIDTH = 640
integer, parameter :: SCREEN_HEIGHT = 480type(c_ptr) :: window
type(c_ptr) :: renderer
type(sdl_event) :: event
type(sdl_rect) :: rect
integer :: rc
logical :: is_running! Initialise SDL.
if (sdl_init(SDL_INIT_VIDEO) < 0) then
write (stderr, '("SDL Error: ", a)') sdl_get_error()
stop
end if! Create the SDL window.
window = sdl_create_window('Fortran SDL 2.0' // c_null_char, &
SDL_WINDOWPOS_UNDEFINED, &
SDL_WINDOWPOS_UNDEFINED, &
SCREEN_WIDTH, &
SCREEN_HEIGHT, &
SDL_WINDOW_SHOWN)if (.not. c_associated(window)) then
write (stderr, '("SDL Error: ", a)') sdl_get_error()
stop
end if! Create the renderer.
renderer = sdl_create_renderer(window, -1, 0)! Set position and size of the rectangle.
rect = sdl_rect(50, 50, 250, 250)! Event loop.
is_running = .true.do while (is_running)
! Catch events.
do while (sdl_poll_event(event) > 0)
select case (event%type)
case (SDL_QUITEVENT)
is_running = .false.
end select
end do! Fill screen black.
rc = sdl_set_render_draw_color(renderer, &
uint8(0), &
uint8(0), &
uint8(0), &
uint8(SDL_ALPHA_OPAQUE))
rc = sdl_render_clear(renderer)! Fill the rectangle.
rc = sdl_set_render_draw_color(renderer, &
uint8(127), &
uint8(255), &
uint8(0), &
uint8(SDL_ALPHA_OPAQUE))
rc = sdl_render_fill_rect(renderer, rect)! Render to screen and wait 20 ms.
call sdl_render_present(renderer)
call sdl_delay(20)
end do! Quit gracefully.
call sdl_destroy_renderer(renderer)
call sdl_destroy_window(window)
call sdl_quit()
end program main
```To compile the source code with GNU Fortran, run:
```
$ gfortran `sdl2-config --cflags` -o example example.f90 libsdl2.a `sdl2-config --libs`
```## Further Examples
Some demo applications can be found in `examples/`:
* [**alpha**](examples/alpha.png) makes one color of an image transparent (software renderer).
* [**cyclic**](examples/cyclic.png) implements a 2D [cyclic cellular automaton](https://en.wikipedia.org/wiki/Cyclic_cellular_automaton) (hardware renderer).
* [**draw**](examples/draw.png) draws some shapes (hardware renderer).
* [**dvd**](examples/dvd.png) loads a PNG file with SDL_image and lets it bounce on the screen (hardware renderer).
* **events** polls SDL events (software renderer).
* [**fire**](examples/fire.png) renders the [DOOM fire effect](http://fabiensanglard.net/doom_fire_psx/) (hardware renderer).
* [**forest**](examples/forest.png) implements a cellular automaton, based on the [forest fire model](https://rosettacode.org/wiki/Forest_fire) (hardware renderer).
* [**gl**](examples/gl.png) renders a triangle with OpenGL 1.3.
* [**gl3d**](examples/gl3d.png) rotates textured cubes with OpenGL 1.3.
* [**glsphere**](examples/glsphere.png) rotates the camera around GLU spheres.
* [**image**](examples/image.png) loads and displays an image (software renderer).
* **info** prints debug information to console (software renderer).
* **log** prints log messages with `SDL_Log()` (software renderer).
* [**logo**](examples/logo.png) lets you fly through a field of Fortran logos (hardware renderer).
* **msgbox** shows a simple message box (software renderer).
* [**opera**](examples/opera.png) plays an OGG file with SDL_mixer (software renderer).
* [**pixel**](examples/pixel.png) copies an SDL_Surface to an SDL_Texture pixelwise (hardware renderer).
* [**scaling**](examples/scaling.png) displays a scaled image (software renderer).
* [**text**](examples/text.png) outputs text with SDL_ttf (hardware renderer).
* **vertex** shows geometry renderer of SDL 2.0.18.
* [**voxel**](examples/voxel.png) renders a [voxel space](https://github.com/s-macke/VoxelSpace) with direct pixel manipulation. Use arrow keys and Q, A for camera movement (hardware renderer).
* **window** opens a window and fills rectangles (software renderer).Compile all examples with:
```
$ make examples
```If you prefer xmake, build and run an example with:
```
$ xmake build
$ xmake run
```To compile all examples, simply run:
```
$ xmake build examples
```## Compatibility
All Fortran interface names are written in snake case. For instance,
`SDL_CreateWindow()` can be accessed by calling Fortran interface
`sdl_create_window()`. The same is valid for derived types and their
components. Enums and constants have kept their original names.### Null-Termination of Strings
A `c_null_char` must be appended to all strings passed to the interfaces,
except `sdl_set_hint()` and `sdl_log*()`, which are wrappers that terminate the
arguments for convenience.### SDL_Color
SDL 2.0 stores RGB colour values as `Uint8`. As Fortran does not feature unsigned
types, the intrinsic procedure `transfer()` has to be used to transfer bit
patterns directly. For example:```fortran
type(sdl_color) :: colorcolor = sdl_color(r = transfer([255, 1], 1_c_int8_t)
g = transfer([127, 1], 1_c_int8_t)
b = transfer([ 0, 1], 1_c_int8_t)
a = transfer([SDL_ALPHA_OPAQUE, 1], 1_c_int8_t))
```The Fortran bindings provide a utility function `uint8()` that simplifies the
conversion:```fortran
color = sdl_color(r = uint8(255), &
g = uint8(127), &
b = uint8(0), &
a = uint8(SDL_ALPHA_OPAQUE))
```### SDL_Surface
C pointers in derived types like `sdl_surface` must be converted to Fortran
types manually by calling the intrinsic procedure `c_f_pointer()`. For instance,
to assign the `sdl_pixel_format` pointer in `sdl_surface`:```fortran
type(sdl_pixel_format), pointer :: pixel_format
type(sdl_surface), pointer :: surface! Convert C pointer to Fortran pointer.
call c_f_pointer(surface%format, pixel_format)
```The C struct `SDL_Surface` stores RGB pixel values as `Uint8`. Use `transfer()`
and `ichar()` to convert `Uint8` to Fortran signed integer. For example:```fortran
integer, parameter :: X = 10
integer, parameter :: Y = 20
integer(kind=int8) :: r, g, b
integer(kind=c_int32_t) :: pixel
integer(kind=c_int8_t), pointer :: pixels(:)
type(sdl_pixel_format), pointer :: pixel_format
type(sdl_surface), pointer :: surface! Load BMP file into SDL_Surface.
surface => sdl_load_bmp('image.bmp' // c_null_char)! Get SDL_PixelFormat.
call c_f_pointer(surface%format, pixel_format)! Get Fortran array of pixel pointers.
call c_f_pointer(surface%pixels, pixels, shape=[surface%pitch * surface%h])! Get single pixel of coordinates X and Y. Convert to Fortran integer.
pixel = ichar(transfer(pixels((Y - 1) * surface%pitch + X), 'a'), kind=c_int32_t)! Get RGB values of pixel.
call sdl_get_rgb(pixel, pixel_format, r, g, b)
```### SDL_Log
Only a single string message can be passed to `sdl_log()` and `sdl_log_*()`
routines, as Fortran does not support ellipsis arguments. For example:```fortran
call sdl_log_debug(SDL_LOG_CATEGORY_TEST, 'debug message')
```You may have to write your log message to a string first:
```fortran
character(len=32) :: msg
integer :: rcwrite (msg, '(a, i0)') 'Error: ', rc
call sdl_log(msg)
```Log messages will be trimmed and null-terminated by the wrapper routines.
### Events
The SDL event [SDL_QUIT](https://wiki.libsdl.org/SDL_EventType#SDL_QUIT) has
been renamed to `SDL_QUITEVENT` in Fortran to avoid conflict with interface
`sdl_quit()`.## Documentation
Generate the source code documentation with
[FORD](https://github.com/cmacmackin/ford). Add FORD with `pip`, for example:```
$ python3 -m venv virtual-environment/
$ source virtual-environment/bin/activate
$ python3 -m pip install ford
```Or, instead, just install the package in your user directory:
```
$ python3 -m pip install --user ford
```Then, run:
```
$ ford project.md -d ./src
```Open `doc/index.html` in a web browser.
## Coverage
See [coverage](COVERAGE.md) for the current status.
## Credits
Thanks go to [angelog0](https://github.com/angelog0).
## Licence
ISC