Bucket Mouse
Active member
Earlier this month I posted eagerly about the invention of the Multi-Tile. There was no enthusiasm or any sort of reaction whatsoever from anyone else. I still don't understand why. If you can make a tile do more than one thing, then the small number of tiles you're given is no longer a limitation. I can do all sorts of things with just one tile now, like for example, warping to fifteen different screens from just one screen. Using just one tile.
The old warp system works by directly assigning warp information to each screen. Every warp tile you place on that screen will go to that location and that location only. You can duplicate the code and make another tile that takes you somewhere else, but if you keep doing that, you'll run out of tiles quickly.
If only you could directly TELL the tile, "this door leads to THIS house and THIS door leads to THAT house." What we need is a tile smart enough to know where exactly on the screen you are, and based on that information, where to send you. Voila!
****
Before we begin, a word of caution: this is not a plug-and-play type of code. You will need to customize it for the needs of the game you're applying it toward. If you're just starting out with NESMaker or ASM you probably won't know what to do. What specifically do you need to know? For starters, how to read the grid of the screen.
Each screen is a 16 by 16 grid, made up of 16 by 16 pixels. They work on a Base 16 numerical system -- hexadecimal numbers, 0 through 9 and then A through F. Each of those pixels has an assigned hex code. In order for the multi-warp tile to recognize where it should do something, you first have to tell it "if the player is standing on the tile and their coordinates are within THIS hex range, then warp to THIS screen." You must know the addresses of your warps.
Fortunately using any Overworld or Underworld screen this is rather simple. If you drag your mouse over the map screen you'll notice little numbers above that tell you the X and Y coordinates of each graphics square. So say you want the warp to take you to screen #1 if the tile is placed on X=2 and Y=4.
Easy. X in this case is #$20 and Y would be #$40. You just have to add a zero (and also convert the number to a letter if it's 10 or over). Here if the player and the tile intersect in the range of #$20 to #$2F horizontally and #$40 to #$4F vertically, a warp should be activated to screen #$01.
HOWEVER if you simply enter that into the code, the sprite will need to be spot-on to activate the warp. Nine times out of ten the sprite will simply hit half the square and nothing will happen, so to allow for this, you must overshoot the numbers by 1 in each direction.
Now that we've made that modification, we have #$10 to #$30 for X and #$30 to #$50 for Y. All we need is the hex code for the screen we want.
The screens are, again, arranged in a 16 by 16 grid for both the Overworld and the Underworld so we get those numbers the same way. Hold your mouse over where you want the player to travel.
Here's where things are a bit different because screens are not named with X and Y coordinates. Instead they're given specific hex numbers. So if your screen is X=11 and Y=0 the actual name of the screen is #$0B.
Now we have the information to make a multi-warp tile.
*****
Below is the rough version of my multi-warp program. You'll notice a lot of repetition in the code. You'll also notice at the beginning I establish variables that I only ended up using once -- this is because I was setting up a loop to cut down on the repeated commands, and I couldn't get the loop to work. Something in the math was wrong. Maybe it's better to post this version since you can read the flow of what's happening more easily.
The program is written to work with the screen warp layout seen in this Facebook post: https://www.facebook.com/groups/NESmakers/permalink/874227152931611/
There are fifteen warps on the screen, five each in three rows. First the program determines which row you're standing on and then which square in that row.
The bugs discussed below have now been fixed. Let me know if you find any more.
The old warp system works by directly assigning warp information to each screen. Every warp tile you place on that screen will go to that location and that location only. You can duplicate the code and make another tile that takes you somewhere else, but if you keep doing that, you'll run out of tiles quickly.
If only you could directly TELL the tile, "this door leads to THIS house and THIS door leads to THAT house." What we need is a tile smart enough to know where exactly on the screen you are, and based on that information, where to send you. Voila!
****
Before we begin, a word of caution: this is not a plug-and-play type of code. You will need to customize it for the needs of the game you're applying it toward. If you're just starting out with NESMaker or ASM you probably won't know what to do. What specifically do you need to know? For starters, how to read the grid of the screen.
Each screen is a 16 by 16 grid, made up of 16 by 16 pixels. They work on a Base 16 numerical system -- hexadecimal numbers, 0 through 9 and then A through F. Each of those pixels has an assigned hex code. In order for the multi-warp tile to recognize where it should do something, you first have to tell it "if the player is standing on the tile and their coordinates are within THIS hex range, then warp to THIS screen." You must know the addresses of your warps.
Fortunately using any Overworld or Underworld screen this is rather simple. If you drag your mouse over the map screen you'll notice little numbers above that tell you the X and Y coordinates of each graphics square. So say you want the warp to take you to screen #1 if the tile is placed on X=2 and Y=4.
Easy. X in this case is #$20 and Y would be #$40. You just have to add a zero (and also convert the number to a letter if it's 10 or over). Here if the player and the tile intersect in the range of #$20 to #$2F horizontally and #$40 to #$4F vertically, a warp should be activated to screen #$01.
HOWEVER if you simply enter that into the code, the sprite will need to be spot-on to activate the warp. Nine times out of ten the sprite will simply hit half the square and nothing will happen, so to allow for this, you must overshoot the numbers by 1 in each direction.
Now that we've made that modification, we have #$10 to #$30 for X and #$30 to #$50 for Y. All we need is the hex code for the screen we want.
The screens are, again, arranged in a 16 by 16 grid for both the Overworld and the Underworld so we get those numbers the same way. Hold your mouse over where you want the player to travel.
Here's where things are a bit different because screens are not named with X and Y coordinates. Instead they're given specific hex numbers. So if your screen is X=11 and Y=0 the actual name of the screen is #$0B.
Now we have the information to make a multi-warp tile.
*****
Below is the rough version of my multi-warp program. You'll notice a lot of repetition in the code. You'll also notice at the beginning I establish variables that I only ended up using once -- this is because I was setting up a loop to cut down on the repeated commands, and I couldn't get the loop to work. Something in the math was wrong. Maybe it's better to post this version since you can read the flow of what's happening more easily.
The program is written to work with the screen warp layout seen in this Facebook post: https://www.facebook.com/groups/NESmakers/permalink/874227152931611/
There are fifteen warps on the screen, five each in three rows. First the program determines which row you're standing on and then which square in that row.
Code:
; MACRO GoToScreen arg0, arg1, arg2
; arg 0 = screen to warp to.
; arg 1 = map, usually #$01
; arg 2 = transition type, usually #$02
; A graphics block is made up of 16 pixels...hex numbers are base 16
; Look at the overworld grid to determine the coordinates
; If the door is at X=2 and Y=4, the coordinates for X are #$20 through #$2F and Y is #$40 through #$4F
; Overshoot your numbers by 1 to compensate for half-touches
; Try to put your doors equal increments apart, so you can create a loop
LDA #$10
STA warpXV
LDA #$30
STA warpYV
LDA #$00
STA warpXH
LDA #$20
STA warpYH
LDA #$01
STA screen2warp2
LDX player1_object
LDA Object_y_hi,x ; load vertical location of player
CMP warpXV
BCC NotSpot1 ; branch if it's less than the spot's general area
CMP warpYV
BCS NotSpot1 ; branch if it's more than the spot's general area
JMP RowSelected ; looks like the player lines up vertically...jump to the horizontal part
NotSpot1: ; the player is not on Row 1, so let's check Row 2
CMP #$50
BCC NotSpot2 ; branch if it's less than the spot's general area
CMP #$70
BCS NotSpot2 ; branch if it's more than the spot's general area
LDA screen2warp2
CLC
ADC #$05 ; add five to screenwarp number since we skipped the five squares in Row 1
STA screen2warp2
JMP RowSelected ; looks like the player lines up vertically...jump to the horizontal part
NotSpot2: ; the player is not on Row 2, so let's check Row 3
CMP #$A0
BCC NotSpot3 ; branch if it's less than the spot's general area
CMP #$C0
BCS NotSpot3 ; branch if it's more than the spot's general area
LDA screen2warp2
CLC
ADC #$0A ; add ten to screenwarp number
STA screen2warp2
JMP RowSelected ; looks like the player lines up vertically...jump to the horizontal part
NotSpot3:
JMP Notanything ; the player is not on any of the tiles, so the program is over
RowSelected:
LDA Object_x_hi,x ; load horizontal location of player
CMP warpXH
BCC Notdoor1
CMP warpYH
BCS Notdoor1
GoToScreen screen2warp2, #$01, #$02 ; We're in the X and Y zone -- we can warp
JMP Notanything
Notdoor1:
INC screen2warp2
CMP #$30
BCC Notdoor2
CMP #$50
BCS Notdoor2
GoToScreen screen2warp2, #$01, #$02 ; We're in the X and Y zone -- we can warp
JMP Notanything
Notdoor2:
INC screen2warp2
CMP #$60
BCC Notdoor3
CMP #$80
BCS Notdoor3
GoToScreen screen2warp2, #$01, #$02 ; We're in the X and Y zone -- we can warp
JMP Notanything
Notdoor3:
INC screen2warp2
CMP #$90
BCC Notdoor4
CMP #$B0
BCS Notdoor4
GoToScreen screen2warp2, #$01, #$02 ; We're in the X and Y zone -- we can warp
JMP Notanything
Notdoor4:
INC screen2warp2
CMP #$C0
BCC Notdoor5
CMP #$E0
BCS Notdoor5
GoToScreen screen2warp2, #$01, #$02 ; We're in the X and Y zone -- we can warp
JMP Notdoor5
Notdoor5:
Notanything:
The bugs discussed below have now been fixed. Let me know if you find any more.