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.

Dependencies:   mbed

Committer:
taylorza
Date:
Sun Jan 11 02:53:03 2015 +0000
Revision:
9:34008d8b1cdf
Child:
14:b4884a31069e
Final version before optimizations

Who changed what in which revision?

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