【ウディタ】ブロックパズル作りの基礎
<注釈>
・ウディタ Ver2.281で実施
・中身はザックリで、備忘録的なものです
・記事を読む前提条件として下記の辺りが対象
> コモンイベントをそこそこ自作できる
> テトリスとかのパズルのイメージが分かる
・正規のやり方などは知りません。独力です。
<概要>
ポリオミノと呼ばれる形式のパズルについて
ある程度の形はできたので記事にしとく。
ここで扱っているのは
ペントミノ(5マスブロック)です。
※有名なテトリスはテトロミノ
作ってたゲーム環境は下記。
下記呼称を使います。
手持ちのブロック:ハンド
受け皿の箱型:ボックス
ここで扱う処理は下記になります。
・ハンドを回転する処理の考え方
・ハンドを反転する処理の考え方
・ハンドを置くときの判定
<事前準備>
可変DBを用意します。
・ボックスは8×8のサイズ
・ハンドは5×5のサイズ
※ハンドは使わないDB区画もあります。
ここでは2つのDB構造を例に出します。
<①データIDと項番で作る可変DB>
最もオーソドックスなDBを扱う方法。
初期値は空欄を示す値などにしましょう
<②項番だけで作る可変DB>
少し特殊ですが10×10サイズまでなら
データ1つの枠で作ることができます。
Xが10の桁で、Yが1の桁として考えます。
例えば、X=5 , Y=8 の場合、ID:58を参照する。
Xを10倍して、それにYを足せばIDになります。
8×8サイズなら、88番まで
タイプ設定で作りましょう。
(0~7でやるなら77番まで)
上図では、タイプ設定で初期値を
空欄を示す値=ー1
未使用欄=99
ブロックID=0~(最大98、扱うブロック種類による)
として設定してます。
ちなみに未使用欄は他用途に使うことも可能です
※例外処理などで省いたりする必要はある
<ブロックを描写>
正方形の1マス画像を用意する。
または、<SQUARE>で描いてもOKです。
1タイル 40pxサイズで作るなど
タイルの大きさを決めておきましょう。
説明をかなり省きますが
ボックスは普通にマス目状にピクチャ表示するだけ。
ハンドブロックはマウス追従するようにします。
ボックス部分…8×8のDBからブロック情報を参照して描写
ハンド部分…5×5のDBから形状を参照して描写
ハンドブロックの生成時は
エフェクトの描画座標シフトでXY移動させると
形を崩さず追従させ やすいです。
▼ハンドブロック生成のサンプル
▼ セルフ変数の初期化 ▼
■変数操作: CSelf51[最小ピクチャ番号] = 25000 + 0
■変数操作: CSelf50[現在ピクチャ番号] = CSelf51[最小ピクチャ番号] + 0
▼ ブロック生成開始 ▼
■変数操作: CSelf31[一時変数X] = 0 + 0
■回数付きループ [ 5 ]回
|■変数操作: CSelf32[一時変数Y] = 0 + 0
|■回数付きループ [ 5 ]回
| |▼ ここでDBから形状をチェック ▼
| |■変数操作: CSelf40[DB項番] = CSelf31[一時変数X] * 10
| |■変数操作: CSelf40[DB項番] += CSelf32[一時変数Y] + 0
| |■DB読込(ユーザ): CSelf20[DBチェック] = ユーザDB[ ブロック形状 : CSelf0[ブロック形状ID] : CSelf40[DB項番] ] (5 : - : -)
| |■条件分岐(変数): 【1】 CSelf20[DBチェック] が 0 以上
| |-◇分岐: 【1】 [ CSelf20[DBチェック] が 0 以上 ]の場合↓
| | |■変数操作: CSelf53[X座標] = 40 * CSelf31[一時変数X]
| | |■変数操作: CSelf54[Y座標] = 40 * CSelf32[一時変数Y]
| | |■ピクチャ表示:CSelf50[現在ピクチャ番号] [中心]ウィンドウ「<SQUARE>」サイズ[40,40] X:0 Y:0 / 0(0)フレーム / パターン 1 / 透 255 / 通常 / 角 0 / 拡 100% / カラー R[100] G[100] B[100]
| | |▼ ここで座標シフト ▼
| | |■ピクチャエフェクト:CSelf50[現在ピクチャ番号] [描画座標シフト] Xシフト CSelf53[X座標] / Yシフト CSelf54[Y座標] (0)フレーム
| | |■変数操作: CSelf50[現在ピクチャ番号] += 1 + 0
| | |■
| |◇分岐終了◇
| |■変数操作: CSelf32[一時変数Y] += 1 + 0
| |■
|◇ループここまで◇◇
|■変数操作: CSelf31[一時変数X] += 1 + 0
|■
◇ループここまで◇◇
▼ ブロック追従処理
■ループ開始
|■変数操作+: CSelf53[X座標] = マウスX座標
|■変数操作+: CSelf54[Y座標] = マウスY座標
|■ピクチャ移動:CSelf50[現在ピクチャ番号] ~ CSelf51[最小ピクチャ番号] X:CSelf53[X座標] Y:CSelf54[Y座標] / 0(0)フレーム / パターン 同値 / 透 同値 / 表示形式:同値 / 角 同値 / 拡 同値 / カラー 同値
|■ウェイト:1 フレーム
|■
◇ループここまで◇◇
■
あとで処理を作る際に、マウス座標を元に
ボックスの座標を取得することになる。
最初はボックスピクチャを0:0座標に表示しておくか
ボックスの始点座標を把握しておく。
<①ハンドを回転させる>
右クリックをしたときに
ハンドブロックを時計回り(右回り)に回転させること
を想定して話を進めます。
回転させるのに、処理的にも負荷的にも楽なのは
形状を先にUDBへ登録してしまうこと。
仮に5×5のブロックであるなら
25×4=100となり、
ウディタのDB項番最大値ギリギリ可能です。
ID 0~24: 0度の回転
ID 25~49: 90度の回転
ID 50~74:180度の回転
ID 75~99:270度の回転
イメージがわかない場合は図を紙に描いて回転させてください。
プログラム側で済ませたい場合は
値を90度右回転させることをイメージしましょう。
上記イメージでは2進数(0と1)で形状を表しています。
<②ハンドを反転させる>
右クリックをしたときに
ハンドブロックを時計回り(右回り)に回転させるが
1周したら反転させて表示する
を作っていることを想定して話を進めます。
簡単に結論を言えば、
通常表示のX座標をマイナス方向にする
と反転表示になります。
これも紙に描いて反転させて(透かして)
見ればイメージしやすいです。
▼ハンドブロックを描写のサンプルコード
■変数操作: CSelf12[一時変数X] = 0 + 0
■回数付きループ [ 5 ]回
|■変数操作: CSelf13[一時変数Y] = 0 + 0
|■回数付きループ [ 5 ]回
| |■DB読込(ユーザ): CSelf20[DBチェック] = ユーザDB[ パズル形状 : CSelf60[現在パズル形状_ID] : CSelf10[一時変数A] ] (7 : - : -)
| |■条件分岐(変数): 【1】 CSelf20[DBチェック] が 1 と同じ
| |-◇分岐: 【1】 [ CSelf20[DBチェック] が 1 と同じ ]の場合↓
| | |■ピクチャ表示:CSelf70[現在PAZ_P番号] [中心]ウィンドウ「<SQUARE>」サイズ[CSelf62[所持タイルの大きさ],CSelf62[所持タイルの大きさ]] X:0 Y:0 / 0(0)フレーム / パターン 1 / 透 0 / 通常 / 角 0 / 拡 100% / カラー R[CSelf57[RED]] G[CSelf58[GREEN]] B[CSelf59[BLUE]]
| | |■変数操作: CSelf53[X座標] = CSelf12[一時変数X] * CSelf42[1タイルの大きさ]
| | |■変数操作: CSelf53[X座標] *= CSelf65[反転判定] + 0
| | |■変数操作: CSelf54[Y座標] = CSelf13[一時変数Y] * CSelf42[1タイルの大きさ]
| | |■可変DB書込:DB[ ハンドブロック状態 : CSelf13[一時変数Y] : CSelf12[一時変数X] ] (30 : - : -) = CSelf60[現在パズル形状_ID]
| | |■ピクチャエフェクト:CSelf70[現在PAZ_P番号] [描画座標シフト] Xシフト CSelf53[X座標] / Yシフト CSelf54[Y座標] (0)フレーム
| | |■変数操作: CSelf70[現在PAZ_P番号] += 1 + 0
| | |■
| |◇分岐終了◇
| |■変数操作: CSelf10[一時変数A] += 1 + 0
| |■変数操作: CSelf13[一時変数Y] += 1 + 0
| |■
|◇ループここまで◇◇
|■変数操作: CSelf12[一時変数X] += 1 + 0
|■
◇ループここまで◇◇
上記では、CSelf65:反転判定(1 or -1)を使って
X座標だけピクチャエフェクトで表示位置をずらしています。
マイナスにするのはY座標でも問題ないですが
どちらかと言えば
X座標をいじる方が使いやすいかなと思います。
(画面は横長なので)
<③ハンドを置くときの判定>
まずは何も回転させてないピース状態から
考えていくのがいいと思います。
ハンドブロックは最大5x5なので
ループで簡単に処理できます。
ボックスのどこに座標=マス目があるかを把握して
そこを基点に形状を照合しましょう。
【処理の流れは下記】
①ハンドブロックをチェック
②ブロックがあるマスなら、ボックスをチェック
③ボックスに何かある=衝突するなら処理終了
④5x5マスを見てハンドとボックスが衝突しないなら設置OK
次は逆表示も含めて
実際に組んだコモンの設定とコード
クリックした地点のXY座標
コモンイベント呼び出し時に入力しています。
CSelf2の逆表示には、{1 or -1} が入力されます。
ハンドブロック形状は先に
"ハンドピース状態"という名前のCDBに登録済みの状態。
CSelf3はボックスに登録するときに使う識別IDです。
|■変数操作: CSelf12[一時変数X] = 0 + 0
|■変数操作: CSelf32[一時XX] = 0 + 0
|■回数付きループ [ 5 ]回
| |■変数操作: CSelf13[一時変数Y] = 0 + 0
| |■回数付きループ [ 5 ]回
| | |■DB読込(可変): CSelf20[DBチェック] = 可変DB[ ハンドピース状態 : CSelf13[一時変数Y] : CSelf12[一時変数X] ] (31 : - : -)
| | |■条件分岐(変数): 【1】 CSelf20[DBチェック] が 0 以上
| | |-◇分岐: 【1】 [ CSelf20[DBチェック] が 0 以上 ]の場合↓
| | | |■変数操作: CSelf25[DBボックス座標] = CSelf32[一時XX] + 1
| | | |■変数操作: CSelf25[DBボックス座標] += CSelf0[X座標] + 0
| | | |■変数操作: CSelf25[DBボックス座標] *= 10 + 0
| | | |■変数操作: CSelf25[DBボックス座標] += CSelf13[一時変数Y] + 1
| | | |■変数操作: CSelf25[DBボックス座標] += CSelf1[Y座標] + 0
| | | |■条件分岐(変数): 【1】 CSelf25[Dマップ座標] が 100 以上 【2】 CSelf25[Dマップ座標] が 10 以下
| | | |-◇分岐: 【1】 [ CSelf25[Dマップ座標] が 100 以上 ]の場合↓
| | | | |■変数操作: CSelf99[結果] = 1 + 0
| | | | |■イベント処理中断
| | | | |■
| | | |-◇分岐: 【2】 [ CSelf25[Dマップ座標] が 10 以下 ]の場合↓
| | | | |■変数操作: CSelf99[結果] = 1 + 0
| | | | |■イベント処理中断
| | | | |■
| | | |◇分岐終了◇
| | | |■DB読込(可変): CSelf21[接触チェック] = 可変DB[ ボックス : 現在編集中 : CSelf25[DBボックス座標] ] (29 : 0 : -)
| | | |■条件分岐(変数): 【1】 CSelf21[接触チェック] が 0 以上
| | | |-◇分岐: 【1】 [ CSelf21[接触チェック] が 0 以上 ]の場合↓
| | | | |■変数操作: CSelf99[結果] = 1 + 0
| | | | |■イベント処理中断
| | | | |■
| | | |◇分岐終了◇
| | | |■
| | |◇分岐終了◇
| | |■変数操作: CSelf13[一時変数Y] += 1 + 0
| | |■
| |◇ループここまで◇◇
| |■変数操作: CSelf12[一時変数X] += 1 + 0
| |■変数操作: CSelf32[一時XX] += CSelf2[逆表示?] + 0
| |■
|◇ループここまで◇◇
※接触時:-1 / 未接触:0をそれぞれ返します
まず CSelf32[一時XX] について
ハンドの表示は反転しているものの
ハンドの可変DBは無反転なので
ボックスを反転参照させるためのものです。
ここは少しややこしいですが
ハンドピースを参照するXYと別々に使っています。
DBボックス座標は
可変DBの1つのデータに0~99の項番で用意。
実際には項番11~88で、XY座標分を使用。
※条件分岐でイベント処理中断を仕込んでますが
10以下は特殊な値で使用、100以上はエラー参照の防止弁
なのであまり気にしないでください。
チェックさえ通れば、同じ処理で
ボックスに1以上のIDを入れるだけなので
登録処理も同じコモンで済ますことができます。
<今回内容のサンプルコモン>
マウスとキーボード操作が必要になる代物で
操作統一性を得るには
自力その部分のコモンは作る必要があります。
※公序良俗に反しない限り自由にご使用可能です
この記事が気に入ったらサポートをしてみませんか?