Skip to content

Instantly share code, notes, and snippets.

@unitycoder
Last active February 6, 2025 12:31
Show Gist options
  • Select an option

  • Save unitycoder/a10c215ec9c477ff0e04c964dff3208f to your computer and use it in GitHub Desktop.

Select an option

Save unitycoder/a10c215ec9c477ff0e04c964dff3208f to your computer and use it in GitHub Desktop.

Revisions

  1. unitycoder revised this gist Jan 29, 2024. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions PongWars.cs
    Original file line number Diff line number Diff line change
    @@ -5,8 +5,6 @@
    using System.Collections.Generic;
    using UnityEngine;



    public class PongWars : MonoBehaviour
    {
    Color DAY_COLOR = Color.white;
  2. unitycoder revised this gist Jan 29, 2024. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion PongWars.cs
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,11 @@
    // 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;

    // source https://github.com/vnglst/pong-wars/blob/main/index.html


    public class PongWars : MonoBehaviour
    {
  3. unitycoder created this gist Jan 29, 2024.
    248 changes: 248 additions & 0 deletions PongWars.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,248 @@
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    // source https://github.com/vnglst/pong-wars/blob/main/index.html

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