Race around the city collecting the flags while avoiding those that stand in the way of your mission. Make no mistake you will need to be quick to outwit your opponents, they are smart and will try to box you in. I wrote this game to prove that writing a game with scrolling scenery is possible even with the limited 6kB of RAM available. I had to compromise sound effects for features, I wanted multiple opponents, I wanted to be able to drop smoke bombs to trap the opponents but all this required memory so the sound effects had to take a back seat.

Dependencies:   mbed

GameScreen.h

Committer:
taylorza
Date:
2015-02-01
Revision:
1:1b8125937f28
Parent:
0:d85c449aca6d

File content as of revision 1:1b8125937f28:

#include "Constants.h"
#include "GameEngine.h"
#include "Map.h"
#include "Assets.h"
#include "Flag.h"
#include "Enemy.h"
#include "Player.h"
#include "Beeper.h"

#ifndef __GAMESCREEN_H__
#define __GAMESCREEN_H__

class GameScreen;

class GameScreen : public TileViewer
{
public: 
    GameScreen() : TileViewer(13, 16),
        _player(Point(184, 400)),
        _enemy1(Point(64, 464), Point(16, -32), Point(8, 8), _player),
        _enemy2(Point(88, 464), Point(1024, -32), Point(32, 32), _player),
        _enemy3(Point(112, 464), Point(16, 1024), Point(-32, -32), _player),
        _radarBitmap(46, 62),
        _radarCanvas(&_radarBitmap),
        _updateCounter(0),
        _gameOver(false)
    {
        Game::Surface.setForegroundColor(Color565::White);
        Game::Surface.setBackgroundColor(HUD_BACKGROUND);
        setMap(map, 48, 64, blocks, sprites);
        _radarCanvas.clear();
        
        _cars[0] = &_player;
        _cars[1] = &_enemy1;
        _cars[2] = &_enemy2;
        _cars[3] = &_enemy3;
                        
        placeFlags();        
        
        _player.setPosition(Point(184, 400));
        _player.setCars(_cars);
        _player.setFlags(_flags);
        
        addGameObject(&_enemy1);    
        addGameObject(&_enemy2);    
        addGameObject(&_enemy3);    
        addGameObject(&_player);    
        
        track(&_player);               
    }
    
    void placeFlags()
    {
        for(int i = 0; i < MAX_FLAGS; ++i)
        {
            int x = 0;
            int y = 0;
            
            for(;;)
            {
                x = rand() % getMapTilesX();
                y = rand() % getMapTilesY();
                const Block &block1 = getBlock(x * 8, y * 8);
                if (&block1 == &blocks[0]) break;
            }
            
            _flags[i].setActive(true);
            _flags[i].setPosition(Point(x * 8, y * 8));
            addGameObject(&_flags[i]);
        }    
    }

    virtual void update()
    {        
        if (_player.getLives() > 0)
        {
            if (_player.getFlagCount() == MAX_FLAGS)
            {                
                if(_player.getFuel() > 0)
                {                    
                    _player.decreaseFuel();
                    _player.increaseScore(10);
                    Beeper::beep(400 + (100 - _player.getFuel()) * 2, 5);                    
                }
                else
                {
                    placeFlags();
                    
                    for (int i = 0; i < MAX_CARS; ++i)
                    {
                        _cars[i]->reset();
                    }
                }
            }
            else
            {
                TileViewer::update();  
            }
        }
        else
        {
            _gameOver = true;            
        }
    }
    
