Breakable Tile (4.5.9)

baardbi

Well-known member
There is a tutorial by 9Panzer here on the forum, but I thought I would add another on how to make a simple breakable tile. This script adds an explosion when the tile breaks as well as letting you choose if you want every player weapon to break the tile or only a specific weapon. This script was made for the MetroVania module but it should work fine for most other modules as well.

1. Put the following code in a blank file and save it as BreakableTile.asm. Put the file in a folder that makes sense to you. You could for example put it in the default Tile folder: GameEngineData\Routines\BASE_4_5\Game\TileScripts

;;; Breakable tile

LDA Object_flags,x
AND #%00000100 ;Player weapon
BNE +doBreakThisTile
JMP +skipBreakThisTile
; LDA Object_type,x
; CMP #1 ;Player projectile (game object 1)
; BEQ +doBreakThisTile
; JMP +skipBreakThisTile
+doBreakThisTile:


LDA updateScreenData
AND #%0000100
BEQ +doTile
RTS
+doTile


LDA tileX
AND #%11110000
LSR
LSR
LSR
LSR
STA tempA

LDA tileY
AND #%11110000
STA tempB

LDA Object_screen,x
STA tempC

DestroyObject ;Destroy player weapon

CreateObjectOnScreen tempA, tempB, #8, #0, tempC ;Create explosion (game object 8)
;; arg0 = x
;; arg1 = y
;; arg2 = object
;; arg3 = beginning state
;; arg4 = what screen do youw ant to create this object on?

ChangeTileAtCollision #2, #0 ; Metatile: Tile graphic at position 2 Collision: NULL (0)
; arg0 = metatile to change into
; arg1 = collision to change into.
JSR doWaitFrame

JMP +doneBreakableTile

+skipBreakThisTile:
LDA ObjectUpdateByte
ORA #%00000001
STA ObjectUpdateByte ;; makes solid

+doneBreakableTile:
PS! By default this script will break the tile with any player weapon. If you want a specific weapon (game object) to break tiles you need to remove these lines at the top:

LDA Object_flags,x
AND #%00000100 ;Player weapon
BNE +doBreakThisTile
JMP +skipBreakThisTile


Then uncomment the following lines:

LDA Object_type,x
CMP #1 ;Player projectile (game object 1)
BEQ +doBreakThisTile
JMP +skipBreakThisTile


This script uses game object 8 as the explosion animation when the tile breaks. This can easily be changed at the line CreateObjectOnScreen...

Also make sure that the tile graphic you want to use is set correctly at the line ChangeTileAtCollision... The metatile number is not the same as the tile number. We count these in 8x8 pixel blocks. Use this picture to find the top left corner of your tile graphic for the broken tile:
Tiles.png

2. Assign the new BreakableTile.asm file to a free tile number. You do this in Project Settings - Script Settings:
ScriptSettings.png

3. Rename the tile in Project Settings - Project Labels - Tile Types:
TileName.png

4. That's it. Now you have a breakable tile with an explosion effect.
 
Last edited:

ScrollHaven

New member
This script uses game object 8 as the explosion animation when the tile breaks. This can easily be changed at the line CreateObjectOnScreen...

@baardbi The explosion "object 8" is created in front of the tile. Is there an easy way to have the explosion happen at the center of the tile instead?
 

baardbi

Well-known member
@baardbi The explosion "object 8" is created in front of the tile. Is there an easy way to have the explosion happen at the center of the tile instead?
Sorry! I think it's going to be hard to get that exactly right (especially during scrolling). The position of the explosion is calculated at the moment the projectile collides with the tile. The tile collision code checks the position of the bounding box of the projectile. I haven't experimented with fine tuning that.
 

RMiao

New member
Nice tutorial, thanks!

Quick question: is there a way to add a bit of code so that when all of the breakable blocks on the screen are destroyed, the player warps to the next stage (for an arcade style game, for example)? And also to get points for breaking a block?
 

baardbi

Well-known member
Nice tutorial, thanks!

Quick question: is there a way to add a bit of code so that when all of the breakable blocks on the screen are destroyed, the player warps to the next stage (for an arcade style game, for example)? And also to get points for breaking a block?
It's definitely possible. However, it would require quite a bit of custom code. There's nothing that counts tiles of a certain type in a simple way by default. There's a section about counting tiles in the official NESmaker shooter tutorial where Joe talks about boss blocks. Maybe you could use the method he's using there to count tiles. Adding points is easy. You just use the AddValue macro in the script for the breakable tile:

AddValue arg0, arg1, arg2, arg3
;arg0 = how many places this value has.
;arg1 = home variable
;arg2 = amount to add
;arg3 = what place value is receiving the addition?
;;; 0 = ones place, 1 = tens place, 2 = hundreds place, etc.

An easier way to count tiles could be to use user screen bytes. But that would require setting a fixed number manually on every screen. So you could for example use userScreenByte0 for the number of a certain tile. So if you have 10 breakable tiles on a screen you set userScreenByte0 to 10, and decrease userScreenByte0 in the breakable tile code. You would also need to add a check to see if it has reached 0.

 

strawmancomics

New member
should it matter which direction the projectile is coming from? I'm assuming that most users will be utilizing a left to right kind of projectile. Mine is going up and down.

Also, do I need to add some kind of destroyMe action step to the projectile so that it makes the tile disappear?
 

