diff --git a/DinoGame/DinoGame.xml b/DinoGame/DinoGame.xml new file mode 100644 index 0000000..4829f5d --- /dev/null +++ b/DinoGame/DinoGame.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DinoGame/README.md b/DinoGame/README.md new file mode 100644 index 0000000..624c200 --- /dev/null +++ b/DinoGame/README.md @@ -0,0 +1,3 @@ +# Mixly_DinoGame + +![Preview](./preview.png) diff --git a/DinoGame/block/dino_game.js b/DinoGame/block/dino_game.js new file mode 100644 index 0000000..0f100cf --- /dev/null +++ b/DinoGame/block/dino_game.js @@ -0,0 +1,79 @@ +;(() => { + // + Blockly.Blocks.dino_game_setup = { + init: function () { + this.appendDummyInput() + .appendField('DinoGame初始化, 选择u8g2实例:') + .appendField(new Blockly.FieldTextInput('u8g2'), 'oled') + + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(345) + this.setTooltip('Dino') + this.setHelpUrl('Dino') + }, + } + + Blockly.Blocks.dino_game_loop = { + init: function () { + this.appendDummyInput().appendField('DinoGame循环执行命令') + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(345) + this.setTooltip('Dino') + this.setHelpUrl('Dino') + }, + } + + Blockly.Blocks.dino_game_start_game = { + init: function () { + this.appendDummyInput().appendField('DinoGame开始游戏') + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(345) + this.setTooltip('Dino') + this.setHelpUrl('Dino') + }, + } + + Blockly.Blocks.dino_game_dino_jump = { + init: function () { + this.appendDummyInput().appendField('DinoGame恐龙跳跃') + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(345) + this.setTooltip('Dino') + this.setHelpUrl('Dino') + }, + } + + Blockly.Blocks.dino_game_set_cheat = { + init: function () { + this.appendDummyInput() + .appendField('是否开启作弊') + .appendField( + new Blockly.FieldDropdown([ + ['开启', 'CHEAT_MODE_CHEAT'], + ['关闭', 'CHEAT_MODE_NORMAL'], + ]), + 'isCheat' + ) + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(345) + this.setTooltip('Dino') + this.setHelpUrl('Dino') + }, + } + + Blockly.Blocks.dino_game_show_ultraman = { + init: function () { + this.appendDummyInput().appendField('DinoGame显示奥特曼') + this.setPreviousStatement(true, null) + this.setNextStatement(true, null) + this.setColour(345) + this.setTooltip('Dino') + this.setHelpUrl('Dino') + }, + } +})() diff --git a/DinoGame/config.json b/DinoGame/config.json new file mode 100644 index 0000000..dfba51c --- /dev/null +++ b/DinoGame/config.json @@ -0,0 +1,3 @@ +{ + "version": "0.1.0" +} \ No newline at end of file diff --git a/DinoGame/generator/dino_game.js b/DinoGame/generator/dino_game.js new file mode 100644 index 0000000..2e47e6f --- /dev/null +++ b/DinoGame/generator/dino_game.js @@ -0,0 +1,37 @@ +;(() => { + // + Blockly.Arduino.forBlock.dino_game_setup = function () { + var oled = this.getFieldValue('oled') + Blockly.Arduino.definitions_[ + 'header' + ] = `#include "dino_game_arduino.h"\nDinoGameArduino dinoGameArduino(&${oled});` + Blockly.Arduino.setups_['setup'] = 'dinoGameArduino.setup();' + var code = '' + return code + } + + Blockly.Arduino.forBlock.dino_game_loop = function () { + var code = 'dinoGameArduino.loop();' + return code + } + + Blockly.Arduino.forBlock.dino_game_start_game = function () { + var code = 'dinoGameArduino.startGame();' + return code + } + + Blockly.Arduino.forBlock.dino_game_dino_jump = function () { + var code = 'dinoGameArduino.dinoJump();' + return code + } + Blockly.Arduino.forBlock.dino_game_set_cheat = function () { + var dropdown_isCheat = this.getFieldValue('isCheat') + var code = `dinoGameArduino.setCheatMode(${dropdown_isCheat});` + return code + } + + Blockly.Arduino.forBlock.dino_game_show_ultraman = function () { + var code = 'dinoGameArduino.showUltraman();' + return code + } +})() diff --git a/DinoGame/libraries/dino_game/dino_game.cpp b/DinoGame/libraries/dino_game/dino_game.cpp new file mode 100644 index 0000000..0245788 --- /dev/null +++ b/DinoGame/libraries/dino_game/dino_game.cpp @@ -0,0 +1,272 @@ +#include +#include "dino_game.h" + +#define dino_min(a, b) ((a) < (b) ? (a) : (b)) + +// public +DinoGame::DinoGame( + int stageWidth, + int stageHeight, unsigned long (*systemCurrentTimeFunc)(), + long (*randomFunc)(long, long)) +{ + _stageWidth = stageWidth; + _stageHeight = stageHeight; + + _cheatMode = CHEAT_MODE_NORMAL; + + if (systemCurrentTimeFunc == nullptr) + { + printf("error: systemCurrentTimeFunc is null \n"); + } + if (randomFunc == nullptr) + { + printf("error: randomFunc is null \n"); + } + + _systemCurrentTimeFunc = systemCurrentTimeFunc; + _randomFunc = randomFunc; +} + +DinoGame::~DinoGame() +{ +} + +void DinoGame::setup() +{ + resetGame(); + splashStage(); +} + +void DinoGame::loop() +{ + if (_gameStatus == GAME_PLAYING_STATUS) + { + moveObstacles(); + moveDino(); + checkCollision(); + calLevel(); + } +} + +void DinoGame::startGame() +{ + if (_gameStatus != GAME_PLAYING_STATUS) + { + _gameStatus = GAME_PLAYING_STATUS; + resetGame(); + } +} + +void DinoGame::setCheatMode(CheatMode mode) +{ + _cheatMode = mode; +} + +Dino *DinoGame::getDino() +{ + return &_dino; +} + +Obstacle *DinoGame::getObstacleReal() +{ + return &_obstacleReal; +} + +Obstacle *DinoGame::getObstacleBackup() +{ + return &_obstacleBackup; +} + +DinoGameStatus DinoGame::getGameStatus() +{ + return _gameStatus; +} + +unsigned int DinoGame::getScore() +{ + return _score; +} + +unsigned int DinoGame::getLevel() +{ + return _level; +} + +void DinoGame::dinoJump() +{ + if (_dino.action == DINO_WALKING || _cheatMode == CHEAT_MODE_CHEAT) + { + _dino.action = DINO_JUMPING; + } +} + +// protected + +void DinoGame::resetGame() +{ + _score = 0; + _speed = 2; + _level = 1; + + _startTime = _systemCurrentTimeFunc(); + + _dino.action = DINO_WALKING; + _dino.pose = DINO_JUMP; + _dino.frame.size.width = 20; + _dino.frame.size.height = 21; + _dino.frame.postion.x = 0; + _dino.frame.postion.y = _stageHeight - _dino.frame.size.height; + _dino.frame.offset.x = 0; + _dino.frame.offset.y = 0; + + _obstacleReal = getRandomObstacle(); + _obstacleReal.frame.postion.x = _stageWidth; + _obstacleBackup = getRandomObstacle(8); + _obstacleBackup.frame.postion.x = _stageWidth * 2; +} + +void DinoGame::splashStage() +{ + _obstacleReal = getRandomObstacle(0); + _obstacleReal.frame.postion.x = _stageWidth * 0.4; + + _obstacleBackup = getRandomObstacle(); + _obstacleBackup.frame.postion.x = _stageWidth * 0.7; +} + +void DinoGame::calLevel() +{ + _currentTime = _systemCurrentTimeFunc(); + + if (_score >= 5 * (_speed - 1)) + { + _speed++; + _level++; + } +} + +void DinoGame::checkCollision() +{ + if (((_obstacleReal.category != OBSTACLE_BIRD && _dino.frame.offset.y < _obstacleReal.hitZone.size.height - 3) || + (_obstacleReal.category == OBSTACLE_BIRD && _dino.frame.offset.y > 5 && _dino.frame.offset.y < _obstacleReal.hitZone.postion.y)) && + (_obstacleReal.hitZone.postion.x < 13 && _obstacleReal.hitZone.postion.x + _obstacleReal.hitZone.size.width > 5)) + { + _gameStatus = GAME_OVER_STATUS; + } +} + +void DinoGame::moveDino() +{ + if (_dino.action == DINO_WALKING) + { + _dino.frame.offset.y = (_dino.frame.offset.y + 1) % 3; + _dino.pose = (DinoPose)(_dino.frame.offset.y + 1); + } + else + { + _dino.pose = DINO_JUMP; + if (_dino.action == DINO_JUMPING) + { + _dino.frame.offset.y = _dino.frame.offset.y + _speed; + if (_dino.frame.offset.y > 32) + { + _dino.action = DINO_FALLING; + } + } + else + { + _dino.frame.offset.y = _dino.frame.offset.y - _speed; + if (_dino.frame.offset.y < 8) + { + _dino.action = DINO_WALKING; + _dino.frame.offset.y = 0; + } + } + } +} + +void DinoGame::moveObstacles() +{ + int newX = _obstacleReal.frame.postion.x - _speed; + + if (newX < -_obstacleReal.frame.size.width) + { + _score = _score + 1; + _obstacleReal = _obstacleBackup; + _obstacleBackup = getRandomObstacle(8); + _obstacleBackup.frame.postion.x = _obstacleReal.frame.postion.x + _randomFunc(_stageWidth * 0.8, _stageWidth); + } + else + { + _obstacleReal.frame.postion.x = newX; + _obstacleBackup.frame.postion.x -= _speed; + } + + _obstacleReal.hitZone.postion = _obstacleReal.frame.postion; + _obstacleBackup.hitZone.postion = _obstacleBackup.frame.postion; +} + +Obstacle DinoGame::getRandomObstacle(int max) +{ + int rand = _randomFunc(0, max); + Obstacle obstacle; + switch (rand) + { + case 1: + obstacle.category = OBSTACLE_ONE_CACTUS; + obstacle.frame.size.width = 10; + obstacle.frame.size.height = 20; + obstacle.frame.postion.x = 200; + obstacle.frame.postion.y = _stageHeight - obstacle.frame.size.height; + break; + case 2: + obstacle.category = OBSTACLE_TWO_CACTUS; + obstacle.frame.size.width = 20; + obstacle.frame.size.height = 20; + obstacle.frame.postion.x = 200; + obstacle.frame.postion.y = _stageHeight - obstacle.frame.size.height; + break; + case 3: + obstacle.category = OBSTACLE_THREE_CACTUS; + obstacle.frame.size.width = 20; + obstacle.frame.size.height = 20; + obstacle.frame.postion.x = 200; + obstacle.frame.postion.y = _stageHeight - obstacle.frame.size.height; + break; + case 4: + obstacle.category = OBSTACLE_ONE_SMALL_CACTUS; + obstacle.frame.size.width = 6; + obstacle.frame.size.height = 12; + obstacle.frame.postion.x = 200; + obstacle.frame.postion.y = _stageHeight - obstacle.frame.size.height; + break; + case 5: + obstacle.category = OBSTACLE_TWO_SMALL_CACTUS; + obstacle.frame.size.width = 12; + obstacle.frame.size.height = 12; + obstacle.frame.postion.x = 200; + obstacle.frame.postion.y = _stageHeight - obstacle.frame.size.height; + break; + case 6: + obstacle.category = OBSTACLE_THREE_SMALL_CACTUS; + obstacle.frame.size.width = 17; + obstacle.frame.size.height = 12; + obstacle.frame.postion.x = 200; + obstacle.frame.postion.y = _stageHeight - obstacle.frame.size.height; + break; + case 0: + default: + obstacle.category = OBSTACLE_BIRD; + obstacle.frame.size.width = 21; + obstacle.frame.size.height = 18; + obstacle.frame.postion.x = 200; + obstacle.frame.postion.y = _stageHeight - obstacle.frame.size.height - _dino.frame.size.height - 3; + break; + } + + obstacle.hitZone = obstacle.frame; + obstacle.hitZone.size.width = dino_min(obstacle.hitZone.size.width, 17); + return obstacle; +} + +// private \ No newline at end of file diff --git a/DinoGame/libraries/dino_game/dino_game.h b/DinoGame/libraries/dino_game/dino_game.h new file mode 100644 index 0000000..e7d1870 --- /dev/null +++ b/DinoGame/libraries/dino_game/dino_game.h @@ -0,0 +1,140 @@ +#ifndef __DINO_GAME_H_ +#define __DINO_GAME_H_ + +typedef struct +{ + int x; + int y; +} Position; + +typedef struct +{ + int x; + int y; +} Offset; + +typedef struct +{ + int width; + int height; +} Size; + +typedef struct +{ + Position postion; + Offset offset; + Size size; +} Frame; + +typedef struct +{ + Frame frame; +} Object; + +typedef enum +{ + OBSTACLE_BIRD = 0, + OBSTACLE_ONE_CACTUS = 1, + OBSTACLE_TWO_CACTUS = 2, + OBSTACLE_THREE_CACTUS = 3, + OBSTACLE_ONE_SMALL_CACTUS = 4, + OBSTACLE_TWO_SMALL_CACTUS = 5, + OBSTACLE_THREE_SMALL_CACTUS = 6, +} ObstacleCategory; + +struct Obstacle : public Object +{ + Frame hitZone; + ObstacleCategory category; +}; + +typedef enum +{ + GAME_WAITING_STATUS = 0, + GAME_PLAYING_STATUS = 1, + GAME_OVER_STATUS = 2, +} DinoGameStatus; + +typedef enum +{ + DINO_WALKING = 0, + DINO_JUMPING = 1, + DINO_FALLING = 2, +} DinoAction; + +typedef enum +{ + DINO_BLAH = 0, + DINO_JUMP = 1, + DINO_LEFT = 2, + DINO_RIGHT = 3, +} DinoPose; + +struct Dino : public Object +{ + DinoAction action; + DinoPose pose; +}; + +typedef enum +{ + CHEAT_MODE_NORMAL = 0, + CHEAT_MODE_CHEAT = 1, +} CheatMode; + +class DinoGame +{ +public: + DinoGame( + int stageWidth, + int stageHeight, + unsigned long (*systemCurrentTimeFunc)(), + long (*randomFunc)(long, long)); + virtual ~DinoGame(); + + void setup(); + void loop(); + + void setCheatMode(CheatMode mode); + + DinoGameStatus getGameStatus(); + Dino *getDino(); + Obstacle *getObstacleReal(); + Obstacle *getObstacleBackup(); + + unsigned int getScore(); + unsigned int getLevel(); + void startGame(); + void dinoJump(); + +protected: + int _stageWidth; + int _stageHeight; + + DinoGameStatus _gameStatus; + unsigned long _startTime; + unsigned long _currentTime; + + unsigned int _speed; + unsigned int _level; + unsigned int _score; + + CheatMode _cheatMode; + + Dino _dino; + Obstacle _obstacleReal; + Obstacle _obstacleBackup; + + Obstacle getRandomObstacle(int max=6); + void calLevel(); + void resetGame(); + void splashStage(); + void checkCollision(); + void moveDino(); + void moveObstacles(); + + unsigned long (*_systemCurrentTimeFunc)(); + long (*_randomFunc)(long, long); +}; + +#endif // !__DINO_GAME_H_ \ No newline at end of file diff --git a/DinoGame/libraries/dino_game/dino_game_arduino.cpp b/DinoGame/libraries/dino_game/dino_game_arduino.cpp new file mode 100644 index 0000000..e2a7f72 --- /dev/null +++ b/DinoGame/libraries/dino_game/dino_game_arduino.cpp @@ -0,0 +1,293 @@ +#include "dino_game_arduino.h" + +unsigned int getObstacleImageAddress(Obstacle *obstacle) +{ + unsigned int obstacleImageAddress; + + switch (obstacle->category) + { + case OBSTACLE_ONE_CACTUS: + obstacleImageAddress = reinterpret_cast(oneCactusImg); + break; + case OBSTACLE_TWO_CACTUS: + obstacleImageAddress = reinterpret_cast(twoCactusImg); + break; + case OBSTACLE_THREE_CACTUS: + obstacleImageAddress = reinterpret_cast(threeCactusImg); + break; + case OBSTACLE_ONE_SMALL_CACTUS: + obstacleImageAddress = reinterpret_cast(oneSmallCactusImg); + break; + case OBSTACLE_TWO_SMALL_CACTUS: + obstacleImageAddress = reinterpret_cast(twoSmallCactusImg); + break; + case OBSTACLE_THREE_SMALL_CACTUS: + obstacleImageAddress = reinterpret_cast(threeSmallCactusImg); + break; + case OBSTACLE_BIRD: + default: + obstacleImageAddress = reinterpret_cast(obstacle->frame.postion.x % 20 > 10 ? birdUpImg : birdDownImg); + break; + } + + return obstacleImageAddress; +} + +// public +DinoGameArduino::DinoGameArduino(U8G2 *u8g2) + : _u8g2(u8g2), + _dinoGame(_u8g2->getWidth(), _u8g2->getHeight(), millis, random) +{ +} + +DinoGameArduino::~DinoGameArduino() +{ +} + +void DinoGameArduino::setup() +{ + _u8g2->begin(); + _u8g2->setFont(u8g2_font_timR08_tf); + _u8g2->setFontMode(1); + _u8g2->setBitmapMode(1); + _u8g2->setFontPosTop(); + _u8g2->enableUTF8Print(); + + _dinoGame.setup(); + delay(300); +} + +void DinoGameArduino::loop() +{ + _u8g2->firstPage(); + do + { + drawDino(); + drawObstacleReal(); + drawObstacleBackup(); + drawCloud(); + + if (_cheatMode == CHEAT_MODE_CHEAT) + { + _u8g2->setFont(u8g2_font_timR08_tf); + _u8g2->setCursor(_cloud.frame.postion.x, 12); + _u8g2->print("c"); + } + + if (_showUltraman == 1) + { + _u8g2->drawXBMP( + _dinoGame.getDino()->frame.postion.x, + _dinoGame.getDino()->frame.postion.y - _dinoGame.getDino()->frame.offset.y - 58 + _dinoGame.getDino()->frame.size.height, + 20, + 58, + ultramanImg); + } + + if (_dinoGame.getGameStatus() == GAME_WAITING_STATUS) + { + _u8g2->setFont(u8g2_font_timR12_tf); + char title[] = "= Dino Game ="; + _u8g2->setCursor((_u8g2->getWidth() - (sizeof(title) - 1) * 8) / 2, 0); + _u8g2->print(title); + } + else if (_dinoGame.getGameStatus() == GAME_OVER_STATUS) + { + _u8g2->drawXBMP( + (_u8g2->getWidth() - 100) / 2, + (_u8g2->getHeight() - 15) / 2, + 100, + 15, + gameOverImg); + } + else if (_dinoGame.getGameStatus() == GAME_PLAYING_STATUS) + { + _u8g2->setFont(u8g2_font_timR08_tf); + + _u8g2->setCursor(0, 0); + char lvText[6]; + unsigned int currentLevel = _dinoGame.getLevel(); + sprintf(lvText, "LV: %d", currentLevel); + _u8g2->print(lvText); + } + + if (_dinoGame.getGameStatus() == GAME_PLAYING_STATUS || _dinoGame.getGameStatus() == GAME_OVER_STATUS) + { + char scoreText[10]; + unsigned int score = _dinoGame.getScore(); + sprintf(scoreText, "SCORE: %d", score); + + unsigned int i; + for (i = 0; i < sizeof(scoreText); i++) + { + if (scoreText[i] == '\0') + { + break; + } + } + _u8g2->setCursor((_u8g2->getWidth() - (i - 1) * 6), 0); + _u8g2->print(scoreText); + } + + } while (_u8g2->nextPage()); + + _dinoGame.loop(); + moveCloud(); +} + +void DinoGameArduino::startGame() +{ + if (_dinoGame.getGameStatus() != GAME_PLAYING_STATUS) + { + _dinoGame.startGame(); + } +} + +void DinoGameArduino::setCheatMode(CheatMode cheatMode) +{ + _cheatMode = cheatMode; + _dinoGame.setCheatMode(cheatMode); +} + +void DinoGameArduino::dinoJump() +{ + _dinoGame.dinoJump(); +} + +void DinoGameArduino::showUltraman() +{ + _showUltraman = 1; +} + +unsigned int DinoGameArduino::getScore() +{ + return _dinoGame.getScore(); +} + +unsigned int DinoGameArduino::getLevel() +{ + return _dinoGame.getLevel(); +} + +DinoGameStatus DinoGameArduino::getGameStatus() +{ + return _dinoGame.getGameStatus(); +} + +// protected + +void DinoGameArduino::drawDino() +{ + Dino *dino = _dinoGame.getDino(); + resetDinoImagePtr(&_dinoImagePtr, dino); + + _u8g2->drawXBMP( + dino->frame.postion.x, + dino->frame.postion.y - dino->frame.offset.y, + dino->frame.size.width, + dino->frame.size.height, + _dinoImagePtr); +} + +void DinoGameArduino::drawObstacleReal() +{ + Obstacle *obstacle = _dinoGame.getObstacleReal(); + resetObstacleImagePtr(&_obstacleRealImagePtr, obstacle); + _u8g2->drawXBMP( + obstacle->frame.postion.x, + obstacle->frame.postion.y, + obstacle->frame.size.width, + obstacle->frame.size.height, + _obstacleRealImagePtr); +} + +void DinoGameArduino::drawObstacleBackup() +{ + Obstacle *obstacle = _dinoGame.getObstacleBackup(); + resetObstacleImagePtr(&_obstacleBackupImagePtr, obstacle); + + _u8g2->drawXBMP( + obstacle->frame.postion.x, + obstacle->frame.postion.y, + obstacle->frame.size.width, + obstacle->frame.size.height, + _obstacleBackupImagePtr); +} + +void DinoGameArduino::moveCloud() +{ + _cloud.frame.postion.y = 10; + _cloud.frame.size.width = 39; + _cloud.frame.size.height = 12; + + _cloud.frame.postion.x--; + + if (_cloud.frame.postion.x < -_cloud.frame.size.width) + { + _cloud.frame.postion.x = _u8g2->getWidth(); + } +} + +void DinoGameArduino::drawCloud() +{ + _u8g2->drawXBMP( + _cloud.frame.postion.x, + _cloud.frame.postion.y, + _cloud.frame.size.width, + _cloud.frame.size.height, + cloudImg); +} + +// private +void DinoGameArduino::resetDinoImagePtr( + const unsigned char **dinoImagePtr, + Dino *dino) +{ + switch (dino->pose) + { + case DINO_JUMP: + *dinoImagePtr = dinoJumpImg; + break; + case DINO_LEFT: + *dinoImagePtr = dinoLeftImg; + break; + case DINO_RIGHT: + *dinoImagePtr = dinoRightImg; + break; + case DINO_BLAH: + default: + *dinoImagePtr = dinoBlahImg; + break; + } +} + +void DinoGameArduino::resetObstacleImagePtr( + const unsigned char **obstacleImagePtr, + Obstacle *obstacle) +{ + switch (obstacle->category) + { + case OBSTACLE_ONE_CACTUS: + *obstacleImagePtr = oneCactusImg; + break; + case OBSTACLE_TWO_CACTUS: + *obstacleImagePtr = twoCactusImg; + break; + case OBSTACLE_THREE_CACTUS: + *obstacleImagePtr = threeCactusImg; + break; + case OBSTACLE_ONE_SMALL_CACTUS: + *obstacleImagePtr = oneSmallCactusImg; + break; + case OBSTACLE_TWO_SMALL_CACTUS: + *obstacleImagePtr = twoSmallCactusImg; + break; + case OBSTACLE_THREE_SMALL_CACTUS: + *obstacleImagePtr = threeSmallCactusImg; + break; + case OBSTACLE_BIRD: + default: + *obstacleImagePtr = obstacle->frame.postion.x % 20 > 10 ? birdUpImg : birdDownImg; + break; + } +} \ No newline at end of file diff --git a/DinoGame/libraries/dino_game/dino_game_arduino.h b/DinoGame/libraries/dino_game/dino_game_arduino.h new file mode 100644 index 0000000..28c0f16 --- /dev/null +++ b/DinoGame/libraries/dino_game/dino_game_arduino.h @@ -0,0 +1,188 @@ +#ifndef __DINO_GAME_ARDUINO_H_ +#define __DINO_GAME_ARDUINO_H_ + +#include "dino_game.h" +#include + +class DinoGameArduino; + +// PRE-SAVED BITMAP CONSTANTS + +// 20 x 21 +static const unsigned char dinoBlahImg[] U8X8_PROGMEM = { + 0x00, 0xFC, 0x07, 0x00, 0xFE, 0x07, 0x00, 0xC6, 0x0F, 0x00, 0xC6, 0x0F, + 0x00, 0xCE, 0x0F, 0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x0F, 0x06, 0xFF, 0x03, + 0x87, 0x7F, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, + 0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0x1F, 0x00, + 0xF0, 0x1F, 0x00, 0xF0, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0x60, 0x0E, 0x00, + 0xE0, 0x1E, 0x00}; + +// 20 x 21 +static const unsigned char dinoJumpImg[] U8X8_PROGMEM = { + 0x00, 0xFC, 0x07, 0x00, 0xFE, 0x07, 0x00, 0xEE, 0x0F, 0x00, 0xFE, 0x0F, + 0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x07, 0x06, 0xFF, 0x03, + 0xC3, 0xFF, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, + 0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0x1F, 0x00, + 0xF0, 0x1F, 0x00, 0xF0, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0xE0, 0x0E, 0x00, + 0xE0, 0x1E, 0x00}; + +// 20 x 21 +static const unsigned char dinoLeftImg[] U8X8_PROGMEM = { + 0x00, 0xFC, 0x07, 0x00, 0xFE, 0x07, 0x00, 0xEE, 0x0F, 0x00, 0xFE, 0x0F, + 0x00, 0xFE, 0x0F, 0x00, 0x7E, 0x08, 0x00, 0x7E, 0x00, 0x06, 0xFF, 0x03, + 0x87, 0x3F, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, + 0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0x1F, 0x00, + 0xF0, 0x1F, 0x00, 0xE0, 0x1E, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0xE0, 0x00, 0x00}; + +// 20 x 21 +static const unsigned char dinoRightImg[] U8X8_PROGMEM = { + 0x00, 0xFC, 0x07, 0x00, 0xEE, 0x07, 0x00, 0xE6, 0x0F, 0x00, 0xFE, 0x0F, + 0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x0F, 0x00, 0x7C, 0x00, 0x06, 0xFF, 0x03, + 0xC3, 0xFF, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, + 0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0x1F, 0x00, + 0xF0, 0x1F, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x1E, 0x00}; + +// shape 0: 39 x 12 +static const unsigned char cloudImg[] U8X8_PROGMEM = { + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x06, 0x00, 0x00, 0x80, 0x01, 0x04, 0x00, 0x00, 0x40, 0x00, 0x1C, + 0x00, 0x00, 0x40, 0x00, 0xE4, 0x03, 0x00, 0x18, 0x00, 0x00, 0x02, 0xE0, + 0x0F, 0x00, 0x00, 0x0E, 0x30, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x40, 0x03, 0xFF, 0xFF, 0xFF, 0x7F}; + +// shape 1: 10 x 20 +static const unsigned char oneCactusImg[] U8X8_PROGMEM = { + 0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x01, 0xFB, 0x03, + 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x01, + 0xFE, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, + 0x78, 0x00, 0x00, 0x00}; + +// shape 2: 20 x 20 +static const unsigned char twoCactusImg[] U8X8_PROGMEM = { + 0x30, 0xC0, 0x00, 0x38, 0xE0, 0x00, 0x38, 0xE8, 0x00, 0x38, 0xEC, 0x00, + 0x38, 0xED, 0x04, 0xBB, 0xED, 0x0E, 0xBB, 0xED, 0x0E, 0xBB, 0xFD, 0x0E, + 0xBB, 0xFD, 0x0E, 0xBB, 0xF9, 0x0E, 0xFF, 0xF1, 0x0F, 0xFF, 0xE0, 0x07, + 0x7E, 0xE0, 0x01, 0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00, + 0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x00}; + +// shape 3: 20 x 20 +static const unsigned char threeCactusImg[] U8X8_PROGMEM = { + 0x00, 0xC0, 0x00, 0x18, 0xC0, 0x01, 0x18, 0xC0, 0x01, 0x58, 0xD8, 0x01, + 0x58, 0xFC, 0x01, 0x58, 0xFC, 0x0F, 0x78, 0xDC, 0x0F, 0x7F, 0xFC, 0x0F, + 0x3B, 0xFD, 0x0D, 0x1B, 0xF9, 0x0C, 0x5B, 0xF5, 0x0F, 0x5B, 0xC5, 0x07, + 0x5F, 0xE7, 0x03, 0xDE, 0xE7, 0x01, 0xD8, 0xC3, 0x01, 0x98, 0xC1, 0x01, + 0x18, 0xC1, 0x01, 0x18, 0xC1, 0x01, 0x18, 0xE1, 0x01, 0x00, 0x00, 0x00}; + +// shape 4: 6 x 12 +static const unsigned char oneSmallCactusImg[] U8X8_PROGMEM = { + 0x0C, 0x0C, 0x3C, 0x3D, 0x2D, 0x3D, 0x1D, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C}; + +// shape 5: 12 x 12 +static const unsigned char twoSmallCactusImg[] U8X8_PROGMEM = { + 0x0C, 0x03, 0x0C, 0x03, 0x6C, 0x0B, 0x6D, 0x0B, 0x6D, 0x0B, 0xBD, 0x0B, + 0x1F, 0x0F, 0x0E, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03}; + +// shape 6: 17 x 12 +static const unsigned char threeSmallCactusImg[] U8X8_PROGMEM = { + 0x04, 0x41, 0x00, 0x0C, 0x61, 0x00, 0xFC, 0x79, 0x01, 0xFD, 0x7D, 0x01, + 0x7D, 0x6D, 0x01, 0x7D, 0x7D, 0x01, 0xCF, 0xE5, 0x01, 0xCE, 0x67, 0x00, + 0x8C, 0x67, 0x00, 0x0C, 0x63, 0x00, 0x0C, 0x61, 0x00, 0x0C, 0x61, 0x00}; + +// 'birdUp', 21x18px +static const unsigned char birdUpImg[] PROGMEM = { + 0x80, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x03, 0x00, 0x30, 0x07, 0x00, 0x38, 0x0f, 0x00, 0x7c, + 0x1f, 0x00, 0x7e, 0x3f, 0x00, 0xff, 0x3f, 0x00, 0xc0, 0x7f, 0x00, 0x80, 0xff, 0x1f, 0x00, 0xff, + 0x03, 0x00, 0xfe, 0x0f, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char birdDownImg[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x7c, + 0x00, 0x00, 0x7e, 0x00, 0x00, 0xff, 0x3f, 0x00, 0xc0, 0x7f, 0x00, 0x80, 0xff, 0x1f, 0x00, 0xff, + 0x03, 0x00, 0xff, 0x0f, 0x00, 0xff, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x01, 0x00}; + +static const unsigned char gameOverImg[] U8X8_PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xF8, 0x01, 0x02, 0x0C, 0x0C, 0x3E, 0x00, 0x78, 0x60, + 0x30, 0x7C, 0xF0, 0x01, 0x0C, 0x01, 0x07, 0x14, 0x0A, 0x02, 0x00, 0x84, + 0x40, 0x10, 0x04, 0x10, 0x02, 0x04, 0x00, 0x05, 0x14, 0x0A, 0x02, 0x00, + 0x02, 0x41, 0x10, 0x04, 0x10, 0x02, 0x04, 0x00, 0x05, 0x14, 0x0A, 0x02, + 0x00, 0x02, 0xC1, 0x18, 0x04, 0x10, 0x02, 0xC4, 0x81, 0x0D, 0x34, 0x0B, + 0x3E, 0x00, 0x02, 0x81, 0x08, 0x7C, 0xF0, 0x01, 0x04, 0x81, 0x08, 0x24, + 0x09, 0x02, 0x00, 0x02, 0x81, 0x0D, 0x04, 0x10, 0x01, 0x04, 0x81, 0x0F, + 0x64, 0x09, 0x02, 0x00, 0x02, 0x01, 0x05, 0x04, 0x10, 0x02, 0x0C, 0xC1, + 0x18, 0xC4, 0x08, 0x02, 0x00, 0x84, 0x00, 0x05, 0x04, 0x10, 0x02, 0xF8, + 0x41, 0x10, 0xC4, 0x08, 0x3E, 0x00, 0x78, 0x00, 0x07, 0x7C, 0x10, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + +static const unsigned char ultramanImg[] U8X8_PROGMEM = { + 0x80, 0x1f, 0x00, 0xe0, 0x7f, 0x00, 0x78, 0xe0, 0x01, 0x1c, 0x80, 0x03, 0x0c, 0x00, 0x03, 0x06, + 0x40, 0x06, 0xe6, 0xe1, 0x06, 0xf3, 0xf3, 0x0f, 0x33, 0x33, 0x0c, 0x13, 0x00, 0x0c, 0x03, 0x00, + 0x0c, 0x03, 0x00, 0x0c, 0x03, 0x20, 0x0c, 0x06, 0x60, 0x06, 0x86, 0x37, 0x06, 0x0c, 0x1f, 0x03, + 0x1c, 0x88, 0x03, 0x78, 0xe0, 0x01, 0xe0, 0x7f, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x80, 0x6d, 0x00, + 0x80, 0x6d, 0x00, 0xc0, 0xcc, 0x00, 0xe0, 0xcc, 0x01, 0x60, 0x8c, 0x01, 0x30, 0x0c, 0x03, 0x30, + 0x0c, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x33, 0x00, 0x80, 0x61, 0x00, 0x80, 0x61, 0x00, 0xc0, + 0xc0, 0x00, 0xe0, 0xc0, 0x01, 0x60, 0x80, 0x01, 0x30, 0x00, 0x03, 0x30, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +class DinoGameArduino +{ +public: + DinoGameArduino(U8G2 *u8g2); + virtual ~DinoGameArduino(); + + void setup(); + void loop(); + + unsigned int getScore(); + unsigned int getLevel(); + DinoGameStatus getGameStatus(); + + void startGame(); + void setCheatMode(CheatMode cheatMode); + void dinoJump(); + void showUltraman(); + +protected: + U8G2 *_u8g2; + DinoGame _dinoGame; + + CheatMode _cheatMode; + + void drawDino(); + void drawObstacleReal(); + void drawObstacleBackup(); + + // Custom game + Object _cloud; + void moveCloud(); + void drawCloud(); + +private: + const unsigned char *_dinoImagePtr; + const unsigned char *_obstacleRealImagePtr; + const unsigned char *_obstacleBackupImagePtr; + + unsigned short _showUltraman; + + void resetDinoImagePtr( + const unsigned char **dinoImagePtr, + Dino *dino); + + void resetObstacleImagePtr( + const unsigned char **obstacleImagePtr, + Obstacle *obstacle); +}; + +#endif // !__DINO_GAME_ARDUINO_H_ \ No newline at end of file diff --git a/DinoGame/preview.png b/DinoGame/preview.png new file mode 100644 index 0000000..dcfd76a Binary files /dev/null and b/DinoGame/preview.png differ