snapshot (WIP)

item-info
John Montagu, the 4th Earl of Sandvich 2022-11-27 19:37:16 -08:00
parent 8e0f80c9d6
commit 8c2c33644e
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
18 changed files with 469 additions and 266 deletions

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://njun3e6v4854"
path="res://.godot/imported/hurt.wav-d823d511f814815fa850bdfbaa893eea.sample"
[deps]
source_file="res://Assets/Sounds/hurt.wav"
dest_files=["res://.godot/imported/hurt.wav-d823d511f814815fa850bdfbaa893eea.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://c4n7ioxpukdwi"
path="res://.godot/imported/parry.wav-95f3f1d45e3d2fd9dd7d767397e50846.sample"
[deps]
source_file="res://Assets/Sounds/parry.wav"
dest_files=["res://.godot/imported/parry.wav-95f3f1d45e3d2fd9dd7d767397e50846.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

View File

@ -11,8 +11,7 @@
[ext_resource type="PackedScene" uid="uid://d72ehtv1ks0e" path="res://Items/Weapons/Sword.tscn" id="8_s3c8r"] [ext_resource type="PackedScene" uid="uid://d72ehtv1ks0e" path="res://Items/Weapons/Sword.tscn" id="8_s3c8r"]
[ext_resource type="AudioStream" uid="uid://njun3e6v4854" path="res://Assets/Sounds/hurt.wav" id="10_n1e64"] [ext_resource type="AudioStream" uid="uid://njun3e6v4854" path="res://Assets/Sounds/hurt.wav" id="10_n1e64"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_8jbxb"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_ms3xg"]
resource_local_to_scene = true
shader = ExtResource("1_fx1w5") shader = ExtResource("1_fx1w5")
shader_parameter/color = null shader_parameter/color = null
shader_parameter/intensity = 0.0 shader_parameter/intensity = 0.0
@ -103,9 +102,9 @@ _data = {
[node name="ExampleEnemy" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine")] [node name="ExampleEnemy" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine")]
texture_filter = 3 texture_filter = 3
material = SubResource("ShaderMaterial_8jbxb") material = SubResource("ShaderMaterial_ms3xg")
y_sort_enabled = true y_sort_enabled = true
collision_layer = 2 collision_layer = 10
script = ExtResource("1_2yopk") script = ExtResource("1_2yopk")
Health = 50.0 Health = 50.0
Sprite = NodePath("Sprite") Sprite = NodePath("Sprite")
@ -114,7 +113,6 @@ StateMachine = NodePath("StateMachine")
Faction = 2 Faction = 2
[node name="Sprite" type="AnimatedSprite2D" parent="."] [node name="Sprite" type="AnimatedSprite2D" parent="."]
use_parent_material = true
frames = SubResource("SpriteFrames_4tm2b") frames = SubResource("SpriteFrames_4tm2b")
animation = &"move" animation = &"move"
playing = true playing = true

View File

@ -1,4 +1,5 @@
using Godot; using Godot;
using SupaLidlGame.Extensions;
using SupaLidlGame.Items; using SupaLidlGame.Items;
using System; using System;
@ -13,15 +14,17 @@ namespace SupaLidlGame.Characters
public float[] Weights => _weights; public float[] Weights => _weights;
[Export]
public float PreferredDistance { get; protected set; } = 64.0f;
protected float[] _weights = new float[16]; protected float[] _weights = new float[16];
protected Vector2[] _weightDirs = new Vector2[16];
protected int _bestWeightIdx; protected int _bestWeightIdx;
protected double _thinkTimeElapsed = 0; protected double _thinkTimeElapsed = 0;
protected Vector2 _blockingDir;
protected static readonly Vector2[] _weightDirs = new Vector2[16];
public override void _Ready() static NPC()
{ {
base._Ready();
Array.Fill(_weights, 0);
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
float y = Mathf.Sin(Mathf.Pi * i * 2 / 16); float y = Mathf.Sin(Mathf.Pi * i * 2 / 16);
@ -30,6 +33,12 @@ namespace SupaLidlGame.Characters
} }
} }
public override void _Ready()
{
base._Ready();
Array.Fill(_weights, 0);
}
/* /*
public override void _Process(double delta) public override void _Process(double delta)
{ {
@ -50,7 +59,7 @@ namespace SupaLidlGame.Characters
#if DEBUG #if DEBUG
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
Vector2 vec = _weightDirs[i] * _weights[i] * 128; Vector2 vec = _weightDirs[i] * _weights[i] * 32;
Color c = Colors.Green; Color c = Colors.Green;
if (_bestWeightIdx == i) if (_bestWeightIdx == i)
{ {
@ -63,6 +72,11 @@ namespace SupaLidlGame.Characters
} }
DrawLine(Vector2.Zero, vec, c); DrawLine(Vector2.Zero, vec, c);
} }
/*
DrawLine(Vector2.Zero, Direction * 32, new Color(0, 1, 0));
DrawLine(Vector2.Zero, Target * 32, Colors.Blue);
DrawLine(Vector2.Zero, _blockingDir, Colors.Red, 2);
*/
#endif #endif
base._Draw(); base._Draw();
@ -93,48 +107,32 @@ namespace SupaLidlGame.Characters
{ {
_thinkTimeElapsed = 0; _thinkTimeElapsed = 0;
Think(); Think();
QueueRedraw();
} }
Direction = Target; //Direction = GetDirection(Target);
//Direction = _weightDirs[_bestWeightIdx]; Direction = _weightDirs[_bestWeightIdx];
} }
protected virtual void Think() public void UpdateWeights(Vector2 pos)
{ {
Vector2 pos = FindBestTarget().GlobalPosition; // FIXME: TODO: remove all the spaghetti
Target = pos - GlobalPosition;//GlobalPosition.DirectionTo(pos);
Vector2 dir = Target.Normalized(); Vector2 dir = Target.Normalized();
float dist = GlobalPosition.DistanceSquaredTo(pos); float dist = GlobalPosition.DistanceSquaredTo(pos);
if (Target.LengthSquared() < 1024) var spaceState = GetWorld2d().DirectSpaceState;
{ var exclude = new Godot.Collections.Array<RID>();
if (Inventory.SelectedItem is Weapon weapon) exclude.Add(this.GetRid());
{
UseCurrentItem();
}
}
#if DEBUGs
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
float directDot = _weightDirs[i].Dot(dir); float directDot = _weightDirs[i].Dot(dir);
// clamp dot from [-1, 1] to [0, 1]
directDot = (directDot + 1) / 2; directDot = (directDot + 1) / 2;
// this dot product resembles values of sine rather than cosine float strafeDot = Math.Abs(_weightDirs[i].Dot(dir.Clockwise90()));
// use it to weigh direction horizontally
Vector2 rotatedDir = new Vector2(-dir.y, dir.x);
float horizDot = Math.Abs(_weightDirs[i].Dot(rotatedDir));
// this is a smaller weight so they are more likely to pick the
// direction they are currently heading when choosing between two
// horizontal weights
float currDirDot = (_weightDirs[i].Dot(Direction) + 1) / 16; float currDirDot = (_weightDirs[i].Dot(Direction) + 1) / 16;
strafeDot = Mathf.Pow((strafeDot + 1) / 2, 2) + currDirDot;
// square so lower values are even lower
horizDot = Mathf.Pow((horizDot + 1) / 2, 2) + currDirDot;
// "When will I use math in the real world" Clueful
if (dist > 4096) if (dist > 4096)
{ {
@ -142,41 +140,35 @@ namespace SupaLidlGame.Characters
} }
else if (dist > 64) else if (dist > 64)
{ {
//float directDotWeighting = dist / 4096; float dDotWeight = Mathf.Sqrt(dist / 4096);
//float directDotWeighting = Mathf.Log(dist) / _log1024; float sDotWeight = 1 - dDotWeight;
float directDotWeighting = Mathf.Sqrt(dist / 4096); _weights[i] = (dDotWeight * directDot) + (sDotWeight * strafeDot);
float horizDotWeighting = 1 - directDotWeighting;
_weights[i] = (directDot * directDotWeighting) +
(horizDot * horizDotWeighting * 0.5f);
} }
else else
{ {
// shorter than 64 _weights[i] = strafeDot;
_weights[i] = horizDot;
} }
// now we shall subtract weights whose rays collide }
// with something
for (int i = 0; i < 16; i++)
{ {
var spaceState = GetWorld2d().DirectSpaceState;
var exclude = new Godot.Collections.Array<RID>();
exclude.Add(this.GetRid());
var rayParams = new PhysicsRayQueryParameters2D var rayParams = new PhysicsRayQueryParameters2D
{ {
Exclude = exclude, Exclude = exclude,
CollideWithBodies = true, CollideWithBodies = true,
From = GlobalPosition, From = GlobalPosition,
To = GlobalPosition + (_weightDirs[i] * 16) To = GlobalPosition + (_weightDirs[i] * 24),
CollisionMask = 1 + 8
}; };
var result = spaceState.IntersectRay(rayParams); var result = spaceState.IntersectRay(rayParams);
// if our ray cast hits something // if we hit something
if (result.Count > 0) if (result.Count > 0)
{ {
// then we subtract the dot product of other directions // then we subtract the value of this from the other weights
float oldWeight = _weights[i];
for (int j = 0; j < 16; j++) for (int j = 0; j < 16; j++)
{ {
if (i == j) if (i == j)
@ -185,27 +177,131 @@ namespace SupaLidlGame.Characters
} }
else else
{ {
float dot = _weightDirs[i].Dot(_weightDirs[j]) / 2; float dot = _weightDirs[i].Dot(_weightDirs[j]);
_weights[j] -= (dot + 1) / 2; _weights[j] -= _weights[j] * dot;
}
} }
} }
} }
} }
float bestWeight = 0; float bestWeight = 0;
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
if (_weights[i] > bestWeight) if (_weights[i] > bestWeight)
{ {
bestWeight = _weights[i];
_bestWeightIdx = i; _bestWeightIdx = i;
bestWeight = _weights[i];
}
} }
} }
QueueRedraw(); public Vector2 GetDirection(Vector2 towards)
#endif {
float directWeight;
float strafeWeight;
float dist = towards.Length();
Vector2 directDir = towards.Normalized();
Vector2 strafeDir;
float crossProduct = towards.Cross(Direction);
// strafeDir is either counter clockwise or clockwise depending on
// the direction the NPC is already traveling
// enemies might rapidly change direction if compared to 0
if (crossProduct < -1)
{
strafeDir = directDir.Counterclockwise90();
}
else
{
strafeDir = directDir.Counterclockwise90();
//strafeDir = directDir.Clockwise90();
}
// weights approach 1
// dy/dx = 1 - y
// y = 1 - e^(-x)
directWeight = 1 - Mathf.Pow(Mathf.E, -(dist / PreferredDistance));
strafeWeight = 1 - directWeight;
/*
Vector2 midpoint = (strafeDir * strafeWeight)
.Midpoint(directDir * directWeight);
*/
Vector2 midpoint = (directDir * directWeight)
.Midpoint(strafeDir * strafeWeight);
_blockingDir = GetBlocking();
midpoint += _blockingDir;
return midpoint.Normalized();
}
public Vector2 GetBlocking()
{
var spaceState = GetWorld2d().DirectSpaceState;
int rayLength = 16;
float[] weights = new float[16];
Vector2[] rays = new Vector2[16];
Vector2 net = Vector2.Zero;
for (int i = 0; i < 16; i++)
{
// cast ray and gets its length
// the length determines its strength
// exclude itself from raycasts
var exclude = new Godot.Collections.Array<RID>();
exclude.Add(GetRid());
var rayParams = new PhysicsRayQueryParameters2D
{
CollisionMask = 9,
From = GlobalPosition,
To = _weightDirs[i] * rayLength,
Exclude = exclude
};
var result = spaceState.IntersectRay(rayParams);
if (result.Count > 0)
{
Vector2 position = (Vector2)result["position"];
float hitDist = GlobalPosition.DistanceTo(position);
//float hitDist = GlobalPosition.DistanceSquaredTo(position);
//float rayDist = Mathf.Pow(rayLength, 2);
//float weight = rayDist - hitDist;
float weight = rayLength - hitDist;
GD.Print(weight);
rays[i] = _weightDirs[i] * weight;
net += rays[i];
}
else
{
rays[i] = Vector2.Zero;
}
}
return net;
//return -Vector2Extensions.Midpoints(rays);
}
protected virtual void Think()
{
Vector2 pos = FindBestTarget().GlobalPosition;
Target = pos - GlobalPosition;//GlobalPosition.DirectionTo(pos);
Vector2 dir = Target;
float dist = GlobalPosition.DistanceSquaredTo(pos);
UpdateWeights(pos);
if (Target.LengthSquared() < 1024)
{
if (Inventory.SelectedItem is Weapon weapon)
{
UseCurrentItem();
}
}
} }
} }
} }

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=29 format=3 uid="uid://b2254pup8k161"] [gd_scene load_steps=28 format=3 uid="uid://b2254pup8k161"]
[ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"] [ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"] [ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"]
@ -105,19 +105,11 @@ _data = {
"RESET": SubResource("Animation_k6l16") "RESET": SubResource("Animation_k6l16")
} }
[sub_resource type="Environment" id="Environment_rs2vs"]
background_mode = 3
background_energy_multiplier = 16.0
ambient_light_source = 3
ambient_light_energy = 2.68
glow_enabled = true
glow_intensity = 8.0
[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("Camera", "Sprite", "Inventory", "StateMachine")] [node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("Camera", "Sprite", "Inventory", "StateMachine")]
texture_filter = 3 texture_filter = 3
material = SubResource("ShaderMaterial_h78y7") material = SubResource("ShaderMaterial_h78y7")
y_sort_enabled = true y_sort_enabled = true
collision_layer = 2 collision_layer = 6
script = ExtResource("1_flygr") script = ExtResource("1_flygr")
Camera = NodePath("Camera2D") Camera = NodePath("Camera2D")
Speed = 64.0 Speed = 64.0
@ -193,9 +185,6 @@ libraries = {
"": SubResource("AnimationLibrary_xe5eq") "": SubResource("AnimationLibrary_xe5eq")
} }
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_rs2vs")
[node name="HurtSound" type="AudioStreamPlayer2D" parent="."] [node name="HurtSound" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("12_h0x0g") stream = ExtResource("12_h0x0g")

View File

@ -42,8 +42,6 @@ namespace SupaLidlGame.Characters.State
if (Character.Inventory.SelectedItem is not null) if (Character.Inventory.SelectedItem is not null)
{ {
Character.UseCurrentItem(); Character.UseCurrentItem();
//Character.Inventory.SelectedItem.Use();
//return AttackState;
} }
} }

