解析不能!30年以上前のレトロゲームから謎の「自動生成アルゴリズム」が見つかる
という記事が気になったので試してみました。
アルゴリズムはWikiにある情報をもとにしています。
以下のスクリプトを空のオブジェクトに取り付けるとマップを生成します。
追記:ブロックを書き戻す場所が左に2コマずれていたのを修正しました
EntombedMazeAlgorithm.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// https://en.wikipedia.org/wiki/Entombed_(Atari_2600)
public class EntombedMazeAlgorithm : MonoBehaviour
{
[SerializeField, Range(5, 20)] int m_lengthH = 11;
[SerializeField, Range(1f, 10f)] float m_mapSpd = 2f;
int[,] m_mapSeed;
Vector3 m_basePos;
// |c|d|e|
// |a|b|X|
int[] mysteryTable = { // X
1,1,1,2, 0,0,2,2, 1,1,1,1, 2,0,0,0,
1,1,1,2, 0,0,0,0, 2,0,1,2, 2,0,0,0
};
Vector2Int[] posTbl = {
new Vector2Int(0,1), // a
new Vector2Int(1,1), // b
new Vector2Int(1,0), // c
new Vector2Int(2,0), // d
new Vector2Int(3,0), // e
};
// Start is called before the first frame update
void Start()
{
m_mapSeed = new int[m_lengthH+3, 2];
for (int i = 0; i < m_lengthH+3; ++i)
{
m_mapSeed[i, 0] = m_mapSeed[i, 1] = ( (i==0) || (i==m_lengthH+2)) ? 1:0;
}
m_basePos = transform.position;
}
// Update is called once per frame
void Update()
{
transform.position += Vector3.up * Time.deltaTime * m_mapSpd;
if(transform.position.y - m_basePos.y >= 1f)
{
m_basePos.y += 1f;
transform.position = m_basePos;
//string dbgStr = "";
for (int posX = 0; posX < m_lengthH; ++posX)
{
int posType = mysteryTable[gettableIdx(posX)];
posType = (posType > 1) ? ((Random.value > 0.5f) ? 0 : 1) : posType;
m_mapSeed[posX+2, 1] = posType;
//dbgStr += posType.ToString();
}
//Debug.Log(dbgStr);
for (int i = 0; i < m_lengthH + 3; ++i)
{
m_mapSeed[i, 0] = m_mapSeed[i, 1];
setBlock(i);
}
}
}
int gettableIdx(int _poxX0)
{
int ret = 0;
for (int i = 0; i < 5; ++i)
ret |= (m_mapSeed[_poxX0 + posTbl[i].x, posTbl[i].y] << (4 - i));
return ret;
}
void setBlock(int _posX)
{
if ((_posX>1)&&(m_mapSeed[_posX, 0] != 0))
{
for(int i = 0; i < 2; ++i)
{
GameObject go0 = GameObject.CreatePrimitive(PrimitiveType.Cube);
go0.transform.position = new Vector3((0.5f+_posX-2)*(i==0?-1f:1f), -15f);
go0.transform.SetParent(transform);
Destroy(go0, 45f/m_mapSpd);
}
}
}
}
やってみたのですが、、似たようなマップにはなるけど同じにはならない。。。
端(マップで言うと真ん中)の処理がなにか必要なのかな?
おまけ
sphereに以下のスクリプトを張り付けてマップの上から落とすと操作(カーソル左右+スペース)できます
PlCtrl.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlCtrl : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
gameObject.layer = LayerMask.NameToLayer("Water");
}
// Update is called once per frame
void Update()
{
GetComponent<Rigidbody>().AddForce(Vector3.right*Input.GetAxis("Horizontal")*10f,ForceMode.Force);
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("BTN");
RaycastHit[] hits = Physics.RaycastAll(transform.position, Vector3.down * 0.6f, (1 << LayerMask.NameToLayer("Default")));
if (hits.Length>0)
{
Destroy(hits[0].collider.gameObject);
}
}
}
}