Nanashi-softプログラマ専用PS3 Linux SDL


◇PS3 Linux SDLでプログラミング -四角を描く-

○なぜHellow worldから始めないのか?

だって SDL関係無いものw
普通にprintfすれば表示されますよ

#include <stdio.h>
main(){
  printf("Hellow world!!");
}

みたいな感じでいいと思う

○SDLヘッダ定義

それでは四角を描いてみます
一番上にヘッダを書きます

#include "SDL.h"

これを書いたら、よく書く stdio.hや string.hは不要です
当然 SDLでもこれらを使用していると思うので、SDL.h内で全て宣言済みなのでしょう

○画面初期化

次に当然 main関数が必須です

int main(int argc,char *argv[]){

mainの引数などを省略すると、うまくコンパイルできないようです
SDL.hで何か宣言しているのでしょうか?

画面を初期化します

if(SDL_Init(SDL_INIT_VIDEO) < 0){
  return -1;
}

初期化に失敗したら終了するようにしておきます

○実画面用サーフェスを生成

画面モードを切り替えて、実画面に描画する為のサーフェスを生成します
サーフェスとは SDLにおける画面描画領域の単位です
ここで生成したサーフェスに描画すると、実画面に反映する事ができます

SDL_Surface *screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE|SDL_FULLSCREEN);
if(screen == NULL){
  SDL_Quit();
  return -1;
}

先頭の3つの引数は、横ドット数、縦ドット数、色深度です
ここの引数に関しては PS3 Linux固有の問題があるのですが、それは別ページにまとめます

4つ目の引数は、生成したサーフェスの種類を指示します
SDL_SWSURFACEは、システムメモリ上に確保される
SDL_FULLSCREENは、フルスクリーンモードに切り替える
他にも沢山ありますが、ここでは割愛します

○四角を描画する

専用関数があるので、それを使ってみます

SDL_Rect box;
box.x = 0;
box.y = 0;
box.w = 640;
box.h = 480;
SDL_FillRect(screen, &box, 0xff2B4B65);
SDL_UpdateRect(screen, 0, 0, 0, 0);

先頭の screenは、実画面用サーフェスです
そこに描画しておいて、updateで更新をかけると表示されます

updateしなければ描画されないので、面倒な気がしますが、
逆に考えれば、updateしなければ描画されないので、裏画面が必要無いメリットがあります

○無限ループを作る

SDLは、無限ループを作らなければそのまま終わってしまい、画面を確認する事ができません
でも単に、whikeループだけを作ると終了する事ができなくなるハメに陥りますので決してしないで下さい
私はそれやってPS3の電源を強制切断する事態に陥りました(汗
……と書いてもやる人はやるので書いておきますが、電源ボタンを2秒くらい長押しで強制電源断できます

SDL_Event event;
int done = 0;
while(!done){
  while(SDL_PollEvent(&event)){
    switch(event.type){
    case SDL_KEYDOWN:
      if(event.key.keysym.sym == SDLK_ESCAPE){
        done = 1;
      }
      break;
    case SDL_QUIT:
      done = 1;
      break;
    }
  }
}

一番外に、フラグが立ったら終了する無限ループを作ります
その内側に、SDLのイベント受け取り待ちループを作ります
イベントが来ると、event.typeの中身を確認して、それぞれの動作を行います

キー入力があると、SDL_KEYDOWNが来ます
event.key.keysym.symにどのキーが押されたが来ているので、押されたキー毎に動作を行います
ここでは、ESCキーが押されたら、一番外の無限ループを終了させるフラグを立てました

SDL_QUITは、プログラムの終了通知が来た事を示すので、これが来ても終了フラグを立てます
この SDL_QUITは、X Window上で、閉じるボタンを押した時に来ました
コマンドライン上では、どうやっても来ませんでした

○SDLを終了する

最後に、SDLの終了処理を行います

SDL_Quit();

これは、プログラム終了時には必ず書いて下さい

特にエラー終了時には記述するように注意です
これを記述せずに終了していると、メモリリークを起こすらしく、PS3が何度かフリーズしました
逆に言えば、これさえ記述していれば安心と言うことですね

○ビルドする

コマンドは以下の通りです

gcc -o 「拡張子無しファイル名」「ファイル名」 `sdl-config --cflags --libs`

この sdl-configはかなり優秀で、Windows上の Cygwinでも同じようにビルドできました
これが無ければ、長い引数を環境毎に試行錯誤で用意したり、makefileファイルを作成したりする必要があります

ちなみに、「`」はバッククォーテーションです。シフトキーを押しながら@キーを押すと入力できます
Unixでは、この記述方法を eval(エヴァル)と言い、囲まれた中のコマンドを実行して、結果をそこに埋め込む事を意味します

例) test.cファイルをビルドする場合

gcc -o test test.c `sdl-config --cflags --libs`

エラーが無ければ、実行ファイル testが生成されます
./test
で起動可能です


コマンドライン上から説明したプログラムを実行すると、凄い画面が乱れます
表示がおかしいだけで、特にテレビ・モニターに負荷はかけませんので安心して下さい
X Windowを起動して、そこから表示すると正常に描画されます
この問題については、別のページで詳しく説明します

○ソース

#include "SDL.h"

int main(int argc,char *argv[]){
  int done;
  SDL_Event event;

  if(SDL_Init(SDL_INIT_VIDEO) < 0){
    return -1;
  }

  SDL_Surface *screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE|SDL_FULLSCREEN);
  if(screen == NULL){
    SDL_Quit();
    return -1;
  }

  SDL_Rect box;
  box.x = 0;
  box.y = 0;
  box.w = 640;
  box.h = 480;
  SDL_FillRect(screen, &box, 0xff2B4B65);
  SDL_UpdateRect(screen,0,0,0,0);

  done = 0;
  while(!done){
    while(SDL_PollEvent(&event)){
      switch(event.type){
      case SDL_KEYDOWN:
        if(event.key.keysym.sym == SDLK_ESCAPE){
          done = 1;
        }
        break;
      case SDL_QUIT:
        done = 1;
        break;
      }
    }
  }

  SDL_Quit();

  return 0;
}



TOPプログラマ専用PS3 Linux SDL