Skip to content

Commit

Permalink
Implement controllable camera
Browse files Browse the repository at this point in the history
  • Loading branch information
Selgesel committed Aug 22, 2021
1 parent ba4f052 commit c1a0bb7
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 6 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.0.2
- Implemented a controllable camera and replaced the old camera with it
- Camera is controlled by moving the mouse
- Camera can be zoomed in and out via mouse wheel
- Player can toggle between captured and visible mouse modes; trapping it inside the game window or just letting it loose
- The camera is a `ClippedCamera` which prevents it from clipping through the environment (though it's not really perfect)

## 0.0.1
- Added the initial project version with the following features:
- A simple scene with platforms and slopes to test the movement system
Expand Down
1 change: 1 addition & 0 deletions Main.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ shadow_enabled = true

[node name="CSGCombiner" type="CSGCombiner" parent="."]
use_collision = true
collision_mask = 2

[node name="CSGMesh" type="CSGMesh" parent="CSGCombiner"]
transform = Transform( 1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0 )
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ You can also see the [Releases](https://github.com/selgesel/godot-third-person-c
| `A` | `move_left` | Move character to the left |
| `D` | `move_right` | Move character to the right |
| `Space` | `jump` | Have the character jump |
| `Esc` | `ui_cancel` | (Built-in) Toggle between captured and visible mouse modes |
| `Mouse Wheel Up` | `zoom_in` | Move the camera closer to the player |
| `Mouse Wheel Down` | `zoom_out` | Move the camera further away from the player |

## License
MIT
53 changes: 53 additions & 0 deletions player/ControllableCamera.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
extends Spatial

class_name ControllableCamera

export(float) var min_pitch: float = -90
export(float) var max_pitch: float = 75
export(float) var rotate_speed: float = 10
export(float) var sensitivity: float = 0.1
export(float) var zoom_speed: float = 10
export(float) var zoom_step: float = .5
export(float) var min_distance: float = 3
export(float) var max_distance: float = 10

onready var _gimbal_h: Spatial = $GimbalH
onready var _gimbal_v: Spatial = $GimbalH/GimbalV
onready var _camera: ClippedCamera = $GimbalH/GimbalV/ClippedCamera

var _rot_h: float = 0
var _rot_v: float = 0
var _is_capturing: bool = true
var _distance: float = 0

func _ready():
yield(get_parent(), "ready")
_distance = _camera.transform.origin.z
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _input(event):
if Input.is_action_just_pressed("ui_cancel"):
_is_capturing = !_is_capturing

if _is_capturing:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)

if _is_capturing && event is InputEventMouseMotion:
_rot_h -= event.relative.x * sensitivity
_rot_v -= event.relative.y * sensitivity

_rot_v = clamp(_rot_v, min_pitch, max_pitch)

if _is_capturing:
if Input.is_action_just_pressed("zoom_in"):
_distance = clamp(_distance - zoom_step, min_distance, max_distance)
if Input.is_action_just_pressed("zoom_out"):
_distance = clamp(_distance + zoom_step, min_distance, max_distance)

func _physics_process(delta):
_gimbal_h.rotation_degrees.y = lerp(_gimbal_h.rotation_degrees.y, _rot_h, rotate_speed * delta)
_gimbal_v.rotation_degrees.x = lerp(_gimbal_v.rotation_degrees.x, _rot_v, rotate_speed * delta)

_camera.transform.origin.z = lerp(_camera.transform.origin.z, _distance, zoom_speed * delta)
14 changes: 14 additions & 0 deletions player/ControllableCamera.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[gd_scene load_steps=2 format=2]

[ext_resource path="res://player/ControllableCamera.gd" type="Script" id=1]

[node name="ControllableCamera" type="Spatial"]
script = ExtResource( 1 )

[node name="GimbalH" type="Spatial" parent="."]

[node name="GimbalV" type="Spatial" parent="GimbalH"]

[node name="ClippedCamera" type="ClippedCamera" parent="GimbalH/GimbalV"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 6 )
current = true
8 changes: 7 additions & 1 deletion player/Player.gd
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ export(float) var max_terminal_velocity: float = 50
export(float) var max_slope_angle: float = 50
export(int) var max_jumps: int = 2
export(float) var jump_cooldown: float = .2
export(float) var cam_follow_speed: float = 8

onready var _skin: Spatial = $Skin
onready var _camera: ControllableCamera = $CamRoot/ControllableCamera

var _move_dir: Vector2 = Vector2.ZERO
var _is_jumping: bool = false
var _move_rot: float = 0

var _velocity: Vector3 = Vector3.ZERO
var _y_velocity: float = 0
Expand All @@ -31,6 +34,9 @@ func _process(delta):
func _physics_process(delta):
var direction = Vector3(_move_dir.x, 0, _move_dir.y)

_move_rot = lerp(_move_rot, deg2rad(_camera._rot_h), cam_follow_speed * delta)
direction = direction.rotated(Vector3.UP, _move_rot)

_velocity = _velocity.linear_interpolate(direction * move_speed, acceleration * delta)

if is_on_floor():
Expand All @@ -48,7 +54,7 @@ func _physics_process(delta):
_jump_cooldown_remaining = jump_cooldown

if _move_dir != Vector2.ZERO:
_rotation = lerp_angle(_rotation, atan2(-_move_dir.x, -_move_dir.y), turn_speed * delta)
_rotation = lerp_angle(_rotation, atan2(-direction.x, -direction.z), turn_speed * delta)
_skin.rotation.y = _rotation

_velocity.y = _y_velocity
Expand Down
10 changes: 6 additions & 4 deletions player/Player.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[gd_scene load_steps=5 format=2]
[gd_scene load_steps=6 format=2]

[ext_resource path="res://player/Player.gd" type="Script" id=1]
[ext_resource path="res://player/ControllableCamera.tscn" type="PackedScene" id=2]

[sub_resource type="CapsuleMesh" id=1]
radius = 0.5
Expand Down Expand Up @@ -34,6 +35,7 @@ material/0 = null
transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1, 0 )
shape = SubResource( 3 )

