Ir ao conteúdo
  • Cadastre-se

[BASIC] Movimentar nave em um jogo


Posts recomendados

Estou fazendo um jogo espacial simples no QBASIC/MS-DOS, conforme imagem abaixo

 

ima.png.566601ae44164453d05875c860b92ea2

 

A ideia é que seja algo tipo space invaders, os inimigos (os objetos vermelhos) do meu jogo inclusive se movimentam igual os alienígenas do jogo do atari.

 

A dificuldade que estou tendo é na movimentação da nave do jogador (objeto verde), pois o movimento as vezes trava e a nave fica se movimentando indefinidamente para determinado lado. Eu poderia usar INKEY para facilitar, mas aí a nave não poderia se movimentar na diagonal.

 

Essa é a parte do código, onde eu implementei a lógica o movimento, que está dando problema. Eu usei operações lógicas para ativar/desativar um bit na variável T, conforme o usuário pressiona ou solta a tecla do movimento.

 


...

SELECT CASE K
    CASE 2: END
    CASE KE:        T = T OR KCE
    CASE KE + 128:  T = T AND NOT KCE
    CASE KD:        T = T OR KCD
    CASE KD + 128:  T = T AND NOT KCD
    CASE KC:        T = T OR KCC
    CASE KC + 128:  T = T AND NOT KCC
    CASE KB:        T = T OR KCB
    CASE KB + 128:  T = T AND NOT KCB
  END SELECT

...

  IF T = KCE THEN X = X - 1
  IF T = KCD THEN X = X + 1
  IF T = KCB THEN Y = Y + 1
  IF T = KCC THEN Y = Y - 1
  IF T = KCB + KCD THEN X = X + 1: Y = Y + 1
  IF T = KCB + KCE THEN X = X - 1: Y = Y + 1
  IF T = KCC + KCD THEN X = X + 1: Y = Y - 1
  IF T = KCC + KCE THEN X = X - 1: Y = Y - 1
  IF X < 0 THEN X = 0
  IF Y < 0 THEN Y = 0
  IF Y > CY - 50 THEN Y = CY - 50
  IF X > CX - 50 THEN X = CX - 50
  
  ...
  

 

 

Alguém tem uma ideia de como resolver esse problema do movimento da nave?

 

valeu!

 

Segue o código

SCREEN 12
DEFINT A-Z

RANDOMIZE TIMER

TYPE INFOINIMIGO
  X AS INTEGER  'COORD. X
  Y AS INTEGER  'COORD. Y
  F AS INTEGER  'FLAG CRIAR/DESTRUIR
  D AS INTEGER  'DIRE€AO DO MOVIMENTO
  V AS INTEGER  'VELOCIDADE
END TYPE

CONST ESQUERDA = 0
CONST DIREITA = 1
CONST INIMIGOS = 2
CONST FOGO = 57
CONST KE = 75
CONST KD = 77
CONST KC = 72
CONST KB = 80
CONST KCE = &H40 'ESQUERDA
CONST KCD = &HA  'DIREITA
CONST KCC = &H4  'CIMA
CONST KCB = &H1  'BAIXO
CONST VERDE = 10
CONST BRANCO = 15
CONST CIANO = 11
CONST VERMELHO = 12
CONST AMARELO = 14
CONST CX = 637
CONST CY = 477
CONST SAIR = "Q"

DIM NAVE(2000)
DIM INIMIGO(2000)
DIM DISPARO(8)
DIM VI(0 TO 10) AS INFOINIMIGO


REM ---------------------------------
REM -- CRIAR O ESPA€O,NAVE E INIMIGO
REM ---------------------------------
CIRCLE (20, 10), 10, VERMELHO
CIRCLE (20, 10), 8, VERMELHO
LINE (10, 10)-(30, 20), VERMELHO, B
GET (10, 0)-(30, 20), INIMIGO
CLS

CIRCLE (1, 1), 1, CIANO
GET (0, 0)-(2, 2), DISPARO
CLS

