Unity ゲーム制作: 2D ピンボール ゲーム Pong (完成したプロジェクト付き)

導入

さあ、またピンボールをしましょう…(^_^)

しばらく独学で Unity を勉強しました。まずは 2D ゲームを作りましょう。実行時のエフェクトは次のとおりです。

目次

ダウンロード

プロジェクトの制作プロセス

1. インターフェース

2. メインプログラム Game.cs

1) 表示の初期化

2) ボールの動きを実感する

3) ベゼルの動き

4) ボールが壁に当たる

5) バッフルとボールの衝突

6) スコアを更新する

7) ボールの追跡

完全なコード


ダウンロード

ダウンロードリンク:

Unity2D ピンボール ゲームの実行可能完全なプロジェクト  0 クレジット

その他のダウンロード:

http://101.201.112.95/2021/Unity_Pong.zip

 

プロジェクトの構造、シーン Pong ファイルを開いて実行します (2017.3 で開発されました。それ以降のバージョンには互換性があるはずです。まだ試していません)。

 

以前に H5 および Python バージョンを作成しました。[ポータル]:

PyGame ゲーム制作:ピンボールゲーム Pong (完全な Python コードが添付されています)

HTML5ゲーム制作:ピンボールゲームPONG(完全コード添付)

 

 

プロジェクトの制作プロセス

制作過程を簡単にお話しますと、2Dゲームの開発も初めての試みです。

1. インターフェース

インターフェイスには 6 つの表示要素が含まれており、対応する位置にドラッグされます。彼らです:

背景画像:bg

ベゼル画像: 左ブロック、右ブロック

ボールの写真: ボール

スコア表示:leftScore、rightScore(使用するuguiのテキストコンポーネント)

 

注 1: 2D における画像単位とピクセル座標の比率は 1:100 (ピクセルと単位) です。

上の図では、3.7 のピクセル概念は 370 です。

 

注2: 絵の前後のオクルージョン関係のレイヤー内での順序を設定する必要があり、値が大きい方が上のレイヤーに表示されます

以下では、これらの値を使用してボールの動きと衝突を計算します (物理エンジンはありません...)

 

 

2. メインプログラム Game.cs

番組の制作アイデアを整理します。

1) 表示の初期化

まず、同じ GameObject オブジェクトをインターフェイスとして定義し、Start 関数で初期化します (インターフェイス内のオブジェクトをバインドします)。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Game : MonoBehaviour {

  //挡板
    private GameObject leftBlock;
    private GameObject rightBlock;

    //小球
    private GameObject ball;

    //左右得分 ugui text
    private Text leftScore;
    private Text rightScore;

    void Start () {
        Application.targetFrameRate = 60; //关掉垂直同步后,设置帧频

        leftBlock = GameObject.Find ("leftBlock");
        rightBlock = GameObject.Find ("rightBlock");

        ball = GameObject.Find ("ball");

        leftScore = GameObject.Find ("leftScore").GetComponent<Text> ();
        rightScore = GameObject.Find ("rightScore").GetComponent<Text> ();

    }

 

2) ボールの動きを実感する

移動速度変数と単位ピクセル比変数を定義します(後で何度も使用します)

    //单位与像素坐标比例为 1: 100 (Pixels To Units)
    private float pixelScale = 100.0f;

    //小球移动速度和方向
    private float ballSpeed = 10.0f;
    private float ballSpeedAngle = 0.25f * Mathf.PI;

アップデート機能でボールの動きを実現

void Update() {

	//计算小球移动速度(极坐标计算)
	float speedY = Mathf.Cos(ballSpeedAngle) * ballSpeed / pixelScale;
	float speedX = Mathf.Sin (ballSpeedAngle) * ballSpeed / pixelScale;

	//小球移动
	Vector2 ballPosition = ball.transform.position;
	ballPosition.x += speedX;
	ballPosition.y += speedY;
	ball.transform.position = ballPosition;

}

 

3) ベゼルの動き

ここでは左側のベゼルの移動を例に挙げ、Update 機能でキーボード制御イベントを追加し、ベゼルの移動速度を制御して効果を実現します。