baardbi

Well-known member
should it matter which direction the projectile is coming from? I'm assuming that most users will be utilizing a left to right kind of projectile. Mine is going up and down.

Also, do I need to add some kind of destroyMe action step to the projectile so that it makes the tile disappear?
Yes. It matters. If you for example drop a projectile on the floor, then the physics script needs to be modified under isSolidSoLand. Top collision probably needs some modification in the solid reaction script. This script only handles collisions from left and right. The projectile doesn't need a destroy me action. When it hits the breakable tile, it is destroyed and a monster death object is created (in this case). This can of course be modified. However, I don't have time to look into these things now I'm afraid. I have to finish my Byte Off project the next couple of days.
 
Yes. It matters. If you for example drop a projectile on the floor, then the physics script needs to be modified under isSolidSoLand. Top collision probably needs some modification in the solid reaction script. This script only handles collisions from left and right. The projectile doesn't need a destroy me action. When it hits the breakable tile, it is destroyed and a monster death object is created (in this case). This can of course be modified. However, I don't have time to look into these things now I'm afraid. I have to finish my Byte Off project the next couple of days.
Aha! Here is the solution to my problem :)
Thank you baardbi

Sharing this, it might help someone else too:
If you dont want to be able to jump through the breakable tile from below, you need to add someting like this to the solid reaction script your player is using.
Open ProjectSettings, scroll down to AI_Solid-reactions
and select the script your player is using when colliding with solid: stopOnSolid_PlatformerBase, for me.

Code:
        ;; ONLY do this is there is a solid directly over head.
        LDY Object_type,x
        LDA Object_x_hi,x
        CLC
        ADC self_left
        STA temp
        JSR getPointColTable
        
        
        LDA Object_y_hi,x
        CLC
        ADC self_top
        CLC
        ADC Object_v_speed_hi,x
        SEC
        SBC #$01
        STA temp1
        
        CheckCollisionPoint temp, temp1, #$01, tempA
        BNE +dontStopVertMove
            JMP +stopVerticalMovementOnSolidHit
        +dontStopVertMove:
        
;;;;;added breaktile 04 as a solid   
        CheckCollisionPoint temp, temp1, #$04, tempA
        BNE +dontStopVertMove
            JMP +stopVerticalMovementOnSolidHit
        +dontStopVertMove:

                ;;adding a right side of player check also
                LDY Object_type,x
                LDA Object_x_hi,x
                CLC
                ADC self_right
                STA tempC
                JSR getPointColTable
        
        
                LDA Object_y_hi,x
                CLC
                ADC self_top
                CLC
                ADC Object_v_speed_hi,x
                SEC
                SBC #$01
                STA tempD

                CheckCollisionPoint tempC, tempD, #$04, tempA
                BNE +dontStopVertMove
                    JMP +stopVerticalMovementOnSolidHit
                +dontStopVertMove:
;;;;/end of added breaktile       

        
        CheckCollisionPoint temp, temp1, #$09, tempA

I wish I had the time to fix this in my ByteOff game before the deadline passed.
But i just ran out of time.
But I'll probably update the Cube with an "improved version" after the byteoff4 winners are announced and the contest is over.
 

TheRetroBro

Active member
Aha! Here is the solution to my problem :)
Thank you baardbi

Sharing this, it might help someone else too:
If you dont want to be able to jump through the breakable tile from below, you need to add someting like this to the solid reaction script your player is using.
Open ProjectSettings, scroll down to AI_Solid-reactions
and select the script your player is using when colliding with solid: stopOnSolid_PlatformerBase, for me.

Code:
        ;; ONLY do this is there is a solid directly over head.
        LDY Object_type,x
        LDA Object_x_hi,x
        CLC
        ADC self_left
        STA temp
        JSR getPointColTable
       
       
        LDA Object_y_hi,x
        CLC
        ADC self_top
        CLC
        ADC Object_v_speed_hi,x
        SEC
        SBC #$01
        STA temp1
       
        CheckCollisionPoint temp, temp1, #$01, tempA
        BNE +dontStopVertMove
            JMP +stopVerticalMovementOnSolidHit
        +dontStopVertMove:
       
;;;;;added breaktile 04 as a solid  
        CheckCollisionPoint temp, temp1, #$04, tempA
        BNE +dontStopVertMove
            JMP +stopVerticalMovementOnSolidHit
        +dontStopVertMove:

                ;;adding a right side of player check also
                LDY Object_type,x
                LDA Object_x_hi,x
                CLC
                ADC self_right
                STA tempC
                JSR getPointColTable
       
       
                LDA Object_y_hi,x
                CLC
                ADC self_top
                CLC
                ADC Object_v_speed_hi,x
                SEC
                SBC #$01
                STA tempD

                CheckCollisionPoint tempC, tempD, #$04, tempA
                BNE +dontStopVertMove
                    JMP +stopVerticalMovementOnSolidHit
                +dontStopVertMove:
;;;;/end of added breaktile      

       
        CheckCollisionPoint temp, temp1, #$09, tempA

I wish I had the time to fix this in my ByteOff game before the deadline passed.
But i just ran out of time.
But I'll probably update the Cube with an "improved version" after the byteoff4 winners are announced and the contest is over.
Thanks for the fix will implement for my current build
 
Top Bottom