Created
September 12, 2018 13:46
-
-
Save nabesi777/3cd4892823902df560917818a55e59da to your computer and use it in GitHub Desktop.
C# 倉庫番
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class Sokoban : MonoBehaviour | |
{ | |
private enum TileType | |
{ | |
NONE, | |
GROUND, | |
TARGET, | |
PLAYER, | |
BLOCK, | |
PLAYER_ON_TARGET, | |
BLOCK_ON_TARGET, | |
} | |
private enum DirectionType | |
{ | |
UP, | |
RIGHT, | |
DOWN, | |
LEFT, | |
} | |
public TextAsset stageFile; | |
private int rows; | |
private int columns; | |
private TileType[,] tileList; | |
public float tileSize; | |
public Sprite groundSprite; | |
public Sprite targetSprite; | |
public Sprite playerSprite; | |
public Sprite blockSprite; | |
private GameObject player; | |
private Vector2 middleOffset; | |
private int blockCount; | |
private bool isClear; | |
private Dictionary<GameObject, Vector2Int> gameObjectPosTable = new Dictionary<GameObject, Vector2Int>(); | |
private void Start() | |
{ | |
LoadTileData(); | |
CreateStage(); | |
} | |
private void LoadTileData() | |
{ | |
var lines = stageFile.text.Split | |
( | |
new[] { '\r', '\n' }, | |
StringSplitOptions.RemoveEmptyEntries | |
); | |
var nums = lines[0].Split(new[] { ',' }); | |
rows = lines.Length; | |
columns = nums.Length; | |
tileList = new TileType[columns, rows]; | |
for (int y = 0; y < rows; y++) | |
{ | |
var st = lines[y]; | |
nums = st.Split(new[] { ',' }); | |
for (int x = 0; x < columns; x++) | |
{ | |
tileList[x, y] = (TileType)int.Parse(nums[x]); | |
} | |
} | |
} | |
private void CreateStage() | |
{ | |
middleOffset.x = columns * tileSize * 0.5f - tileSize * 0.5f; | |
middleOffset.y = rows * tileSize * 0.5f - tileSize * 0.5f; | |
for (int y = 0; y < rows; y++) | |
{ | |
for (int x = 0; x < columns; x++) | |
{ | |
var val = tileList[x, y]; | |
if (val == TileType.NONE) continue; | |
var name = "tile" + y + "_" + x; | |
var tile = new GameObject(name); | |
var sr = tile.AddComponent<SpriteRenderer>(); | |
sr.sprite = groundSprite; | |
tile.transform.position = GetDisplayPosition(x, y); | |
if (val == TileType.TARGET) | |
{ | |
var destination = new GameObject("destination"); | |
sr = destination.AddComponent<SpriteRenderer>(); | |
sr.sprite = targetSprite; | |
sr.sortingOrder = 1; | |
destination.transform.position = GetDisplayPosition(x, y); | |
} | |
if (val == TileType.PLAYER) | |
{ | |
player = new GameObject("player"); | |
sr = player.AddComponent<SpriteRenderer>(); | |
sr.sprite = playerSprite; | |
sr.sortingOrder = 2; | |
player.transform.position = GetDisplayPosition(x, y); | |
gameObjectPosTable.Add(player, new Vector2Int(x, y)); | |
} | |
else if (val == TileType.BLOCK) | |
{ | |
blockCount++; | |
var block = new GameObject("block" + blockCount); | |
sr = block.AddComponent<SpriteRenderer>(); | |
sr.sprite = blockSprite; | |
sr.sortingOrder = 2; | |
block.transform.position = GetDisplayPosition(x, y); | |
gameObjectPosTable.Add(block, new Vector2Int(x, y)); | |
} | |
} | |
} | |
} | |
private Vector2 GetDisplayPosition(int x, int y) | |
{ | |
return new Vector2 | |
( | |
x * tileSize - middleOffset.x, | |
y * -tileSize + middleOffset.y | |
); | |
} | |
private GameObject GetGameObjectAtPosition(Vector2Int pos) | |
{ | |
foreach (var pair in gameObjectPosTable) | |
{ | |
if (pair.Value == pos) | |
{ | |
return pair.Key; | |
} | |
} | |
return null; | |
} | |
private bool IsBlock(Vector2Int pos) | |
{ | |
var cell = tileList[pos.x, pos.y]; | |
return cell == TileType.BLOCK || cell == TileType.BLOCK_ON_TARGET; | |
} | |
private bool IsValidPosition(Vector2Int pos) | |
{ | |
if (0 <= pos.x && pos.x < columns && 0 <= pos.y && pos.y < rows) | |
{ | |
return tileList[pos.x, pos.y] != TileType.NONE; | |
} | |
return false; | |
} | |
private void Update() | |
{ | |
if (isClear) return; | |
if (Input.GetKeyDown(KeyCode.UpArrow)) | |
{ | |
TryMovePlayer(DirectionType.UP); | |
} | |
if (Input.GetKeyDown(KeyCode.RightArrow)) | |
{ | |
TryMovePlayer(DirectionType.RIGHT); | |
} | |
if (Input.GetKeyDown(KeyCode.DownArrow)) | |
{ | |
TryMovePlayer(DirectionType.DOWN); | |
} | |
if (Input.GetKeyDown(KeyCode.LeftArrow)) | |
{ | |
TryMovePlayer(DirectionType.LEFT); | |
} | |
} | |
private void TryMovePlayer(DirectionType direction) | |
{ | |
var currentPlayerPos = gameObjectPosTable[player]; | |
var nextPlayerPos = GetNextPositionAlong(currentPlayerPos, direction); | |
if (!IsValidPosition(nextPlayerPos)) return; | |
if (IsBlock(nextPlayerPos)) | |
{ | |
var nextBlockPos = GetNextPositionAlong(nextPlayerPos, direction); | |
if (IsValidPosition(nextBlockPos) && !IsBlock(nextBlockPos)) | |
{ | |
var block = GetGameObjectAtPosition(nextPlayerPos); | |
UpdateGameObjectPosition(nextPlayerPos); | |
block.transform.position = GetDisplayPosition(nextBlockPos.x, nextBlockPos.y); | |
gameObjectPosTable[block] = nextBlockPos; | |
if (tileList[nextBlockPos.x, nextBlockPos.y] == TileType.GROUND) | |
{ | |
tileList[nextBlockPos.x, nextBlockPos.y] = TileType.BLOCK; | |
} | |
else if (tileList[nextBlockPos.x, nextBlockPos.y] == TileType.TARGET) | |
{ | |
tileList[nextBlockPos.x, nextBlockPos.y] = TileType.BLOCK_ON_TARGET; | |
} | |
UpdateGameObjectPosition(currentPlayerPos); | |
player.transform.position = GetDisplayPosition(nextPlayerPos.x, nextPlayerPos.y); | |
gameObjectPosTable[player] = nextPlayerPos; | |
if (tileList[nextPlayerPos.x, nextPlayerPos.y] == TileType.GROUND) | |
{ | |
tileList[nextPlayerPos.x, nextPlayerPos.y] = TileType.PLAYER; | |
} | |
else if (tileList[nextPlayerPos.x, nextPlayerPos.y] == TileType.TARGET) | |
{ | |
tileList[nextPlayerPos.x, nextPlayerPos.y] = TileType.PLAYER_ON_TARGET; | |
} | |
} | |
} | |
else | |
{ | |
UpdateGameObjectPosition(currentPlayerPos); | |
player.transform.position = GetDisplayPosition(nextPlayerPos.x, nextPlayerPos.y); | |
gameObjectPosTable[player] = nextPlayerPos; | |
if (tileList[nextPlayerPos.x, nextPlayerPos.y] == TileType.GROUND) | |
{ | |
tileList[nextPlayerPos.x, nextPlayerPos.y] = TileType.PLAYER; | |
} | |
else if (tileList[nextPlayerPos.x, nextPlayerPos.y] == TileType.TARGET) | |
{ | |
tileList[nextPlayerPos.x, nextPlayerPos.y] = TileType.PLAYER_ON_TARGET; | |
} | |
} | |
CheckCompletion(); | |
} | |
private Vector2Int GetNextPositionAlong(Vector2Int pos, DirectionType direction) | |
{ | |
switch (direction) | |
{ | |
case DirectionType.UP: | |
pos.y -= 1; | |
break; | |
case DirectionType.RIGHT: | |
pos.x += 1; | |
break; | |
case DirectionType.DOWN: | |
pos.y += 1; | |
break; | |
case DirectionType.LEFT: | |
pos.x -= 1; | |
break; | |
} | |
return pos; | |
} | |
private void UpdateGameObjectPosition(Vector2Int pos) | |
{ | |
var cell = tileList[pos.x, pos.y]; | |
if (cell == TileType.PLAYER || cell == TileType.BLOCK) | |
{ | |
tileList[pos.x, pos.y] = TileType.GROUND; | |
} | |
else if (cell == TileType.PLAYER_ON_TARGET || cell == TileType.BLOCK_ON_TARGET) | |
{ | |
tileList[pos.x, pos.y] = TileType.TARGET; | |
} | |
} | |
private void CheckCompletion() | |
{ | |
int blockOnTargetCount = 0; | |
for (int y = 0; y < rows; y++) | |
{ | |
for (int x = 0; x < columns; x++) | |
{ | |
if(tileList[x,y]==TileType.BLOCK_ON_TARGET) | |
{ | |
blockOnTargetCount++; | |
} | |
} | |
} | |
if(blockOnTargetCount==blockCount) | |
{ | |
isClear = true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment