Aeca

Capítulo 07 — Constantes: valores que não deveriam mudar

Série: Do zero ao jogo comercial com C++ e SFML

Capítulo 07 — Constantes: valores que não deveriam mudar
aeca

Quando uma informação representa uma regra fixa, nosso código também deve deixar essa intenção explícita

No capítulo anterior começamos a perceber que nem toda informação do nosso jogo possui a mesma natureza.

Criamos:

  std::string playerName = "Alex";
int playerHealth = 100;
int playerCoins = 25;
int playerLevel = 1;
float playerSpeed = 4.5f;
bool isAlive = true;
char playerGrade = 'A';

Agora nosso programa já consegue representar diferentes tipos de dados.

Mas existe outra diferença importante entre informações.

Algumas devem mudar durante a execução:

  playerHealth
playerCoins
playerLevel

Outras representam regras ou limites que, depois de definidos, não deveriam ser alterados:

  Maximum Player Health
Maximum Inventory Slots
Default Player Speed

Imagine uma regra do nosso jogo:

  Maximum Player Health = 100

Poderíamos escrever:

  int maxPlayerHealth = 100;

Mas nada impediria isto:

  maxPlayerHealth = 500;

O código compilaria.

Só que talvez isso violasse completamente nossa intenção.

Precisamos conseguir dizer ao compilador:

Este valor existe, mas não deve ser modificado depois de inicializado.

É exatamente para esse tipo de situação que começaremos a utilizar const.


1. Nosso problema atual

Vamos começar com um estado simples:

  int playerHealth = 100;

Durante o jogo, playerHealth pode mudar:

  100
 ↓
80
 ↓
50
 ↓
100

Isso faz sentido.

O jogador pode:

  • sofrer dano;

  • recuperar vida;

  • utilizar itens;

  • receber efeitos.

Portanto:

  int playerHealth = 100;

representa estado mutável.

Agora imagine:

  Maximum Player Health = 100

Essa informação possui outro significado.

Ela representa uma regra.


2. Variável mutável versus valor constante

Podemos pensar em duas categorias iniciais:

  ESTADO MUTÁVEL

playerHealth
100 → 80 → 60 → 100

e:

  REGRA

MAX_PLAYER_HEALTH
100

O primeiro pode mudar.

O segundo não deveria.

Se ambos forem declarados simplesmente como int, nosso código não expressa essa diferença.


3. Nossa primeira constante

Em C++, podemos escrever:

  const int MAX_PLAYER_HEALTH = 100;

Agora temos:

  const int MAX_PLAYER_HEALTH = 100;
│      │          │             │
│      │          │             └── valor inicial
│      │          │
│      │          └── nome
│      │
│      └── tipo
│
└── não pode ser modificado depois

Essa declaração comunica uma intenção muito diferente de:

  int playerHealth = 100;

4. Nossa convenção para constantes

No projeto utilizaremos:

  UPPERCASE

para constantes.

E continuaremos utilizando nomes em inglês.

Portanto:

  const int MAX_PLAYER_HEALTH = 100;
const int MAX_INVENTORY_SLOTS = 20;
const float DEFAULT_PLAYER_SPEED = 4.5f;

Observe o padrão:

  MAX_PLAYER_HEALTH
MAX_INVENTORY_SLOTS
DEFAULT_PLAYER_SPEED

Palavras separadas por:

underscore.

Essa é uma convenção do nosso projeto.

C++ não exige que constantes utilizem letras maiúsculas.

Poderíamos tecnicamente escrever:

  const int maxPlayerHealth = 100;

Mas nossa convenção será:

  const int MAX_PLAYER_HEALTH = 100;

Consistência importa.


5. Vamos usar uma constante de verdade

Atualize nosso main.cpp:

  #include <iostream>

int main()
{
    const int MAX_PLAYER_HEALTH = 100;

    int playerHealth = MAX_PLAYER_HEALTH;

    std::cout << "Maximum Health: " << MAX_PLAYER_HEALTH << std::endl;
    std::cout << "Current Health: " << playerHealth << std::endl;

    return 0;
}

Faça:

  Save
 ↓
Build
 ↓
Run

Resultado:

  Maximum Health: 100
Current Health: 100

Agora temos dois conceitos diferentes.


6. A constante representa a regra

Temos:

  const int MAX_PLAYER_HEALTH = 100;

e:

  int playerHealth = MAX_PLAYER_HEALTH;

Podemos visualizar:

  REGRA

MAX_PLAYER_HEALTH
┌───────┐
│  100  │
└───────┘
     │
     │ valor inicial
     ▼
playerHealth
┌───────┐
│  100  │
└───────┘

Depois o jogador sofre dano:

  playerHealth = playerHealth - 20;

Agora:

  MAX_PLAYER_HEALTH
100

playerHealth
80

A regra continua a mesma.

O estado mudou.


7. Vamos observar isso no programa

  #include <iostream>

int main()
{
    const int MAX_PLAYER_HEALTH = 100;

    int playerHealth = MAX_PLAYER_HEALTH;

    std::cout << "=== INITIAL STATE ===" << std::endl;
    std::cout << "Maximum Health: " << MAX_PLAYER_HEALTH << std::endl;
    std::cout << "Current Health: " << playerHealth << std::endl;

    playerHealth = playerHealth - 20;

    std::cout << std::endl;
    std::cout << "=== AFTER DAMAGE ===" << std::endl;
    std::cout << "Maximum Health: " << MAX_PLAYER_HEALTH << std::endl;
    std::cout << "Current Health: " << playerHealth << std::endl;

    return 0;
}

Resultado:

  === INITIAL STATE ===
Maximum Health: 100
Current Health: 100

=== AFTER DAMAGE ===
Maximum Health: 100
Current Health: 80

Agora nosso programa expressa claramente:

  Maximum Health
→ regra

Current Health
→ estado

8. O que acontece se tentarmos modificar uma constante?

Vamos quebrar nosso programa de propósito.

Adicione:

  MAX_PLAYER_HEALTH = 200;

Teremos:

  #include <iostream>

int main()
{
    const int MAX_PLAYER_HEALTH = 100;

    MAX_PLAYER_HEALTH = 200;

    return 0;
}

Faça Build.

O compilador deverá rejeitar essa alteração.

E isso é exatamente o que queremos.


9. O compilador agora protege nossa intenção

Quando declaramos:

  const int MAX_PLAYER_HEALTH = 100;

estamos fornecendo uma informação adicional ao compilador:

este objeto não deve ser modificado através desse nome depois de inicializado.

Então:

  MAX_PLAYER_HEALTH = 200;

não é simplesmente uma alteração indesejada do ponto de vista do Game Design.

Ela também se torna inválida no código.

Isso é muito poderoso.


10. Antes e depois de const

Sem const:

  int MAX_PLAYER_HEALTH = 100;

MAX_PLAYER_HEALTH = 200;

Tecnicamente permitido.

Mesmo que nossa intenção fosse manter 100.

Com const:

  const int MAX_PLAYER_HEALTH = 100;

MAX_PLAYER_HEALTH = 200;

o compilador consegue impedir a alteração.

Temos:

  INTENÇÃO
   +
LINGUAGEM
   ↓
proteção maior

11. const também melhora a leitura

Compare:

  int MAX_INVENTORY_SLOTS = 20;

com:

  const int MAX_INVENTORY_SLOTS = 20;

Mesmo sem procurar onde a variável é utilizada, o segundo código já comunica:

MAX_INVENTORY_SLOTS não deve mudar.

Isso melhora nossa capacidade de compreender o programa.

Uma boa declaração não descreve apenas qual valor existe.

Ela também descreve como esse valor pode ser utilizado.


12. Constante precisa de valor inicial

Experimente:

  const int MAX_PLAYER_HEALTH;

Para esse tipo fundamental local, isso não é válido.

Estamos declarando um objeto const, mas não fornecemos um valor com o qual ele possa ser inicializado.

A forma correta:

  const int MAX_PLAYER_HEALTH = 100;

Isso faz sentido.

Se depois da inicialização não poderemos atribuir outro valor, precisamos definir adequadamente seu estado inicial.


13. Inicialização continua diferente de atribuição

No Capítulo 05 vimos essa distinção.

Aqui ela fica ainda mais importante.

Isto:

  const int MAX_PLAYER_HEALTH = 100;

é inicialização.

Não estamos:

  1. criando a constante;

  2. deixando-a sem valor;

  3. atribuindo 100 depois.

Ela nasce inicializada.

Depois disso:

  MAX_PLAYER_HEALTH = 200;

não é permitido.


14. Constantes podem ter outros tipos

Não estamos limitados a:

  const int

Podemos ter:

  const float DEFAULT_PLAYER_SPEED = 4.5f;