CIRCLE (25, 25), 5, VERDE
LINE (17, 24)-(18, 15), VERDE, B
LINE (33, 24)-(34, 15), VERDE, B
LINE (10, 24)-(40, 26), VERDE, B
CIRCLE (40, 25), 20, VERDE, , , 10
CIRCLE (10, 25), 20, VERDE, , , 10
GET (0, 0)-(50, 50), NAVE
CLS

LINE (0, 0)-(CX, CY), 10, B

REM --------------
REM --- ESTRELAS
REM --------------
FOR I = 0 TO 500
  PSET (RND(1) * (CX - 1), RND(1) * (CY - 1)), BRANCO
NEXT I

CONTA = 0: T = 0: X = 200: Y = 400

POSICAO = 0: PONTOS = 0

FOR I = 0 TO INIMIGOS
  VI(I).X = RND(1) * (CX - 30)
  VI(I).Y = RND(1) * (CY - 300)
  VI(I).F = 1
  VI(I).D = RND(1) * 1
  VI(I).V = 10
  PUT (VI(I).X, VI(I).Y), INIMIGO
NEXT I

N = 0

DO
  CONTA = CONTA + 1
  K = INP(&H60)
 
  REM -----------------------------------
  REM CONTROLAR MOVIMENTOS DOS INIMIGOS
  REM -----------------------------------
    IF N > INIMIGOS THEN N = 0

    IF VI(N).F = 1 THEN PUT (VI(N).X, VI(N).Y), INIMIGO
  
    IF VI(N).D = ESQUERDA THEN VI(N).X = VI(N).X - VI(N).V
    IF VI(N).D = DIREITA THEN VI(N).X = VI(N).X + VI(N).V
  
      IF VI(N).X >= (CX - 50) THEN
        VI(N).X = (CX - 50) - 1
        VI(N).D = ESQUERDA
        VI(N).Y = VI(N).Y + 1
        IF VI(N).Y > 200 THEN VI(N).V = VI(N).V + 1
      END IF

      IF VI(N).X <= 1 THEN
        VI(N).X = 2
        VI(N).D = DIREITA
        VI(N).Y = VI(N).Y + 1
        IF VI(N).Y > 200 THEN VI(N).V = VI(N).V + 1
      END IF
  
     
  PUT (X, Y), NAVE
  WAIT &H3DA, 8
  PUT (X, Y), NAVE
 
  IF VI(N).F = 1 THEN PUT (VI(N).X, VI(N).Y), INIMIGO
  N = N + 1

  IF K = KE THEN
    T = T OR KCE
  ELSEIF K = (KE + 128) THEN
    T = T AND NOT KCE
  END IF
 
  SELECT CASE K
    CASE 2: END
    CASE KE:        T = T OR KCE
    CASE KE + 128:  T = T AND NOT KCE
    CASE KD:        T = T OR KCD
    CASE KD + 128:  T = T AND NOT KCD
    CASE KC:        T = T OR KCC
    CASE KC + 128:  T = T AND NOT KCC
    CASE KB:        T = T OR KCB
    CASE KB + 128:  T = T AND NOT KCB
  END SELECT

  IF K = FOGO THEN DISPAROU = 1
 
  IF DISPAROU = 1 THEN
    IF POSICAO = 0 THEN DX = X: DY = Y
   
    IF DY > 0 THEN PUT (DX + 17, DY), DISPARO
    IF POSICAO = 0 THEN PUT (DX + 17, DY), DISPARO
   
    DY = DY - 5
    
    POSICAO = 1
    
    IF DY > 0 THEN PUT (DX + 17, DY), DISPARO
       
   
    IF DY <= 0 THEN
      POSICAO = 0
      DISPAROU = 0
    END IF

  END IF

  IF DISPAROU = 1 THEN
    FOR I = 0 TO INIMIGOS
      IF (VI(I).X <= DX + 20 AND VI(I).X >= DX - 3) THEN
        IF (DY <= VI(I).Y + 10 AND DY >= VI(I).Y - 10) THEN
          IF VI(I).F = 1 THEN
            PUT (VI(I).X, VI(I).Y), INIMIGO
            VI(I).F = 0
            PONTOS = PONTOS + 1
          END IF
        END IF
      END IF
    NEXT I
  END IF

  IF T = KCE THEN X = X - 1
  IF T = KCD THEN X = X + 1
  IF T = KCB THEN Y = Y + 1
  IF T = KCC THEN Y = Y - 1
  IF T = KCB + KCD THEN X = X + 1: Y = Y + 1
  IF T = KCB + KCE THEN X = X - 1: Y = Y + 1
  IF T = KCC + KCD THEN X = X + 1: Y = Y - 1
  IF T = KCC + KCE THEN X = X - 1: Y = Y - 1
  IF X < 0 THEN X = 0
  IF Y < 0 THEN Y = 0
  IF Y > CY - 50 THEN Y = CY - 50
  IF X > CX - 50 THEN X = CX - 50

  DEF SEG = &H40
  POKE &H1A, PEEK(&H1C)

  IF CONTA = 50 THEN CONTA = 0
  IF PONTOS = INIMIGOS + 1 GOTO FIM
