Minilop Retroware

MPAGD Avanzado

Plataformas móviles horizontales en MPAGD

14 de noviembre de 2020

Las plataformas que se mueven son un clásico de la mayoría de los juegos de plataformas, un género para el que MPAGD es ideal a la hora de programar juegos retro de 8 bits fluidos. Sin embargo, la herramienta no incluye un script 'listo para usar' para plataformas que se muevan horizontalmente.

Es algo que intenté resolver en mi primer juego, Cocoa and the Time Machine. Primero, tenía en mente una idea de cómo quería que funcionaran. Había visto algunos intentos en otros juegos de AGD que se acercaban, pero no eran exactamente lo que yo quería. Sobre todo, requerían que el jugador pulsara la tecla de dirección para mantenerse en la plataforma, de modo que si la plataforma se movía a la derecha...el jugador tenía que pulsar la tecla derecha para seguir encima.

Pero eso no era lo que yo quería. Quería que el jugador aterrizara en la plataforma y fuera transportado automáticamente, pero que además pudiera moverse a izquierda y derecha sobre la plataforma para ajustar su posición, y saltar encima y fuera de ella.

Tras muchísimos intentos, conseguí un efecto que funcionaba, aunque visualmente no era tan bueno como podría haber sido, en Cocoa and the Time Machine

Como puedes ver, Cocoa puede caminar o saltar sobre la plataforma y fuera de ella, y también puede ajustar su posición encima. El problema es más bien estético...el sprite de Cocoa va, bueno, un poco a trompicones.

El código para esto implicaba usar unas cuantas variables para saber si el jugador estaba o no sobre la plataforma, la dirección de avance actual de la plataforma, etcétera.

En 24 Hour Parsley People me propuse mejorarlo....y aquí tienes el código nuevo aplicado al juego original:

Mucho mejor.

Así se hace.

Primero, en el evento del sprite de la 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

Bien, eso controlará cómo funciona la plataforma: comprueba si el jugador está sobre ella y, si es así, lo mantiene ahí y lo mueve, pero sigue permitiéndole ajustar su posición.

Ahora necesitaremos algo de código para el evento del jugador:

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

Fíjate en que en el código anterior también compruebo con antelación si la plataforma va a chocar contra un bloque de pared; esto es útil para que el jugador siga moviéndose en la dirección correcta cuando la propia plataforma cambia de dirección...el desfase entre ambos eventos tiene además un beneficio accidental: simula inercia cuando el jugador cambia de dirección, como puedes ver en el vídeo de arriba...¡un extra!

Este código también se presta muy bien a poner obstáculos en el camino que el jugador tenga que saltar, como estos de 24 Hour Parsley People...

Seguro que gente mucho más lista que yo podrá mejorarlos; yo solo estoy contento de haber conseguido mejorarlos de mi primer juego a mi segundo :)

También lo usé en el tercer episodio de 24 Parsley People, pero de una forma ligeramente distinta. Esta vez usé mi código de Pushables (ya escribiré sobre él en otro blog), pero cuando un determinado objeto empujable se empuja al agua, se convierte en una plataforma móvil horizontal....a ver si me explico...

Habría quedado mejor si no me hubiera quedado sin memoria, porque tenía otro fotograma para el tronco, de modo que se viera de lado cuando flota en el agua...en fin, así es el código de 8 bits en 39K de memoria disponible :)

¡Espero que te sirva de ayuda!

Todo MPAGD Avanzado