Month: October 2019

  • Pamac > Pacman

    I must say that I much prefer the Pamac CLI package manager to Pacman. It’s much more intuitive and I’m glad that Manjaro includes it by default.

  • Arduino Pong

    This is a simple pong game I created for fun for the CICS 290M Makerboard running Arduino software. The board is part of the CS Make course at UMass Amherst.

    Below is the source code, it’s also available on GitHub.

    // Imports
    #include <Adafruit_SSD1306.h>
    
    // Globals
    #define UP_BUTTON 34
    #define DOWN_BUTTON 0
    #define RESET_BUTTON 35
    #define BUZZER 17
    
    // Game State
    int score = 0;
    
    // Paddle
    int paddle_pos = 32;
    int paddle_velocity = 1;
    int paddle_height = 16;
    int paddle_width = 4;
    
    // Ball
    volatile int ball_x = random(10, 80);
    volatile int ball_y = random(16, 48);
    volatile int ball_radius = 3;
    volatile int ball_velocity_x = random(1, 3);
    volatile int ball_velocity_y = random(1, 3);
    
    
    Adafruit_SSD1306 lcd(128, 64); // create display object
    
    // Callbacks
    void IRAM_ATTR moveUp() {
      if (paddle_pos >= 0) {
        paddle_pos -= 1;
      }
    }
    
    void IRAM_ATTR moveDown() {
      if (paddle_pos + paddle_height <= 64) {
        paddle_pos += 1;
      }
    }
    
    void IRAM_ATTR restart() {
      if (gameOver()) {
        score = 0;
        ball_x = random(10, 80);
        ball_y = random(16, 48);
        ball_velocity_x = random(1, 3);
        ball_velocity_y = random(1, 3);
      }
    }
    void setup() {
      Serial.begin(9600);
      pinMode(BUZZER, OUTPUT);
      pinMode(UP_BUTTON, INPUT);
      pinMode(DOWN_BUTTON, INPUT);
      pinMode(RESET_BUTTON, INPUT);
      lcd.begin(SSD1306_SWITCHCAPVCC, 0x3C); // init
      lcd.setTextColor(WHITE);
      lcd.clearDisplay(); // clear software buffer
      lcd.display();
      attachInterrupt(RESET_BUTTON, restart, FALLING);
    }
    
    // Test if coordinates are out of bounds
    boolean yIsOutOfBounds(int y) {return y > 63 || y < 0;}
    boolean xIsOutOfBounds(int x) {return x > 127 || x < 0;}
    boolean outOfBounds(int x, int y) {return xIsOutOfBounds(x) || yIsOutOfBounds(y);}
    boolean gameOver() {return ball_x + ball_radius >= 127;}
    boolean ballPaddleCollision(int x, int y) {
      return (x > 128 - paddle_width) && (y < paddle_pos + paddle_height && y > paddle_pos);
    }
    
    void drawPaddle(int x, int y, int width, int height) {
      lcd.fillRect(x, y, width, height, WHITE);
    }
    
    void ding() {
      ledcSetup(0, 5000, 8);
      ledcAttachPin(BUZZER, 0);
      ledcWriteTone(0, 500);
      delay(50); // 500Hz for 0.05 second
      ledcWriteTone(0, 0); // buzzer off
    }
    
    void drawBall() {
      lcd.fillCircle(ball_x, ball_y, ball_radius, BLACK);
      if (xIsOutOfBounds(ball_x + ball_radius) || xIsOutOfBounds(ball_x - ball_radius)) {
        ball_velocity_x *= -1;
        ding();
      }
      if (yIsOutOfBounds(ball_y + ball_radius) || yIsOutOfBounds(ball_y - ball_radius)) {ball_velocity_y *= -1;}
      if (ballPaddleCollision(ball_x + ball_radius, ball_y) || ballPaddleCollision(ball_x - ball_radius, ball_y)) {
        ball_velocity_x *= -1;
        ding();
        score++;
      }
      ball_x += ball_velocity_x;
      ball_y += ball_velocity_y;
      lcd.fillCircle(ball_x, ball_y, ball_radius, WHITE);
    }
    
    void loop() {
      // Check if Game is over
      if (gameOver()) {
        lcd.clearDisplay();
        lcd.setCursor(0,0);
        lcd.print("Score: " + String(score) + "\nPress bottom button \nto restart.");
        lcd.display();
        return;
      }
      // Check for button presses
      if (!digitalRead(UP_BUTTON)) {
        moveUp();
      }
      if (!digitalRead(DOWN_BUTTON)) {
        moveDown();
      }
      lcd.clearDisplay();
      drawPaddle(0, ball_y - (paddle_height / 2), paddle_width, paddle_height);
      drawPaddle(127 - paddle_width, paddle_pos + paddle_velocity, paddle_width, paddle_height); 
      drawBall();
      lcd.display();
    }