View File

@ -26,9 +26,14 @@ namespace SupaLidlGame.Extensions
} }
/// <summary> /// <summary>
/// /// A version <c>GetNode</c> that returns null rather than cause an
/// exception if the node is not found or is not the same type.
/// </summary> /// </summary>
public static T GetNode<T>(this Node node, string name) where T : Node /// <returns>
/// <see langword="null">null</see> if <param>name</param> does not match
/// a valid Node
/// </returns>
public static T GetN<T>(this Node node, string name) where T : Node
{ {
return node.GetNode(name) as T; return node.GetNode(name) as T;
} }

View File

@ -0,0 +1,13 @@
using Godot;
namespace SupaLidlGame.Extensions
{
public static class Node2DExtensions
{
public static void RayCast(this Node2D node, Vector2 ray)
{
//var spaceState = node.GetWorld2d().DirectSpaceState;
//var result = spaceState.IntersectRay();
}
}
}

View File

@ -0,0 +1,39 @@
using Godot;
using System.Linq;
namespace SupaLidlGame.Extensions
{
public static class Vector2Extensions
{
public static Vector2 Midpoint(this Vector2 vector, Vector2 other)
{
return new Vector2((vector.x + other.x) / 2,
(vector.y + other.y) / 2);
}
public static Vector2 Midpoints(params Vector2[] vectors)
{
int length = vectors.Length;
float x = 0;
float y = 0;
for (int i = 0; i < length; i++)
{
x += vectors[i].x;
y += vectors[i].y;
}
return new Vector2(x / length, y / length);
}
public static Vector2 Counterclockwise90(this Vector2 vector)
{
return new Vector2(-vector.y, vector.x);
}
public static Vector2 Clockwise90(this Vector2 vector)
{
return new Vector2(vector.y, -vector.x);
}
}
}

