diff --git a/.gitattributes b/.gitattributes new file mode 100755 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/Characters/Animator.gd b/Characters/Animator.gd new file mode 100755 index 0000000..c2064a5 --- /dev/null +++ b/Characters/Animator.gd @@ -0,0 +1,20 @@ +extends Node + +@onready var walk: SpriteFrames +@onready var idle: SpriteFrames + +@onready var parent = get_parent() +@onready var sprite = $"../Sprite" + +var facing = 1 + +func _process(delta): + if ! is_zero_approx(parent.velocity.x): + sprite.scale.x = 1 if parent.velocity.x > 0 else -1 + + if ! parent.is_on_floor(): + sprite.play("Jump") + elif is_zero_approx(parent.velocity.x): + sprite.play("Idle") + else: + sprite.play("WalkRight", 2.0) diff --git a/Characters/Controller.gd b/Characters/Controller.gd new file mode 100755 index 0000000..673bfbb --- /dev/null +++ b/Characters/Controller.gd @@ -0,0 +1,6 @@ +extends Node + +func _process(delta): + var direction = Input.get_axis("MoveLeft", "MoveRight") + get_parent().move(direction) + get_parent().jump(Input.is_action_pressed("Jump")) diff --git a/Characters/Movement.gd b/Characters/Movement.gd new file mode 100644 index 0000000..66d665f --- /dev/null +++ b/Characters/Movement.gd @@ -0,0 +1,134 @@ +extends CharacterBody2D + +@export var acceleration = 6000.0 +@export var maxSpeed = 600.0 +@export var decelleration = 4000.0 + +@export var maxJumpHeight = 310.0 +@export var minJumpHeight = 90.0 +@export var peakTime = 0.5 + +@export var coyoteTime = 0.2 + +# Calculated physics variables +var holdGravity = 0 +var tapGravity = 0 +var jumpVelocity = 0 + +# Input variables set by controller +var direction = 0 +var startJump = false +var jumpHeld = false + +var jumpWindowRemaining = 0 + +func jump(pressed): + startJump = startJump or (!jumpHeld and pressed) + jumpHeld = pressed + +func move(dir): + direction = dir + +func updateVars(): + jumpVelocity = - 2 * maxJumpHeight / peakTime + holdGravity = 2 * maxJumpHeight / (peakTime * peakTime) + tapGravity = (jumpVelocity * jumpVelocity) / (2 * minJumpHeight) + +func _ready(): + updateVars() + +func _process(delta): + # We need to keep updating the vars because the inspector might have changed the settings + # Would be better to have a function we call on update instead of running every tick, but I can't be bothered right now + updateVars() + +func _physics_process(delta): + if direction != 0: + velocity.x += acceleration * direction * delta + else: + velocity.x = move_toward(velocity.x, 0, decelleration*delta) + + velocity.x = clampf(velocity.x, -maxSpeed, maxSpeed) + + if is_on_floor(): + jumpWindowRemaining = coyoteTime + else: + jumpWindowRemaining -= delta + + if startJump: + startJump = false + if jumpWindowRemaining > 0: + velocity.y = jumpVelocity + jumpWindowRemaining = 0 + + if not is_on_floor(): + var gravity = holdGravity if jumpHeld and velocity.y < 0 else tapGravity + velocity.y += gravity * delta + + move_and_slide() + +func getInspecctorDefinition(): + return [ + { + label = "Max Speed", + editable = true, + property = "maxSpeed", + max = 1000 + }, + { + label = "Acceleration", + editable = true, + property = "acceleration", + min = 1000, + max = 10000 + }, + { + label = "Decelleration", + editable = true, + property = "decelleration", + min = 1000, + max = 10000 + }, + { + label = "Max Jump Height", + editable = true, + property = "maxJumpHeight", + max = 1000 + }, + { + label = "Min Jump Height", + editable = true, + property = "minJumpHeight", + max = 1000 + }, + { + label = "Peak Time", + editable = true, + property = "peakTime", + max = 1 + }, + { + label = "Coyote Time", + editable = true, + property = "coyoteTime", + max = 0.5 + }, + { + type = 'spacer' + }, + { + label = "HoldGravity", + editable = false, + property = "holdGravity", + }, + { + label = "TapGravity", + editable = false, + property = "tapGravity", + }, + { + label = "Jump Velocity", + editable = false, + property = "jumpVelocity", + } + ] diff --git a/Characters/Player.tscn b/Characters/Player.tscn new file mode 100644 index 0000000..7527a64 --- /dev/null +++ b/Characters/Player.tscn @@ -0,0 +1,82 @@ +[gd_scene load_steps=15 format=3 uid="uid://bqkkr282ri5u2"] + +[ext_resource type="Texture2D" uid="uid://b1jerlmu0fp2c" path="res://Sprites/Base pack/Player/p1_stand.png" id="1_1sijd"] +[ext_resource type="Script" path="res://Characters/Movement.gd" id="1_81rbw"] +[ext_resource type="Texture2D" uid="uid://d1ywy6d18wmsm" path="res://Sprites/Base pack/Player/p1_jump.png" id="2_y4wvh"] +[ext_resource type="Texture2D" uid="uid://bigwlp8cud68a" path="res://Sprites/Base pack/Player/p1_walk/PNG/p1_walk01.png" id="3_770w6"] +[ext_resource type="Texture2D" uid="uid://b2cqw3woam708" path="res://Sprites/Base pack/Player/p1_walk/PNG/p1_walk02.png" id="4_q2d3d"] +[ext_resource type="Texture2D" uid="uid://b611l8fvgljfs" path="res://Sprites/Base pack/Player/p1_walk/PNG/p1_walk03.png" id="5_hnf8a"] +[ext_resource type="Texture2D" uid="uid://b3eoqc48hgxix" path="res://Sprites/Base pack/Player/p1_walk/PNG/p1_walk04.png" id="6_sdjwh"] +[ext_resource type="Texture2D" uid="uid://bl38ou8pb3jk1" path="res://Sprites/Base pack/Player/p1_walk/PNG/p1_walk05.png" id="7_tr8pv"] +[ext_resource type="Texture2D" uid="uid://cgx0s032e83u0" path="res://Sprites/Base pack/Player/p1_walk/PNG/p1_walk06.png" id="8_rndrl"] +[ext_resource type="Texture2D" uid="uid://dpfdy8g6p706q" path="res://Sprites/Base pack/Player/p1_walk/PNG/p1_walk07.png" id="9_djnid"] +[ext_resource type="Script" path="res://Characters/Animator.gd" id="11_thosa"] +[ext_resource type="Script" path="res://Characters/Controller.gd" id="12_1k5oy"] + +[sub_resource type="SpriteFrames" id="SpriteFrames_dc0ly"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("1_1sijd") +}], +"loop": true, +"name": &"Idle", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2_y4wvh") +}], +"loop": true, +"name": &"Jump", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("4_q2d3d") +}, { +"duration": 1.0, +"texture": ExtResource("5_hnf8a") +}, { +"duration": 1.0, +"texture": ExtResource("6_sdjwh") +}, { +"duration": 1.0, +"texture": ExtResource("7_tr8pv") +}, { +"duration": 1.0, +"texture": ExtResource("9_djnid") +}, { +"duration": 1.0, +"texture": ExtResource("8_rndrl") +}, { +"duration": 1.0, +"texture": ExtResource("3_770w6") +}], +"loop": true, +"name": &"WalkRight", +"speed": 5.0 +}] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_sktd2"] +size = Vector2(67, 94) + +[node name="Player" type="CharacterBody2D"] +script = ExtResource("1_81rbw") + +[node name="Sprite" type="AnimatedSprite2D" parent="."] +sprite_frames = SubResource("SpriteFrames_dc0ly") +animation = &"WalkRight" + +[node name="Collider" type="CollisionShape2D" parent="."] +position = Vector2(2.5, -1) +shape = SubResource("RectangleShape2D_sktd2") + +[node name="Camera" type="Camera2D" parent="."] +zoom = Vector2(0.8, 0.8) + +[node name="Animator" type="Node" parent="."] +script = ExtResource("11_thosa") + +[node name="Controller" type="Node" parent="."] +script = ExtResource("12_1k5oy") diff --git a/Inspector/Inspector.gd b/Inspector/Inspector.gd new file mode 100755 index 0000000..ab2b6f6 --- /dev/null +++ b/Inspector/Inspector.gd @@ -0,0 +1,35 @@ +extends Control +const DefaultDisplay = preload("InspectorDisplay.tscn") +const DefaultControl = preload("InspectorControl.tscn") +const DefaultSpacer = preload("InspectorSpacer.tscn") + +@export var target: Node2D + +func _ready(): + if target: + setTarget(target) + +func setTarget(newTarget): + target = newTarget + + for child in get_children(): + child.queue_free() + + var definition = target.getInspecctorDefinition() + for spec in definition: + if 'type' in spec: + match (spec.type): + 'spacer': + add_child(DefaultSpacer.instantiate()) + continue + + var node = (DefaultControl if spec.editable else DefaultDisplay).instantiate() + node.property = spec.property + node.target = target + node.label = spec.label + if 'min' in spec: + node.min = spec.min + if 'max' in spec: + node.max = spec.max + add_child(node) + diff --git a/Inspector/Inspector.tscn b/Inspector/Inspector.tscn new file mode 100644 index 0000000..a9e663c --- /dev/null +++ b/Inspector/Inspector.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://b6v35khfa5naf"] + +[ext_resource type="Script" path="res://Inspector/Inspector.gd" id="1_kq8ag"] + +[node name="Inspector" type="VBoxContainer"] +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("1_kq8ag") diff --git a/Inspector/InspectorControl.gd b/Inspector/InspectorControl.gd new file mode 100755 index 0000000..854a809 --- /dev/null +++ b/Inspector/InspectorControl.gd @@ -0,0 +1,39 @@ +extends HBoxContainer + +@export var target: Node2D +@export var property: String +@export var min = 0 +@export var max = 100 +@export var label = "" + +@onready var SliderNode = $Slider +@onready var ValueNode = $Value +@onready var LabelNode = $Label + +# Called when the node enters the scene tree for the first time. +func _ready(): + LabelNode.text = label + SliderNode.min_value = min + SliderNode.max_value = max + SliderNode.drag_ended.connect(_drag_ended) + SliderNode.drag_started.connect(_drag_started) + + var value = target.get(property) + ValueNode.text = "%.02f" % value + SliderNode.set_value_no_signal(value) + set_process(false) + +func update(): + target.set(property, SliderNode.value) + ValueNode.text = "%.02f" % SliderNode.value + +func _drag_ended(changed): + if changed: + update() + +func _drag_started(): + set_process(true) + +func _process(delta): + update() + diff --git a/Inspector/InspectorControl.tscn b/Inspector/InspectorControl.tscn new file mode 100644 index 0000000..990d83a --- /dev/null +++ b/Inspector/InspectorControl.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=2 format=3 uid="uid://bt2a1pwx6mj5s"] + +[ext_resource type="Script" path="res://Inspector/InspectorControl.gd" id="1_kjmon"] + +[node name="InspectorControl" type="HBoxContainer"] +script = ExtResource("1_kjmon") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +text = "