[4.5.6] Quick tutorial: Adding the ability to switch between the Player and another object

dale_coop

Moderator
Staff member
Here's a quick tutorial so add the ability to switch your Player into another player object:

transform.gif


I will share here an input script to do that, but it could be used on a tile script or an AI action script...


1) Make your Other player object, for that I recommend to use one of the Game Objects (for this tutorial I will use the last one, the object #15, I will name it "Deamon").
Set it like you did for the Player object, "player" and "Persistent", reactions, a speed / acceleration, animations, ... and the bounding box:

2020-10-11-20-23-22-NES-MAKER-4-5-6-Version-0x176-Adventure-Tutorial-MST.png



2) Now, create a new, input script "SwitchPlayerObject.asm" with that:

Code:
	;; SCRIPT to Switch between my Player object and my Deamon game object
switchPlayer:
	;; if the player has this ability (if you don't want that limitation, comment out those 4 lines):
    LDA weaponsUnlocked
    AND #%00000100			;; weapon 3 unlocked
    BNE canSwitchPlayer		;; he can switch into another object
    JMP doneSwitchingPlayer
	
canSwitchPlayer:

    TXA
    PHA
		;; first, we will store every placement informations about the player 
        LDX player1_object
        LDA Object_x_hi,x		;; the current horizontal position
        ; CLC
        ; ADC #$04
        STA tempA
        LDA Object_y_hi,x		;; the current vertical position
        ; CLC
        ; ADC #$04
        STA tempB
        LDA Object_direction,x	;; the current facing and movements
        ; AND #%00000111
        STA tempC
		
		;; now, depending of the current object used by the player:
		;; we can switch to the new object, or switch back the normal one
		LDA Object_type,x
		BNE +changeIntoNormal
			LDA #15				;; <-- HERE ! the new player object to transform into
			STA tempD
			JMP continueChangePlayerInto
		changeIntoNormal:
			LDA #00				;; the normal player object
			STA tempD
			
        continueChangePlayerInto:
		DestroyObject							;; we destroy the current object
		CreateObject tempA, tempB, tempD, #$00	;; and create the new one
		TXA
		STA player1_object						;; store that new created object in the Player 1 var
		STA camObject
		LDA tempC								;; set back the player directions
		STA Object_direction,x
    PLA
    TAX

doneSwitchingPlayer:	
    RTS

Note: If you want to use another game object than the #15, you can modify it at line 31 of the script.


3) Now, assign that "SwitchPlayerObject.asm" script to your button (I will use the "release" "SELECT" button, for that tutorial) :



Also, you need to assign (again) all the input scripts to your OTHER object (the "Deamon" object in my case), for moving left/right/... stopMoving.. etc the same scripts than the ones assigned to your Player.


4) my script is made to be used as an ability, you can unlock (from an NPC or a pickup... as you want), but if you want to use it from the start, just set "on" the "weapon 3" check box in the Project Infos ("Initial Data"):

 

drexegar

Member
Pretty awesome! In klepsydra, I use directions to have different characters. This makes it far limited of course, but good for space shooters and simpler games where you want multiple ship or characters and you don't want to waste input space. Then I had to write a pallete swap code to check for characters to load up the right colors for given character.
 

offparkway

Active member
Been using this in a brawler game. If I switch players, the graphic tiles glitch on the seams of the scrolling screens.
Example: I switch players and walk right. After 1.5 screens, there is a vertical line of incorrect graphic tiles where the screen loaded. This happens even if I warp to another screen.

Any way to avoid this?


Capture1.JPG
 

offparkway

Active member
...or heres a thought: my graphics are laid out the same for each player, on the same tile sheet. Is there maybe a way to not change the player1_object at all, but instead just swap out the tiles?
 

davev

New member
I don't know if this is related, but I have a similar problem in a scrolling game. If I walk to any screen but the initial screen, my player disappears when I try to swap. On the initial screen it works flawlessly. Any idea what might be going on?
 

davev

New member
OK maybe this can help you offparkway - I fixed my bug - my code needed to know which screen to put the object -

I made this change to the code that swaps the objects:

Code:
LDA Object_screen,x  ;; the current screen
STA tempD

DestroyObject                           ;; we destroy the current object
CreateObjectOnScreen tempA, tempB, #00, #$01, tempD    ;; and create the new one
 

ronin1011

Member
OK maybe this can help you offparkway - I fixed my bug - my code needed to know which screen to put the object -

I made this change to the code that swaps the objects:

Code:
LDA Object_screen,x  ;; the current screen
STA tempD

