8 point collision , what I know

fearspork

New member
i dont know 6502 assembly code and i have no interest in learning, what i do want to do is solve a common problem a lot of us are having with larger players sliding through platforms with out shrinking the hit box, 6502 is a super abstract and old language, googling tile collision will find you stuck in 15 year old dead threads with people who expect you to know 6502 assembly code. so here's what I've figured out

the bounding box is not actually a box , the way its laid out in the platform module is in 4 points labeled 0,1,2,3 that are checked one at a time for collisions with solid tiles. although almost every single game checked collisions differently and with different code , this basic idea is a super common way it was done , the problem with larger sprites and player characters is that the points are stretched to a point where the collisions aren't being detected in the middle, the solution then is to add more points to check

if you imagine your player is on a grid like battle ship each point on the grid has an address like C6 or B4 ( but i dont know how those addresses are written in assembly) in memory they are not stored in a grid they're stored in a straight line to be reassembled as a grid on your screen later, so if you had a 8x8 grid it would be 0,1,2,3,4,5,6,7,... and then the second line down would start at 8,9,10...ect probably in hex values. in the code the number of addresses need to be defined and then a way to retrieve each point and then what to do with the points and then the reactions of these points.

in the platform module there is a .ASM file called TileCollision_Platform_simple_alt.asm wich i am sure is what defines all of this in NESmaker Platform Module. in the file there is already the code for 6 point tile collision but its disabled some how because i'm assuming games run better with less points to individually check.

HandleTileCollision:
;; uses collisionPoint0,1,2,and 3
;; makes use of left+bbox_left, top+bbox_top, width and height of an object to form bounding box.
;; gets collision data for each point.

;LDA ObjectFlags,y
;AND #%10000000 ;; ignore background collisions?
;BEQ dontIgnoreBackgroundCollisions
;LDA Object_flags,x
;AND #%01000000
;BEQ dontIgnoreBackgroundCollisions

;RTS
dontIgnoreBackgroundCollisions:

;;;=== HANDLES TOP LEFT CORNER
LDA xHold_hi
CLC
ADC ObjectBboxLeft,y ;; y is still loaded with object type, so this reads from lut table.
STA tileX
LDA yHold_hi
CLC
ADC ObjectBboxTop,y
STA tileY
JSR GetTileAtPosition
LDA collisionTable,y
;; y is now loaded with tile type
STA collisionPoint0
;;; if it is solid, disregard the other collisions, this should *stop us*.
LDY Object_type,x

;;; === handles top right corner
LDA tileX
CLC
ADC ObjectWidth,y
STA tileX
JSR GetTileAtPosition
;; y is now loaded with tile type
LDA collisionTable,y
STA collisionPoint1

LDY Object_type,x

;;; === handles bottom right corner
LDA tileY
CLC
ADC ObjectHeight,y
STA tileY
JSR GetTileAtPosition
LDA collisionTable,y
;; y is now loaded with tile type
STA collisionPoint2

LDY Object_type,x

;;; === handles bottom left corner
LDA tileX
SEC
SBC ObjectWidth,y
STA tileX
JSR GetTileAtPosition
LDA collisionTable,y
;; y is now loaded with tile type
STA collisionPoint3

;;;;;;;;;;;;;;;;;;six point collision
LDY Object_type,x

;;; === handles bottom left corner
LDA ObjectHeight,y
LSR
STA temp
LDA tileY
SEC
SBC temp
STA tileY
JSR GetTileAtPosition
LDA collisionTable,y
;; y is now loaded with tile type
STA collisionPoint4

LDY Object_type,x

;;; === handles bottom left corner
LDA tileX
clc
adc ObjectWidth,y
STA tileX
JSR GetTileAtPosition
LDA collisionTable,y
;; y is now loaded with tile type
STA collisionPoint5

LDY Object_type,x ;; final restoring corrupted y value




LDA collisionPoint0
ORA collisionPoint1
ORA collisionPoint2
ORA collisionPoint3
ORA collisionPoint4
ORA collisionPoint5
; ;;; all collision points were zero.
BEQ noCollisionHappened

