Minilop Retroware

MPAGD Avançado

Plataformas móveis horizontais em MPAGD

14 de novembro de 2020

As plataformas que se movem são um clássico da maioria dos jogos de plataformas, um género para o qual o MPAGD é ideal na programação de jogos retro de 8 bits fluidos. No entanto, a ferramenta não traz um script 'pronto a usar' para plataformas que se movam na horizontal.

Foi algo que tentei resolver no meu primeiro jogo, Cocoa and the Time Machine. Primeiro, tinha em mente uma ideia de como queria que funcionassem. Tinha visto algumas tentativas noutros jogos AGD que se aproximavam, mas não era bem o que eu queria. Predominantemente exigiam que o jogador premisse a tecla de direção para se manter na plataforma, por isso, se a plataforma se movesse para a direita...o jogador tinha de premir a tecla da direita para se manter nela.

Mas não era isso que eu queria. Queria que o jogador aterrasse na plataforma e fosse transportado automaticamente, mas que também pudesse mover-se para a esquerda e para a direita em cima da plataforma para ajustar a sua posição, e saltar para dentro e para fora dela.

Depois de muitas, muitas tentativas, consegui um efeito que funcionava, embora visualmente não fosse tão bom como poderia ter sido, em Cocoa and the Time Machine

Como podes ver, o Cocoa pode andar ou saltar para cima da plataforma e para fora dela, e também pode ajustar a sua posição em cima dela. O problema é mais a estética...o sprite do Cocoa anda, bem, um pouco aos solavancos.

O código para isto envolvia usar algumas variáveis para saber se o jogador estava ou não na plataforma, a direção de deslocação atual da plataforma, e assim por diante.

Em 24 Hour Parsley People propus-me melhorá-lo....e aqui está o código novo aplicado ao jogo original:

Muito melhor.

Eis como se faz.

Primeiro, no evento do sprite da plataforma:

EVENT SPRITETYPE1


IF COLLISION 0                          	; first check if the player is colliding with the platform, if so:
	LET P = Y                              	; store the Y value of the platform in P
	OTHER					; now switch to the player sprite    
	IF P > Y				; is player above the platform?
		SUBTRACT Y FROM P		; if so, by how much?
		IF P <= 4			; if less than 4 px  landing is unsuccessful!
			ENDSPRITE						
			EXIT
		ELSE                                 
			ADD Y TO P		; reset P (the platforms Y co-ord)
			LET Y = P		; make the players Y = the platforms Y
			SUBTRACT 16 FROM Y	; now put the  player on top of the platform
			STOPFALL		; and keep the player on top
			IF KEY LEFT		; lets add in some controls for movement on the platform
				IF CANGOLEFT
					SPRITELEFT
				ENDIF
			ENDIF
			IF KEY RIGHT
				IF CANGORIGHT
					SPRITERIGHT	
				ENDIF
			ENDIF
			ENDSPRITE
		ENDIF

		IF DIRECTION = 0		; 0 means the platform is moving left but isnt carrying a player
			LET DIRECTION = 2 	; so if it was 0 when the player landed use 2 to denote CARRYING LEFT
		ELSE				; if not 0 it must be going right
			LET DIRECTION = 3	; so we'll use 3 to denote the platform is CARRYING RIGHT
		ENDIF
		IF DIRECTION = 2		; now that the platform is carrying left
			IF CANGOLEFT		; check it can still go left
				SPRITELEFT	; in which case continue
				OTHER 		; and set the players Direction to 5 (which we use in the player event)
				IF CANGOLEFT
					LET DIRECTION = 5
				ENDIF
				ENDSPRITE	; switch back to the platform
			ELSE                     
				LET DIRECTION = 3	; if platfrom cant go left anymore, switch to carrying right
			ENDIF
		ENDIF
		IF DIRECTION = 3			; now that the platform is carrying right
			IF CANGORIGHT			; check it can still go right
				SPRITERIGHT		; in which case continue
				OTHER
				IF CANGORIGHT
					LET DIRECTION = 6	; and set the players Direction to 6 (which we use in the player event)
				ENDIF
				ENDSPRITE			; switch back to the platform
			ELSE
				LET DIRECTION = 2		; if platfrom cant go right anymore, switch to carrying left
			ENDIF
		ENDIF
		EXIT
	ELSE
		ENDSPRITE
	ENDIF