LOOP


FIM:
  LOCATE 1, 1: PRINT "FIM: "; PONTOS; " PONTO(S)"

 

 

 

Link para o comentário
Compartilhar em outros sites

  • 1 ano depois...

Ola, apesar de ter mais de ano a postagem, vou postar pois pode ser útil caso ainda deseje alterar ou continuar seu projeto, ou mesmo para outros que procurem por isso!

Também estive fazendo um game baseado na atari, o primeiro problema que tive foi com movimento do personagem, pesquisando um pouco encontrei a base principal para executar esse movimento sem problemas de conflito!

O fundamental no qbasic e ter a rotina de teclado correta, a partir disso fica bastante descomplicado fazer qualquer coisa:

 

a rotina e a seguinte:

 

start:
DO
    _LIMIT 160
    Cmmnd$ = UCASE$(INKEY$)
LOOP UNTIL Cmmnd$ = CHR$(O) + "H" OR Cmmnd$ = CHR$(O) + "P" OR Cmmnd$ = CHR$(O) + "M" OR Cmmnd$ = CHR$(O) + "K" OR Cmmnd$ = CHR$(27)
IF Cmmnd$ = CHR$(0) + "K" THEN PRINT Cmmnd$
IF Cmmnd$ = CHR$(0) + "M" THEN PRINT Cmmnd$
IF Cmmnd$ = CHR$(0) + "P" THEN PRINT Cmmnd$
IF Cmmnd$ = CHR$(0) + "H" THEN PRINT Cmmnd$
IF Cmmnd$ = CHR$(27) GOTO finish
GOTO start
finish:

Cada vez que você pressiona uma tecla a rotina do loop é interrompida, e continua nos IF que vai verficar a tecla que foi precionada, e executar um comando, nesse caso o print mostrando qual codigo da tecla que foi precionada, nesse exemplo as teclas de seta, e ESC para interromper a rotina e sair.

 

Observe que dentro da rotina do loop existe o valor _LIMIT 160, ele corresponde a um atraso na velocidade do loop é necessário, também porque ajusta o loop a velocidade processador da maquina, sem isso você pode ter problemas quando usando o programa em computadores diferentes.

 

http://www.qb64.net/wiki/index.php/LIMIT

 

Se quiser pode dar uma olhada no jogo que criei, deixei disponível o código em basic, rotina completa, e algumas rotinas básicas para analise.

 

https://www.youtube.com/channel/UCw4fZc7jxV_dHS1OLDPvxnw

 

https://mega.nz/#F!So4l0JaL!rpwQ-JK887H8Y18KHjJc0w

 

Tem o arquivo "Minimum of instruction.bas" que possui uma rotina de múltiplos movimentos.

 

 

 

 

 

Link para o comentário
Compartilhar em outros sites

  • 3 semanas depois...

Depois vendo o post novamente me dei conta que você não quer usar inkey$, pois não da para usar duas teclas ao mesmo tempo, analisando usa rotina é muito boa, então resolvi adaptar para meu game