const bool DEFAULT_FULLSCREEN = false;
const char DEFAULT_PLAYER_GRADE = 'A';

Também poderíamos utilizar std::string:

  #include <string>

const std::string DEFAULT_PLAYER_NAME = "Player";

O conceito é o mesmo:

aquela informação não deve ser modificada depois de inicializada através daquele objeto const.


15. Um pequeno conjunto de regras do jogo

Podemos escrever:

  #include <iostream>

int main()
{
    const int MAX_PLAYER_HEALTH = 100;
    const int MAX_INVENTORY_SLOTS = 20;
    const float DEFAULT_PLAYER_SPEED = 4.5f;

    int playerHealth = MAX_PLAYER_HEALTH;
    int inventorySlotsUsed = 0;
    float playerSpeed = DEFAULT_PLAYER_SPEED;

    std::cout << "Maximum Health: " << MAX_PLAYER_HEALTH << std::endl;
    std::cout << "Current Health: " << playerHealth << std::endl;
    std::cout << "Inventory Capacity: " << MAX_INVENTORY_SLOTS << std::endl;
    std::cout << "Inventory Used: " << inventorySlotsUsed << std::endl;
    std::cout << "Default Speed: " << DEFAULT_PLAYER_SPEED << std::endl;
    std::cout << "Current Speed: " << playerSpeed << std::endl;

    return 0;
}

Agora começamos a enxergar duas categorias no nosso código.


16. Regras versus estado

  CONSTANTES

MAX_PLAYER_HEALTH
MAX_INVENTORY_SLOTS
DEFAULT_PLAYER_SPEED

Representam regras ou valores configurados para nosso exemplo.

Enquanto:

  VARIÁVEIS

playerHealth
inventorySlotsUsed
playerSpeed

representam estado atual.

Podemos visualizar:

  REGRAS
│
├── MAX_PLAYER_HEALTH = 100
├── MAX_INVENTORY_SLOTS = 20
└── DEFAULT_PLAYER_SPEED = 4.5

ESTADO ATUAL
│
├── playerHealth = 80
├── inventorySlotsUsed = 7
└── playerSpeed = 6.0

Agora nosso modelo está ficando semanticamente mais claro.


17. Nem todo valor fixo precisa virar constante nomeada

Aqui precisamos evitar outro extremo.

Considere:

  return 0;

Não precisamos imediatamente criar:

  const int SUCCESS_CODE = 0;

só porque 0 aparece no código.

Da mesma forma, não devemos transformar cada número existente em uma constante apenas para dizer que "evitamos magic numbers".

Precisamos analisar contexto e intenção.


18. O que é um magic number?

Imagine:

  if (playerHealth > 100)
{
}

Ainda não estudamos if, então observe apenas conceitualmente.

O que significa:

  100

?

Talvez seja:

  maximum player health

Se aquele valor representa uma regra importante, algo como:

  MAX_PLAYER_HEALTH

expressaria melhor a intenção.

Agora imagine:

  playerLevel = playerLevel + 1;

O:

  1

é bastante claro como incremento de um nível naquele contexto.

Criar:

  const int ONE_LEVEL = 1;

provavelmente deixaria o código pior.

Portanto:

evitar magic numbers não significa nomear cegamente todo literal numérico.


19. Uma constante deve representar um conceito

Bom exemplo:

  const int MAX_PLAYER_HEALTH = 100;

Porque existe um conceito:

  Maximum Player Health

Outro:

  const int MAX_INVENTORY_SLOTS = 20;

Existe um conceito de limite de inventário.

Agora isto:

  const int VALUE_ONE = 1;

provavelmente não comunica nenhuma regra relevante.

O nome deveria explicar por que aquele valor importa.


20. const não significa "global"

Não precisamos colocar nossas constantes fora de main.

Podemos continuar:

  int main()
{
    const int MAX_PLAYER_HEALTH = 100;

    int playerHealth = MAX_PLAYER_HEALTH;

    return 0;
}

Neste estágio isso é suficiente.

Colocar constantes globalmente apenas porque são constantes criaria outro assunto:

  scope
lifetime
linkage
translation units

Ainda não precisamos disso.

Vamos manter nosso código simples.


21. Constante global não é automaticamente melhor

Você poderá encontrar códigos assim:

  const int MAX_PLAYER_HEALTH = 100;

int main()
{
}

Isso pode ser adequado em certos contextos.

Mas não adotaremos a regra:

