PC SOFT

FOROS PROFESIONALES
WINDEVWEBDEV y WINDEV Mobile

Inicio → WINDEV 25 → Jogo *Space Invaders* em WLanguage, utilizando Orientação a Objetos (OOP)
Jogo *Space Invaders* em WLanguage, utilizando Orientação a Objetos (OOP)
Iniciado por Boller, 17,mar. 2025 17:09 - No hay respuesta
Miembro registrado
4.520 mensajes
Publicado el 17,marzo 2025 - 17:09
Boa tarde

Vou criar uma implementação simplificada do jogo *Space Invaders* em WLanguage, utilizando Orientação a Objetos (OOP) e aplicando as melhores práticas, como encapsulamento, responsabilidade única (SOLID), modularidade e código limpo. O jogo incluirá uma nave controlada pelo jogador, alienígenas que se movem e descem, e tiros disparados pela nave. Por ser WLanguage (WinDev), focaremos em uma versão funcional para console, com sugestões para interface gráfica no final.

---

### Estrutura do Projeto
Dividiremos o código em classes com responsabilidades claras:
- **`Nave`**: Representa a nave do jogador e seus disparos.
- **`Alien`**: Representa um inimigo no tabuleiro.
- **`Tabuleiro`**: Gerencia o estado do jogo (nave, aliens, tiros) e a lógica de colisão.
- **`Jogo`**: Controla o fluxo do jogo e a interação com o usuário.

---

### Passo 1: Código das Classes

1. **Classe `Nave`**
Representa a nave do jogador e seus disparos.

```wlanguage
CLASS Nave
PRIVATE
nPosX IS int = 5 // Posição horizontal (0 a 9)
nTiros IS array of int // Posições Y dos tiros (subindo)
PUBLIC
PROCEDURE Construtor()
nPosX = 5
nTiros = []
END
PROCEDURE Mover(direcao IS int)
nPosX += direcao
IF nPosX < 0 THEN nPosX = 0
IF nPosX > 9 THEN nPosX = 9
END
PROCEDURE Atirar()
ArrayAdd(nTiros, 9) // Tiro começa na linha 9 (base da nave)
END
FUNCTION GetPosX() IS int
RETURN nPosX
END
FUNCTION GetTiros() IS array of int
RETURN nTiros
END
PROCEDURE AtualizarTiros()
LOCAL
i IS int
FOR i = ArrayCount(nTiros) DOWNTO 1
nTiros[i] -= 1 // Tiro sobe
IF nTiros[i] < 0 THEN
ArrayDelete(nTiros, i) // Remove tiro fora do tabuleiro
END
END
END
END
```
- **Encapsulamento**: Posição e tiros são privados.
- **Responsabilidade**: Gerencia a nave e os disparos.

2. **Classe `Alien`**
Representa um alienígena no tabuleiro.

```wlanguage
CLASS Alien
PRIVATE
nPosX IS int
nPosY IS int
bVivo IS boolean
PUBLIC
PROCEDURE Construtor(nX IS int, nY IS int)
nPosX = nX
nPosY = nY
bVivo = True
END
FUNCTION GetPosX() IS int
RETURN nPosX
END
FUNCTION GetPosY() IS int
RETURN nPosY
END
FUNCTION EstaVivo() IS boolean
RETURN bVivo
END
PROCEDURE Mover(direcao IS int)
nPosX += direcao
END
PROCEDURE Descer()
nPosY += 1
END
PROCEDURE Matar()
bVivo = False
END
END
```
- **Encapsulamento**: Estado interno privado.
- **Responsabilidade**: Gerencia posição e estado de um alien.

3. **Classe `Tabuleiro`**
Gerencia o estado do jogo, incluindo nave, aliens e colisões.