JMP collisionHappened


i'm sure that re-enabling this is super easy for some one who knows how to code, but i dont know what i'm looking at and i cant simply cut and paste someone else's code from some other indie game because every game does this different and the little bit of code i did find i'm sure is not compatible with NESmaker. im sure also it would be easy to add 2 more points to this to make an 8 point collision detection's again i dont know how to do that and the more points you add the slower the game will get.

i've looked at hours of youtube videos and scoured old dev blogs and this was the best resource i could find http://forums.nesdev.com/viewtopic.php?f=2&t=352&start=60 . i hope this gets solved soon or that i at least helped someone who doesn't code what is happening when you slide through a platform
 

jorotroid

Member
I am confused. That is the code for 6 point collision detection and it's not disabled. Isn't TileCollision_Platform_simple_alt.asm the default collision detection routine for the platformer module? It's working for me. How big is your player character? If its bounding box is bigger than 4 sprites tall, then you would need more that 6 points.
 

fearspork

New member
my player is 4(8x8)tiles wide by 3(8x8)tiles tall. this code explained by joe on facebook only checks 4 points and that it maxes out at a 1(8x8) wide by 2(8x8) tall character. the current work around suggested by dale_coop is to make the bounding box a max of 1(8x8) wide by 2(8x8), http://nesmakers.com/viewtopic.php?f=19&t=211 this works but makes other problems. its suggested by joe in the tutorial that we can change the current 4 points to 8 points , but that it slows down the game and its not native to the NESMaker front end and that explaining the ASM would take too long. it looks to me like that is the working 6 point code but perhaps the 2 middle points are not defined so when this script goes to check for them it just skips the missing points, maybe its just a ;; some where blocking the middle points from working ? maybe i miss understood and all 6 points are working and i really need 8 points , i have no clue this looks like alphabet soup to me. here is a post of the same problem from some one else with screen shots so you can see what i'm talking about http://nesmakers.com/viewtopic.php?f=23&t=586&p=5989&hilit=tile+collision#p5989
 

fearspork

New member
this is cut and paste from face book i changed My name to Fearspork... i'm the friend ....

FEARSPORK so i have a friend ... who's in project settings>script setting> i'm going through the visible asm. files menu. witch asm. script changes to a 6 or 8 point collision detection and how Do i add that.... i'm asking for a friend
Manage

· Reply · 6d
Joe Granato
Joe Granato If you're not super clear on ASM, it might be best posed to the forums for multiple reasons:

1) lots of people with at least a little ASM experience there
2) It's not possible to write code in FB like it is there.
3) What you learn, others can learn from.

:)
Manage
Like
· Reply · 6d

Joe Granato Though to give you a clear idea, you can look at your tile collisions script in your script manager. You can see how collision points 1-4 are figured. Then you'd just have to make a 5th and sixth, and just like 1-4 check to see what's there, and react accordingly, you'd do the same for 5&6.

(this would also require you to to add variables for those two new collision points).

So it's actually pretty easy for someone who can read the ASM. But if you're not there yet, my advise is don't stress about that part of it yet, continue to use NESmaker and the tutorials as learnign the basic interface. :)
Manage
Like
· Reply · 6d

FEARSPORK thank you for the response, but if its on there its not coming up in any of my searches, theres a lot of post suggesting to do this but no one explains how, Dale_coop who is a monster on the forum has the biggest post but his solution is to just make the hit box smaller, but that results in enemy attacks going through the players head or sinking much too far into the floor, also i know nothing about coding, zero, so i dont even know what files to look at in what folder and if its even adding to my game or what.... i mean my friend
Manage
Like
· Reply · 6d

Joe Granato Haha. Right. That's why I say that you're probably not to the point of digging deep in the ASM. So for the time being, you have a few choices. You can make your block areas thicker. You can make your character smaller, as is intended in that tutorial module, or you can figure out a reason to make this a mechanic in your game. That module isn't designed to use characters bigger than 16x16 for collision detection. It's not a hard ASM change, and I'm sure there will be scripts that handle it by the community if not from us before long. But that shouldn't concern you too much at this point, because if you're not at the point where you'd feel comfortable making those changes anyway, you shouldn't be trying to create your opus game yet...you're just learning the tool. Stick close to the tutorials until you're more comfortable and broader base of possibilities / more code options / deeper tutorials open up on the forums :)
3

