@jarrodmedrano/claude-skills 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/bevy/SKILL.md +406 -0
- package/.claude/skills/bevy/references/bevy_specific_tips.md +385 -0
- package/.claude/skills/bevy/references/common_pitfalls.md +217 -0
- package/.claude/skills/bevy/references/ecs_patterns.md +277 -0
- package/.claude/skills/bevy/references/project_structure.md +116 -0
- package/.claude/skills/bevy/references/ui_development.md +147 -0
- package/.claude/skills/domain-driven-design/SKILL.md +459 -0
- package/.claude/skills/domain-driven-design/references/ddd_foundations_and_patterns.md +664 -0
- package/.claude/skills/domain-driven-design/references/rich_hickey_principles.md +406 -0
- package/.claude/skills/domain-driven-design/references/visualization_examples.md +790 -0
- package/.claude/skills/domain-driven-design/references/wlaschin_patterns.md +639 -0
- package/.claude/skills/game-design-theory/SKILL.md +102 -0
- package/.claude/skills/game-design-theory/design-principles.md +308 -0
- package/.claude/skills/game-design-theory/gameplay-elements.md +213 -0
- package/.claude/skills/game-design-theory/player-psychology.md +175 -0
- package/.claude/skills/game-design-theory/playtesting.md +321 -0
- package/.claude/skills/game-design-theory/storytelling.md +219 -0
- package/.claude/skills/game-feel/SKILL.md +305 -0
- package/.claude/skills/game-feel/references/adsr-tuning.md +271 -0
- package/.claude/skills/game-feel/references/classic-profiles.md +279 -0
- package/.claude/skills/game-feel/references/perception-thresholds.md +160 -0
- package/.claude/skills/game-feel/references/polish-effects.md +246 -0
- package/.claude/skills/game-feel/references/simulation-recipes.md +306 -0
- package/.claude/skills/game-feel/references/six-metrics.md +239 -0
- package/.claude/skills/godot/SKILL.md +728 -0
- package/.claude/skills/godot/assets/templates/attribute_template.gd +109 -0
- package/.claude/skills/godot/assets/templates/component_template.gd +76 -0
- package/.claude/skills/godot/assets/templates/interaction_template.gd +108 -0
- package/.claude/skills/godot/assets/templates/item_resource.tres +11 -0
- package/.claude/skills/godot/assets/templates/spell_resource.tres +20 -0
- package/.claude/skills/godot/references/architecture-patterns.md +608 -0
- package/.claude/skills/godot/references/common-pitfalls.md +518 -0
- package/.claude/skills/godot/references/file-formats.md +491 -0
- package/.claude/skills/godot/references/godot4-physics-api.md +302 -0
- package/.claude/skills/godot/scripts/validate_tres.py +145 -0
- package/.claude/skills/godot/scripts/validate_tscn.py +170 -0
- package/.claude/skills/level-design/SKILL.md +249 -0
- package/.claude/skills/level-design/anticipatory-play.md +223 -0
- package/.claude/skills/level-design/hiding-linearity.md +181 -0
- package/.claude/skills/level-design/indie-practices.md +286 -0
- package/.claude/skills/level-design/open-world-planning.md +294 -0
- package/.claude/skills/level-design/play-personas.md +240 -0
- package/.claude/skills/level-design/procedural-handmade.md +271 -0
- package/.claude/skills/level-design/themed-environments.md +264 -0
- package/.claude/skills/react-three-fiber/SKILL.md +2055 -0
- package/.claude/skills/react-three-fiber/scripts/build-scene.ts +171 -0
- package/package.json +3 -1
- package/scripts/install.js +16 -1
- package/templates/github-actions/README.md +36 -0
- /package/.claude/{commands/design-review → agents}/design-review-agent.md +0 -0
- /package/.claude/{commands/code-review → agents}/pragmatic-code-review-subagent.md +0 -0
- /package/{.claude/commands/code-review → templates/github-actions}/claude-code-review-custom.yml +0 -0
- /package/{.claude/commands/code-review → templates/github-actions}/claude-code-review.yml +0 -0
- /package/{.claude/commands/security-review → templates/github-actions}/security.yml +0 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Polish Effects for Game Feel
|
|
2
|
+
|
|
3
|
+
Polish transforms mechanical interactions into visceral experiences. Without polish, even perfect mechanics feel flat and lifeless.
|
|
4
|
+
|
|
5
|
+
## Why Polish Matters
|
|
6
|
+
|
|
7
|
+
> "Because of the limited processing power, each individual effect is drop-dead simple. They harmonize so well, though, that the net effect is a powerful sense of physical properties."
|
|
8
|
+
> — On Asteroids
|
|
9
|
+
|
|
10
|
+
Polish accomplishes three things:
|
|
11
|
+
1. **Sells the interaction** — Makes virtual contact feel real
|
|
12
|
+
2. **Provides feedback** — Confirms player actions
|
|
13
|
+
3. **Creates consistency** — Builds coherent physical world
|
|
14
|
+
|
|
15
|
+
## The Polish Toolkit
|
|
16
|
+
|
|
17
|
+
### Visual Effects
|
|
18
|
+
|
|
19
|
+
| Effect | Use For | Example |
|
|
20
|
+
|--------|---------|---------|
|
|
21
|
+
| **Particles** | Impacts, movement, environment | Dust on landing, sparks on collision |
|
|
22
|
+
| **Screen shake** | Heavy impacts, explosions | Camera shake on ground pound |
|
|
23
|
+
| **Screen flash** | Damage, power-ups, transitions | White flash on hit |
|
|
24
|
+
| **Motion blur** | High speed, impacts | Blur during dash |
|
|
25
|
+
| **Distortion** | Energy, impacts, power | Shockwave ripple |
|
|
26
|
+
| **Squash/stretch** | Weight, anticipation | Character squashes on landing |
|
|
27
|
+
| **Trailing** | Fast movement, special moves | Afterimages during jump |
|
|
28
|
+
|
|
29
|
+
### Audio Effects
|
|
30
|
+
|
|
31
|
+
| Effect | Use For | Example |
|
|
32
|
+
|--------|---------|---------|
|
|
33
|
+
| **Impact sounds** | Collisions, attacks | Thud on landing |
|
|
34
|
+
| **Footsteps** | Movement grounding | Steps sync with animation |
|
|
35
|
+
| **Whooshes** | Fast movement | Swoosh during jump/swing |
|
|
36
|
+
| **UI sounds** | Feedback, confirmation | Click on menu selection |
|
|
37
|
+
| **Ambient** | Environmental presence | Wind, machinery |
|
|
38
|
+
| **Music stingers** | State changes, achievements | Jingle on item pickup |
|
|
39
|
+
|
|
40
|
+
### Haptic Effects
|
|
41
|
+
|
|
42
|
+
| Effect | Use For | Example |
|
|
43
|
+
|--------|---------|---------|
|
|
44
|
+
| **Rumble pulse** | Impacts, damage | Vibration on hit |
|
|
45
|
+
| **Sustained rumble** | Ongoing effects | Engine running |
|
|
46
|
+
| **Pattern rumble** | Footsteps, rhythm | Step-step-step pattern |
|
|
47
|
+
|
|
48
|
+
### Animation Polish
|
|
49
|
+
|
|
50
|
+
| Technique | Purpose | Example |
|
|
51
|
+
|-----------|---------|---------|
|
|
52
|
+
| **Anticipation** | Prepares viewer for action | Wind-up before jump |
|
|
53
|
+
| **Follow-through** | Completes action believably | Hair settling after landing |
|
|
54
|
+
| **Secondary motion** | Adds life and weight | Cape flowing behind |
|
|
55
|
+
| **Exaggeration** | Emphasizes key moments | Fist enlarges during punch |
|
|
56
|
+
| **Ease in/out** | Natural acceleration | Smooth start/stop |
|
|
57
|
+
|
|
58
|
+
## The Three-Tier Impact System
|
|
59
|
+
|
|
60
|
+
Many polished games use three impact levels:
|
|
61
|
+
|
|
62
|
+
### Light Impact
|
|
63
|
+
- Small particle burst
|
|
64
|
+
- High-pitched click sound
|
|
65
|
+
- Subtle/no screen shake
|
|
66
|
+
- Brief rumble pulse
|
|
67
|
+
|
|
68
|
+
### Medium Impact
|
|
69
|
+
- Moderate particle spray
|
|
70
|
+
- Mid-tone thud sound
|
|
71
|
+
- Slight screen shake
|
|
72
|
+
- Medium rumble
|
|
73
|
+
|
|
74
|
+
### Heavy Impact
|
|
75
|
+
- Large particle explosion
|
|
76
|
+
- Deep boom sound
|
|
77
|
+
- Strong screen shake
|
|
78
|
+
- Long rumble
|
|
79
|
+
|
|
80
|
+
**Application**: Map game interactions to appropriate tier:
|
|
81
|
+
- Walking into wall → Light
|
|
82
|
+
- Landing from jump → Medium
|
|
83
|
+
- Ground pound → Heavy
|
|
84
|
+
|
|
85
|
+
## Sound-Motion Harmony
|
|
86
|
+
|
|
87
|
+
### Pitch-Position Correlation
|
|
88
|
+
Mario's jump: Rising tone as he rises, falling tone as he falls.
|
|
89
|
+
Creates subconscious reinforcement of motion.
|
|
90
|
+
|
|
91
|
+
### Size-Pitch Correlation
|
|
92
|
+
- Large objects → Low sounds
|
|
93
|
+
- Small objects → High sounds
|
|
94
|
+
- Asteroids: Large asteroid explosion = deep boom, small = high ping
|
|
95
|
+
|
|
96
|
+
### Speed-Intensity Correlation
|
|
97
|
+
- Fast motion → Louder, more intense
|
|
98
|
+
- Slow motion → Quieter, more subtle
|
|
99
|
+
|
|
100
|
+
### Material-Sound Correlation
|
|
101
|
+
Footstep sounds change based on surface:
|
|
102
|
+
- Stone → Hard click
|
|
103
|
+
- Grass → Soft thud
|
|
104
|
+
- Metal → Metallic clang
|
|
105
|
+
- Water → Splash
|
|
106
|
+
|
|
107
|
+
## Animation Timing
|
|
108
|
+
|
|
109
|
+
### Sync Points
|
|
110
|
+
Critical moments when animation, sound, and effect must align:
|
|
111
|
+
- **Foot contact** — Footstep sound, dust particle
|
|
112
|
+
- **Impact moment** — Hit sound, screen shake, particle burst
|
|
113
|
+
- **Jump apex** — Can trigger state changes, sound shifts
|
|
114
|
+
|
|
115
|
+
### Frame-Perfect Events
|
|
116
|
+
Some events must happen on exact frames:
|
|
117
|
+
- Jump sound on frame 1 of jump
|
|
118
|
+
- Landing effect on exact frame of ground contact
|
|
119
|
+
- Attack hit on specific animation frame
|
|
120
|
+
|
|
121
|
+
## Screen Shake Best Practices
|
|
122
|
+
|
|
123
|
+
### Parameters to Control
|
|
124
|
+
- **Intensity** — How far camera moves
|
|
125
|
+
- **Duration** — How long shake lasts
|
|
126
|
+
- **Frequency** — How fast it oscillates
|
|
127
|
+
- **Decay** — How it diminishes over time
|
|
128
|
+
- **Direction** — Random, directional, or circular
|
|
129
|
+
|
|
130
|
+
### Guidelines
|
|
131
|
+
- Heavy impacts: High intensity, medium duration, fast decay
|
|
132
|
+
- Rumble effects: Low intensity, long duration, no decay
|
|
133
|
+
- Avoid constant shaking — loses impact
|
|
134
|
+
- Direction can indicate impact direction
|
|
135
|
+
|
|
136
|
+
### Common Mistake
|
|
137
|
+
Shake intensity too high → Nauseating, obscures action
|
|
138
|
+
Shake duration too long → Annoying, feels broken
|
|
139
|
+
|
|
140
|
+
## Crossover Sensation
|
|
141
|
+
|
|
142
|
+
When multiple mechanics exist, polish should reinforce their shared physics:
|
|
143
|
+
|
|
144
|
+
**Swimming feels floaty BECAUSE walking feels grounded**
|
|
145
|
+
- Same gravity system, different friction values
|
|
146
|
+
- Polish effects reflect this (bubbles vs dust)
|
|
147
|
+
|
|
148
|
+
**Flying defies THE SAME gravity that affects jumping**
|
|
149
|
+
- Player recognizes the relationship
|
|
150
|
+
- Polish should reference the shared system
|
|
151
|
+
|
|
152
|
+
## Asteroids Polish Case Study
|
|
153
|
+
|
|
154
|
+
Despite limited hardware, Asteroids achieves excellent polish through coherence:
|
|
155
|
+
|
|
156
|
+
### Visual-Audio Consistency
|
|
157
|
+
- Large asteroid → Deep boom, large debris
|
|
158
|
+
- Medium asteroid → Mid-pitch, medium debris
|
|
159
|
+
- Small asteroid → High ping, small debris
|
|
160
|
+
- Ship thruster → Lowest rumble (powerful device)
|
|
161
|
+
|
|
162
|
+
### Effect Cohesion
|
|
163
|
+
- Ship destruction → Breaks into component lines
|
|
164
|
+
- Asteroid destruction → Particle spray
|
|
165
|
+
- Consistent visual language
|
|
166
|
+
|
|
167
|
+
## Mario 64 Polish Case Study
|
|
168
|
+
|
|
169
|
+
### Three-Tier System
|
|
170
|
+
All interactions categorized as light/medium/heavy with corresponding:
|
|
171
|
+
- Animation intensity
|
|
172
|
+
- Sound pitch and volume
|
|
173
|
+
- Particle quantity
|
|
174
|
+
- Screen shake intensity
|
|
175
|
+
|
|
176
|
+
### Footstep Sophistication
|
|
177
|
+
- Sound varies by surface material
|
|
178
|
+
- Timing syncs with animation
|
|
179
|
+
- Volume scales with movement speed
|
|
180
|
+
|
|
181
|
+
### Mario's Vocalizations
|
|
182
|
+
- Rising yell during jump ascent
|
|
183
|
+
- Grunt on heavy landing
|
|
184
|
+
- "Wahoo!" on special jumps
|
|
185
|
+
- Reinforces motion with voice
|
|
186
|
+
|
|
187
|
+
### Impact Exaggeration
|
|
188
|
+
- Mario's fist enlarges during punch
|
|
189
|
+
- Foot enlarges during kick
|
|
190
|
+
- Sells the power of the impact
|
|
191
|
+
|
|
192
|
+
## Polish Implementation Checklist
|
|
193
|
+
|
|
194
|
+
For each player action, ensure:
|
|
195
|
+
|
|
196
|
+
- [ ] Immediate visual feedback (frame 1)
|
|
197
|
+
- [ ] Appropriate sound effect
|
|
198
|
+
- [ ] Animation supports the action
|
|
199
|
+
- [ ] Effect intensity matches action intensity
|
|
200
|
+
- [ ] Effects harmonize (don't contradict)
|
|
201
|
+
- [ ] Haptic feedback (if applicable)
|
|
202
|
+
|
|
203
|
+
## Common Polish Mistakes
|
|
204
|
+
|
|
205
|
+
### Over-Polish
|
|
206
|
+
Too many effects obscure the action. Know when to restrain.
|
|
207
|
+
|
|
208
|
+
### Inconsistent Polish
|
|
209
|
+
One action heavily polished, another bare. Feels uneven.
|
|
210
|
+
|
|
211
|
+
### Wrong Intensity
|
|
212
|
+
Light action with heavy polish (or vice versa). Creates confusion.
|
|
213
|
+
|
|
214
|
+
### Out of Sync
|
|
215
|
+
Sound slightly before or after visual. Breaks believability.
|
|
216
|
+
|
|
217
|
+
### Polish Without Purpose
|
|
218
|
+
Effects that don't reinforce an interaction. Just noise.
|
|
219
|
+
|
|
220
|
+
## The Minimum Viable Polish
|
|
221
|
+
|
|
222
|
+
If resources are limited, prioritize:
|
|
223
|
+
|
|
224
|
+
1. **Jump landing** — Players do this constantly
|
|
225
|
+
2. **Attack/hit confirmation** — Core gameplay feedback
|
|
226
|
+
3. **Damage received** — Critical player information
|
|
227
|
+
4. **Movement sounds** — Grounds player in world
|
|
228
|
+
5. **UI feedback** — Confirms player inputs
|
|
229
|
+
|
|
230
|
+
## Testing Polish
|
|
231
|
+
|
|
232
|
+
### The Mute Test
|
|
233
|
+
Play with sound off. Can you still feel the impacts?
|
|
234
|
+
If not, visual polish is insufficient.
|
|
235
|
+
|
|
236
|
+
### The Blind Test
|
|
237
|
+
Listen without watching. Can you tell what's happening?
|
|
238
|
+
If not, audio polish is insufficient.
|
|
239
|
+
|
|
240
|
+
### The Slow-Mo Test
|
|
241
|
+
Watch at reduced speed. Do effects align with actions?
|
|
242
|
+
Reveals timing issues.
|
|
243
|
+
|
|
244
|
+
### The Comparison Test
|
|
245
|
+
Compare to a polished reference game.
|
|
246
|
+
Note where your game feels "flat" by comparison.
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# Simulation Recipes for Game Feel
|
|
2
|
+
|
|
3
|
+
Practical patterns for implementing specific feel profiles.
|
|
4
|
+
|
|
5
|
+
## Fundamental Simulation Approaches
|
|
6
|
+
|
|
7
|
+
### Level 1: Set Position Directly
|
|
8
|
+
```
|
|
9
|
+
position = position + (direction × speed)
|
|
10
|
+
```
|
|
11
|
+
- Input directly moves object
|
|
12
|
+
- Feel: Stiff, robotic, no momentum
|
|
13
|
+
- Example: Donkey Kong, early arcade games
|
|
14
|
+
|
|
15
|
+
### Level 2: Set Velocity
|
|
16
|
+
```
|
|
17
|
+
if (input) velocity = targetVelocity
|
|
18
|
+
position = position + velocity
|
|
19
|
+
```
|
|
20
|
+
- Input sets speed directly
|
|
21
|
+
- Feel: More responsive than position, but still abrupt
|
|
22
|
+
- Example: Some puzzle games
|
|
23
|
+
|
|
24
|
+
### Level 3: Apply Force (Acceleration)
|
|
25
|
+
```
|
|
26
|
+
if (input) acceleration = force
|
|
27
|
+
velocity = velocity + acceleration
|
|
28
|
+
velocity = velocity × friction
|
|
29
|
+
position = position + velocity
|
|
30
|
+
```
|
|
31
|
+
- Input adds force, velocity accumulates
|
|
32
|
+
- Feel: Fluid, physical, expressive
|
|
33
|
+
- Example: Mario, Asteroids, most modern games
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## The Asteroids Recipe
|
|
38
|
+
|
|
39
|
+
The classic "spaceship" feel.
|
|
40
|
+
|
|
41
|
+
### Core Principle
|
|
42
|
+
**Separate thrust from rotation.**
|
|
43
|
+
|
|
44
|
+
### Variables
|
|
45
|
+
```
|
|
46
|
+
shipRotation // Current facing angle
|
|
47
|
+
shipPosition // X, Y coordinates
|
|
48
|
+
shipVelocity // Current movement vector
|
|
49
|
+
thrustSpeed // Current thrust magnitude
|
|
50
|
+
thrustAcceleration // How fast thrust builds
|
|
51
|
+
thrustVelocity // Force vector to add
|
|
52
|
+
maxThrustSpeed // Speed cap
|
|
53
|
+
dampening // Very low (0.99+)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### The Algorithm
|
|
57
|
+
```
|
|
58
|
+
// Rotation: Direct, instant
|
|
59
|
+
if (rotateLeft) shipRotation -= rotateSpeed
|
|
60
|
+
if (rotateRight) shipRotation += rotateSpeed
|
|
61
|
+
|
|
62
|
+
// Thrust: Simulated, accumulates
|
|
63
|
+
if (thrustButton) {
|
|
64
|
+
thrustSpeed = min(thrustSpeed + thrustAcceleration, maxThrustSpeed)
|
|
65
|
+
thrustVelocity = directionFromAngle(shipRotation) × thrustSpeed
|
|
66
|
+
shipVelocity = shipVelocity + thrustVelocity
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Very low friction (space feel)
|
|
70
|
+
shipVelocity = shipVelocity × dampening
|
|
71
|
+
|
|
72
|
+
// Cap maximum speed
|
|
73
|
+
shipVelocity = clampMagnitude(shipVelocity, maxVelocity)
|
|
74
|
+
|
|
75
|
+
// Update position
|
|
76
|
+
shipPosition = shipPosition + shipVelocity
|
|
77
|
+
|
|
78
|
+
// Screen wrap
|
|
79
|
+
shipPosition = wrapToScreen(shipPosition)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Key Insight
|
|
83
|
+
Thrust vector is ADDED to velocity, not overwriting it. This decouples rotation from movement direction, creating the "always on the edge of control" feel.
|
|
84
|
+
|
|
85
|
+
### Tuning Notes
|
|
86
|
+
- Rotation should be instant with very slight attack (~0.1s)
|
|
87
|
+
- Dampening very low: 4+ seconds to stop from full speed
|
|
88
|
+
- Screen wrap prevents escape, creates constant danger
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## The Super Mario Bros Recipe
|
|
93
|
+
|
|
94
|
+
The gold standard for platformer feel.
|
|
95
|
+
|
|
96
|
+
### Core Principle
|
|
97
|
+
**Separate horizontal and vertical systems.**
|
|
98
|
+
|
|
99
|
+
### Horizontal Variables
|
|
100
|
+
```
|
|
101
|
+
walkAcceleration // Force applied when walking
|
|
102
|
+
walkMaxSpeed // Walking speed cap
|
|
103
|
+
runAcceleration // Force when B held (higher)
|
|
104
|
+
runMaxSpeed // Running speed cap (higher)
|
|
105
|
+
airAcceleration // Reduced control in air
|
|
106
|
+
deceleration // Friction when not pressing direction
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Vertical Variables
|
|
110
|
+
```
|
|
111
|
+
gravity // Constant downward force
|
|
112
|
+
initialJumpForce // Upward velocity on button press
|
|
113
|
+
minJumpTime // Minimum button hold for jump
|
|
114
|
+
maxJumpTime // Maximum button hold for jump
|
|
115
|
+
reducedJumpVelocity // Velocity set on early release
|
|
116
|
+
fallGravity // Gravity after apex (3× normal!)
|
|
117
|
+
terminalVelocity // Maximum fall speed
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Horizontal Movement
|
|
121
|
+
```
|
|
122
|
+
if (leftOrRight) {
|
|
123
|
+
if (onGround) {
|
|
124
|
+
if (runButton) {
|
|
125
|
+
velocity.x += runAcceleration × direction
|
|
126
|
+
velocity.x = clamp(velocity.x, -runMaxSpeed, runMaxSpeed)
|
|
127
|
+
} else {
|
|
128
|
+
velocity.x += walkAcceleration × direction
|
|
129
|
+
velocity.x = clamp(velocity.x, -walkMaxSpeed, walkMaxSpeed)
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
// Reduced air control
|
|
133
|
+
velocity.x += airAcceleration × direction
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
// Apply deceleration toward zero
|
|
137
|
+
velocity.x = moveToward(velocity.x, 0, deceleration)
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Vertical Movement (The Jump)
|
|
142
|
+
```
|
|
143
|
+
// Gravity always applied
|
|
144
|
+
velocity.y -= gravity
|
|
145
|
+
|
|
146
|
+
// Jump initiation
|
|
147
|
+
if (jumpButtonPressed && onGround) {
|
|
148
|
+
velocity.y = initialJumpForce
|
|
149
|
+
jumpHoldTime = 0
|
|
150
|
+
isJumping = true
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Jump extension while held
|
|
154
|
+
if (isJumping && jumpButtonHeld) {
|
|
155
|
+
jumpHoldTime += deltaTime
|
|
156
|
+
if (jumpHoldTime < maxJumpTime) {
|
|
157
|
+
// Continue applying upward force
|
|
158
|
+
velocity.y = initialJumpForce
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// THE CRITICAL HACK: Early release handling
|
|
163
|
+
if (isJumping && jumpButtonReleased) {
|
|
164
|
+
if (velocity.y > reducedJumpVelocity) {
|
|
165
|
+
velocity.y = reducedJumpVelocity // Artificial cap!
|
|
166
|
+
}
|
|
167
|
+
isJumping = false
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Increased fall gravity after apex
|
|
171
|
+
if (velocity.y < 0) {
|
|
172
|
+
velocity.y -= fallGravity // 3× normal gravity!
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Terminal velocity
|
|
176
|
+
velocity.y = max(velocity.y, -terminalVelocity)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Why the "Hack" Works
|
|
180
|
+
Setting velocity to a fixed low value on early release:
|
|
181
|
+
1. Creates consistent arc shapes
|
|
182
|
+
2. Maintains graceful motion
|
|
183
|
+
3. Provides clear minimum jump height
|
|
184
|
+
4. Feels natural despite being artificial
|
|
185
|
+
|
|
186
|
+
### Running Jump Boost
|
|
187
|
+
```
|
|
188
|
+
if (jumpButtonPressed && speed > walkMaxSpeed) {
|
|
189
|
+
initialJumpForce *= 1.1 // Slight boost
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## The Mario 64 Recipe
|
|
196
|
+
|
|
197
|
+
Translating platformer feel to 3D.
|
|
198
|
+
|
|
199
|
+
### Core Additions for 3D
|
|
200
|
+
|
|
201
|
+
**Camera-Relative Input**
|
|
202
|
+
```
|
|
203
|
+
// Thumbstick direction relative to camera, not character
|
|
204
|
+
worldDirection = cameraForward × stick.y + cameraRight × stick.x
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Turn Interpolation**
|
|
208
|
+
```
|
|
209
|
+
// Blend toward desired direction for carving motion
|
|
210
|
+
if (speed > 0) {
|
|
211
|
+
currentDirection = lerp(currentDirection, desiredDirection, turnSpeed)
|
|
212
|
+
} else {
|
|
213
|
+
currentDirection = desiredDirection // Instant at standstill
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Incline Physics**
|
|
218
|
+
```
|
|
219
|
+
groundAngle = getGroundAngle()
|
|
220
|
+
if (groundAngle > slideThreshold) {
|
|
221
|
+
// Enter slide state
|
|
222
|
+
state = SLIDING
|
|
223
|
+
velocity += getDownhillVector() × slideAcceleration
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Multiple Jump Types
|
|
228
|
+
|
|
229
|
+
| Jump | Trigger | Properties |
|
|
230
|
+
|------|---------|------------|
|
|
231
|
+
| **Basic** | A button | Variable height (hold-sensitive) |
|
|
232
|
+
| **Continuous** | A after landing | Higher, still variable |
|
|
233
|
+
| **Triple** | A after Continuous + speed | Fixed trajectory, highest |
|
|
234
|
+
| **Long** | Z+A while moving | Fixed, horizontal emphasis |
|
|
235
|
+
| **Back Somersault** | A while ducking | Fixed, highest vertical |
|
|
236
|
+
| **Side Somersault** | A during direction change | Fixed, high |
|
|
237
|
+
| **Wall Kick** | A near wall + away input | Fixed |
|
|
238
|
+
|
|
239
|
+
### Fixed vs Variable Trajectories
|
|
240
|
+
- **Variable** (basic): Expressive, moment-to-moment control
|
|
241
|
+
- **Fixed** (special): Predictable, precision platforming
|
|
242
|
+
|
|
243
|
+
### The Ground Pound
|
|
244
|
+
```
|
|
245
|
+
if (inAir && zButtonPressed) {
|
|
246
|
+
velocity.x = 0
|
|
247
|
+
velocity.z = 0
|
|
248
|
+
// Pause briefly
|
|
249
|
+
wait(0.1)
|
|
250
|
+
// Slam down with high gravity
|
|
251
|
+
velocity.y = -groundPoundSpeed
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
Provides precision landing by removing horizontal momentum.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Tuning Guidelines
|
|
259
|
+
|
|
260
|
+
### For "Tight" Feel
|
|
261
|
+
- High acceleration values
|
|
262
|
+
- Short attack times (<0.1s)
|
|
263
|
+
- Moderate deceleration
|
|
264
|
+
- Quick release phase
|
|
265
|
+
|
|
266
|
+
### For "Floaty" Feel
|
|
267
|
+
- Low acceleration values
|
|
268
|
+
- Long attack times (0.3-0.5s)
|
|
269
|
+
- Low deceleration (high inertia)
|
|
270
|
+
- Long release phase
|
|
271
|
+
|
|
272
|
+
### For "Weighty" Feel
|
|
273
|
+
- Strong gravity
|
|
274
|
+
- Even stronger fall gravity
|
|
275
|
+
- Moderate acceleration
|
|
276
|
+
- Pronounced squash/stretch animation
|
|
277
|
+
|
|
278
|
+
### For "Responsive" Feel
|
|
279
|
+
- <100ms input-to-response
|
|
280
|
+
- Direct mapping where possible
|
|
281
|
+
- Visual feedback on frame 1
|
|
282
|
+
- Sound on input, not on action completion
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Common Pitfalls
|
|
287
|
+
|
|
288
|
+
### Problem: Character won't stop
|
|
289
|
+
**Cause**: No deceleration when input stops
|
|
290
|
+
**Fix**: Apply friction force toward zero velocity
|
|
291
|
+
|
|
292
|
+
### Problem: Jump feels "swimmy"
|
|
293
|
+
**Cause**: Same gravity up and down
|
|
294
|
+
**Fix**: Increase fall gravity (2-3× normal)
|
|
295
|
+
|
|
296
|
+
### Problem: Controls feel random
|
|
297
|
+
**Cause**: Variable attack/release based on frame timing
|
|
298
|
+
**Fix**: Use fixed-timestep physics, frame-independent values
|
|
299
|
+
|
|
300
|
+
### Problem: Can't make precise movements
|
|
301
|
+
**Cause**: Only high-speed movement available
|
|
302
|
+
**Fix**: Add acceleration curve, lower minimum speed threshold
|
|
303
|
+
|
|
304
|
+
### Problem: Character slides off platforms
|
|
305
|
+
**Cause**: Deceleration too slow, momentum carries past edge
|
|
306
|
+
**Fix**: Increase deceleration, or snap to platform edges
|