void Update() {

	//按下按键
	if (Input.GetKeyDown (KeyCode.W)) {  
		Debug.Log("您按下了W键");  
		leftMoveSpeed = 0.08f;
	}  

	if (Input.GetKeyDown (KeyCode.S)) {  
		Debug.Log("您按下了S键");  
		leftMoveSpeed = -0.08f;
	}  

	//抬起按键  
	if (Input.GetKeyUp (KeyCode.W))  
	{  
		Debug.Log("您抬起了W键");  
		leftMoveSpeed = 0.0f;
	}  

	if (Input.GetKeyUp (KeyCode.S))  
	{  
		Debug.Log("您抬起了S键");  
		leftMoveSpeed = 0.0f;
	} 

	//左右挡板移动
	Vector2 leftBlockPosition = leftBlock.transform.position;
	leftBlockPosition.y += leftMoveSpeed;
	//碰到边缘处理
	if (leftBlockPosition.y > 2.5f) {
		leftBlockPosition.y = 2.5f;
	}
	//碰到边缘处理
	if (leftBlockPosition.y < -2.5f) {
		leftBlockPosition.y = -2.5f;
	}
	leftBlock.transform.position = leftBlockPosition;

}

 

4) ボールが壁に当たる

実際のアイデアは、ボールの位置を計算し、ボールの移動角度を変更することです。

    //小球碰撞到边缘后反弹
    if (ballPosition.x > 400 / pixelScale) { //右侧
        ballSpeedAngle = -ballSpeedAngle;
    }
    if (ballPosition.x < -400 / pixelScale) { //左侧
        ballSpeedAngle = -ballSpeedAngle;
    }
    if (ballPosition.y > 300 / pixelScale) { //上侧
        ballSpeedAngle = -(ballSpeedAngle - Mathf.PI);
    }
    if (ballPosition.y < -300 / pixelScale) { //下侧
        ballSpeedAngle = -(ballSpeedAngle - Mathf.PI);
    }

 

5) バッフルとボールの衝突

	//左边挡板碰撞
	//挡板的宽高分别是 20、100像素,所以计算碰撞区域时,按照宽高一半进行计算
	if (ballPosition.x < leftBlockPosition.x + 10 / pixelScale && ballPosition.x > leftBlockPosition.x - 10 / pixelScale
		&& ballPosition.y < leftBlockPosition.y + 50 / pixelScale && ballPosition.y > leftBlockPosition.y - 50 / pixelScale) {

		//碰撞上了
                   
	}

 

6) スコアを更新する

ボールが画面の左右端に当たるとスコア表示を更新します

    //左边得分
 	leftScoreNum ++;
	leftScore.text = leftScoreNum.ToString ();

 

7) ボールの追跡

以下の図に示すように、ボール オブジェクト上で右クリックして軌跡を追加します。

 

完全なコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Game : MonoBehaviour {

	//挡板
	private GameObject leftBlock;
	private GameObject rightBlock;

	//小球
	private GameObject ball;

	//左右得分 ugui text
	private Text leftScore;
	private Text rightScore;

	//单位与像素坐标比例为 1: 100 (Pixels To Units)
	private float pixelScale = 100.0f;

	//小球移动速度和方向
	private float ballSpeed = 10.0f;
	private float ballSpeedAngle = 0.25f * Mathf.PI;

	//左右挡板的移动速度
	private float leftMoveSpeed = 0.0f;
	private float rightMoveSpeed = 0.0f;

	private int leftScoreNum = 0;
	private int rightScoreNum = 0;

	// Use this for initialization
	void Start () {

		Application.targetFrameRate = 60; //关掉垂直同步后,设置帧频

		leftBlock = GameObject.Find ("leftBlock");
		rightBlock = GameObject.Find ("rightBlock");

		ball = GameObject.Find ("ball");

		leftScore = GameObject.Find ("leftScore").GetComponent<Text> ();
		rightScore = GameObject.Find ("rightScore").GetComponent<Text> ();

	}
	
	// Update is called once per frame
	void Update () {

		//## 小球移动
		//计算小球移动速度(极坐标计算)
		float speedY = Mathf.Cos(ballSpeedAngle) * ballSpeed / pixelScale;
		float speedX = Mathf.Sin (ballSpeedAngle) * ballSpeed / pixelScale;

		//小球移动
		Vector2 ballPosition = ball.transform.position;
		ballPosition.x += speedX;
		ballPosition.y += speedY;
		ball.transform.position = ballPosition;

		//小球碰撞到边缘后反弹
		if (ballPosition.x > 400 / pixelScale) {
			ballSpeedAngle = -ballSpeedAngle;
			//左边得分
			leftScoreNum ++;
			leftScore.text = leftScoreNum.ToString ();
		}
		if (ballPosition.x < -400 / pixelScale) {
			ballSpeedAngle = -ballSpeedAngle;
			//右边得分
			rightScoreNum ++;
			rightScore.text = rightScoreNum.ToString ();
		}
		if (ballPosition.y > 300 / pixelScale) {
			ballSpeedAngle = -(ballSpeedAngle - Mathf.PI);
		}
		if (ballPosition.y < -300 / pixelScale) {
			ballSpeedAngle = -(ballSpeedAngle - Mathf.PI);
		}


		//左右挡板移动
		Vector2 leftBlockPosition = leftBlock.transform.position;
		leftBlockPosition.y += leftMoveSpeed;
		//碰到边缘处理
		if (leftBlockPosition.y > 2.5f) {
			leftBlockPosition.y = 2.5f;
		}
		//碰到边缘处理
		if (leftBlockPosition.y < -2.5f) {
			leftBlockPosition.y = -2.5f;
		}
		leftBlock.transform.position = leftBlockPosition;


		Vector2 rightBlockPosition = rightBlock.transform.position;
		rightBlockPosition.y += rightMoveSpeed;
		//碰到边缘处理
		if (rightBlockPosition.y > 2.5f) {
			rightBlockPosition.y = 2.5f;
		}
		if (rightBlockPosition.y < -2.5f) {
			rightBlockPosition.y = -2.5f;
		}
		rightBlock.transform.position = rightBlockPosition;


		//### 左挡板控制 ###
		//按下按键
		if (Input.GetKeyDown (KeyCode.W)) {  
			Debug.Log("您按下了W键");  
			leftMoveSpeed = 0.08f;
		}  

		if (Input.GetKeyDown (KeyCode.S)) {  
			Debug.Log("您按下了S键");  
			leftMoveSpeed = -0.08f;
		}  

		//抬起按键  
		if (Input.GetKeyUp (KeyCode.W))  
		{  
			Debug.Log("您抬起了W键");  
			leftMoveSpeed = 0.0f;
		}  

		if (Input.GetKeyUp (KeyCode.S))  
		{  
			Debug.Log("您抬起了S键");  
			leftMoveSpeed = 0.0f;
		} 


		//### 右挡板控制 ###
		//按下按键
		if (Input.GetKeyDown (KeyCode.UpArrow)) {  
			rightMoveSpeed = 0.08f;
		}  

		if (Input.GetKeyDown (KeyCode.DownArrow)) {   
			rightMoveSpeed = -0.08f;
		}  

		//抬起按键  
		if (Input.GetKeyUp (KeyCode.UpArrow)) {  
			rightMoveSpeed = 0.0f;
		}  

		if (Input.GetKeyUp (KeyCode.DownArrow)) {  
			rightMoveSpeed = 0.0f;
		} 

		//### 计算小球与挡板的碰撞 ###
		//左边挡板碰撞
		bool isLeftBlockCrash = false;
		//挡板的宽高分别是 20、100像素,所以计算碰撞区域时,按照宽高一半进行计算
		if (ballPosition.x < leftBlockPosition.x + 10 / pixelScale && ballPosition.x > leftBlockPosition.x - 10 / pixelScale
		    && ballPosition.y < leftBlockPosition.y + 50 / pixelScale && ballPosition.y > leftBlockPosition.y - 50 / pixelScale) {

			Debug.Log ("crash");
			if (isLeftBlockCrash == false) {
				if (speedX < 0) {
					ballSpeedAngle = (leftBlockPosition.y - ballPosition.y) / 50.0f * pixelScale + Mathf.PI / 2.0f;

				}
				isLeftBlockCrash = true;
			}
		
		} else {
			isLeftBlockCrash = false;
		}

		//右边挡板碰撞
		bool isRightBlockCrash = false;
		//挡板的宽高分别是 20、100像素,所以计算碰撞区域时,按照宽高一半进行计算
		if (ballPosition.x < rightBlockPosition.x + 10 / pixelScale && ballPosition.x > rightBlockPosition.x - 10 / pixelScale
			&& ballPosition.y < rightBlockPosition.y + 50 / pixelScale && ballPosition.y > rightBlockPosition.y - 50 / pixelScale) {

			Debug.Log ("crash");
			if (isRightBlockCrash == false) {
				if (speedX > 0) {
					ballSpeedAngle =  Mathf.PI * 3 / 2 - (rightBlockPosition.y - ballPosition.y) / 50.0f * pixelScale;

				}
				isRightBlockCrash = true;
			}

		} else {
			isRightBlockCrash = false;
		}



	}
}

 

おすすめ

転載: blog.csdn.net/fujian87232/article/details/115321853
おすすめ