Power up management (Platform module)

baardbi

Well-known member
The purpose of this tutorial is to show how easily you can manage different power ups in your NESmaker project.

Prerequisites for this tutorial:
- Basic understanding of NESmaker
- Knowledge about Game Objects
- Very basic understandig of ASM scripts

There are basically two things that make this work; game objects and variables.

PS! You can make all kinds of power ups, but in this tutorial I will show you four different kinds:

- A shoe that will make you jump higher
- A weapon that enables you to shoot projectiles in a straight line (max 3 on screen at a time)
- A weapon that shoots saw blades that sort of moves along the ground (max 1 on screen at a time)
- A sword that acts like a melee weapon (not a projectile)

*** Thanks to Dale Coop for the scripts to use projectile and melee weapons in the platform module (more on this later) ***

THE JUMP SHOE
shoe.png


For this to work you have to change a User Constant from constant to variable (the reason is that constants can't be changed during the game).

1. Go to Project Settings and navigate to the tab User Constants

2. Delete the constant JUMP_SPEED_HI
(Don't delete the constant JUMP_SPEED_LO)
userconstants.png


3. Under the tab User Variables create a new variable named JUMP_SPEED_HI
(You will have to experiment with the value. I put 5 as my default value, but you also have to experiment with the User Constants GRAVITY_HI and GRAVITY_LO to get the jump physics to work the way you want. I put 0 on GRAVITY_HI and 100 on GRAVITY_LO.)
uservariables.png

While you are in User Variables you might as well just create the other two variables we will need for the rest of this tutorial:

- WEAPON_TYPE
- PROJECTILE_MAX

Set the default values to 0.

4. Create a Game Object that acts as the power up you collect in the game. I use game object 7 in this example (the default is Currency Pickup in NESmaker).
gameobjectsshoe.png


5. Make an ASM script that runs when you pick up Power Up 03:

Code:
LDA #$08 ;This is the new jump speed
STA JUMP_SPEED_HI
PlaySound #SND_GET
TriggerScreen screenType ;This is only if you place the item on screen and only want it to appear once

Save this in C:\Users\baardbi\Desktop\MVTestgame\GameEngineData\Routines\Basic\ModuleScripts\PowerUpCode\MVTestgamePowerUp\JumpShoePowerUp.asm

(Obviously you can save it where you want, but I recommend using the PowerUpCode folder and making your own subfolder).

6. Assign this script to Power Up 03 in Script Settings:
scriptsettingsshoe.png


7. Finished! The jump shoe power up should now work as expected.


THE CRYSTAL PROJECTILE
projectile1.png


1. Create a Game Object that will act as the power up you collect:
gameobjectprojectile.png

I use game object 6 in this example (the default is Key Pickup in NESmaker).

2. Make an ASM script that runs when you pick up Power Up 02:

Code:
LDA #$02 ;Game Object 2
STA WEAPON_TYPE

LDA #$03 ;Max number of projectiles on screen
STA PROJECTILE_MAX

PlaySound #SND_GET

TriggerScreen screenType ;This is only if you place the item on screen and only want it to appear once

3. Save this in C:\Users\baardbi\Desktop\MVTestgame\GameEngineData\Routines\Basic\ModuleScripts\PowerUpCode\MVTestgamePowerUp\ShooterPowerUp.asm

4. Assign this script to Power Up 02 in Script Settings:
scriptsettingsshooter.png


5. Create a Game Object that will act as the projectile:
gameobjectshooter.png

I use game object 2 in this example (the default is Projectile Source in NESmaker).

6. Set the values for this Game Object as follows:

Details (you can obviously experiment with the speed values)
projectile1details.png

Actions
projectile1actions.png


Remember to set a Bounding Box.

PS! For the projectile to work properly when Ignore Gravity is set, follow Dale Coops tutorial on projectiles in the platform module:
http://www.nesmakers.com/viewtopic.php?f=35&t=1703
Don't get confused. You only have to follow it from "3/ Make a new script "b_create_projectile_platformer.asm"..." where it says "Modify the "UserSubroutines.asm" script...".

7. Almost finished with the crystal projectile. However we need a script that shoots the projectile (I have it assigned to the B button). This script is a mix of Dale Coops projectile script and melee weapon script:

Code:
    LDA WEAPON_TYPE
    CMP #$00 ;; 0 = No weapons
    BNE ++
    RTS
++
    CMP #$01 ;; Is it weapon type 1 (melee attack)
    BNE shooting
    JMP meleeAttack
shooting:
        
    LDA gameHandler
    AND #%00100000  
    BEQ canShoot
    JMP doneShooting

canShoot:
   ;; We count the projectile already on screen to see if can Shoot another one :
   CountObjects #%00000100, #$00   ;; count player weapon on screen
   LDA monsterCounter              ;; the variable used to count is monsterCounter
   CLC
   CMP #PROJECTILE_MAX             ;; compare to 1
   BCC +                    ;; if less than 1 on screen we can create a projectile
   RTS                             ;; else we quit
+
    LDX player1_object
    ;;; IF YOU WANT TO USE A SPECIFIC ANIMATION / ACTION STEP WHEN SHOOTING, comment out the following 3 lines: 
    ;;; check if already shooting (assuming the shoot action step is 03)
    GetCurrentActionType player1_object
    CMP #$03
    BNE notAlreadyShooting
    
    JMP wasAlreadyShooting 
notAlreadyShooting
    ;;; IF YOU WANT TO USE AN SPECIFIC ANIMATION / ACTION STEP WHEN SHOOTING, comment out the following 1 line: 
    ;;; if not already shooting, change it's action step (assuming the shoot action step is 03)
    ChangeObjectState #$03, #$02
    
    ;;; if you want your player stops when he's shooting, comment out the following lines:
    ;LDA Object_movement,x
    ;AND #%00001111
    ;STA Object_movement,x
    ;LDA #$00
    ;STA Object_h_speed_hi,x
    ;STA Object_h_speed_lo,x
    ;STA Object_v_speed_hi,x
    ;STA Object_v_speed_lo,x
    
;; if was already shooting
wasAlreadyShooting:

    LDA Object_movement,x
    AND #%00000111
    STA temp2
    TAY

    LDA Object_x_hi,x
    SEC 
    SBC #$08 ;; width of projectile 
    STA temp
    LDA Object_scroll,x
    SBC #$00
    STA temp3

    LDA temp
    ;;; offset x for creation
    CLC
    ADC projOffsetTableX,y
    STA temp
    LDA temp3
    ADC #$00
    STA temp3

    LDA Object_y_hi,x
    CLC
    ADC projOffsetTableY,y
    sec
    sbc #$08 ;; height of projectile
    STA temp1   
    
    
    CreateObject temp, temp1, WEAPON_TYPE, #$00, temp3
  
    ;;;; x is now the newly created object's x.
    LDA Object_movement,x
    ORA temp2
    STA Object_movement,x
    LDY temp2
    LDA directionTable,y
    ORA Object_movement,x
    STA Object_movement,x
    
    PlaySound #SND_SHOOT
doneShooting:
    ChangeObjectState #$00, #$02
    RTS

meleeAttack:
    LDX player1_object
    GetCurrentActionType player1_object
    CMP #$03
    BNE notAlreadyAttacking 
    JMP doneAttacking
    
notAlreadyAttacking:
    ;;; don't attack if already attacking.
    ;;; do we have to check for hurt here?
    ;;;;; Here, we WOULD create melee
    ChangeObjectState #$03, #$02
    LDA Object_movement,x
    AND #%00001111
    STA Object_movement,x
    LDA #$00
    STA Object_h_speed_hi,x
    STA Object_h_speed_lo,x
    STA Object_v_speed_hi,x
    STA Object_v_speed_lo,x

    LDA Object_x_hi,x
    STA temp
    LDA Object_y_hi,x
    STA temp1

    LDA Object_movement,x
    AND #%00000111
    STA temp2
    TAY

    LDA Object_x_hi,x
    SEC 
    SBC #$08    ;; <<--- HERE, you have to set width of melee weapon in HEX (1 tile = 8px, 8 in decimal = #$08 in hex. Use the binary <-> hex converter plugin)
    STA temp
    LDA Object_scroll,x
    SBC #$00
    STA temp3

    LDA temp
    ;;; offset x for creation
    CLC
    ADC weaponOffsetTableX,y
    STA temp
    LDA temp3
    ADC #$00
    STA temp3

    LDA Object_y_hi,x
    CLC
    ADC weaponOffsetTableY,y
    SEC
    SBC #$08    ;; <<--- HERE, you have to set height of melee weapon in HEX (1 tile = 8px, 8 in decimal = #$08 in hex. Use the binary <-> hex converter plugin)
    STA temp1   
    
    CreateObject temp, temp1, WEAPON_TYPE, #$00, temp3
    
meleeCreated:
    ;;;; x is now the newly created object's x.
    LDA Object_movement,x
    ORA temp2
    STA Object_movement,x
    
    PlaySound #SND_SLASH
    
doneAttacking:
    RTS

Save this script and put it in: C:\Users\baardbi\Desktop\MVTestgame\GameEngineData\Routines\Basic\ModuleScripts\InputScripts\SimplePlatformer\b_create_weapon.asm

Assign it to the button you like (I prefer the B button):
inputeditor.png


8. Finished with the crystal projectile. Now you should have a projectile that shoots in a straight line (and max 3 on screen at a time).


THE SAW BLADE PROJECTILE
sawblade.png


This is basically exactly the same as the crystal projectile, except this projectile doesn't ignore gravity.

1. Create a Game Object that will act as the power up you collect:
gameobjectsawblade.png

I use game object 5 in this example (the default is Charge Pickup in NESmaker).

2. Make an ASM script that runs when you pick up Power Up 01:

Code:
LDA #$03 ;Game Object 3
STA WEAPON_TYPE

LDA #$01 ;Max number of projectiles on screen
STA PROJECTILE_MAX

PlaySound #SND_GET

TriggerScreen screenType ;This is only if you place the item on screen and only want it to appear once

3. Save this in C:\Users\baardbi\Desktop\MVTestgame\GameEngineData\Routines\Basic\ModuleScripts\PowerUpCode\MVTestgamePowerUp\SawBladePowerUp.asm

4. Assign this script to Power Up 01 in Script Settings:
scriptsettingssawblade.png


5. Create a Game Object that will act as the projectile:
gameobjectsawbladeprojectile.png

I use game object 3 in this example (the default is Projectile in NESmaker).

6. Set the values for this Game Object as follows:

Details (you can obviously experiment with the speed values)
projectile2details.png

Actions
projectile2actions.png


Remember to set a Bounding Box.

7. Finished with the saw blade projectile.


THE SWORD (MELEE WEAPON)
sword.png


1. Create a Game Object that will act as the power up you collect:
gameobjectsword.png

I use game object 4 in this example (the default is Health Pickup in NESmaker).

2. Make an ASM script that runs when you pick up Power Up 00:

Code:
LDA #$01 ;Game Object 1
STA WEAPON_TYPE

LDA #$00 ;Max number of projectiles on screen
STA PROJECTILE_MAX

PlaySound #SND_GET

TriggerScreen screenType ;This is only if you place the item on screen and only want it to appear once

3. Save this in C:\Users\baardbi\Desktop\MVTestgame\GameEngineData\Routines\Basic\ModuleScripts\PowerUpCode\MVTestgamePowerUp\SwordPowerUp.asm

4. Assign this script to Power Up 00 in Script Settings:
scriptsettingssword.png


5. Create a Game Object that will act as the melee weapon:
gameobjectswordmelee.png

I use game object 1 in this example (the default is Melee in NESmaker).

6. Set the values for this Game Object as follows:

Details
melee1details.png

Actions
melee1actions.png


Remember to set a Bounding Box.

7. Finished! You should now have a melee attack weapon that doesn't shoot when you press the B button.


This is the end of the tutorial. If you have strange issues like for example your projectiles launches from the top of the players head, you need to check the placement for your melee and projectiles:

gameobjectplacement.png


If there are any mistakes in this tutorial please let me know so I can fix them.

Good luck with your power ups in NESmaker.
 

dale_coop

Moderator
Staff member
This is a great tutorial baardbi, beautifully illistrated as I love them. Great work! And thank you for sharing it.
 

baardbi

Well-known member
Thanks for the feedback guys. I hope this tutorial is as easy to follow as I intended it to be.
 

Saulus_Lira

Member
Very good tutorial. Congratulations!
I'm implementing only "SUPER JUMP" in my project (this is so cool !!).
Just a question. I did exactly as described, and when I start the game my character already has the jump increased, without collecting anything.
I must have missed something. Any tips?
 

baardbi

Well-known member
Thank you :) It's very important that JUMP_SPEED_HI is a User Variable and not a User Constant. Maybe you could check that.
 
Top Bottom