Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions Content/scripts/sonic_the_hedgehog/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# 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

### 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:
- 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 | Shift | A Button |
| Roll | Down while moving | Down while moving |
| Spin Dash | Down + Shift (hold & release) | Down + A (hold & release) |
| Toggle Debug | H | - |
| Reload Script | R | - |
| Exit | Escape | - |

## Usage

### Standalone Demo

Run the script directly to see Sonic in action with a demo level:

```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. Use `SonicModule.CreateSonicForPath()` with your existing 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
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

The script uses the authentic Sonic 2 sprite sheet. Frame definitions are in `SonicModule.SpriteFrames`:

```lua
-- Customize animation frames
SonicModule.SpriteFrames.idle = {{x, y, width, height}}
```

## 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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading