티스토리 뷰

OS/micro:bit

micro:bit - Pong Game

파란크리스마스 2018. 1. 27. 08:27
728x90

본 체험 제품은 element14 의 후원을 받아 아이씨뱅큐㈜ 에서 진행하는 무상 체험단 활동으로 작성한 것입니다.

출처 : Arduino Pong Game - OLED Display: 5 Steps (with Pictures)

micro:bit - Pong Game

Arduino로 SSD1331이용해서 만들어진 간단한 PONG 게임을 micro:bit에서 구동 되도록 만들어 보았습니다. micro:bit에 내장된 좌우 버튼으로 좌버튼을 누르면 올라가고, 우버튼을 누르면 내려가도록 했습니다.

  

main.cpp - pong_game_source_2.7z

#include "MicroBit.h" 
#include "ssd1331.h"
 
// Color definitions
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

#define LOW 0

const unsigned long PADDLE_RATE = 33;
const unsigned long BALL_RATE = 20;
const uint8_t PADDLE_HEIGHT = 24;
int MAX_SCORE = 3;

int CPU_SCORE = 0;
int PLAYER_SCORE = 0;


// You can use any (4 or) 5 pins 
#define sclk 13
#define mosi 11
#define cs   10
#define rst  9
#define dc   8

// MOSI is Data pin on display breakout
// ssd1331(PinName cs_pin, PinName rst_pin, PinName a0_pin, PinName mosi_pin, PinName miso_pin, PinName sclk_pin);
ssd1331 display(P0_16, P0_18, P0_10, P0_21, P0_22, P0_23); // cs, res, dc, miso(nc), sck (KL25z)

void drawCourt();
void gameOver();
void loop();
void showScore();

uint8_t ball_x = 64, ball_y = 32;
uint8_t ball_dir_x = 1, ball_dir_y = 1;

bool gameIsRunning = true;
bool resetBall = false;

static const unsigned char pong [] = {
0xff,0xe0,0x0,0x3f,0x80,0x7,0xe0,0x7,0xc0,0x3,0xfc,0x0,
0xff,0xf8,0x1,0xff,0xe0,0x7,0xf0,0x7,0xc0,0x1f,0xff,0x0,
0xff,0xfc,0x3,0xff,0xf0,0x7,0xf0,0x7,0xc0,0x3f,0xff,0x0,
0xff,0xfe,0x7,0xff,0xf8,0x7,0xf8,0x7,0xc0,0xff,0xff,0x0,
0xf8,0x7f,0xf,0xff,0xfc,0x7,0xfc,0x7,0xc0,0xff,0xff,0x0,
0xf8,0x3f,0xf,0xe0,0xfe,0x7,0xfc,0x7,0xc1,0xfc,0x7,0x0,
0xf8,0x1f,0x1f,0x80,0x7e,0x7,0xfe,0x7,0xc3,0xf8,0x1,0x0,
0xf8,0x1f,0x1f,0x0,0x3e,0x7,0xfe,0x7,0xc3,0xf0,0x0,0x0,
0xf8,0x1f,0x3f,0x0,0x3f,0x7,0xdf,0x7,0xc7,0xe0,0x0,0x0,
0xf8,0x1f,0x3e,0x0,0x1f,0x7,0xdf,0x87,0xc7,0xc0,0x0,0x0,
0xf8,0x3f,0x3e,0x0,0x1f,0x7,0xcf,0x87,0xc7,0xc1,0xff,0x80,
0xf8,0x7e,0x3e,0x0,0x1f,0x7,0xc7,0xc7,0xc7,0xc1,0xff,0x80,
0xff,0xfe,0x3e,0x0,0x1f,0x7,0xc7,0xe7,0xc7,0xc1,0xff,0x80,
0xff,0xfc,0x3e,0x0,0x1f,0x7,0xc3,0xe7,0xc7,0xc1,0xff,0x80,
0xff,0xf8,0x3e,0x0,0x1f,0x7,0xc1,0xf7,0xc7,0xc0,0xf,0x80,
0xff,0xe0,0x3f,0x0,0x3f,0x7,0xc1,0xf7,0xc7,0xe0,0xf,0x80,
0xf8,0x0,0x1f,0x0,0x3e,0x7,0xc0,0xff,0xc3,0xe0,0xf,0x80,
0xf8,0x0,0x1f,0x80,0x7e,0x7,0xc0,0x7f,0xc3,0xf0,0xf,0x80,
0xf8,0x0,0x1f,0xc0,0xfc,0x7,0xc0,0x7f,0xc3,0xfc,0xf,0x80,
0xf8,0x0,0xf,0xff,0xfc,0x7,0xc0,0x3f,0xc1,0xff,0xff,0x80,
0xf8,0x0,0x7,0xff,0xf8,0x7,0xc0,0x3f,0xc0,0xff,0xff,0x80,
0xf8,0x0,0x3,0xff,0xf0,0x7,0xc0,0x1f,0xc0,0x7f,0xff,0x80,
0xf8,0x0,0x1,0xff,0xe0,0x7,0xc0,0xf,0xc0,0x3f,0xff,0x0,
0xf8,0x0,0x0,0x7f,0x0,0x7,0xc0,0xf,0xc0,0x7,0xf8,0x0
};

