From 1fabf1e914db5052fb6655d4e6b870bac0e70a30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:10:54 +0000 Subject: [PATCH 1/6] Initial plan From a1a223f4e23d640180b8edf7b53db9e7427b8aca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:16:46 +0000 Subject: [PATCH 2/6] Add Sonic The Hedgehog controller script with Sonic 2 accurate physics Co-authored-by: ExtCan <60326708+ExtCan@users.noreply.github.com> --- Content/scripts/sonic_the_hedgehog/README.md | 164 +++ .../sonic_the_hedgehog/sonic_the_hedgehog.lua | 1038 +++++++++++++++++ 2 files changed, 1202 insertions(+) create mode 100644 Content/scripts/sonic_the_hedgehog/README.md create mode 100644 Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua diff --git a/Content/scripts/sonic_the_hedgehog/README.md b/Content/scripts/sonic_the_hedgehog/README.md new file mode 100644 index 0000000000..56de967867 --- /dev/null +++ b/Content/scripts/sonic_the_hedgehog/README.md @@ -0,0 +1,164 @@ +# Sonic The Hedgehog for WickedEngine + +A Lua script that implements a playable Sonic The Hedgehog character with physics accurate to Sonic The Hedgehog 2 (1992). + +## Features + +### Sonic 2 Accurate Physics + +This implementation faithfully recreates the physics system from Sonic The Hedgehog 2, including: + +#### Ground Movement +- **Acceleration**: 0.046875 pixels/frame² (12/256 subpixels) +- **Deceleration**: 0.5 pixels/frame² (128/256 subpixels) +- **Friction**: 0.046875 pixels/frame² (same as acceleration) +- **Top Speed**: 6 pixels/frame (1536/256 subpixels) + +#### Rolling Physics +- **Roll Friction**: 0.0234375 pixels/frame² (half of normal friction) +- **Roll Deceleration**: 0.125 pixels/frame² (when actively braking) +- Automatic uncurl when speed drops below 1 pixel/frame + +#### Air Movement +- **Air Acceleration**: 0.09375 pixels/frame² (2x ground acceleration) +- **Air Drag**: Applied when moving upward and horizontally fast +- No deceleration or friction while airborne + +#### Jumping +- **Jump Force**: 6.5 pixels/frame initial velocity +- **Variable Jump Height**: Release early for shorter jumps +- **Jump Release Cap**: 4 pixels/frame minimum upward velocity + +#### Gravity +- **Gravity**: 0.21875 pixels/frame² (56/256 subpixels) +- **Terminal Velocity**: 16 pixels/frame + +#### Slope Physics +- **Slope Factor**: 0.125 pixels/frame² (affects ground speed on inclines) +- **Roll Uphill Factor**: 0.078125 pixels/frame² (less speed loss going up) +- **Roll Downhill Factor**: 0.3125 pixels/frame² (more speed gain going down) + +#### Spin Dash (Sonic 2 Feature) +- **Base Speed**: 8 pixels/frame +- **Charge Increment**: 2 pixels/frame per button press +- **Maximum Charges**: 8 +- **Charge Decay**: floor(charge × 8) / 256 per frame + +### Character States + +The script implements all classic Sonic states: +- Idle +- Walking +- Running +- Jumping +- Rolling (Spin Attack) +- Spin Dash +- Skidding +- Pushing +- Looking Up +- Crouching +- Balancing (edge detection) +- Hurt +- Dying + +### Collision System + +The script uses a sensor-based collision system similar to the original: +- Ground sensors for floor detection +- Wall sensors for horizontal collision +- Ceiling sensors for overhead collision +- Slope angle detection for proper physics on inclines + +## Controls + +| Action | Keyboard | Gamepad | +|--------|----------|---------| +| Move Left/Right | Arrow Keys / A,D | Left Stick | +| Look Up | Up Arrow / W | Left Stick Up | +| Crouch | Down Arrow / S | Left Stick Down | +| Jump | Space | A Button | +| Roll | Down while moving | Down while moving | +| Spin Dash | Down + Space (hold & release) | Down + A (hold & release) | +| Toggle Debug | H | - | +| Reload Script | R | - | +| Exit | Escape | - | + +## Usage + +### Loading the Script + +1. Place the script in your WickedEngine content folder +2. In the WickedEngine Editor or your application, execute: + ```lua + dofile("Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua") + ``` + +### Integration with Your Scene + +The script creates a 2D render path by default. To integrate with a 3D scene: + +1. Modify the render path creation to use `RenderPath3D` +2. Add scene collision detection using `scene.Intersects()` +3. Load your level geometry with navigation mesh tags + +### Customization + +#### Adjusting Physics + +All physics constants are defined in the `Physics` table at the top of the script. You can modify these to create different gameplay feels: + +```lua +Physics.TOP_SPEED = toPixelsPerSecond(2048) -- Faster top speed +Physics.JUMP_FORCE = toPixelsPerSecond(2000) -- Higher jumps +Physics.GRAVITY = toPixelsPerSecondSq(40) -- Floatier physics +``` + +#### Adding Sprites + +Replace the placeholder sprite with your own Sonic sprite sheet: + +```lua +self.sprite = Sprite("path/to/sonic_spritesheet.png") +-- Configure sprite sheet animation using DrawRectAnim +``` + +## Technical Notes + +### Subpixel Conversion + +The original Sonic games used a 256 subpixel-per-pixel system at 60 FPS. This script converts these values to pixels/second for WickedEngine's variable timestep: + +```lua +-- Convert from subpixels/frame to pixels/second +local function toPixelsPerSecond(subpixelsPerFrame) + return subpixelsPerFrame * (1/256) * 60 +end +``` + +### Frame Independence + +All physics calculations use delta time (`dt`) for frame-rate independent movement: + +```lua +self.groundSpeed = self.groundSpeed - Physics.ACCELERATION * dt +``` + +### Sensor System + +The collision system uses the same sensor layout as the original games: +- Two ground sensors (left and right, 9 pixels apart) +- Two wall sensors (at mid-height) +- Two ceiling sensors + +## References + +- [Sonic Retro Physics Guide](https://info.sonicretro.org/Sonic_Physics_Guide) +- [Sonic 2 Disassembly](https://github.com/sonicretro/s2disasm) + +## License + +This script is provided as part of the WickedEngine samples and is subject to the WickedEngine license. + +## Version History + +- **1.0**: Initial release with Sonic 2 physics implementation diff --git a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua new file mode 100644 index 0000000000..e7f8bd330f --- /dev/null +++ b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua @@ -0,0 +1,1038 @@ +-- Sonic The Hedgehog Controller Script for WickedEngine +-- Implements Sonic The Hedgehog 2 physics accurately +-- +-- Physics reference: Sonic Retro Physics Guide +-- All values are converted from the original 256 subpixels per pixel system +-- Original game runs at 60 FPS +-- +-- CONTROLS: +-- Arrow Keys / WASD / Left Analog Stick: Move +-- SPACE / A Button: Jump +-- DOWN while moving: Roll +-- DOWN + SPACE while stationary: Spin Dash (charge and release) +-- H: Toggle debug mode +-- R: Reload script +-- ESCAPE: Exit + +-- ============================================================================ +-- SONIC 2 PHYSICS CONSTANTS +-- ============================================================================ +-- Original values are in subpixels (256 per pixel) at 60 FPS +-- We convert to pixels/second for WickedEngine + +local PIXELS_PER_SUBPIXEL = 1 / 256 +local FRAMES_PER_SECOND = 60 + +-- Convert Sonic 2 subpixel/frame values to pixels/second +local function toPixelsPerSecond(subpixelsPerFrame) + return subpixelsPerFrame * PIXELS_PER_SUBPIXEL * FRAMES_PER_SECOND +end + +-- Convert Sonic 2 subpixel/frame^2 values to pixels/second^2 +local function toPixelsPerSecondSq(subpixelsPerFrameSq) + return subpixelsPerFrameSq * PIXELS_PER_SUBPIXEL * FRAMES_PER_SECOND * FRAMES_PER_SECOND +end + +-- Sonic 2 Physics Constants (original subpixel values in comments) +local Physics = { + -- Ground Movement + ACCELERATION = toPixelsPerSecondSq(12), -- 0.046875 (12/256) subpixels/frame^2 + DECELERATION = toPixelsPerSecondSq(128), -- 0.5 (128/256) subpixels/frame^2 + FRICTION = toPixelsPerSecondSq(12), -- 0.046875 (12/256) subpixels/frame^2 + TOP_SPEED = toPixelsPerSecond(1536), -- 6 (1536/256) pixels/frame + + -- Rolling + ROLL_FRICTION = toPixelsPerSecondSq(6), -- 0.0234375 (6/256) subpixels/frame^2 + ROLL_DECELERATION = toPixelsPerSecondSq(32), -- 0.125 (32/256) subpixels/frame^2 + + -- Air Movement + AIR_ACCELERATION = toPixelsPerSecondSq(24), -- 0.09375 (24/256) subpixels/frame^2 + + -- Jumping + JUMP_FORCE = toPixelsPerSecond(1664), -- 6.5 (1664/256) pixels/frame + JUMP_RELEASE_SPEED = toPixelsPerSecond(1024), -- 4 (1024/256) pixels/frame + + -- Gravity + GRAVITY = toPixelsPerSecondSq(56), -- 0.21875 (56/256) subpixels/frame^2 + + -- Slopes + SLOPE_FACTOR = toPixelsPerSecondSq(32), -- 0.125 (32/256) subpixels/frame^2 + SLOPE_FACTOR_ROLLUP = toPixelsPerSecondSq(20), -- 0.078125 (20/256) subpixels/frame^2 + SLOPE_FACTOR_ROLLDOWN = toPixelsPerSecondSq(80), -- 0.3125 (80/256) subpixels/frame^2 + + -- Spin Dash + SPINDASH_BASE = toPixelsPerSecond(2048), -- 8 (2048/256) pixels/frame + SPINDASH_CHARGE = toPixelsPerSecond(512), -- 2 (512/256) pixels/frame per charge + SPINDASH_MAX_CHARGES = 8, + SPINDASH_DECAY = 0.96875, -- Charge decay per frame (floor(charge * 8) / 256) + + -- Speed Caps + SPEED_CAP = toPixelsPerSecond(4096), -- 16 (4096/256) pixels/frame + ROLL_SPEED_THRESHOLD = toPixelsPerSecond(256), -- 1 (256/256) pixel/frame - minimum speed to maintain roll + + -- Animation thresholds + WALK_ANIM_THRESHOLD = toPixelsPerSecond(1024), -- 4 pixels/frame + RUN_ANIM_THRESHOLD = toPixelsPerSecond(1536), -- 6 pixels/frame +} + +-- ============================================================================ +-- GAME STATE +-- ============================================================================ + +local GameState = { + TITLE = "title", + PLAYING = "playing", + PAUSED = "paused", +} + +-- ============================================================================ +-- SONIC STATES +-- ============================================================================ + +local SonicState = { + IDLE = "idle", + WALKING = "walking", + RUNNING = "running", + JUMPING = "jumping", + ROLLING = "rolling", + SPINDASH = "spindash", + SKIDDING = "skidding", + PUSHING = "pushing", + LOOKING_UP = "looking_up", + CROUCHING = "crouching", + BALANCING = "balancing", + HURT = "hurt", + DYING = "dying", + SPRING = "spring", +} + +-- ============================================================================ +-- ANIMATION FRAMES (for sprite sheet animation) +-- ============================================================================ + +local Animations = { + idle = { frames = {1}, speed = 0, loop = false }, + walking = { frames = {2, 3, 4, 5, 6, 7}, speed = 0.1, loop = true }, + running = { frames = {8, 9, 10, 11}, speed = 0.05, loop = true }, + rolling = { frames = {12, 13, 14, 15, 16}, speed = 0.05, loop = true }, + spindash = { frames = {12, 13, 14, 15, 16}, speed = 0.03, loop = true }, + jumping = { frames = {12, 13, 14, 15, 16}, speed = 0.05, loop = true }, + skidding = { frames = {17}, speed = 0, loop = false }, + pushing = { frames = {18, 19, 20, 21}, speed = 0.15, loop = true }, + looking_up = { frames = {22}, speed = 0, loop = false }, + crouching = { frames = {23}, speed = 0, loop = false }, + balancing = { frames = {24, 25}, speed = 0.2, loop = true }, + hurt = { frames = {26}, speed = 0, loop = false }, + dying = { frames = {27}, speed = 0, loop = false }, + spring = { frames = {28}, speed = 0, loop = false }, +} + +-- ============================================================================ +-- HELPER FUNCTIONS +-- ============================================================================ + +local function sign(x) + if x > 0 then return 1 + elseif x < 0 then return -1 + else return 0 end +end + +local function clamp(value, min, max) + if value < min then return min end + if value > max then return max end + return value +end + +local function approach(current, target, delta) + if current < target then + return math.min(current + delta, target) + elseif current > target then + return math.max(current - delta, target) + end + return target +end + +-- ============================================================================ +-- SONIC CHARACTER CLASS +-- ============================================================================ + +local function Sonic() + local self = { + -- Position (in pixels, Y increases downward like classic Sonic) + x = 0, + y = 0, + + -- Velocity + xSpeed = 0, -- Horizontal speed + ySpeed = 0, -- Vertical speed + groundSpeed = 0, -- Speed along the ground (considering slopes) + + -- Ground angle (in radians, 0 = flat ground) + groundAngle = 0, + + -- State + state = SonicState.IDLE, + prevState = SonicState.IDLE, + facingRight = true, + isGrounded = true, + isRolling = false, + isJumping = false, + + -- Spin Dash + spindashCharge = 0, + spindashCharges = 0, + + -- Animation + currentAnim = "idle", + animFrame = 1, + animTimer = 0, + + -- Collision + width = 19, -- Hitbox width (push sensors) + height = 39, -- Hitbox height standing + heightRolling = 29, -- Hitbox height rolling + + -- Visual + sprite = nil, + spriteParams = nil, + + -- Input state + inputLeft = false, + inputRight = false, + inputUp = false, + inputDown = false, + inputJump = false, + inputJumpPressed = false, + inputJumpReleased = false, + + -- Control lock (for slope sliding) + controlLockTimer = 0, + + -- Rings and score + rings = 0, + score = 0, + lives = 3, + + -- Invincibility frames + invincibilityTimer = 0, + + -- Debug + debugMode = false, + } + + -- ======================================================================== + -- INITIALIZATION + -- ======================================================================== + + function self:Init(startX, startY) + self.x = startX or 100 + self.y = startY or 200 + self.xSpeed = 0 + self.ySpeed = 0 + self.groundSpeed = 0 + self.groundAngle = 0 + self.state = SonicState.IDLE + self.isGrounded = true + self.isRolling = false + self.isJumping = false + self.facingRight = true + + -- Create sprite for visual representation + -- In a full implementation, this would load a sprite sheet + self.sprite = Sprite() + self.spriteParams = ImageParams() + self.spriteParams.SetSize(Vector(64, 64)) + self.spriteParams.SetPivot(Vector(0.5, 0.5)) + self.sprite.SetParams(self.spriteParams) + end + + -- ======================================================================== + -- INPUT HANDLING + -- ======================================================================== + + function self:UpdateInput() + local prevJump = self.inputJump + + -- Keyboard input + self.inputLeft = input.Down(KEYBOARD_BUTTON_LEFT) or input.Down(string.byte('A')) + self.inputRight = input.Down(KEYBOARD_BUTTON_RIGHT) or input.Down(string.byte('D')) + self.inputUp = input.Down(KEYBOARD_BUTTON_UP) or input.Down(string.byte('W')) + self.inputDown = input.Down(KEYBOARD_BUTTON_DOWN) or input.Down(string.byte('S')) + self.inputJump = input.Down(KEYBOARD_BUTTON_SPACE) or input.Down(GAMEPAD_BUTTON_2) + + -- Gamepad input (add to keyboard) + local analog = input.GetAnalog(GAMEPAD_ANALOG_THUMBSTICK_L) + if analog.GetX() < -0.3 then self.inputLeft = true end + if analog.GetX() > 0.3 then self.inputRight = true end + if analog.GetY() > 0.3 then self.inputUp = true end + if analog.GetY() < -0.3 then self.inputDown = true end + + -- Detect press and release + self.inputJumpPressed = self.inputJump and not prevJump + self.inputJumpReleased = not self.inputJump and prevJump + end + + -- ======================================================================== + -- GROUND MOVEMENT (Sonic 2 accurate) + -- ======================================================================== + + function self:GroundMovement(dt) + -- Skip if control is locked (e.g., after sliding off a slope) + if self.controlLockTimer > 0 then + self.controlLockTimer = self.controlLockTimer - dt + -- Still apply friction when locked + self.groundSpeed = approach(self.groundSpeed, 0, Physics.FRICTION * dt) + else + -- Acceleration + if self.inputLeft and not self.inputRight then + if self.groundSpeed > 0 then + -- Skidding (turning around) + self.groundSpeed = self.groundSpeed - Physics.DECELERATION * dt + if self.groundSpeed <= 0 then + self.groundSpeed = -Physics.DECELERATION * dt + end + if not self.isRolling and self.groundSpeed > Physics.TOP_SPEED / 2 then + self.state = SonicState.SKIDDING + end + elseif self.groundSpeed > -Physics.TOP_SPEED then + -- Normal acceleration left + self.groundSpeed = self.groundSpeed - Physics.ACCELERATION * dt + if self.groundSpeed < -Physics.TOP_SPEED then + self.groundSpeed = -Physics.TOP_SPEED + end + end + self.facingRight = false + elseif self.inputRight and not self.inputLeft then + if self.groundSpeed < 0 then + -- Skidding (turning around) + self.groundSpeed = self.groundSpeed + Physics.DECELERATION * dt + if self.groundSpeed >= 0 then + self.groundSpeed = Physics.DECELERATION * dt + end + if not self.isRolling and self.groundSpeed < -Physics.TOP_SPEED / 2 then + self.state = SonicState.SKIDDING + end + elseif self.groundSpeed < Physics.TOP_SPEED then + -- Normal acceleration right + self.groundSpeed = self.groundSpeed + Physics.ACCELERATION * dt + if self.groundSpeed > Physics.TOP_SPEED then + self.groundSpeed = Physics.TOP_SPEED + end + end + self.facingRight = true + else + -- Friction (no input) + self.groundSpeed = approach(self.groundSpeed, 0, Physics.FRICTION * dt) + end + end + + -- Rolling physics (different friction/deceleration) + if self.isRolling then + local friction = Physics.ROLL_FRICTION + if (self.inputLeft and self.groundSpeed > 0) or (self.inputRight and self.groundSpeed < 0) then + -- Actively braking while rolling + friction = Physics.ROLL_DECELERATION + end + self.groundSpeed = approach(self.groundSpeed, 0, friction * dt) + + -- Uncurl if too slow + if math.abs(self.groundSpeed) < Physics.ROLL_SPEED_THRESHOLD then + self.isRolling = false + self.state = SonicState.IDLE + end + end + + -- Slope factor (gravity effect on slopes) + if self.groundAngle ~= 0 then + local slopeFactor = Physics.SLOPE_FACTOR + if self.isRolling then + if sign(self.groundSpeed) == sign(math.sin(self.groundAngle)) then + slopeFactor = Physics.SLOPE_FACTOR_ROLLUP -- Going uphill + else + slopeFactor = Physics.SLOPE_FACTOR_ROLLDOWN -- Going downhill + end + end + self.groundSpeed = self.groundSpeed - slopeFactor * math.sin(self.groundAngle) * dt + end + + -- Convert ground speed to X/Y velocity + self.xSpeed = self.groundSpeed * math.cos(self.groundAngle) + self.ySpeed = self.groundSpeed * -math.sin(self.groundAngle) + end + + -- ======================================================================== + -- AIR MOVEMENT (Sonic 2 accurate) + -- ======================================================================== + + function self:AirMovement(dt) + -- Horizontal air control + if self.inputLeft and not self.inputRight then + if self.xSpeed > -Physics.TOP_SPEED then + self.xSpeed = self.xSpeed - Physics.AIR_ACCELERATION * dt + if self.xSpeed < -Physics.TOP_SPEED then + self.xSpeed = -Physics.TOP_SPEED + end + end + elseif self.inputRight and not self.inputLeft then + if self.xSpeed < Physics.TOP_SPEED then + self.xSpeed = self.xSpeed + Physics.AIR_ACCELERATION * dt + if self.xSpeed > Physics.TOP_SPEED then + self.xSpeed = Physics.TOP_SPEED + end + end + end + + -- Air drag (when moving upward and fast) + if self.ySpeed < 0 and self.ySpeed > -Physics.JUMP_RELEASE_SPEED then + if math.abs(self.xSpeed) >= Physics.ACCELERATION * 60 / 32 then + -- Original formula: xSpeed -= xSpeed / 32 per frame at 60 FPS + self.xSpeed = self.xSpeed - (self.xSpeed / 32) * (dt * 60) + end + end + + -- Apply gravity + self.ySpeed = self.ySpeed + Physics.GRAVITY * dt + + -- Speed cap + if self.ySpeed > Physics.SPEED_CAP then + self.ySpeed = Physics.SPEED_CAP + end + + -- Variable jump height (release jump button early) + if self.isJumping and self.inputJumpReleased and self.ySpeed < -Physics.JUMP_RELEASE_SPEED then + self.ySpeed = -Physics.JUMP_RELEASE_SPEED + end + end + + -- ======================================================================== + -- JUMPING + -- ======================================================================== + + function self:TryJump() + if self.isGrounded and self.inputJumpPressed then + -- Calculate jump velocity considering ground angle + self.xSpeed = self.xSpeed - Physics.JUMP_FORCE * math.sin(self.groundAngle) + self.ySpeed = -Physics.JUMP_FORCE * math.cos(self.groundAngle) + + self.isGrounded = false + self.isJumping = true + self.state = SonicState.JUMPING + + -- If was rolling, maintain roll in air + if self.isRolling then + self.state = SonicState.JUMPING + end + end + end + + -- ======================================================================== + -- ROLLING + -- ======================================================================== + + function self:TryRoll() + if self.isGrounded and not self.isRolling then + if self.inputDown and math.abs(self.groundSpeed) >= Physics.ROLL_SPEED_THRESHOLD then + self.isRolling = true + self.state = SonicState.ROLLING + end + end + end + + -- ======================================================================== + -- SPIN DASH (Sonic 2 feature) + -- ======================================================================== + + function self:UpdateSpindash(dt) + if self.state == SonicState.SPINDASH then + -- Charge decay + self.spindashCharge = self.spindashCharge * math.pow(Physics.SPINDASH_DECAY, dt * 60) + + -- Add charge on button press + if self.inputJumpPressed then + self.spindashCharges = math.min(self.spindashCharges + 1, Physics.SPINDASH_MAX_CHARGES) + self.spindashCharge = self.spindashCharge + Physics.SPINDASH_CHARGE + end + + -- Release spin dash + if not self.inputDown then + local launchSpeed = Physics.SPINDASH_BASE + self.spindashCharge + self.groundSpeed = self.facingRight and launchSpeed or -launchSpeed + self.isRolling = true + self.state = SonicState.ROLLING + self.spindashCharge = 0 + self.spindashCharges = 0 + end + elseif self.isGrounded and self.inputDown and math.abs(self.groundSpeed) < 0.1 then + -- Initiate spin dash + if self.inputJumpPressed then + self.state = SonicState.SPINDASH + self.spindashCharge = 0 + self.spindashCharges = 0 + end + end + end + + -- ======================================================================== + -- LOOKING UP / CROUCHING + -- ======================================================================== + + function self:UpdateLookUpCrouch() + if self.isGrounded and math.abs(self.groundSpeed) < 0.1 and not self.isRolling then + if self.inputUp and not self.inputDown then + self.state = SonicState.LOOKING_UP + elseif self.inputDown and not self.inputUp then + if self.state ~= SonicState.SPINDASH then + self.state = SonicState.CROUCHING + end + elseif self.state == SonicState.LOOKING_UP or self.state == SonicState.CROUCHING then + self.state = SonicState.IDLE + end + end + end + + -- ======================================================================== + -- STATE MANAGEMENT + -- ======================================================================== + + function self:UpdateState() + self.prevState = self.state + + if not self.isGrounded then + if self.isJumping or self.isRolling then + self.state = SonicState.JUMPING + else + -- Fell off a ledge + self.state = SonicState.WALKING + end + elseif self.state == SonicState.SPINDASH then + -- Handled in UpdateSpindash + elseif self.isRolling then + self.state = SonicState.ROLLING + elseif math.abs(self.groundSpeed) < 0.1 then + if self.state ~= SonicState.LOOKING_UP and self.state ~= SonicState.CROUCHING then + self.state = SonicState.IDLE + end + elseif self.state ~= SonicState.SKIDDING then + if math.abs(self.groundSpeed) >= Physics.RUN_ANIM_THRESHOLD then + self.state = SonicState.RUNNING + else + self.state = SonicState.WALKING + end + else + -- Check if skidding is done + if sign(self.groundSpeed) == (self.facingRight and 1 or -1) or self.groundSpeed == 0 then + self.state = SonicState.WALKING + end + end + end + + -- ======================================================================== + -- ANIMATION + -- ======================================================================== + + function self:UpdateAnimation(dt) + local animName = "idle" + + -- Map state to animation + if self.state == SonicState.IDLE then animName = "idle" + elseif self.state == SonicState.WALKING then animName = "walking" + elseif self.state == SonicState.RUNNING then animName = "running" + elseif self.state == SonicState.JUMPING then animName = "jumping" + elseif self.state == SonicState.ROLLING then animName = "rolling" + elseif self.state == SonicState.SPINDASH then animName = "spindash" + elseif self.state == SonicState.SKIDDING then animName = "skidding" + elseif self.state == SonicState.PUSHING then animName = "pushing" + elseif self.state == SonicState.LOOKING_UP then animName = "looking_up" + elseif self.state == SonicState.CROUCHING then animName = "crouching" + elseif self.state == SonicState.BALANCING then animName = "balancing" + elseif self.state == SonicState.HURT then animName = "hurt" + elseif self.state == SonicState.DYING then animName = "dying" + end + + -- Handle animation change + if animName ~= self.currentAnim then + self.currentAnim = animName + self.animFrame = 1 + self.animTimer = 0 + end + + -- Animate + local anim = Animations[animName] + if anim and anim.loop and anim.speed > 0 then + -- Adjust animation speed based on ground speed for walking/running + local animSpeed = anim.speed + if animName == "walking" or animName == "running" then + local speedFactor = math.abs(self.groundSpeed) / Physics.TOP_SPEED + animSpeed = anim.speed / (0.5 + speedFactor) + end + + self.animTimer = self.animTimer + dt + if self.animTimer >= animSpeed then + self.animTimer = self.animTimer - animSpeed + self.animFrame = self.animFrame + 1 + if self.animFrame > #anim.frames then + self.animFrame = 1 + end + end + end + end + + -- ======================================================================== + -- COLLISION DETECTION + -- ======================================================================== + + function self:CheckCollision(dt) + -- Basic ground collision (simplified - a full implementation would use sensors) + -- In a real implementation, you'd use the scene's Intersects function with rays + + local groundY = 400 -- Temporary ground level for testing + + if not self.isGrounded then + -- Check if landing + if self.ySpeed > 0 and self.y + self.ySpeed * dt >= groundY then + self.y = groundY + self.ySpeed = 0 + self.isGrounded = true + self.isJumping = false + self.groundSpeed = self.xSpeed -- Transfer horizontal speed to ground speed + self.groundAngle = 0 + + if self.isRolling then + self.state = SonicState.ROLLING + else + self.isRolling = false + end + end + else + -- Stay on ground (simplified) + self.y = groundY + end + + -- Left/Right boundaries (for testing) + local minX = 32 + local maxX = 800 - 32 + + if self.x < minX then + self.x = minX + self.groundSpeed = 0 + self.xSpeed = 0 + end + if self.x > maxX then + self.x = maxX + self.groundSpeed = 0 + self.xSpeed = 0 + end + end + + -- ======================================================================== + -- SCENE COLLISION (Using WickedEngine's scene intersection) + -- ======================================================================== + + function self:CheckSceneCollision(scene, dt) + -- Ground detection using multiple downward rays (sensor system) + local sensorSpacing = 9 -- Distance between ground sensors + local floorCheckDistance = 16 -- How far to look for ground + + local leftSensorX = self.x - sensorSpacing + local rightSensorX = self.x + sensorSpacing + local sensorY = self.y + + local foundGround = false + local closestGroundY = self.y + floorCheckDistance + local closestAngle = 0 + + -- Cast rays downward from both sensors + for i, sensorX in ipairs({leftSensorX, self.x, rightSensorX}) do + local ray = Ray( + Vector(sensorX, sensorY - 10, 0), -- Start slightly above current position + Vector(0, 1, 0), -- Cast downward + 0, + floorCheckDistance + 10 + ) + + local entity, position, normal = scene.Intersects(ray, FILTER_NAVIGATION_MESH) + if entity ~= INVALID_ENTITY then + local groundY = position.GetY() + if groundY < closestGroundY then + closestGroundY = groundY + closestAngle = math.atan2(normal.GetX(), normal.GetY()) + foundGround = true + end + end + end + + if foundGround and self.ySpeed >= 0 then + local groundDist = closestGroundY - self.y + if groundDist <= floorCheckDistance and groundDist >= -8 then + self.y = closestGroundY + self.ySpeed = 0 + self.isGrounded = true + self.isJumping = false + self.groundSpeed = self.xSpeed * math.cos(closestAngle) + self.ySpeed * math.sin(closestAngle) + self.groundAngle = closestAngle + end + end + + -- Wall detection (left and right) + local wallCheckDistance = self.width / 2 + 1 + local heightCheck = self.isRolling and self.heightRolling or self.height + local wallCheckY = self.y - heightCheck / 2 + + -- Left wall + local leftRay = Ray( + Vector(self.x, wallCheckY, 0), + Vector(-1, 0, 0), + 0, + wallCheckDistance + ) + local leftEntity, leftPos = scene.Intersects(leftRay, FILTER_NAVIGATION_MESH) + if leftEntity ~= INVALID_ENTITY then + if self.xSpeed < 0 then + self.x = leftPos.GetX() + self.width / 2 + self.xSpeed = 0 + if self.isGrounded then self.groundSpeed = 0 end + end + end + + -- Right wall + local rightRay = Ray( + Vector(self.x, wallCheckY, 0), + Vector(1, 0, 0), + 0, + wallCheckDistance + ) + local rightEntity, rightPos = scene.Intersects(rightRay, FILTER_NAVIGATION_MESH) + if rightEntity ~= INVALID_ENTITY then + if self.xSpeed > 0 then + self.x = rightPos.GetX() - self.width / 2 + self.xSpeed = 0 + if self.isGrounded then self.groundSpeed = 0 end + end + end + + -- Ceiling detection + local ceilingRay = Ray( + Vector(self.x, self.y - heightCheck, 0), + Vector(0, -1, 0), + 0, + math.abs(self.ySpeed * dt) + 1 + ) + local ceilEntity, ceilPos = scene.Intersects(ceilingRay, FILTER_NAVIGATION_MESH) + if ceilEntity ~= INVALID_ENTITY and self.ySpeed < 0 then + self.y = ceilPos.GetY() + heightCheck + self.ySpeed = 0 + end + end + + -- ======================================================================== + -- MAIN UPDATE + -- ======================================================================== + + function self:Update(dt) + self:UpdateInput() + + -- Physics update + if self.isGrounded then + self:TryJump() + self:UpdateSpindash(dt) + self:TryRoll() + self:UpdateLookUpCrouch() + + if self.state ~= SonicState.SPINDASH then + self:GroundMovement(dt) + end + else + self:AirMovement(dt) + end + + -- Apply velocity to position + self.x = self.x + self.xSpeed * dt + self.y = self.y + self.ySpeed * dt + + -- Collision detection + self:CheckCollision(dt) + + -- Update state based on current conditions + self:UpdateState() + + -- Animation + self:UpdateAnimation(dt) + + -- Update invincibility timer + if self.invincibilityTimer > 0 then + self.invincibilityTimer = self.invincibilityTimer - dt + end + end + + -- ======================================================================== + -- RENDERING + -- ======================================================================== + + function self:Render(path) + -- Update sprite position and orientation + local canvas = application.GetCanvas() + local screenX = self.x + local screenY = canvas.GetLogicalHeight() - self.y -- Convert to screen coordinates (Y up) + + self.spriteParams.SetPos(Vector(screenX, screenY)) + + -- Flip sprite based on facing direction + if self.facingRight then + self.spriteParams.DisableMirror() + else + self.spriteParams.EnableMirror() + end + + -- Rotation for slopes (when grounded) + if self.isGrounded then + self.spriteParams.SetRotation(-self.groundAngle) + else + self.spriteParams.SetRotation(0) + end + + -- Blinking when invincible + if self.invincibilityTimer > 0 then + local blink = math.floor(self.invincibilityTimer * 10) % 2 + self.spriteParams.SetOpacity(blink == 0 and 1 or 0.3) + else + self.spriteParams.SetOpacity(1) + end + + self.sprite.SetParams(self.spriteParams) + end + + -- ======================================================================== + -- DEBUG RENDERING + -- ======================================================================== + + function self:RenderDebug() + local canvas = application.GetCanvas() + local debugY = 10 + local lineHeight = 15 + + local function debugLine(text) + local font = SpriteFont(text) + font.SetPos(Vector(10, debugY)) + font.SetSize(12) + font.SetColor(Vector(1, 1, 0, 1)) + debugY = debugY + lineHeight + return font + end + + local debugInfo = string.format( + "Sonic Debug Info:\n" .. + "Position: (%.1f, %.1f)\n" .. + "Ground Speed: %.2f px/s\n" .. + "X Speed: %.2f px/s\n" .. + "Y Speed: %.2f px/s\n" .. + "Ground Angle: %.2f deg\n" .. + "State: %s\n" .. + "Grounded: %s\n" .. + "Rolling: %s\n" .. + "Facing: %s\n" .. + "Rings: %d\n", + self.x, self.y, + self.groundSpeed, + self.xSpeed, + self.ySpeed, + math.deg(self.groundAngle), + self.state, + tostring(self.isGrounded), + tostring(self.isRolling), + self.facingRight and "Right" or "Left", + self.rings + ) + + DrawDebugText(debugInfo, Vector(10, 10, 0), Vector(1, 1, 0, 1), 0.5) + + -- Draw collision sensors + local sensorY = canvas.GetLogicalHeight() - self.y + DrawPoint(Vector(self.x, sensorY, 0), 5, Vector(0, 1, 0, 1)) + DrawPoint(Vector(self.x - 9, sensorY, 0), 3, Vector(0, 0, 1, 1)) + DrawPoint(Vector(self.x + 9, sensorY, 0), 3, Vector(1, 0, 0, 1)) + end + + return self +end + +-- ============================================================================ +-- HUD +-- ============================================================================ + +local function HUD() + local self = { + scoreFont = nil, + timeFont = nil, + ringsFont = nil, + livesFont = nil, + time = 0, + } + + function self:Init() + self.scoreFont = SpriteFont("SCORE: 0") + self.scoreFont.SetSize(20) + self.scoreFont.SetColor(Vector(1, 1, 0, 1)) + + self.timeFont = SpriteFont("TIME: 0:00") + self.timeFont.SetSize(20) + self.timeFont.SetColor(Vector(1, 1, 1, 1)) + + self.ringsFont = SpriteFont("RINGS: 0") + self.ringsFont.SetSize(20) + self.ringsFont.SetColor(Vector(1, 1, 0, 1)) + + self.livesFont = SpriteFont("LIVES: 3") + self.livesFont.SetSize(20) + self.livesFont.SetColor(Vector(1, 1, 1, 1)) + end + + function self:Update(dt, sonic) + self.time = self.time + dt + + local minutes = math.floor(self.time / 60) + local seconds = math.floor(self.time % 60) + + self.scoreFont.SetText(string.format("SCORE: %d", sonic.score)) + self.timeFont.SetText(string.format("TIME: %d:%02d", minutes, seconds)) + self.ringsFont.SetText(string.format("RINGS: %d", sonic.rings)) + self.livesFont.SetText(string.format("LIVES: %d", sonic.lives)) + + self.scoreFont.SetPos(Vector(16, 16)) + self.timeFont.SetPos(Vector(16, 40)) + self.ringsFont.SetPos(Vector(16, 64)) + self.livesFont.SetPos(Vector(16, 88)) + end + + function self:AddToPath(path) + path.AddFont(self.scoreFont) + path.AddFont(self.timeFont) + path.AddFont(self.ringsFont) + path.AddFont(self.livesFont) + end + + return self +end + +-- ============================================================================ +-- MAIN GAME LOOP +-- ============================================================================ + +runProcess(function() + -- Store previous path to restore on exit + local prevPath = application.GetActivePath() + + -- Create render path (2D for classic Sonic style) + local path = RenderPath2D() + + -- Apply render path + application.SetActivePath(path, 0.5) + + -- Wait for transition + while not application.IsFaded() do + update() + end + waitSeconds(0.5) + + -- Initialize game objects + local sonic = Sonic() + sonic:Init(100, 200) + + local hud = HUD() + hud:Init() + hud:AddToPath(path) + + -- Add Sonic sprite to render path + path.AddSprite(sonic.sprite) + + -- Create simple ground visual (temporary - for testing) + local groundSprite = Sprite() + local groundParams = ImageParams() + groundParams.SetColor(Vector(0.2, 0.6, 0.2, 1)) + groundParams.SetSize(Vector(800, 100)) + groundParams.SetPos(Vector(0, 400)) + groundSprite.SetParams(groundParams) + path.AddSprite(groundSprite) + + -- Help text + local helpText = [[ +Sonic The Hedgehog - WickedEngine Demo +======================================== +Controls: + Arrow Keys / WASD: Move + SPACE: Jump + DOWN while moving: Roll + DOWN + SPACE (stationary): Spin Dash + H: Toggle debug mode + R: Reload script + ESCAPE: Exit + +Physics: Sonic The Hedgehog 2 accurate +]] + + local helpFont = SpriteFont(helpText) + helpFont.SetSize(14) + helpFont.SetColor(Vector(1, 1, 1, 0.8)) + helpFont.SetPos(Vector(10, 450)) + path.AddFont(helpFont) + + -- Title + local titleFont = SpriteFont("SONIC THE HEDGEHOG") + titleFont.SetSize(32) + titleFont.SetColor(Vector(0, 0.5, 1, 1)) + titleFont.SetPos(Vector(200, 20)) + path.AddFont(titleFont) + + -- Debug mode flag + local debugMode = false + + backlog_post("Sonic The Hedgehog script loaded!") + backlog_post("Press H to toggle debug mode, R to reload, ESC to exit") + + -- Main game loop + while true do + local dt = getDeltaTime() + + -- Update game + sonic:Update(dt) + hud:Update(dt, sonic) + + -- Render + sonic:Render(path) + + -- Debug rendering + if debugMode then + sonic:RenderDebug() + end + + update() + + -- Input handling for debug and exit + if not backlog_isactive() then + -- Toggle debug mode + if input.Press(string.byte('H')) then + debugMode = not debugMode + sonic.debugMode = debugMode + end + + -- Reload script + if input.Press(string.byte('R')) then + backlog_post("Reloading Sonic script...") + application.SetActivePath(prevPath, 0.5) + while not application.IsFaded() do + update() + end + killProcesses() + dofile(script_file()) + return + end + + -- Exit + if input.Press(KEYBOARD_BUTTON_ESCAPE) then + backlog_post("Exiting Sonic script...") + application.SetActivePath(prevPath, 0.5) + killProcesses() + return + end + end + end +end) From 1aeb3890734e0638775d9c5078b5cdd0adfbc179 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:19:47 +0000 Subject: [PATCH 3/6] Address code review feedback: extract magic numbers to constants Co-authored-by: ExtCan <60326708+ExtCan@users.noreply.github.com> --- .../sonic_the_hedgehog/sonic_the_hedgehog.lua | 58 ++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua index e7f8bd330f..fcf1ec0a87 100644 --- a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua +++ b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua @@ -75,6 +75,38 @@ local Physics = { RUN_ANIM_THRESHOLD = toPixelsPerSecond(1536), -- 6 pixels/frame } +-- ============================================================================ +-- INPUT KEY CONSTANTS +-- ============================================================================ + +local Keys = { + A = string.byte('A'), + D = string.byte('D'), + W = string.byte('W'), + S = string.byte('S'), + H = string.byte('H'), + R = string.byte('R'), +} + +-- ============================================================================ +-- LEVEL/DISPLAY CONSTANTS +-- ============================================================================ + +local LevelConfig = { + DEFAULT_GROUND_Y = 400, -- Default ground level for testing + DEFAULT_SCREEN_WIDTH = 800, -- Default screen width + DEFAULT_SCREEN_HEIGHT = 600, -- Default screen height + BOUNDARY_MARGIN = 32, -- Distance from screen edge for boundaries +} + +local DebugConfig = { + TEXT_POS_X = 10, -- Debug text X position + TEXT_POS_Y = 10, -- Debug text Y position + TEXT_SCALE = 0.5, -- Debug text scale + SENSOR_POINT_SIZE = 5, -- Size of center sensor debug point + SENSOR_SIDE_SIZE = 3, -- Size of side sensor debug points +} + -- ============================================================================ -- GAME STATE -- ============================================================================ @@ -254,10 +286,10 @@ local function Sonic() local prevJump = self.inputJump -- Keyboard input - self.inputLeft = input.Down(KEYBOARD_BUTTON_LEFT) or input.Down(string.byte('A')) - self.inputRight = input.Down(KEYBOARD_BUTTON_RIGHT) or input.Down(string.byte('D')) - self.inputUp = input.Down(KEYBOARD_BUTTON_UP) or input.Down(string.byte('W')) - self.inputDown = input.Down(KEYBOARD_BUTTON_DOWN) or input.Down(string.byte('S')) + self.inputLeft = input.Down(KEYBOARD_BUTTON_LEFT) or input.Down(Keys.A) + self.inputRight = input.Down(KEYBOARD_BUTTON_RIGHT) or input.Down(Keys.D) + self.inputUp = input.Down(KEYBOARD_BUTTON_UP) or input.Down(Keys.W) + self.inputDown = input.Down(KEYBOARD_BUTTON_DOWN) or input.Down(Keys.S) self.inputJump = input.Down(KEYBOARD_BUTTON_SPACE) or input.Down(GAMEPAD_BUTTON_2) -- Gamepad input (add to keyboard) @@ -585,7 +617,7 @@ local function Sonic() -- Basic ground collision (simplified - a full implementation would use sensors) -- In a real implementation, you'd use the scene's Intersects function with rays - local groundY = 400 -- Temporary ground level for testing + local groundY = LevelConfig.DEFAULT_GROUND_Y if not self.isGrounded then -- Check if landing @@ -609,8 +641,8 @@ local function Sonic() end -- Left/Right boundaries (for testing) - local minX = 32 - local maxX = 800 - 32 + local minX = LevelConfig.BOUNDARY_MARGIN + local maxX = LevelConfig.DEFAULT_SCREEN_WIDTH - LevelConfig.BOUNDARY_MARGIN if self.x < minX then self.x = minX @@ -843,13 +875,13 @@ local function Sonic() self.rings ) - DrawDebugText(debugInfo, Vector(10, 10, 0), Vector(1, 1, 0, 1), 0.5) + DrawDebugText(debugInfo, Vector(DebugConfig.TEXT_POS_X, DebugConfig.TEXT_POS_Y, 0), Vector(1, 1, 0, 1), DebugConfig.TEXT_SCALE) -- Draw collision sensors local sensorY = canvas.GetLogicalHeight() - self.y - DrawPoint(Vector(self.x, sensorY, 0), 5, Vector(0, 1, 0, 1)) - DrawPoint(Vector(self.x - 9, sensorY, 0), 3, Vector(0, 0, 1, 1)) - DrawPoint(Vector(self.x + 9, sensorY, 0), 3, Vector(1, 0, 0, 1)) + DrawPoint(Vector(self.x, sensorY, 0), DebugConfig.SENSOR_POINT_SIZE, Vector(0, 1, 0, 1)) + DrawPoint(Vector(self.x - 9, sensorY, 0), DebugConfig.SENSOR_SIDE_SIZE, Vector(0, 0, 1, 1)) + DrawPoint(Vector(self.x + 9, sensorY, 0), DebugConfig.SENSOR_SIDE_SIZE, Vector(1, 0, 0, 1)) end return self @@ -1009,13 +1041,13 @@ Physics: Sonic The Hedgehog 2 accurate -- Input handling for debug and exit if not backlog_isactive() then -- Toggle debug mode - if input.Press(string.byte('H')) then + if input.Press(Keys.H) then debugMode = not debugMode sonic.debugMode = debugMode end -- Reload script - if input.Press(string.byte('R')) then + if input.Press(Keys.R) then backlog_post("Reloading Sonic script...") application.SetActivePath(prevPath, 0.5) while not application.IsFaded() do From 4add42f54e67439962588046bd78cfc55ed7099a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:35:31 +0000 Subject: [PATCH 4/6] Change jump button from Space to Shift Co-authored-by: ExtCan <60326708+ExtCan@users.noreply.github.com> --- Content/scripts/sonic_the_hedgehog/README.md | 4 ++-- .../scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Content/scripts/sonic_the_hedgehog/README.md b/Content/scripts/sonic_the_hedgehog/README.md index 56de967867..3c1e91583c 100644 --- a/Content/scripts/sonic_the_hedgehog/README.md +++ b/Content/scripts/sonic_the_hedgehog/README.md @@ -76,9 +76,9 @@ The script uses a sensor-based collision system similar to the original: | Move Left/Right | Arrow Keys / A,D | Left Stick | | Look Up | Up Arrow / W | Left Stick Up | | Crouch | Down Arrow / S | Left Stick Down | -| Jump | Space | A Button | +| Jump | Shift | A Button | | Roll | Down while moving | Down while moving | -| Spin Dash | Down + Space (hold & release) | Down + A (hold & release) | +| Spin Dash | Down + Shift (hold & release) | Down + A (hold & release) | | Toggle Debug | H | - | | Reload Script | R | - | | Exit | Escape | - | diff --git a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua index fcf1ec0a87..59c7aebbca 100644 --- a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua +++ b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua @@ -7,9 +7,9 @@ -- -- CONTROLS: -- Arrow Keys / WASD / Left Analog Stick: Move --- SPACE / A Button: Jump +-- SHIFT / A Button: Jump -- DOWN while moving: Roll --- DOWN + SPACE while stationary: Spin Dash (charge and release) +-- DOWN + SHIFT while stationary: Spin Dash (charge and release) -- H: Toggle debug mode -- R: Reload script -- ESCAPE: Exit @@ -290,7 +290,7 @@ local function Sonic() self.inputRight = input.Down(KEYBOARD_BUTTON_RIGHT) or input.Down(Keys.D) self.inputUp = input.Down(KEYBOARD_BUTTON_UP) or input.Down(Keys.W) self.inputDown = input.Down(KEYBOARD_BUTTON_DOWN) or input.Down(Keys.S) - self.inputJump = input.Down(KEYBOARD_BUTTON_SPACE) or input.Down(GAMEPAD_BUTTON_2) + self.inputJump = input.Down(KEYBOARD_BUTTON_LSHIFT) or input.Down(KEYBOARD_BUTTON_RSHIFT) or input.Down(GAMEPAD_BUTTON_2) -- Gamepad input (add to keyboard) local analog = input.GetAnalog(GAMEPAD_ANALOG_THUMBSTICK_L) @@ -991,9 +991,9 @@ Sonic The Hedgehog - WickedEngine Demo ======================================== Controls: Arrow Keys / WASD: Move - SPACE: Jump + SHIFT: Jump DOWN while moving: Roll - DOWN + SPACE (stationary): Spin Dash + DOWN + SHIFT (stationary): Spin Dash H: Toggle debug mode R: Reload script ESCAPE: Exit From b55d4ba51e01110aa40d181495b6f8b4c4bc8e00 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 16:06:01 +0000 Subject: [PATCH 5/6] Add Sonic 2 sprite sheet integration with actual sprites Co-authored-by: ExtCan <60326708+ExtCan@users.noreply.github.com> --- Content/scripts/sonic_the_hedgehog/README.md | 13 ++ .../assets/sonic_sprites.png | Bin 0 -> 148121 bytes .../sonic_the_hedgehog/sonic_the_hedgehog.lua | 200 +++++++++++++++--- 3 files changed, 179 insertions(+), 34 deletions(-) create mode 100644 Content/scripts/sonic_the_hedgehog/assets/sonic_sprites.png diff --git a/Content/scripts/sonic_the_hedgehog/README.md b/Content/scripts/sonic_the_hedgehog/README.md index 3c1e91583c..72c84bbe34 100644 --- a/Content/scripts/sonic_the_hedgehog/README.md +++ b/Content/scripts/sonic_the_hedgehog/README.md @@ -61,6 +61,19 @@ The script implements all classic Sonic states: - Hurt - Dying +### Sprite Sheet + +The script uses the authentic Sonic 2 sprite sheet located at `assets/sonic_sprites.png` (10073.png from The Spriters Resource). The sprite sheet includes: +- Idle and standing poses +- Walking animation (8 frames) +- Running animation (4 frames with motion blur legs) +- Rolling/Spin ball animation (5 frames) +- Skidding/braking pose +- Pushing animation (4 frames) +- Looking up and crouching poses +- Edge balancing animation (2 frames) +- Hurt and dying poses + ### Collision System The script uses a sensor-based collision system similar to the original: diff --git a/Content/scripts/sonic_the_hedgehog/assets/sonic_sprites.png b/Content/scripts/sonic_the_hedgehog/assets/sonic_sprites.png new file mode 100644 index 0000000000000000000000000000000000000000..60ce21b1e5a8644ca64cd6940aeacc4c9e12181a GIT binary patch literal 148121 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

