brown water

ゲームやアニメの感想とかプログラムとか

ジャンプゲームの制作3 完成編

前回に引き続き制作していきます。
変更箇所もいろいろ、今回で完結です。

プレイヤーのアニメーション設定

プレイヤーの画像を変更。フリー素材を使わせていただきます。

f:id:chaz4:20180415172633p:plain

f:id:chaz4:20180415172638p:plain

スプライトをアニメーション用に3種類作成。マスク等が同じ位置に来るようにDuplicateを使うのがいいです。
Edit Spriteで画像を追加したりして編集。
走っている時用のplayer_runは4コマで、これをループして走るアニメーションにします。image1と3は同じ画像です。
idle(何も操作していない時)とjumpはrunの中から1コマだけ使っています。
ゲーム中、状態によってアニメーションを選択する時に、「spr_player_run」のように直接指定します。

///初期化
m_hsp = 0;
m_vsp = 0;

image_speed = 0.2;

プレイヤーオブジェクトのスプライトにはとりあえずplayer_idleを設定、Createイベントにコードを書きます。
image_speedでアニメーションの速度を設定。
m_hspは操作していない時の水平方向移動値=動く床に乗っている時のみ使用されます。

///移動
key_left = -keyboard_check(vk_left);
key_right = keyboard_check(vk_right);
key_jump = keyboard_check_pressed(vk_space);

var move = key_left + key_right;
var hsp = move * PLAYER_SPEED;
hsp += m_hsp;   //動く床の移動を加える

//地面に接地しているか
var isGround = false;
if place_meeting(x, y+1, obj_wall) isGround = true;

//垂直方向に重力を加える
if m_vsp < PLAYER_FALLMAX {m_vsp += PLAYER_GRAVITY;}

//方向によってスプライトの向きを変える
if move != 0 {image_xscale = sign(move);}

//地面に接地していたらスペースキーでジャンプ
if key_jump && isGround {m_vsp = -PLAYER_JUMPSPEED;}

//水平方向の衝突
if place_meeting(x+hsp, y, obj_wall) {
    while(!place_meeting(x+sign(hsp), y, obj_wall)) x += sign(hsp);
    hsp = 0;
}
x += hsp;

//垂直方向の衝突
if place_meeting(x, y+m_vsp, obj_wall) {
    while(!place_meeting(x, y+sign(m_vsp), obj_wall)) y += sign(m_vsp);
    m_vsp = 0;
} 
y += m_vsp;

m_hsp = 0;

//アニメーション
if !isGround {
    sprite_index = spr_player_jump;
} else {
    if move != 0 {
        sprite_index = spr_player_run;
    } else {
        sprite_index = spr_player_idle;
    }
}

続いてプレイヤーオブジェクトのStep-Stepのコード。
アニメーション判定用に接地しているかどうかを変数にしました。
接地していない→ジャンプ
接地していて移動操作している→ラン
それ以外→アイドル
sprite_indexで最初に設定しておいたスプライトを指定します。

動く床を2種類にする

最初に作った動く床はスタート時に右に動くものだけだったので、左に動くものも作ります。
スタート時に値を与える方式でも良いのですが、今回は簡単にするため複製してもう1つを作りました。

f:id:chaz4:20180415172702p:plain Duplicateで2つに。

moveFloorLの設定は多少の変更あり。
ParentにmoveFloorRを設定して継承するようにしました。

maxLeft = xstart - 64;
maxRight = xstart + 64;
m_hsp = -1;
///移動
event_inherited();

初期化のm_hspは-1、移動時は親のイベントを実行=moveFloorRと同じ動作をする。

フォントの設定

場面によってフォントを切り替えられるようにあらかじめ設定しておきます。

f:id:chaz4:20180415172643p:plain

f:id:chaz4:20180415172649p:plain

FontsツリーからCreate Fontで作成、フォント名とサイズだけの設定で大丈夫です。 今回はクリア時用、取得ジュエル表示用、ステージ情報表示用の3種類を作っておきました。