```wlanguage
CLASS Tabuleiro
PRIVATE
oNave IS Nave
arrAliens IS array of Alien
nDirecaoAliens IS int = 1 // 1 = direita, -1 = esquerda
nVelocidade IS int = 1
PUBLIC
PROCEDURE Construtor()
oNave = NEW Nave()
arrAliens = []
// Cria 5 aliens na linha superior
FOR i = 0 TO 4
ArrayAdd(arrAliens, NEW Alien(i*2, 0))
END
END
PROCEDURE MoverNave(direcao IS int)
oNave.Mover(direcao)
END
PROCEDURE Atirar()
oNave.Atirar()
END
PROCEDURE Atualizar()
// Atualiza tiros
oNave.AtualizarTiros()
// Move aliens
LOCAL
i IS int
bBorda IS boolean = False
FOR i = 0 TO ArrayCount(arrAliens)-1
IF arrAliens[i].EstaVivo() THEN
arrAliens[i].Mover(nDirecaoAliens)
IF arrAliens[i].GetPosX() >= 9 OR arrAliens[i].GetPosX() <= 0 THEN
bBorda = True
END
END
END
IF bBorda THEN
nDirecaoAliens = -nDirecaoAliens
FOR i = 0 TO ArrayCount(arrAliens)-1
IF arrAliens[i].EstaVivo() THEN
arrAliens[i].Descer()
END
END
END
// Verifica colisões
FOR i = ArrayCount(oNave.GetTiros()) DOWNTO 1
FOR j = ArrayCount(arrAliens)-1 DOWNTO 0
IF arrAliens[j].EstaVivo() AND
arrAliens[j].GetPosX() = oNave.GetPosX() AND
arrAliens[j].GetPosY() = oNave.GetTiros()[i] THEN
arrAliens[j].Matar()
ArrayDelete(oNave.GetTiros(), i)
BREAK
END
END
END
END
FUNCTION EstaTerminado() IS boolean
LOCAL
i IS int
bTodosMortos IS boolean = True
FOR i = 0 TO ArrayCount(arrAliens)-1
IF arrAliens[i].EstaVivo() THEN
bTodosMortos = False
IF arrAliens[i].GetPosY() >= 9 THEN
RETURN True // Aliens chegaram à base
END
END
END
RETURN bTodosMortos // Vitória se todos aliens morreram
END
FUNCTION ToString() IS string
LOCAL
sTab IS string = ""
arrGrid IS array of string[10,10] = " "
i, j IS int
// Marca aliens
FOR i = 0 TO ArrayCount(arrAliens)-1
IF arrAliens[i].EstaVivo() THEN
arrGrid[arrAliens[i].GetPosY(), arrAliens[i].GetPosX()] = "A"
END
END
// Marca tiros
FOR i = 0 TO ArrayCount(oNave.GetTiros())-1
arrGrid[oNave.GetTiros()[i], oNave.GetPosX()] = "|"
END
// Marca nave
arrGrid[9, oNave.GetPosX()] = "V"
// Monta string
FOR i = 0 TO 9
FOR j = 0 TO 9
sTab += arrGrid[i,j] + " "
END
sTab += Charact(13)
END
RETURN sTab
END
END
```
- **Encapsulamento**: Estado interno privado.
- **Responsabilidade**: Gerencia o tabuleiro e a lógica do jogo.

4. **Classe `Jogo`**
Controla o fluxo e a interação com o usuário.

```wlanguage
CLASS Jogo
PRIVATE
oTabuleiro IS Tabuleiro
PUBLIC
PROCEDURE Iniciar()
oTabuleiro = NEW Tabuleiro()
Info("Bem-vindo ao Space Invaders!" + Charact(13) +
"Comandos: E (esquerda), D (direita), T (atirar), S (sair)")
LOOP
Info(oTabuleiro.ToString())
sComando IS string = Upper(Input("Digite o comando: "))
SWITCH sComando
CASE "E": oTabuleiro.MoverNave(-1)
CASE "D": oTabuleiro.MoverNave(1)
CASE "T": oTabuleiro.Atirar()
CASE "S": BREAK
OTHER CASE: Info("Comando inválido!")
END
oTabuleiro.Atualizar()
IF oTabuleiro.EstaTerminado() THEN
Info(oTabuleiro.ToString())
IF ArrayCount(oTabuleiro.arrAliens) = 0 THEN
Info("Vitória! Todos os aliens foram destruídos!")
ELSE
Info("Derrota! Os aliens chegaram à base!")
END
BREAK
END
END
END
END
```
- **Separação de Camadas**: Coordena interação e delega lógica ao `Tabuleiro`.

---

### Passo 2: Implementação no WinDev
1. Crie um projeto no WinDev.
2. Adicione as classes em um arquivo `.wls`.
3. No evento principal (ex.: botão "Jogar"), chame:
```wlanguage
oJogo IS Jogo
oJogo = NEW Jogo()
oJogo.Iniciar()
```

4. **Interface Gráfica (sugestão)**:
- Use uma tabela 10x10 ou controles gráficos (ex.: imagens para nave, aliens, tiros).
- Atualize a UI com `oTabuleiro.ToString()` ou acesse os objetos diretamente.
- Use eventos de teclado (ex.: `KeyPress`) para capturar "E", "D", "T".

---

### Melhores Práticas Aplicadas
- **SOLID**:
- **S**: Cada classe tem uma única responsabilidade (`Nave` para jogador, `Alien` para inimigos, `Tabuleiro` para lógica).
- **O**: Fácil de estender (ex.: mais aliens ou níveis).
- **I**: Métodos públicos são específicos.
- **D**: Dependências injetadas (`Jogo` usa `Tabuleiro`).

- **Código Limpo**:
- Nomes descritivos (`Mover`, `Atirar`).
- Funções curtas e claras.
- Validações para limites do tabuleiro.

---

### Passo 3: Melhorias Possíveis
- **Pontuação**: Adicione pontos por alien destruído.
- **Velocidade**: Aumente a dificuldade com o tempo.
- **UI Avançada**: Use sprites no WinDev (ex.: imagens para nave e aliens).
- **Som**: Integre sons com `SoundPlay` do WinDev.

Se precisar de ajustes ou da implementação gráfica, é só avisar!Je suis

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/