View File

@ -141,6 +141,52 @@ tracks/2/keys = {
"values": [0, 1, 2, 0] "values": [0, 1, 2, 0]
} }
[sub_resource type="Animation" id="Animation_nivo8"]
resource_name = "use-npc"
length = 1.5
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Anchor:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = false
tracks/0/keys = {
"times": PackedFloat32Array(0.05, 0.3, 0.4, 0.45, 0.75, 1.5),
"transitions": PackedFloat32Array(1, 4, 1, 2, 4, 1),
"update": 3,
"values": [-0.610865, -1.309, 3.92699, 3.92699, 3.75246, -0.785398]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.3, 0.45),
"transitions": PackedFloat32Array(1, 1),
"values": [{
"args": [],
"method": &"Attack"
}, {
"args": [],
"method": &"Deattack"
}]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("SwingSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.4, 0.5, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 0]
}
[sub_resource type="Animation" id="Animation_y4mj3"] [sub_resource type="Animation" id="Animation_y4mj3"]
resource_name = "use2" resource_name = "use2"
length = 0.75 length = 0.75
@ -187,52 +233,6 @@ tracks/2/keys = {
"values": [0, 1, 3, 0] "values": [0, 1, 3, 0]
} }
[sub_resource type="Animation" id="Animation_nivo8"]
resource_name = "use-npc"
length = 1.5
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Anchor:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = false
tracks/0/keys = {
"times": PackedFloat32Array(0.05, 0.3, 0.4, 0.45, 0.75, 1.5),
"transitions": PackedFloat32Array(1, 4, 1, 2, 4, 1),
"update": 3,
"values": [-0.610865, -0.959931, 3.92699, 3.92699, 3.75246, -0.785398]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.3, 0.45),
"transitions": PackedFloat32Array(1, 1),
"values": [{
"args": [],
"method": &"Attack"
}, {
"args": [],
"method": &"Deattack"
}]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("SwingSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.4, 0.5, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 0]
}
[sub_resource type="Animation" id="Animation_2k2er"] [sub_resource type="Animation" id="Animation_2k2er"]
resource_name = "use2-npc" resource_name = "use2-npc"
length = 0.75 length = 0.75
@ -247,7 +247,7 @@ tracks/0/keys = {
"times": PackedFloat32Array(0.05, 0.3, 0.4, 0.45, 0.75), "times": PackedFloat32Array(0.05, 0.3, 0.4, 0.45, 0.75),
"transitions": PackedFloat32Array(1, 4, 1, 2, 1), "transitions": PackedFloat32Array(1, 4, 1, 2, 1),
"update": 3, "update": 3,
"values": [3.75246, 4.10152, -0.785398, -0.785398, -0.610865] "values": [3.75246, 4.45059, -0.785398, -0.785398, -0.610865]
} }
tracks/1/type = "method" tracks/1/type = "method"
tracks/1/imported = false tracks/1/imported = false