ENDIF
								; if the player and platform are not colliding any more
IF DIRECTION = 2						; if it was set to CARRYING LEFT
	LET DIRECTION = 0					; switch to normal left movement (not carrying the player)
ENDIF

IF DIRECTION = 3						; if it was set to CARRYING RIGHT
	LET DIRECTION = 1					; switch to normal right movement (not carrying the player)
ENDIF

IF DIRECTION = 0						; normal left movement of the platform (not carrying the player)
	IF CANGOLEFT
		SPRITELEFT
	ELSE
		LET DIRECTION = 1
	ENDIF
ENDIF
IF DIRECTION = 1 						; normal right movement of the platform (not carrying the player)
	IF CANGORIGHT
		SPRITERIGHT
	ELSE
		LET DIRECTION = 0
	ENDIF
ENDIF

Bem, isso vai controlar o funcionamento da plataforma: verifica se o jogador está na plataforma e, se estiver, mantém-no lá e move-o, mas continua a permitir-lhe ajustar a sua posição.

Agora vamos precisar de algum código para o evento do jogador:

IF DIRECTION = 5                          ; is the players direction set to being carried left?
   IF CANGOLEFT                           ; if so, can the player go left?
      SPRITELEFT                          ; if so, move them left
   ELSE                                   ; if not
      LET DIRECTION = 0                   ; set the players direction to normal left
   ENDIF
   ADD 16 TO Y                            ; check ahead to see if the platform is about to reach a wall block
   SUBTRACT 2 FROM X
   GETBLOCK X Y
   SUBTRACT 16 FROM Y
   ADD 2 TO X
   IF BLOCK = WALLBLOCK                   ; if it is about to reach a wallblock
      LET DIRECTION = 0                   ; change the player direction to normal left
   ENDIF
  
ENDIF


IF DIRECTION = 6                          ; is the players direction set to being carried right?
   IF CANGORIGHT                          ; if so can the player go right?
      SPRITERIGHT                         ; if so, move them right
   ELSE                                   ; if not
      LET DIRECTION =1                    ; set the players direction to normal right
   ENDIF   
   ADD 16 TO Y                            ; check ahead to see if the platform is about to reach a wall block 
   ADD 16 TO X
   GETBLOCK X Y
   SUBTRACT 16 FROM Y
   SUBTRACT 16 FROM X
   IF BLOCK = WALLBLOCK                   ; if it is about to reach a wallblock
      LET DIRECTION = 1                   ; change the player direction to normal left
   ENDIF
ENDIF

Repara que no código acima também estou a verificar antecipadamente se a plataforma vai bater num bloco de parede; isto é útil para manter o jogador a mover-se na direção correta quando a própria plataforma muda de direção...o desfasamento entre os dois eventos tem ainda um benefício acidental: simula inércia quando o jogador muda de direção, como podes ver no vídeo acima...um bónus!

Este código também se presta muito bem a colocar obstáculos no caminho que o jogador tem de saltar, como estes em 24 Hour Parsley People...

Tenho a certeza de que pessoas muito mais inteligentes do que eu conseguirão melhorá-los; eu fico apenas contente por ter conseguido melhorá-los do meu primeiro jogo para o segundo :)

Também usei isto no terceiro episódio de 24 Parsley People, mas de uma forma ligeiramente diferente. Desta vez usei o meu código de Pushables (vou escrever sobre isso noutro dia no blogue), mas quando um determinado objeto empurrável é empurrado para a água, torna-se uma plataforma móvel horizontal....é isto que quero dizer...

Teria ficado melhor se eu não tivesse ficado sem memória, porque tinha outro fotograma para o tronco, para que se visse de lado quando está a flutuar na água...enfim, é assim o código de 8 bits em 39K de memória disponível :)

Espero que isto ajude!

Todo o MPAGD Avançado