Перед началом вы можете посмотреть игру на itch.io
Анализ Понг
Понг был одной из первых когда-либо созданных видеоигр и первой успешной коммерческой игрой. Когда Pong был впервые создан, разработчики, скорее всего, боролись с логикой кода, однако в настоящее время вы можете создать простой Pong для двух игроков с одним вызовом метода, коллайдерами и спрайтами. Понг становится сложнее создавать, когда принято решение сделать Понга для одного игрока. В этом уроке мы создадим базовый игровой процесс для понга и разберем очень простую альтернативу искусственного интеллекта, которая все еще увеличивает ценность игрового процесса.
Мы должны спросить, каковы основные элементы игрового процесса понг? Вот список с ответом на этот вопрос:
- Ввод игрока — мы хотим, чтобы игрок мог перемещать весло вверх и вниз, чтобы он мог ударить по мячу.
- Столкновение мяча — когда мяч попадает на весло или границы, нельзя терять скорость.
- Столкновение границ — мяч должен отскакивать от верхней и нижней части экрана, чтобы он не покинул игровую зону.
- Enemy AI — Значение игрового процесса в игре было бы близко к нулю, если бы противник сидел на противоположном конце экрана и не двигался.
- Spawning the Ball — когда мяч попадает на одну из границ позади весла, нам нужно его возродить, чтобы мы могли продолжить игру.
- Обнаружение зоны попадания мяча в лопатку — это позволяет мячу отскочить от лопатки под уникальными углами, чтобы мы могли лучше целиться в мяч, когда он ударен лопаткой.
С помощью этого списка мы можем начать программирование игры.
Обратите внимание, что любые числа, относящиеся к расположению, повороту, масштабу и т. Д. Игрового объекта, являются относительными, и их может потребоваться изменить для вашей конкретной настройки.
Настройка игры
Теперь, когда мы проанализировали основы понга, мы можем приступить к настройке игры. Идите вперед, откройте Unity и создайте новый 2D-проект. После открытия редактора установите соотношение сторон экрана игры на 4: 3. Мы используем 4: 3, поскольку это одно из самых распространенных соотношений экрана и одно из самых близких к стандартным. Внутри панели « Assets
Scripts
Sprites
Prefabs
Materials
Эти папки будут использоваться для хранения всех наших игровых активов.
Загрузите соответствующие изображения для игры и добавьте их в папку Sprites (это можно сделать с помощью перетаскивания). Добавленные нами изображения будут спрайтами, интерактивными игровыми объектами, используемыми в игре.
Нам нужно изменить пиксели на единицу для спрайтов, чтобы они соответствовали стандарту. Я обычно использую 64 пикселя на единицу, поскольку это дает большинству спрайтов четкий чистый вид и сохраняет их относительный размер. Вы можете думать о пикселях на единицу как о плотности пикселей, размещенных в пространстве 1 × 1 в редакторе Unity.
Давайте установим пиксели квадратов на единицу равными 64, а пиксели круга на единицу — 128. Мы можем продолжить и добавить три изображения на панель иерархии.
Теперь нам нужно дать каждому активу имя и установить его начальные свойства и теги. Вы можете назвать синий блок «Player» и установить x-позицию игрока на 6
.2
Нам понадобится создать тег, чтобы отделить игровые объекты от других. В широком смысле вы можете думать о Tags
Нажмите «Untagged» (находится под именем игрока) и выберите «Добавить тег». Создайте новый тег с именем «Paddle», повторно выберите игровой объект игрока и установите для него «Paddle».
Назовите красный блок «Враг». Установите х-позицию противника в -6
.2
Сделайте тег вражеского игрового объекта Paddle.
Назовите серый кружок «Ball» и создайте новый тег «Ball». Убедитесь, что для тега объекта игры с мячом установлено значение Ball.
Добавление ввода игрока
На панели «Ресурсы» откройте папку «Сценарии» и создайте новый сценарий C # с именем «PlayerController». Откройте скрипт PlayerController в вашей IDE и введите:
//speed of player
public float speed = 10;
//bounds of player
public float topBound = 4.5F;
public float bottomBound = -4.5F;
// Use this for initialization
void Start () {
Time.timeScale = 0;
}
void Update(){
//pauses or plays game when player hits p
if(Input.GetKeyDown(KeyCode.P) && Time.timeScale == 0){
Time.timeScale = 1;
} else if(Input.GetKeyDown(KeyCode.P) && Time.timeScale == 1){
Time.timeScale = 0;
}
}
// Update is called once per frame
void FixedUpdate () {
//get player input and set speed
float movementSpeedY = speed * Input.GetAxis("Vertical") * Time.deltaTime;
transform.Translate(0, movementSpeedY, 0);
//set bounds of player
if(transform.position.y > topBound){
transform.position = new Vector3(transform.position.x, topBound, 0);
} else if(transform.position.y < bottomBound){
transform.position = new Vector3(transform.position.x, bottomBound, 0);
}
}
Добавьте сценарий PlayerController к игровому объекту Player на панели иерархии, перетащив сценарий на игровой объект. Выберите игровой объект Player и добавьте Box Collider 2D к игровому объекту, щелкнув «Добавить компонент» в нижней части панели инспектора.
Столкновение мячей
Откройте папку «Материалы» внутри панели «Ресурсы». Вы можете создать новый Материал Physics2D, щелкнув правой кнопкой мыши и выбрав Создать -> Материал Physics2D (как на рисунке ниже).
Идите вперед и назовите новый материал «Bounce», и установите его отскок на 1 и его трение на 0.
Выберите объект игры с мячом на панели иерархии. Добавьте Circle Collider 2D к игровому объекту Ball. Перетащите материал отказов в свойство Материал коллайдера, чтобы настроить материал на отскок. Предоставляя объекту игры с мячом материал для отскока, мы делаем его таким образом, чтобы, когда объект игры с мячом достигал границ, он не терял никакой скорости и отскакивал под правильным углом. Нам также нужно добавить Rigidbody 2D к игровому объекту Ball и установить гравитационный масштаб на 0, затем проверить фиксированный угол.
Откройте папку «Сценарии» внутри панели «Ресурсы» и создайте сценарий с именем «BallController». Откройте скрипт BallController внутри вашей IDE и введите:
//speed of the ball
public float speed = 3.5F;
//the initial direction of the ball
private Vector2 spawnDir;
//ball's components
Rigidbody2D rig2D;
// Use this for initialization
void Start () {
//setting balls Rigidbody 2D
rig2D = this.gameObject.GetComponent<Rigidbody2D>();
//generating random number based on possible initial directions
int rand = Random.Range(1,4);
//setting initial direction
if(rand == 1){
spawnDir = new Vector2(1,1);
} else if(rand == 2){
spawnDir = new Vector2(1,-1);
} else if(rand == 3){
spawnDir = new Vector2(-1,-1);
} else if(rand == 4){
spawnDir = new Vector2(-1,1);
}
//moving ball in initial direction and adding speed
rig2D.velocity = (spawnDir*speed);
}
Столкновение границы
Внутри панели иерархии создайте два пустых игровых объекта (щелкните правой кнопкой мыши -> создать пустой) и назовите новые игровые объекты «RightBound» и «TopBound». Установите x-положение RightBound равным 7 и добавьте Box Collider 2D к игровому объекту RightBound. На панели «Инспектор» установите флажок «Триггер» и установите для y-размера коллайдера значение 20. Дублируйте игровой объект RightBound (выберите его и нажмите Ctrl + D). Назовите дубликат «LeftBound» и установите его y-позицию в -7.
Затем выберите игровой объект TopBound и установите его y-позицию равным 5,5, и добавьте Box Collider 2D к игровому объекту TopBound. Установите размер x коллайдера на 20. Дублируйте игровой объект TopBound и назовите дубликат «BottomBound». Установите у-позицию игрового объекта BottomBound на -5,5.
Мы хотим, чтобы левая и правая границы уничтожали мяч, когда мяч проходит мимо одного из лопаток. Внутри панели Assets откройте папку Scripts и создайте новый скрипт C # с именем «BoundController». Откройте BoundController внутри вашей любимой IDE и введите:
void OnTriggerEnter2D(Collider2D other){
//Destroys gameobject if its tag is Ball
if(other.gameObject.tag == "Ball"){
Destroy(other.gameObject);
}
}
Добавьте скрипт BoundController к игровому объекту LeftBound и игровому объекту RightBound.
Враг А.И.
Выберите игровой объект Враг и добавьте Box Collider 2D. Внутри панели Assets откройте папку Scripts. Создайте новый сценарий C # с именем «EnemyController» и введите:
//Speed of the enemy
public float speed = 1.75F;
//the ball
Transform ball;
//the ball's rigidbody 2D
Rigidbody2D ballRig2D;
//bounds of enemy
public float topBound = 4.5F;
public float bottomBound = -4.5F;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void FixedUpdate () {
//finding the ball
ball = GameObject.FindGameObjectWithTag("Ball").transform;
//setting the ball's rigidbody to a variable
ballRig2D = ball.GetComponent<Rigidbody2D>();
//checking x direction of the ball
if(ballRig2D.velocity.x < 0){
//checking y direction of ball
if(ball.position.y < this.transform.position.y){
//move ball down if lower than paddle
transform.Translate(Vector3.down*speed*Time.deltaTime);
} else if(ball.position.y > this.transform.position.y){
//move ball up if higher than paddle
transform.Translate(Vector3.up*speed*Time.deltaTime);
}
}
//set bounds of enemy
if(transform.position.y > topBound){
transform.position = new Vector3(transform.position.x, topBound, 0);
} else if(transform.position.y < bottomBound){
transform.position = new Vector3(transform.position.x, bottomBound, 0);
}
}
Примечание: 1,75 используется для скорости противника исключительно потому, что он делает противника достаточно медленным, чтобы не иметь возможности добраться до каждого шара, который идет в его направлении.
Еще одно примечание: мы использовали фиксированное обновление, потому что этот метод лучше для движения, поскольку он обновляет игровой объект с фиксированной скоростью.
Порождение мяча
Создайте пустой игровой объект внутри панели иерархии и назовите его «BallSpawner». Затем добавьте объект игры Ball в папку Prefabs на панели Assets. Мы можем удалить игровой объект Ball внутри панели иерархии.
Откройте папку «Сценарии» внутри панели «Ресурсы» и создайте новый сценарий C # с именем «BallSpawnerController». Откройте BallSpawnerController внутри вашей IDE и введите:
public GameObject ball;
// Use this for initialization
void Start () {
GameObject ballClone;
ballClone = Instantiate(ball, this.transform.position, this.transform.rotation) as GameObject;
ballClone.transform.SetParent(this.transform);
}
// Update is called once per frame
void Update () {
if(transform.childCount == 0){
GameObject ballClone;
ballClone = Instantiate(ball, this.transform.position, this.transform.rotation) as GameObject;
ballClone.transform.SetParent(this.transform);
}
}
Добавьте скрипт BallSpawnerController к игровому объекту BallSpawner. Теперь мы можем перетащить объект игры Ball из папки Prefabs в значение Ball в BallSpawnerController.
Добавление основного текста
Нам нужно добавить текст на экран, чтобы игроки нажимали P, чтобы начать игру и поставить игру на паузу, чтобы игроки знали, как начать игру и поставить игру на паузу.
Мы можем создать текстовый игровой объект (в панели иерархии щелкните правой кнопкой мыши -> UI -> Text) и назовите текстовый игровой объект PlayText. Далее давайте установим его текстовое значение «Hit P to play или pause» и выровняем текст по центру. Теперь мы можем выровнять игровой объект по верху экрана и затем привязать его. Давайте установим его ширину на 200, чтобы весь текст был виден. Наконец, установите цвет текста на белый.
Сохраните сцену и добавьте ее в настройки сборки (путем перетаскивания или проверки добавления текущей сцены), и все готово!
Вывод
Теперь вы официально создали базовый клон Pong для одного игрока в Unity2D. Для большей практики попробуйте придумать способы обновить игру и сделать ее лучше — добавьте ускорение мячу (чем больше ударов, тем быстрее мяч), добавьте инерцию к веслам, добавьте уровни сложности, увеличив скорость противника и т. Д.
Вы можете скачать проект на GitHub