SDLでボンバーマン風ゲームを作ってみる5


今回は、タイトル画像を追加してみました。







ソースコードはこちら

http://www.geocities.jp/finnissy/data/090810.zip


snd.c

#include "main.h"
#include "game.h"
#include "import.h"
#include "libttf.h"
#include "gfx.h"
#include "snd.h"
#include "color.h"
#include <stdio.h>
#include <ctype.h>

#define MVAL    (2)         //移動量
#define ID_BALL (0)         // blit image ID
#define FUNC_MAX    (10)    //同時に実行する関数の最大値

#define MENU01_X    (180)
#define MENU01_Y    (150)
#define MENU01_ID   (20)
#define MENU02_X    (180)
#define MENU02_Y    (200)
#define MENU02_ID   (21)
#define MENU03_X    (180)
#define MENU03_Y    (250)
#define MENU03_ID   (22)

#define FONT_SIZE_MENU (FONT_SIZE+8)

/****************************************************/
/*                  private method                  */
/****************************************************/
static void title_event(void);
static void menu_blit(void);

static void proc_event(void);
static void key_event(SDLKey key);
static void notify_end(void);
static void notify_state(gstate state);
static void wait(void);
static void frame_blit(void);
static void move_abs(int x,int y,int mval);
static void move_pos(int x,int y);
static boolean dec_keys(SDLKey key);
static void proc_keys(SDLKey key);

/****************************************************/
/*                  private member                  */
/****************************************************/
/************************/
/*          flags       */
/************************/
static boolean active;              //ゲームフラグ
static boolean pressed;             //押下
static boolean flg_bomm;            //爆弾フラグ
static int game_state;                  //状態

/************************/
/*      parameter       */
/************************/
static Uint32 elapsed_ms;           //経過ミリ秒
static SDLKey key_state;            //Key Code
static Sint16 screenX = 7*BLOCK_SIZE;
static Sint16 screenY = 7*BLOCK_SIZE;
static Sint16 move_state;
static Sint8 key_count = 0;
static Uint16 level = 1;
static Sint8 now_menu;

static struct game_func{
    void (*f[FUNC_MAX])(void);
    int numfunc;
} games;

/****************************************************/
/*                  private method                  */
/****************************************************/


static
void title_event(void)
{
    SDL_Event ev;

    while( SDL_PollEvent(&ev) )
    {
        switch(ev.type)
        {
        case SDL_QUIT:      /*ウィンドウの[×]ボタン*/
            notify_end();
            notify_state(STATE_END);
            break;
        case SDL_KEYDOWN:   /*キーダウン*/
            switch( ev.key.keysym.sym )
            {
            case SDLK_UP:       key_state = SDLK_UP;        break;
            case SDLK_DOWN:     key_state = SDLK_DOWN;      break;
            case SDLK_RETURN:   key_state = SDLK_RETURN;    break;
            default:            return; //------abort
            }
            pressed = TRUE;
            break;
        case SDL_KEYUP:
            break;
        case SDL_MOUSEBUTTONDOWN:   /*マウスダウン*/
            break;
        default:
            break;
        }
    }
}

static
void menu_blit(void)
{
    if( pressed )
    {
        switch( key_state )
        {
        case SDLK_UP:       now_menu = (now_menu-1) < 0 ? 0 : now_menu-1;   break;
        case SDLK_DOWN:     now_menu = (now_menu+1) % (STATE_MAX-1);        break;  //unused state_quit 
        case SDLK_RETURN:   notify_end();
                            if(now_menu == 0)   notify_state(STATE_PLAY);   else
                            if(now_menu == 1)   notify_state(STATE_PLAY);   else
                                                //notify_state(STATE_OPTION);   else
                            if(now_menu == 2)   notify_state(STATE_END);
                            break;
        default:            break;
        }

        switch(now_menu)
        {
        case 0:
            blit_text(MENU01_X,MENU01_Y,COL_RED,COL_PINK,"START",MENU01_ID);
            blit_text(MENU02_X,MENU02_Y,COL_BLUE,COL_AQUA,"OPTION",MENU02_ID);
            blit_text(MENU03_X,MENU03_Y,COL_WHITE,COL_GRAY,"END",MENU03_ID);
            break;
        case 1:
            blit_text(MENU01_X,MENU01_Y,COL_AQUA,COL_ORANGE,"START",MENU01_ID);
            blit_text(MENU02_X,MENU02_Y,COL_RED,COL_PINK,"OPTION",MENU02_ID);
            blit_text(MENU03_X,MENU03_Y,COL_WHITE,COL_GRAY,"END",MENU03_ID);
            break;
        case 2:
            blit_text(MENU01_X,MENU01_Y,COL_AQUA,COL_ORANGE,"START",MENU01_ID);
            blit_text(MENU02_X,MENU02_Y,COL_BLUE,COL_AQUA,"OPTION",MENU02_ID);
            blit_text(MENU03_X,MENU03_Y,COL_RED,COL_PINK,"END",MENU03_ID);
            break;
        default:    break;
        }
        pressed = FALSE;
    }
}

