takaya030の備忘録

PHP、Laravel、Docker などの話がメインです

MSYS2 + MinGW 環境に SDL2 をインストール

検証環境

Windows10 Home Edition

msys2-x86_64-20170918

$ gcc --version
gcc.exe (Rev2, Built by MSYS2 project) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

MSYS2、MinGW のインストール

下記サイトの手順で 64bit 版をインストールする
takaya030.hatenablog.com

SDL2 のインストール

今回はパッケージマネージャ (pacman) を使ってインストールする

SDL2 パッケージの確認

64bit 環境なので mingw64 のパッケージを使う

$ pacman -Sl | grep SDL2
mingw32 mingw-w64-i686-SDL2 2.0.7-1
mingw32 mingw-w64-i686-SDL2_gfx 1.0.1-2
mingw32 mingw-w64-i686-SDL2_image 2.0.2-1
mingw32 mingw-w64-i686-SDL2_mixer 2.0.2-2
mingw32 mingw-w64-i686-SDL2_net 2.0.1-1
mingw32 mingw-w64-i686-SDL2_ttf 2.0.14-1
mingw64 mingw-w64-x86_64-SDL2 2.0.7-1
mingw64 mingw-w64-x86_64-SDL2_gfx 1.0.1-2
mingw64 mingw-w64-x86_64-SDL2_image 2.0.2-1
mingw64 mingw-w64-x86_64-SDL2_mixer 2.0.2-2
mingw64 mingw-w64-x86_64-SDL2_net 2.0.1-1
mingw64 mingw-w64-x86_64-SDL2_ttf 2.0.14-1

インストール

$ pacman -S mingw-w64-x86_64-SDL2
$ pacman -S mingw-w64-x86_64-SDL2_mixer
$ pacman -S mingw-w64-x86_64-SDL2_ttf

動作確認

以下のサンプルコードが動作するか確認する

sdl2_sample.cpp

#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL2/SDL.h>
#include <iostream>

#define SDL_WINDOW_TITLE "SDL2"
#define SDL_WINDOW_WIDTH (640)
#define SDL_WINDOW_HEIGHT (480)

#define SDL_PrintError(name)                                    \
  do {                                                          \
    std::cerr << #name << ": " << SDL_GetError() << std::endl;  \
  } while (0)

static SDL_Window *gWindow;
static SDL_GLContext context;


static bool initialize()
{
  if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
    SDL_PrintError(SDL_Init);
    return false;
  }

  gWindow = SDL_CreateWindow(SDL_WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		  SDL_WINDOW_WIDTH, SDL_WINDOW_HEIGHT,
		  SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
  if (gWindow == nullptr) {
    SDL_PrintError(SDL_CreateWindow);
    goto err1;
  }

  // create OpenGL Context
  context = SDL_GL_CreateContext(gWindow);
  if ( !context ) {
      SDL_PrintError(SDL_GL_CreateContext);
	  goto err2;
  }

  return true;

 err2:
  SDL_DestroyWindow(gWindow);
 err1:
  SDL_Quit();
  return false;
}

static bool initGL()
{

    /* Enable smooth shading */
    glShadeModel( GL_SMOOTH );

    /* Set the background black */
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

    /* Depth buffer setup */
    glClearDepth( 1.0f );

    /* Enables Depth Testing */
    glEnable( GL_DEPTH_TEST );

    /* The Type Of Depth Test To Do */
    glDepthFunc( GL_LEQUAL );

    /* Really Nice Perspective Calculations */
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );

    return( TRUE );
}

static bool resizeWindow( int width, int height )
{
    /* Height / width ration */
    GLfloat ratio;

    /* Protect against a divide by zero */
    if ( height == 0 )
	height = 1;

    ratio = ( GLfloat )width / ( GLfloat )height;

    /* Setup our viewport. */
    glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );

    /* change to the projection matrix and set our viewing volume. */
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );

    /* Set our perspective */
    gluPerspective( 45.0f, ratio, 0.1f, 100.0f );

    /* Make sure we're chaning the model view and not the projection */
    glMatrixMode( GL_MODELVIEW );

    /* Reset The View */
    glLoadIdentity( );

    return( true );
}