constantes devem ficar no topo do arquivo.

A pergunta correta será:

qual é o escopo adequado para esse valor?

Ainda teremos um capítulo específico sobre escopo.

Quando tivermos informação suficiente, poderemos tomar decisões melhores.


22. E #define?

Talvez você encontre:

  #define MAX_PLAYER_HEALTH 100

em códigos C ou C++.

Macros existem e terão seu momento.

Mas não utilizaremos #define para representar constantes simples quando uma solução tipada como:

  const int MAX_PLAYER_HEALTH = 100;

expressa melhor nosso objetivo atual.

Macros são processadas pelo pré-processador e possuem características bastante diferentes de objetos const.

Não precisamos introduzir essa complexidade agora.


23. E constexpr?

C++ moderno também possui:

  constexpr

Você poderá encontrar:

  constexpr int MAX_PLAYER_HEALTH = 100;

Então por que estamos começando com:

  const int MAX_PLAYER_HEALTH = 100;

Porque precisamos primeiro compreender a ideia de imutabilidade através de const.

constexpr envolve também a possibilidade/requisito de avaliação em contexto de tempo de compilação e possui implicações que merecem uma explicação própria.

Não vamos misturar os conceitos prematuramente.

Primeiro:

  mutable
versus
const

Depois evoluímos.


24. const começa a nos ensinar uma ideia maior

Até agora poderíamos pensar:

  const = valor que não muda

Isso é útil para começar.

Mas em C++, const é muito mais importante.

Futuramente teremos:

  const Player& player

métodos como:

  int GetHealth() const;

pointers envolvendo const e outras combinações.

A ideia maior será:

const correctness

Ou seja, utilizar o sistema de tipos para expressar corretamente onde alterações são permitidas e onde não são.

Mas não vamos saltar para referências e métodos agora.

Hoje construímos apenas o primeiro degrau.


25. Erro proposital — alterando a constante

Vamos utilizar nossa metodologia de troubleshooting.

Código:

  #include <iostream>

int main()
{
    const int MAX_PLAYER_HEALTH = 100;

    MAX_PLAYER_HEALTH = 200;

    return 0;
}

Faça Build.

Depois responda:

  O que aconteceu?

Qual linha está envolvida?

Qual objeto possui const?

Qual operação estamos tentando realizar?

Por que essa operação contradiz nossa declaração?

Depois remova:

  MAX_PLAYER_HEALTH = 200;

Faça Build novamente.

Valide.


26. Erro proposital — constante sem inicialização

Teste:

  const int MAX_PLAYER_HEALTH;

Faça Build.

Observe o diagnóstico.

Depois corrija:

  const int MAX_PLAYER_HEALTH = 100;

Novamente:

  QUEBRAR
 ↓
LER
 ↓
ENTENDER
 ↓
CORRIGIR
 ↓
VALIDAR

O erro continua sendo parte do nosso processo educacional.


27. Microdesafio — o que deve ser constante?

Considere estas informações:

  Current Health
Maximum Health
Current Coins
Maximum Inventory Slots
Current Level
Default Player Speed

Quais provavelmente representam estado mutável e quais representam regras fixas no nosso exemplo?

Uma classificação possível:

  MUTÁVEIS

playerHealth
playerCoins
playerLevel
playerSpeed

e:

  CONSTANTES

MAX_PLAYER_HEALTH
MAX_INVENTORY_SLOTS
DEFAULT_PLAYER_SPEED

Mas atenção:

playerSpeed pode mudar durante o jogo devido a buffs ou efeitos.

Por isso temos:

  const float DEFAULT_PLAYER_SPEED = 4.5f;
float playerSpeed = DEFAULT_PLAYER_SPEED;

A palavra:

  DEFAULT

é importante.

Ela comunica que estamos falando do valor inicial/padrão, e não necessariamente do valor atual.


28. Microdesafio prático

Crie:

  const int MAX_PLAYER_HEALTH = 100;
const int MAX_INVENTORY_SLOTS = 20;
const float DEFAULT_PLAYER_SPEED = 4.5f;

Depois:

  int playerHealth = MAX_PLAYER_HEALTH;
int inventorySlotsUsed = 5;
float playerSpeed = DEFAULT_PLAYER_SPEED;

Mostre:

  === GAME RULES ===
Maximum Health: 100
Maximum Inventory Slots: 20
Default Player Speed: 4.5