static
void proc_event(void)
{
    SDL_Event ev;

    while( SDL_PollEvent(&ev) )
    {
        switch(ev.type)
        {
        case SDL_QUIT:      /*ウィンドウの[×]ボタン*/
//            printf("QUIT\n");
            notify_end();
            notify_state(STATE_END);
            break;
        case SDL_KEYDOWN:   /*キーダウン*/
//            printf("KeyDonw\n");
            proc_keys( ev.key.keysym.sym );
            break;
        case SDL_KEYUP:
//          printf("KeyUp\n");
            if( dec_keys(ev.key.keysym.sym) )
            {
                pressed = FALSE;
                key_count = 0;
            }
            break;
        case SDL_MOUSEBUTTONDOWN:   /*マウスダウン*/
//          printf("MouseDonw\n");
            break;
        default:
            break;
        }
    }
}

static
void frame_blit(void)
{
    int i;

    for(i = 0;i < games.numfunc;i++)
    {
        if(games.f[i] != NULL)
            games.f[i]();
    }

    if(flg_bomm)
    {
        bomm_start(screenX,screenY);
        flg_bomm = FALSE;
    } else 
    if(pressed)
    {
        key_event(key_state);
    }

    blit(screenX, screenY, images.ball, ID_BALL);
}

static
void key_event(SDLKey key)
{
    switch(key)
    {
    case SDLK_ESCAPE:   notify_end();
                        notify_state(STATE_END);break;
    case SDLK_RIGHT:    move_abs(1,0,MVAL);     break;
    case SDLK_LEFT:     move_abs(-1,0,MVAL);    break;
    case SDLK_UP:       move_abs(0,-1,MVAL);    break;
    case SDLK_DOWN:     move_abs(0,1,MVAL);     break;
    default:            break;
    }
}

static
boolean dec_keys(SDLKey key)
{
    switch(key)
    {
    case SDLK_RIGHT:    key_count--;    break;
    case SDLK_LEFT:     key_count--;    break;
    case SDLK_UP:       key_count--;    break;
    case SDLK_DOWN:     key_count--;    break;
    default:            return FALSE;
    }

    return key_count <= 0 ? TRUE    :   FALSE;
}

static
void proc_keys(SDLKey key)
{
    switch(key)
    {
    case SDLK_ESCAPE:   key_state = key;
    case SDLK_RIGHT:    key_state = key;    key_count++;    break;
    case SDLK_LEFT:     key_state = key;    key_count++;    break;
    case SDLK_UP:       key_state = key;    key_count++;    break;
    case SDLK_DOWN:     key_state = key;    key_count++;    break;
    case SDLK_SPACE:    flg_bomm = TRUE;
                        return;
    default:            return;
    }

    pressed = TRUE;
}

