Godot 4.6 · Physics Platformer
// Systems
// Architecture
All connections via Godot signals — zero direct node references across boundaries
// Source Code
SNIPPETS · Full files in repository# Excerpt from Player.gd — full file ~280 lines # Showing: FSM core, transitions, and gravity flip enum State { IDLE, RUN, JUMP, FALL, WALL_SLIDE, GRAVITY_FLIP, DEAD } var current_state: State = State.IDLE func _transition_to(new_state: State) -> void: if new_state == current_state: return var old_name := State.keys()[current_state] var new_name := State.keys()[new_state] _exit_state(current_state) current_state = new_state _enter_state(new_state) emit_signal("state_changed", old_name, new_name) func _transition_states() -> void: match current_state: State.JUMP: if (velocity.y * gravity_direction) >= 0: _transition_to(State.FALL) elif is_on_wall() and not is_on_floor(): _transition_to(State.WALL_SLIDE) State.FALL: if is_on_floor(): _transition_to(State.IDLE) elif is_on_wall(): _transition_to(State.WALL_SLIDE) # Gravity flip: one float drives all physics func _flip_gravity() -> void: gravity_inverted = not gravity_inverted gravity_direction = -1.0 if gravity_inverted else 1.0 velocity.y = JUMP_VELOCITY * gravity_direction * 0.7 emit_signal("gravity_flipped", gravity_inverted)
# Excerpt from LevelGenerator.gd — full file ~220 lines # Showing: terrain generation via constrained random walk func _generate_terrain() -> void: var total_cols := level_width_chunks * chunk_width var floor_h := chunk_height / 2 # Constrained random walk for floor height profile for col in range(total_cols): platform_heights.append(floor_h) # Gap probability scales with level progress var gap_chance := 0.1 + (float(col) / total_cols) * 0.15 if col > 4 and rng.randf() < gap_chance: var gap_len := rng.randi_range(min_gap, max_gap) for _g in range(gap_len): platform_heights.append(-1) # void else: floor_h = clamp(floor_h + rng.randi_range(-1, 1), 3, chunk_height - 3) # Paint tiles at runtime for col in range(platform_heights.size()): var h: int = platform_heights[col] if h < 0: continue tilemap.set_cell(0, Vector2i(col, h), SOURCE_ID, TILE_TOP) for row in range(h + 1, chunk_height + 2): tilemap.set_cell(0, Vector2i(col, row), SOURCE_ID, TILE_SOLID)
# Excerpt from CameraController.gd — full file ~80 lines # Showing: smooth follow, look-ahead, screen shake, dynamic zoom func _process(delta: float) -> void: if not _target: return # Look-ahead: offset based on velocity direction var vel: Vector2 = _target.velocity var desired_offset := Vector2(vel.x, 0.0).normalized() * look_ahead_dist _look_ahead_offset = _look_ahead_offset.lerp(desired_offset, look_ahead_speed * delta) # Smooth follow var target_pos := _target.global_position + _look_ahead_offset global_position = global_position.lerp(target_pos, follow_speed * delta) # Screen shake via FastNoiseLite if shake_strength > 0.1: var t := Time.get_ticks_msec() / 1000.0 _shake_offset = Vector2( _noise.get_noise_2d(t * 20.0, 0.0), _noise.get_noise_2d(0.0, t * 20.0) ) * shake_strength shake_strength = lerpf(shake_strength, 0.0, shake_decay * delta) offset = _shake_offset # Dynamic zoom: proportional to speed var speed_ratio := clamp(_target.velocity.length() / 500.0, 0.0, 1.0) var target_zoom := lerpf(base_zoom, zoom_out_max, speed_ratio) zoom = zoom.lerp(Vector2(target_zoom, target_zoom), zoom_speed * delta)
# Excerpt from GameManager.gd — full file ~130 lines # Showing: signal wiring and gravity-flip camera tween func _connect_signals() -> void: player.state_changed.connect(_on_player_state_changed) player.gravity_flipped.connect(_on_gravity_flipped) player.collected_orb.connect(_on_orb_collected) player.player_died.connect(_on_player_died) level_gen.level_generated.connect(_on_level_generated) func _on_gravity_flipped(is_inverted: bool) -> void: # Tween camera rotation for dramatic visual effect var target_rot := PI if is_inverted else 0.0 var tween := create_tween() tween.tween_property(camera, "rotation", target_rot, 0.35)\ .set_ease(Tween.EASE_IN_OUT)\ .set_trans(Tween.TRANS_CUBIC) func _check_win_condition(orbs: int) -> void: if orbs >= orbs_needed: var elapsed := Time.get_ticks_msec() / 1000.0 - run_start_time if elapsed < best_time: best_time = elapsed _set_state(GameState.WIN)