Like
· Reply · 6d

FEARSPORK i had to make the player big to make a no code melee attack solution, i made the player 4x3 tiles, the with is to add an animation for the melee weapon, i then added a blank tile in the projectile and timed it so it disappears at the end of the melee animation. so if i make it smaller ... more problems
Manage

· Reply · 6d
FEARSPORK i mean my friend

Like
· Reply · 6d

Joe Granato Again, here's what you're saying:

"I deviated from the things in the tutorial video, and now things don't work exactly like they do in the tutorial, and I don't know how to fix it".

To which I'm replying, "Right...I understand. For now, stick to the tutorial videos, and know that you're not creating your dream game, you're just using these as exercises to learn the basics of the tool. More tutorials, more modules, more code, more drop-in solutions will be developed as time goes on, which will help you make the exact game you want...but you're not there yet. Right now, stick to the tutorials. :)"
 

dale_coop

Moderator
Staff member
I think Joe's right. Currenlty NESMaker (even if released) is kinda still a WIP. The tutorial videos are made for us learning how to use the tool, understand the concepts, ... to prepare us for the moment when it will be finliazed (all the modules no more big changes).
So I will also recommend to stick to the video tutorials if you're not familiar (or at ease) with the asm code.

But some small experimentations is alway fun, ah ah ;)
 

fearspork

New member
hey dale_coop as far as i'm concerned you're the top user authority, but after talking to joe about it he did suggest that this is not a bug and so not a priority to fix and that if i wanted a no code solution that i would have to wait for the community to figure it out so... here i am in the community, the code is already there and joe suggested if you know asm its an easy fix. a lot of people have run into this problem and i feel the smaller hitbox solution has stopped other users from looking into this a little deeper -
 

fearspork

New member
i actually have tinkered a bit i made in the neighborhood of 20 copies of my current game build and have cut and snipped and added various things into the code but its all a shot in the dark, ASM is so abstract and i dont know any code
 

dale_coop

Moderator
Staff member
In fact, Joe loves to say you need to stick with the tutorial but that you can do it if you dig in the code. He wants teach you, how to use... and how to break his code!
Of course, he might help us and write that code for us if nobody found the solution. He knows that.
He's very smart, he wants us to lean and master the tool... learn the code, the limitations, the rules... until we are ready to break it ourself.

So I followed his advice, I just followed the tutorials (A LOT of times) and try learning how NESMaker tool works, how the engine works. And try to bend the things I now understand.
The collision code is still blurry for me. I Need to spend more time into it. But as a lot of people here, I am waiting for the 4.1 before diggin' more into the code, right now, because a lot of things will change.
 

fearspork

New member
yeah it probably not worth going crazy until 4.1 but after talking to him last week , he seemed to imply it was an easy fix, thats what got me on my quest again, even in the tutorial he suggests doing 8 points, the code for 6 points is there already. surely one of us nerds knows how this works
 

fearspork

New member
what i figured out above though also explains why the number of tiles cant change to accommodate different animations, if you went from a 1x2 tiles to say 3x2 tiles it would change the adresses for the points on the bounding box mid animation, im sure there are ways to do this but would be way to complicated and take up more space in memory then you would save from the smaller frames in the animations
 

jorotroid

Member
Weird, I thought I posted a reply last night before going to bed. Those forum threads you shared are out of date. The first one was started during the beta. The second one was started by me when version 4.0.0 was the latest version. As of 4.0.11, 6 point collision is in. I'm using it in my game, I have a 2x4 sprite. I think I know what your problem is. Your falling through the floor, not passing through them from the side like my character was in my thread, right? 6 point collision is meant to fix tall characters from going through 1 tile thick platform on the side. For a character with the dimensions you have, you will need 8 point collision to do additional checks below and above the character. Or you can try to cheat a bit and make your bounding box small enough that you don't need to do that.