static
void move_abs(int x,int y,int mval)
{
    int x_dumy;
    int y_dumy;
    int x_flg;
    int y_flg;
    int now_state;

    x_dumy = (screenX + x*mval) <= -BLOCK_SIZE ?
        FRAME_WIDTH - BLOCK_SIZE    :
        (screenX + x*mval) % FRAME_WIDTH;
    y_dumy = (screenY + y*mval) <= -BLOCK_SIZE ?
        FRAME_HEIGHT - BLOCK_SIZE   :
        (screenY + y*mval) % FRAME_HEIGHT;

    x_flg = screenX - x_dumy;
    y_flg = screenY - y_dumy;
    now_state = (x_flg > 0) ? MV_LEFT : (x_flg < 0) ? MV_RIGHT :
                (y_flg > 0) ? MV_UP : (y_flg < 0) ? MV_DOWN :
                MV_LEFT;

    //printf("%d : %d\n",x_dumy,y_dumy);
    if( map_calc(x_dumy, y_dumy, now_state) )   //進行方向にトライ
    {
        move_state = now_state;
        screenX = x_dumy;
        screenY = y_dumy;
    } else 
    if(move_state != now_state)     //前回と今回が同じ進行方向は無理
    {   
        //前回の進行方向にトライ
        switch( move_state )
        {
        case MV_LEFT:
            if( map_calc(screenX - MVAL,screenY,move_state) )
                screenX -= MVAL;
            break;
        case MV_RIGHT:
            if( map_calc(screenX + MVAL,screenY,move_state) )
                screenX += MVAL;
            break;
        case MV_UP:
            if( map_calc(screenX,screenY - MVAL,move_state) )
                screenY -= MVAL;
            break;
        case MV_DOWN:
            if( map_calc(screenX,screenY + MVAL,move_state) )
                screenY += MVAL;
            break;
        default:
            break;
        }
    }
}

static
void move_pos(int x,int y)
{
    screenX = (x < 0) ?
        0   :   x % FRAME_WIDTH;

    screenY = (y < 0) ? 
        0   :   y % FRAME_HEIGHT;
}

static
void notify_end(void)
{
    active = FALSE;
}

static
void notify_state(gstate state)
{
    game_state = state;
}

static
void wait(void)
{
    Uint32 ms;
    const Uint8 frate = 16;

    ms = SDL_GetTicks() - elapsed_ms;

    if(ms < frate)
    {
        SDL_Delay(frate - ms);
        //printf("wait() : %d\n", frate - ms);
    }

    elapsed_ms = SDL_GetTicks();
}

/************************************************/
/*              Public Method                   */
/************************************************/
gstate proc_title(void)
{
    active = TRUE;
    play_bgm(sounds.opening);
    ttf_resize(FONT_SIZE_MENU);

    blit_text(MENU01_X,MENU01_Y,COL_AQUA,COL_ORANGE,"START",MENU01_ID);
    blit_text(MENU02_X,MENU02_Y,COL_BLUE,COL_AQUA,"OPTION",MENU02_ID);
    blit_text(MENU03_X,MENU03_Y,COL_WHITE,COL_GRAY,"END",MENU03_ID);

    while(active)
    {
        title_event();
        menu_blit();
        draw();
        update();
        wait();
    }
    return game_state;
}

gstate proc_play(void)
{
    active = TRUE;
    draw_scene(STATE_PLAY);
    play_bgm(sounds.play);

    while(active)
    {
        proc_event();
        frame_blit();
        fps(elapsed_ms,FRAME_RATE);
        draw();
        update();
        wait();
    }

    return game_state;
}

gstate proc_end(void)
{
    return STATE_QUIT;
}

void add_func(void (*f)(void))
{
    int i;

    for(i = 0;i < games.numfunc;i++)
    {
        if(games.f[i] == f)
        {
            i = -1;
            break;
        }
    }

    if(i >= 0 && games.numfunc < FUNC_MAX)
    {
        games.f[games.numfunc] = f;
        games.numfunc++;
    }
}

void del_func(void (*f)(void))
{
    int i;

    for(i = 0;i < games.numfunc;i++)
    {
        if(games.f[i] == f)
        {
            int idx = i + 1;
            while(idx < games.numfunc)
            {
                games.f[i] = games.f[idx];
                i++;
                idx++;
            }
            games.f[i] = NULL;
            games.numfunc--;
            break;
        }
    }
}

Uint16 get_level(void)
{
    return level % MAX_LEVEL;
}