
落とし穴 落とし穴に落ちる
前回の落とし穴
前回、落とし穴を作った。
今回は、プレイヤーが落ちた時の処理を作る。
落とし穴、超絶面白いわ♪
今日のドット絵

今回のハイライト 「落ちたのはYOUです!」

落とし穴の想い出② 全落水落オープン
今を時めく芸人たちが、落とし穴に落ちまくる。
ドッキリの定番でおいらの大好物。小木と竹山が特にオモロかった。
今はできない昭和のお笑い。アマゾンに頑張ってもらおう。

プレイヤーが落とし穴に落ちた時の処理
将来的に何らかの演出するとして、とりあえず、プレイヤーが落ちた時に、ダメージを受けた後に、別の穴から出てくるようにしてみた。
別の穴にワープ
・穴に入った時に煙を出して消す
・ランダムにどこかの穴から出てくる
・ワープ後に再落下しないように落下フラグで制御し、ダメージを与えて
ぶっ飛ばして穴から移動させる
プレイヤー(obj_player)のCreateEvent(作成)
into_hole = false; // 穴への落下フラグ
プレイヤー(obj_player)の穴とのコリジョンイベント
if (!into_hole) {
into_hole = true; // 落下状態にする
instance_create_layer(x, y, "hitmark", obj_smoke_s); // 煙を出す
life -= 1; // ダメージを与える
damage_hit = true; // ダメージ状態に変更
rolling_attack = false; // ローリングアタックを解除
sprite_index = spr_i_damage; // ダメージアニメーションに変更
// どのobj_holeから出現させるかをランダムに選択
var _spawn_points = instance_number(obj_hole); // 穴の数を取得
random_spawn_index = irandom(_spawn_points - 1); // 穴のIDをランダム取得
// ランダムに選択したobj_holeの位置を取得
var _chosen_spawn = instance_find(obj_hole, random_spawn_index);
x = _chosen_spawn.x;
y = _chosen_spawn.y;
instance_create_layer(x, y, "hitmark", obj_smoke_s); // 出現位置で煙を表示
speed = 5; // 穴から出るスピード
direction = irandom(359) // 穴から出る方向
alarm[2] = 20; // 穴からぶっ飛ぶ時間
}
プレイヤー(obj_player)のアラームイベント
into_hole = false; // 落下状態でなくす
damage_hit = false; // ダメージ状態で無くす
speed = 0; // 止まる
rolling_attack = false; // ローリングアタック解除
sprite_index = spr_i_idle; // 待機アニメーションにする
instance_destroy(obj_charging); // チャージエフェクトを消去
image_blend = c_white; // キャラの色を元に戻す
こんな感じ。

これでも良いけど、同じ場所は選ばないようにしたい。
穴の位置に煙が出ないとおかしいな。それもついでに直そう。
AIに相談:落ちた穴と別の場所にワープ
特定の穴に入ったプレイヤーを、それ以外の穴にワープさせるには以下のステップで処理を行います。
ステップ 1: 穴のIDを保持
各穴 (obj_hole) にユニークな hole_id を割り当て、ワープ先を管理します。
ステップ 2: プレイヤーが入った穴のIDを記録
プレイヤーが入ったときに、対象の穴の hole_id を記録します。
ステップ 3: 別の穴にワープ
記録された hole_id を除外して、ランダムに別の穴を選びます。
AIアドバイスに従うも、時々同じ場所にワープする問題

原因は、穴のインスタンスIDの取得ミス。
holeのインスタンスIDをhole_id = []のように配列になっていたので、入った穴のインスタンスIDと乱数が決めたインスタンスIDが一致しないから、同じ穴から時々出ちゃう。
debug messageを出して原因が分かった。
hole_id = idにすれば良かったが、単純ミスに気付かず、AIに聞いても的外れな回答が返ってきて、ぜんぜん直らなった。
AIに任せで関数の内容を全く理解してないし、デバッグのやり方も良く分からん。できればいいや。という非効率なやり方でやってるからなあ。コード汚いし。
自分でプログラムしたりドット絵描いたりして、プログラマーやアートの人へのリスペクトが止まらなくなる。感謝。

別のプロジェクト作って1個づつ原因を切り分けながらテストして修正したのがこちら。
穴(obj_hole)のCreateEvent(作成)
hole_id = id; // 自身のインスタンスIDを使用して一意のIDを設定
プレイヤー(obj_player)のCreateEvent(作成)
into_hole = false;
target_hole = -1;
プレイヤー(obj_player)の穴(obj_hole)のコリジョンイベント
if (!into_hole) {
into_hole = true; // 穴に落下状態にする
instance_create_layer(x, y, "hitmark", obj_smoke_s); // 入った穴に煙を出す
// ダメージ処理
life -= 1; // ダメージを与える
damage_hit = true; // ダメージ状態に変更
rolling_attack = false; // ローリングアタックを解除
sprite_index = spr_i_damage; // ダメージアニメーションに変更
// 変数を初期化
var _entered_hole_id = other.hole_id; // 衝突した穴の ID を取得
var _possible_holes = []; // ワープ可能な穴を格納
// with で他の穴を調査
with (obj_hole) {
if (hole_id != _entered_hole_id) { // 入った穴以外を選択
array_push(_possible_holes, id); // ワープ先候補として追加
}
}
// ワープ先を決定
if (array_length(_possible_holes) > 0) {
var _random_index = irandom(array_length(_possible_holes) - 1);
var _target_hole = _possible_holes[_random_index]; // ランダムにインスタンスIDを設定
// ワープ先の穴が存在する場合、その座標にプレイヤーを移動
if (instance_exists(_target_hole)) {
x = _target_hole.x;
y = _target_hole.y;
// 結果を確認
show_debug_message("enter hole id: " + string(_entered_hole_id)); // debug表示
show_debug_message("random id: " + string(_target_hole)); // debug表示
instance_create_layer(x, y, "hitmark", obj_smoke_s); // ワープ先で煙を出す
speed = 5;
direction = irandom(359)
alarm[0] = 20;
} else {
show_debug_message("ワープ先の穴が見つかりません!");
}
} else {
show_debug_message("ワープ先が見つかりません!");
}
}
プレイヤー(obj_player)のアラームイベント
into_hole = false; // 落下状態でなくす
damage_hit = false; // ダメージ状態で無くす
speed = 0; // 止まる
rolling_attack = false; // ローリングアタック解除
sprite_index = spr_i_idle; // 待機アニメーションにする
instance_destroy(obj_charging); // チャージエフェクトを消去
image_blend = c_white; // キャラの色を元に戻す
やっとできた。

ワープ後のキャラを目立たせる
ワープ後、見失わないように看板を作った。
人は「大きさ」「動き」「色」「形」の順に認識
32x32で作ったが、キャラと比較してデカすぎだので24x24に修正。
それだと目立たないので、光ったり動かしたりするようにした。


コードは丸影のものを流用したので割愛。時間で消えるようにした。
看板が消える前に穴に入ると、看板が重なって表示されるので、穴を呼び出す前に、前の看板が残っていたら消すようにした。

arrayには気を付けよう。関数を理解しよう。

使用ツールとAI
ゲームツールは「GameMaker」
ドット絵ツールは「EDGE」
AIは「ChatGPT」