cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

sgb_pong.c (4194B)


      1#include <gb/gb.h>
      2#include <gb/sgb.h>
      3#include <gbdk/console.h>
      4
      5#include <stdint.h>
      6#include <stdio.h>
      7
      8uint8_t sprite_data[] = {
      9    0x3C,0x3C,0x42,0x7E,0x99,0xFF,0xA9,0xFF,0x89,0xFF,0x89,0xFF,0x42,0x7E,0x3C,0x3C,
     10    0x3C,0x3C,0x42,0x7E,0xB9,0xFF,0x89,0xFF,0x91,0xFF,0xB9,0xFF,0x42,0x7E,0x3C,0x3C,
     11    0x3C,0x3C,0x42,0x7E,0x99,0xFF,0x89,0xFF,0x99,0xFF,0x89,0xFF,0x5A,0x7E,0x3C,0x3C,
     12    0x3C,0x3C,0x42,0x7E,0xA9,0xFF,0xA9,0xFF,0xB9,0xFF,0x89,0xFF,0x42,0x7E,0x3C,0x3C
     13
     14};
     15
     16// initializes sprites for pad. every pad uses 3 sprites which id's are aligned by 4
     17void init_pad(uint8_t n) {
     18    set_sprite_tile(n << 2, n);
     19    set_sprite_tile((n << 2) + 1, n);
     20    set_sprite_tile((n << 2) + 2, n);
     21}
     22
     23// inline function for moving pads; code of this function will be inlined with the code of main()
     24inline void draw_pad(uint8_t n, uint8_t x, uint8_t y) {
     25    move_sprite(n << 2, x, y);
     26    move_sprite((n << 2) + 1, x, y + 8);
     27    move_sprite((n << 2) + 2, x, y + 16);
     28}
     29
     30joypads_t joypads;
     31
     32// absolute Y coordinates of player 1 & 2
     33uint8_t player1, player2;
     34uint16_t player1_score, player2_score;
     35
     36// player constraints
     37#define YMIN 28
     38#define YMAX 100
     39#define PLAYER1_X 16
     40#define PLAYER2_X (uint8_t)((20 * 8) - 8)
     41
     42// coordinates and speeds of ball
     43uint8_t ballX, ballY;
     44int8_t spd_ballX, spd_ballY;
     45
     46#define INITBALLX 80 + 4 
     47#define INITBALLY 64 + 8
     48
     49const unsigned char HUD[] = " p1: %d   p2: %d";
     50
     51// main funxction
     52void main(void) {
     53    // init palettes
     54    BGP_REG = OBP0_REG = OBP1_REG = 0xE4;
     55
     56    // load tile data into VRAM
     57    set_sprite_data(0, 4, sprite_data);
     58    
     59    // init pad sprites
     60    init_pad(0);
     61    init_pad(1);
     62    
     63    // init ball sprite
     64    set_sprite_tile(3, 2);
     65
     66    // show bkg and sprites
     67    SHOW_BKG; SHOW_SPRITES;
     68
     69    // init 2 joypads
     70    if (joypad_init(2, &joypads) != 2) {
     71        printf(" This program must\n  be executed  on\n   Super GameBoy");
     72        return;
     73    }
     74 
     75    // init players
     76    player1 = 64, player2 = 64;
     77    player1_score = player2_score = 0;
     78    
     79    // draw score
     80    printf(HUD, player1_score, player2_score);
     81    
     82    // init ball
     83    ballX = INITBALLX, ballY = INITBALLY;
     84    spd_ballX = 1, spd_ballY = 1;
     85    
     86    while(1) {
     87        // poll joypads
     88        joypad_ex(&joypads);
     89        
     90        // player 1
     91        if (joypads.joy0 & J_UP) {
     92            player1 -= 2;
     93            if (player1 < YMIN) player1 = YMIN;
     94        } else if (joypads.joy0 & J_DOWN) {
     95            player1 += 2;
     96            if (player1 > YMAX) player1 = YMAX;            
     97        }
     98        draw_pad(0, PLAYER1_X, player1);
     99        
    100        // player 2
    101        if (joypads.joy1 & J_UP) {
    102            player2 -= 2;
    103            if (player2 < YMIN) player2 = YMIN;
    104        } else if (joypads.joy1 & J_DOWN) {
    105            player2 += 2;
    106            if (player2 > YMAX) player2 = YMAX;            
    107        }
    108        draw_pad(1, PLAYER2_X, player2);
    109
    110        // move ball
    111        ballX += spd_ballX, ballY += spd_ballY;
    112        // check bounce from limits
    113        if ((ballY < YMIN) || (ballY > (YMAX + 24))) {
    114            spd_ballY = -spd_ballY; 
    115        }
    116        // check bounce from bats
    117        if (ballX < (PLAYER1_X + 8)) {
    118            if ((ballY > player1) && (ballY < (player1 + 24)) && (spd_ballX < 0)) 
    119                spd_ballX = -spd_ballX;
    120        } else if (ballX > (PLAYER2_X - 8)) {
    121            if ((ballY > player2) && (ballY < (player2 + 24)) && (spd_ballX > 0)) 
    122                spd_ballX = -spd_ballX;
    123        }
    124        // check player1 or 2 wins, update scores, start from center
    125        if (ballX < PLAYER1_X) {
    126            // player2 wins
    127            ballX = INITBALLX, ballY = INITBALLY;
    128            spd_ballX = -spd_ballX;
    129            player2_score++;
    130            gotoxy(0, 0); printf(HUD, player1_score, player2_score);
    131        } else if (ballX > PLAYER2_X) {
    132            // player1 wins
    133            ballX = INITBALLX, ballY = INITBALLY;
    134            spd_ballX = -spd_ballX;
    135            player1_score++;
    136            gotoxy(0, 0); printf(HUD, player1_score, player2_score);
    137        }
    138        // move ball sprite
    139        move_sprite(3, ballX, ballY);
    140
    141        // wait for VBlank to slow down everything
    142        wait_vbl_done();
    143    }
    144}