[4.1] Use the real Melee object weapon in the Platformer module

dale_coop

Moderator
Staff member
If you prefer to have a real object based Melee weapon, in your plateformer game project.
Here how to do :


1/ In the "Project Settings > User Constants", create a new constant named "OBJECT_PLAYER_MELEE" with the value "1".

2019-01-14-15-24-44-Project-Settings.png



2/ Create a new script "b_create_melee_weapon.asm" in the "GameEngineData\Routines\Basic\ModuleScripts\InputScripts" folder, with this code:
Code:
	LDA gameHandler
	AND #%00100000
	BEQ notNPCstate_attack
	JMP doneAttacking
notNPCstate_attack:
	 LDA weaponsUnlocked
	 AND #%00000001
	 BNE canAttack
	 JMP doneAttacking
canAttack:
	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, #OBJECT_PLAYER_MELEE, #$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
(in the script, don't forget to adapt/modify the with and the height of your weapon)


3/ In the hierarchy, under "Game Objects", select and setup your "Melee" object:

2019-01-14-15-27-04-NES-MAKER-4-1-1-Version-0x158-Plateform-Test-MST.png


In the "Details Object", you can its left / right animation :

2019-01-14-15-30-15-Monster-Animation-Info.png


Then, set it as "Player weapon".:

2019-01-14-15-30-22-Monster-Animation-Info.png


Set the "Action step 0" to "Ignore gravity" and to "DestroyMe" after the end of the Action, give a timer value of "1" (if you have an animation, you could you the "end of animation" with the right animation speed):

2019-01-19-13-34-00-Monster-Animation-Info.png


And don't forget to set the Bounding Box!


4/ Now, select the "Player" object, go the "Object Details". For the "Action Step 03", uncheck the "Harmfull invicible", set to "GoToFirst" the end of Action, give a timer value of "1", at least the value of the weapon timer (if you have an animation, you could you the "end of animation" with the right animation speed):

2019-01-19-13-37-12-Monster-Animation-Info.png



5/ In the hierarchy, select the "Game Object" element, and set the position (the Offset) of your Melee object with your Player for all its facing directions:

2019-01-15-17-40-02-NES-MAKER-4-1-1-Version-0x158-Plateform-Test-MST.png



6/ In the "Scripts > input Scripts" add the "b_create_melee_weapon.asm" script.

7/ In the "Input Editor", assign it to your button ("Press" "B" button).


8/ In your "Project Settings > Script Settings", select the "Use Sprite Based Weapon" element and assign it the "Routines\Basic\ModuleScripts\BlankScript.asm":

2019-01-14-15-42-59-Project-Settings.png



9/ Make a new script "PreDraw_DC.asm" in your "GameEngineData\Routines\Basic\ModuleScripts\MainScripts\ScrollingPlatformer" folder, with this code (it's the same script that the PreDraw, I just removed all the part about the weapon):

Code:
;; sprite pre-draw
;;; this will allow a user to draw sprites
;;; before object sprites are drawn.
;;; keep in mind, there are still only 64 sprites
;;; that can be drawn on a screen, 
;;; and still only 8 per scan line!

;;; you can use DrawSprite macro directly using the following scheme:
;DrawSprite arg0, arg1, arg2, arg3, arg4
	;arg0 = x
	;arg1 = y
	;arg2 = chr table value
	;arg3 = attribute data
	;arg3 = starting ram position
	
;; x and y are the direct positions on the screen in pixels.
;; chr table value is which sprite you'd like to draw from the ppu table.
;; attribute data is a binary number (starts with #%), and here are how the bits work:
	;;; bit 7 - Flip sprite vertically
	;;; bit 6 - Flip sprite horizontally
	;;; bit 5 - priority (0 in front of background, 1 behind background)
	;;; bit 4,3,2 - (null)
	;;; bit 1,0 - subpalette used (00, 01, 10, 11)
	
	
;;; for starting ram position, use spriteOffset.
;; this is set to 0 just before entering this script (or 4 if sprite 0 hit was used).
;; ***remember to increase spriteOffset by 4 for every sprite that is drawn,
;; including after the last one drawn*****, so that the first object's sprite begins
;; in the next available spot.

;; I have created a macro function to handle updating to the next sprite.  So, to update to the next sprite position,
;; all that you have to do is use the function UpdateSpritePointer

;;EXAMPLE:
; DrawSprite #$80, #$80, #$10, #%00000000, spriteOffset
; UpdateSpritePointer

;;;; DRAW SPRITE ZERO FOR SPRITE ZERO HIT
	LDA gameState
	CMP #GS_MainGame	
	BNE + ;dont draw sprite zero
	;DrawSprite #$f8, #$1e, #$7F, #%00000000, spriteOffset
				;248   30    127   bit 5 = priority
	DrawSprite #SPRITE_ZERO_X, #SPRITE_ZERO_Y, #SPRITE_ZERO_INDEX, #%00100000, spriteOffset
	UpdateSpritePointer
;dont draw sprite zero.
+

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

And assigned it the the "Handle Sprite Pre-Draw" element in the "Project Settings > Script Settings".


10/ In your "Project Infos", you can check the "Weapon 1 unlock" if you want your player to have the weapon at launch (else he will have to get it from an NPC):

2019-01-14-15-40-09-Initial-Data.png



11/ Last thing, you should do a small modification in your StartMovingPlayerxxx script, just moving the "++" from before the "FaceDirection" line, to AFTER "FaceDirection" line.
For exemple, StartMovingPlayerRight.Asm should be like this :
Code:
 ;;;;; START MOVING PLAYER RIGHT:
 ;;;;; We will use this when the right button is pressed.
 ;;;;; If we are already showing the walking animation, which is for this module
 ;;;;; action step 1, we will skip changing to the walking state.
    LDX player1_object
    GetCurrentActionType player1_object
    CMP #$02 ;; if the state is invincible
    BEQ ++ ; skip movement if attacking
    CMP #$03
    BEQ ++ ;skip if we are casting spell
    CMP #$01
    BEQ + ;; if the action type already equals 1, jump forward
    ChangeObjectState #$01, #$04
+
;;;;;; Then, we will begin moving.
    StartMoving player1_object, MOVE_RIGHT
;;;;;; Lastly, we will change the facing direction.
    FaceDirection player1_object, FACE_RIGHT
++
    RTS

VoilĂ , your Melee weapon should work as expected...


Note: you should get rid of your GetSword pickup object, make it a health pickup or anything else you want (change the script assign to the "Power Up 00" in the "Project Settings > Script Settings").
 

SuperNatetendo

New member
So... I've made a janky solution to keep the object with you when allowing the attack to be done while mid-run/jump/etc

EDIT: forgot to say - I added this to the pre-draw script.

EDIT2: Added a few lines. Fixed a little directional issue.

Code:
;; Nate's janky object parenting w/ melee weapon

     LDX player1_object
   
    LDA Object_animation_frame,x
    STA temp
    
    LDA Object_movement,x
    AND #%00000111
    STA temp3
    TAY
    
    LDA Object_x_hi,x
    SEC 
    SBC #$10 ;; width of melee weapon 
    CLC
    ADC weaponOffsetTableX,y
    STA temp1
    
    LDA Object_y_hi,x    
    CLC
    ADC weaponOffsetTableY,y
    SEC
    SBC #$18 ;; height of melee weapon
    STA temp2
    
    LDX #OBJ_PLAYER_MELEE
    LDA temp1
    STA Object_x_hi,x
    LDA temp2
    STA Object_y_hi,x
    
    LDA Object_movement,x
    ORA temp3
    STA Object_movement,x

Here's the problem, though... It has some weird directional issues which I'm not sure how to fix. Give it a shot and see what could be fixed.
 

VDfreesince1983

New member
Ta-da check out this sweet sword action https://youtu.be/RW9ZWZ4yQ8E . I am not sure why sprite (12, 2) is showing up in the middle of my Melee object if anyone has any idea. But other than that I adjusted both the object alignment in the GUI [Right: (35,16), Left: (1,16)] and the melee width in your Player Melee script

Code:
 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 #$14 ;; width of melee weapon 
    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 ;; height of melee weapon
    STA temp1   
    
    CreateObject temp, temp1, #$01, #$00, temp3
 

dale_coop

Moderator
Staff member
Great!
Yep, exactly, I forgot to say that in the script you have to modify it with the width and the height of your weapon (the tutorial one is 8x8).
And, of course, adjust your offset of your Melee weapon (like you did for your projectiles), via the "Game Object" element in the NESMaker GUI.

Updated the OP
 

DanielT1985

Member
dale_coop said:
If you prefer to have a real object based Melee weapon, in your plateformer game project.
Here how to do :


1/ In the "Project Settings > User Constants", create a new constant named "OBJECT_PLAYER_MELEE" with the value "1".

2019-01-14-15-24-44-Project-Settings.png



2/ Create a new script "b_create_melee_weapon.asm" in the "GameEngineData\Routines\Basic\ModuleScripts\InputScripts" folder, with this code:
Code:
	LDA gameHandler
	AND #%00100000
	BEQ notNPCstate_attack
	JMP doneAttacking
notNPCstate_attack:
	 LDA weaponsUnlocked
	 AND #%00000001
	 BNE canAttack
	 JMP doneAttacking
canAttack:
	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 
	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
	STA temp1	
	
	CreateObject temp, temp1, #OBJECT_PLAYER_MELEE, #$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
(in the script, don't forget to adapt/modify the with and the height of your weapon)


3/ In the hierarchy, under "Game Objects", select and setup your "Melee" object:

2019-01-14-15-27-04-NES-MAKER-4-1-1-Version-0x158-Plateform-Test-MST.png


In the "Details Object", you can its left / right animation :

2019-01-14-15-30-15-Monster-Animation-Info.png


Then, set it as "Player weapon".:

2019-01-14-15-30-22-Monster-Animation-Info.png


Set the "Action step 0" to "Ignore gravity" and to "DestroyMe" after the end of the animation, give an animation speed (even if don't have any particular animation!):

2019-01-14-15-16-32-Monster-Animation-Info.png


And don't forget to set the Bounding Box!


4/ Now, select the "Player" object, go the "Object Details". For the "Action Step 03", uncheck the "Harmfull invicible", set to "Loop" the end of action and set to "GoToFirst" the End of animation, give an animation speed (even if don't have any particular animation!):

2019-01-14-15-18-22-Monster-Animation-Info.png



5/ In the hierarchy, select the "Game Object" element, and set the position (the Offset) of your Melee object with your Player for all its facing directions:

2019-01-15-17-40-02-NES-MAKER-4-1-1-Version-0x158-Plateform-Test-MST.png



6/ In the "Scripts > input Scripts" add the "b_create_melee_weapon.asm" script.

7/ In the "Input Editor", assign it to your button ("Press" "B" button).


8/ In your "Project Settings > Script Settings", select the "Use Sprite Based Weapon" element and assign it the "Routines\Basic\ModuleScripts\BlankScript.asm":

2019-01-14-15-42-59-Project-Settings.png



9/ Make a new script "PreDraw_DC.asm" in your "GameEngineData\Routines\Basic\ModuleScripts\MainScripts\AdventureGame" folder, with this code (it's the same script that the PreDraw, I just removed all the part about the weapon):

Code:
;; sprite pre-draw
;;; this will allow a user to draw sprites
;;; before object sprites are drawn.
;;; keep in mind, there are still only 64 sprites
;;; that can be drawn on a screen, 
;;; and still only 8 per scan line!

;;; you can use DrawSprite macro directly using the following scheme:
;DrawSprite arg0, arg1, arg2, arg3, arg4
	;arg0 = x
	;arg1 = y
	;arg2 = chr table value
	;arg3 = attribute data
	;arg3 = starting ram position
	
;; x and y are the direct positions on the screen in pixels.
;; chr table value is which sprite you'd like to draw from the ppu table.
;; attribute data is a binary number (starts with #%), and here are how the bits work:
	;;; bit 7 - Flip sprite vertically
	;;; bit 6 - Flip sprite horizontally
	;;; bit 5 - priority (0 in front of background, 1 behind background)
	;;; bit 4,3,2 - (null)
	;;; bit 1,0 - subpalette used (00, 01, 10, 11)
	
	
;;; for starting ram position, use spriteOffset.
;; this is set to 0 just before entering this script (or 4 if sprite 0 hit was used).
;; ***remember to increase spriteOffset by 4 for every sprite that is drawn,
;; including after the last one drawn*****, so that the first object's sprite begins
;; in the next available spot.

;; I have created a macro function to handle updating to the next sprite.  So, to update to the next sprite position,
;; all that you have to do is use the function UpdateSpritePointer

;;EXAMPLE:
; DrawSprite #$80, #$80, #$10, #%00000000, spriteOffset
; UpdateSpritePointer

;;;; DRAW SPRITE ZERO FOR SPRITE ZERO HIT
	LDA gameState
	CMP #GS_MainGame	
	BNE + ;dont draw sprite zero
	;DrawSprite #$f8, #$1e, #$7F, #%00000000, spriteOffset
				;248   30    127   bit 5 = priority
	DrawSprite #SPRITE_ZERO_X, #SPRITE_ZERO_Y, #SPRITE_ZERO_INDEX, #%00100000, spriteOffset
	UpdateSpritePointer
;dont draw sprite zero.
+

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

And assigned it the the "Handle Sprite Pre-Draw" element in the "Project Settings > Script Settings".


10/ In your "Project Infos", you can check the "Weapon 1 unlock" if you want your player to have the weapon at launch (else he will have to get it from an NPC):

2019-01-14-15-40-09-Initial-Data.png



VoilĂ , your Melee weapon should work as expected...


Note: you should get rid of your GetSword pickup object, make it a health pickup or anything else you want (change the script assign to the "Power Up 00" in the "Project Settings > Script Settings").

I tried doing this, and ended up getting this error, saying,"Routines\Basic\ModuleScripts\InputScripts\b_create_melee_weapon.asm(65):CreateObject(26): Unknown label"
 

dale_coop

Moderator
Staff member
Cool ;) galt you fixed it...
And don't hesitate to make some tests (changing some values in the objects details, animations, end of animations ...) to find something that would work well for your game.
And you should also test the script of SuperNateTendo http://nesmakers.com/viewtopic.php?p=11084#p11084 (for you weapon to follow your player when moving) also you should block the movements scripts where your player is attacking (like it was in the 4.0).
 

Subotai

Active member
Thanks Dale, I followed your tutorials step by step. It's well explained.
It works but :

I've some problem with the offset of the weapon when I test the game, see below :

offset_weapon.jpg


My weapon is Height 1, Width : 2
So in script : SBC #$01 ;; height of melee weapon and SBC #$02 ;; width of melee weapon

With some tries, I found the ideal offnet for "AttackRight".
But for AttackLeft, even is the Offset X value is to minimum (0)... My weapon is through the character and not on the left side.

Any idea ?
 

dale_coop

Moderator
Staff member
Ah, in fact your weapon is Height 1 and Width : 2 ... in the GUI. In fact for the code engine, your Weapon is 1 tile of 8px by 2 tiles of 8x, it means your weapon height 8 and your weapon with is 16.

So you should try:
Code:
  SBC #$10 ;; width of melee weapon (="16" in decimal = 2 tiles)
and :
Code:
  SBC #$08 ;; height of melee weapon (1 tile)
 

dale_coop

Moderator
Staff member
After some tests, I updated the tutorial to use "end of action" instead of "end of animation" by default (for those who don't have any animation for their attacking state or for the weapon). It give better results.
 

dale_coop

Moderator
Staff member
I just realize now that, in my tutorial (in my proejct) I used the Action Step 3 as the attacking state... but in the default behaviour (sprite-based melee) it was the Action Step 2!
I might update the tutorial in order to use the Action Step 2...
 
"Yep, exactly, I forgot to say that in the script you have to modify it with the width and the height of your weapon (the tutorial one is 8x8)."

Sorry, how does one do this? Not sure what variable this is in the code that you posted :)
 

dale_coop

Moderator
Staff member
In my "b_create_melee_weapon.asm", if you read the lines... there are comments saying ";; <<--- HERE..."
And my comment here: http://nesmakers.com/viewtopic.php?p=11238#p11238
 
Top Bottom