Changing background tiles from code

PH5

New member
Hi all. I can't figure out how to change the background graphics assets from custom code. What I would like to do is change a closed door asset with a solid tile type to an open door asset with a warp to screen tile type. The closest example would be something like in the legend of zelda when you are in a dungeon and push a block and a stairway appears somewhere on the screen. I have studied all of the code I can find that changes background objects, but they all seem to act on objects that are at the point of collision. I can't figure out how to find an object on the screen and either change the object directly, or destroy it and create a new one. I believe it would be somewhat like what the macros from ChangeTile.asm or ChangeTileAtCollision.asm do.

I think the smart thing would be to loop through all of the background objects and look for a certain custom tile type (i.e a closeddoor tile type) to find it's coordinates. I know assembly code well enough, but I just don't understand the underlying coding for object storage enough to know how to do that. Can anyone show me how to loop through the objects and access their details? Any help or suggestions is appreciated.
 

Mugi

Member
MACRO ChangeAllTiles arg0, arg1, arg2, arg3
; arg0 - what tile index (collision) are you trying to change?
; arg1 - what is the new collision type?
; arg2 - what is the new top left meta tile value?
; arg3 - which nametable, left or right. 0 - left, 1 = right

changes a tile based on it's collision type (say, door tile, or a warp tile) into a tile with new collision type and new graphic value. This changes all the tiles of that type into the new type though.

the macro list has several macros for different ways to change tiles. it's worth to take a look from the defined script's macro list to see what they do.
 

dale_coop

Moderator
Staff member
A good example would be the "4 - Locked Door" tile types... check the LockedDoor.asm script.
 

PH5

New member
Mugi - That looks very close to what I am looking for. If I understand it right then, if I want to change the Solid type to a Warp to Screen type, arg0 would equal 1 ( would it be #TILE_SOLID?), and arg1 would equal 5? This being based on the typical info on tile types in project settings. And arg3 would typically be the currentnametable for the screen my player is on? And then, where do I get the top left meta tile value?

Dale - I've looked at this briefly, but it appears that it always interacts with the point of collision. So, I think what Mugi is suggesting is closer to what I am trying to do, which is interact with something somewhere else on the screen. Good thought though!
 

Mugi

Member
keep in mind though, that this tile macro replaces ALL tiles that are defined as solid, so your floor, your walls your whatever.
to have it replace specific tiles, you will have to have a specific collision type defined for it.

for an example, if you want to replace your solid tiles (collision type 01) to a warp tile (collision type 05)
you will do:

ChangeAllTiles #$01, #$05, #$xx ,currentnametable
the xx here would be the coordinate of the new tile graphic in your graphics bank.
(note: im not really sure how "currentnametable" works here so it might spaz out on you, test it and see how it goes.)


the top left tile is #$00 and the bottom right tile is #$FF

keep in mind that this allows you to draw using any loaded tiles (main tiles, screentiles, path tiles, hud tiles)
the layout of it is as follows:

PPU_chart.png

nevermind my scribbles on the picture, i use the graphics a little differently than nesmaker wants me to :p
 

PH5

New member
I'm closer, but not quite there. So I made a test input script with the following:

ChangeAllTiles #$08,#$05,#$0A,#$00
RTS

My new tile type is #$08 and I set my closed door asset to that type and made the closed door collision script set as a solid. The script above works on the first screen. I found that nametables don't work as expected. 0 in nametables affects the entire visible screen for me. 1 only affects the left half of the visible screen. Not sure what is happening there. But, the main problem is on the next screen. On the second screen, the code works and changes the image of the closed door to an open door as expected. But, the door doesn't change from solid to warp. My player can't pass into it or warp with it. I also tried changing #$01 type to a #$05 type, which changed a lot of screen tiles, and the behavior was the same from one screen to the next. Is there a bug in the ChangeAllTiles macro? Is there some sort of carry-over affect from one screen to the next that I am not seeing? Any thoughts?
 

dale_coop

Moderator
Staff member
Have you tried, changing for both nametables at the same time?

Code:
	ChangeAllTiles #$08,#$05,#$0A,#$00
	ChangeAllTiles #$08,#$05,#$0A,#$01
	RTS
 

Mugi

Member
it propably doesnt play nice with the scrolling if i had to guess.
but i dont really use this myself so i have no experience to say what it's actually doing.

ifi had to guess the issue is that since the macro has a nametable value, it will only do the change affecting this nametable, and since with scrolling we now have 2 nametables loaded, the other one is simply being ignored.
you could try to call it twice to make it write on both tables i suppose. but im terrible with the nametable stuff to begin with (i gave up on fixing the scrolling because im just too stupid for this whole deal with tables lol.) so yeah... no idea really.
 

PH5

New member
Since you mention scrolling, I think maybe it is the wrong set of scripts that is messing with me. I am basically doing like the maze game tutorial, no scrolling involved. But when I started my game, I chose basic instead of basic_no_scrolling as my type. Now, I wonder if that is part of what is messing me up. I'll try changing that later today and see what happens.
 

Mugi

Member
what dale_coop said.

that said, if you use the basic module, it does still contain the scrolling engine in it as far as i know (all the modules up to 4.1.4 before the noscrolling engine was added contain it)
which means that even if you're not using the scrolling, the engine is still loading 2 nametables at once.
 

PH5

New member
OK. So maybe not changing the code base then. I'll try hitting it twice as you suggested Dale. Thanks!
 

PH5

New member
Yes, running the ChangeAllTiles once for each nametable seems to work. The doors work correctly now. I wish I knew better what was going on in the details there, but I am happy with the results.
 

dale_coop

Moderator
Staff member
As Mugi, said the engine loads 2 nametables each time (the data for 2 screens)... for dealing with the scrolling code. Even if you are not making a scrolling game.
So if you update only one the two name tables you will have only half of the tiles changed on your screen (and the code that load the screen is not the same for even screens and for odd screens. It's the reason you had not the same result on the second screen).

If you check the tutorial video about "understanding the sprite0", you can see a illustration of that (for example, the HUD doesn't render on odd screens...).
 

baardbi

Well-known member
is this still working , cause i cant find such macro .. only the collision one
dale_coop made a great macro that let's you change a tile at a given position.

 
Top Bottom