[4.5.6] [SOLVED] Wall Grab and CheckCollisionPoint

Greetings, original post follows, but skip to the end for the fully working code. :)

Hello! I have been trying to get wall grab working for about a week now, and I have sort of accomplished that task...however I have to use a spawned game object, and that is quite inefficient and there has to be a better way.

There was a previous post for wall grab in a different version, however the commands used in there dont seem to exist anymore, so I have had to do alot of poking and prodding at other things to get to where I am. Despite having to use a game object I think the implementation itself works well, I just want to...optimize it as we are making a game that has lots of projectiles similar to a Mega Man style game, so I want to keep any unnecessary object spawning to a minimum.

I utilize the very last object in the Game Objects list, its pretty simple, a black tile, with a small collision bot in the center, its default action has a 1 timer on it, and the end of action...uh action is to DestroyItself. And an action step just for Wall Grab that is set to ignore gravity.

This is my current code for when the player is pressing and holding the Up Direction, I know I could make this you have to just press up right when you want to grab, but that feels terrible and janky so I refuse lol.

Code:
TXA
STA temp
GetActionStep temp
	CMP #$07 ;; is the player hurt?
	BNE +notHurt
		JMP +doNotWallGrab
	+notHurt
	
	CMP #$03 ;; player jumping?
	BEQ +isJumping
		JMP +doNotWallGrab
	+isJumping		
		LDA Object_y_hi,x
		CLC
		ADC #$08 ;; middle of player, about where hand is
		STA temp2

		LDA Object_direction,x
		AND #%00000111
		CMP #%00000110 ;; is the player facing left?
		BNE +notLeft
			;; Facing Left so set temp variables for left
			LDA Object_x_hi,x
			CLC
			SBC #$01 ;; 1 pixel to the left of the player to check.
			STA temp1
			JMP +tryWallGrab_Left
		+notLeft
			;; Facing Right
			LDA Object_x_hi,x
			CLC
			adc #$0D ;; Right Side of Player
			STA temp1
			JMP +tryWallGrab_Right
		
+tryWallGrab_Left
	CreateObjectOnScreen temp1, temp2, #$02, #$00, tempA
	CheckCollisionPoint temp1, temp2, #$00, tempA ;; is it a solid?
	BEQ +doNotWallGrab
		JMP +doWallGrab
	
+tryWallGrab_Right
	CreateObjectOnScreen temp1, temp2, #$02, #$00, tempA
	CheckCollisionPoint temp1, temp2, #$00, tempA ;; is it a solid?
	BEQ +doNotWallGrab
	
+doWallGrab
	ChangeActionStep temp, #$04 ;; change action to WallGrab
	StopMoving temp, #$FF, #$04
	
+doNotWallGrab
	RTS

If anyone has an ideas as to what I am doing wrong here that would be much appreciated. If you comment out lines 43 and 52, everything stops working...which I dont quite understand why. Isn't CheckCollisionPoint telling me if the collision tile at that point is whatever collision type I pass it?

Am I just completely miss-understanding how CheckCollisionPoint works?
 

AllDarnDavey

Active member
If I'm following this right if the player is not hurt, and is jumping. You then go up about half a tile and over a pixel in the direction you're facing... then spawn your gameobject at that spot and check if it's collision overlaps with a solid, and if it does change your action step and stop moving.

