#include #include #include #include "font.h" //some useful colors #define BLACK 0x0000 #define WHITE 0xFFFF #define BLUE 0xEE00 #define CYAN 0xFF00 #define GREEN 0x0EE0 #define RED 0x00FF #define MAGENTA 0xF00F #define BROWN 0x0D0D //defines for the video system unsigned short* videoBuffer = (unsigned short*)0x6000000; #define DISPLAY_CONTROLLER *(unsigned long*)0x4000000 #define VIDC_BASE_HALF ((volatile unsigned short int*) 0x04000000) #define VCOUNT (VIDC_BASE_HALF[3]) //pointer to the button interface volatile unsigned int *BUTTONS = (volatile unsigned int *)0x04000130; #define VIDEO_MODE_3 0x3 #define BACKGROUND2 0x400 #define SCREEN_W 240 #define SCREEN_H 160 //game constants #define BALL_SIZE 3 #define PADDLE_WIDTH 30 #define PADDLE_HEIGHT 8 #define PADDLE_SPEED 4 #define BLOCK_WIDTH 20 #define BLOCK_HEIGHT 10 //global variables int paddleX = 120; int paddleY = 150; int ballX = 120, ballY = 139; int velX = 2, velY = -1; int score = 0; int lives = 5; int play = 1; int blocks[10][6]; void setMode(int mode) { DISPLAY_CONTROLLER = mode | BACKGROUND2; } inline void drawPixel(int x, int y, unsigned short color) { videoBuffer[y * 240 + x] = color; } inline unsigned short getpixel(int x, int y) { return videoBuffer[y * 240 + x]; } int buttonPressed(int button) { //see if UP button is pressed if (!((*BUTTONS) & button)) return 1; else return 0; } //draw text using characters contained in font.h void print(int left, int top, char *str, unsigned short color) { int x, y, draw; int pos = 0; char letter; //look at all characters in this string while (*str) { //get current character ASCII code letter = (*str++) - 32; //draw the character for(y = 0; y < 8; y++) for(x = 0; x < 8; x++) { //grab a pixel from the font character draw = font[letter * 64 + y * 8 + x]; //if pixel = 1, then draw it if (draw) drawPixel(left + pos + x, top + y, color); } //jump over 8 pixels pos += 8; } } void drawbox(int left, int top, int right, int bottom, unsigned short color) { int x = left, y; for (y = top; y < bottom; y++) { for (x = left; x < right; x++) drawPixel(x, y, color); } } void printScore() { //display score char s[5]; sprintf(s,"%i",score); print(5,1,s,WHITE); } void printLives() { //display lives char s[6]; sprintf(s,"%i",lives); print(219,1,s,WHITE); } void eraseScore() { drawbox(0,0,24,9,BLACK); } void eraseLives() { drawbox(210,0,240,9,BLACK); } void updateBall() { if (ballX < 1 || ballX > SCREEN_W - BALL_SIZE - 1) { velX *= -1; } if (ballY < 9) { velY *= -1; } if (ballY > SCREEN_H - BALL_SIZE - 1) { ballY = paddleY - 40; eraseLives(); lives = lives - 1; velY = -1; } ballX += velX; ballY += velY; } void drawBall() { drawbox(ballX, ballY, ballX + BALL_SIZE, ballY + BALL_SIZE, RED); } void eraseBall() { drawbox(ballX, ballY, ballX + BALL_SIZE, ballY + BALL_SIZE, BLACK); } void drawBlock(int row, int col, int color) { int startx,starty; startx = 10 + row * (BLOCK_WIDTH+2); starty = 20 + col * (BLOCK_HEIGHT+2); drawbox(startx, starty, startx + BLOCK_WIDTH, starty + BLOCK_HEIGHT, color); } void drawBlocks() { int x,y; for (y = 0; y < 6; y++) { for (x = 0; x < 10; x++) { //is this block still visible? if (blocks[x][y] == 1) { drawBlock(x,y, GREEN); } } } } void drawPaddle() { drawbox(paddleX, paddleY, paddleX + PADDLE_WIDTH, paddleY + PADDLE_HEIGHT, WHITE); } void erasePaddle() { drawbox(paddleX-4, paddleY, paddleX + PADDLE_WIDTH+4, paddleY + PADDLE_HEIGHT, BLACK); } void updatePaddle() { //check for LEFT button press if (buttonPressed(32)) { if (paddleX > 1) paddleX -= PADDLE_SPEED; } //check for RIGHT button press if (buttonPressed(16)) { if (paddleX < SCREEN_W - PADDLE_WIDTH - 2) paddleX += PADDLE_SPEED; } } int inside(int x,int y, int left, int top, int right, int bottom) { return (x > left && x < right && y > top && y < bottom); } void testPaddleCollision() { int x1 = paddleX; int y1 = paddleY; int x2 = paddleX + PADDLE_WIDTH; int y2 = paddleY + PADDLE_HEIGHT; int bx = ballX + BALL_SIZE/2; int by = ballY + BALL_SIZE/2; if (inside(bx,by,x1,y1,x2,y2)) { velY *= -1; ballY += velY; } } void testBlockCollisions() { int x,y,x1,y1,x2,y2,bx,by; for (y = 0; y < 6; y++) { for (x = 0; x < 10; x++) { if (blocks[x][y] == 1) { x1 = 10 + x * (BLOCK_WIDTH+2); y1 = 20 + y * (BLOCK_HEIGHT+2); x2 = x1 + BLOCK_WIDTH; y2 = y1 + BLOCK_HEIGHT; bx = ballX + BALL_SIZE/2; by = ballY + BALL_SIZE/2; if (inside(bx, by, x1, y1, x2, y2)) { eraseScore(); score++; drawBlock(x,y,BLACK); blocks[x][y] = 0; eraseBall(); velY *= -1; ballY += velY; } } } } } int endProgram() { return 0; } void waitRetrace() { while (VCOUNT != 160); while (VCOUNT == 160); } void clearScreen() { drawbox(0,0,239,159,0x0000); } void eraseText() { drawbox(0,0,SCREEN_W-1,SCREEN_H-1,BLACK); } void resetGame() { if(score == 60 || lives <=0) { clearScreen(); print(SCREEN_W/2-32,SCREEN_H/2,"WOULD YOU LIKE",WHITE); print(SCREEN_W/2-32,SCREEN_H/2 + 10,"TO PLAY AGAIN?",WHITE); print(SCREEN_W/2-32,SCREEN_H/2 + 20,"(UP = Y DOWN = N)",WHITE); while(play == 1) { //check for UP button Press if (buttonPressed(64)) { clearScreen(); play = 0; } //check for DOWN button Press if(buttonPressed(128)) { clearScreen(); } } } } void drawScreen() { drawBall(); drawPaddle(); drawBlocks(); } void updateScreen() { updateBall(); updatePaddle(); } int main(void) { //init video mode 3 (240x160) setMode(VIDEO_MODE_3); //turn on the blocks so they are all visible int x,y; for (y = 0; y < 6; y++) { for (x = 0; x < 10; x++) { blocks[x][y] = 1; } } //display title print(SCREEN_W/2-32,1,"BREAKOUT", BLUE); //game loop while(play == 1) { waitRetrace(); eraseBall(); erasePaddle(); updateScreen(); drawScreen(); testBlockCollisions(); testPaddleCollision(); printScore(); printLives(); resetGame(); } return 0; }