diff --git a/ball.cpp b/ball.cpp new file mode 100644 index 0000000..699a83a --- /dev/null +++ b/ball.cpp @@ -0,0 +1,92 @@ +#include "ball.h" + +#include +extern Gamebuino gb; + +#include "line.h" + +uint8_t Ball::ballsize = 2; +uint8_t Ball::maxballs = 15; + +Ball::Ball(uint8_t x, uint8_t y) +: _x(x), _y(y) +{ + if (random(2)) + _vx = 1; + else + _vx = -1; + if (random(2)) + _vy = 1; + else + _vy = -1; +} + +void Ball::move(uint8_t gamex, uint8_t gamey, uint8_t gamew, uint8_t gameh) +{ + if ((_x == gamex + gamew - ballsize && _vx > 0) || (_x == gamex && _vx < 0)) + { + _vx = -_vx; + gb.sound.playTick(); + } + else + _x += _vx; + + if ((_y == gamey + gameh - ballsize && _vy > 0) || (_y == gamey && _vy < 0)) + { + _vy = -_vy; + gb.sound.playTick(); + } + else + _y += _vy; +} + +void Ball::collide(Ball &ball) +{ + if (!gb.collideRectRect(_x, _y, ballsize, ballsize, ball._x, ball._y, ballsize, ballsize)) + return; + //ball on the right + if (_vx > 0 && ball._x == _x + ballsize - 1) + { + _vx = -1; + ball._vx = 1; + } + //ball on the left + else if (_vx < 0 && _x == ball._x + ballsize - 1) + { + _vx = 1; + ball._vx = -1; + } + //ball on the top + if (_vy > 0 && ball._y == _y + ballsize - 1) + { + _vy = -1; + ball._vy = 1; + } + //ball on the bottom + else if (_vy < 0 && _y == ball._y + ballsize - 1) + { + _vy = 1; + ball._vy = -1; + } + gb.sound.playTick(); +} + +bool Ball::collide(Line &line) +{ + if (!line.collision(*this)) + return false; + + if (line.getH()) + _vy *= -1; + else + _vx *= -1; + gb.sound.playTick(); + return true; +} + + +void Ball::draw() const +{ + gb.display.fillRect(_x, _y, ballsize, ballsize); +} + diff --git a/ball.h b/ball.h new file mode 100644 index 0000000..8fa5c03 --- /dev/null +++ b/ball.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +class Line; + +class Ball { + public: + Ball(uint8_t x, uint8_t y); + + void draw() const; + + void move(uint8_t gamex, uint8_t gamey, uint8_t gamew, uint8_t gameh); + + void collide(Ball &ball); + bool collide(Line &ball); + + inline uint8_t getX() { return _x; } + inline uint8_t getY() { return _y; } + + static uint8_t ballsize; + static uint8_t maxballs; + + private: + uint8_t _x, _y; + int8_t _vx, _vy; +}; + diff --git a/board.cpp b/board.cpp new file mode 100644 index 0000000..7268969 --- /dev/null +++ b/board.cpp @@ -0,0 +1,159 @@ +#include "board.h" + +#include +extern Gamebuino gb; + +extern unsigned int level; +extern unsigned int score; +extern unsigned int levelscore; + +extern int nbboards; +extern Board **boards; + +uint8_t Board::totalballs = 0; +Ball ** Board::ballsarray = NULL; + +Board::Board(uint8_t x, uint8_t y, uint8_t w, uint8_t h) +:_x(x), _y(y), _w(w), _h(h), _nbballs(0), _balls(NULL) +{ +} + +void Board::initBalls(uint8_t nb) +{ + if (ballsarray) + clearBalls(); + + totalballs = nb; + ballsarray = (Ball **)malloc(totalballs * sizeof(Ball *)); + _nbballs = nb; + _balls = ballsarray; + memset(ballsarray, 0, sizeof(ballsarray)); + for (uint8_t i = 0 ; i < totalballs ; i++) + ballsarray[i] = new Ball(random(_w - Ball::ballsize), random(_h - Ball::ballsize)); +} + +void Board::clearBalls() +{ + if (!ballsarray) + return; + for (uint8_t i = 0 ; i < totalballs ; i++) + delete ballsarray[i]; + free(ballsarray); + ballsarray = NULL; + totalballs = 0; +} + +void Board::moveBalls() +{ + for (uint8_t i = 0 ; i < _nbballs ; i++) + { + _balls[i]->move(_x, _y, _w, _h); + + //bounce balls against each other + for (uint8_t j = i + 1 ; j < _nbballs ; j++) + _balls[i]->collide(*_balls[j]); + } +} + +Board *Board::split(Line &line) +{ + uint8_t tempnbballs = _nbballs; + + if (!line.finished()) + return; + + if (line.getH()) + { + boards[nbboards] = new Board(_x, line.getY() + 1, _w, _h + _y - line.getY() - 1); + boards[nbboards]->_balls = _balls + _nbballs; + _h = line.getY() - _y; + } + else + { + boards[nbboards] = new Board(line.getX() + 1, _y, _w + _x - line.getX() - 1, _h); + boards[nbboards]->_balls = _balls + _nbballs; + _w = line.getX() - _x; + } + _nbballs = 0; + + while (_nbballs + boards[nbboards]->_nbballs < tempnbballs) + { + if (gb.collideRectRect(_x, _y, _w, _h, _balls[_nbballs]->getX(), _balls[_nbballs]->getY(), Ball::ballsize, Ball::ballsize)) + _nbballs++; + else + { + Ball *temp = _balls[_nbballs]; + _balls[_nbballs] = _balls[tempnbballs - boards[nbboards]->_nbballs - 1]; + _balls[tempnbballs - boards[nbboards]->_nbballs - 1] = temp; + boards[nbboards]->_balls--; + boards[nbboards]->_nbballs++; + } + } + //Check for empty boards + if (boards[nbboards]->_nbballs == 0) + { + if (line.getH()) + { + uint16_t s = boards[nbboards]->_w * (boards[nbboards]->_h + 1); + score += s; + levelscore += s; + } + else + { + uint16_t s = (boards[nbboards]->_w + 1) * boards[nbboards]->_h; + score += s; + levelscore += s; + } + boards[nbboards]->_balls = NULL; + delete boards[nbboards]; + } + else if (_nbballs == 0) + { + if (line.getH()) + { + uint16_t s = _w * (_h + 1); + score += s; + levelscore += s; + } + else + { + uint16_t s = (_w + 1) * _h; + score += s; + levelscore += s; + } + _x = boards[nbboards]->_x; + _y = boards[nbboards]->_y; + _w = boards[nbboards]->_w; + _h = boards[nbboards]->_h; + _balls = boards[nbboards]->_balls; + _nbballs = boards[nbboards]->_nbballs; + boards[nbboards]->_balls = NULL; + delete boards[nbboards]; + } + else + { + if (line.getH()) + { + score += _w; + levelscore += _w; + } + else + { + score += _h; + levelscore += _h; + } + nbboards++; + } +} + +void Board::draw() const +{ + gb.display.fillRect(_x, _y, _w, _h); +} + +void Board::drawBalls() const +{ + for (uint8_t i = 0 ; i < _nbballs ; i++) + _balls[i]->draw(); +} + diff --git a/board.h b/board.h new file mode 100644 index 0000000..ea3275b --- /dev/null +++ b/board.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "ball.h" +#include "line.h" + +class Board { + public: + Board(uint8_t x, uint8_t y, uint8_t w, uint8_t h); + + inline uint8_t getX() { return _x; } + inline uint8_t getY() { return _y; } + inline uint8_t getW() { return _w; } + inline uint8_t getH() { return _h; } + inline uint8_t getNbBalls() { return _nbballs; } + inline Ball * getBall(uint8_t i) { return _balls[i]; } + + void initBalls(uint8_t nb); + static void clearBalls(); + + void moveBalls(); + + Board *split(Line &line); + + void draw() const; + void drawBalls() const; + + private: + uint8_t _x, _y, _w, _h; + Ball **_balls; + uint8_t _nbballs; + + static Ball ** ballsarray; + static uint8_t totalballs; +}; + diff --git a/cursor.cpp b/cursor.cpp new file mode 100644 index 0000000..0fada9d --- /dev/null +++ b/cursor.cpp @@ -0,0 +1,22 @@ +#include "cursor.h" + +#include +extern Gamebuino gb; + +uint8_t Cursor::cursorsize = 3; +uint8_t Cursor::gamew = LCDWIDTH - 22; +uint8_t Cursor::gameh = LCDHEIGHT; + +Cursor::Cursor() +:_x(gamew/2 - cursorsize + 1), _y(gameh/2), _horizontal(true) +{ +} + +void Cursor::draw() const +{ + if (_horizontal) + gb.display.drawFastHLine(_x - (cursorsize/2), _y, cursorsize); + else + gb.display.drawFastVLine(_x, _y - (cursorsize/2), cursorsize); +} + diff --git a/cursor.h b/cursor.h new file mode 100644 index 0000000..60ce758 --- /dev/null +++ b/cursor.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +class Cursor { + public: + Cursor(); + + void draw() const; + + uint8_t getX() const { return _x; } + uint8_t getY() const { return _y; } + bool getH() const { return _horizontal; } + + inline void up() { _y = constrain(_y - 1, 0, gameh - 1); } + inline void down() { _y = constrain(_y + 1, 0, gameh - 1); } + inline void right() { _x = constrain(_x + 1, 0, gamew - 1); } + inline void left() { _x = constrain(_x - 1, 0, gamew - 1); } + inline void rotate() { _horizontal = !_horizontal; } + + private: + uint8_t _x, _y; + bool _horizontal; + + static uint8_t gamew, gameh; + static uint8_t cursorsize; +}; + diff --git a/jezzball.ino b/jezzball.ino index b799adf..6c9aef0 100644 --- a/jezzball.ino +++ b/jezzball.ino @@ -4,55 +4,27 @@ #include Gamebuino gb; -extern const byte font5x7[]; -extern const byte font3x5[]; - -struct ball_t { - int x; - int y; - int vx; - int vy; -}; -#define MAXBALLS 15 -#define BALLSIZE 2 +#include "cursor.h" +Cursor cursor; -struct cursor_t { - int x; - int y; - bool h; -}; -cursor_t cursor; -#define CURSORSIZE 3 - -struct board_t { - int x; - int y; - int w; - int h; - ball_t **balls; - int nbballs; -}; -board_t **boards; +#include "ball.h" +#include "board.h" int nbboards; +Board **boards; -#define LINEIDLE 0 -#define LINEEXPANDING 1 +#include "line.h" +Line line; -struct line_t { - uint8_t state; - int x; - int y; - int l; - bool h; - int board; -}; -line_t line; + +extern const byte font5x7[]; +extern const byte font3x5[]; unsigned int highscore = 0; unsigned int score = 0; unsigned int lives = 5; unsigned int level = 0; unsigned int levelscore = 0; + #define BOARDWIDTH (LCDWIDTH - 22) #define BOARDHEIGHT LCDHEIGHT #define LEVELCLEAR 2300//((int)((unsigned long)(BOARDWIDTH * BOARDHEIGHT) * 75/ 100)) @@ -97,42 +69,49 @@ void preparelevel() level++; levelscore = 0; - int numballs = constrain(level, 1, MAXBALLS); - - ball_t **balls = (ball_t **)malloc(numballs * sizeof(ball_t *)); - memset(balls, 0, sizeof(balls)); - int i; - for (i = 0 ; i < numballs ; i++) - { - balls[i] = (ball_t *)malloc(sizeof(ball_t)); - *(balls[i]) = { (int)random(BOARDWIDTH) - BALLSIZE + 1, (int)random(BOARDHEIGHT) - BALLSIZE + 1, 1, 1 }; - } + int numballs = constrain(level, 1, Ball::maxballs); //each board has at least one ball //there cannot be more boards than balls - boards = (board_t **)malloc(numballs * sizeof(board_t *)); + boards = (Board **)malloc(numballs * sizeof(Board *)); nbboards = 1; memset(boards, 0, sizeof(boards)); - boards[0] = (board_t *)malloc(sizeof(board_t)); - *(boards[0]) = {0, 0, BOARDWIDTH, BOARDHEIGHT, balls, numballs}; - - cursor = { BOARDWIDTH/2 - (CURSORSIZE - 1), BOARDHEIGHT/2 }; - line = { LINEIDLE, 0, 0, 0, 0, 0}; + boards[0] = new Board(0, 0, BOARDWIDTH, BOARDHEIGHT); + boards[0]->initBalls(numballs); + line.setState(Line::LINEIDLE); } void clearlevel() { - int numballs = constrain(level, 1, MAXBALLS); - int i, j; - for (i = 0 ; i < nbboards ; i++) + for (uint8_t i = 0 ; i < nbboards ; i++) + delete boards[i]; + free(boards); + Board::clearBalls(); + line.setState(Line::LINEIDLE); +} + +unsigned char magic[3] = {42, 12, 28}; + +unsigned int get_highscore() +{ + unsigned char temp; + for (uint8_t i = 0 ; i < 3 ; i++) { - for (j = 0 ; j < boards[i]->nbballs ; j++) - free(boards[i]->balls[j]); - free(boards[i]->balls); - free(boards[i]); + EEPROM.get(i, temp); + if (magic[i] != temp) + { + for (int j = 0 ; j < 3 ; j++) + EEPROM.put(0, magic[j]); + highscore = 0; + return; + } } - free(boards); - line.state = LINEIDLE; + EEPROM.get(3, highscore); +} + +void set_highscore() +{ + EEPROM.put(3, highscore); } void setup() @@ -142,10 +121,7 @@ void setup() gb.pickRandomSeed(); gb.battery.show = false; - if (EEPROM.read(0) == 0xff) - EEPROM.put(0, 0x0000); - else - EEPROM.get(0, highscore); + get_highscore(); preparelevel(); } @@ -161,7 +137,6 @@ int numlength(int number) void drawgame() { - int i, j; gb.display.fillScreen(BLACK); //sidebar gb.display.setColor(WHITE); @@ -178,7 +153,7 @@ void drawgame() gb.display.cursorX = LCDWIDTH - 4 * numlength(score); gb.display.println(score); gb.display.cursorX = LCDWIDTH - 20; - for (i = 0 ; i < lives ; i++) + for (uint8_t i = 0 ; i < lives ; i++) gb.display.print("\03"); unsigned long percent = (unsigned long)levelscore * 100 / (BOARDWIDTH * BOARDHEIGHT); gb.display.cursorX = LCDWIDTH - 4 * (numlength(percent) + 1); @@ -188,38 +163,21 @@ void drawgame() //boards gb.display.setColor(WHITE); - for (i = 0 ; i < nbboards ; i++) - gb.display.fillRect(boards[i]->x, boards[i]->y, boards[i]->w, boards[i]->h); + for (uint8_t i = 0 ; i < nbboards ; i++) + boards[i]->draw(); + //line gb.display.setColor(BLACK); - if (line.state == LINEEXPANDING) - { - if (line.h) - { - int pos = constrain(line.x - line.l, boards[line.board]->x, boards[line.board]->x + boards[line.board]->w - 1); - int width = constrain(2 * line.l + 1, 0, boards[line.board]->w - (pos - boards[line.board]->x)); - gb.display.drawFastHLine(pos, line.y, width); - } - else - { - int pos = constrain(line.y - line.l, boards[line.board]->y, boards[line.board]->y + boards[line.board]->h - 1); - int width = constrain(2 * line.l + 1, 0, boards[line.board]->h - (pos - boards[line.board]->y)); - gb.display.drawFastVLine(line.x, pos, width); - } - } + line.draw(); + //cursor gb.display.setColor(INVERT); - if (cursor.h) - gb.display.drawFastHLine(cursor.x - (CURSORSIZE/2), cursor.y, CURSORSIZE); - else - gb.display.drawFastVLine(cursor.x, cursor.y - (CURSORSIZE/2), CURSORSIZE); + cursor.draw(); + //balls gb.display.setColor(BLACK); - for (i = 0 ; i < nbboards ; i++) - { - for (j = 0 ; j < boards[i]->nbballs ; j++) - gb.display.fillRect(boards[i]->balls[j]->x, boards[i]->balls[j]->y, BALLSIZE, BALLSIZE); - } + for (uint8_t i = 0 ; i < nbboards ; i++) + boards[i]->drawBalls(); } void drawgameover() @@ -267,38 +225,37 @@ void drawlevelclear() void inputsgame() { - if (gb.buttons.pressed(BTN_A)) - cursor.h = !cursor.h; - if (gb.buttons.pressed(BTN_B) && line.state == LINEIDLE) + if (gb.buttons.pressed(BTN_A) && line.getState() == Line::LINEIDLE) { int i; for (i = 0 ; i < nbboards ; i++) { - if (gb.collidePointRect(cursor.x, cursor.y, boards[i]->x, boards[i]->y, boards[i]->w, boards[i]->h)) + if (gb.collidePointRect(cursor.getX(), cursor.getY(), boards[i]->getX(), boards[i]->getY(), boards[i]->getW(), boards[i]->getH())) + { - line.state = LINEEXPANDING; - line.x = cursor.x; - line.y = cursor.y; - line.l = 0; - line.h = cursor.h; - line.board = i; + if (cursor.getH()) + line.start(cursor.getX(), cursor.getY(), true, i); + else + line.start(cursor.getX(), cursor.getY(), false, i); break; } } } + + if (gb.buttons.pressed(BTN_B)) + cursor.rotate(); + if(gb.buttons.pressed(BTN_C)) gb.titleScreen(F(""), logo); + if (gb.buttons.repeat(BTN_UP, 1)) - cursor.y -= 1; + cursor.up(); else if (gb.buttons.repeat(BTN_DOWN, 1)) - cursor.y += 1; + cursor.down(); if (gb.buttons.repeat(BTN_LEFT, 1)) - cursor.x -= 1; + cursor.left(); else if (gb.buttons.repeat(BTN_RIGHT, 1)) - cursor.x += 1; - - cursor.x = constrain(cursor.x, 0, BOARDWIDTH - 1); - cursor.y = constrain(cursor.y, 0, BOARDHEIGHT - 1); + cursor.right(); } void inputsgameover() @@ -308,7 +265,7 @@ void inputsgameover() if (score > highscore) { highscore = score; - EEPROM.put(0, highscore); + set_highscore(); } score = 0; level = 0; @@ -333,209 +290,35 @@ void inputslevelclear() void updategame() { - int i, j, k; - ball_t *ball, *ball2; - //move balls - for (i = 0 ; i < nbboards ; i++) - { - for (j = 0 ; j < boards[i]->nbballs ; j++) - { - ball = boards[i]->balls[j]; - ball->x = ball->x + ball->vx; - ball->y = ball->y + ball->vy; - - //bouncings with board - bool bounced = false; - if (ball->x < boards[i]->x) - { - ball->vx = -ball->vx; - bounced = true; - gb.sound.playTick(); - } - else if ((ball->x + BALLSIZE) > boards[i]->x + boards[i]->w) - { - ball->vx = -ball->vx; - bounced = true; - gb.sound.playTick(); - } - if (ball->y < boards[i]->y) - { - ball->vy = -ball->vy; - bounced = true; - gb.sound.playTick(); - } - else if ((ball->y + BALLSIZE) > boards[i]->y + boards[i]->h) - { - ball->vy = -ball->vy; - bounced = true; - gb.sound.playTick(); - } - //we do not bounce if against a wall - if (!bounced) - { - for (k = j+1 ; k < boards[i]->nbballs ; k++) - { - ball2 = boards[i]->balls[k]; - if (!gb.collideRectRect(ball->x, ball->y, BALLSIZE, BALLSIZE, ball2->x, ball2->y, BALLSIZE, BALLSIZE)) - continue; - //ball on the right - if (ball->vx > 0 && ball2->x == ball->x + BALLSIZE - 1) - { - ball->vx = -1; - ball2->vx = 1; - } - //ball on the left - else if (ball->vx < 0 && ball->x == ball2->x + BALLSIZE - 1) - { - ball->vx = 1; - ball2->vx = -1; - } - //ball on the top - if (ball->vy > 0 && ball2->y == ball->y + BALLSIZE - 1) - { - ball->vy = -1; - ball2->vy = 1; - } - //ball on the bottom - else if (ball->vy < 0 && ball->y == ball2->y + BALLSIZE - 1) - { - ball->vy = 1; - ball2->vy = -1; - } - } - } - } - } + for (uint8_t i = 0 ; i < nbboards ; i++) + boards[i]->moveBalls(); - if (line.state == LINEEXPANDING) + if (line.getState() == Line::LINEEXPANDING) { - line.l++; + line.grow(); //check collision with a ball - int i; - for (i = 0 ; i < boards[line.board]->nbballs ; i++) + for (uint8_t i = 0 ; i < boards[line.getBoard()]->getNbBalls() ; i++) { - if ((line.h && gb.collideRectRect(line.x - line.l, line.y, 2 * line.l + 1, 1, boards[line.board]->balls[i]->x, boards[line.board]->balls[i]->y, BALLSIZE, BALLSIZE)) || - (!line.h && gb.collideRectRect(line.x, line.y - line.l, 1, 2 * line.l + 1, boards[line.board]->balls[i]->x, boards[line.board]->balls[i]->y, BALLSIZE, BALLSIZE))) + if (boards[line.getBoard()]->getBall(i)->collide(line)) { - if (line.h) - boards[line.board]->balls[i]->vy *= -1; - else - boards[line.board]->balls[i]->vx *= -1; lives--; - line.state = LINEIDLE; + line.setState(Line::LINEIDLE); return; } } - ball_t **tempballs = boards[line.board]->balls; - int tempnbballs = boards[line.board]->nbballs; - board_t *newboard; - int numballs = constrain(level, 1, MAXBALLS); - - //finished horizontal line - if (line.h && line.x - line.l <= boards[line.board]->x && line.x + line.l >= boards[line.board]->x + boards[line.board]->w) + if (line.finished()) { - newboard = (board_t *)malloc(sizeof(board_t)); - newboard->x = boards[line.board]->x; - newboard->y = line.y + 1; - newboard->w = boards[line.board]->w; - newboard->h = boards[line.board]->h + boards[line.board]->y - line.y - 1; - newboard->balls = (ball_t **)malloc(numballs * sizeof(ball_t *)); - newboard->nbballs = 0; - - boards[line.board]->x = boards[line.board]->x; - boards[line.board]->y = boards[line.board]->y; - boards[line.board]->w = boards[line.board]->w; - boards[line.board]->h = line.y - boards[line.board]->y; - boards[line.board]->balls = (ball_t **)malloc(numballs * sizeof(ball_t *)); - boards[line.board]->nbballs = 0; - } - //finished vertical line - else if (!line.h && line.y - line.l <= boards[line.board]->y && line.y + line.l >= boards[line.board]->y + boards[line.board]->h) - { - newboard = (board_t *)malloc(sizeof(board_t)); - newboard->x = line.x + 1; - newboard->y = boards[line.board]->y; - newboard->w = boards[line.board]->w + boards[line.board]->x - line.x - 1; - newboard->h = boards[line.board]->h; - newboard->balls = (ball_t **)malloc(numballs * sizeof(ball_t *)); - newboard->nbballs = 0; - - boards[line.board]->x = boards[line.board]->x; - boards[line.board]->y = boards[line.board]->y; - boards[line.board]->w = line.x - boards[line.board]->x; - boards[line.board]->h = boards[line.board]->h; - boards[line.board]->balls = (ball_t **)malloc(numballs * sizeof(ball_t *)); - boards[line.board]->nbballs = 0; - } - //line not finished - else - return; - - for (i = 0 ; i < tempnbballs ; i++) - { - if (gb.collideRectRect(boards[line.board]->x, boards[line.board]->y, boards[line.board]->w, boards[line.board]->h, - tempballs[i]->x, tempballs[i]->y, BALLSIZE, BALLSIZE)) - { - boards[line.board]->balls[boards[line.board]->nbballs] = tempballs[i]; - boards[line.board]->nbballs++; - } - else - { - newboard->balls[newboard->nbballs] = tempballs[i]; - newboard->nbballs++; - } - } - free(tempballs); - if (newboard->nbballs == 0) - { - if (line.h) + Board *newboard = boards[line.getBoard()]->split(line); + + if (newboard) { - score += newboard->w * (newboard->h + 1); - levelscore += newboard->w * (newboard->h + 1); + boards[nbboards] = newboard; + nbboards++; } - else - { - score += (newboard->w + 1) * newboard->h; - levelscore += (newboard->w + 1) * newboard->h; - } - free(newboard->balls); - free(newboard); + line.setState(Line::LINEIDLE); } - else if (boards[line.board]->nbballs == 0) - { - if (line.h) - { - score += boards[line.board]->w * (boards[line.board]->h + 1); - levelscore += boards[line.board]->w * (boards[line.board]->h + 1); - } - else - { - score += (boards[line.board]->w + 1) * boards[line.board]->h; - levelscore += (boards[line.board]->w + 1) * boards[line.board]->h; - } - free(boards[line.board]->balls); - free(boards[line.board]); - boards[line.board] = newboard; - } - else - { - if (line.h) - { - score += boards[line.board]->w; - levelscore += boards[line.board]->w; - } - else - { - score += boards[line.board]->h; - levelscore += boards[line.board]->h; - } - boards[nbboards] = newboard; - nbboards++; - } - - line.state = LINEIDLE; } } diff --git a/line.cpp b/line.cpp new file mode 100644 index 0000000..637c3af --- /dev/null +++ b/line.cpp @@ -0,0 +1,72 @@ +#include "line.h" + +#include +extern Gamebuino gb; + +#include "board.h" +extern int nbboards; +extern Board **boards; + +Line::Line() +: _x(0), _y(0), _l(0), _h(true), _board(0) +{ +} + +void Line::start(uint8_t x, uint8_t y, uint8_t h, uint8_t board) +{ + _x = x; + _y = y; + _h = h; + _l = 0; + _board = board; + _state = LINEEXPANDING; +} + +bool Line::collision(Ball &ball) +{ + if (_h) + { + uint8_t min = boards[_board]->getX(); + uint8_t max = boards[_board]->getX() + boards[_board]->getW() - 1; + int pos = constrain(_x - _l, min, max); + int length = constrain(2 * _l + 1, 0, max - min); + return gb.collideRectRect(pos, _y, length, 1, ball.getX(), ball.getY(), Ball::ballsize, Ball::ballsize); + } + else + { + uint8_t min = boards[_board]->getY(); + uint8_t max = boards[_board]->getY() + boards[_board]->getH() - 1; + int pos = constrain(_y - _l, min, max); + int length = constrain(2 * _l + 1, 0, max - min); + return gb.collideRectRect(_x, pos, 1, length, ball.getX(), ball.getY(), Ball::ballsize, Ball::ballsize); + } +} + +bool Line::finished() +{ + Board *b = boards[_board]; + return ((_h && _x - _l <= b->getX() && _x + _l >= b->getX() + b->getW()) || (!_h && _y - _l <= b->getY() && _y + _l >= b->getY() + b->getH())); +} + +void Line::draw() const +{ + if (_state == LINEIDLE) + return; + if (_h) + { + uint8_t min = boards[_board]->getX(); + uint8_t max = boards[_board]->getX() + boards[_board]->getW() - 1; + int pos = constrain(_x - _l, min, max); + int length = constrain(2 * _l + 1, 0, max - min); + gb.display.drawFastHLine(pos, _y, length); + } + else + { + uint8_t min = boards[_board]->getY(); + uint8_t max = boards[_board]->getY() + boards[_board]->getH() - 1; + int pos = constrain(_y - _l, min, max); + int length = constrain(2 * _l + 1, 0, max - min); + gb.display.drawFastVLine(_x, pos, length); + } +} + diff --git a/line.h b/line.h new file mode 100644 index 0000000..bada85c --- /dev/null +++ b/line.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +class Ball; + +class Line { + public: + enum line_state { + LINEIDLE, + LINEEXPANDING + }; + + Line(); + + void draw() const; + + void start(uint8_t x, uint8_t y, uint8_t h, uint8_t board); + + inline void grow() { _l++; } + + bool finished(); + + bool collision(Ball &ball); + + inline line_state getState () { return _state; } + inline void setState(line_state s) { _state = s; } + + inline uint8_t getBoard() { return _board; } + inline bool getH() { return _h; } + inline uint8_t getX() { return _x; } + inline uint8_t getY() { return _y; } + + private: + line_state _state; + uint8_t _x, _y, _l; + bool _h; + uint8_t _board; +}; +