Consegui fazer funcionar, essa sua rotina complica pois ao apertar uma tecla ela tende a fazer muitas contagens no loop, dando chamada de função inválida por facilmente ultrapassar os limites da contagem, uma solução é usar o _LIMIT depois usar um desvio no loop para contar numero por numero, bom deixo uma rotina básica, para alguém que esteja a procura disso.

CONST KL = 75
CONST KR = 77
CONST KU = 72
CONST KD = 80
CONST KCL = &H40 'LEFT
CONST KCR = &HA 'RIGHT
CONST KCU = &H4 'UP
CONST KCD = &H1 'DOWN
scrennn% = 1000
'------------- velocit= items, velocit2 = square
velocit% = 12
velocit2% = 20
PALETTE 0, 0
' -------------------------------- Creating items
' -------------------------------- Creating test item
Test$ = STRING$(2, CHR$(1))
Xtest% = 5
YTest% = 5
' -------------------------------- Defining square location
a% = 41
b% = 22
' ------------------------------ start
start:
IF countmove% = velocit2% THEN
    IF T = KCL THEN a% = a% - 1
    IF T = KCR THEN a% = a% + 1
    IF T = KCD THEN b% = b% + 1
    IF T = KCU THEN b% = b% - 1
    IF T = KCD + KCR THEN a% = a% + 1
    IF T = KCD + KCL THEN a% = a% - 1
    IF T = KCU + KCR THEN a% = a% + 1
    IF T = KCU + KCL THEN a% = a% - 1
END IF
IF scrennn% = 1000 THEN GOTO home
' -------------------------------- home screen
home:
CLS
IF a% = 3 THEN a% = a% + 1
IF a% = 79 THEN a% = a% - 1
IF b% = 25 THEN b% = b% - 1
IF b% = 1 THEN b% = b% + 1
COLOR 1, 7
FOR i% = 1 TO 24
    LOCATE i%, 1
    PRINT STRING$(2, CHR$(219));
NEXT i%
FOR i% = 1 TO 24
    LOCATE i%, 79
    PRINT STRING$(2, CHR$(219));
NEXT i%
LOCATE 1, 1
PRINT STRING$(80, CHR$(219));
LOCATE 25, 1
PRINT STRING$(80, CHR$(219));
GOTO items
' ----------------------------------------items instructions
items:
' ---------------------------------------- show items
' ---------------------------------------- Square item
COLOR 1, 7
LOCATE b%, a%
PRINT STRING$(1, CHR$(219));
LOCATE b%, a% - 1
PRINT STRING$(1, CHR$(219));
' ---------------------------------------- Test item
COLOR 0, 7
LOCATE YTest%, Xtest%
PRINT Test$;
GOTO keyloop
' ---------------------------------------------------------------------Movement of objects
move:
Xtest% = Xtest% + 1
IF Xtest% = 77 THEN Xtest% = 2
GOTO start
keyloop:
' -------------------------------------------------------------------------------------- loop keyboard
IF countmove% = velocit2% THEN
    countmove% = 0
    IF T = KCD + KCR THEN b% = b% + 1: GOTO start
    IF T = KCD + KCL THEN b% = b% + 1: GOTO start
    IF T = KCU + KCR THEN b% = b% - 1: GOTO start
    IF T = KCU + KCL THEN b% = b% - 1: GOTO start
END IF
DO
    countmove% = countmove% + 1
    IF countmove% = velocit% GOTO move
    IF countmove% = velocit2% GOTO start
    _LIMIT 900
    K = INP(&H60)
    IF K = KL THEN
        T = T OR KCL
    ELSEIF K = (KL + 128) THEN
        T = T AND NOT KCL
    END IF
    SELECT CASE K
        CASE 1: END
        CASE KL: T = T OR KCL
        CASE KL + 128: T = T AND NOT KCL
        CASE KR: T = T OR KCR
        CASE KR + 128: T = T AND NOT KCR
        CASE KU: T = T OR KCU
        CASE KU + 128: T = T AND NOT KCU
        CASE KD: T = T OR KCD
        CASE KD + 128: T = T AND NOT KCD
    END SELECT
LOOP

 

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!