SDLで描画ライブラリの作成
今回はプレゼンハムの線分発生アルゴリズムを使って、線を描く関数を作ります。
Enterキーを押すと、ライン描画関数を使ったグラデーションの矩形を描画します。
Enterを繰り返し押下するごとに、描画する矩形の色が変わります。
main.c
#include <SDL/SDL.h> #include "drw_line.h" #pragma comment(lib,"SDL.lib") #pragma comment(lib,"SDLmain.lib") SDL_Surface *g_screen; int rcv_event(void); int main(int argc,char *argv[]) { Uint8 r,g,b; Uint8 flg = 1; Sint8 inc[3] = {1,1,-1}; r = 0x00; g = 0x00; b = 0xff; if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { printf("Initialize Error : %s",SDL_GetError()); return -1; } SDL_WM_SetCaption("SDL",NULL); if( (g_screen = SDL_SetVideoMode(456,456,32,SDL_SWSURFACE)) == NULL) { printf("SetVideoMode Error : %s",SDL_GetError()); return -1; } while( flg ) { SDL_FillRect(g_screen, NULL, 0x00000000); switch( rcv_event() ) { case 1: flg = 0; break; case 2: { int x1,x2,y1,y2; int drw_w; x1 = 100; x2 = 356; y1 = 100; y2 = 356; drw_w = (x2 + x1)/2; while(x1 <= drw_w) { drw_line(x1,y1,x2,y1,0,(r<<16)+(g<<8)+b,g_screen); drw_line(x2,y1,x2,y2,0,(r<<16)+(g<<8)+b,g_screen); drw_line(x2,y2,x1,y2,0,(r<<16)+(g<<8)+b,g_screen); drw_line(x1,y2,x1,y1,0,(r<<16)+(g<<8)+b,g_screen); x1++; x2--; y1++; y2--; r += inc[0]; g += inc[1]; b += inc[2]; } switch(flg) { case 1: inc[0] = 1,inc[1] = -1,inc[2] = -1; r = 0x00,g = 0xff,b = 0xff; break; case 2: inc[0] = -1,inc[1] = 1,inc[2] = -1; r = 0xff,g = 0x00,b = 0xff; break; case 3: inc[0] = -1,inc[1] = -1,inc[2] = 1; r = 0xff,g = 0xff,b = 0x00; break; case 4: inc[0] = -1,inc[1] = 1,inc[2] = 1; r = 0xff,g = 0x00,b = 0x00; break; } if( flg++ > 4){ flg = 1; inc[0] = 1,inc[1] = 1,inc[2] = -1; r = 0x00,g = 0x00,b = 0xff; } } SDL_Flip(g_screen); break; default: break; } SDL_Delay(60); } SDL_FreeSurface(g_screen); SDL_Quit(); return 0; } int rcv_event( void ) { SDL_Event ev; SDLKey *key; while( SDL_PollEvent( &ev ) ) { switch( ev.type ) { case SDL_QUIT: return 1; break; case SDL_KEYDOWN: /************************************/ /* キー情報を取得する */ /************************************/ key = &(ev.key.keysym.sym); switch( *key ) { case SDLK_ESCAPE: return 1; //終了通知 break; case SDLK_RETURN: return 2; default: break; } //----------------------------------// // GetKeyEvent END // //----------------------------------// default: break; } } return 0; //イベントなし } |
Graphics.c
#pragma comment(lib,"SDL.lib") #pragma comment(lib,"SDLmain.lib") /********************************************************************************/ /* 関数プロトタイプ */ /********************************************************************************/ /********************************************************************************/ /* 関数の実装 */ /********************************************************************************/ /*----------------------------------------------------------------------*/ /* 作成日時 2009/02/10 */ /* 概要 プレゼンハムの線分発生アルゴリズムを使った */ /* 直線描画関数 */ /* Descripsion */ /* return value */ /* */ /*----------------------------------------------------------------------*/ int drw_line(Sint16 x0,Sint16 y0,Sint16 x1,Sint16 y1, Uint8 pxl, Uint32 color, SDL_Surface *screen) { if( screen->locked == 0 ) { if( SDL_LockSurface( screen ) >= 0) { Uint32 *fld; Uint32 *adr_min; Uint32 *adr_max; Sint16 E, x, y, w; Sint16 cnt; Uint16 pitch; Uint8 bpp; Sint16 p_flg; const Sint8 INC_X = (x1 - x0 >= 0) ? 1 : -1; const Sint8 INC_Y = (y1 - y0 >= 0) ? 1 : -1; const Uint16 REV_X = abs(2*(x1 - x0)); /* xの補正値を設定 */ const Uint16 REV_Y = abs(2*(y1 - y0)); /* yの補正値を設定 */ adr_min = (Uint32*)screen->pixels; adr_max = (Uint32*)screen->pixels + screen->h * screen->w; x = x0; y = y0; w = screen->w; pitch = screen->pitch; bpp = screen->format->BytesPerPixel; p_flg = abs(x1-x0) - abs(y1-y0); if( screen->format->BitsPerPixel != 8) { color = SDL_MapRGB(screen->format, (Uint8)(color>>16),(Uint8)(color>>8),(Uint8)color); }else{ return -1; } if(p_flg > 0) { /* Xの増分値が常に1以上 */ E = -(abs(x1 - x0)); cnt = (x < x1) ? x : x1 - (x - x1); do{ /* 描画対象のアドレスを計算 */ fld = adr_min + (x) + (y * w); /* 描画領域から外れていなければ */ if( (fld >= adr_min) && (fld < adr_max) ) { /* 指定の色で描画する */ *fld = color; } x += INC_X; E += REV_Y; if( E >= 0) { y += INC_Y; E -= REV_X; } }while(cnt++ < x1); }else if(p_flg < 0) { /* Yの増分値が常に1以上 */ E = -(abs(y1 - y0)); cnt = (y < y1) ? y : y1 - (y - y1); do{ /* 描画対象のアドレスを計算 */ fld = adr_min + (x) + (y * w); /* 描画領域から外れていなければ */ if( (fld >= adr_min) && (fld < adr_max) ) { /* 指定の色で描画する */ *fld = color; } y += INC_Y; E += REV_X; if( E >= 0) { x += INC_X; E -= REV_Y; } }while(cnt++ < y1); }else{ /* XとYの増分値が常に1 */ cnt = (x < x1) ? x : x1 - (x - x1); do{ /* 描画対象のアドレスを計算 */ fld = adr_min + (x) + (y * w); /* 描画領域から外れていなければ */ if( (fld >= adr_min) && (fld < adr_max) ) { /* 指定の色で描画する */ *fld = color; } x += INC_X; y += INC_Y; }while(cnt++ < x1); } SDL_UnlockSurface( screen ); }else{ //push Error Message } } return 0; } |