Advertisement

Pong AI

Started by April 26, 2018 01:57 PM
4 comments, last by bowcox 6 years, 7 months ago

Hi guys! 

I have created a Pong game that has an AI that is almost beatable, changing the speed of the AI can make it ridiculously easy or hard depending on the way you go about it. 

 


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

public class ComputerMovement : MonoBehaviour {

	private float speed;
	private float reAdjustSpeed = 1f;
	private Rigidbody2D computer2d;
	public static bool isTwoPlayer;
	GameObject theBall;
	Rigidbody2D rb2d;

	void Start() {
		computer2d = GetComponent<Rigidbody2D> ();
	}

	void FixedUpdate() {
		if (isTwoPlayer == true) {
			speed = 5f;
			if (Input.GetKey (KeyCode.W)) { 
				computer2d.position += Vector2.up * speed * Time.deltaTime;
			}

			if (Input.GetKey (KeyCode.S)) { 
				computer2d.position += Vector2.down * speed * Time.deltaTime;
			}
		}

		if (isTwoPlayer == false) {
			speed = 3f;


			if (theBall == null) {
				theBall = GameObject.FindGameObjectWithTag ("Ball");
			}

			rb2d = theBall.GetComponent<Rigidbody2D> ();

			//Is the ball going left or right
			if (rb2d.velocity.x > 0) {

				if (rb2d.velocity.y > 0) {
					if (rb2d.position.y > computer2d.position.y) {
						MoveUp ();
					}
				
					if (rb2d.position.y < computer2d.position.y) {
						MoveDown ();
					}
				} 

				if (rb2d.velocity.y < 0) {
					if (rb2d.position.y > computer2d.position.y) {
						MoveUp ();
					}
					if (rb2d.position.y < computer2d.position.y) {
						MoveDown ();
					}
				}

			}

			//Whilst it's not moving at the paddle, let it gain a slight reset by moving with the ball at a slower pace. 
			if (rb2d.velocity.x < 0) {
				if (computer2d.position.y < 0) {
					computer2d.position += Vector2.up * reAdjustSpeed * Time.deltaTime;
				}

				if (computer2d.position.y > 0) {
					computer2d.position += Vector2.down * reAdjustSpeed * Time.deltaTime;
				}
			}
		}
	}

	void MoveDown() {
		if (Mathf.Abs(rb2d.velocity.y) > speed) {
			computer2d.position += Vector2.down * speed * Time.deltaTime;
		} else {
			computer2d.position += Vector2.down * speed * Time.deltaTime;
		}
	}

	void MoveUp() {
		if (Mathf.Abs (rb2d.velocity.y) > speed) {
			computer2d.position += Vector2.up * speed * Time.deltaTime;
		} else {
			computer2d.position += Vector2.up * speed * Time.deltaTime;
		}
	}

}

 

I have looked up several posts across many different forums in order to create a much better AI. Most of the posts recommend that I use Raycasts to find out exactly where the ball might hit the paddle. I have looked up how to use them and I'm just completely lost, do raycasts consider collisions and go on infinitely or once they hit a wall, that's where it'll end up? Would anyone be able to help me understand raycasts a little better? 

If you have another solution that enables me to calculate exactly where the ball will end up on the opponents side, I am more than willing to hear it :P

Thanks again if you read this!

I'm not so sure about the way I use raycast, but it works in my game. What I do is check the X and Y axis if it will have a collision in the next frame (it have to happen in both axis, otherwise it would collide without touching it).


// Velocity is the speed with a direction
// I'm considering that the ball and player have the origin in the center of the object
// The bot_position.x - (bot_size.x / 2), check the leftmost part of the paddle

if (ball_position.x + velocity.x * delta_time <= bot_position.x &&
    ball_position.x + velocity.x * delta_time >= bot_position.x - (bot_size.x / 2))

It's only an example, so you'd have to change it to actually check the whole hit box of both.

To know where it collided, you could do after finding that it collided:


float paddle_part = (bot_position.y - ball_position.y) / (bot_size.y / 2).

 

PS: A more experienced person is more than welcome to correct any mistake I made.

Advertisement
On 4/26/2018 at 6:05 PM, Luhan M. said:

I'm not so sure about the way I use raycast, but it works in my game. What I do is check the X and Y axis if it will have a collision in the next frame (it have to happen in both axis, otherwise it would collide without touching it).



// Velocity is the speed with a direction
// I'm considering that the ball and player have the origin in the center of the object
// The bot_position.x - (bot_size.x / 2), check the leftmost part of the paddle

if (ball_position.x + velocity.x * delta_time <= bot_position.x &&
    ball_position.x + velocity.x * delta_time >= bot_position.x - (bot_size.x / 2))

It's only an example, so you'd have to change it to actually check the whole hit box of both.

To know where it collided, you could do after finding that it collided:



float paddle_part = (bot_position.y - ball_position.y) / (bot_size.y / 2).

 

PS: A more experienced person is more than welcome to correct any mistake I made.

Thanks very much for replying, I did try your method but have ended up trying to use raycasts. It's not been fun but I'm almost there. Thanks for your input though, it gave me something to try when I was struggling to think of anything else :).

8 minutes ago, bowcox said:

Thanks very much for replying, I did try your method but have ended up trying to use raycasts. It's not been fun but I'm almost there. Thanks for your input though, it gave me something to try when I was struggling to think of anything else .

If you want you could post here your code, or a pseucode of what you're trying to do, and explain what is actually happening, I don't use c#, but probably I could try to help you because I did a pong not a long time ago.

And you of course can try something else, as myself, I didn't use it, I was only checking for the whole box of both if there was a collision (when i did make the pong).

 

4 minutes ago, Luhan M. said:

If you want you could post here your code, or a pseucode of what you're trying to do, and explain what is actually happening, I don't use c#, but probably I could try to help you because I did a pong not a long time ago.

And you of course can try something else, as myself, I didn't use it, I was only checking for the whole box of both if there was a collision (when i did make the pong).

Above is a link to my new post, if you'd like to help, I would more than welcome it :)

This topic is closed to new replies.

Advertisement