snapshot (WIP)
parent
8e0f80c9d6
commit
8c2c33644e
Binary file not shown.
|
@ -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.
|
@ -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
|
|
@ -11,8 +11,7 @@
|
|||
[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"]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_8jbxb"]
|
||||
resource_local_to_scene = true
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ms3xg"]
|
||||
shader = ExtResource("1_fx1w5")
|
||||
shader_parameter/color = null
|
||||
shader_parameter/intensity = 0.0
|
||||
|
@ -103,9 +102,9 @@ _data = {
|
|||
|
||||
[node name="ExampleEnemy" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine")]
|
||||
texture_filter = 3
|
||||
material = SubResource("ShaderMaterial_8jbxb")
|
||||
material = SubResource("ShaderMaterial_ms3xg")
|
||||
y_sort_enabled = true
|
||||
collision_layer = 2
|
||||
collision_layer = 10
|
||||
script = ExtResource("1_2yopk")
|
||||
Health = 50.0
|
||||
Sprite = NodePath("Sprite")
|
||||
|
@ -114,7 +113,6 @@ StateMachine = NodePath("StateMachine")
|
|||
Faction = 2
|
||||
|
||||
[node name="Sprite" type="AnimatedSprite2D" parent="."]
|
||||
use_parent_material = true
|
||||
frames = SubResource("SpriteFrames_4tm2b")
|
||||
animation = &"move"
|
||||
playing = true
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Godot;
|
||||
using SupaLidlGame.Extensions;
|
||||
using SupaLidlGame.Items;
|
||||
using System;
|
||||
|
||||
|
@ -13,15 +14,17 @@ namespace SupaLidlGame.Characters
|
|||
|
||||
public float[] Weights => _weights;
|
||||
|
||||
[Export]
|
||||
public float PreferredDistance { get; protected set; } = 64.0f;
|
||||
|
||||
protected float[] _weights = new float[16];
|
||||
protected Vector2[] _weightDirs = new Vector2[16];
|
||||
protected int _bestWeightIdx;
|
||||
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++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -50,7 +59,7 @@ namespace SupaLidlGame.Characters
|
|||
#if DEBUG
|
||||
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;
|
||||
if (_bestWeightIdx == i)
|
||||
{
|
||||
|
@ -63,6 +72,11 @@ namespace SupaLidlGame.Characters
|
|||
}
|
||||
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
|
||||
|
||||
base._Draw();
|
||||
|
@ -93,48 +107,32 @@ namespace SupaLidlGame.Characters
|
|||
{
|
||||
_thinkTimeElapsed = 0;
|
||||
Think();
|
||||
QueueRedraw();
|
||||
}
|
||||
|
||||
Direction = Target;
|
||||
//Direction = _weightDirs[_bestWeightIdx];
|
||||
//Direction = GetDirection(Target);
|
||||
Direction = _weightDirs[_bestWeightIdx];
|
||||
}
|
||||
|
||||
protected virtual void Think()
|
||||
public void UpdateWeights(Vector2 pos)
|
||||
{
|
||||
Vector2 pos = FindBestTarget().GlobalPosition;
|
||||
Target = pos - GlobalPosition;//GlobalPosition.DirectionTo(pos);
|
||||
// FIXME: TODO: remove all the spaghetti
|
||||
Vector2 dir = Target.Normalized();
|
||||
float dist = GlobalPosition.DistanceSquaredTo(pos);
|
||||
|
||||
if (Target.LengthSquared() < 1024)
|
||||
{
|
||||
if (Inventory.SelectedItem is Weapon weapon)
|
||||
{
|
||||
UseCurrentItem();
|
||||
}
|
||||
}
|
||||
var spaceState = GetWorld2d().DirectSpaceState;
|
||||
var exclude = new Godot.Collections.Array<RID>();
|
||||
exclude.Add(this.GetRid());
|
||||
|
||||
#if DEBUGs
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
float directDot = _weightDirs[i].Dot(dir);
|
||||
// clamp dot from [-1, 1] to [0, 1]
|
||||
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));
|
||||
|
||||
// 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 strafeDot = Math.Abs(_weightDirs[i].Dot(dir.Clockwise90()));
|
||||
float currDirDot = (_weightDirs[i].Dot(Direction) + 1) / 16;
|
||||
|
||||
// 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
|
||||
|
||||
strafeDot = Mathf.Pow((strafeDot + 1) / 2, 2) + currDirDot;
|
||||
|
||||
if (dist > 4096)
|
||||
{
|
||||
|
@ -142,41 +140,35 @@ namespace SupaLidlGame.Characters
|
|||
}
|
||||
else if (dist > 64)
|
||||
{
|
||||
//float directDotWeighting = dist / 4096;
|
||||
//float directDotWeighting = Mathf.Log(dist) / _log1024;
|
||||
float directDotWeighting = Mathf.Sqrt(dist / 4096);
|
||||
float horizDotWeighting = 1 - directDotWeighting;
|
||||
|
||||
_weights[i] = (directDot * directDotWeighting) +
|
||||
(horizDot * horizDotWeighting * 0.5f);
|
||||
float dDotWeight = Mathf.Sqrt(dist / 4096);
|
||||
float sDotWeight = 1 - dDotWeight;
|
||||
_weights[i] = (dDotWeight * directDot) + (sDotWeight * strafeDot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// shorter than 64
|
||||
_weights[i] = horizDot;
|
||||
_weights[i] = strafeDot;
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
Exclude = exclude,
|
||||
CollideWithBodies = true,
|
||||
From = GlobalPosition,
|
||||
To = GlobalPosition + (_weightDirs[i] * 16)
|
||||
To = GlobalPosition + (_weightDirs[i] * 24),
|
||||
CollisionMask = 1 + 8
|
||||
};
|
||||
|
||||
var result = spaceState.IntersectRay(rayParams);
|
||||
|
||||
// if our ray cast hits something
|
||||
// if we hit something
|
||||
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++)
|
||||
{
|
||||
if (i == j)
|
||||
|
@ -185,27 +177,131 @@ namespace SupaLidlGame.Characters
|
|||
}
|
||||
else
|
||||
{
|
||||
float dot = _weightDirs[i].Dot(_weightDirs[j]) / 2;
|
||||
_weights[j] -= (dot + 1) / 2;
|
||||
}
|
||||
float dot = _weightDirs[i].Dot(_weightDirs[j]);
|
||||
_weights[j] -= _weights[j] * dot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float bestWeight = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (_weights[i] > bestWeight)
|
||||
{
|
||||
bestWeight = _weights[i];
|
||||
_bestWeightIdx = i;
|
||||
bestWeight = _weights[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QueueRedraw();
|
||||
#endif
|
||||
public Vector2 GetDirection(Vector2 towards)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"]
|
||||
|
@ -105,19 +105,11 @@ _data = {
|
|||
"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")]
|
||||
texture_filter = 3
|
||||
material = SubResource("ShaderMaterial_h78y7")
|
||||
y_sort_enabled = true
|
||||
collision_layer = 2
|
||||
collision_layer = 6
|
||||
script = ExtResource("1_flygr")
|
||||
Camera = NodePath("Camera2D")
|
||||
Speed = 64.0
|
||||
|
@ -193,9 +185,6 @@ libraries = {
|
|||
"": SubResource("AnimationLibrary_xe5eq")
|
||||
}
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_rs2vs")
|
||||
|
||||
[node name="HurtSound" type="AudioStreamPlayer2D" parent="."]
|
||||
stream = ExtResource("12_h0x0g")
|
||||
|
||||
|
|
|
@ -42,8 +42,6 @@ namespace SupaLidlGame.Characters.State
|
|||
if (Character.Inventory.SelectedItem is not null)
|
||||
{
|
||||
Character.UseCurrentItem();
|
||||
//Character.Inventory.SelectedItem.Use();
|
||||
//return AttackState;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,14 @@ namespace SupaLidlGame.Extensions
|
|||
}
|
||||
|
||||
/// <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>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -141,6 +141,52 @@ tracks/2/keys = {
|
|||
"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"]
|
||||
resource_name = "use2"
|
||||
length = 0.75
|
||||
|
@ -187,52 +233,6 @@ tracks/2/keys = {
|
|||
"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"]
|
||||
resource_name = "use2-npc"
|
||||
length = 0.75
|
||||
|
@ -247,7 +247,7 @@ tracks/0/keys = {
|
|||
"times": PackedFloat32Array(0.05, 0.3, 0.4, 0.45, 0.75),
|
||||
"transitions": PackedFloat32Array(1, 4, 1, 2, 1),
|
||||
"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/imported = false
|
||||
|
|
|
@ -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="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="Shader" path="res://Shaders/Flash.gdshader" id="4_056cf"]
|
||||
|
||||
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_1pa1q"]
|
||||
texture = ExtResource("1_k6myx")
|
||||
|
@ -233,6 +232,7 @@ texture = ExtResource("1_k6myx")
|
|||
7:3/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/polygon_0/points = PackedVector2Array(-8, 2, 8, 2, 8, 12, -8, 12)
|
||||
8:3/0 = 0
|
||||
8:3/0/physics_layer_0/linear_velocity = Vector2(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/physics_layer_0/linear_velocity = Vector2(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/physics_layer_0/linear_velocity = Vector2(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
|
||||
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="TileMap" type="TileMap" parent="."]
|
||||
|
@ -1122,7 +1111,7 @@ tile_set = SubResource("TileSet_18c7j")
|
|||
format = 2
|
||||
layer_0/name = "Walls"
|
||||
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/enabled = true
|
||||
layer_1/modulate = Color(1, 1, 1, 1)
|
||||
|
@ -1150,11 +1139,21 @@ position = Vector2(-81, -34)
|
|||
motion_mode = 1
|
||||
|
||||
[node name="ExampleEnemy" parent="TileMap" instance=ExtResource("2_uti3y")]
|
||||
material = SubResource("ShaderMaterial_whp32")
|
||||
position = Vector2(38, 42)
|
||||
scale = Vector2(1.00571, 1)
|
||||
|
||||
[node name="ExampleEnemy2" parent="TileMap" instance=ExtResource("2_uti3y")]
|
||||
material = SubResource("ShaderMaterial_rthg0")
|
||||
position = Vector2(190, 99)
|
||||
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)
|
||||
|
|
|
@ -1,99 +1,58 @@
|
|||
using Godot;
|
||||
using SupaLidlGame.Extensions;
|
||||
using System;
|
||||
|
||||
namespace SupaLidlGame.Prototyping
|
||||
{
|
||||
public partial class ContextBasedSteering : Node2D
|
||||
{
|
||||
float[] _weights = new float[16];
|
||||
Vector2[] _weightDirs = new Vector2[16];
|
||||
int _bestWeightIdx;
|
||||
public float PreferredDistance { get; set; } = 256.0f;
|
||||
Vector2 _direction;
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
Array.Fill(_weights, 1);
|
||||
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);
|
||||
}
|
||||
GD.Print("Started ContextBasedSteering test");
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
Vector2 pos = GetLocalMousePosition();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
_direction = GetDirection();
|
||||
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()
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
Vector2 vec = _weightDirs[i] * _weights[i] * 128;
|
||||
Color c = Colors.Green;
|
||||
if (_bestWeightIdx == i)
|
||||
{
|
||||
c = Colors.Blue;
|
||||
}
|
||||
DrawLine(GlobalPosition, GlobalPosition + vec, c);
|
||||
}
|
||||
DrawLine(Vector2.Zero, _direction * 256, Colors.Green);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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="Texture2D" uid="uid://bw052v8ikfget" path="res://icon.svg" id="2_cvdwc"]
|
||||
|
||||
[node name="ContextBasedSteeringTest" type="Node2D"]
|
||||
|
||||
[node name="ContextBasedSteering" type="Node2D" parent="."]
|
||||
position = Vector2(410, 242)
|
||||
script = ExtResource("1_g16e3")
|
||||
|
||||
[node name="Icon" type="Sprite2D" parent="ContextBasedSteering"]
|
||||
texture = ExtResource("2_cvdwc")
|
||||
|
|
|
@ -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
|
|
@ -7,7 +7,7 @@ custom_features=""
|
|||
export_filter="all_resources"
|
||||
include_filter=""
|
||||
exclude_filter=""
|
||||
export_path="./SupaLidlGame.exe"
|
||||
export_path="Build/SupaLidlGame.exe"
|
||||
encryption_include_filters=""
|
||||
encryption_exclude_filters=""
|
||||
encrypt_pck=false
|
||||
|
@ -45,3 +45,33 @@ application/product_name=""
|
|||
application/file_description=""
|
||||
application/copyright=""
|
||||
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"
|
||||
|
|
|
@ -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]
|
||||
|
||||
2d/default_gravity=0.0
|
||||
|
|
Loading…
Reference in New Issue