static const unsigned char game [] ={
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xff,0x80,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc3,0xff,0x80,
0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xc3,0xff,0x80,
0x0,0x0,0x0,0x0,0x3,0xe0,0xf,0xc3,0xe0,0x0,
0x0,0x0,0x0,0x0,0x7,0xf0,0x1f,0xc1,0xe0,0x0,
0x0,0x0,0x0,0xf8,0x7,0xf0,0x1f,0xc1,0xe0,0x0,
0x0,0xfc,0x1,0xfc,0x7,0xf8,0x1f,0xc1,0xe0,0x0,
0x7,0xfc,0x1,0xfc,0x3,0xf8,0x1f,0xe1,0xff,0x80,
0x1f,0xfc,0x1,0xde,0x3,0xbc,0x3d,0xe1,0xff,0x80,
0x3f,0xfe,0x1,0xde,0x3,0xbc,0x39,0xe1,0xff,0x80,
0x7e,0x0,0x3,0xdf,0x3,0xde,0x39,0xe1,0xfc,0x0,
0x7c,0x0,0x3,0xcf,0x3,0xde,0x39,0xe1,0xe0,0x0,
0xf8,0x0,0x3,0xcf,0x3,0xcf,0x39,0xe1,0xf0,0x0,
0xf8,0x0,0x3,0x87,0x83,0xcf,0x79,0xe0,0xf0,0x0,
0xf0,0x7f,0x7,0x87,0x83,0xc7,0xf1,0xe0,0xf0,0xe0,
0xf0,0xff,0x7,0x83,0xc3,0xc7,0xf1,0xe0,0xff,0xe0,
0xf0,0xff,0x7,0xff,0xc1,0xc3,0xf1,0xf0,0xff,0xe0,
0xf0,0xff,0x7,0xff,0xe1,0xc3,0xf0,0xf0,0xff,0xe0,
0xf8,0xf,0xf,0xff,0xe1,0xc1,0xe0,0xf0,0xe0,0x0,
0xf8,0xf,0x8f,0x1,0xf1,0xe1,0xe0,0xf0,0x0,0x0,
0x7c,0xf,0x8f,0x0,0xf1,0xe1,0xe0,0x0,0x0,0x0,
0x7f,0x1f,0x8f,0x0,0xf9,0xc0,0x0,0x0,0x0,0x0,
0x3f,0xff,0x9f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x1f,0xff,0x1f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x7,0xfc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};

unsigned long ball_update;
unsigned long paddle_update;

const uint8_t CPU_X = 12;
uint8_t cpu_y = 16;

const uint8_t PLAYER_X = 85;
uint8_t player_y = 16;

uint64_t millis() { return us_ticker_read() / 1000; }
void delay(uint32_t delay) { wait_ms(delay); }

uint8_t random(uint8_t min, uint8_t max) {
	return (rand() % (max - min + 1) ) + 1;
}

DigitalIn UP_BUTTON(MICROBIT_PIN_BUTTON_A);
DigitalIn DOWN_BUTTON(MICROBIT_PIN_BUTTON_B);

int main() { 
 
  display.cls(); // clear screen to black
  display.drawBitmap(3,0,pong,89,24,GREEN);
  display.drawBitmap(10,30,game,75,26,RED);
  while(UP_BUTTON && DOWN_BUTTON) {
    wait_ms(100);
  }

  unsigned long start = millis();

    
  display.fillScreen(BLACK);
  drawCourt();

  while(millis() - start < 2000);
  ball_update = millis();
  paddle_update = ball_update;
  ball_x = random(25,65); 
  ball_y = random(3,63);
  
  while(1) {
  	loop();
  }
  
  release_fiber();   
}

