[Sonic 1 Github] Basics of Dynamic Level Events, and how to use them in your levels.

Discussion in 'Tutorials' started by Giovanni, Feb 4, 2020.

  1. Giovanni

    Giovanni It's Joevanni, not Geovanni. Member

    Apr 16, 2015
    This guide is in the middle of being edited. Expect the content of this guide to be changed.


    What are Dynamic Level Events?

    Dynamic Level Events are events that happen during a level when a specific condition is met. The condition is checked every frame.

    Dynamic Level Events are found in "_inc\DynamicLevelEvents.asm" if you're a GitHub user, and are generally used to resize a level when you reach specific coordinates, but they can be used for pretty much anything you want.

    Here's an example of Dynamic Level Event taken straight from Scrap Brain Zone act 3:

            cmpi.w    #$D00,(v_screenposx).w
            bcs.s    locret_6F8C
            cmpi.w    #$18,(v_player+obY).w ; has Sonic reached the top of the level?
            bcc.s    locret_6F8C    ; if not, branch
            clr.b    (v_lastlamp).w
            move.w    #1,(f_restart).w ; restart level
            move.w    #(id_SBZ<<8)+2,(v_zone).w ; set level number to 0502 (FZ)
            move.b    #1,(f_lockmulti).w ; freeze Sonic
    This snippet of code represents the way SBZ3 takes you to FZ. What all the code means is that if Sonic reaches $18 on the Y coordinate while his X coordinate is higher than $D00, he will be transported to the Final Zone (The "last checkpoint" variable is reset, and the restart flag is enabled to properly reset Sonic, so that he can reach the Final Zone without in game issues).

    You can do so much more with Dynamic Level Events, as long as you have imagination and programming abilities. For now, I will explain two essential cases where you'll find yourself using Dynamic Level Events.

    How to use DLEs to change the level boundaries.

    I never really liked that section in GHZ2 with the large moving platforms and the spikes at the bottom. I always felt it was too frustrating, so I decided to get rid of it and replace it with something else.


    You'll notice that the area enclosed in the red rectangle has been changed. It has two routes, each connecting to a different part of the original level.

    However, there's a problem with the bottom route, and if you've played enough Sonic 1, I think you already know how things are going to end. If you're confused, here's a video.

    Yup, Sonic dies upon entering the S-tube. That's because of how the original DLEs are set up.

            move.w    #$300,(v_limitbtm1).w
            cmpi.w    #$ED0,(v_screenposx).w
            bcs.s    locret_6E3A
            move.w    #$200,(v_limitbtm1).w
            cmpi.w    #$1600,(v_screenposx).w
            bcs.s    locret_6E3A
            move.w    #$400,(v_limitbtm1).w
            cmpi.w    #$1D60,(v_screenposx).w
            bcs.s    locret_6E3A
            move.w    #$300,(v_limitbtm1).w
    When the screen reaches $ED0 on the X coordinate, the bottom boundary goes up to $200 on the Y coordinate. This corresponds to the bottomless pit that was originally on GHZ2.

    What you need to change ultimately depends on how you design your level, so you'll need to figure out things by yourself. If you find yourself in trouble, you can always use Debug mode or a RAM viewer to help yourself find the right coordinates.

    Here's how I changed the code for my own level:

            move.w    #$300,(v_limitbtm1).w
            cmpi.w    #$1450,(v_screenposx).w
            bcs.s    locret_6E3A
            move.w    #$400,(v_limitbtm1).w
            cmpi.w    #$1D60,(v_screenposx).w
            bcs.s    locret_6E3A
            move.w    #$300,(v_limitbtm1).w
    What I did was remove the trigger that caused the bottom limit to go up to $200, and moved the trigger that increases such limit earlier into the level. This new placement will cause the bottom boundary to move when you reach that part in the level near the new staircase with the crabmeat.

    Here's how the rest of the bottom route plays:

    These new Dynamic Level Events will allow the player to actually take the bottom route as I intended. Of course, all edits you must make depend entirely on how YOU design your level and how you intend it to be played.


    WARNING: Anything past this point is part of an older version of this guide. I will, eventually, polish it.

    How to use DLEs to relocate Eggman.

    DISCLAIMER: This part of the guide assumes that you already know how to resize levels through the Level Size Array. You will also need boss editing skills if you are going to use this part of the guide.

    You're trying to resize GHZ3, but Eggman gets in the way. So you open up your level editor of choice and try to move Eggman's object. Except he isn't there. But where is he then?

    You see, his spawn position does not depend on the position of an object, but it depends on DLEs as well.

            cmpi.w    #$2960,(v_screenposx).w
            bcs.s    locret_6EE8
            bsr.w    FindFreeObj
            bne.s    loc_6ED0
            move.b    #id_BossGreenHill,0(a1) ; load GHZ boss    object
            move.w    #$2A60,obX(a1)
            move.w    #$280,obY(a1)
    This is the code that spawns Eggman.
    Basically, when the screen reaches the X position of #$2960, the game spawns Eggman at the following coordinates:

    X: #$2A60
    Y: #$280

    Let's just try moving him #$1000 pixels further on the X axis. You should replace #$2960 with #$3960 and #$2A60 with #$3A60 to do so. This way, when the screen reaches the X position of #$3960, the game will spawn Eggman.

    This is the final result:

    It works! Except you'll have to change a few values from the Eggman object to make him act properly...

    Thank you for reading this guide! This is just a fraction of what DLEs can do. Trust me, if used well, they can turn a basic level into something impressive! Your only limitations are your programming knowledge, your imagination and the technical limitations of the hardware.

    If you were already aware of how DLEs worked, then please consider giving me feedback! Did I do a good job at explaining? Are there things that I could improve/fix? I am ready to take your suggestions.
    Last edited: Jan 9, 2022