View File

@ -1,9 +1,8 @@
[gd_scene load_steps=9 format=3 uid="uid://dd6xy1y0m8smm"] [gd_scene load_steps=6 format=3 uid="uid://dd6xy1y0m8smm"]
[ext_resource type="Texture2D" uid="uid://gm2pcnfg7h8j" path="res://Assets/Sprites/tileset.png" id="1_k6myx"] [ext_resource type="Texture2D" uid="uid://gm2pcnfg7h8j" path="res://Assets/Sprites/tileset.png" id="1_k6myx"]
[ext_resource type="PackedScene" uid="uid://b2254pup8k161" path="res://Characters/Player.tscn" id="1_m35hr"] [ext_resource type="PackedScene" uid="uid://b2254pup8k161" path="res://Characters/Player.tscn" id="1_m35hr"]
[ext_resource type="PackedScene" uid="uid://ddcf6bfv212wj" path="res://Characters/ExampleEnemy.tscn" id="2_uti3y"] [ext_resource type="PackedScene" uid="uid://ddcf6bfv212wj" path="res://Characters/ExampleEnemy.tscn" id="2_uti3y"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="4_056cf"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_1pa1q"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_1pa1q"]
texture = ExtResource("1_k6myx") texture = ExtResource("1_k6myx")
@ -233,6 +232,7 @@ texture = ExtResource("1_k6myx")
7:3/0 = 0 7:3/0 = 0
7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) 7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:3/0/physics_layer_0/angular_velocity = 0.0 7:3/0/physics_layer_0/angular_velocity = 0.0
7:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 2, 8, 2, 8, 12, -8, 12)
8:3/0 = 0 8:3/0 = 0
8:3/0/physics_layer_0/linear_velocity = Vector2(0, 0) 8:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
8:3/0/physics_layer_0/angular_velocity = 0.0 8:3/0/physics_layer_0/angular_velocity = 0.0
@ -308,6 +308,7 @@ texture = ExtResource("1_k6myx")
6:4/0 = 0 6:4/0 = 0
6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) 6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:4/0/physics_layer_0/angular_velocity = 0.0 6:4/0/physics_layer_0/angular_velocity = 0.0
6:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -1, 8, -1, 8, 8, -8, 8)
8:4/0 = 0 8:4/0 = 0
8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0) 8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
8:4/0/physics_layer_0/angular_velocity = 0.0 8:4/0/physics_layer_0/angular_velocity = 0.0
@ -1101,18 +1102,6 @@ texture = ExtResource("1_k6myx")
physics_layer_0/collision_layer = 1 physics_layer_0/collision_layer = 1
sources/0 = SubResource("TileSetAtlasSource_1pa1q") sources/0 = SubResource("TileSetAtlasSource_1pa1q")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_whp32"]
resource_local_to_scene = true
shader = ExtResource("4_056cf")
shader_parameter/color = null
shader_parameter/intensity = 0.0
[sub_resource type="ShaderMaterial" id="ShaderMaterial_rthg0"]
resource_local_to_scene = true
shader = ExtResource("4_056cf")
shader_parameter/color = null
shader_parameter/intensity = 0.0
[node name="Level" type="Node2D"] [node name="Level" type="Node2D"]
[node name="TileMap" type="TileMap" parent="."] [node name="TileMap" type="TileMap" parent="."]
@ -1122,7 +1111,7 @@ tile_set = SubResource("TileSet_18c7j")
format = 2 format = 2
layer_0/name = "Walls" layer_0/name = "Walls"
layer_0/y_sort_enabled = true layer_0/y_sort_enabled = true
layer_0/tile_data = PackedInt32Array(131065, 458752, 0, -65531, 458752, 0) layer_0/tile_data = PackedInt32Array(131065, 458752, 0, -65531, 458752, 0, 327679, 458752, 3, 327687, 458752, 3)
layer_1/name = "Ground 2" layer_1/name = "Ground 2"
layer_1/enabled = true layer_1/enabled = true
layer_1/modulate = Color(1, 1, 1, 1) layer_1/modulate = Color(1, 1, 1, 1)
@ -1150,11 +1139,21 @@ position = Vector2(-81, -34)
motion_mode = 1 motion_mode = 1
[node name="ExampleEnemy" parent="TileMap" instance=ExtResource("2_uti3y")] [node name="ExampleEnemy" parent="TileMap" instance=ExtResource("2_uti3y")]
material = SubResource("ShaderMaterial_whp32")
position = Vector2(38, 42) position = Vector2(38, 42)
scale = Vector2(1.00571, 1) scale = Vector2(1.00571, 1)
[node name="ExampleEnemy2" parent="TileMap" instance=ExtResource("2_uti3y")] [node name="ExampleEnemy2" parent="TileMap" instance=ExtResource("2_uti3y")]
material = SubResource("ShaderMaterial_rthg0")
position = Vector2(190, 99) position = Vector2(190, 99)
scale = Vector2(1.00571, 1) scale = Vector2(1.00571, 1)
[node name="ExampleEnemy3" parent="TileMap" instance=ExtResource("2_uti3y")]
position = Vector2(175, 2)
scale = Vector2(1.00571, 1)
[node name="ExampleEnemy4" parent="TileMap" instance=ExtResource("2_uti3y")]
position = Vector2(122, 36)
scale = Vector2(1.00571, 1)
[node name="ExampleEnemy5" parent="TileMap" instance=ExtResource("2_uti3y")]
position = Vector2(207, 56)
scale = Vector2(1.00571, 1)

