Capítulo 05 — Variáveis: nosso futuro jogo precisa lembrar informações
Série: Do zero ao jogo comercial com C++ e SFML
Nosso primeiro passo para transformar mensagens fixas em um programa que possui estado
Até agora, nosso projeto sabe fazer algo muito simples:
#include <iostream>
int main()
{
std::cout << "Game Engineering com C++ começou!" << std::endl;
return 0;
}
Nos capítulos anteriores aprendemos a:
criar nosso primeiro programa;
compreender sua estrutura básica;
quebrá-lo propositalmente;
interpretar os primeiros erros;
diferenciar código-fonte, Build, executável e execução.
Mas existe uma limitação importante.
Nosso programa ainda não lembra informações.
Se escrevermos:
std::cout << "Player Health: 100" << std::endl;
vemos:
Player Health: 100
Mas esse 100 faz parte do texto.
Nosso programa não possui realmente algo chamado:
playerHealth
Ele simplesmente imprimiu caracteres no console.
Para começarmos a construir um jogo, isso não será suficiente.
Um jogo precisa conhecer informações como:
Health
Energy
Coins
Level
Experience
Score
E, mais importante:
essas informações precisam poder mudar enquanto o jogo está sendo executado.
É aqui que entram as variáveis.
1. Começando pelo problema
Imagine nosso futuro jogo.
O jogador começa com:
Health: 100
Coins: 25
Level: 1
Durante a partida ele recebe dano:
Health: 100
↓
Health: 80
Depois vende algum recurso:
Coins: 25
↓
Coins: 35
Mais tarde sobe de nível:
Level: 1
↓
Level: 2
Nosso programa precisa representar esses valores.
Não podemos simplesmente escrever:
std::cout << "Health: 100" << std::endl;
e esperar que o 100 magicamente se transforme quando o jogador receber dano.
Precisamos armazenar essa informação.
2. Nossa primeira variável
Vamos começar com:
int playerHealth = 100;
Essa pequena instrução apresenta vários conceitos novos.
Podemos inicialmente separá-la assim:
int playerHealth = 100;
│ │ │ │
│ │ │ └── valor inicial
│ │ │
│ │ └── atribuição/inicialização
│ │
│ └── nome
│
└── tipo
Ainda estudaremos tipos profundamente no próximo capítulo.
Por enquanto, precisamos apenas saber que:
int
representa um tipo inteiro.
E:
playerHealth
é o nome que escolhemos para nossa variável.
Finalmente:
100
é seu valor inicial.
3. O que é uma variável?
Uma definição inicial bastante útil é:
Uma variável é uma representação nomeada de uma informação que nosso programa pode armazenar e utilizar durante sua execução.
Em nosso exemplo:
int playerHealth = 100;
podemos pensar conceitualmente:
playerHealth
┌──────────────┐
│ 100 │
└──────────────┘
Agora nosso programa possui uma informação chamada:
playerHealth
com valor:
100
Essa representação é propositalmente simplificada.
Quando chegarmos a memória, endereços, referências, pointers, stack e lifetime, construiremos um modelo muito mais preciso.
Por enquanto, ela é suficiente para começarmos.
4. Por que não chamar a variável de x?
Poderíamos escrever:
int x = 100;
O compilador aceitaria.
Mas compare:
int x = 100;
com:
int playerHealth = 100;
Qual deles explica melhor a intenção?
No contexto do nosso futuro jogo:
playerHealth
é muito mais expressivo.
O nome nos informa:
esta informação representa a vida do jogador.
Código também é comunicação entre desenvolvedores.
Por isso nomes importam.
5. Nossa convenção para variáveis
A partir daqui começaremos a aplicar uma das convenções estabelecidas para nosso projeto.
Variáveis utilizarão:
camelCase
Por exemplo:
playerHealth
playerCoins
playerLevel
playerEnergy
currentScore
Observe:
playerHealth
│ │
│ └── nova palavra começa com maiúscula
│
└── primeira palavra começa com minúscula
Também utilizaremos identificadores em inglês.
Portanto, preferiremos:
playerHealth
em vez de:
vidaJogador
As explicações continuam em português do Brasil.
O código seguirá nomenclatura técnica em inglês.
6. Vamos colocar nossa variável no programa
Altere nosso main.cpp:
#include <iostream>
int main()
{
int playerHealth = 100;
std::cout << "Player Health: " << playerHealth << std::endl;
return 0;
}
Faça:
Save
↓
Build
↓
Run
O resultado deverá ser:
Player Health: 100
Visualmente, o resultado parece semelhante ao que tínhamos antes.
Mas internamente existe uma diferença fundamental.
7. Antes e depois
Antes:
std::cout << "Player Health: 100" << std::endl;
O valor estava preso dentro do texto.
Agora:
int playerHealth = 100;
std::cout << "Player Health: " << playerHealth << std::endl;
Temos duas coisas separadas:
"Player Health: "
e:
playerHealth
Podemos visualizar:
playerHealth
│
▼
100
│
▼
std::cout
│
▼
Player Health: 100
Agora o valor existe como informação manipulável pelo programa.
8. Observe o << novamente
No Capítulo 02 aprendemos:
std::cout << "Hello";
Agora temos:
std::cout << "Player Health: " << playerHealth << std::endl;
Estamos inserindo diferentes informações no fluxo:
std::cout
│
├── << "Player Health: "
│
├── << playerHealth
│
└── << std::endl
O primeiro valor é texto.
O segundo vem da variável.
9. Vamos provar que a variável realmente pode mudar
Depois da primeira saída, adicione:
playerHealth = 80;
Nosso código:
#include <iostream>
int main()
{
int playerHealth = 100;
std::cout << "Player Health: " << playerHealth << std::endl;
playerHealth = 80;
std::cout << "Player Health: " << playerHealth << std::endl;
return 0;
}
Execute.
Resultado:
Player Health: 100
Player Health: 80
Agora aconteceu algo completamente novo em nossa série.
10. Nosso programa mudou seu próprio estado
Começamos com:
playerHealth
┌──────────────┐
│ 100 │
└──────────────┘
Depois executamos:
playerHealth = 80;
Conceitualmente:
ANTES
playerHealth
┌──────────────┐
│ 100 │
└──────────────┘
↓
playerHealth = 80;
↓
DEPOIS
playerHealth
┌──────────────┐
│ 80 │
└──────────────┘
Essa capacidade é fundamental.
Um jogo é cheio de estado que muda.
11. Estado
Vamos introduzir uma palavra muito importante:
State — Estado
O estado representa informações que descrevem determinada situação do programa em um momento.
Imagine nosso jogador:
Player State
│
├── Health: 100
├── Energy: 80
├── Coins: 25
└── Level: 1
Depois de alguns acontecimentos:
Player State
│
├── Health: 75
├── Energy: 60
├── Coins: 40
└── Level: 2
O jogador continua sendo conceitualmente o mesmo.
Mas seu estado mudou.
Variáveis serão uma das ferramentas fundamentais para representar esse estado.
12. Nosso primeiro pequeno estado de jogo
Vamos expandir um pouco:
#include <iostream>
int main()
{
int playerHealth = 100;
int playerCoins = 25;
int playerLevel = 1;
std::cout << "Player Health: " << playerHealth << std::endl;
std::cout << "Player Coins: " << playerCoins << std::endl;
std::cout << "Player Level: " << playerLevel << std::endl;
return 0;
}
Execute.
Resultado:
Player Health: 100
Player Coins: 25
Player Level: 1
Agora nosso programa possui três informações independentes.
13. Visualizando nosso estado
Podemos imaginar:
MEMÓRIA — MODELO CONCEITUAL
playerHealth
┌───────┐
│ 100 │
└───────┘
playerCoins
┌───────┐
│ 25 │
└───────┘
playerLevel
┌───────┐
│ 1 │
└───────┘
Novamente:
esse desenho é uma abstração didática.
Ainda não estamos afirmando detalhes sobre endereços, tamanho, stack ou representação física.
Chegaremos lá progressivamente.
14. Declaração
Quando escrevemos:
int playerHealth;
estamos declarando uma variável.
Estamos dizendo, de maneira simplificada:
haverá uma variável chamada
playerHealthdo tipoint.
Observe que ainda não fornecemos explicitamente um valor nessa linha.
15. Inicialização
Quando escrevemos:
int playerHealth = 100;
estamos declarando a variável e fornecendo um valor inicial.
Podemos pensar:
int playerHealth = 100;
│ │ │
│ │ └── valor inicial
│ │
│ └── nome
│
└── tipo
Para nossos exemplos iniciais, vamos preferir inicializar as variáveis quando as criamos sempre que fizer sentido.
Isso reduz estados indeterminados e torna a intenção mais clara.
16. Declaração e atribuição posterior
Também poderíamos escrever:
int playerHealth;
playerHealth = 100;
Aqui temos duas etapas.
Primeiro:
int playerHealth;
Depois:
playerHealth = 100;
Mas isso não é exatamente a mesma operação conceitual que:
int playerHealth = 100;
No primeiro caso declaramos e posteriormente atribuímos.
No segundo fornecemos um valor durante a inicialização.
Essa diferença ficará mais importante quando estudarmos tipos e objetos mais sofisticados.
17. Inicialização versus atribuição
Vamos registrar:
Inicialização
int playerHealth = 100;
A variável nasce com aquele valor.
Atribuição
Depois:
playerHealth = 80;
Estamos alterando o valor de uma variável que já existe.
Conceitualmente:
Inicialização
playerHealth
↓
100
Depois
Atribuição
↓
playerHealth = 80
↓
novo valor
18. O sinal = merece atenção
Em:
playerHealth = 80;
o:
=
não deve ser lido simplesmente como a igualdade matemática tradicional.
Aqui estamos utilizando o operador de atribuição.
Podemos inicialmente ler:
atribua
80aplayerHealth.
Ou:
80
↓
playerHealth
Mais adiante veremos operadores em detalhes.
19. Uma variável pode aparecer dos dois lados de uma operação
Considere:
playerHealth = playerHealth - 20;
Ainda não estudamos operadores formalmente, mas conseguimos entender a ideia.
Se:
playerHealth = 100
então:
playerHealth - 20
produz:
80
e depois atribuímos esse resultado novamente:
playerHealth = 80
Conceitualmente:
valor atual
↓
100
↓
100 - 20
↓
80
↓
novo playerHealth
Isso começa a parecer um jogo.
20. Nosso primeiro "dano"
Vamos experimentar:
#include <iostream>
int main()
{
int playerHealth = 100;
std::cout << "Player Health: " << playerHealth << std::endl;
playerHealth = playerHealth - 20;
std::cout << "Player Health: " << playerHealth << std::endl;
return 0;
}
Resultado:
Player Health: 100
Player Health: 80
Ainda não temos um sistema de combate.
Nem deveríamos.
Mas já conseguimos representar uma mudança de estado.
21. Isso ainda não é uma regra de gameplay completa
Não devemos olhar para:
playerHealth = playerHealth - 20;
e criar imediatamente:
DamageSystem
CombatManager
HealthComponent
EventBus
Temos uma linha.
Ela resolve nosso problema atual.
Mais tarde talvez apareçam necessidades como:
diferentes fontes de dano;
defesa;
resistência;
invulnerabilidade;
efeitos;
morte;
eventos;
UI;
testes.
Quando esses problemas surgirem, nossa solução poderá evoluir.
Hoje ela não precisa.
22. Mudando as moedas
Podemos fazer algo semelhante:
int playerCoins = 25;
playerCoins = playerCoins + 10;
Conceitualmente:
25
↓
+ 10
↓
35
Depois:
std::cout << "Player Coins: " << playerCoins << std::endl;
Resultado:
Player Coins: 35
Nosso programa agora consegue representar:
perder Health
ganhar Coins
mesmo que ainda de forma extremamente simples.
23. Nosso primeiro pequeno fluxo de estado
Experimente:
#include <iostream>
int main()
{
int playerHealth = 100;
int playerCoins = 25;
int playerLevel = 1;
std::cout << "=== Initial State ===" << std::endl;
std::cout << "Health: " << playerHealth << std::endl;
std::cout << "Coins: " << playerCoins << std::endl;
std::cout << "Level: " << playerLevel << std::endl;
playerHealth = playerHealth - 20;
playerCoins = playerCoins + 10;
playerLevel = 2;
std::cout << std::endl;
std::cout << "=== Current State ===" << std::endl;
std::cout << "Health: " << playerHealth << std::endl;
std::cout << "Coins: " << playerCoins << std::endl;
std::cout << "Level: " << playerLevel << std::endl;
return 0;
}
Resultado:
=== Initial State ===
Health: 100
Coins: 25
Level: 1
=== Current State ===
Health: 80
Coins: 35
Level: 2
Agora existe uma transformação observável.
24. O jogo começa a existir como dados
Ainda não temos gráficos.
Mas já começamos a representar algo essencial:
GAME STATE
Health
Coins
Level
Essa é uma lição importante de Game Engineering.
Um jogo não é apenas aquilo que aparece na tela.
Existe uma grande quantidade de estado e regras por trás da apresentação visual.
A interface gráfica futuramente mostrará esses dados.
Mas os dados precisam existir independentemente da aparência.
25. A HUD do futuro
Imagine futuramente uma HUD exibindo:
❤️ 80
🪙 35
⭐ 2
Visualmente teremos sprites, fonts, UI e rendering.
Mas por trás dela poderá existir algo conceitualmente equivalente a:
playerHealth
playerCoins
playerLevel
A interface apresenta o estado.
Ela não deveria ser o próprio estado.
Essa separação ficará muito importante quando começarmos a pensar em arquitetura.
26. Variável não é apenas "uma caixinha"
Muitos cursos definem variável assim:
"Uma variável é uma caixa na memória."
Essa analogia pode ajudar no começo.
Por isso utilizamos desenhos como:
playerHealth
┌───────┐
│ 100 │
└───────┘
Mas precisamos tomar cuidado para não transformar a analogia em uma definição absoluta.
C++ possui detalhes importantes envolvendo:
storage;
lifetime;
scope;
object representation;
references;
addresses;
memory;
optimization.
Então prefiro que você pense:
uma variável nos permite dar um nome a uma informação armazenada/manipulada pelo programa.
A metáfora da caixa é apenas um primeiro modelo visual.
27. Nomes ruins começam a cobrar preço rapidamente
Imagine:
int a = 100;
int b = 25;
int c = 1;
Depois:
a = a - 20;
b = b + 10;
c = 2;
Você consegue descobrir o significado?
Talvez.
Mas precisa lembrar:
a = Health
b = Coins
c = Level
Agora compare:
int playerHealth = 100;
int playerCoins = 25;
int playerLevel = 1;
playerHealth = playerHealth - 20;
playerCoins = playerCoins + 10;
playerLevel = 2;
A intenção está muito mais clara.
28. Código deve revelar intenção
Uma das ideias que aparecerá repetidamente durante nossa jornada é:
o código deve tentar revelar o que está fazendo.
Isso não significa escrever nomes gigantescos para tudo.
Significa escolher nomes adequados ao contexto.
Por exemplo:
playerHealth
é melhor que:
x
para nosso caso.
Mas algo absurdo como:
currentIntegerValueRepresentingTheHealthOfTheMainPlayer
provavelmente seria desnecessário.
Clareza também envolve equilíbrio.
29. Variáveis diferentes podem ter valores iguais
Considere:
int playerHealth = 100;
int playerEnergy = 100;
Temos duas variáveis.
Mesmo que seus valores sejam iguais:
100
100
elas representam conceitos diferentes.
playerHealth ≠ playerEnergy
semanticamente.
Se reduzirmos:
playerEnergy = 80;
isso não deveria alterar automaticamente:
playerHealth
São estados independentes.
30. O nome faz parte do significado
Observe:
int playerHealth = 100;
int enemyHealth = 100;
Os valores iniciais são iguais.
Mas representam entidades conceitualmente diferentes.
playerHealth
enemyHealth
Isso será extremamente importante quando começarmos a modelar objetos.
Ainda não precisamos de uma classe Player.
Mas o problema que um dia poderá justificá-la começa a nascer.
31. Escopo está esperando por nós
No Capítulo 02 vimos rapidamente que:
{
}
define um bloco.
Agora nossas variáveis estão dentro:
int main()
{
int playerHealth = 100;
}
Isso terá implicações importantes.
Onde playerHealth existe?
Quem consegue utilizá-la?
Quando ela deixa de existir?
Essas perguntas envolvem:
Scope
Lifetime
E terão capítulos próprios.
Não vamos antecipá-las.
32. Não transforme tudo em global
Talvez você encontre exemplos na internet colocando variáveis fora de main:
int playerHealth = 100;
int main()
{
}
Não faremos isso apenas para "facilitar o acesso".
Variáveis globais possuem implicações importantes para:
dependências;
estado compartilhado;
testes;
manutenção;
concorrência;
arquitetura.
Quando tivermos um problema que nos obrigue a discutir esse tipo de decisão, estudaremos com contexto.
Por enquanto nossas variáveis ficam dentro de main.
33. Podemos criar qualquer nome?
Não.
Existem regras da linguagem para identificadores.
Por exemplo, não podemos utilizar uma palavra reservada da linguagem como nome comum de variável.
Algo como:
int return = 10;
não é válido porque:
return
possui significado especial em C++.
Também existem outras regras de formação de identificadores que estudaremos progressivamente.
34. Um nome também não deve começar com número
Algo como:
int 1player = 100;
não representa um identificador válido.
Enquanto:
int player1 = 100;
pode ser sintaticamente válido.
Mas validade sintática não significa automaticamente bom nome.
Sempre precisamos considerar intenção.
35. Case sensitivity novamente
No capítulo anterior aprendemos que C++ diferencia maiúsculas e minúsculas.
Então:
playerHealth
PlayerHealth
PLAYERHEALTH
podem ser identificadores diferentes.
Nossa convenção elimina parte dessa confusão:
Variável
↓
camelCase
↓
playerHealth
Mais tarde:
Class
↓
PascalCase
↓
Player
E constantes:
Constant
↓
UPPERCASE
↓
MAX_PLAYER_HEALTH
Consistência reduz carga mental.
36. E constantes?
Você talvez esteja pensando:
"Se uma variável muda, como representamos algo que não deveria mudar?"
Excelente pergunta.
Teremos:
constants
em um capítulo específico.
Quando chegarmos lá, nossa convenção será:
MAX_PLAYER_HEALTH
em UPPERCASE.
Não precisamos antecipar a implementação ainda.
Primeiro precisamos dominar variáveis.
37. Um pequeno erro proposital
Escreva:
int playerHealth = 100;
std::cout << playerhealth << std::endl;
Observe:
playerHealth
versus:
playerhealth
Faça Build.
O compilador deverá reclamar porque esses identificadores não correspondem.
Use nossa metodologia:
OBSERVAR
↓
LER
↓
LOCALIZAR
↓
COMPARAR
↓
CRIAR HIPÓTESE
↓
CORRIGIR
↓
VALIDAR
Depois restaure:
std::cout << playerHealth << std::endl;
38. Outro erro proposital
Tente:
int playerHealth = 100;
playerHealth = "eighty";
Faça Build.
Temos uma variável declarada como:
int
e estamos tentando atribuir texto a ela.
Não precisamos compreender ainda todos os detalhes do diagnóstico.
A pergunta importante é:
Por que uma variável inteira não aceita simplesmente qualquer tipo de informação?
Essa pergunta nos leva diretamente ao próximo capítulo.
39. Variáveis possuem tipo
Até agora usamos:
int
em:
int playerHealth = 100;
Mas nosso futuro jogo terá informações que não são apenas números inteiros.
Por exemplo:
Health: 100
Player Name: Alex
Speed: 4.5
Is Alive: true
Esses valores possuem naturezas diferentes.
E C++ precisa lidar com essas diferenças.
Isso significa que variáveis e tipos estão profundamente relacionados.
40. Por que não estudar todos os tipos agora?
Porque isso transformaria este capítulo em algo muito maior do que precisa ser.
Hoje nosso objetivo é específico:
compreender por que variáveis existem e utilizá-las para representar estado mutável.
No próximo capítulo, o problema será:
nem toda informação do jogo é igual.
Aí estudaremos tipos com profundidade adequada.
Essa separação mantém nossa progressão clara.
41. Microdesafio — estado inicial do jogador
Crie três variáveis:
playerHealth
playerCoins
playerLevel
com:
100
25
1
Depois produza:
=== PLAYER ===
Health: 100
Coins: 25
Level: 1
Use apenas aquilo que já aprendemos.
42. Uma possível solução
#include <iostream>
int main()
{
int playerHealth = 100;
int playerCoins = 25;
int playerLevel = 1;
std::cout << "=== PLAYER ===" << std::endl;
std::cout << "Health: " << playerHealth << std::endl;
std::cout << "Coins: " << playerCoins << std::endl;
std::cout << "Level: " << playerLevel << std::endl;
return 0;
}
Execute.
Confirme o resultado.
43. Microdesafio — faça o estado mudar
Agora simule:
Player sofre 25 de dano
Player ganha 15 moedas
Player sobe para Level 2
Estado esperado:
Health: 75
Coins: 40
Level: 2
Tente antes de continuar.
44. Uma possível solução
#include <iostream>
int main()
{
int playerHealth = 100;
int playerCoins = 25;
int playerLevel = 1;
playerHealth = playerHealth - 25;
playerCoins = playerCoins + 15;
playerLevel = 2;
std::cout << "=== PLAYER ===" << std::endl;
std::cout << "Health: " << playerHealth << std::endl;
std::cout << "Coins: " << playerCoins << std::endl;
std::cout << "Level: " << playerLevel << std::endl;
return 0;
}
Resultado:
=== PLAYER ===
Health: 75
Coins: 40
Level: 2
Nosso programa agora possui estado que muda durante a execução.
Esse é o resultado observável deste capítulo.
45. O que nosso futuro Game Loop fará?
Ainda estamos longe do Game Loop real.
Mas podemos começar a enxergar a relação.
Hoje fazemos:
Estado inicial
↓
Alteração
↓
Novo estado
↓
Mostrar resultado
Um jogo fará algo conceitualmente muito mais próximo de:
Estado
↓
Input
↓
Update
↓
Novo estado
↓
Render
↓
repetir
Quando chegarmos ao Game Loop, variáveis deixarão de parecer apenas um exercício de fundamentos.
Elas estarão em toda parte.
46. Não precisamos de novas pastas
Nosso projeto continua:
CppGameEngine/
└── main.cpp
Isso é suficiente.
Ainda não existe razão para:
Player/
Stats/
State/
Game/
Engine/
Temos três variáveis e algumas instruções.
Nossa arquitetura deve acompanhar o problema.
Não antecipá-lo.
47. O código final deste capítulo
Podemos manter como evolução prática:
#include <iostream>
int main()
{
int playerHealth = 100;
int playerCoins = 25;
int playerLevel = 1;
std::cout << "=== Initial State ===" << std::endl;
std::cout << "Health: " << playerHealth << std::endl;
std::cout << "Coins: " << playerCoins << std::endl;
std::cout << "Level: " << playerLevel << std::endl;
playerHealth = playerHealth - 20;
playerCoins = playerCoins + 10;
playerLevel = 2;
std::cout << std::endl;
std::cout << "=== Current State ===" << std::endl;
std::cout << "Health: " << playerHealth << std::endl;
std::cout << "Coins: " << playerCoins << std::endl;
std::cout << "Level: " << playerLevel << std::endl;
return 0;
}
Agora existe uma mudança real em relação ao nosso primeiro programa.
Portanto, desta vez faz sentido registrá-la no Git.
48. Nosso commit
Depois de validar:
Save
↓
Build succeeded
↓
Run
↓
resultado correto
verifique:
git status
Depois adicione o arquivo correspondente ao projeto.
Por exemplo:
git add CppGameEngine/main.cpp
Confirme o caminho real no seu repositório antes de executar.
O commit pode ser:
git commit -m "feat: add initial player state variables"
O commit descreve a evolução real:
agora nosso programa possui variáveis representando estado inicial do jogador.
49. Atualizando o CHANGELOG
Como houve evolução funcional real no exemplo principal, podemos registrar em [Unreleased] algo como:
### Added
- Added initial player state variables for health, coins, and level.
- Added state updates during program execution.
- Added console output for initial and current player state.
Depois:
git add CHANGELOG.md
git commit -m "docs: update changelog with player state variables"
Não precisamos alterar o ROADMAP apenas para marcar cada pequeno conceito educacional.
O ROADMAP técnico continuará acompanhando marcos técnicos maiores.
50. O que aprendemos?
Partimos de:
std::cout << "Health: 100" << std::endl;
onde 100 era apenas parte do texto.
Chegamos a:
int playerHealth = 100;
Agora playerHealth representa informação manipulável pelo programa.
Depois:
playerHealth = 80;
e descobrimos que o estado pode mudar durante a execução.
Também começamos a diferenciar:
declaração
inicialização
atribuição
e estabelecemos nossa convenção:
Variáveis
→ camelCase
→ inglês
Como:
playerHealth
playerCoins
playerLevel
Mais importante, nosso programa começou a possuir estado.
Conclusão
Até aqui nosso programa sabia produzir saída.
Agora ele começou a lembrar informações.
Essa diferença parece pequena:
std::cout << "Health: 100";
para:
int playerHealth = 100;
mas representa um avanço fundamental.
Um jogo precisa constantemente manter e transformar estado:
Health
Energy
Coins
Experience
Inventory
Position
Time
Weather
NPC State
Quest State
World State
Hoje demos o primeiro passo.
Começamos com:
playerHealth
playerCoins
playerLevel
e observamos:
Estado inicial
↓
Acontecimento
↓
Estado atualizado
Nosso código ainda é minúsculo.
Mas agora ele não apenas mostra uma frase.
Ele possui informações que podem mudar.
E isso cria imediatamente nossa próxima pergunta:
Se
playerHealthé um número inteiro, como representaremos velocidade, nome, verdadeiro/falso e outras informações do jogo?
Porque nem todo dado é igual.
Próximo capítulo
Capítulo 06 — Tipos: nem toda informação é igual
No próximo artigo vamos partir de um problema concreto:
Health → 100
Speed → 4.5
Player Name → Alex
Is Alive → true
Todos são dados.
Mas não representam a mesma coisa.
Vamos começar a compreender por que C++ precisa conhecer o tipo da informação que estamos armazenando e explorar, progressivamente, os tipos necessários para começar a representar nosso mundo.
Sem tentar decorar uma tabela gigantesca de tipos.
Primeiro veremos o problema.
Depois entenderemos por que o sistema de tipos existe.
E então nosso pequeno estado de jogo começará a ficar muito mais interessante.
Comentários
Ainda não há comentários. Sê o primeiro a comentar!