Unity game production: 2D pinball game Pong (with complete project)

introduce

Here, let's play pinball again... (^_^)

I have taught myself Unity for a while, let’s make a 2D game first, the running effect is as follows:

Table of contents

download

Project production process

1. Interface

2. The main program Game.cs

1) Display initialization

2) Realize the movement of the ball

3) Bezel movement

4) The ball hits the wall

5) Collision between the baffle and the ball

6) Update score

7) Ball trailing

full code


download

download link:

Unity2D pinball game runnable complete project   0 credits

Other downloads:

http://101.201.112.95/2021/Unity_Pong.zip

 

The structure of the project, open the scene Pong file, and run it (developed in 2017.3, higher versions should be compatible, I haven't tried it yet)

 

I made H5 and Python versions before, [Portal]:

PyGame game production: pinball game Pong (complete Python code is attached)

HTML5 game production: pinball game PONG (complete code attached)

 

 

Project production process

Let’s briefly talk about the production process. Developing a 2D game is also my first attempt.

1. Interface

The interface includes 6 display elements, which are dragged to the corresponding positions. They are:

Background image: bg

Bezel image: leftBlock, rightBlock

Ball picture: ball

Score display: leftScore, rightScore (text component of ugui used)

 

Note 1: The ratio of image units to pixel coordinates in 2D is 1: 100 (Pixels To Units)

In the picture above, the pixel concept of 3.7 is 370

 

Note 2: It is necessary to set the order in layer of the front and rear occlusion relationship of the picture, and the larger value is displayed on the top layer

The following will use these values ​​​​to calculate the movement and collision of the ball (no physics engine...)

 

 

2. The main program Game.cs

Organize the production ideas of the program.

1) Display initialization

First, define the same GameObject object as the interface, and initialize it in the Start function (bind the objects in the interface)

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) Realize the movement of the ball

Define the moving speed variable, and the unit pixel ratio variable (will be used many times later)

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

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

Realize the movement of the ball in the Update function

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) Bezel movement

Here we take the movement of the left bezel as an example. In the Update function, add keyboard control events and control the moving speed of the bezel to achieve the effect.

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) The ball hits the wall

The idea is actually to calculate the position of the ball and change the movement angle of the ball.

    //小球碰撞到边缘后反弹
    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) Collision between the baffle and the ball

	//左边挡板碰撞
	//挡板的宽高分别是 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) Update score

When the ball hits the left and right edges of the screen, update the score display

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

 

7) Ball trailing

On the ball object, right-click to add Trail, as shown in the figure below:

 

full code

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;
		}



	}
}

 

Guess you like

Origin blog.csdn.net/fujian87232/article/details/115321853