View File

@ -1,99 +1,58 @@
using Godot; using Godot;
using SupaLidlGame.Extensions;
using System; using System;
namespace SupaLidlGame.Prototyping namespace SupaLidlGame.Prototyping
{ {
public partial class ContextBasedSteering : Node2D public partial class ContextBasedSteering : Node2D
{ {
float[] _weights = new float[16]; public float PreferredDistance { get; set; } = 256.0f;
Vector2[] _weightDirs = new Vector2[16]; Vector2 _direction;
int _bestWeightIdx;
// Called when the node enters the scene tree for the first time. // Called when the node enters the scene tree for the first time.
public override void _Ready() public override void _Ready()
{ {
Array.Fill(_weights, 1); GD.Print("Started ContextBasedSteering test");
for (int i = 0; i < 16; i++)
{
float y = Mathf.Sin(Mathf.Pi * i * 2 / 16);
float x = Mathf.Cos(Mathf.Pi * i * 2 / 16);
_weightDirs[i] = new Vector2(x, y);
}
} }
// Called every frame. 'delta' is the elapsed time since the previous frame. // Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta) public override void _Process(double delta)
{ {
Vector2 pos = GetLocalMousePosition(); _direction = GetDirection();
Vector2 dir = GlobalPosition.DirectionTo(pos);
float dist = GlobalPosition.DistanceSquaredTo(pos);
for (int i = 0; i < 16; i++)
{
float directDot = _weightDirs[i].Dot(dir);
directDot = (directDot + 1) / 2;
// this dot product resembles values of sine rather than cosine
// use it to weigh direction horizontally
Vector2 rotatedDir = new Vector2(-dir.y, dir.x);
float horizDot = Math.Abs(_weightDirs[i].Dot(rotatedDir));
// square so lower values are even lower
horizDot = Mathf.Pow((horizDot + 1) / 2, 2);
// "When will I use math in the real world" Clueful
if (dist > 1024)
{
_weights[i] = directDot;
}
else if (dist > 256)
{
float directDotWeighting = (dist - 256) / 768;
float horizDotWeighting = 1 - directDotWeighting;
_weights[i] = (directDot * directDotWeighting) +
(horizDot * horizDotWeighting);
}
else
{
// shorter than 256
_weights[i] = horizDot;
}
// now we shall subtract weights whose rays collide
// with something
{
}
}
float bestWeight = 0;
for (int i = 0; i < 16; i++)
{
if (_weights[i] > bestWeight)
{
bestWeight = _weights[i];
_bestWeightIdx = i;
}
}
QueueRedraw(); QueueRedraw();
} }
public Vector2 GetDirection()
{
float directWeight;
float strafeWeight;
Vector2 towards = GetGlobalMousePosition() - GlobalPosition;
float dist = towards.Length();
Vector2 directDir = towards.Normalized();
Vector2 strafeDir = directDir.Clockwise90();
// weights approach 1
// dy/dx = 1 - y
// y = 1 - e^(-x)
directWeight = 1 - Mathf.Pow(Mathf.E, -(dist / PreferredDistance));
strafeWeight = 1 - directWeight;
/*
Vector2 midpoint = (strafeDir * strafeWeight)
.Midpoint(directDir * directWeight);
*/
Vector2 midpoint = (directDir * directWeight)
.Midpoint(strafeDir * strafeWeight);
return midpoint.Normalized();
}
public override void _Draw() public override void _Draw()
{ {
for (int i = 0; i < 16; i++) DrawLine(Vector2.Zero, _direction * 256, Colors.Green);
{
Vector2 vec = _weightDirs[i] * _weights[i] * 128;
Color c = Colors.Green;
if (_bestWeightIdx == i)
{
c = Colors.Blue;
}
DrawLine(GlobalPosition, GlobalPosition + vec, c);
}
} }
} }
} }

