Last active
January 29, 2024 06:14
-
-
Save unitycoder/a10c215ec9c477ff0e04c964dff3208f to your computer and use it in GitHub Desktop.
Pong-Wars in Unity c#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// original JS source https://github.com/vnglst/pong-wars/blob/main/index.html | |
// https://unitycoder.com/blog/2024/01/29/pong-wars-in-unity/ | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class PongWars : MonoBehaviour | |
{ | |
Color DAY_COLOR = Color.white; | |
Color DAY_BALL_COLOR = Color.black; | |
Color NIGHT_COLOR = Color.black; | |
Color NIGHT_BALL_COLOR = Color.white; | |
const int SQUARE_SIZE = 8 + 8; | |
const int canvasWidth = 512; | |
const int canvasHeight = 512; | |
const int numSquaresX = canvasWidth / SQUARE_SIZE; | |
const int numSquaresY = canvasHeight / SQUARE_SIZE; | |
Color[,] squares = new Color[numSquaresX, numSquaresY]; | |
Texture2D tex; | |
float x1 = 0, y1 = 0; | |
float x2 = 0, y2 = 0; | |
float dx1 = 0, dy1 = 0; | |
float dx2 = 0, dy2 = 0; | |
public AudioClip hitSound; | |
private void Start() | |
{ | |
tex = new Texture2D(canvasWidth, canvasHeight, TextureFormat.RGB24, false, false); | |
GetComponent<Renderer>().material.mainTexture = tex; | |
tex.filterMode = FilterMode.Point; | |
tex.wrapMode = TextureWrapMode.Clamp; | |
for (var i = 0; i < numSquaresX; i++) | |
{ | |
//squares[i] = new Color[numSquaresY]; | |
for (var j = 0; j < numSquaresY; j++) | |
{ | |
squares[i, j] = i < numSquaresX / 2 ? DAY_COLOR : NIGHT_COLOR; | |
} | |
} | |
x1 = canvasWidth / 4; | |
y1 = canvasHeight / 2; | |
dx1 = 12.5f; | |
dy1 = -12.5f; | |
x2 = (canvasWidth / 4) * 3; | |
y2 = canvasHeight / 2; | |
dx2 = -12.5f; | |
dy2 = 12.5f; | |
var iteration = 0; | |
} | |
void drawBall(int cx, int cy, Color color) | |
{ | |
//ctx.beginPath(); | |
//ctx.arc(x, y, SQUARE_SIZE / 2, 0, Math.PI * 2, false); | |
//ctx.fillStyle = color; | |
//ctx.fill(); | |
//ctx.closePath(); | |
// TODO draw circle | |
for (var x = cx - SQUARE_SIZE / 2; x < cx + SQUARE_SIZE / 2; x++) | |
{ | |
for (var y = cy - SQUARE_SIZE / 2; y < cy + SQUARE_SIZE / 2; y++) | |
{ | |
tex.SetPixel(x, y, color); | |
} | |
} | |
tex.Apply(false); | |
} | |
void drawSquares() | |
{ | |
for (var i = 0; i < numSquaresX; i++) | |
{ | |
for (var j = 0; j < numSquaresY; j++) | |
{ | |
//ctx.fillStyle = squares[i][j]; | |
//ctx.fillRect(i * SQUARE_SIZE, j * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE); | |
for (var x = i * SQUARE_SIZE; x < i * SQUARE_SIZE + SQUARE_SIZE; x++) | |
{ | |
for (var y = j * SQUARE_SIZE; y < j * SQUARE_SIZE + SQUARE_SIZE; y++) | |
{ | |
tex.SetPixel(x, y, squares[i, j]); | |
} | |
} | |
} | |
} | |
tex.Apply(false); | |
} | |
float randomNum(float min, float max) | |
{ | |
return Random.Range(min, max); | |
} | |
(float, float) updateSquareAndBounce(float x, float y, float dx, float dy, Color color) | |
{ | |
float updatedDx = dx; | |
float updatedDy = dy; | |
// Check multiple points around the ball's circumference | |
for (float angle = 0; angle < Mathf.PI * 2; angle += Mathf.PI / 4) | |
{ | |
var checkX = x + Mathf.Cos(angle) * (SQUARE_SIZE / 2); | |
var checkY = y + Mathf.Sin(angle) * (SQUARE_SIZE / 2); | |
int i = Mathf.FloorToInt(checkX / SQUARE_SIZE); | |
int j = Mathf.FloorToInt(checkY / SQUARE_SIZE); | |
if (i >= 0 && i < numSquaresX && j >= 0 && j < numSquaresY) | |
{ | |
if (squares[i, j] != color) | |
{ | |
squares[i, j] = color; | |
// Determine bounce direction based on the angle | |
if (Mathf.Abs(Mathf.Cos(angle)) > Mathf.Abs(Mathf.Sin(angle))) | |
{ | |
updatedDx = -updatedDx; | |
AudioSource.PlayClipAtPoint(hitSound, new Vector3(0, 0, 0)); | |
} | |
else | |
{ | |
updatedDy = -updatedDy; | |
AudioSource.PlayClipAtPoint(hitSound, new Vector3(0, 0, 0)); | |
} | |
// Add some randomness to the bounce to prevent the balls from getting stuck in a loop | |
updatedDx += randomNum(-0.01f, 0.01f); | |
updatedDy += randomNum(-0.01f, 0.01f); | |
} | |
} | |
} | |
return (updatedDx, updatedDy); | |
//return { dx: updatedDx, dy: updatedDy }; | |
} // updateSquareAndBounce | |
//void updateScoreElement() | |
//{ | |
// var dayScore = 0; | |
// var nightScore = 0; | |
// for (var i = 0; i < numSquaresX; i++) | |
// { | |
// for (var j = 0; j < numSquaresY; j++) | |
// { | |
// if (squares[i][j] === DAY_COLOR) | |
// { | |
// dayScore++; | |
// } | |
// else if (squares[i][j] === NIGHT_COLOR) | |
// { | |
// nightScore++; | |
// } | |
// } | |
// } | |
// scoreElement.textContent = `day ${ dayScore} | night ${ nightScore}`; | |
//} | |
(float, float) checkBoundaryCollision(float x, float y, float dx, float dy) | |
{ | |
if (x + dx > canvasWidth - SQUARE_SIZE / 2 || x + dx < SQUARE_SIZE / 2) | |
{ | |
dx = -dx; | |
// TODO different sound for 1/2 | |
AudioSource.PlayClipAtPoint(hitSound, new Vector3(0, 0, 0)); | |
} | |
if ( | |
y + dy > canvasHeight - SQUARE_SIZE / 2 || | |
y + dy < SQUARE_SIZE / 2 | |
) | |
{ | |
dy = -dy; | |
AudioSource.PlayClipAtPoint(hitSound, new Vector3(0, 0, 0)); | |
} | |
return (dx, dy); | |
//return { dx: dx, dy: dy }; | |
} | |
int iteration = 0; | |
private void Update() | |
{ | |
draw(); | |
} | |
void draw() | |
{ | |
//ctx.clearRect(0, 0, canvasWidth, canvasHeight); | |
drawSquares(); | |
drawBall((int)x2, (int)y2, NIGHT_BALL_COLOR); | |
var bounce2 = updateSquareAndBounce(x2, y2, dx2, dy2, NIGHT_COLOR); | |
dx2 = bounce2.Item1; | |
dy2 = bounce2.Item2; | |
drawBall((int)x1, (int)y1, DAY_BALL_COLOR); | |
var bounce1 = updateSquareAndBounce(x1, y1, dx1, dy1, DAY_COLOR); | |
dx1 = bounce1.Item1; | |
dy1 = bounce1.Item2; | |
var boundary1 = checkBoundaryCollision(x1, y1, dx1, dy1); | |
dx1 = boundary1.Item1; | |
dy1 = boundary1.Item2; | |
var boundary2 = checkBoundaryCollision(x2, y2, dx2, dy2); | |
dx2 = boundary2.Item1; | |
dy2 = boundary2.Item2; | |
x1 += dx1; | |
y1 += dy1; | |
x2 += dx2; | |
y2 += dy2; | |
//iteration++; | |
//if (iteration % 1_000 === 0) console.log("interation", iteration); | |
//updateScoreElement(); | |
//requestAnimationFrame(draw); | |
} | |
void clearRect(int x, int y, int width, int height) | |
{ | |
for (var i = x; i < x + width; i++) | |
{ | |
for (var j = y; j < y + height; j++) | |
{ | |
tex.SetPixel(i, j, Color.clear); | |
} | |
} | |
tex.Apply(false); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment