项目作者: interkosmos

项目描述 :
Fortran 2008 interface bindings to SDL 2.0
高级语言: Fortran
项目地址: git://github.com/interkosmos/fortran-sdl2.git
创建时间: 2018-02-28T21:53:47Z
项目社区:https://github.com/interkosmos/fortran-sdl2

开源协议:ISC License

下载


fortran-sdl2

A collection of ISO C binding interfaces to
Simple DirectMedia Layer 2.0 (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.2

For bindings to
SDL2_gfx,
see fortran-sdl2_gfx.

Build Instructions

If not present already, install SDL 2.0 with development headers (and
optionally: SDL_image 2.0,
SDL_mixer 2.0, and/or
SDL_ttf 2.0). On FreeBSD, run:

  1. # pkg install devel/sdl20 graphics/sdl2_image audio/sdl2_mixer graphics/sdl2_ttf

Either use GNU/BSD make, xmake to build fortran-sdl2, or
the Fortran Package Manager (fpm).

Make

Run make sdl2 to compile the static library libsdl2.a:

  1. $ git clone --depth 1 https://github.com/interkosmos/fortran-sdl2
  2. $ cd fortran-sdl2/
  3. $ make sdl2

On Microsoft Windows, you have to set LIBGL and LIBGLU:

  1. $ 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:

  1. $ 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:

  1. $ xmake

Build a particular library with:

  1. $ xmake build <name>

The default output directory is build/.

Example

The following example shows how to fill a rectangle, using the hardware renderer.

  1. ! example.f90
  2. program main
  3. use, intrinsic :: iso_c_binding, only: c_associated, c_null_char, c_ptr
  4. use, intrinsic :: iso_fortran_env, only: stdout => output_unit, stderr => error_unit
  5. use :: sdl2
  6. implicit none
  7. integer, parameter :: SCREEN_WIDTH = 640
  8. integer, parameter :: SCREEN_HEIGHT = 480
  9. type(c_ptr) :: window
  10. type(c_ptr) :: renderer
  11. type(sdl_event) :: event
  12. type(sdl_rect) :: rect
  13. integer :: rc
  14. logical :: is_running
  15. ! Initialise SDL.
  16. if (sdl_init(SDL_INIT_VIDEO) < 0) then
  17. write (stderr, '("SDL Error: ", a)') sdl_get_error()
  18. stop
  19. end if
  20. ! Create the SDL window.
  21. window = sdl_create_window('Fortran SDL 2.0' // c_null_char, &
  22. SDL_WINDOWPOS_UNDEFINED, &
  23. SDL_WINDOWPOS_UNDEFINED, &
  24. SCREEN_WIDTH, &
  25. SCREEN_HEIGHT, &
  26. SDL_WINDOW_SHOWN)
  27. if (.not. c_associated(window)) then
  28. write (stderr, '("SDL Error: ", a)') sdl_get_error()
  29. stop
  30. end if
  31. ! Create the renderer.
  32. renderer = sdl_create_renderer(window, -1, 0)
  33. ! Set position and size of the rectangle.
  34. rect = sdl_rect(50, 50, 250, 250)
  35. ! Event loop.
  36. is_running = .true.
  37. do while (is_running)
  38. ! Catch events.
  39. do while (sdl_poll_event(event) > 0)
  40. select case (event%type)
  41. case (SDL_QUITEVENT)
  42. is_running = .false.
  43. end select
  44. end do
  45. ! Fill screen black.
  46. rc = sdl_set_render_draw_color(renderer, &
  47. uint8(0), &
  48. uint8(0), &
  49. uint8(0), &
  50. uint8(SDL_ALPHA_OPAQUE))
  51. rc = sdl_render_clear(renderer)
  52. ! Fill the rectangle.
  53. rc = sdl_set_render_draw_color(renderer, &
  54. uint8(127), &
  55. uint8(255), &
  56. uint8(0), &
  57. uint8(SDL_ALPHA_OPAQUE))
  58. rc = sdl_render_fill_rect(renderer, rect)
  59. ! Render to screen and wait 20 ms.
  60. call sdl_render_present(renderer)
  61. call sdl_delay(20)
  62. end do
  63. ! Quit gracefully.
  64. call sdl_destroy_renderer(renderer)
  65. call sdl_destroy_window(window)
  66. call sdl_quit()
  67. end program main

To compile the source code with GNU Fortran, run:

  1. $ gfortran `sdl2-config --cflags` -o example example.f90 libsdl2.a `sdl2-config --libs`

Further Examples

Some demo applications can be found in examples/:

  • alpha makes one color of an image transparent (software renderer).
  • cyclic implements a 2D cyclic cellular automaton (hardware renderer).
  • draw draws some shapes (hardware renderer).
  • dvd loads a PNG file with SDL_image and lets it bounce on the screen (hardware renderer).
  • events polls SDL events (software renderer).
  • fire renders the DOOM fire effect (hardware renderer).
  • forest implements a cellular automaton, based on the forest fire model (hardware renderer).
  • gl renders a triangle with OpenGL 1.3.
  • gl3d rotates textured cubes with OpenGL 1.3.
  • glsphere rotates the camera around GLU spheres.
  • image 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 lets you fly through a field of Fortran logos (hardware renderer).
  • msgbox shows a simple message box (software renderer).
  • opera plays an OGG file with SDL_mixer (software renderer).
  • pixel copies an SDL_Surface to an SDL_Texture pixelwise (hardware renderer).
  • scaling displays a scaled image (software renderer).
  • text outputs text with SDL_ttf (hardware renderer).
  • vertex shows geometry renderer of SDL 2.0.18.
  • voxel renders a voxel space 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:

  1. $ make examples

If you prefer xmake, build and run an example with:

  1. $ xmake build <name>
  2. $ xmake run <name>

To compile all examples, simply run:

  1. $ 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:

  1. type(sdl_color) :: color
  2. color = sdl_color(r = transfer([255, 1], 1_c_int8_t)
  3. g = transfer([127, 1], 1_c_int8_t)
  4. b = transfer([ 0, 1], 1_c_int8_t)
  5. a = transfer([SDL_ALPHA_OPAQUE, 1], 1_c_int8_t))

The Fortran bindings provide a utility function uint8() that simplifies the
conversion:

  1. color = sdl_color(r = uint8(255), &
  2. g = uint8(127), &
  3. b = uint8(0), &
  4. 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:

  1. type(sdl_pixel_format), pointer :: pixel_format
  2. type(sdl_surface), pointer :: surface
  3. ! Convert C pointer to Fortran pointer.
  4. 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:

  1. integer, parameter :: X = 10
  2. integer, parameter :: Y = 20
  3. integer(kind=int8) :: r, g, b
  4. integer(kind=c_int32_t) :: pixel
  5. integer(kind=c_int8_t), pointer :: pixels(:)
  6. type(sdl_pixel_format), pointer :: pixel_format
  7. type(sdl_surface), pointer :: surface
  8. ! Load BMP file into SDL_Surface.
  9. surface => sdl_load_bmp('image.bmp' // c_null_char)
  10. ! Get SDL_PixelFormat.
  11. call c_f_pointer(surface%format, pixel_format)
  12. ! Get Fortran array of pixel pointers.
  13. call c_f_pointer(surface%pixels, pixels, shape=[surface%pitch * surface%h])
  14. ! Get single pixel of coordinates X and Y. Convert to Fortran integer.
  15. pixel = ichar(transfer(pixels((Y - 1) * surface%pitch + X), 'a'), kind=c_int32_t)
  16. ! Get RGB values of pixel.
  17. 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:

  1. call sdl_log_debug(SDL_LOG_CATEGORY_TEST, 'debug message')

You may have to write your log message to a string first:

  1. character(len=32) :: msg
  2. integer :: rc
  3. write (msg, '(a, i0)') 'Error: ', rc
  4. call sdl_log(msg)

Log messages will be trimmed and null-terminated by the wrapper routines.

Events

The SDL event 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. Add FORD with pip, for example:

  1. $ python3 -m venv virtual-environment/
  2. $ source virtual-environment/bin/activate
  3. $ python3 -m pip install ford

Or, instead, just install the package in your user directory:

  1. $ python3 -m pip install --user ford

Then, run:

  1. $ ford project.md -d ./src

Open doc/index.html in a web browser.

Coverage

See coverage for the current status.

Credits

Thanks go to angelog0.

Licence

ISC