View File

@ -1,9 +1,13 @@
[gd_scene load_steps=2 format=3 uid="uid://c2d4dmf4yg481"] [gd_scene load_steps=3 format=3 uid="uid://c2d4dmf4yg481"]
[ext_resource type="Script" path="res://Tests/ContextBasedSteering.cs" id="1_g16e3"] [ext_resource type="Script" path="res://Tests/ContextBasedSteering.cs" id="1_g16e3"]
[ext_resource type="Texture2D" uid="uid://bw052v8ikfget" path="res://icon.svg" id="2_cvdwc"]
[node name="ContextBasedSteeringTest" type="Node2D"] [node name="ContextBasedSteeringTest" type="Node2D"]
[node name="ContextBasedSteering" type="Node2D" parent="."] [node name="ContextBasedSteering" type="Node2D" parent="."]
position = Vector2(410, 242) position = Vector2(410, 242)
script = ExtResource("1_g16e3") script = ExtResource("1_g16e3")
[node name="Icon" type="Sprite2D" parent="ContextBasedSteering"]
texture = ExtResource("2_cvdwc")

18
UI/HealthBar.tscn 100644
View File

@ -0,0 +1,18 @@
[gd_scene load_steps=2 format=3 uid="uid://bxo553hblp6nf"]
[ext_resource type="FontFile" uid="uid://cgwa8bjiyv534" path="res://Assets/Fonts/alagard.ttf" id="1_700b8"]
[node name="HealthBar" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ProgressBar" type="ProgressBar" parent="."]
offset_right = 128.0
offset_bottom = 32.0
theme_override_fonts/font = ExtResource("1_700b8")
step = 1.0
value = 84.0

View File

@ -7,7 +7,7 @@ custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter=""
exclude_filter="" exclude_filter=""
export_path="./SupaLidlGame.exe" export_path="Build/SupaLidlGame.exe"
encryption_include_filters="" encryption_include_filters=""
encryption_exclude_filters="" encryption_exclude_filters=""
encrypt_pck=false encrypt_pck=false
@ -45,3 +45,33 @@ application/product_name=""
application/file_description="" application/file_description=""
application/copyright="" application/copyright=""
application/trademarks="" application/trademarks=""
[preset.1]
name="Linux/X11"
platform="Linux/X11"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path=""
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=1
script_encryption_key=""
[preset.1.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_script=1
binary_format/embed_pck=false
texture_format/bptc=false
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
texture_format/no_bptc_fallbacks=true
binary_format/architecture="x86_64"

View File

@ -62,6 +62,13 @@ equip={
] ]
} }
[layer_names]
2d_physics/layer_1="World"
2d_physics/layer_2="Character"
2d_physics/layer_3="Player"
2d_physics/layer_4="NPC"
[physics] [physics]
2d/default_gravity=0.0 2d/default_gravity=0.0