アマゾンバナーリンク

ディスプレイ広告

スポンサーリンク

Unityで作る15パズル

こんにちは!ジェイです。只今TPSオンラインゲーム制作中ですが、たまにはサクッと短時間で作れるゲームを紹介したいと思って、今回は15パズルをUnityで作ります。

記事内広告

下準備

まずはSpriteの準備をします。Spriteでは以下の画像データを利用することができます。今回使う素材は、私の誕生日のお祝いの時にミーゼアちゃんが描いてくれた絵を使わせていただきます。

BMP・EXR・GIF・HDR・IFF・JPG・PICT・PNG・PSD・TGA・TIFF・GIF・JPG・PNGといった定番の形式から幅広く対応しています。

次にスプライトを分割して使うための設定をします。まずはResourcesをつくり素材となる画像を入れます。その後、画像を選択し、以下のようにMultipluを選びSprite Editorを選択します。

詳細設定はこちら

今回は4×4=16にパズルを配置したいので、TypeをGrid By Countにしました。他にもピクセルを指定したりする方法もあります。その後Resourcesフォルダを作成し中にいれておきましょう。(Resources.LoadAllで使うため)

カメラの設定

ソースコード

次に空のオブジェクトを作り以下のコードを張り付けましょう!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CPazuru : MonoBehaviour
{
public AudioClip audioClip1;
private AudioSource audioSource;
public Text NumberText;
const int PANEL_X_NUM = 4;
const int PANEL_Y_NUM = 4;
const int ALL_PANEL_NUM = PANEL_X_NUM * PANEL_Y_NUM;
int PanelXSize;
int PanelYSize;
int PicAll;
int[] Pics = new int[ALL_PANEL_NUM];
int[] Panel = new int[ALL_PANEL_NUM];
enum EState
{ 
TITLE, MAIN, CLEAR 
}
EState State = EState.TITLE;
// スプライト画像格納用の配列
Sprite[] sprites;
GameObject[] PanelObj;
Vector2[] BasePos;
// Start is called before the first frame update
void Start()
{
audioSource = gameObject.GetComponent<AudioSource>();
audioSource.clip = audioClip1;
// スプライトを配列にロードする
sprites = Resources.LoadAll<Sprite>("jay");
// 空のゲームオブジェクトを作成する
GameObject obj = new GameObject();
PanelObj = new GameObject[sprites.Length];
BasePos = new Vector2[sprites.Length];
// とりあえずスプライトの数だけループ
for (int i = 0; i < sprites.Length; i++)
{
// 空のゲームオブジェクトを生成する、横に並べてみた
PanelObj[i] = Instantiate(obj, new Vector3(2.6f*(i%4), -1.85f*(i/4), 0), Quaternion.identity) as GameObject;
// 生成したゲームオブジェクトはTransformのみなのでSpriteRendererをスクリプトから追加、スプライトに配列の画像を代入
SpriteRenderer sr = PanelObj[i].AddComponent<SpriteRenderer>();
sr.sprite = sprites[i];
PanelObj[i].AddComponent<BoxCollider2D>();
PanelObj[i].name = i.ToString();
PanelObj[i].tag = "Panle";
BasePos[i].x = PanelObj[i].transform.position.x;
BasePos[i].y = PanelObj[i].transform.position.y;
}
// 空のゲームオブジェクトが気に入らないのでとりあえず消しとく
Destroy(obj);
PanelXSize = Screen.width / PANEL_X_NUM;
PanelYSize = Screen.height / PANEL_Y_NUM;
}
void Change(int x, int y)
{
int p1 = y * PANEL_X_NUM + x; // クリックしたパネル番号
int p2 = -1; // 次に移動する予定のパネル番号
// 左端に空白がある場合は左へ移動
if (x > 0 && Panel[p1 - 1] == ALL_PANEL_NUM - 1)
{
p2 = p1 - 1;
}
// 右に空白がある場合は右へ移動
if (x < PANEL_X_NUM - 1 && Panel[p1 + 1] == ALL_PANEL_NUM - 1)
{
p2 = p1 + 1;
}
// 上に空白がある場合は上へ移動
if (y > 0 && Panel[p1 - PANEL_Y_NUM] == ALL_PANEL_NUM - 1)
{
p2 = p1 - PANEL_Y_NUM;
}
// 下に空白がある場合は下へ移動
if (y < PANEL_Y_NUM - 1 && Panel[p1 + PANEL_Y_NUM] == ALL_PANEL_NUM - 1)
{
p2 = p1 + PANEL_Y_NUM;
}
if (p2 != -1)
{
Panel[p2] = Panel[p1]; // クリックしたパネルを次の場所へ移動
Panel[p1] = ALL_PANEL_NUM - 1; // クリックしたパネルを空白にする
}
NumberText.text = string.Empty;
for (int i = 0; i < ALL_PANEL_NUM; i++)
{
if (Panel[i] < ALL_PANEL_NUM - 1)
{
PanelObj[Panel[i]].transform.position = BasePos[i];
PanelObj[Panel[i]].name = i.ToString();
}
else
{
Vector2 temp = PanelObj[Panel[i]].transform.position;
temp.y = 2.0f;
PanelObj[Panel[i]].transform.position = temp;
PanelObj[Panel[i]].name = i.ToString();
}
NumberText.text += (Panel[i]+1).ToString() + " ";
if(i%PANEL_X_NUM == PANEL_X_NUM-1)
{
NumberText.text += "\n";
}
}
}
void GameTitle()
{
if (Input.GetMouseButtonDown(0))
{
for (int i = 0; i < ALL_PANEL_NUM; i++)
{
Panel[i] = i;
}
for (int i = 0; i < ALL_PANEL_NUM * 1000; i++)
{
Change(Random.Range(0, PANEL_X_NUM), Random.Range(0, PANEL_Y_NUM));
}
State = EState.MAIN;
audioSource.Play();
}
}
GameObject clickedGameObject;
void GameMain()
{
PanelXSize = Screen.width / PANEL_X_NUM;
PanelYSize = Screen.height / PANEL_Y_NUM;
if (Input.GetMouseButtonDown(0))
{
clickedGameObject = null;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit2d = Physics2D.Raycast((Vector2)ray.origin, (Vector2)ray.direction);
int x = 0, y = 0;
if (hit2d)
{
clickedGameObject = hit2d.transform.gameObject;
x = int.Parse(clickedGameObject.name)% PANEL_X_NUM;
y = int.Parse(clickedGameObject.name)/ PANEL_Y_NUM;
}
Change(x , y);
bool clear = true;
for (int i = 0; i < ALL_PANEL_NUM; i++)
{
if (Panel[i] != i)
clear = false;
}
if (clear)
{
for (int i = 0; i < ALL_PANEL_NUM; i++)
{
PanelObj[i].transform.position = BasePos[i];
}
State = EState.CLEAR;
}
}
}
void GameClear()
{
NumberText.text = "Game Clear";
}
// Update is called once per frame
void Update()
{
switch (State)
{
case EState.TITLE: GameTitle(); break;
case EState.MAIN: GameMain(); break;
case EState.CLEAR: GameClear(); break;
}
}
}

テキストとサウンドをスクリプトにアタッチ

こんな感じで設定できれば完成です!

実行結果