=== PLAYER STATE ===
Current Health: 100
Inventory Used: 5
Current Speed: 4.5

Tente antes de ver uma solução possível.


29. Uma possível implementação

  #include <iostream>

int main()
{
    const int MAX_PLAYER_HEALTH = 100;
    const int MAX_INVENTORY_SLOTS = 20;
    const float DEFAULT_PLAYER_SPEED = 4.5f;

    int playerHealth = MAX_PLAYER_HEALTH;
    int inventorySlotsUsed = 5;
    float playerSpeed = DEFAULT_PLAYER_SPEED;

    std::cout << "=== GAME RULES ===" << std::endl;
    std::cout << "Maximum Health: " << MAX_PLAYER_HEALTH << std::endl;
    std::cout << "Maximum Inventory Slots: " << MAX_INVENTORY_SLOTS << std::endl;
    std::cout << "Default Player Speed: " << DEFAULT_PLAYER_SPEED << std::endl;

    std::cout << std::endl;

    std::cout << "=== PLAYER STATE ===" << std::endl;
    std::cout << "Current Health: " << playerHealth << std::endl;
    std::cout << "Inventory Used: " << inventorySlotsUsed << std::endl;
    std::cout << "Current Speed: " << playerSpeed << std::endl;

    return 0;
}

Essa implementação continua simples.

Mas ela já expressa algo que nosso código anterior não expressava:

  REGRA
≠
ESTADO

30. Nosso código final do capítulo

Podemos manter como evolução principal:

  #include <iostream>

int main()
{
    const int MAX_PLAYER_HEALTH = 100;
    const int MAX_INVENTORY_SLOTS = 20;
    const float DEFAULT_PLAYER_SPEED = 4.5f;

    int playerHealth = MAX_PLAYER_HEALTH;
    int inventorySlotsUsed = 5;
    float playerSpeed = DEFAULT_PLAYER_SPEED;

    std::cout << "=== GAME RULES ===" << std::endl;
    std::cout << "Maximum Health: " << MAX_PLAYER_HEALTH << std::endl;
    std::cout << "Maximum Inventory Slots: " << MAX_INVENTORY_SLOTS << std::endl;
    std::cout << "Default Player Speed: " << DEFAULT_PLAYER_SPEED << std::endl;

    std::cout << std::endl;

    std::cout << "=== PLAYER STATE ===" << std::endl;
    std::cout << "Current Health: " << playerHealth << std::endl;
    std::cout << "Inventory Used: " << inventorySlotsUsed << std::endl;
    std::cout << "Current Speed: " << playerSpeed << std::endl;

    playerHealth = playerHealth - 20;
    inventorySlotsUsed = inventorySlotsUsed + 1;

    std::cout << std::endl;

    std::cout << "=== UPDATED PLAYER STATE ===" << std::endl;
    std::cout << "Current Health: " << playerHealth << std::endl;
    std::cout << "Inventory Used: " << inventorySlotsUsed << std::endl;
    std::cout << "Current Speed: " << playerSpeed << std::endl;

    return 0;
}

O resultado será semelhante a:

  === GAME RULES ===
Maximum Health: 100
Maximum Inventory Slots: 20
Default Player Speed: 4.5

=== PLAYER STATE ===
Current Health: 100
Inventory Used: 5
Current Speed: 4.5

=== UPDATED PLAYER STATE ===
Current Health: 80
Inventory Used: 6
Current Speed: 4.5

As regras permaneceram.

O estado mudou.

Esse é o resultado observável deste capítulo.


31. Nossa arquitetura ainda não precisa mudar

Continuamos apenas com:

  CppGameEngine/
└── main.cpp

Não precisamos criar:

  Constants/
Config/
GameRules/
Settings/

ainda.

Temos três constantes.

Criar uma infraestrutura inteira para isso seria antecipar complexidade.

Quando essas regras começarem a crescer, ficar espalhadas ou depender de configuração, teremos um problema novo.

Então analisaremos a solução adequada.


32. Validando a implementação

Faça:

  Ctrl + S

Depois:

  Ctrl + Shift + B

Confirme:

  Build succeeded

Execute:

  Ctrl + F5

Verifique:

  MAX_PLAYER_HEALTH permanece 100

MAX_INVENTORY_SLOTS permanece 20

DEFAULT_PLAYER_SPEED permanece 4.5

playerHealth muda

inventorySlotsUsed muda

Também faça o teste negativo:

  MAX_PLAYER_HEALTH = 200;