    virtual void draw()
    {
        if (!_gameOver)
        {
            TileViewer::draw();                          
        }
        else
        {
            Game::Surface.setForegroundColor(Color565::Red);
            Game::Surface.setBackgroundColor(Color565::Black);
            Game::Surface.drawString(font_ibm, 18, 60, "GAME OVER");
        }
        
        // Update HUD
        if (_updateCounter++ % 8 == 0)
        {
            Game::Surface.drawBitmap(109, 17, getRadarBitmap(), 0, 0, 46, 62);                
        
            char buffer[10];
            Game::Surface.setForegroundColor(Color565::Aqua);
            Game::Surface.setBackgroundColor(HUD_BACKGROUND);                
            sprintf(buffer, "%d", _player.getScore());
            Game::Surface.drawString(font_ibm, 108, 4, buffer);
            
            // Render lives
            for (int i = 0; i < _player.getLives(); ++i)
            {
                Game::Surface.drawBitmap(108 + i * 8, 100, spriteSheet, 56, 32, 8, 8);
            }
            
            for (int i = _player.getLives(); i < MAX_LIVES; ++i)
            {
                Game::Surface.fillRect(108 + i * 8, 100, (108 + i * 8) + 8, 108, HUD_BACKGROUND);
            }
            
            // Render fuel
            uint8_t limit = (uint8_t)(((float)_player.getFuel() / 100) * 48);        
                        
            uint16_t fuelColor = limit < 15 ? Color565::Red : Color565::Yellow;
            Game::Surface.fillRect(108, 84, 108 + limit, 90, fuelColor);
            Game::Surface.fillRect(108 + limit + 1, 84, 160, 90, HUD_BACKGROUND);
            
            // Fuel ticks
            Game::Surface.drawLine(108, 92, 114, 92, Color565::Red);
            Game::Surface.drawLine(108, 92, 108, 94, Color565::Red);
            Game::Surface.drawLine(114, 92, 114, 94, Color565::Red);
            
            
            Game::Surface.drawLine(115, 92, 156, 92, Color565::Yellow);
            for (int i = 12; i <= 48; i += 6)
            {
                Game::Surface.drawLine(108 + i, 92, 108 + i, 94, Color565::Yellow);
            }
        }
    }
    
    inline RallyCar** getCars() { return _cars; } 
    
    void drawEntity(int16_t x, int16_t y, uint16_t color)
    {
        _radarCanvas.setPixel(x - 1, y - 1, color);
        _radarCanvas.setPixel(x, y - 1, color);
        _radarCanvas.setPixel(x + 1, y - 1, color);
        
        _radarCanvas.setPixel(x - 1, y, color);
        _radarCanvas.setPixel(x, y, color);
        _radarCanvas.setPixel(x + 1, y, color);
        
        _radarCanvas.setPixel(x - 1, y + 1, color);
        _radarCanvas.setPixel(x, y + 1, color);
        _radarCanvas.setPixel(x + 1, y + 1, color);
    }
    
    Bitmap2bpp& getRadarBitmap() 
    { 
        _radarCanvas.clear();        
        
        for (int i = 0; i < MAX_FLAGS; ++i)
        {            
            Flag &flag = _flags[i];
            if (flag.getActive())
            {
                drawEntity(flag.getPosition().X / 8, flag.getPosition().Y / 8, 3);                
            }
        }
        
        drawEntity(_enemy1.getPosition().X / 8, _enemy1.getPosition().Y / 8, 2);
        drawEntity(_enemy2.getPosition().X / 8, _enemy2.getPosition().Y / 8, 2);
        drawEntity(_enemy3.getPosition().X / 8, _enemy3.getPosition().Y / 8, 2);
        drawEntity(_player.getPosition().X / 8, _player.getPosition().Y / 8, 1);        

        return _radarBitmap; 
    }
    
private:
    Player  _player;
    Enemy   _enemy1;
    Enemy   _enemy2;
    Enemy   _enemy3;
    
    RallyCar    *_cars[MAX_CARS];
    Flag        _flags[MAX_FLAGS];
        
    Bitmap2bpp          _radarBitmap;
    Canvas<Bitmap2bpp>  _radarCanvas;    
    
    uint8_t     _updateCounter;
    bool        _gameOver;
};
#endif //__GAMESCREEN_H__