Not sure why you need the extra gameobject and cannot just check the tile type at that location instead (but I've never tried this before).
 
Yeah thats exactly my point! If I comment that out, it stops working, and it makes absolutely no sense to me what so ever.

I actually go down half a tile, since positive Y is down. Then I check facing, and I either offset X 1 pixel left, or about 13 pixels to the right...which is also weird and I was expecting that to be 17 pixels since the player itself is 16 wide and 16 tall and the collider is centered...
 

AllDarnDavey

Active member
Yeah, I don't see why you need the "CreateObjectOnScreen" line.
Maybe it's the TXA... I know a lot of these subroutines assume the object is loaded in X. In your first couple lines you transfer x into A and save that into temp. But you don't TAX it back into x afterwards. So maybe you threw off x, and creating a new object puts that objects into x.

Just a guess, but try adding TAX to on line 3.
 

mouse spirit

Well-known member
check this one out.I feel like its simple enough to do it this way.But i
don't know if it would work for your game persay.
Im guessing they used a tile type and said when colliding and facing correct direction,
and pressing the correct buttons,go to state grabwall.

https://nesmakers.com/viewtopic.php?f=52&t=5563

Sounds like what you are saying you want, except you are having to do
some extra stuff.

Just a thought.Dont use temp at the begining GetActionStep, use the exact #$XX object reference.
or LDA #$00 then STA temp.

Also i see tempA. What is that tempA?
 
I honestly dont know what tempA is, I think its supposed to be left right direction, judging by what CheckCollisionPoint MACRO comments say. The climbLadderUp_ActionPlatformer script uses tempA without also assigning to it, which is where I have been reverse engineering from.
 
Yeah I had thought it might be a problem with X, I didnt know what TXA was doing to that makes more sense now thanks...I will try that next!
 
I have tried TXA it didnt work, I now no longer use those TSA and saving to temp, and am accessing the game object directly. However everything still functions exactly the same, and I am required to do this stupid game object spawn...gah this is frustrating af
 
I dont want to use a special tile, as I just want ALL solid collision to just be climbable, I don't want to have to go through and tag everything as wall grabable. I went down that path already and had a hell of a time getting the tile to act as solid, but still allow me to grab onto it. As soon as it becomes solid it no longer allows grabbing...
 

mouse spirit

Well-known member
I see. I did it in gamemaker but thats a whole different story.
Also, i think there was a hard time because we dont collide with solid tiles. I think you have to be in a tile to collide with it .This may not be true but thats the way i understood it.
 
Yeah thats what I have come to understand, it's stopping me from colliding with it, so I am not sure what else to do other than check a collision point...which then doesn't do what I am expecting.
 

mouse spirit

Well-known member
So ok. I see whats goin on So you created an object. Cause i was gonna say create a "weapon" that collides.
That probly is a good way to do it.
 

mouse spirit

Well-known member
I know it sucks but thats probly how to do it here.
I would say stay on the wall unless you press jump and the object wont disappear till you jump also.
Probly what you already did.
 
I actually dont need to object once I am in the wall grab state, its only while I am holding up, in the air, and not wall grabbing does it spawn the game object. Because I can jump, and range attack in our game I dont want to reduce attacking efficiency due to pressing up.
 

AllDarnDavey

Active member
I'm trying to recreate what you have, and am unable to get it to do anything.
You're assigning the above code as an input script for the player holding up, right?

Also, you say you're using the last gameobject, but the code says object #$02? Not sure if that might be causing some issues?
 

AllDarnDavey

Active member
Okay, I got a version working for me locally without the need to spawn a gameobject

Code:
TXA
STA temp
TAX
GetActionStep temp
	CMP #$07 ;; is the player hurt?
	BNE +notHurt
		JMP +doNotWallGrab
	+notHurt
	
	CMP #$02 ;; player jumping?
	BEQ +isJumping
		JMP +doNotWallGrab
	+isJumping		
		LDA Object_y_hi,x
		CLC
		ADC #$08 ;; middle of player, about where hand is
		STA temp2

		LDA Object_direction,x
		AND #%00000111
		CMP #%00000110 ;; is the player facing left?
		BNE +notLeft
			;; Facing Left so set temp variables for left
			LDA Object_x_hi,x
			CLC
			SBC #$01 ;; 1 pixel to the left of the player to check.
			STA temp1
			JMP +tryWallGrab_Left
		+notLeft
			;; Facing Right
			LDA Object_x_hi,x
			CLC
			adc #$10 ;; Right Side of Player
			STA temp1
			JMP +tryWallGrab_Right
		
+tryWallGrab_Left
	CheckCollisionPoint temp1, temp2, #$01, tempA ;; is it a solid?
	CMP #$01
	BNE +doNotWallGrab
		JMP +doWallGrab
	
+tryWallGrab_Right
	CheckCollisionPoint temp1, temp2, #$01, tempA ;; is it a solid?
	CMP #$01
	BNE +doNotWallGrab
	
+doWallGrab
	PlaySound #sfx_zip
	ChangeActionStep temp, #$04 ;; change action to WallGrab
	StopMoving temp, #$FF, #$04
	RTS
	
+doNotWallGrab
	PlaySound #sfx_thump
	RTS

You're action step for Jumping or Wallgrab may be different than mine, but just change the number if it is. You're code was checking for tile #$00 which is usually null not solid, mine checks for #$01 which is normally solid.

I also threw in some sfx calls, one for trying and failing to wall grab, and another for successfully wall grabing, feel free to remove or change.

I think mostly you're branch conditions were incorrect, and I tweaked a few numbers to get it to work for me. You also can't wall jump, only wall grab. Hopefully that's what you were going for.

WallGrab.gif
 
The great thing, is that copying what you have into my game I can't get this to work at all.

Yep have tried alot to get what you have working...not sure why what I have doesnt work with that...
 
I GOT IT!

Omg after almost a week on this one thing haha, it was a two fold problem. The first was I was missing the "CMP #$01" to see if I was actually comparing a solid, thanks @AllDarnDavey for that spot. The next however was that I was using CheckCollisionPoint, which is basically me asking hey is my Player(#$00)'s collision at this point? Which in fact is always no haha.

Davey's example not working for me also was like...I have to be using the wrong check collision MACRO. So I went and took a look at the MACRO folder and what do ya know...I find GetCollisionPoint...which is exactly what I was wanting in the first place and I am super annoyed that I didnt just look before, but also relieved that I wasn't crazy and what I was trying to do was correct all along.

Anyways, here is my working Wall Grab asm, enjoy:
Code:
GetActionStep #$00 ;; Get the player's action
    CMP #$07 ;; is the player hurt?
    BNE +notHurt
        JMP +doNotWallGrab
    +notHurt
    
    CMP #$03 ;; player jumping?
    BEQ +isJumping
        JMP +doNotWallGrab
    +isJumping
        LDA Object_y_hi,x
        CLC
        ADC #$06 ;; middle of player, about where hand is
        STA temp2

        LDA Object_direction,x
        AND #%00000111
        CMP #%00000110 ;; is the player facing left?
        BNE +notLeft
            ;; Facing Left so set temp variables for left
            LDA Object_x_hi,x
            CLC
            ADC #$01 ;; Adding 1 pixel to get to my characters left side
            STA temp1
            JMP +tryWallGrab
        +notLeft
            ;; Facing Right so set temp variables for right
            LDA Object_x_hi,x
            CLC
            adc #$0D ;; Adding 13 pixels to get to my characters right side
            STA temp1
            JMP +tryWallGrab
        
+tryWallGrab
GetCollisionPoint temp1, temp2, #$00, tempA ;; is the player next to a solid?
    CMP #$01
    BNE +doNotWallGrab
        ChangeActionStep #$00, #$04 ;; change action to WallGrab
        StopMoving #$00, #$FF, #$04 ;; ensure we stop moving
    +doNotWallGrab
    RTS

Requirements:
- This is an input script, and is intended to be run when you Press and Hold Up. You can also set it to run only when you press, but you wont be able to hold up to just grab on when a wall gets in range.
- Hurt is assigned to action 7 (#$07) - Only used for not allowing grab when hurt, remove lines 2-5 if you dont want this.
- Jump is assigned to action 3 (#$03) - Line 7 is where you change this if your jump is a different action.
- Lines 23 and 30 may need to have their values tweaked based on your characters art and collision.
- ADC means to Add with Carry (Adds and holds the value to the next instruction)
- SBC means to Subtract with Carry (Subtracts and holds the value to the next instruction)
- WallGrab is assigned to action 4 (#$04) - Lines 38 and 39 need to have this changed if yours is a different action.
- WallGrab action should have Ignores Gravity turned on. (Yes this was built off of the Action Platformer base)

Lemme know if this works for you, and if you have any questions feel free to ask!
 
Top Bottom