Programação de Jogos - Design Patterns

27
{Programação de Jogos} Bruno Cicanci @ TDC SP 2015

Transcript of Programação de Jogos - Design Patterns

{Programação de Jogos}Bruno Cicanci @ TDC SP 2015

{Design Patterns}

● Command● Flyweight● Observer● Prototype● States● Singleton

{Command: Problema}void InputHandler::handleInput(){ if (isPressed(BUTTON_X)) jump(); else if (isPressed(BUTTON_Y)) fireGun(); else if (isPressed(BUTTON_A)) swapWeapon(); else if (isPressed(BUTTON_B)) reloadWeapon();}

http://gameprogrammingpatterns.com/command.html

{Command: Solução}class Command{public: virtual ~Command() {} virtual void execute() = 0;};

class JumpCommand : public Command{public: virtual void execute() { jump(); }};

void InputHandler::handleInput(){ if (isPressed(BUTTON_X)) buttonX_->execute(); else if (isPressed(BUTTON_Y)) buttonY_->execute(); else if (isPressed(BUTTON_A)) buttonA_->execute(); else if (isPressed(BUTTON_B)) buttonB_->execute();}

http://gameprogrammingpatterns.com/command.html

{Command: Uso}● Input● Undo● Redo

{Flyweight: Problema}class Tree{private: Mesh mesh_; Texture bark_; Texture leaves_; Vector position_; double height_; double thickness_; Color barkTint_; Color leafTint_;};

http://gameprogrammingpatterns.com/flyweight.html

{Flyweight: Solução}class TreeModel{private: Mesh mesh_; Texture bark_; Texture leaves_;};

class Tree{private: TreeModel* model_;

Vector position_; double height_; double thickness_; Color barkTint_; Color leafTint_;};

http://gameprogrammingpatterns.com/flyweight.html

{Flyweight: Uso}● Milhares de instâncias● Tile maps

{Observer: Problema}void Physics::updateEntity(Entity& entity){ bool wasOnSurface = entity.isOnSurface(); entity.accelerate(GRAVITY); entity.update(); if (wasOnSurface && !entity.isOnSurface()) { notify(entity, EVENT_START_FALL); }}

http://gameprogrammingpatterns.com/observer.html

{Observer: Solução parte 1}class Observer

{

public:

virtual ~Observer() {}

virtual void onNotify(const Entity& entity, Event event) = 0;

};

class Achievements : public Observer

{

public:

virtual void onNotify(const Entity& entity, Event event)

{

switch (event)

{

case EVENT_ENTITY_FELL:

if (entity.isHero() && heroIsOnBridge_)

{

unlock(ACHIEVEMENT_FELL_OFF_BRIDGE);

}

break;

}

}

}; http://gameprogrammingpatterns.com/observer.html

{Observer: Solução parte 2}class Subject

{

private:

Observer* observers_[MAX_OBSERVERS];

int numObservers_;

protected:

void notify(const Entity& entity, Event event)

{

for (int i = 0; i < numObservers_; i++)

{

observers_[i]->onNotify(entity, event);

}

}

};

class Physics : public Subject{public: void updateEntity(Entity& entity);};

http://gameprogrammingpatterns.com/observer.html

{Observer: Uso}● Achievements● Efeitos sonoros / visuais● Eventos● Mensagens● Expirar demo● Callback async

{Prototype: Problema}class Monster{ // Stuff...};

class Ghost : public Monster {};class Demon : public Monster {};class Sorcerer : public Monster {};

http://gameprogrammingpatterns.com/prototype.html

class Spawner

{

public:

virtual ~Spawner() {}

virtual Monster* spawnMonster() = 0;

};

class GhostSpawner : public Spawner

{

public:

virtual Monster* spawnMonster()

{

return new Ghost();

}

};

{Prototype: Solução parte 1}class Monster{public: virtual ~Monster() {} virtual Monster* clone() = 0;

// Other stuff...};

http://gameprogrammingpatterns.com/prototype.html

class Ghost : public Monster {

public:

Ghost(int health, int speed)

: health_(health),

speed_(speed)

{}

virtual Monster* clone()

{

return new Ghost(health_, speed_);

}

private:

int health_;

int speed_;

};

{Prototype: Solução parte 2}class Spawner{public: Spawner(Monster* prototype) : prototype_(prototype) {} Monster* spawnMonster() { return prototype_->clone(); }private: Monster* prototype_;}; http://gameprogrammingpatterns.com/prototype.html

{Prototype: Uso}● Spawner● Tiros● Loot

{States: Problema}void Heroine::handleInput(Input input)

{

if (input == PRESS_B)

{

if (!isJumping_ && !isDucking_)

{

// Jump...

}

}

else if (input == PRESS_DOWN)

{

if (!isJumping_)

{

isDucking_ = true;

}

} http://gameprogrammingpatterns.com/state.html

else if (input == RELEASE_DOWN)

{

if (isDucking_)

{

isDucking_ = false;

}

}

}

{States: Solução}void Heroine::handleInput(Input input)

{

switch (state_)

{

case STATE_STANDING:

if (input == PRESS_B)

{

state_ = STATE_JUMPING;

}

else if (input == PRESS_DOWN)

{

state_ = STATE_DUCKING;

}

break;http://gameprogrammingpatterns.com/state.html

case STATE_JUMPING:

if (input == PRESS_DOWN)

{

state_ = STATE_DIVING;

}

break;

case STATE_DUCKING:

if (input == RELEASE_DOWN)

{

state_ = STATE_STANDING;

}

break;

}

}

{States: Uso}● Controle de animação● Fluxo de telas● Movimento do personagem

{Singleton: Problema}

“Garante que uma classe tenha somente uma instância E fornecer um ponto global de acesso para ela”

Gang of Four, Design Patterns

{Singleton: Solução}class FileSystem{public: static FileSystem& instance() { if (instance_ == NULL) instance_ = new FileSystem(); return *instance_; }private: FileSystem() {} static FileSystem* instance_;};

http://gameprogrammingpatterns.com/singleton.html

{Singleton: Uso}

“Friends don’t let friends create singletons”Robert Nystrom, Game Programming Patterns

{Outros Design Patterns}Double BufferGame LoopUpdate Method

BytecodeSubclass SandboxType Object

ComponentEvent QueueService Locator

Data LocalityDirty FlagObject PoolSpatial Partition

{Livro: Game Programming Patterns}

http://gameprogrammingpatterns.com

{Outros livros}FísicaPhysics for Game Developers

Computação Gráfica3D Math Primer for Graphics and Game

Game DesignGame Design WorkshopLevel Up! The Guide to Great Game Design

ProduçãoThe Game Production HandbookAgile Game Development with Scrum

ProgramaçãoCode CompleteClean Code

Programação de JogosGame Programming PatternsGame Programming Algorithms and TechniquesGame Coding Complete

Inteligência ArtificialProgramming Game AI by Example

{Blog: gamedeveloper.com.br}

{Obrigado}

E-mail: [email protected]

Twitter: @cicanci

PSN: cicanci42