The code that you pasted is correct for 6 point collision, but it looks like the comments haven't been updated. You can tell that there was some copying and pasting with collision points 4 and 5 because the comments for those and point 3 all say ";;; === handles bottom left corner." I don't think I have the time to write out the code for you at the moment, but I can probably point you in the right direction if your feeling adventurous. I think you'll need to do at least 3 things:
-Add two more copies of the collision code like the ones I pointed out. Then modify them to check for the center bottom and center top of the bounding box. You can divide a number by 2 by using LSR (look in the code you pasted for an example).
-Near the bottom of the code, add ORA collisionPoint6 and 7 for your new collision points.
-Define collisionPoint6 and 7 in ZP_and_vars.asm. Look for the other collision points in there and just add in 6 and 7 right after them.
 

fearspork

New member
i won't be home for hours but this is the missing peice, the file with the point address, so let me run through in my head how to do this
in the collision detection file I need to cut and paste the code for points 4 and 5
change the numbers to 6 and 7 ( label them something like middlerightB or something so I know what it is)
change the code where it says max points 6 to 8 ( I think that's in there twice)
then I need to jump to the variable file
cut and paste the code for collision point variable 4 and 5 (what ever that looks like)
change that to 6 and 7( and probably label that something to match the collision detection file)
and then change the code to define the 2 new addresses

I may need to plot my sprite out on a paper graph, and then alter the size of the bounding box in nesmaker to see how the other points change to get the locations of the other points for the paper graph, if you follow

have I got that about right?
 

fearspork

New member
this is most of the code from TileCollision_platform_simple_alt.asm the code i added 2 more points and changed the max points to 8
Code:
[color=#00FF00];; uses collisionPoint0,1,2,and 3
	;; makes use of left+bbox_left, top+bbox_top, width and height of an object to form bounding box.
	;; gets collision data for each point.

	;LDA ObjectFlags,y
	;AND #%10000000 ;; ignore background collisions?
	;BEQ dontIgnoreBackgroundCollisions
	;LDA Object_flags,x
	;AND #%01000000
	;BEQ dontIgnoreBackgroundCollisions

	;RTS 
dontIgnoreBackgroundCollisions:

	;;;=== HANDLES TOP LEFT CORNER
	LDA xHold_hi
	CLC
	ADC ObjectBboxLeft,y ;; y is still loaded with object type, so this reads from lut table.
	STA tileX
	LDA yHold_hi
	CLC
	ADC ObjectBboxTop,y
	STA tileY
	JSR GetTileAtPosition
	LDA collisionTable,y
	;; y is now loaded with tile type
	STA collisionPoint0
	;;; if it is solid, disregard the other collisions, this should *stop us*.
	LDY Object_type,x
	
	;;; === handles top right corner
	LDA tileX
	CLC
	ADC ObjectWidth,y
	STA tileX
	JSR GetTileAtPosition
	;; y is now loaded with tile type
	LDA collisionTable,y
	STA collisionPoint1

	LDY Object_type,x
	
	;;; === handles bottom right corner
	LDA tileY
	CLC
	ADC ObjectHeight,y
	STA tileY
	JSR GetTileAtPosition
	LDA collisionTable,y
	;; y is now loaded with tile type
	STA collisionPoint2

	LDY Object_type,x
	
	;;; === handles bottom left corner
	LDA tileX
	SEC
	SBC ObjectWidth,y
	STA tileX
	JSR GetTileAtPosition
	LDA collisionTable,y
	;; y is now loaded with tile type
	STA collisionPoint3

;;;;;;;;;;;;;;;;;;six point collision
	LDY Object_type,x
	
	;;; === handles bottom left corner
	LDA ObjectHeight,y
	LSR
	STA temp
	LDA tileY
	SEC 
	SBC temp
	STA tileY
	JSR GetTileAtPosition
	LDA collisionTable,y
	;; y is now loaded with tile type
	STA collisionPoint4

	LDY Object_type,x
	
	;;; === handles bottom left corner
	LDA tileX
	clc 
	adc ObjectWidth,y
	STA tileX
	JSR GetTileAtPosition
	LDA collisionTable,y
	;; y is now loaded with tile type
	STA collisionPoint5

        LDY Object_type,x  
	
	;;; === handles bottom left corner
	LDA ObjectHeight,y
	LSR
	STA temp
	LDA tileY
	SEC 
	SBC temp
	STA tileY
	JSR GetTileAtPosition
	LDA collisionTable,y
	;; y is now loaded with tile type
	STA collisionPoint6

	LDY Object_type,x
	
	;;; === handles bottom left corner
	LDA tileX
	clc 
	adc ObjectWidth,y
	STA tileX
	JSR GetTileAtPosition
	LDA collisionTable,y
	;; y is now loaded with tile type
	STA collisionPoint7

	LDY Object_type,x ;; final restoring corrupted y value
	

	
	
	LDA collisionPoint0
	ORA collisionPoint1
	ORA collisionPoint2
	ORA collisionPoint3
	ORA collisionPoint4
	ORA collisionPoint5
	ORA collisionPoint6
	ORA collisionPoint7
;	;;; all collision points were zero.
	BEQ noCollisionHappened
	
	JMP collisionHappened

noCollisionHappened:	
	RTS ;; no collision happened.
	
collisionHappened:


	LDA currentBank
	STA prevBank
	LDY #DATABANK1
	JSR bankswitchY
	
	TXA 
	STA currentObject
	
	LDA #$00
	STA tempCol
	
DoCheckPointsLoop:
	LDY tempCol
	LDA collisionPoint0,y
	BEQ DontCheckTileType0
	TAY
	LDA tileTypeBehaviorLo,y
	STA temp16
	LDA tileTypeBehaviorHi,y
	STA temp16+1
	JSR UseTileTypeTrampoline
	JMP pastTileTypeTrampoline
UseTileTypeTrampoline:
	JMP (temp16)
pastTileTypeTrampoline
	
DontCheckTileType0:
	INC tempCol
	LDA tempCol
	CMP #$08 ;; max number of collision points. 
	BNE DoCheckPointsLoop

in file ZP_and_VARS.ams i changed this code

Code:
[color=#00FF00];************************************
;;Object collision checking variables
;;************************************
	selfLeft 		.dsb 1				
	selfRight		.dsb 1				
	selfTop			.dsb 1				
	selfBottom		.dsb 1				
	
	otherLeft		.dsb 1				
	otherRight		.dsb 1					
	otherTop		.dsb 1			
	otherBottom		.dsb 1			

	selfCenterX 	.dsb 1				
	selfCenterY		.dsb 1	
					
	otherCenterX	.dsb 1				
	otherCenterY	.dsb 1	
	
	xHold_lo		.dsb 1
	xHold_hi		.dsb 1
	yHold_lo		.dsb 1
	yHold_hi		.dsb 1

	collisionPoint0 .dsb 1
	collisionPoint1 .dsb 1	
	collisionPoint2 .dsb 1
	collisionPoint3 .dsb 1
	collisionPoint4	.dsb 1
	collisionPoint5 .dsb 1
	collisionPoint6	.dsb 1
	collisionPoint7 .dsb 1[
	
	tileX					.dsb 1		
	tileY					.dsb 1	
	tile_solidity		.dsb 1[/color]

this code worked in that it did not error out and the game played but the problem of sliding sideways into one way platforms is still happening, theres still something i'm missing, i have not seen specific defines for points of the bounding box, im thinking now they're not stored in an .ASM file but are held with the specific sprites in a .DAT file... i really dont know though i'm just guessing and its not worth going any further until 4.1 comes out
 

jorotroid

Member
Sorry for taking a while to respond. I had a busy last couple of days. I haven't completely figured out how the one way platforms work, but so far in my opinion, getting caught on them doesn't have anything to do with n points collision. The one way platform code is a little hard to track down, it was hard coded into a different file than the one that is labelled as one way platfrom. I think it was in the tile collision file where it checks to see if you if a tile has attribute 8, then performs some code there.
 

fearspork

New member
jorotroid no worries take the time you like , so my wife actually had the same idea last night to alter the one way platform code in some way but when you open onewayplatform.asm it just says canPenetrate: thats it im kinda at a loss, again i dont know code but my guess is canpenetrate is a command of some sort and the actual code is held in bounds_platform_simple.asm, but that looks like some one spilled scrabble on the floor to me , i'm really pulling this from my ass at this point, this might be the end of the road for me until 4.1 comes out
 

jorotroid

Member
That canPenetrate: doesn't do anything. I don't know why it's there. It's a label that you can jump to from elsewhere in the code. The compiler essentially ignores those. Also it's the only place in the code where that appears, so in other words, nothing is ever jumping to that. If you were to make that file blank, the one way platforms would still work.

The actual one way code appears to be in Physics_Platform_Simple.asm in a few different spots. If you search for CMP #$08 you will probably find a section of code that has to do with one way platforms. Here is one example:

Code:
AboveIsNotSolid:
	;; check other potentiall solid types here
	;; monsters may see other types as solid/not solid - do you want them to respect or ignore here?
	CMP #$08
	BNE AboveIsNotSolid_a
	TYA
	AND #%11110000
	CMP tileY
	BCC AboveIsNotSolid_a
	JMP AboveIsSolid

My best guess on how this works without studying it too hard is that when the player is moving up, if it collides with a one way platform, then that collision gets ignored. On the way, down it registers as solid. So the getting stuck thing probably only happens at the peak of the jump arc such that the one way tile is in the middle of the player so it goes from being free in one frame where the player is moving up, then stuck in the next frame when the player is moving down. Hopefully some one can read this and maybe figure out a fix. I'll look into it if I end up wanting one way platforms in my game, but it looks like a decent time sink at the moment.
 

fearspork

New member
if this is a problem with the one way platform, would it be possible to make right and left end caps that would have solid right and left leading edges that are solid bu still be null from the bottom and solid on top?
 

jorotroid

Member
Maybe, but I have some doubts that it would be the fix you are looking for. For one thing in my tests with one way platform, I've noticed that the problem is not limited to the ends of the one way platforms as you can see in this screen I threw together in my game. It seems like maybe the variable jump script might have something to do with this because I can only seem to get stuck when I release the jump button at just the right time.

g6Ah12u.gif


Also interesting to note is that other times that I release the button, the character moves up higher than a normal jump. I think others here have posted an alternate variable jump. It might be worth checking out to see if it happens to also fix the one ways.

Another reason end caps you might just end up with the same problem with horizontal movement through those caps where the player will suddenly stop moving side to side.
 

fearspork

New member
jorotroid, i know less now then when i started and i ran out of ideas 3 posts ago, well at least now we really honed in on the problem , specifically jump collisions with one way platforms, there must be a solution. my memory of the early 80's is fuzzy but i do remember several player characters of that size but now i'm not remembering if those games actually had one-way platforms. even wider sprites like mine existed for instance megaman was super wide to allow for a different palates to be used on the face and for different animations. 4.1 will come out soon and we can start on a whole new batch of work arounds
 

jorotroid

Member
So I have been running into issues trying to add a tile type that is solid to the player, but null to monsters. I lead me to take a deeper dive into understanding how tile collisions work. I now understand more. I now understand less. In the platform module with the Physics_Platform_Simple.asm file, collision checks when an object is moving horizontally function differently than when an object is moving vertically. When an object collides with a tile horizontally in the platform module (or horizontally and vertically in the adventure module) this eventually jumps to HandleTileCollision in the TileCollision_Platform_Simple_alt.asm file. There it checks all points and if there is a collision, it runs the code in the associated tile behavior file.

With vertical movement, however, there is never a jump to HandleTileCollision so those tile behavior scripts never get called. Instead it appears that each collision point is checked one by one and the behavior of the tile is hard-coded there. I think one of the main reasons it was set up this way was to make it easier to distinguish when an object lands on the ground. At least, that is what I think is going on so far. I need to examine this more after sleep.
 
Top Bottom