Website
Home
Database
News
Submissions queue
Community
Forum
Clubs
Discord
Members
Tools
ROM Patcher
ROM Hasher
Pages
Support us
Learn Romhacking
About
Contact Us
Help & Legal Pages
Guest
Login
Forum
Entries
News
Settings
Community
Tutorials & Guides
[Tutorial] How to add Dynamic Camera in Sonic 1
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
<blockquote data-quote="Mildanner" data-source="post: 6935" data-attributes="member: 7577"><p>In this guide, you will learn how to replace Sonic CD's linear moving camera with the smooth one.</p><p></p><p>If you already have added extended camera, this tutorial may be simple for you. Go to your <strong>_incobj/01 Sonic.asm</strong> file and find the Sonic_PanCamera: label. It has a speed limit of how it will extend.</p><p></p><p>Replace this entire routine of the label with this</p><p>[CODE]Sonic_PanCamera:</p><p> move.w (v_camera_pan).w,d1 ; d1 = Current camera pan value</p><p> move.w #320/2,d3 ; d3 = Default center position (160)</p><p></p><p> move.w obInertia(a0),d0 ; Get Sonic's ground speed</p><p> btst #1,obStatus(a0) ; Is Sonic in the air?</p><p> beq.s .IsGrounded ; If not, branch</p><p> move.w obVelX(a0),d0 ; If in the air, use X velocity</p><p></p><p>.IsGrounded:</p><p> ; d0 stores the speed (positive/right or negative/left)</p><p> ; Maps the speed to the pan offset</p><p> ext.l d0 ; Sign-extend d0 to 32-bit for multiplication</p><p> asl.l #6,d0 ; Multiply speed by 64 (6-bit Logical Shift Left)</p><p> divs.w #$0600,d0 ; Divide by $0600 (Normal maximum speed)</p><p> </p><p> ; Subtract from center to invert logic (look ahead of Sonic)</p><p> sub.w d0,d3 ; d3 = Center - Offset</p><p></p><p> ; Ensure the pan target does not exceed boundaries (+-64 pixels)</p><p> cmpi.w #(320/2)-64,d3 ; Left boundary limit</p><p> bge.s .CheckMaxCap</p><p> move.w #(320/2)-64,d3</p><p></p><p>.CheckMaxCap:</p><p> cmpi.w #(320/2)+64,d3 ; Right boundary limit</p><p> ble.s .ApplyTweening</p><p> move.w #(320/2)+64,d3</p><p></p><p>.ApplyTweening:</p><p> ; d3 = Perfect target position</p><p> ; d1 = Current camera position</p><p> cmp.w d3,d1 ; Is the camera already at the target position?</p><p> beq.s .SetPanVal ; If yes, terminate</p><p> blo.s .TweenRight ; If current position < target, move right</p><p></p><p>.TweenLeft:</p><p> ; Camera needs to move left (decrease d1 towards d3)</p><p> move.w d1,d2 ; d2 = Current position</p><p> sub.w d3,d2 ; d2 = Calculate distance to target (current - target)</p><p> lsr.w #3,d2 ; Divide distance by 8 (adjust smoothness here)</p><p> addq.w #1,d2 ; Guarantee minimum speed of 1px/frame</p><p> </p><p> sub.w d2,d1 ; Apply movement to camera (move left)</p><p> cmp.w d3,d1 ; Did it overshoot the target?</p><p> bge.s .SetPanVal ; If not, continue</p><p> move.w d3,d1 ; If it overshot, snap to exact target</p><p> bra.s .SetPanVal</p><p></p><p>.TweenRight:</p><p> ; Camera needs to move right (increase d1 towards d3)</p><p> move.w d3,d2 ; d2 = Target</p><p> sub.w d1,d2 ; d2 = Calculate distance to target (target - current)</p><p> lsr.w #3,d2 ; Divide distance by 8 (adjust smoothness here)</p><p> addq.w #1,d2 ; Guarantee minimum speed of 1px/frame</p><p> </p><p> add.w d2,d1 ; Apply movement to camera (move right)</p><p> cmp.w d3,d1 ; Did it overshoot the target?</p><p> ble.s .SetPanVal ; If not, continue</p><p> move.w d3,d1 ; If it overshot, snap to exact target</p><p></p><p>.SetPanVal:</p><p> move.w d1,(v_camera_pan).w ; Save the new smoothed pan value into RAM</p><p> rts[/CODE]</p><p>Looks neat! Also, there's a known issue: it looks off for Sonic if you want a fixed camera (only for Sonic when he goes into a Spindash or Peel-out).</p><p></p><p>Please replace your previous version of the 'Pan' Camera code with this newer, fresher one.</p><p>[CODE]Sonic_PanCamera:</p><p> move.w (v_camera_pan).w,d1 ; d1 = Current camera pan value (Actual position)</p><p> move.w #320/2,d3 ; d3 = Default target: Screen center (160)</p><p> move.w #2,d4 ; d4 = DEFAULT SPEED (lsr.w #2 = Divisor 4 for normal running)</p><p></p><p> ; --- ACTIVE STATE CHECK (SPINDASH / PEEL-OUT) ---</p><p> tst.b spindash_flag(a0) ; Is Sonic charging Spindash or Peel-out?</p><p> bne.s .ForcedPanDirection ; If yes, force full pan to the current direction</p><p></p><p> ; --- MOVEMENT CHECK ---</p><p> move.w obInertia(a0),d0 ; Get Sonic's ground speed</p><p> btst #1,obStatus(a0) ; Is Sonic in the air?</p><p> beq.s .CheckGroundVel ; If not, check ground speed</p><p> move.w obVelX(a0),d0 ; If in the air, use X velocity</p><p></p><p>.CheckGroundVel:</p><p> and.w d0,d0 ; Is Sonic completely stopped?</p><p> beq.s .ApplyTweening ; IF STOPPED: Do not modify d3 (Keep default center = 160)</p><p></p><p> ; --- DYNAMIC CALCULATION BY SPEED (Moving) ---</p><p> ext.l d0 ; Sign-extend to 32-bit</p><p> asl.l #6,d0 ; Multiply speed by 64</p><p> divs.w #$0600,d0 ; Divide by the game's maximum speed</p><p> sub.w d0,d3 ; d3 = Center (160) - Dynamic offset</p><p> bra.s .ClampCameraLimits</p><p></p><p>.ForcedPanDirection:</p><p> move.w #3,d4 ; OMIT ADDITIONAL CHANGES: PEEL-OUT SPEED CHANGE HERE</p><p> ; (lsr.w #3 = Divisor 8. Makes Peel-Out panning slower and smoother)</p><p></p><p> ; If charging Spindash/Peel-out while stationary, shift the target completely</p><p> btst #0,obStatus(a0) ; Check Sonic's direction (Bit 0: 0=Right, 1=Left)</p><p> beq.s .ForcedRight</p><p></p><p> ; Looking left: push camera ahead of Sonic (Add to target d3)</p><p> add.w #64,d3 ; d3 = 160 + 64 = 224</p><p> bra.s .ApplyTweening</p><p></p><p>.ForcedRight:</p><p> ; Looking right: push camera ahead of Sonic (Subtract from target d3)</p><p> sub.w #64,d3 ; d3 = 160 - 64 = 96</p><p> bra.s .ApplyTweening</p><p></p><p>.ClampCameraLimits:</p><p> ; Ensures calculation by speed does not break safe boundaries of +-64 pixels</p><p> cmpi.w #(320/2)-64,d3 ; Left limit (96)</p><p> bge.s .CheckMaxCap</p><p> move.w #(320/2)-64,d3</p><p></p><p>.CheckMaxCap:</p><p> cmpi.w #(320/2)+64,d3 ; Right limit (224)</p><p> ble.s .ApplyTweening</p><p> move.w #(320/2)+64,d3</p><p></p><p>.ApplyTweening:</p><p> ; d3 = Final validated target</p><p> ; d1 = Current camera position</p><p> cmp.w d3,d1 ; Is the camera already at the target position?</p><p> beq.s .SaveAndExit ; If yes, exit without wasting processing time</p><p> bgt.s .TweenLeft ; If current (d1) > target (d3), move left</p><p></p><p>.TweenRight:</p><p> ; --- IMPROVED TWEENING TO THE RIGHT ---</p><p> move.w d3,d2 ; d2 = Target</p><p> sub.w d1,d2 ; d2 = Remaining distance (Target - Current)</p><p> lsr.w d4,d2 ; Apply the speed stored in d4</p><p> addq.w #1,d2 ; Adjusted minimum speed to 1px for maximum smoothness</p><p> </p><p> add.w d2,d1 ; Apply movement to the right</p><p> cmp.w d3,d1 ; Did it overshoot the target?</p><p> blt.s .SaveAndExit ; If not, save</p><p> move.w d3,d1 ; If it overshot, snap to exact target</p><p> bra.s .SaveAndExit</p><p></p><p>.TweenLeft:</p><p> ; --- IMPROVED TWEENING TO THE LEFT ---</p><p> move.w d1,d2 ; d2 = Current</p><p> sub.w d3,d2 ; d2 = Remaining distance (Current - Target)</p><p> lsr.w d4,d2 ; Apply the speed stored in d4</p><p> addq.w #1,d2 ; Adjusted minimum speed to 1px for maximum smoothness</p><p> </p><p> sub.w d2,d1 ; Apply movement to the left</p><p> cmp.w d3,d1 ; Did it overshoot the target?</p><p> bgt.s .SaveAndExit ; If not, save</p><p> move.w d3,d1 ; If it overshot, snap to exact target</p><p></p><p>.SaveAndExit:</p><p> move.w d1,(v_camera_pan).w ; Save the new corrected pan value into RAM</p><p> rts[/CODE]</p><p>And... That's it! I hope you enjoyed this tutorial, enjoy your vastly dynamic camera which is better for player's vision and no comparison to the original game.</p><p></p><p>Happy hacking! <img class="smilie smilie--emoji" alt="😃" src="https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/72x72/1f603.png" title="Grinning face with big eyes :smiley:" data-shortname=":smiley:" loading="lazy" width="72" height="72" /></p></blockquote><p></p>
[QUOTE="Mildanner, post: 6935, member: 7577"] In this guide, you will learn how to replace Sonic CD's linear moving camera with the smooth one. If you already have added extended camera, this tutorial may be simple for you. Go to your [B]_incobj/01 Sonic.asm[/B] file and find the Sonic_PanCamera: label. It has a speed limit of how it will extend. Replace this entire routine of the label with this [CODE]Sonic_PanCamera: move.w (v_camera_pan).w,d1 ; d1 = Current camera pan value move.w #320/2,d3 ; d3 = Default center position (160) move.w obInertia(a0),d0 ; Get Sonic's ground speed btst #1,obStatus(a0) ; Is Sonic in the air? beq.s .IsGrounded ; If not, branch move.w obVelX(a0),d0 ; If in the air, use X velocity .IsGrounded: ; d0 stores the speed (positive/right or negative/left) ; Maps the speed to the pan offset ext.l d0 ; Sign-extend d0 to 32-bit for multiplication asl.l #6,d0 ; Multiply speed by 64 (6-bit Logical Shift Left) divs.w #$0600,d0 ; Divide by $0600 (Normal maximum speed) ; Subtract from center to invert logic (look ahead of Sonic) sub.w d0,d3 ; d3 = Center - Offset ; Ensure the pan target does not exceed boundaries (+-64 pixels) cmpi.w #(320/2)-64,d3 ; Left boundary limit bge.s .CheckMaxCap move.w #(320/2)-64,d3 .CheckMaxCap: cmpi.w #(320/2)+64,d3 ; Right boundary limit ble.s .ApplyTweening move.w #(320/2)+64,d3 .ApplyTweening: ; d3 = Perfect target position ; d1 = Current camera position cmp.w d3,d1 ; Is the camera already at the target position? beq.s .SetPanVal ; If yes, terminate blo.s .TweenRight ; If current position < target, move right .TweenLeft: ; Camera needs to move left (decrease d1 towards d3) move.w d1,d2 ; d2 = Current position sub.w d3,d2 ; d2 = Calculate distance to target (current - target) lsr.w #3,d2 ; Divide distance by 8 (adjust smoothness here) addq.w #1,d2 ; Guarantee minimum speed of 1px/frame sub.w d2,d1 ; Apply movement to camera (move left) cmp.w d3,d1 ; Did it overshoot the target? bge.s .SetPanVal ; If not, continue move.w d3,d1 ; If it overshot, snap to exact target bra.s .SetPanVal .TweenRight: ; Camera needs to move right (increase d1 towards d3) move.w d3,d2 ; d2 = Target sub.w d1,d2 ; d2 = Calculate distance to target (target - current) lsr.w #3,d2 ; Divide distance by 8 (adjust smoothness here) addq.w #1,d2 ; Guarantee minimum speed of 1px/frame add.w d2,d1 ; Apply movement to camera (move right) cmp.w d3,d1 ; Did it overshoot the target? ble.s .SetPanVal ; If not, continue move.w d3,d1 ; If it overshot, snap to exact target .SetPanVal: move.w d1,(v_camera_pan).w ; Save the new smoothed pan value into RAM rts[/CODE] Looks neat! Also, there's a known issue: it looks off for Sonic if you want a fixed camera (only for Sonic when he goes into a Spindash or Peel-out). Please replace your previous version of the 'Pan' Camera code with this newer, fresher one. [CODE]Sonic_PanCamera: move.w (v_camera_pan).w,d1 ; d1 = Current camera pan value (Actual position) move.w #320/2,d3 ; d3 = Default target: Screen center (160) move.w #2,d4 ; d4 = DEFAULT SPEED (lsr.w #2 = Divisor 4 for normal running) ; --- ACTIVE STATE CHECK (SPINDASH / PEEL-OUT) --- tst.b spindash_flag(a0) ; Is Sonic charging Spindash or Peel-out? bne.s .ForcedPanDirection ; If yes, force full pan to the current direction ; --- MOVEMENT CHECK --- move.w obInertia(a0),d0 ; Get Sonic's ground speed btst #1,obStatus(a0) ; Is Sonic in the air? beq.s .CheckGroundVel ; If not, check ground speed move.w obVelX(a0),d0 ; If in the air, use X velocity .CheckGroundVel: and.w d0,d0 ; Is Sonic completely stopped? beq.s .ApplyTweening ; IF STOPPED: Do not modify d3 (Keep default center = 160) ; --- DYNAMIC CALCULATION BY SPEED (Moving) --- ext.l d0 ; Sign-extend to 32-bit asl.l #6,d0 ; Multiply speed by 64 divs.w #$0600,d0 ; Divide by the game's maximum speed sub.w d0,d3 ; d3 = Center (160) - Dynamic offset bra.s .ClampCameraLimits .ForcedPanDirection: move.w #3,d4 ; OMIT ADDITIONAL CHANGES: PEEL-OUT SPEED CHANGE HERE ; (lsr.w #3 = Divisor 8. Makes Peel-Out panning slower and smoother) ; If charging Spindash/Peel-out while stationary, shift the target completely btst #0,obStatus(a0) ; Check Sonic's direction (Bit 0: 0=Right, 1=Left) beq.s .ForcedRight ; Looking left: push camera ahead of Sonic (Add to target d3) add.w #64,d3 ; d3 = 160 + 64 = 224 bra.s .ApplyTweening .ForcedRight: ; Looking right: push camera ahead of Sonic (Subtract from target d3) sub.w #64,d3 ; d3 = 160 - 64 = 96 bra.s .ApplyTweening .ClampCameraLimits: ; Ensures calculation by speed does not break safe boundaries of +-64 pixels cmpi.w #(320/2)-64,d3 ; Left limit (96) bge.s .CheckMaxCap move.w #(320/2)-64,d3 .CheckMaxCap: cmpi.w #(320/2)+64,d3 ; Right limit (224) ble.s .ApplyTweening move.w #(320/2)+64,d3 .ApplyTweening: ; d3 = Final validated target ; d1 = Current camera position cmp.w d3,d1 ; Is the camera already at the target position? beq.s .SaveAndExit ; If yes, exit without wasting processing time bgt.s .TweenLeft ; If current (d1) > target (d3), move left .TweenRight: ; --- IMPROVED TWEENING TO THE RIGHT --- move.w d3,d2 ; d2 = Target sub.w d1,d2 ; d2 = Remaining distance (Target - Current) lsr.w d4,d2 ; Apply the speed stored in d4 addq.w #1,d2 ; Adjusted minimum speed to 1px for maximum smoothness add.w d2,d1 ; Apply movement to the right cmp.w d3,d1 ; Did it overshoot the target? blt.s .SaveAndExit ; If not, save move.w d3,d1 ; If it overshot, snap to exact target bra.s .SaveAndExit .TweenLeft: ; --- IMPROVED TWEENING TO THE LEFT --- move.w d1,d2 ; d2 = Current sub.w d3,d2 ; d2 = Remaining distance (Current - Target) lsr.w d4,d2 ; Apply the speed stored in d4 addq.w #1,d2 ; Adjusted minimum speed to 1px for maximum smoothness sub.w d2,d1 ; Apply movement to the left cmp.w d3,d1 ; Did it overshoot the target? bgt.s .SaveAndExit ; If not, save move.w d3,d1 ; If it overshot, snap to exact target .SaveAndExit: move.w d1,(v_camera_pan).w ; Save the new corrected pan value into RAM rts[/CODE] And... That's it! I hope you enjoyed this tutorial, enjoy your vastly dynamic camera which is better for player's vision and no comparison to the original game. Happy hacking! 😃 [/QUOTE]
Insert quotes…
Verification
Post reply
Community
Tutorials & Guides
[Tutorial] How to add Dynamic Camera in Sonic 1
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.
Accept
Learn more…
Back
Top