
落とし穴 地形の自動配置システム
前回の落とし穴
前回は、普通は穴に近寄らないが興奮すると我を忘れて穴の近くに来るボスを作った。
今回は、地形ブロックや穴をランダムに自動配置してみる。
今日のハイライト

落とし穴の想い出 側溝
昔住んでいた場所は駅に近い住宅地だった。
そこは起伏の少ない平地だったので、雨水を流すために側溝があった。
1年に1度の側溝の掃除は結構辛かったのを思い出す。
側溝で強烈なインパクトだったのは、近所の子供が自転車で側溝に落ちて買ったばかりの自転車が大破した話だ。子供は擦り傷程度ですんだが、運が悪ければ大怪我につながる。怖すぎる。
子供の頃は、学校の帰りに側溝を歩いて帰ったりしていたな。
側溝は遊び場だったが、状況が違えば怖い場所に変わる。。。
地形の自動生成
ブロック崩しの自動生成を使ってみる
コードに関しては自動配置システムの一連の記事を参照。
地形ブロックのサイズに合わせ、以下のようにパラメータを変更。
grid_size_x = 32;
grid_size_y = 16;
blocks = 5;
x_range = 256;
offset_x = 16;
center_x = room_width/2;
完全なランダム配置だとうまく遊べない
ブロック崩しでは左右対称にランダムに配置していた。
完全にランダムだと通路がなかったりバラバラだったりするので使いにくいし、そもそも落とし穴では左右対称の必要がないのでシステムを再構築することにした。

地形ブロックの配置システムを再構築
地形を配置する条件
・画面を何分割かに区切ることで「落とす快楽」の障害を作る
・地形ブロックの周りをまわって敵を巻くのに使える
・穴やスポーンポイントが置けるだけのスペースがある
・地形ブロックの数は多すぎず少なすぎず、ランダムに増減したい
etc…
画面を何分割かに区切って自動配置
①画面を分割して、それぞれに起点となるブロックを置いてみる
②起点となるブロックの上下左右にブロックを置いてみる
③穴を配置する
①起点となるブロックをランダムに配置
・画面の4か所に起点となるブロックを置いてみた

②起点ブロックの上下左右に追加で配置
・起点ブロックの上下左右に、それぞれ70%の確率でブロックを配置
※描画順を考慮する必要がある

③穴を配置
・4分割した画面にそれぞれ70%の確率で1個づつ穴を配置
・もし、地形ブロックと重なった場合は、起点ブロックと点対象に配置

