introduzir
Aqui, vamos jogar pinball de novo...(^_^)
Eu aprendi Unity sozinho por um tempo, vamos fazer um jogo 2D primeiro, o efeito de execução é o seguinte:
Índice
Processo de produção do projeto
2. O programa principal Game.cs
2) Perceba o movimento da bola
5) Colisão entre o defletor e a bola
download
Link para Download:
Projeto completo executável do jogo de pinball Unity2D 0 créditos
Outros downloads:
http://101.201.112.95/2021/Unity_Pong.zip
A estrutura do projeto, abra o arquivo Pong da cena e execute-o (desenvolvido em 2017.3, versões superiores devem ser compatíveis, ainda não testei)
Eu fiz versões H5 e Python antes, [Portal]:
Produção do jogo PyGame: jogo de pinball Pong (o código Python completo está anexado)
Produção de jogos HTML5: jogo de pinball PONG (código completo anexado)
Processo de produção do projeto
Vamos falar brevemente sobre o processo de produção. Desenvolver um jogo 2D também é minha primeira tentativa.
1. Interface
A interface inclui 6 elementos de exibição, que são arrastados para as posições correspondentes. Eles são:
Imagem de fundo: bg
Imagem da moldura: leftBlock, rightBlock
imagem da bola: bola
Exibição de pontuação: leftScore, rightScore (componente de texto do ugui usado)
Observação 1: A proporção de unidades de imagem para coordenadas de pixel em 2D é 1: 100 (Pixels para unidades)
Na foto acima, o conceito de pixel de 3,7 é 370
Nota 2: É necessário definir a ordem na camada da relação de oclusão frontal e traseira da imagem, e o valor maior é exibido na camada superior
O seguinte usará esses valores para calcular o movimento e a colisão da bola (sem motor de física...)
2. O programa principal Game.cs
Organizar as ideias de produção do programa.
1) Inicialização da tela
Primeiro, defina o mesmo objeto GameObject da interface e inicialize-o na função Start (vincule os objetos na 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) Perceba o movimento da bola
Defina a variável de velocidade de movimento e a variável de proporção de unidade de pixel (será usada muitas vezes mais tarde)
//单位与像素坐标比例为 1: 100 (Pixels To Units)
private float pixelScale = 100.0f;
//小球移动速度和方向
private float ballSpeed = 10.0f;
private float ballSpeedAngle = 0.25f * Mathf.PI;
Perceba o movimento da bola na função Atualizar
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) Movimento do bisel
Aqui, tomamos como exemplo o movimento do painel esquerdo.Na função Atualizar, adicione eventos de controle do teclado e controle a velocidade de movimento do painel para obter o efeito.
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) A bola bate na parede
A ideia é realmente calcular a posição da bola e mudar o ângulo de movimento da bola.
//小球碰撞到边缘后反弹
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) Colisão entre o defletor e a bola
//左边挡板碰撞
//挡板的宽高分别是 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) Atualizar pontuação
Quando a bola atingir as bordas esquerda e direita da tela, atualize a exibição do placar
//左边得分
leftScoreNum ++;
leftScore.text = leftScoreNum.ToString ();
7) Bola para trás
No objeto bola, clique com o botão direito do mouse para adicionar Trilha, conforme a figura abaixo:
código completo
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;
}
}
}