e|M>&a9uC5G^hcL_0LsoR(i5QX% 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 Xy>6@_J!CxjDo7P2jThw#Z~XrQ8O`ze literal 0 HcmV?d00001 diff --git a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua index 59c7aebbca..e9f4bad093 100644 --- a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua +++ b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua @@ -139,24 +139,128 @@ local SonicState = { } -- ============================================================================ --- ANIMATION FRAMES (for sprite sheet animation) +-- SPRITE SHEET CONFIGURATION -- ============================================================================ +-- Sprite sheet: 10073.png from Sonic 2 (1204x1509 pixels) +-- Each frame is defined as {x, y, width, height} in normalized UV coordinates (0-1) +local SPRITE_SHEET_WIDTH = 1204 +local SPRITE_SHEET_HEIGHT = 1509 +local SPRITE_SHEET_PATH = "assets/sonic_sprites.png" + +-- Convert pixel coordinates to normalized UV coordinates +local function toUV(x, y, w, h) + return { + x / SPRITE_SHEET_WIDTH, + y / SPRITE_SHEET_HEIGHT, + w / SPRITE_SHEET_WIDTH, + h / SPRITE_SHEET_HEIGHT + } +end + +-- Frame rectangles for each animation (pixel coordinates on sprite sheet) +-- Format: {x, y, width, height} +local SpriteFrames = { + -- Idle/Standing (top left area) + idle = { + {3, 12, 29, 39} -- Standing pose + }, + -- Walking animation (8 frames) + walking = { + {3, 51, 38, 39}, + {42, 51, 29, 40}, + {72, 51, 24, 43}, + {97, 51, 38, 39}, + {136, 51, 29, 40}, + {166, 51, 24, 43}, + {191, 51, 38, 39}, + {230, 51, 29, 40} + }, + -- Running animation (4 frames - blurry legs) + running = { + {3, 94, 32, 37}, + {36, 94, 32, 37}, + {69, 94, 32, 37}, + {102, 94, 32, 37} + }, + -- Rolling/Spin ball (5 frames) + rolling = { + {3, 193, 30, 30}, + {34, 193, 30, 30}, + {65, 193, 30, 30}, + {96, 193, 30, 30}, + {127, 193, 30, 30} + }, + -- Spin dash (same as rolling but charged) + spindash = { + {3, 193, 30, 30}, + {34, 193, 30, 30}, + {65, 193, 30, 30}, + {96, 193, 30, 30}, + {127, 193, 30, 30} + }, + -- Jumping (same as rolling) + jumping = { + {3, 193, 30, 30}, + {34, 193, 30, 30}, + {65, 193, 30, 30}, + {96, 193, 30, 30}, + {127, 193, 30, 30} + }, + -- Skidding/Braking + skidding = { + {3, 131, 35, 39} + }, + -- Pushing animation + pushing = { + {3, 276, 35, 36}, + {39, 276, 38, 36}, + {78, 276, 35, 36}, + {114, 276, 38, 36} + }, + -- Looking up + looking_up = { + {3, 170, 27, 46} + }, + -- Crouching/Ducking + crouching = { + {31, 170, 38, 28} + }, + -- Balancing on edge + balancing = { + {3, 316, 38, 44}, + {42, 316, 38, 46} + }, + -- Hurt/Hit + hurt = { + {3, 364, 43, 34} + }, + -- Dying + dying = { + {3, 364, 43, 34} + }, + -- Spring bounce + spring = { + {3, 12, 29, 39} + } +} + +-- Animation timing configuration local Animations = { - idle = { frames = {1}, speed = 0, loop = false }, - walking = { frames = {2, 3, 4, 5, 6, 7}, speed = 0.1, loop = true }, - running = { frames = {8, 9, 10, 11}, speed = 0.05, loop = true }, - rolling = { frames = {12, 13, 14, 15, 16}, speed = 0.05, loop = true }, - spindash = { frames = {12, 13, 14, 15, 16}, speed = 0.03, loop = true }, - jumping = { frames = {12, 13, 14, 15, 16}, speed = 0.05, loop = true }, - skidding = { frames = {17}, speed = 0, loop = false }, - pushing = { frames = {18, 19, 20, 21}, speed = 0.15, loop = true }, - looking_up = { frames = {22}, speed = 0, loop = false }, - crouching = { frames = {23}, speed = 0, loop = false }, - balancing = { frames = {24, 25}, speed = 0.2, loop = true }, - hurt = { frames = {26}, speed = 0, loop = false }, - dying = { frames = {27}, speed = 0, loop = false }, - spring = { frames = {28}, speed = 0, loop = false }, + idle = { speed = 0, loop = false }, + walking = { speed = 0.08, loop = true }, + running = { speed = 0.04, loop = true }, + rolling = { speed = 0.03, loop = true }, + spindash = { speed = 0.02, loop = true }, + jumping = { speed = 0.03, loop = true }, + skidding = { speed = 0, loop = false }, + pushing = { speed = 0.12, loop = true }, + looking_up = { speed = 0, loop = false }, + crouching = { speed = 0, loop = false }, + balancing = { speed = 0.15, loop = true }, + hurt = { speed = 0, loop = false }, + dying = { speed = 0, loop = false }, + spring = { speed = 0, loop = false }, } -- ============================================================================ @@ -269,12 +373,24 @@ local function Sonic() self.isJumping = false self.facingRight = true - -- Create sprite for visual representation - -- In a full implementation, this would load a sprite sheet - self.sprite = Sprite() + -- Create sprite for visual representation with actual sprite sheet + local spritePath = script_dir() .. SPRITE_SHEET_PATH + self.sprite = Sprite(spritePath) self.spriteParams = ImageParams() - self.spriteParams.SetSize(Vector(64, 64)) - self.spriteParams.SetPivot(Vector(0.5, 0.5)) + self.spriteParams.SetSize(Vector(80, 80)) -- Display size (scaled up from ~40px sprites) + self.spriteParams.SetPivot(Vector(0.5, 1.0)) -- Pivot at bottom center for proper grounding + self.spriteParams.SetBlendMode(BLENDMODE_ALPHA) + self.spriteParams.SetQuality(QUALITY_NEAREST) -- Pixel-perfect scaling for retro look + + -- Set initial animation frame + local frame = SpriteFrames.idle[1] + self.spriteParams.EnableDrawRect(Vector( + frame[1] / SPRITE_SHEET_WIDTH, + frame[2] / SPRITE_SHEET_HEIGHT, + (frame[1] + frame[3]) / SPRITE_SHEET_WIDTH, + (frame[2] + frame[4]) / SPRITE_SHEET_HEIGHT + )) + self.sprite.SetParams(self.spriteParams) end @@ -588,23 +704,39 @@ local function Sonic() self.animTimer = 0 end - -- Animate + -- Get animation config and frames local anim = Animations[animName] - if anim and anim.loop and anim.speed > 0 then - -- Adjust animation speed based on ground speed for walking/running - local animSpeed = anim.speed - if animName == "walking" or animName == "running" then - local speedFactor = math.abs(self.groundSpeed) / Physics.TOP_SPEED - animSpeed = anim.speed / (0.5 + speedFactor) + local frames = SpriteFrames[animName] + + if anim and frames and #frames > 0 then + -- Animate if looping and has speed + if anim.loop and anim.speed > 0 then + -- Adjust animation speed based on ground speed for walking/running + local animSpeed = anim.speed + if animName == "walking" or animName == "running" then + local speedFactor = math.abs(self.groundSpeed) / Physics.TOP_SPEED + animSpeed = anim.speed / (0.5 + speedFactor) + end + + self.animTimer = self.animTimer + dt + if self.animTimer >= animSpeed then + self.animTimer = self.animTimer - animSpeed + self.animFrame = self.animFrame + 1 + if self.animFrame > #frames then + self.animFrame = 1 + end + end end - self.animTimer = self.animTimer + dt - if self.animTimer >= animSpeed then - self.animTimer = self.animTimer - animSpeed - self.animFrame = self.animFrame + 1 - if self.animFrame > #anim.frames then - self.animFrame = 1 - end + -- Update sprite draw rect to show current frame + local frame = frames[self.animFrame] or frames[1] + if frame then + self.spriteParams.EnableDrawRect(Vector( + frame[1] / SPRITE_SHEET_WIDTH, + frame[2] / SPRITE_SHEET_HEIGHT, + (frame[1] + frame[3]) / SPRITE_SHEET_WIDTH, + (frame[2] + frame[4]) / SPRITE_SHEET_HEIGHT + )) end end end From a4592beaa759f97d64aa31fd98aa3d1d15de2de5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 16:19:57 +0000 Subject: [PATCH 6/6] Fix jump input, proper initialization, and add module import support Co-authored-by: ExtCan <60326708+ExtCan@users.noreply.github.com> --- Content/scripts/sonic_the_hedgehog/README.md | 69 ++++++++++++---- .../sonic_the_hedgehog/sonic_the_hedgehog.lua | 81 +++++++++++++++++-- 2 files changed, 131 insertions(+), 19 deletions(-) diff --git a/Content/scripts/sonic_the_hedgehog/README.md b/Content/scripts/sonic_the_hedgehog/README.md index 72c84bbe34..d10bcad538 100644 --- a/Content/scripts/sonic_the_hedgehog/README.md +++ b/Content/scripts/sonic_the_hedgehog/README.md @@ -98,19 +98,59 @@ The script uses a sensor-based collision system similar to the original: ## Usage -### Loading the Script +### Standalone Demo -1. Place the script in your WickedEngine content folder -2. In the WickedEngine Editor or your application, execute: - ```lua - dofile("Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua") - ``` +Run the script directly to see Sonic in action with a demo level: -### Integration with Your Scene +```lua +dofile("Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua") +``` + +### Importing into Your Own Scene + +The script exports a `SonicModule` that can be used to add Sonic to any existing scene: + +```lua +-- Load the module +local sonic_script = dofile("Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua") + +-- Or access the global module after loading +local SonicModule = _G.SonicModule + +-- Create Sonic for your render path +local sonic, hud = SonicModule.CreateSonicForPath(myRenderPath, startX, startY, true) + +-- In your game loop: +sonic:Update(dt) +sonic:Render(myRenderPath) +hud:Update(dt, sonic) + +-- Customize physics if needed +SonicModule.Physics.JUMP_FORCE = SonicModule.Physics.JUMP_FORCE * 1.5 -- Higher jumps + +-- Set custom ground level +SonicModule.SetGroundLevel(500) + +-- Set custom screen bounds +SonicModule.SetScreenBounds(1920, 1080, 64) +``` + +### Module API Reference + +- `SonicModule.Sonic` - The Sonic character class +- `SonicModule.HUD` - The HUD class +- `SonicModule.Physics` - Physics constants (modifiable) +- `SonicModule.SonicState` - Character state constants +- `SonicModule.LevelConfig` - Level configuration +- `SonicModule.CreateSonicForPath(path, x, y, includeHUD)` - Quick setup helper +- `SonicModule.SetGroundLevel(y)` - Set the ground collision level +- `SonicModule.SetScreenBounds(width, height, margin)` - Set screen boundaries + +### Integration with 3D Scenes The script creates a 2D render path by default. To integrate with a 3D scene: -1. Modify the render path creation to use `RenderPath3D` +1. Use `SonicModule.CreateSonicForPath()` with your existing RenderPath3D 2. Add scene collision detection using `scene.Intersects()` 3. Load your level geometry with navigation mesh tags @@ -121,18 +161,19 @@ The script creates a 2D render path by default. To integrate with a 3D scene: All physics constants are defined in the `Physics` table at the top of the script. You can modify these to create different gameplay feels: ```lua -Physics.TOP_SPEED = toPixelsPerSecond(2048) -- Faster top speed -Physics.JUMP_FORCE = toPixelsPerSecond(2000) -- Higher jumps -Physics.GRAVITY = toPixelsPerSecondSq(40) -- Floatier physics +local Physics = SonicModule.Physics +Physics.TOP_SPEED = Physics.TOP_SPEED * 1.5 -- Faster top speed +Physics.JUMP_FORCE = Physics.JUMP_FORCE * 1.2 -- Higher jumps +Physics.GRAVITY = Physics.GRAVITY * 0.8 -- Floatier physics ``` #### Adding Sprites -Replace the placeholder sprite with your own Sonic sprite sheet: +The script uses the authentic Sonic 2 sprite sheet. Frame definitions are in `SonicModule.SpriteFrames`: ```lua -self.sprite = Sprite("path/to/sonic_spritesheet.png") --- Configure sprite sheet animation using DrawRectAnim +-- Customize animation frames +SonicModule.SpriteFrames.idle = {{x, y, width, height}} ``` ## Technical Notes diff --git a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua index e9f4bad093..127e8596ed 100644 --- a/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua +++ b/Content/scripts/sonic_the_hedgehog/sonic_the_hedgehog.lua @@ -362,7 +362,7 @@ local function Sonic() function self:Init(startX, startY) self.x = startX or 100 - self.y = startY or 200 + self.y = startY or LevelConfig.DEFAULT_GROUND_Y -- Start at ground level self.xSpeed = 0 self.ySpeed = 0 self.groundSpeed = 0 @@ -415,8 +415,8 @@ local function Sonic() if analog.GetY() > 0.3 then self.inputUp = true end if analog.GetY() < -0.3 then self.inputDown = true end - -- Detect press and release - self.inputJumpPressed = self.inputJump and not prevJump + -- Detect press and release using input.Press() for more reliable detection + self.inputJumpPressed = input.Press(KEYBOARD_BUTTON_LSHIFT) or input.Press(KEYBOARD_BUTTON_RSHIFT) or input.Press(GAMEPAD_BUTTON_2) self.inputJumpReleased = not self.inputJump and prevJump end @@ -1078,7 +1078,75 @@ local function HUD() end -- ============================================================================ --- MAIN GAME LOOP +-- EXPORT FOR MODULE USE +-- ============================================================================ +-- This allows the script to be imported into any scene + +local SonicModule = { + -- Export the Sonic character class + Sonic = Sonic, + + -- Export the HUD class + HUD = HUD, + + -- Export physics constants for customization + Physics = Physics, + + -- Export state constants + SonicState = SonicState, + + -- Export level config + LevelConfig = LevelConfig, + + -- Export sprite frames for customization + SpriteFrames = SpriteFrames, + + -- Export animations for customization + Animations = Animations, + + -- Helper to create a complete Sonic setup for any render path + CreateSonicForPath = function(path, startX, startY, includeHUD) + local sonic = Sonic() + sonic:Init(startX or 100, startY or LevelConfig.DEFAULT_GROUND_Y) + path.AddSprite(sonic.sprite) + + local hud = nil + if includeHUD ~= false then -- default true + hud = HUD() + hud:Init() + hud:AddToPath(path) + end + + return sonic, hud + end, + + -- Helper to run Sonic update/render in an existing game loop + UpdateSonic = function(sonic, dt) + sonic:Update(dt) + end, + + RenderSonic = function(sonic, path) + sonic:Render(path) + end, + + -- Set custom ground level + SetGroundLevel = function(y) + LevelConfig.DEFAULT_GROUND_Y = y + end, + + -- Set custom screen bounds + SetScreenBounds = function(width, height, margin) + LevelConfig.DEFAULT_SCREEN_WIDTH = width or 800 + LevelConfig.DEFAULT_SCREEN_HEIGHT = height or 600 + LevelConfig.BOUNDARY_MARGIN = margin or 32 + end +} + +-- Make module available globally for import +_G.SonicModule = SonicModule + +-- ============================================================================ +-- STANDALONE DEMO (runs when script is executed directly) -- ============================================================================ runProcess(function() @@ -1099,7 +1167,7 @@ runProcess(function() -- Initialize game objects local sonic = Sonic() - sonic:Init(100, 200) + sonic:Init(100, LevelConfig.DEFAULT_GROUND_Y) -- Start at ground level local hud = HUD() hud:Init() @@ -1200,3 +1268,6 @@ Physics: Sonic The Hedgehog 2 accurate end end end) + +-- Return the module for use with dofile/require +return SonicModule