void loop() {

    unsigned long time = millis();    
    static bool up_state = false;
    static bool down_state = false;
    
    up_state |= (UP_BUTTON == LOW);
    down_state |= (DOWN_BUTTON == LOW);

    if(resetBall)
    {
      ball_x = random(25,70); 
      ball_y = random(3,63);
      
      /*
      do
      {
      	ball_dir_x = random(-1,2);
      }while(ball_dir_x==0);

       do
      {
      	ball_dir_y = random(-1,2);
      }while(ball_dir_y==0);
      */
      
      ball_dir_x = 1;
      ball_dir_y = 1;
      
      resetBall=false;
    }

    if(time > ball_update && gameIsRunning) {
        uint8_t new_x = ball_x + ball_dir_x;
        uint8_t new_y = ball_y + ball_dir_y;

        // Check if we hit the vertical walls
        if(new_x == 0) //Player Gets a Point
        {
            PLAYER_SCORE++;
            if(PLAYER_SCORE==MAX_SCORE)
            {
              gameOver();
            }else
            {
              showScore();
            }
        }

         // Check if we hit the vertical walls
        if(new_x == 95) //CPU Gets a Point
        {
            CPU_SCORE++;
            if(CPU_SCORE==MAX_SCORE)
            {
              gameOver();
            }else
            {
              showScore();
            }
        }

        // Check if we hit the horizontal walls.
        if(new_y == 0 || new_y == 63) {
            ball_dir_y = -ball_dir_y;
            new_y += ball_dir_y + ball_dir_y;
        }

        // Check if we hit the CPU paddle
        if(new_x == CPU_X && new_y >= cpu_y && new_y <= cpu_y + PADDLE_HEIGHT) {
            ball_dir_x = -ball_dir_x;
            new_x += ball_dir_x + ball_dir_x;
        }

        // Check if we hit the player paddle
        if(new_x == PLAYER_X
           && new_y >= player_y
           && new_y <= player_y + PADDLE_HEIGHT)
        {
            ball_dir_x = -ball_dir_x;
            new_x += ball_dir_x + ball_dir_x;
        }

        display.drawPixel(ball_x, ball_y, BLACK);
        display.drawPixel(new_x, new_y, WHITE);
        ball_x = new_x;
        ball_y = new_y;

        ball_update += BALL_RATE;

    }

    if(time > paddle_update && gameIsRunning) {
        paddle_update += PADDLE_RATE;

        // CPU paddle
        display.drawFastVLine(CPU_X, cpu_y,PADDLE_HEIGHT, BLACK);
        const uint8_t half_paddle = PADDLE_HEIGHT >> 1;
        if(cpu_y + half_paddle > ball_y) {
            cpu_y -= 1;
        }
        if(cpu_y + half_paddle < ball_y) {
            cpu_y += 1;
        }
        if(cpu_y < 1) cpu_y = 1;
        if(cpu_y + PADDLE_HEIGHT > 63) cpu_y = 63 - PADDLE_HEIGHT;
        display.drawFastVLine(CPU_X, cpu_y, PADDLE_HEIGHT, RED);

        // Player paddle
        display.drawFastVLine(PLAYER_X, player_y,PADDLE_HEIGHT, BLACK);
        if(up_state) {
            player_y -= 1;
        }
        if(down_state) {
            player_y += 1;
        }
        up_state = down_state = false;
        if(player_y < 1) player_y = 1;
        if(player_y + PADDLE_HEIGHT > 63) player_y = 63 - PADDLE_HEIGHT;
        display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, GREEN);
    }
}

void drawCourt() {
  display.drawRect(0, 0, 96, 64, WHITE);
}

void gameOver()
{
  gameIsRunning = false;
  display.fillScreen(BLACK);
  drawCourt();
  if(PLAYER_SCORE>CPU_SCORE)
  {
    display.setCursor(5,4);
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.printf("You Won");
  }else
  {
    display.setCursor(5,4);
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.printf("CPU WON");
  }

  display.setCursor(20,30);
  display.setTextColor(RED);
  display.setTextSize(3);
  display.printf("%d", CPU_SCORE);

  display.setCursor(60,30);
  display.setTextColor(GREEN);
  display.setTextSize(3);
  display.printf("%d",PLAYER_SCORE);
  
  delay(2000);

  while(UP_BUTTON && DOWN_BUTTON)  
  {
    delay(100);
  }
  gameIsRunning = true;
  
  CPU_SCORE = PLAYER_SCORE = 0;
  
  unsigned long start = millis();
  
	display.Scrollstop(); // stop scroll
  delay(100);
  
	display.fillScreen(BLACK);
	drawCourt();
	while(millis() - start < 2000);
	ball_update = millis();    
	paddle_update = ball_update;
	gameIsRunning = true;
	resetBall=true;
	
	display.Scrollstop(); // stop scroll
  wait(1);
}

void showScore()
{
  gameIsRunning = false;
  display.fillScreen(BLACK);
  drawCourt();
  
  display.setCursor(15,4);
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.printf("Score");

  display.setCursor(20,30);
  display.setTextColor(RED);
  display.setTextSize(3);
  display.printf("%d",CPU_SCORE);

  display.setCursor(60,30);
  display.setTextColor(GREEN);
  display.setTextSize(3);
  display.printf("%d",PLAYER_SCORE);

	delay(2000);
	unsigned long start = millis();
	
	display.Scrollstop(); // stop scroll
  delay(100);

	display.fillScreen(BLACK);
	drawCourt();
	while(millis() - start < 2000);
	ball_update = millis();    
	paddle_update = ball_update;
	gameIsRunning = true;
	resetBall=true;
}

실행 - pulse-combined.hex


마이크로비트 공식 구입처 : 아이씨뱅큐 http://www.icbanq.com/
엘리먼트14의 특장점 - 글로벌 전자부품 유통회사, 6만원 이상 무료배송, 60만가지 재고 보유, MOQ 없음, 한글 웹사이트, 국내서비스센터 운영 (http://kr.element14.com/?CMP=DSP-ODB-KR-JAN2018-BLOG-ICBanQ1-HOMEPAGE)

마이크로비트 공식 카페 : http://cafe.naver.com/bbcmicro
아이씨뱅큐 공식 블로그 : http://blog.naver.com/icbanq

댓글
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함