DestroyObject                           ;; we destroy the current object
CreateObjectOnScreen tempA, tempB, #00, #$01, tempD    ;; and create the new one
Hey where did you plug your new code into the original script? I'm using the h_shooter mod
Thanks
 
Last edited:

IMBrendan

Member
You were really close - this code plugged into Dale's original will allow you to transform on any screen, however it will only swap you to the other player1_object once and then trap you there.
Code:
LDA Object_screen,x  ;; the current screen
STA tempD

DestroyObject                           ;; we destroy the current object
CreateObjectOnScreen tempA, tempB, #00, #$01, tempD    ;; and create the new one

I took a couple of minutes a tweaked the two codes and now I have a fully functioning transformation. This is a godsend for my project - I honest thought I was going to have to warp from screen to screen at edge in a metroidvania game. Here's what I plugged in instead;

HTML clipboard

;; SCRIPT to Switch between my Player object and my Deamon game object
switchPlayer:
; ;; if the player has this ability (if you don't want that limitation, comment out those 4 lines):
; LDA weaponsUnlocked
; AND #%00000100 ;; weapon 3 unlocked
; BNE canSwitchPlayer ;; he can switch into another object
; JMP doneSwitchingPlayer

canSwitchPlayer:

TXA
PHA
;; first, we will store every placement informations about the player
LDX player1_object
LDA Object_x_hi,x ;; the current horizontal position
; CLC
; ADC #$04
STA tempA
LDA Object_y_hi,x ;; the current vertical position
; CLC
; ADC #$04
STA tempB
; LDA Object_direction,x ;; the current facing and movements
; AND #%00000111
; STA tempC

;; now, depending of the current object used by the player:
;; we can switch to the new object, or switch back the normal one
LDA Object_type,x
BNE +changeIntoNormal
LDA #15 ;; <-- HERE ! the new player object to transform into
STA tempD
JMP continueChangePlayerInto
changeIntoNormal:
LDA #00 ;; the normal player object
STA tempD

continueChangePlayerInto:

LDA Object_screen,x ;; the current screen
STA tempC

DestroyObject ;; we destroy the current object
CreateObjectOnScreen tempA, tempB, tempD, #$01, tempC ;; and create the new one


TXA
STA player1_object ;; store that new created object in the Player 1 var
STA camObject
; LDA tempC ;; set back the player directions
; STA Object_direction,x
PLA
TAX

doneSwitchingPlayer:
RTS

Quick note - I fixed the problem by commenting out the tempC sections that set player direction after the transformation. I think you can solve this issue by adding a user variable if you really NEED facing direction to be set right away.
 

SciNEStist

Active member
This was very helpful! I'm just wondering if there is a better way to do things than to assign the controls to every single object you want to control.
I'm working on a 2 player game and I was hoping to have 4 characters to select from.

2 players X 4 characters X 8 buttons X 2 button states (press/release) = 128 scripts! basically fills things up a little too fast.

It would be nice if I could figure out how to point at an object type and say "any controls player 1 presses, goes to this object type, and player 2 goes to this object type" and then change that object type on the fly by overwriting 2 variables. (for example: "P1Object" and "P2Object")

I figure this might be possible by altering the doHandleInputScripts.asm script (defined scripts>game>handle input scripts)

perhaps by altering the part under "findObjectOfType:" ?

Am I looking at the right script here? Am I trying to do something that is way way more complicated than I am suggesting?

Any advice would be greatly appreciated.
 

SciNEStist

Active member
woke up at 6:30 am and had the solutuion in my brain, hopped into nesmaker and tested it:

To avoid slowdowns when there are too many objects in your screen, instead of adding inputs for every single object you might control, do this instead:

1: always remember that immediatly after you create the new object you want to control, add "STA player1_object" or "STA player2_object" to the next line (player2 only if you switching to/spawning the player 2 object)

2: add this code to the beginning of all your input scripts

Code:
TXA
LDA controllerNumber_hold
BNE +player2
   LDX player1_object
   JMP +
+player2
   LDX player2_object
+
STA temp

3: in all your input functions, always refer to "temp" instead of "player1_object" or "player2_object"

4: set up both player 1 and player 2 inputs only once each to use the same scripts

now you have a much cleaner input editor screen, no need to have separate scripts for player 2, and your game isnt contantly trying to control 2-4 (or more) non existant character objects all at the same time, causing huge slowdowns
 
Last edited:

BITVADER

Member
This script will be useful for damage expressions like "Ghosts 'n Goblins".
It's the knowledge I want to use in the next game I make, but it won't work as is.
 
Top Bottom