今回のコード
画面分割するところも自動化してきれいにしたいが、色々実験するために、力業で作ってしまった。美しくないなー。
/// @description ブロックの自動配置
// このエディターでコードを作成することができます
// 4か所に数ブロックづつランダム配置する
grid_size_x = 32; // グリッドx
grid_size_y = 16; // グリッドy
x_positions = []; // 既存のブロックのx座標
y_positions = []; // 既存のブロックのY座標
randomize();
// ブロック
// 4か所の起点を作って起点から何個かブロックを置く
var range_x = room_width/2/grid_size_x - 2;
var range_y = room_height/2/grid_size_y - 2;
// 左上
var x1 = irandom_range(2, range_x)*grid_size_x+grid_size_x/2;
var y1 = irandom_range(2, range_y)*grid_size_y;
if (irandom(2) = 0) instance_create_layer(x1-grid_size_x,y1,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x1+grid_size_x,y1,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x1,y1+grid_size_y,"block",obj_block_32);
instance_create_layer(x1,y1,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x1,y1-grid_size_y,"block",obj_block_32);
// 右上
var x2 = irandom_range(1, range_x)*grid_size_x+grid_size_x/2;
var y2 = irandom_range(2, range_y)*grid_size_y;
if (irandom(2) = 0) instance_create_layer(x2-grid_size_x + room_width/2 ,y2,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x2+grid_size_x + room_width/2 ,y2,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x2 + room_width/2 ,y2+grid_size_y,"block",obj_block_32);
instance_create_layer(x2 + room_width/2 ,y2,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x2 + room_width/2 ,y2-grid_size_y,"block",obj_block_32);
// 左下
var x3 = irandom_range(2, range_x)*grid_size_x+grid_size_x/2;
var y3 = irandom_range(2, range_y)*grid_size_y;
if (irandom(2) = 0) instance_create_layer(x3-grid_size_x,y3 + room_height/2 ,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x3+grid_size_x,y3 + room_height/2 ,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x3,y3+grid_size_y + room_height/2 ,"block",obj_block_32);
instance_create_layer(x3,y3 + room_height/2 ,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x3,y3-grid_size_y + room_height/2 ,"block",obj_block_32);
// 右下
var x4 = irandom_range(1, range_x)*grid_size_x+grid_size_x/2;
var y4 = irandom_range(2, range_y)*grid_size_y;
if (irandom(2) = 0) instance_create_layer(x4-grid_size_x + room_width/2 ,y4 + room_height/2 ,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x4+grid_size_x + room_width/2 ,y4 + room_height/2 ,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x4 + room_width/2 ,y4+grid_size_y + room_height/2 ,"block",obj_block_32);
instance_create_layer(x4 + room_width/2 ,y4 + room_height/2 ,"block",obj_block_32);
if (irandom(2) = 0) instance_create_layer(x4 + room_width/2 ,y4-grid_size_y + room_height/2 ,"block",obj_block_32);
// 穴のポジション
// 左上
var hx1 = irandom_range(2, range_x)*grid_size_x;
var hy1 = irandom_range(2, range_y)*grid_size_y;
if (abs(hx1-x1) >= grid_size_x*2 && abs(hy1-y1) >= grid_size_y*2) {
instance_create_layer(hx1,hy1,"block",obj_hole);
} else if (irandom(9) < 7 && abs(room_width/2-x1-x1)>=grid_size_x*2 && abs(room_height/2-y1-y1)>=grid_size_y*2) {
instance_create_layer(room_width/2 - x1, room_height/2 -y1, "block",obj_hole);
}
// 右上
var hx2 = irandom_range(2, range_x)*grid_size_x;
var hy2 = irandom_range(2, range_y)*grid_size_y;
if (abs(hx2-x2) >= grid_size_x*2 && abs(hy2-y2) >= grid_size_y*2) {
instance_create_layer(room_width/2+hx2,hy2,"block",obj_hole);
} else if (irandom(9) < 7 && abs(room_width-x2-x2)>=grid_size_x*2 && abs(room_height/2-y2-y2)>=grid_size_y*2) {
instance_create_layer(room_width - x2, room_height/2 -y2, "block",obj_hole);
}
// 左下
var hx3 = irandom_range(2, range_x)*grid_size_x;
var hy3 = irandom_range(2, range_y)*grid_size_y;
if (abs(hx3-x3) >= grid_size_x*2 && abs(hy3-y3) >= grid_size_y*2) {
instance_create_layer(hx3,hy3+room_height/2,"block",obj_hole);
} else if (irandom(9) < 7 && abs(room_width/2-x3-x3)>=grid_size_x*2 && abs(room_height-y3-y3)>=grid_size_y*2) {
instance_create_layer(room_width/2 - x3, room_height -y3, "block",obj_hole);
}
// 右下
var hx4 = irandom_range(2, range_x)*grid_size_x;
var hy4 = irandom_range(2, range_y)*grid_size_y;
if (abs(hx4-x4) >= grid_size_x*2 && abs(hy4-y4) >= grid_size_y*2) {
instance_create_layer(hx4+room_width/2,hy4+room_height/2,"block",obj_hole);
} else if (irandom(9) < 7 && abs(room_width-x4-x4)>=grid_size_x*2 && abs(room_height-y4-y4)>=grid_size_y*2) {
instance_create_layer(room_width - x4, room_height -y4, "block",obj_hole);
}
// 真ん中
if (instance_number(obj_hole) < 2) instance_create_layer(room_width/2,room_height/2,"block",obj_hole);
次回はゲームとガッチャンコしてテスト
使用ツールとAI
ゲームツールは「GameMaker」
ドット絵ツールは「EDGE」
AIは「ChatGPT」