static void finalize()
{
  SDL_GL_DeleteContext(context);
  SDL_DestroyWindow(gWindow);
  SDL_Quit();
}

static void render()
{
  /* Clear The Screen And The Depth Buffer */
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    /* Move Left 1.5 Units And Into The Screen 6.0 */
    glLoadIdentity();
    glTranslatef( -1.5f, 0.0f, -6.0f );

    glBegin( GL_TRIANGLES );             /* Drawing Using Triangles       */
      glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
      glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle               */
      glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
      glVertex3f( -1.0f, -1.0f,  0.0f ); /* Left Of Triangle              */
      glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
      glVertex3f(  1.0f, -1.0f,  0.0f ); /* Right Of Triangle             */
    glEnd( );                            /* Finished Drawing The Triangle */

    /* Move Right 3 Units */
    glTranslatef( 3.0f, 0.0f, 0.0f );

    /* Set The Color To Blue One Time Only */
    glColor3f( 0.5f, 0.5f, 1.0f);

    glBegin( GL_QUADS );                 /* Draw A Quad              */
      glVertex3f(  1.0f,  1.0f,  0.0f ); /* Top Right Of The Quad    */
      glVertex3f( -1.0f,  1.0f,  0.0f ); /* Top Left Of The Quad     */
      glVertex3f( -1.0f, -1.0f,  0.0f ); /* Bottom Left Of The Quad  */
      glVertex3f(  1.0f, -1.0f,  0.0f ); /* Bottom Right Of The Quad */
    glEnd( );                            /* Done Drawing The Quad    */

  /* Draw it to the screen */
  SDL_GL_SwapWindow(gWindow);

  /** NOTE: Sleep 10 msec. */
  SDL_Delay(10);
}

static bool input()
{
  SDL_Event event;

  /** NOTE: SDL_PollEvent does not sleep while SDL_WaitEvent sleep
      till event comes. SDL_WaitEvent is more relaxible than
      SDL_PollEvent. If input is combined with rendering,
      SDL_WaitEvent cannot be used. */
  while (SDL_PollEvent(&event)) {
    switch (event.type) {
    case SDL_QUIT:
      return true;
      break;
    case SDL_WINDOWEVENT:
      switch( event.window.event ) {
        case SDL_WINDOWEVENT_RESIZED:
	    /* handle resize event */
	    SDL_SetWindowSize( gWindow, event.window.data1, event.window.data2 );
	    resizeWindow( event.window.data1, event.window.data2 );
	    break;
      }
      break;
    default:
      break;
    }
  }

  return false;
}

int main(int argc, char *argv[])
{
  if (!initialize())
    return 1;

  initGL();
  resizeWindow( SDL_WINDOW_WIDTH, SDL_WINDOW_HEIGHT );

  while (1) {
    if (input())
      break;
    render();
  }

  finalize();
  return 0;
}

Makefile

TARGETS = sdl2_sample

all: $(TARGETS)

SDL_PREFIX	= /mingw64
SDL_CONFIG	= $(SDL_PREFIX)/bin/sdl2-config
CG_LIBS		= 

CROSS_COMPILE	= /mingw64/bin
CC		= $(CROSS_COMPILE)/gcc
CXX		= $(CROSS_COMPILE)/g++

CFLAGS 		= -g -Wall `/bin/sh $(SDL_CONFIG) --cflags`
CXXFLAGS	= -g -Wall `/bin/sh $(SDL_CONFIG) --cflags`
LDFLAGS		= `/bin/sh $(SDL_CONFIG) --libs`	-Wl,-rpath,$(SDL_PREFIX)/lib
LIBS		= -lopengl32 -lglu32 -lm

clean:
	rm -f *.o *.a *~ $(TARGETS)

sdl2_sample: sdl2_sample.o
	$(CXX) -o $@ $^ $(LDFLAGS) $(LIBS)

ビルド

$ make

実行

$ ./sdl2_sample.exe

このようなウィンドウが表示されれば成功です
f:id:takaya030:20180109225315p:plain