こちらはITRC Advent Calendar 2019 12日目の記事です。
経緯
よ〜し!Rustのプログラムかくぞ〜!
ん?ここなんでエラー出てるんだろ?
ん?なおらんぞ?
ここを直せば!
直った?いや、エラーが増えた!?
やばい日付かわった。。
締め切りが...
おわらーーーーーーーーーん!!!!!!!
ということでこんにちは!@saba383810です。元々書こうと思っていたrustの記事が間に合いませんでした。ゴメンナチャイ(;ω;)
埋め合わせで何か書くことあるかな〜と探していた時に家のメインPCから高校の課題研究(完成前のデータ)を発掘!そこで、サークルのメンバーに私が高校時代どんなプログラムを書いていたかということも踏まえて限定公開で記事を書けばいいんじゃね?と思いこの記事を書き始めたとさ。
環境
- unity 2017.3.17f
- UnityC#
- monodevelop
- win 10
3Dテトリス
どんなゲームか完結に説明すると
「3D世界」と「ポリゴン世界」を移動できる主人公が
二つのフィールドを行き来しながらフィールドにいる女の子(NPC)とテトリスバトルをする
というゲームです。
え?つまんなそうだって??
うん。おもしろいゲームだって信じてる...
今回全て紹介すると記述量がやばくなるので2Dテトリスの一部のソースコードを紹介します。
デバック時の動画
タイトル〜フィールド
こんな感じでフィールドを移動できます。ジャンプ機能もあります。
フィールドにいる「F」(ウネウネしたやつ)は友達のオリジナルキャラを入れて欲しい言われてしょうがなく配置したキャラなのであまり気にせずに。。
2Dテトリス画面
ミノもちゃんときえます。
Tスピンならできる。Lスピンは実装できなかった。
##ソースコード
2Dテトリスに関するプログラムです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tetrimino : MonoBehaviour
{
private float t = 0;
private float t2 = 0;
private float fallSpeed = 0.5f;
float fall = 0;
public bool allowRotation = true;
public bool limitRotation = false;
void Update ()
{
CheckUserInput ();
}
void CheckUserInput ()
{
t += Time.deltaTime;
t2 += Time.deltaTime;
///right
if (t > 0.1f) {
if (Input.GetAxis ("DDF2") > 0) {
transform.position += new Vector3 (1, 0, 0);
t = 0;
if (CheckIsValidPosition ()) {
FindObjectOfType<Game> ().UpdateGrid (this);
} else {
transform.position += new Vector3 (-1, 0, 0);
}
}
///Left
else if (Input.GetAxis ("DDF2") < 0) {
transform.position += new Vector3 (-1, 0, 0);
t = 0;
if (CheckIsValidPosition ()) {
FindObjectOfType<Game> ().UpdateGrid (this);
} else {
transform.position += new Vector3 (1, 0, 0);
}
}
///Down
else if (Input.GetAxis ("DDF1") < 0 || Time.time - fall >= fallSpeed) {
transform.position += new Vector3 (0, -1, 0);
fall = Time.time;
t = 0;
if (CheckIsValidPosition ()) {
FindObjectOfType<Game> ().UpdateGrid (this);
} else {
//object生成
transform.position += new Vector3 (0, 1, 0);
FindObjectOfType<Game> ().DeleateRow ();
if (FindObjectOfType<Game> ().CheckIsAboveGrid (this)) {
FindObjectOfType<Game> ().GameOver();
}
enabled = false;
FindObjectOfType<Game> ().SpownNextTetrimino ();
}
} else if (t2 > 0.2f) {
//回転
if (Input.GetKey (KeyCode.JoystickButton0)) {
if (allowRotation) {
if (limitRotation) {
if (transform.rotation.eulerAngles.z >= 90) {
transform.Rotate (0, 0, -90);
t2 = 0;
} else {
transform.Rotate (0, 0, 90);
t2 = 0;
}
} else {
transform.Rotate (0, 0, 90);
t2 = 0;
}
if (CheckIsValidPosition ()) {
FindObjectOfType<Game> ().UpdateGrid (this);
} else {
if (limitRotation) {
if (transform.rotation.eulerAngles.z >= 90) {
transform.Rotate (0, 0, -90);
t2 = 0;
} else {
transform.Rotate (0, 0, 90);
t2 = 0;
}
} else {
transform.Rotate (0, 0, -90);
t2 = 0;
}
}
}
}
//回転
else if (Input.GetKey (KeyCode.JoystickButton1)) {
if (allowRotation) {
if (limitRotation) {
if (transform.rotation.eulerAngles.z >= 90) {
transform.Rotate (0, 0, -90);
t2 = 0;
} else {
transform.Rotate (0, 0, 90);
t2 = 0;
}
} else {
transform.Rotate (0, 0, -90);
t2 = 0;
}
if (CheckIsValidPosition ()) {
FindObjectOfType<Game> ().UpdateGrid (this);
} else {
if (limitRotation) {
if (transform.rotation.eulerAngles.z >= 90) {
transform.Rotate (0, 0, -90);
t2 = 0;
} else {
transform.Rotate (0, 0, 90);
t2 = 0;
}
} else {
transform.Rotate (0, 0, 90);
t2 = 0;
}
}
}
}
}
}
}
bool CheckIsValidPosition ()
{
foreach (Transform mino in transform) {
Vector2 pos = FindObjectOfType<Game> ().Round (mino.position);
if (FindObjectOfType<Game> ().CheckIsInsideGrid (pos) == false) {
return false;
}
if (FindObjectOfType<Game> ().GetTransformAtGridPosition (pos) != null && FindObjectOfType<Game> ().GetTransformAtGridPosition (pos).parent != transform) {
return false;
}
}
return true;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Game : MonoBehaviour {
public static int gridWidth = 10;
public static int gridHeight = 20;
public static bool [] Judege = new bool[7]{true,true,true,true,true,true,true};
int CountA,count;
public static Transform[,] grid = new Transform[gridWidth,gridHeight];
void Start () {
SpownNextTetrimino ();
}
public bool CheckIsAboveGrid (Tetrimino tetrimino){
for (int x = 0; x < gridWidth; ++x) {
foreach (Transform mino in tetrimino.transform) {
Vector2 pos = Round (mino.position);
if (pos.y > gridHeight - 1) {
return true;
}
}
}
return false;
}
public bool IsFullRowAt (int y){
for (int x = 0; x < gridWidth; ++x) {
if (grid [x, y] == null) {
return false;
}
}
return true;
}
public void DeleateMinoAt (int y){
for (int x = 0; x < gridWidth; ++x) {
Destroy (grid [x, y].gameObject);
grid [x, y] = null;
}
}
public void MoveRowDown (int y){
for (int x = 0; x < gridWidth; ++x) {
if (grid [x, y] != null) {
grid [x, y - 1] = grid [x, y];
grid [x, y] = null;
grid [x, y - 1].position += new Vector3 (0, -1, 0);
}
}
}
public void MoveAllRowsDown (int y){
for (int i = y; i < gridHeight; ++i) {
MoveRowDown (i);
}
}
public void DeleateRow () {
for (int y = 0; y < gridHeight; ++y) {
if (IsFullRowAt (y)) {
DeleateMinoAt (y);
MoveAllRowsDown (y + 1);
--y;
}
}
}
public void UpdateGrid (Tetrimino tetrimino){
for (int y = 0; y < gridHeight; ++y) {
for (int x = 0; x < gridWidth; ++x) {
if(grid[x,y] != null){
if (grid [x, y].parent == tetrimino.transform) {
grid [x, y] = null;
}
}
}
}
foreach (Transform mino in tetrimino.transform) {
Vector2 pos = Round (mino.position);
if (pos.y < gridHeight) {
grid [(int)pos.x, (int)pos.y] = mino;
}
}
}
public Transform GetTransformAtGridPosition(Vector2 pos){
if (pos.y > gridHeight - 1) {
return null;
} else {
return grid [(int)pos.x, (int)pos.y];
}
}
public void SpownNextTetrimino () {
GameObject nextTetrimino = (GameObject)Instantiate(Resources.Load (GetRandomTetrimino (), typeof(GameObject)), new Vector2 (5.0f, 19.0f), Quaternion.identity);
}
public bool CheckIsInsideGrid (Vector2 pos){
return ((int)pos.x >= 0 && (int)pos.x < gridWidth && (int)pos.y >= 0);
}
public Vector2 Round (Vector2 pos){
return new Vector2 (Mathf.Round (pos.x), Mathf.Round (pos.y));
}
//次に出てくるミノを計算する。
string GetRandomTetrimino(){
string randomTetriminoName = "Prefabs/Tetrimino_T";
while (true) {
int randomTetrimino = Random.Range (1, 8);
if (Judege [randomTetrimino - 1] == true) {
switch (randomTetrimino) {
case 1:
randomTetriminoName = "Prefabs/Tetrimino_T";
break;
case 2:
randomTetriminoName = "Prefabs/Tetrimino_I";
break;
case 3:
randomTetriminoName = "Prefabs/Tetrimino_O";
break;
case 4:
randomTetriminoName = "Prefabs/Tetrimino_J";
break;
case 5:
randomTetriminoName = "Prefabs/Tetrimino_L";
break;
case 6:
randomTetriminoName = "Prefabs/Tetrimino_S";
break;
case 7:
randomTetriminoName = "Prefabs/Tetrimino_Z";
break;
}
Judege [randomTetrimino - 1] = false;
return randomTetriminoName;
} else {
for (count = 0; count < 7; count++) {
if (Judege [count] == false) {
CountA = CountA + 1;
}
}
if (CountA == 7) {
for (int i = 0; i < 7; i++) {
Judege [i] = true;
}
} else {
CountA = 0;
}
}
}
}
public void GameOver(){
SceneManager.LoadScene ("GameOver");
}
}
tetrimino.cs
は主にテトリスのミノを回したり表示させたり動かしたりするプログラムです。
game.cs
はミノが揃った時に消える判定です。このコードには書いてないのですがスコア判定もここで行いました。
こんな感じで高校時代にunityでゲームをつくっていました。当時は楽しいと思う反面イライラしながら作っていました。なつかしいですね〜〜。
まとめ
どうでしたか?
高校時代に書いたソースなので綺麗なコードではないですが動いていたので多めに見いていただけると嬉しいです。
今回書く予定だった「Rustでwhitespace変換器作ってみた」は次回書きますのでおたのしみに。
ではでは。。