過去ログ 4
過去ログは下にいくほど新しい記事となっております。
※注意:このサイトにあるプログラムのソースコードや、その他の情報はすべて無保証です。やばいと思ったら実行しないでください。コンパイル、実行などによって生じた損害に対する責任は負いませんので、ご了承ください。
アナロ熊
29-4-2009
というのを見つけた。 (公式サイト:アナログマ)
┼╂┼ ∩_┃_∩ | ノ ヽ / ● ● | | ( _●_) ミ 彡、 |∪| 、`\ <2011年7月24日まで、 / __ ヽノ /´,> ) まだまだ余裕クマー (___) / (_/ | / | /\ \ | / ) ) ∪ ( \ \_)
(※ 著作権フリーだそうです。)
なんか地デジカよりもかわいいな。ちなみに、うちのテレビはまだアナログ。買い替えの目処は立っておりません。
今日のSDL
キーが押されたときのイベントについてやります。
キーが押されたときに終了するプログラムは前に作りました(昨日のプログラム例もキー押下で終了するものです)。今日は押されたキーを判別する方法をやります。
SDL_PollEvent()の引数に発生したイベントの詳細がセットされます。そのイベント詳細を解析すれば、どのボタンが押されたか分かります。
SDL_event.hより (順番の入れ替えあり)
/* General event structure */ typedef union SDL_Event { Uint8 type; SDL_ActiveEvent active; SDL_KeyboardEvent key; SDL_MouseMotionEvent motion; SDL_MouseButtonEvent button; SDL_JoyAxisEvent jaxis; SDL_JoyBallEvent jball; SDL_JoyHatEvent jhat; SDL_JoyButtonEvent jbutton; SDL_ResizeEvent resize; SDL_ExposeEvent expose; SDL_QuitEvent quit; SDL_UserEvent user; SDL_SysWMEvent syswm; } SDL_Event;/* Keyboard event structure */ typedef struct SDL_KeyboardEvent { Uint8 type; /* SDL_KEYDOWN or SDL_KEYUP */ Uint8 which; /* The keyboard device index */ Uint8 state; /* SDL_PRESSED or SDL_RELEASED */ SDL_keysym keysym; } SDL_KeyboardEvent;SDL_keyboard.hより
typedef struct SDL_keysym { Uint8 scancode; /* hardware specific scancode */ SDLKey sym; /* SDL virtual keysym */ SDLMod mod; /* current key modifiers */ Uint16 unicode; /* translated character */ } SDL_keysym;
SDLKeyはSDL_keysym.hまたはwikiにて確認できます。
#include <SDL/SDL.h> #include <SDL/SDL_ttf.h> int main(){ SDL_Surface *screen; SDL_Surface *ttf_surface; SDL_Rect rect_scr = {0,0,300,300}; SDL_Rect rect_img = {0,0,200,200}; SDL_Color color = {255, 255, 255}; SDL_Event event; int endflag = 0; TTF_Font *font; SDL_KeyboardEvent *key; /* SDL_Eventのキャスト用 */ SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ TTF_Init(); SDL_WM_SetCaption("タイトル", "たいとる"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); font = TTF_OpenFont("ipag-mona.ttf", 36); screen = SDL_GetVideoSurface(); rect_scr.y = 0; ttf_surface = TTF_RenderUTF8_Blended(font, "1 終了しない", color); rect_img.w = ttf_surface->w; rect_img.h = ttf_surface->h; SDL_BlitSurface(ttf_surface, &rect_img, screen, &rect_scr); SDL_FreeSurface(ttf_surface); rect_scr.y += 40; ttf_surface = TTF_RenderUTF8_Blended(font, "2 終了する", color); rect_img.w = ttf_surface->w; rect_img.h = ttf_surface->h; SDL_BlitSurface(ttf_surface, &rect_img, screen, &rect_scr); SDL_FreeSurface(ttf_surface); SDL_Flip(screen); while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_KEYDOWN: /* キーダウン */ /* 2を押したときに、終了する */ key = (SDL_KeyboardEvent*)&event; switch(key->keysym.sym){ case SDLK_2: endflag = 1; break; default: break; } break; default: break; } } SDL_Delay(1); } TTF_Quit(); SDL_Quit(); /* SDL終了 */ return 0; }
ペンギンはお休みです。
windowが閉じられようとしたとき、または2が押されたときに終了します。
実際に使う場合は、「key->keysym.sym」が汚いので、下のようにマクロにしてしまった方がいいかもしれません。
#define GET_KEY(__x) (__x->keysym.sym)
キーアップ時のイベント
キーアップ時のイベントはSDL_KEYUPで取得できます。この場合、「キーが押されていない」ではなく、「キーが一度押されて離された」ときにイベント発生となります。
※コメント、トラックバックはできません。(ブログじゃないから)
マウスの動き
30-4-2009
今日のSDL
SDLの参考サイトなど
- SDL Documentation Wiki
- SDL ライブラリ
- SDL_image ライブラリ
- SDL_ttf ライブラリ
- SDL_mixer ライブラリ
- SDL_net ライブラリ
- SDL_gfx ライブラリ
マウスの動き
マウスの動きは大きく分けて2種類あります。
- マウスを動かしたとき
- ボタンを押したとき
今日はこのイベントを感知することを行います。
SDL_event.hより (順番の入れ替えあり)
/* General event structure */ typedef union SDL_Event { Uint8 type; SDL_ActiveEvent active; SDL_KeyboardEvent key; SDL_MouseMotionEvent motion; SDL_MouseButtonEvent button; SDL_JoyAxisEvent jaxis; SDL_JoyBallEvent jball; SDL_JoyHatEvent jhat; SDL_JoyButtonEvent jbutton; SDL_ResizeEvent resize; SDL_ExposeEvent expose; SDL_QuitEvent quit; SDL_UserEvent user; SDL_SysWMEvent syswm; } SDL_Event; /* Mouse motion event structure */ typedef struct SDL_MouseMotionEvent { Uint8 type; /* SDL_MOUSEMOTION */ Uint8 which; /* The mouse device index */ Uint8 state; /* The current button state */ Uint16 x, y; /* The X/Y coordinates of the mouse */ Sint16 xrel; /* The relative motion in the X direction */ Sint16 yrel; /* The relative motion in the Y direction */ } SDL_MouseMotionEvent; /* Mouse button event structure */ typedef struct SDL_MouseButtonEvent { Uint8 type; /* SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP */ Uint8 which; /* The mouse device index */ Uint8 button; /* The mouse button index */ Uint8 state; /* SDL_PRESSED or SDL_RELEASED */ Uint16 x, y; /* The X/Y coordinates of the mouse at press time */ } SDL_MouseButtonEvent;
とりあえず、画面をクリックしたら終了するプログラムを作成します。
#include <SDL/SDL.h> int main(){ SDL_Event event; int endflag = 0; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_WM_SetCaption("タイトル", "たいとる"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_MOUSEBUTTONUP: /* マウスクリック */ endflag = 1; break; default: break; } } SDL_Delay(1); } SDL_Quit(); /* SDL終了 */ return 0; }
マウスのクリックですが、一般に「マウスのボタンを押す + 離す」で1クリックとされますので、SDL_MOUSEBUTTONUPを使いました。ボタンを押したときに何かアクションをしたい場合はSDL_MOUSEBUTTONDOWNを使います。
また、ドラッグ&ドロップをしたい場合はSDL_MOUSEBUTTONDOWN、SDL_MOUSEBUTTONUPの両方を使用することになります。マウスのボタンを押したときの座標とマウスのボタンを離したときの座標からドラッグ&ドロップの動作を行います。
押されたボタンを判定する
マウスには左クリック、右クリック、あと中央のボタンがあります。どのボタンが押されたかについては、SDL_MouseButtonEventのbuttonにて判別します。buttonには次のような値が入ります。
SDL_button.hより
#define SDL_BUTTON_LEFT 1 #define SDL_BUTTON_MIDDLE 2 #define SDL_BUTTON_RIGHT 3 #define SDL_BUTTON_WHEELUP 4 #define SDL_BUTTON_WHEELDOWN 5
では、右クリックしたときに終了するようにプログラムを書き換えてみます。
/* 該当部分抜粋 */ SDL_MouseButtonEvent *mouse; /* 中略 */ while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_MOUSEBUTTONUP: /* マウスクリック */ mouse = (SDL_MouseButtonEvent*)&event; switch(mouse->button){ case SDL_BUTTON_RIGHT: endflag = 1; break; default: break; } break; default: break; } } SDL_Delay(1); }
次回、もうすこし応用的なことをやっていきます。
※コメント、トラックバックはできません。メール、リンクは適当に。
ごーるでんうぃーく
2-5-2009
インフルエンザこわいよー。
昨日は
アナログマの格闘ゲームをやっていて更新するのを忘れていました。いや、本当に。
まだパーフェクト勝ちはできていないっす。
こんなのを見つけた
ギャルゲーですね。分かります。
(※ 体験版やってみたら、育成+恋愛ゲームでした。)
今日のSDL
SDLの参考サイトなど
- SDL Documentation Wiki
- SDL ライブラリ
- SDL_image ライブラリ
- SDL_ttf ライブラリ
- SDL_mixer ライブラリ
- SDL_net ライブラリ
- SDL_gfx ライブラリ
ちょっと今回から少し難しく(ソースコードも長く)なります。
ボタンをつくる
前回はとりあえずマウスをクリックしたら終了する、というプログラムを作成しました。今回は、「ボタンをクリックしたら終了する」プログラムを作ります。
ボタン素材を作るのが面倒なので、赤いエリアをボタンだと考えてください。
チェックは4段階で
- イベントが発生したか(イベント待ち)
- ボタンクリックイベントか
- 左クリックか
- ボタンのエリア内か
の、順に行います。
#include <SDL/SDL.h> /* ボタンの座標設定 */ #define BUTTON_LEFT (50) #define BUTTON_TOP (50) #define BUTTON_WIDTH (100) #define BUTTON_HEIGHT (100) #define BUTTON_BOTTOM (BUTTON_TOP + BUTTON_HEIGHT) #define BUTTON_RIGHT (BUTTON_LEFT + BUTTON_WIDTH) int main(){ SDL_Surface *screen; SDL_Rect rect = {BUTTON_LEFT, BUTTON_TOP, BUTTON_WIDTH, BUTTON_HEIGHT}; SDL_Event event; SDL_MouseButtonEvent *mouse; int endflag = 0; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_WM_SetCaption("タイトル", "たいとる"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 255, 0, 0)); SDL_Flip(screen); while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_MOUSEBUTTONUP: /* マウスクリック */ mouse = (SDL_MouseButtonEvent*)&event; switch(mouse->button){ case SDL_BUTTON_LEFT: if((mouse->x > BUTTON_LEFT && mouse->x < BUTTON_RIGHT) && (mouse->y > BUTTON_TOP && mouse->y < BUTTON_BOTTOM) ){ endflag = 1; } break; default: break; } break; default: break; } } SDL_Delay(1); } SDL_Quit(); /* SDL終了 */ return 0; }
少し問題がありますが、一応できました。これをベースに手直し&機能追加をしていきましょう。
手直し - ソースコードの整理
機能説明の見本のプログラムですので、処理を複数の関数に分割するということは極力行わないつもりですが、クリック時の位置判定はあまりにも汚いソースコードとなっています。色々修正を加えたときに間違えそうですので、範囲内に入っているかどうかを判別する関数を作成します。
int areacheck(Uint16 x, Uint16 y, SDL_Rect *rect){ if (rect == NULL) { return -1; } if ((x > rect->x && x < (rect->x + rect->w)) && (y > rect->y && y < (rect->y + rect->h))){ return 1; } return 0; }
エリア内だと1、エリア外だと0、SDL_RectのポインタがNULLだと-1が返ります。
すると、この様に書き直せます。
#include <SDL/SDL.h> /* ボタンの座標設定 */ #define BUTTON_LEFT (50) #define BUTTON_TOP (50) #define BUTTON_WIDTH (100) #define BUTTON_HEIGHT (100) int areacheck(Uint16 x, Uint16 y, SDL_Rect *rect){ if (rect == NULL) { return -1; } if ((x > rect->x && x < (rect->x + rect->w)) && (y > rect->y && y < (rect->y + rect->h))){ return 1; } return 0; } int main(){ SDL_Surface *screen; SDL_Rect rect = {BUTTON_LEFT, BUTTON_TOP, BUTTON_WIDTH, BUTTON_HEIGHT}; SDL_Event event; SDL_MouseButtonEvent *mouse; int endflag = 0; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_WM_SetCaption("タイトル", "たいとる"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 255, 0, 0)); SDL_Flip(screen); while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_MOUSEBUTTONUP: /* マウスクリック */ mouse = (SDL_MouseButtonEvent*)&event; switch(mouse->button){ case SDL_BUTTON_LEFT: if(areacheck(mouse->x, mouse->y, &rect) == 1){ endflag = 1; } break; default: break; } break; default: break; } } SDL_Delay(1); } SDL_Quit(); /* SDL終了 */ return 0; }
内容は同じになります。
手直し - マウスボタンをエリア外で押して、エリア内で離した時の対処
現在、マウスボタンをエリア外で押し、エリア内で離した時もエリア内をクリックしたと認識してしまいます。エリア内でボタンを押し、離したときのみクリックしたと認識されるよう、修正します。
ボタンを押したときに座標を記憶し、離したときに押した座標と離した座標が共にエリア内に入っていればOKとします(これでもちょっと問題がありますが・・・次回に回します)。
/* 該当部分抜粋 */ int main(){ SDL_Surface *screen; SDL_Rect rect = {BUTTON_LEFT, BUTTON_TOP, BUTTON_WIDTH, BUTTON_HEIGHT}; SDL_Event event; SDL_MouseButtonEvent *mouse; int endflag = 0; Uint16 x_pressed, y_pressed; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_WM_SetCaption("タイトル", "たいとる"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 255, 0, 0)); SDL_Flip(screen); mouse = (SDL_MouseButtonEvent*)&event; /* あらかじめポインタをセットしておく */ while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_MOUSEBUTTONDOWN: /* マウスのボタンを押した */ case SDL_MOUSEBUTTONUP: /* マウスのボタンを離した */ switch(mouse->button){ case SDL_BUTTON_LEFT: if(mouse->type == SDL_MOUSEBUTTONDOWN){ x_pressed = mouse->x; y_pressed = mouse->y; } else { if(areacheck(mouse->x, mouse->y, &rect) == 1 && areacheck(x_pressed, y_pressed, &rect) == 1){ endflag = 1; } } break; default: break; } break; default: break; } } SDL_Delay(1); } SDL_Quit(); /* SDL終了 */ return 0; }
-- 続く --
※コメント、トラックバックはできません。メール、リンクは適当に。
今日の更新
3-5-2009
更新中にエディタが落ちた。ショック。
今日のSDL
SDLの参考サイトなど
- SDL Documentation Wiki
- SDL ライブラリ
- SDL_image ライブラリ
- SDL_ttf ライブラリ
- SDL_mixer ライブラリ
- SDL_net ライブラリ
- SDL_gfx ライブラリ
前回のソースコード
#include <SDL/SDL.h> /* ボタンの座標設定 */ #define BUTTON_LEFT (50) #define BUTTON_TOP (50) #define BUTTON_WIDTH (100) #define BUTTON_HEIGHT (100) int areacheck(Uint16 x, Uint16 y, SDL_Rect *rect){ if (rect == NULL) { return -1; } if ((x > rect->x && x < (rect->x + rect->w)) && (y > rect->y && y < (rect->y + rect->h))){ return 1; } return 0; } int main(){ SDL_Surface *screen; SDL_Rect rect = {BUTTON_LEFT, BUTTON_TOP, BUTTON_WIDTH, BUTTON_HEIGHT}; SDL_Event event; SDL_MouseButtonEvent *mouse; int endflag = 0; Uint16 x_pressed, y_pressed; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_WM_SetCaption("タイトル", "たいとる"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 255, 0, 0)); SDL_Flip(screen); mouse = (SDL_MouseButtonEvent*)&event; /* あらかじめポインタをセットしておく */ while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_MOUSEBUTTONDOWN: /* マウスのボタンを押した */ case SDL_MOUSEBUTTONUP: /* マウスのボタンを離した */ switch(mouse->button){ case SDL_BUTTON_LEFT: if(mouse->type == SDL_MOUSEBUTTONDOWN){ x_pressed = mouse->x; y_pressed = mouse->y; } else { if(areacheck(mouse->x, mouse->y, &rect) == 1 && areacheck(x_pressed, y_pressed, &rect) == 1){ endflag = 1; } } break; default: break; } break; default: break; } } SDL_Delay(1); } SDL_Quit(); /* SDL終了 */ return 0; }
追加機能 - マウスがエリアに入ったときに色を変える
マウスがエリア内に入ったときに色を変えます。
テストプログラムで作っているエリアの大きさだと、マウスカーソルが入っているか入っていないか一目瞭然ですが、小さなボタンだと、ちゃんと入っているかどうか、入っている時にちょっと色を変えたりするとわかりやすくなります。
単純に、
- マウスカーソルの移動を検知
- エリア内であれば青、エリア外であれば赤にする
という処理を入れてみます。(マウスボタンイベントの変数名が変更されていることに注意してください。)
#include <SDL/SDL.h> /* ボタンの座標設定 */ #define BUTTON_LEFT (50) #define BUTTON_TOP (50) #define BUTTON_WIDTH (100) #define BUTTON_HEIGHT (100) int areacheck(Uint16 x, Uint16 y, SDL_Rect *rect){ if (rect == NULL) { return -1; } if ((x > rect->x && x < (rect->x + rect->w)) && (y > rect->y && y < (rect->y + rect->h))){ return 1; } return 0; } int toggle_area(SDL_Surface *surface, SDL_Rect *rect, int flag){ static int prev_flag = -1; Uint32 color; if(prev_flag != flag){ prev_flag = flag; if(flag == 0){ color = SDL_MapRGB(surface->format, 255, 0, 0); } else { color = SDL_MapRGB(surface->format, 0, 0, 255); } SDL_FillRect(surface, rect, color); return 1; } return 0; } int main(){ SDL_Surface *screen; SDL_Rect rect = {BUTTON_LEFT, BUTTON_TOP, BUTTON_WIDTH, BUTTON_HEIGHT}; SDL_Event event; SDL_MouseButtonEvent *mouse_button; SDL_MouseMotionEvent *mouse_motion; int mouse_over; int endflag = 0; Uint16 x_pressed, y_pressed; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_WM_SetCaption("タイトル", "たいとる"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); toggle_area(screen, &rect, 0); SDL_Flip(screen); mouse_button = (SDL_MouseButtonEvent*)&event; mouse_motion = (SDL_MouseMotionEvent*)&event; while(!endflag){ while(SDL_PollEvent(&event)){ switch(event.type){ case SDL_QUIT: /* ウインドウクローズ */ endflag = 1; break; case SDL_MOUSEMOTION: /* マウスを動かした */ if(areacheck(mouse_motion->x, mouse_motion->y, &rect)){ mouse_over = 1; } else { mouse_over = 0; } if(toggle_area(screen, &rect, mouse_over) == 1){ SDL_Flip(screen); } break; case SDL_MOUSEBUTTONDOWN: /* マウスのボタンを押した */ case SDL_MOUSEBUTTONUP: /* マウスのボタンを離した */ switch(mouse_button->button){ case SDL_BUTTON_LEFT: if(mouse_button->type == SDL_MOUSEBUTTONDOWN){ x_pressed = mouse_button->x; y_pressed = mouse_button->y; } else { if(areacheck(mouse_button->x, mouse_button->y, &rect) == 1 && areacheck(x_pressed, y_pressed, &rect) == 1){ endflag = 1; } } break; default: break; } break; default: break; } } SDL_Delay(1); } SDL_Quit(); /* SDL終了 */ return 0; }
マウスが動く度に、エリア内→エリア内の移動、エリア外→エリア外の移動でもSDL_FillRect()、SDL_FlipSurface()が呼ばれないように、色を変更する処理は別関数にしています。
画像を使う場合は、通常の画像とマウスカーソルが上に乗った時の画像を用意して、SDL_BlitSurface()で切り替えるなどとすればいいでしょう。
-- 続く --
※コメント、トラックバックはできません。メール、リンクは適当に。
トップページのCSSなどをいじってみた
4-5-2009
あんまり変わらないか。
※コメント、トラックバックはできません。メール、リンクは適当に。
ゴールデンウイークも終わりです
6-5-2009
エンターキーのききが悪くなってちょっと困っている今日このごろ。
今日のSDL
- SDL Documentation Wiki
- SDL ライブラリ
- SDL_image ライブラリ
- SDL_ttf ライブラリ
- SDL_mixer ライブラリ
- SDL_net ライブラリ
- SDL_gfx ライブラリ
前、画像を移動させるということをやりました。座標をずらして、再描画して動かしているわけですが、どうも疾走感に欠けます。子供向けのムービー作成ソフトでちょっと作ってみました、的なチープさがありましたので、もうちょっと格好良くしてみます。
残像を表示させる
今日のテーマは残像です。SDLのAPIに残像機能などありませんので、自分で作らなければなりません。
今回は今巷で流行りの「アナロ熊」イメージを用意しました。
(※ 透過pngです)
このアナロ熊を表示するプログラムは次のようになります。
#include <SDL/SDL.h> #include <SDL/SDL_image.h> #define WINDOW_WIDTH (640) /* ウインドウ横サイズ */ #define WINDOW_HEIGHT (480) /* ウインドウ縦サイズ */ int main(){ SDL_Surface *image; SDL_Surface *screen; SDL_Rect rect_scr = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; SDL_Rect rect_img = {0, 0, 0, 0}; SDL_Rect rect_put = {0, 0, 0, 0}; int loop; SDL_Init(SDL_INIT_EVERYTHING); SDL_WM_SetCaption("アナロ熊", "アナロ熊"); SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); image = IMG_Load("analoguma.png"); rect_img.w = image->w; rect_img.h = image->h; SDL_BlitSurface(image, &rect_img, screen, &rect_put); SDL_Flip(screen); SDL_Delay(3000); SDL_FreeSurface(image); SDL_Quit(); return 0; }
3秒ウエイトプログラムに戻っていますが、処理を単純にしているだけなので、あまり気にしないでください
フェードアウト
フェードアウトの方法は色々あります。イメージのαチャンネルを設定して、徐々に透明な画像をセットするようにする方法、バッファ全体のαチャンネルを調節する方法、半透明な背景色を重ねていく方法などが考えられます。
最初の方法は残像を出す位置を毎回指定しなければならないので大変です。ただし、影など、残像以外のものを位置計算して表示する場合は有力な方法です。
2番目の方法は簡単な方法ですが、全体的に透明になりますので、フェードアウトには適していますが、残像表示には向きません(実体も透明になっていってしまいます。)
3番目の方法はサーフェスを余分に作らないといけないので面倒ですが、過去の影のみを少しずつ透明化できるので、残像を表示するには適しているといえます。今回はこの方法を用います。
#include <SDL/SDL.h> #include <SDL/SDL_image.h> #define WINDOW_WIDTH (640) #define WINDOW_HEIGHT (480) #define OPACITY (40) int main(){ SDL_Surface *image; SDL_Surface *screen; SDL_Surface *buffer; SDL_Surface *buffer_tmp; SDL_Rect rect_scr = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; SDL_Rect rect_img = {0, 0, 0, 0}; SDL_Rect rect_put = {0, 0, 0, 0}; int loop; SDL_Init(SDL_INIT_EVERYTHING); SDL_WM_SetCaption("アナロ熊", "アナロ熊"); SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); /* buffer = 黒い半透明のサーフェスを作成する */ buffer_tmp = SDL_CreateRGBSurface(SDL_HWSURFACE, WINDOW_WIDTH, WINDOW_HEIGHT, 32, 0, 0, 0, 0); SDL_FillRect(buffer_tmp, &rect_scr, SDL_MapRGB(buffer_tmp->format, 0,0,0)); SDL_SetAlpha(buffer_tmp, SDL_SRCALPHA, OPACITY); buffer = SDL_DisplayFormat(buffer_tmp); SDL_FreeSurface(buffer_tmp); image = IMG_Load("analoguma.png"); rect_img.w = image->w; rect_img.h = image->h; SDL_BlitSurface(image, &rect_img, screen, &rect_put); for(loop = 0; loop < 40; loop ++){ SDL_Flip(screen); /* 半透明の黒サーフェスを重ねる +/ SDL_BlitSurface(buffer, &rect_scr, screen, &rect_scr); SDL_Delay(100); } SDL_FreeSurface(buffer); SDL_FreeSurface(image); SDL_Quit(); return 0; }
OPACITYの値を変えるとフェードアウトのスピードの調節ができます。
残像
フェードアウトができましたので、あとは画像を動かすだけです。
#include <SDL/SDL.h> #include <SDL/SDL_image.h> #define WINDOW_WIDTH (640) #define WINDOW_HEIGHT (480) #define OPACITY (40) int main(){ SDL_Surface *image; SDL_Surface *screen; SDL_Surface *buffer; SDL_Surface *buffer_tmp; SDL_Rect rect_scr = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; SDL_Rect rect_put = {0, 0, 0, 0}; SDL_Rect rect_img = {0, 0, 0, 0}; int loop; SDL_Init(SDL_INIT_EVERYTHING); SDL_WM_SetCaption("アナロ熊", "アナロ熊"); SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_HWSURFACE); screen = SDL_GetVideoSurface(); buffer_tmp = SDL_CreateRGBSurface(SDL_HWSURFACE, WINDOW_WIDTH, WINDOW_HEIGHT, 32, 0, 0, 0, 0); SDL_FillRect(buffer_tmp, &rect_scr, SDL_MapRGB(buffer_tmp->format, 0,0,0)); SDL_SetAlpha(buffer_tmp, SDL_SRCALPHA, OPACITY); buffer = SDL_DisplayFormat(buffer_tmp); SDL_FreeSurface(buffer_tmp); image = IMG_Load("analoguma.png"); rect_img.w = image->w; rect_img.h = image->h; for(loop = 0; loop < 40; loop ++){ SDL_BlitSurface(buffer, &rect_scr, screen, &rect_scr); SDL_BlitSurface(image, &rect_img, screen, &rect_put); SDL_Flip(screen); if(loop < 20){ rect_put.x = loop * 20; } SDL_Delay(100); } SDL_FreeSurface(buffer); SDL_FreeSurface(image); SDL_Quit(); return 0; }
↑「等速直線運動」というやつです。もう少しスピード感を出すには座標セットの計算を変えてやります。
/* 該当部分抜粋 */ if(loop < 20){ rect_put.x = rect_put.x + loop; }
パラメータは適当に設定しているので色々変えてみてください。
※コメント、トラックバックはできません。メール、リンクは適当に。
Copyright (c) 2008, 2009 greencap