ゲームマネージャーの設定

ゲーム全体を管理するマネージャーオブジェクトを作っておきます。
画面には表示されないのでスプライトは無し。
ルームを移動しても破棄されないように、Persistentにチェックを付けておきます。

f:id:chaz4:20180415172658p:plain

数ステージ構成のためにルームを複数作成しますが、マネージャーオブジェクトは最初のルームだけに配置します。表示されないので適当な位置に配置。

///グローバル変数設定
jeweldata[2] = 0;
jeweldata[1] = 0;
jeweldata[0] = 0;
nowStage = 0;

Createイベントのコード
ステージごとのジュエルを取った数を記録しておくための配列を設定。
GameMakerでは配列の初期化時に最大値から設定しておくのが良いらしいです。
今回は最初に一度しか設定しないので影響はないかも知れませんが慣例に従います。
ちなみにこのゲームは全3ステージなのでこのようになりました。
nowStageは現在のステージ情報です。
Persistentにチェックを入れているため、ここで設定した変数はルームを移動をしてもそのまま引き継がれます。

///表示処理
if (room == rm_end) {
    var posY = room_height/2-120;
    draw_set_color(c_black);
    draw_set_font(font_clear);
    draw_set_halign(fa_center);
    draw_text(room_width/2, posY, "CONGRATULATIONS !");

    posY += 20;
    var posX = room_width/2;
    draw_set_font(font_result);
    draw_set_halign(fa_right);
    for (i=0; i<3; i++) {
        posY += 40;
        for (j=0; j<jeweldata[i]; j++) {
            draw_sprite(obj_jewel, 0, posX+10+j*32, posY);
        }
        draw_text(posX-10, posY, "STAGE " + string(i+1));
    }
} else {
    draw_set_color(c_white);
    draw_set_font(font_info);
    draw_set_halign(fa_left);
    draw_text(0, 0, "STAGE " + string(nowStage+1));
}

マネージャーのDraw-Draw GUIイベントのコード
エンディング用ルーム(rm_end)の時はエンディングメッセージと取得したジュエルを表示、それ以外の時はステージ情報を表示しています。
rm_endはルームに付ける名前そのもので、このルームは最後に配置しています。
draw_set_fontで、先程作っておいたフォントを設定。
set_colorで色、set_halignで水平方向の描画開始位置を設定。
設定しないと前の設定が残ったままになります。

ゴールの設定

f:id:chaz4:20180415172654p:plain

///クリアフラグ設定
clear_flag = false;

Createイベントでクリアしたかどうかのフラグを設定

///次のステージへ
clear_flag = false;
obj_manager.nowStage++;
room_goto(room_next(room));

アラーム0のコード
フラグをリセット、マネージャーのステージ情報を更新、次のルームへ移動。

///ゴールした時
clear_flag = true;

effect_create_above(ef_ring, x+sprite_width/2, y+sprite_height/2, 1, c_olive);
audio_play_sound(snd_clear, 10, false);

//プレイヤーを消去
with(other) {instance_destroy();}

//取得したジュエル数を記録
var jw = 2 - instance_number(obj_jewel);
with(obj_manager) {
    jeweldata[nowStage] = jw;
}

//4秒後にアラーム発動
alarm[0] = room_speed * 4;

ゴールとプレイヤーが接触した時のコード ここでマネージャーにジュエル数を記録しておきます。 各ステージのジュエル数は2なので、ゴール時に存在しているインスタンスを2から引いて計算しています。

///メッセージ描画
if (clear_flag) {
    draw_set_color(c_black);
    draw_set_font(font_clear);
    draw_set_halign(fa_center);
    draw_text(room_width/2, room_height/2, "STAGE CLEAR");
}

クリアフラグがオンの時のみメッセージが描画されます。
アラーム発動中のため、4秒後には全て消去されます。

以下のサイトのフリー素材を使わせて頂きました。ありがとうございます。

Free Seed Material

blog.pipoya.net

soundeffect-lab.info

maoudamashii.jokersounds.com

白螺子屋