e confirme que o compilador impede a alteração.

Depois restaure o código válido.


33. Registrando a evolução no Git

Desta vez temos uma mudança real no código.

Verifique:

  git status

Depois adicione o arquivo correto:

  git add CppGameEngine/main.cpp

Ajuste o caminho caso sua estrutura local seja diferente.

Podemos registrar:

  git commit -m "feat: add immutable game rule constants"

O commit representa a evolução:

nosso programa agora diferencia regras constantes de estado mutável.


34. Atualizando o CHANGELOG

Em [Unreleased], podemos acrescentar:

  ### Added

- Added immutable game rule constants.
- Added maximum player health and inventory slot limits.
- Added default player speed configuration.
- Added separation between game rules and mutable player state.

Depois:

  git add CHANGELOG.md
git commit -m "docs: update changelog with game rule constants"

Não precisamos alterar o ROADMAP técnico apenas por esse pequeno avanço de fundamentos.


35. O que aprendemos?

No capítulo anterior tínhamos apenas variáveis:

  int playerHealth = 100;

Agora aprendemos a expressar outra intenção:

  const int MAX_PLAYER_HEALTH = 100;

Começamos a diferenciar:

  MUTÁVEL
↓
playerHealth

de:

  CONSTANTE
↓
MAX_PLAYER_HEALTH

Aprendemos também que:

  • const impede modificações posteriores através daquele objeto;

  • constantes devem ser adequadamente inicializadas;

  • nossa convenção utilizará UPPERCASE;

  • identificadores continuarão em inglês;

  • constantes podem utilizar diferentes tipos;

  • nem todo literal precisa virar uma constante;

  • uma constante nomeada deve representar um conceito;

  • const não significa global;

  • const não é o mesmo que #define;

  • constexpr existe, mas possui responsabilidades adicionais;

  • estamos dando nosso primeiro passo em direção a const correctness.

Mais importante:

nosso código agora consegue expressar não apenas o valor de uma informação, mas também a intenção de que ela não seja modificada.


Conclusão

Nosso pequeno programa já conhece diferentes tipos de informação:

  int
float
bool
char
std::string

Agora também começou a diferenciar duas naturezas de estado:

  VALORES QUE MUDAM

e:

  VALORES QUE NÃO DEVERIAM MUDAR

Podemos representar:

  GAME RULES

MAX_PLAYER_HEALTH      = 100
MAX_INVENTORY_SLOTS   = 20
DEFAULT_PLAYER_SPEED  = 4.5

enquanto o jogador possui:

  PLAYER STATE

playerHealth        = 80
inventorySlotsUsed  = 6
playerSpeed         = 4.5

Essa separação é simples.

Mas já começa a tornar nosso código mais seguro e mais expressivo.

Programação não consiste apenas em fazer o compilador aceitar instruções.

Também queremos comunicar nossas intenções.

E const nos dá uma forma de dizer:

este valor representa algo que não deveria ser alterado.

No próximo capítulo, essas informações começarão a interagir ainda mais.

Até agora fizemos algumas operações como:

  playerHealth = playerHealth - 20;

e:

  inventorySlotsUsed = inventorySlotsUsed + 1;

Mas ainda não estudamos formalmente o que são:

  +
-
=
*
/
%

e outros operadores.

Chegou a hora.


Próximo capítulo

Capítulo 08 — Operadores: transformando dados

Série: Do zero ao jogo comercial com C++ e SFML

No próximo artigo vamos partir de situações reais do nosso pequeno estado:

  Player sofre dano
Player recupera Health
Player recebe Coins
Player gasta Coins
Experience aumenta

e descobrir como operadores permitem transformar informações.

Vamos trabalhar progressivamente com operações como:

  playerHealth - damage
playerCoins + reward
playerCoins - itemPrice

e começar a diferenciar:

  atribuição
aritmética
incremento
decremento

sem tentar estudar todos os operadores C++ de uma única vez.

Primeiro construiremos as operações que nosso jogo já precisa.

Depois entenderemos o que cada operador está fazendo.

Nosso programa está deixando de apenas armazenar estado.

Agora começará a transformá-lo.

Subscreve "Aeca" para receber atualizações diretamente na tua caixa de entrada
aeca

Subscreve aeca para reagir

Subscrever

Comentários

Ainda não há comentários. Sê o primeiro a comentar!

Subscreve Aeca para receber atualizações diretamente na tua caixa de entrada