[node name="Camera" type="Camera" parent="."]
transform = Transform( 1, 0, 0, 0, 0.923639, 0.383264, 0, -0.383264, 0.923639, 0, 4.4251, 4.51287 )
current = true
[node name="CamRoot" type="Spatial" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0 )

[node name="ControllableCamera" parent="CamRoot" instance=ExtResource( 2 )]
25 changes: 25 additions & 0 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@

config_version=4

_global_script_classes=[ {
"base": "Spatial",
"class": "ControllableCamera",
"language": "GDScript",
"path": "res://player/ControllableCamera.gd"
} ]
_global_script_class_icons={
"ControllableCamera": ""
}

[application]

config/name="Third Person"
Expand Down Expand Up @@ -46,6 +56,21 @@ jump={
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null)
]
}
zoom_in={
"deadzone": 0.5,
"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":4,"pressed":false,"doubleclick":false,"script":null)
]
}
zoom_out={
"deadzone": 0.5,
"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":5,"pressed":false,"doubleclick":false,"script":null)
]
}

[layer_names]

3d_physics/layer_1="environment"
3d_physics/layer_2="player"

[physics]

Expand Down
4 changes: 3 additions & 1 deletion ui/Debugger.gd
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ func _process(delta):
_label.text += "Player Velocity: (%.2f, %.2f, %.2f)\n" % [_player._velocity.x, _player._y_velocity, _player._velocity.z]
_label.text += "Player Rotation: %.2f\n" % [rad2deg(_player._rotation)]
_label.text += "Jumps: %d\n" % [_player._jump_count]
_label.text += "Jump Cooldown: %.2f" % [_player._jump_cooldown_remaining]
_label.text += "Jump Cooldown: %.2f\n" % [_player._jump_cooldown_remaining]
_label.text += "Camera Rotation: (%.2f, %.2f)\n" % [_player._camera._rot_h, _player._camera._rot_v]
_label.text += "Camera Distance: %.2f" % [_player._camera._distance]

0 comments on commit c1a0bb7

Please sign in to comment.