Platform game written for the GHI/OutrageousCircuits RETRO game device. Navigate the caves collecting all the pickups and avoiding the creatures and haunted mine carts that patrol the caves. Oh and remember to watch out for the poisonous plants... This game demonstrates the ability to have multiple animated sprites where the sprites can overlap the background environment. See how the player moves past the fence and climbs the wall in the 3rd screen.
RetroGameEngine/Scene.cpp@16:f9227904afc4, 2015-02-16 (annotated)
- Committer:
- taylorza
- Date:
- Mon Feb 16 03:46:57 2015 +0000
- Revision:
- 16:f9227904afc4
- Parent:
- 14:b4884a31069e
Added a 4th game screen
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
taylorza | 9:34008d8b1cdf | 1 | #include "GameEngine.h" |
taylorza | 9:34008d8b1cdf | 2 | |
taylorza | 9:34008d8b1cdf | 3 | Bitmap4bpp Scene::BitmapBuffer(24, 24); |
taylorza | 9:34008d8b1cdf | 4 | |
taylorza | 9:34008d8b1cdf | 5 | Scene::Scene() : |
taylorza | 9:34008d8b1cdf | 6 | _map(NULL), |
taylorza | 9:34008d8b1cdf | 7 | _x(0), |
taylorza | 9:34008d8b1cdf | 8 | _y(0), |
taylorza | 9:34008d8b1cdf | 9 | _objectsHeld(0) |
taylorza | 9:34008d8b1cdf | 10 | { |
taylorza | 9:34008d8b1cdf | 11 | Game::Surface.setOrientation(LCD_ST7735::Rotate270, false); |
taylorza | 9:34008d8b1cdf | 12 | Game::Surface.clearScreen(); |
taylorza | 9:34008d8b1cdf | 13 | |
taylorza | 9:34008d8b1cdf | 14 | for (int i = 0; i < MAX_GAMEOBJECTS; ++i) |
taylorza | 9:34008d8b1cdf | 15 | { |
taylorza | 9:34008d8b1cdf | 16 | _gameObjects[i] = NULL; |
taylorza | 9:34008d8b1cdf | 17 | } |
taylorza | 9:34008d8b1cdf | 18 | } |
taylorza | 9:34008d8b1cdf | 19 | |
taylorza | 9:34008d8b1cdf | 20 | Scene::~Scene() |
taylorza | 9:34008d8b1cdf | 21 | { |
taylorza | 14:b4884a31069e | 22 | |
taylorza | 9:34008d8b1cdf | 23 | } |
taylorza | 9:34008d8b1cdf | 24 | |
taylorza | 9:34008d8b1cdf | 25 | void Scene::restartScreen() |
taylorza | 9:34008d8b1cdf | 26 | { |
taylorza | 9:34008d8b1cdf | 27 | _objectsHeld = 0; |
taylorza | 9:34008d8b1cdf | 28 | Game::Surface.clearScreen(); |
taylorza | 9:34008d8b1cdf | 29 | drawMap(); |
taylorza | 9:34008d8b1cdf | 30 | } |
taylorza | 9:34008d8b1cdf | 31 | |
taylorza | 9:34008d8b1cdf | 32 | void Scene::update() |
taylorza | 9:34008d8b1cdf | 33 | { |
taylorza | 9:34008d8b1cdf | 34 | for (int i = 0; i < MAX_GAMEOBJECTS; ++i) |
taylorza | 9:34008d8b1cdf | 35 | { |
taylorza | 9:34008d8b1cdf | 36 | GameObject *o = _gameObjects[i]; |
taylorza | 9:34008d8b1cdf | 37 | if (o != NULL) o->update(); |
taylorza | 9:34008d8b1cdf | 38 | } |
taylorza | 9:34008d8b1cdf | 39 | } |
taylorza | 9:34008d8b1cdf | 40 | |
taylorza | 9:34008d8b1cdf | 41 | void Scene::draw() |
taylorza | 9:34008d8b1cdf | 42 | { |
taylorza | 9:34008d8b1cdf | 43 | for (int i = 0; i < MAX_GAMEOBJECTS; ++i) |
taylorza | 9:34008d8b1cdf | 44 | { |
taylorza | 9:34008d8b1cdf | 45 | GameObject *o = _gameObjects[i]; |
taylorza | 9:34008d8b1cdf | 46 | if (o != NULL) o->draw(); |
taylorza | 9:34008d8b1cdf | 47 | } |
taylorza | 9:34008d8b1cdf | 48 | } |
taylorza | 9:34008d8b1cdf | 49 | |
taylorza | 9:34008d8b1cdf | 50 | void Scene::setPosition(uint8_t x, uint8_t y) |
taylorza | 9:34008d8b1cdf | 51 | { |
taylorza | 9:34008d8b1cdf | 52 | if (x != _x || y != _y) |
taylorza | 9:34008d8b1cdf | 53 | { |
taylorza | 9:34008d8b1cdf | 54 | _x = x; |
taylorza | 9:34008d8b1cdf | 55 | _y = y; |
taylorza | 9:34008d8b1cdf | 56 | drawMap(); |
taylorza | 9:34008d8b1cdf | 57 | } |
taylorza | 9:34008d8b1cdf | 58 | } |
taylorza | 9:34008d8b1cdf | 59 | |
taylorza | 9:34008d8b1cdf | 60 | void Scene::setMap(const uint8_t *map, uint8_t xCells, uint8_t yCells, const Block *blocks, Sprite *sprites) |
taylorza | 9:34008d8b1cdf | 61 | { |
taylorza | 9:34008d8b1cdf | 62 | _map = map; |
taylorza | 9:34008d8b1cdf | 63 | _xCells = xCells; |
taylorza | 9:34008d8b1cdf | 64 | _yCells = yCells; |
taylorza | 9:34008d8b1cdf | 65 | _blocks = blocks; |
taylorza | 9:34008d8b1cdf | 66 | _sprites = sprites; |
taylorza | 9:34008d8b1cdf | 67 | } |
taylorza | 9:34008d8b1cdf | 68 | |
taylorza | 9:34008d8b1cdf | 69 | void Scene::addGameObject(GameObject *gameObject) |
taylorza | 9:34008d8b1cdf | 70 | { |
taylorza | 9:34008d8b1cdf | 71 | for (int i = 0; i < MAX_GAMEOBJECTS; ++i) |
taylorza | 9:34008d8b1cdf | 72 | { |
taylorza | 9:34008d8b1cdf | 73 | if (_gameObjects[i] == NULL) |
taylorza | 9:34008d8b1cdf | 74 | { |
taylorza | 9:34008d8b1cdf | 75 | _gameObjects[i] = gameObject; |
taylorza | 9:34008d8b1cdf | 76 | gameObject->setScene(this); |
taylorza | 9:34008d8b1cdf | 77 | break; |
taylorza | 9:34008d8b1cdf | 78 | } |
taylorza | 9:34008d8b1cdf | 79 | } |
taylorza | 9:34008d8b1cdf | 80 | } |
taylorza | 9:34008d8b1cdf | 81 | |
taylorza | 9:34008d8b1cdf | 82 | void Scene::removeGameObject(GameObject *gameObject) |
taylorza | 9:34008d8b1cdf | 83 | { |
taylorza | 9:34008d8b1cdf | 84 | for (int i = 0; i < MAX_GAMEOBJECTS; ++i) |
taylorza | 9:34008d8b1cdf | 85 | { |
taylorza | 9:34008d8b1cdf | 86 | if (_gameObjects[i] == gameObject) |
taylorza | 9:34008d8b1cdf | 87 | { |
taylorza | 9:34008d8b1cdf | 88 | gameObject->setScene(NULL); |
taylorza | 9:34008d8b1cdf | 89 | _gameObjects[i] = NULL; |
taylorza | 9:34008d8b1cdf | 90 | break; |
taylorza | 9:34008d8b1cdf | 91 | } |
taylorza | 9:34008d8b1cdf | 92 | } |
taylorza | 9:34008d8b1cdf | 93 | } |
taylorza | 9:34008d8b1cdf | 94 | |
taylorza | 9:34008d8b1cdf | 95 | const GameObject* Scene::detectCollision(GameObject *primary) |
taylorza | 9:34008d8b1cdf | 96 | { |
taylorza | 9:34008d8b1cdf | 97 | for (int i = 0; i < MAX_GAMEOBJECTS; ++i) |
taylorza | 9:34008d8b1cdf | 98 | { |
taylorza | 9:34008d8b1cdf | 99 | GameObject *other = _gameObjects[i]; |
taylorza | 9:34008d8b1cdf | 100 | if (other != NULL && other != primary) |
taylorza | 9:34008d8b1cdf | 101 | { |
taylorza | 9:34008d8b1cdf | 102 | if (detectCollision(primary, other)) |
taylorza | 9:34008d8b1cdf | 103 | { |
taylorza | 9:34008d8b1cdf | 104 | return other; |
taylorza | 9:34008d8b1cdf | 105 | } |
taylorza | 9:34008d8b1cdf | 106 | } |
taylorza | 9:34008d8b1cdf | 107 | } |
taylorza | 9:34008d8b1cdf | 108 | return NULL; |
taylorza | 9:34008d8b1cdf | 109 | } |
taylorza | 9:34008d8b1cdf | 110 | |
taylorza | 9:34008d8b1cdf | 111 | const Block* Scene::detectBlock(GameObject *primary) |
taylorza | 9:34008d8b1cdf | 112 | { |
taylorza | 9:34008d8b1cdf | 113 | Point &position = primary->getPosition(); |
taylorza | 9:34008d8b1cdf | 114 | uint8_t cellX = position.X / 8; |
taylorza | 9:34008d8b1cdf | 115 | uint8_t cellY = position.Y / 8; |
taylorza | 9:34008d8b1cdf | 116 | |
taylorza | 9:34008d8b1cdf | 117 | int my = cellY < _yCells ? 2 : 1; |
taylorza | 9:34008d8b1cdf | 118 | int mx = cellX < _xCells ? 2 : 1; |
taylorza | 9:34008d8b1cdf | 119 | |
taylorza | 9:34008d8b1cdf | 120 | int offset = (cellY * _xCells) + cellX; |
taylorza | 9:34008d8b1cdf | 121 | for (int y = 0; y < my; ++y, ++cellY) |
taylorza | 9:34008d8b1cdf | 122 | { |
taylorza | 9:34008d8b1cdf | 123 | for (int x = 0; x < mx; ++x, ++cellX) |
taylorza | 9:34008d8b1cdf | 124 | { |
taylorza | 9:34008d8b1cdf | 125 | uint8_t blockId = _map[offset++]; |
taylorza | 9:34008d8b1cdf | 126 | const Block &block = _blocks[blockId]; |
taylorza | 9:34008d8b1cdf | 127 | switch(block.getType()) |
taylorza | 9:34008d8b1cdf | 128 | { |
taylorza | 9:34008d8b1cdf | 129 | case Block::Deadly : return █ |
taylorza | 9:34008d8b1cdf | 130 | case Block::Pickup : return !isHeld(cellX, cellY) ? &block : NULL; |
taylorza | 9:34008d8b1cdf | 131 | } |
taylorza | 9:34008d8b1cdf | 132 | } |
taylorza | 9:34008d8b1cdf | 133 | offset += _xCells - mx; |
taylorza | 9:34008d8b1cdf | 134 | } |
taylorza | 9:34008d8b1cdf | 135 | return NULL; |
taylorza | 9:34008d8b1cdf | 136 | } |
taylorza | 9:34008d8b1cdf | 137 | |
taylorza | 9:34008d8b1cdf | 138 | #pragma push |
taylorza | 9:34008d8b1cdf | 139 | //#pragma diag_suppress 4017 |
taylorza | 9:34008d8b1cdf | 140 | bool Scene::detectCollision(GameObject *o1, GameObject *o2) |
taylorza | 9:34008d8b1cdf | 141 | { |
taylorza | 9:34008d8b1cdf | 142 | Rect r1 = o1->getCollisionRect(); |
taylorza | 9:34008d8b1cdf | 143 | Rect r2 = o2->getCollisionRect(); |
taylorza | 9:34008d8b1cdf | 144 | |
taylorza | 9:34008d8b1cdf | 145 | return r1.left < r2.right && |
taylorza | 9:34008d8b1cdf | 146 | r2.left < r1.right && |
taylorza | 9:34008d8b1cdf | 147 | r1.top < r2.bottom && |
taylorza | 9:34008d8b1cdf | 148 | r2.top < r1.bottom; |
taylorza | 9:34008d8b1cdf | 149 | } |
taylorza | 9:34008d8b1cdf | 150 | #pragma pop |
taylorza | 9:34008d8b1cdf | 151 | |
taylorza | 9:34008d8b1cdf | 152 | |
taylorza | 9:34008d8b1cdf | 153 | void Scene::drawMap() |
taylorza | 9:34008d8b1cdf | 154 | { |
taylorza | 9:34008d8b1cdf | 155 | if (_map == NULL) return; |
taylorza | 9:34008d8b1cdf | 156 | |
taylorza | 9:34008d8b1cdf | 157 | int yOffset = 0; |
taylorza | 9:34008d8b1cdf | 158 | |
taylorza | 9:34008d8b1cdf | 159 | for(int y = 0; y < _yCells; ++y, yOffset += _xCells) |
taylorza | 9:34008d8b1cdf | 160 | { |
taylorza | 9:34008d8b1cdf | 161 | for (int x = 0; x < _xCells; ++x) |
taylorza | 9:34008d8b1cdf | 162 | { |
taylorza | 9:34008d8b1cdf | 163 | uint8_t blockId = _map[yOffset + x]; |
taylorza | 9:34008d8b1cdf | 164 | if (blockId != 0) |
taylorza | 9:34008d8b1cdf | 165 | { |
taylorza | 9:34008d8b1cdf | 166 | drawBlock(blockId, x * 8, y * 8); |
taylorza | 9:34008d8b1cdf | 167 | } |
taylorza | 9:34008d8b1cdf | 168 | } |
taylorza | 9:34008d8b1cdf | 169 | } |
taylorza | 9:34008d8b1cdf | 170 | } |
taylorza | 9:34008d8b1cdf | 171 | |
taylorza | 9:34008d8b1cdf | 172 | bool Scene::canEnter(uint16_t x, uint16_t y) |
taylorza | 9:34008d8b1cdf | 173 | { |
taylorza | 9:34008d8b1cdf | 174 | uint8_t cellX = x / 8; |
taylorza | 9:34008d8b1cdf | 175 | uint8_t cellY = y / 8; |
taylorza | 9:34008d8b1cdf | 176 | uint8_t blockId = _map[(cellY * _xCells) + cellX]; |
taylorza | 9:34008d8b1cdf | 177 | const Block &block = _blocks[blockId]; |
taylorza | 9:34008d8b1cdf | 178 | Block::Type type = block.getType(); |
taylorza | 9:34008d8b1cdf | 179 | |
taylorza | 9:34008d8b1cdf | 180 | switch(type) |
taylorza | 9:34008d8b1cdf | 181 | { |
taylorza | 9:34008d8b1cdf | 182 | case Block::Background : return true; |
taylorza | 9:34008d8b1cdf | 183 | case Block::Platform : return true; |
taylorza | 9:34008d8b1cdf | 184 | case Block::Solid : return false; |
taylorza | 9:34008d8b1cdf | 185 | case Block::Ladder : return true; |
taylorza | 9:34008d8b1cdf | 186 | } |
taylorza | 9:34008d8b1cdf | 187 | |
taylorza | 9:34008d8b1cdf | 188 | return true; |
taylorza | 9:34008d8b1cdf | 189 | } |
taylorza | 9:34008d8b1cdf | 190 | |
taylorza | 9:34008d8b1cdf | 191 | bool Scene::canEnterFromTop(uint16_t x, uint16_t y) |
taylorza | 9:34008d8b1cdf | 192 | { |
taylorza | 9:34008d8b1cdf | 193 | uint8_t cellX = x / 8; |
taylorza | 9:34008d8b1cdf | 194 | uint8_t cellY = y / 8; |
taylorza | 9:34008d8b1cdf | 195 | uint8_t blockId = _map[(cellY * _xCells) + cellX]; |
taylorza | 9:34008d8b1cdf | 196 | const Block &block = _blocks[blockId]; |
taylorza | 9:34008d8b1cdf | 197 | Block::Type type = block.getType(); |
taylorza | 9:34008d8b1cdf | 198 | |
taylorza | 9:34008d8b1cdf | 199 | switch(type) |
taylorza | 9:34008d8b1cdf | 200 | { |
taylorza | 9:34008d8b1cdf | 201 | case Block::Background : return true; |
taylorza | 9:34008d8b1cdf | 202 | case Block::Platform : return false; |
taylorza | 9:34008d8b1cdf | 203 | case Block::Solid : return false; |
taylorza | 9:34008d8b1cdf | 204 | case Block::Ladder : return true; |
taylorza | 9:34008d8b1cdf | 205 | } |
taylorza | 9:34008d8b1cdf | 206 | |
taylorza | 9:34008d8b1cdf | 207 | return true; |
taylorza | 9:34008d8b1cdf | 208 | } |
taylorza | 9:34008d8b1cdf | 209 | |
taylorza | 9:34008d8b1cdf | 210 | const Block& Scene::getBlock(uint16_t x, uint16_t y) |
taylorza | 9:34008d8b1cdf | 211 | { |
taylorza | 9:34008d8b1cdf | 212 | uint8_t cellX = x / 8; |
taylorza | 9:34008d8b1cdf | 213 | uint8_t cellY = y / 8; |
taylorza | 9:34008d8b1cdf | 214 | uint8_t blockId = _map[(cellY * _xCells) + cellX]; |
taylorza | 9:34008d8b1cdf | 215 | return _blocks[blockId]; |
taylorza | 9:34008d8b1cdf | 216 | } |
taylorza | 9:34008d8b1cdf | 217 | |
taylorza | 9:34008d8b1cdf | 218 | void Scene::animate(uint8_t spriteId) |
taylorza | 9:34008d8b1cdf | 219 | { |
taylorza | 9:34008d8b1cdf | 220 | Sprite &sprite = _sprites[spriteId]; |
taylorza | 9:34008d8b1cdf | 221 | sprite.animate(); |
taylorza | 9:34008d8b1cdf | 222 | } |
taylorza | 9:34008d8b1cdf | 223 | |
taylorza | 9:34008d8b1cdf | 224 | bool Scene::pickupObject(uint8_t cellX, uint8_t cellY) |
taylorza | 9:34008d8b1cdf | 225 | { |
taylorza | 9:34008d8b1cdf | 226 | if (_objectsHeld == MAX_PICKUPS) return false; |
taylorza | 9:34008d8b1cdf | 227 | if (getBlock(cellX * 8, cellY * 8).getType() != Block::Pickup) return false; |
taylorza | 9:34008d8b1cdf | 228 | |
taylorza | 9:34008d8b1cdf | 229 | if (isHeld(cellX, cellY)) return false; |
taylorza | 9:34008d8b1cdf | 230 | |
taylorza | 9:34008d8b1cdf | 231 | _pickups[_objectsHeld].X = cellX; |
taylorza | 9:34008d8b1cdf | 232 | _pickups[_objectsHeld].Y = cellY; |
taylorza | 9:34008d8b1cdf | 233 | ++_objectsHeld; |
taylorza | 9:34008d8b1cdf | 234 | drawBlock(0, cellX * 8, cellY * 8); |
taylorza | 9:34008d8b1cdf | 235 | return true; |
taylorza | 9:34008d8b1cdf | 236 | } |
taylorza | 9:34008d8b1cdf | 237 | |
taylorza | 9:34008d8b1cdf | 238 | bool Scene::isHeld(uint8_t cellX, uint8_t cellY) |
taylorza | 9:34008d8b1cdf | 239 | { |
taylorza | 14:b4884a31069e | 240 | Point pt(cellX, cellY); |
taylorza | 9:34008d8b1cdf | 241 | for (int i = 0; i < _objectsHeld; ++i) |
taylorza | 9:34008d8b1cdf | 242 | { |
taylorza | 9:34008d8b1cdf | 243 | if (pt == _pickups[i]) return true; |
taylorza | 9:34008d8b1cdf | 244 | } |
taylorza | 9:34008d8b1cdf | 245 | return false; |
taylorza | 9:34008d8b1cdf | 246 | } |
taylorza | 9:34008d8b1cdf | 247 | |
taylorza | 9:34008d8b1cdf | 248 | void Scene::compose(const Block &block, uint8_t x, uint8_t y) |
taylorza | 9:34008d8b1cdf | 249 | { |
taylorza | 9:34008d8b1cdf | 250 | uint8_t fc = block.getForegroundColor(); |
taylorza | 9:34008d8b1cdf | 251 | uint8_t fch = (fc << 4) & 0xf0; |
taylorza | 9:34008d8b1cdf | 252 | uint8_t fcl = fc & 0x0f; |
taylorza | 9:34008d8b1cdf | 253 | |
taylorza | 9:34008d8b1cdf | 254 | uint8_t bc = block.getBackgroundColor(); |
taylorza | 9:34008d8b1cdf | 255 | uint8_t bch = (bc << 4) & 0xf0; |
taylorza | 9:34008d8b1cdf | 256 | uint8_t bcl = bc & 0x0f; |
taylorza | 9:34008d8b1cdf | 257 | |
taylorza | 9:34008d8b1cdf | 258 | uint8_t *bitmap = Scene::BitmapBuffer.getBitmapData(); |
taylorza | 9:34008d8b1cdf | 259 | int offsetRow = (y * Scene::BitmapBuffer.getStride()) + (x >> 1); |
taylorza | 9:34008d8b1cdf | 260 | |
taylorza | 9:34008d8b1cdf | 261 | for (int iy = 0; iy < 8; ++iy, offsetRow += Scene::BitmapBuffer.getStride()) |
taylorza | 9:34008d8b1cdf | 262 | { |
taylorza | 9:34008d8b1cdf | 263 | int offset = offsetRow; |
taylorza | 9:34008d8b1cdf | 264 | uint8_t b = *block.getBits(iy); |
taylorza | 9:34008d8b1cdf | 265 | bool highNibble = ((x & 0x01) == 0); |
taylorza | 9:34008d8b1cdf | 266 | for(int c = 0; c < 8; ++c, b <<= 1) |
taylorza | 9:34008d8b1cdf | 267 | { |
taylorza | 9:34008d8b1cdf | 268 | if (b & 0x80) |
taylorza | 9:34008d8b1cdf | 269 | { |
taylorza | 9:34008d8b1cdf | 270 | if (highNibble) bitmap[offset] = ((bitmap[offset] & 0x0f) | fch); |
taylorza | 9:34008d8b1cdf | 271 | else |
taylorza | 9:34008d8b1cdf | 272 | { |
taylorza | 9:34008d8b1cdf | 273 | bitmap[offset] = ((bitmap[offset] & 0xf0) | fcl); |
taylorza | 9:34008d8b1cdf | 274 | ++offset; |
taylorza | 9:34008d8b1cdf | 275 | } |
taylorza | 9:34008d8b1cdf | 276 | } |
taylorza | 9:34008d8b1cdf | 277 | else if (block.getType() == Block::Foreground) |
taylorza | 9:34008d8b1cdf | 278 | { |
taylorza | 9:34008d8b1cdf | 279 | if (!highNibble) ++offset; |
taylorza | 9:34008d8b1cdf | 280 | } |
taylorza | 9:34008d8b1cdf | 281 | else |
taylorza | 9:34008d8b1cdf | 282 | { |
taylorza | 9:34008d8b1cdf | 283 | if (highNibble) bitmap[offset] = ((bitmap[offset] & 0x0f) | bch); |
taylorza | 9:34008d8b1cdf | 284 | else |
taylorza | 9:34008d8b1cdf | 285 | { |
taylorza | 9:34008d8b1cdf | 286 | bitmap[offset] = ((bitmap[offset] & 0xf0) | bcl); |
taylorza | 9:34008d8b1cdf | 287 | ++offset; |
taylorza | 9:34008d8b1cdf | 288 | } |
taylorza | 9:34008d8b1cdf | 289 | } |
taylorza | 9:34008d8b1cdf | 290 | highNibble = !highNibble; |
taylorza | 9:34008d8b1cdf | 291 | } |
taylorza | 9:34008d8b1cdf | 292 | } |
taylorza | 9:34008d8b1cdf | 293 | } |
taylorza | 9:34008d8b1cdf | 294 | |
taylorza | 9:34008d8b1cdf | 295 | void Scene::compose(const Sprite &sprite, uint8_t x, uint8_t y, bool flip) |
taylorza | 9:34008d8b1cdf | 296 | { |
taylorza | 9:34008d8b1cdf | 297 | uint8_t fc = sprite.getForegroundColor(); |
taylorza | 9:34008d8b1cdf | 298 | uint8_t fch = (fc << 4) & 0xf0; |
taylorza | 9:34008d8b1cdf | 299 | uint8_t fcl = fc & 0x0f; |
taylorza | 9:34008d8b1cdf | 300 | |
taylorza | 9:34008d8b1cdf | 301 | uint8_t *bitmap = Scene::BitmapBuffer.getBitmapData(); |
taylorza | 9:34008d8b1cdf | 302 | int offsetRow = (y * Scene::BitmapBuffer.getStride()) + (x >> 1); |
taylorza | 9:34008d8b1cdf | 303 | |
taylorza | 9:34008d8b1cdf | 304 | if (!flip) |
taylorza | 9:34008d8b1cdf | 305 | { |
taylorza | 9:34008d8b1cdf | 306 | for (int iy = 0; iy < 16; ++iy, offsetRow += Scene::BitmapBuffer.getStride()) |
taylorza | 9:34008d8b1cdf | 307 | { |
taylorza | 9:34008d8b1cdf | 308 | int offset = offsetRow; |
taylorza | 9:34008d8b1cdf | 309 | uint8_t *p = sprite.getBits(iy); |
taylorza | 9:34008d8b1cdf | 310 | bool highNibble = ((x & 0x01) == 0); |
taylorza | 9:34008d8b1cdf | 311 | for (int ix = 0; ix < 2; ++ix) |
taylorza | 9:34008d8b1cdf | 312 | { |
taylorza | 9:34008d8b1cdf | 313 | uint8_t b = *p++; |
taylorza | 9:34008d8b1cdf | 314 | for(int c = 0; c < 8; ++c, b <<= 1) |
taylorza | 9:34008d8b1cdf | 315 | { |
taylorza | 9:34008d8b1cdf | 316 | if (b & 0x80) |
taylorza | 9:34008d8b1cdf | 317 | { |
taylorza | 9:34008d8b1cdf | 318 | if (highNibble) bitmap[offset] = ((bitmap[offset] & 0x0f) | fch); |
taylorza | 9:34008d8b1cdf | 319 | else |
taylorza | 9:34008d8b1cdf | 320 | { |
taylorza | 9:34008d8b1cdf | 321 | bitmap[offset] = ((bitmap[offset] & 0xf0) | fcl); |
taylorza | 9:34008d8b1cdf | 322 | offset++; |
taylorza | 9:34008d8b1cdf | 323 | } |
taylorza | 9:34008d8b1cdf | 324 | } |
taylorza | 9:34008d8b1cdf | 325 | else if (!highNibble) |
taylorza | 9:34008d8b1cdf | 326 | { |
taylorza | 9:34008d8b1cdf | 327 | offset++; |
taylorza | 9:34008d8b1cdf | 328 | } |
taylorza | 9:34008d8b1cdf | 329 | highNibble = !highNibble; |
taylorza | 9:34008d8b1cdf | 330 | } |
taylorza | 9:34008d8b1cdf | 331 | } |
taylorza | 9:34008d8b1cdf | 332 | } |
taylorza | 9:34008d8b1cdf | 333 | } |
taylorza | 9:34008d8b1cdf | 334 | else |
taylorza | 9:34008d8b1cdf | 335 | { |
taylorza | 9:34008d8b1cdf | 336 | for (int iy = 0; iy < 16; ++iy, offsetRow += Scene::BitmapBuffer.getStride()) |
taylorza | 9:34008d8b1cdf | 337 | { |
taylorza | 9:34008d8b1cdf | 338 | int offset = offsetRow; |
taylorza | 9:34008d8b1cdf | 339 | uint8_t *p = sprite.getBits(iy) + 1; |
taylorza | 9:34008d8b1cdf | 340 | bool highNibble = ((x & 0x01) == 0); |
taylorza | 9:34008d8b1cdf | 341 | for (int ix = 0; ix < 2; ++ix) |
taylorza | 9:34008d8b1cdf | 342 | { |
taylorza | 9:34008d8b1cdf | 343 | uint8_t b = *p--; |
taylorza | 9:34008d8b1cdf | 344 | for(int c = 0; c < 8; ++c, b >>= 1) |
taylorza | 9:34008d8b1cdf | 345 | { |
taylorza | 9:34008d8b1cdf | 346 | if (b & 0x01) |
taylorza | 9:34008d8b1cdf | 347 | { |
taylorza | 9:34008d8b1cdf | 348 | if (highNibble) bitmap[offset] = ((bitmap[offset] & 0x0f) | fch); |
taylorza | 9:34008d8b1cdf | 349 | else |
taylorza | 9:34008d8b1cdf | 350 | { |
taylorza | 9:34008d8b1cdf | 351 | bitmap[offset] = ((bitmap[offset] & 0xf0) | fcl); |
taylorza | 9:34008d8b1cdf | 352 | offset++; |
taylorza | 9:34008d8b1cdf | 353 | } |
taylorza | 9:34008d8b1cdf | 354 | } |
taylorza | 9:34008d8b1cdf | 355 | else if (!highNibble) |
taylorza | 9:34008d8b1cdf | 356 | { |
taylorza | 9:34008d8b1cdf | 357 | offset++; |
taylorza | 9:34008d8b1cdf | 358 | } |
taylorza | 9:34008d8b1cdf | 359 | highNibble = !highNibble; |
taylorza | 9:34008d8b1cdf | 360 | } |
taylorza | 9:34008d8b1cdf | 361 | } |
taylorza | 9:34008d8b1cdf | 362 | } |
taylorza | 9:34008d8b1cdf | 363 | } |
taylorza | 9:34008d8b1cdf | 364 | } |
taylorza | 9:34008d8b1cdf | 365 | |
taylorza | 9:34008d8b1cdf | 366 | void Scene::drawBlock(uint8_t blockId, int16_t x, int16_t y) |
taylorza | 9:34008d8b1cdf | 367 | { |
taylorza | 9:34008d8b1cdf | 368 | const Block &block = _blocks[blockId]; |
taylorza | 9:34008d8b1cdf | 369 | uint8_t fc = block.getForegroundColor(); |
taylorza | 9:34008d8b1cdf | 370 | uint8_t fch = (fc << 4) & 0xf0; |
taylorza | 9:34008d8b1cdf | 371 | uint8_t fcl = fc & 0x0f; |
taylorza | 9:34008d8b1cdf | 372 | |
taylorza | 9:34008d8b1cdf | 373 | uint8_t bc = block.getBackgroundColor(); |
taylorza | 9:34008d8b1cdf | 374 | uint8_t bch = (bc << 4) & 0xf0; |
taylorza | 9:34008d8b1cdf | 375 | uint8_t bcl = bc & 0x0f; |
taylorza | 9:34008d8b1cdf | 376 | |
taylorza | 9:34008d8b1cdf | 377 | uint8_t *bitmap = Scene::BitmapBuffer.getBitmapData(); |
taylorza | 9:34008d8b1cdf | 378 | |
taylorza | 9:34008d8b1cdf | 379 | int offset = 0; |
taylorza | 9:34008d8b1cdf | 380 | for (int iy = 0; iy < 8; ++iy) |
taylorza | 9:34008d8b1cdf | 381 | { |
taylorza | 9:34008d8b1cdf | 382 | uint8_t b = *block.getBits(iy); |
taylorza | 9:34008d8b1cdf | 383 | |
taylorza | 9:34008d8b1cdf | 384 | bitmap[offset] = b & 0x80 ? ((bitmap[offset] & 0x0f) | fch) : ((bitmap[offset] & 0x0f) | bch); |
taylorza | 9:34008d8b1cdf | 385 | bitmap[offset] = b & 0x40 ? ((bitmap[offset] & 0xf0) | fcl) : ((bitmap[offset] & 0xf0) | bcl); |
taylorza | 9:34008d8b1cdf | 386 | ++offset; |
taylorza | 9:34008d8b1cdf | 387 | |
taylorza | 9:34008d8b1cdf | 388 | bitmap[offset] = b & 0x20 ? ((bitmap[offset] & 0x0f) | fch) : ((bitmap[offset] & 0x0f) | bch); |
taylorza | 9:34008d8b1cdf | 389 | bitmap[offset] = b & 0x10 ? ((bitmap[offset] & 0xf0) | fcl) : ((bitmap[offset] & 0xf0) | bcl); |
taylorza | 9:34008d8b1cdf | 390 | ++offset; |
taylorza | 9:34008d8b1cdf | 391 | |
taylorza | 9:34008d8b1cdf | 392 | bitmap[offset] = b & 0x08 ? ((bitmap[offset] & 0x0f) | fch) : ((bitmap[offset] & 0x0f) | bch); |
taylorza | 9:34008d8b1cdf | 393 | bitmap[offset] = b & 0x04 ? ((bitmap[offset] & 0xf0) | fcl) : ((bitmap[offset] & 0xf0) | bcl); |
taylorza | 9:34008d8b1cdf | 394 | ++offset; |
taylorza | 9:34008d8b1cdf | 395 | |
taylorza | 9:34008d8b1cdf | 396 | bitmap[offset] = b & 0x02 ? ((bitmap[offset] & 0x0f) | fch) : ((bitmap[offset] & 0x0f) | bch); |
taylorza | 9:34008d8b1cdf | 397 | bitmap[offset] = b & 0x01 ? ((bitmap[offset] & 0xf0) | fcl) : ((bitmap[offset] & 0xf0) | bcl); |
taylorza | 9:34008d8b1cdf | 398 | //++offset; |
taylorza | 9:34008d8b1cdf | 399 | offset += Scene::BitmapBuffer.getStride() - 3; |
taylorza | 9:34008d8b1cdf | 400 | } |
taylorza | 9:34008d8b1cdf | 401 | |
taylorza | 9:34008d8b1cdf | 402 | Game::Surface.drawBitmap(_x + x, _y + y, Scene::BitmapBuffer, 0, 0, 8, 8); |
taylorza | 9:34008d8b1cdf | 403 | } |
taylorza | 9:34008d8b1cdf | 404 | |
taylorza | 9:34008d8b1cdf | 405 | void Scene::drawSprite(uint8_t spriteId, int16_t x, int16_t y, int16_t dx, int16_t dy, bool flip) |
taylorza | 9:34008d8b1cdf | 406 | { |
taylorza | 9:34008d8b1cdf | 407 | uint8_t cellX = x / 8; |
taylorza | 9:34008d8b1cdf | 408 | uint8_t cellY = y / 8; |
taylorza | 9:34008d8b1cdf | 409 | uint8_t rx = x % 8; |
taylorza | 9:34008d8b1cdf | 410 | uint8_t ry = y % 8; |
taylorza | 9:34008d8b1cdf | 411 | |
taylorza | 9:34008d8b1cdf | 412 | if (rx == 0 && dx > 0 && cellX > 0) { --cellX; rx += 8; } |
taylorza | 9:34008d8b1cdf | 413 | if (ry == 0 && dy > 0 && cellY > 0) { --cellY; ry += 8; } |
taylorza | 9:34008d8b1cdf | 414 | |
taylorza | 9:34008d8b1cdf | 415 | Scene::BitmapBuffer.clear(); |
taylorza | 9:34008d8b1cdf | 416 | |
taylorza | 9:34008d8b1cdf | 417 | // Compose blocks, except foreground blocks |
taylorza | 9:34008d8b1cdf | 418 | for (int cy = 0; cy < 3; ++cy) |
taylorza | 9:34008d8b1cdf | 419 | { |
taylorza | 9:34008d8b1cdf | 420 | int yOffset = (cellY + cy) * _xCells; |
taylorza | 9:34008d8b1cdf | 421 | for (int cx = 0; cx < 3; ++cx) |
taylorza | 9:34008d8b1cdf | 422 | { |
taylorza | 9:34008d8b1cdf | 423 | uint8_t blockId = _map[yOffset + cellX + cx]; |
taylorza | 9:34008d8b1cdf | 424 | const Block &block = _blocks[blockId]; |
taylorza | 9:34008d8b1cdf | 425 | |
taylorza | 9:34008d8b1cdf | 426 | if (blockId != 0 && block.getType() != Block::Foreground) |
taylorza | 9:34008d8b1cdf | 427 | { |
taylorza | 9:34008d8b1cdf | 428 | if (!(block.getType() == Block::Pickup && isHeld(cellX + cx, cellY + cy))) |
taylorza | 9:34008d8b1cdf | 429 | { |
taylorza | 9:34008d8b1cdf | 430 | compose(block, cx * 8, cy * 8); |
taylorza | 9:34008d8b1cdf | 431 | } |
taylorza | 9:34008d8b1cdf | 432 | } |
taylorza | 9:34008d8b1cdf | 433 | } |
taylorza | 9:34008d8b1cdf | 434 | } |
taylorza | 9:34008d8b1cdf | 435 | |
taylorza | 9:34008d8b1cdf | 436 | // Compose sprite |
taylorza | 9:34008d8b1cdf | 437 | const Sprite &sprite = _sprites[spriteId]; |
taylorza | 9:34008d8b1cdf | 438 | compose(sprite, rx, ry, flip); |
taylorza | 9:34008d8b1cdf | 439 | |
taylorza | 9:34008d8b1cdf | 440 | // Compose foreground blocks |
taylorza | 9:34008d8b1cdf | 441 | for (int cy = 0; cy < 3; ++cy) |
taylorza | 9:34008d8b1cdf | 442 | { |
taylorza | 9:34008d8b1cdf | 443 | int yOffset = (cellY + cy) * _xCells; |
taylorza | 9:34008d8b1cdf | 444 | for (int cx = 0; cx < 3; ++cx) |
taylorza | 9:34008d8b1cdf | 445 | { |
taylorza | 9:34008d8b1cdf | 446 | uint8_t blockId = _map[yOffset + cellX + cx]; |
taylorza | 9:34008d8b1cdf | 447 | const Block &block = _blocks[blockId]; |
taylorza | 9:34008d8b1cdf | 448 | if (blockId != 0 && block.getType() == Block::Foreground) |
taylorza | 9:34008d8b1cdf | 449 | { |
taylorza | 9:34008d8b1cdf | 450 | compose(block, cx * 8, cy * 8); |
taylorza | 9:34008d8b1cdf | 451 | } |
taylorza | 9:34008d8b1cdf | 452 | } |
taylorza | 9:34008d8b1cdf | 453 | } |
taylorza | 9:34008d8b1cdf | 454 | |
taylorza | 9:34008d8b1cdf | 455 | // Render the composed image |
taylorza | 9:34008d8b1cdf | 456 | //Screen.drawBitmap(cellX * 8, cellY * 8, Scene::BitmapBuffer, 0, 0, 24, 24); |
taylorza | 9:34008d8b1cdf | 457 | |
taylorza | 9:34008d8b1cdf | 458 | Game::Surface.drawBitmap( |
taylorza | 9:34008d8b1cdf | 459 | _x + (dx > 0 ? x - dx : x), |
taylorza | 9:34008d8b1cdf | 460 | _y + (dy > 0 ? y - dy : y), |
taylorza | 9:34008d8b1cdf | 461 | Scene::BitmapBuffer, |
taylorza | 9:34008d8b1cdf | 462 | dx > 0 ? rx - dx : rx, |
taylorza | 9:34008d8b1cdf | 463 | dy > 0 ? ry - dy : ry, |
taylorza | 9:34008d8b1cdf | 464 | 16 + abs(dx), 16 + abs(dy)); |
taylorza | 9:34008d8b1cdf | 465 | |
taylorza | 9:34008d8b1cdf | 466 | } |