144 lines
5.3 KiB
C#
144 lines
5.3 KiB
C#
using Godot;
|
|
|
|
public partial class PropShop : Node3D
|
|
{
|
|
private struct PropSpec
|
|
{
|
|
public string Name;
|
|
public float Radius;
|
|
public Vector3 Box;
|
|
public float Mass;
|
|
public float Bounce;
|
|
public float Friction;
|
|
public Color Color;
|
|
public Vector3 Position;
|
|
}
|
|
|
|
private static readonly PropSpec[] Specs =
|
|
{
|
|
new() { Name = "Ping pong · 2.7 g", Radius = 0.02f, Mass = 0.0027f, Bounce = 0.9f, Friction = 0.3f, Color = new(1f, 1f, 1f), Position = new(-0.5f, 0.78f, -0.55f) },
|
|
new() { Name = "Bouncy ball · 50 g", Radius = 0.03f, Mass = 0.05f, Bounce = 0.85f, Friction = 0.4f, Color = new(1f, 0.4f, 0.7f), Position = new(-0.3f, 0.79f, -0.45f) },
|
|
new() { Name = "Apple · 150 g", Radius = 0.045f, Mass = 0.15f, Bounce = 0.3f, Friction = 0.6f, Color = new(0.85f, 0.15f, 0.1f), Position = new(-0.08f, 0.81f, -0.55f) },
|
|
new() { Name = "Crate · 2 kg", Box = new(0.16f, 0.16f, 0.16f), Mass = 2f, Bounce = 0.1f, Friction = 0.8f, Color = new(0.7f, 0.5f, 0.25f), Position = new(0.18f, 0.84f, -0.5f) },
|
|
new() { Name = "Brick · 3.5 kg", Box = new(0.2f, 0.06f, 0.095f), Mass = 3.5f, Bounce = 0.05f, Friction = 0.9f, Color = new(0.6f, 0.3f, 0.2f), Position = new(-0.32f, 0.79f, -0.25f) },
|
|
new() { Name = "Bowling ball · 7.2 kg", Radius = 0.11f, Mass = 7.2f, Bounce = 0.1f, Friction = 0.5f, Color = new(0.1f, 0.2f, 0.5f), Position = new(0.05f, 0.87f, -0.25f) },
|
|
new() { Name = "Anvil · 50 kg", Box = new(0.28f, 0.16f, 0.13f), Mass = 50f, Bounce = 0f, Friction = 0.95f, Color = new(0.25f, 0.25f, 0.28f), Position = new(0.38f, 0.84f, -0.35f) },
|
|
};
|
|
|
|
public override void _Ready()
|
|
{
|
|
BuildTable();
|
|
foreach (PropSpec spec in Specs)
|
|
SpawnProp(spec);
|
|
}
|
|
|
|
public void Respawn()
|
|
{
|
|
foreach (Node node in GetTree().GetNodesInGroup("prop"))
|
|
node.QueueFree();
|
|
foreach (PropSpec spec in Specs)
|
|
SpawnProp(spec);
|
|
GD.Print("PropShop: table reset");
|
|
}
|
|
|
|
private void BuildTable()
|
|
{
|
|
Color wood = new(0.45f, 0.3f, 0.18f);
|
|
StaticBody3D table = new();
|
|
table.CollisionMask = 0b1101; // world + player body + hands
|
|
table.AddChild(new CollisionShape3D
|
|
{
|
|
Position = new Vector3(0, 0.725f, -0.6f),
|
|
Shape = new BoxShape3D { Size = new Vector3(1.4f, 0.05f, 0.8f) },
|
|
});
|
|
MeshInstance3D top = new()
|
|
{
|
|
Position = new Vector3(0, 0.725f, -0.6f),
|
|
Mesh = new BoxMesh { Size = new Vector3(1.4f, 0.05f, 0.8f) },
|
|
};
|
|
top.SetSurfaceOverrideMaterial(0, MakeMaterial(wood));
|
|
table.AddChild(top);
|
|
|
|
Vector3[] legOffsets =
|
|
{
|
|
new(-0.62f, 0, 0.32f),
|
|
new(0.62f, 0, 0.32f),
|
|
new(-0.62f, 0, -0.32f),
|
|
new(0.62f, 0, -0.32f),
|
|
};
|
|
foreach (Vector3 offset in legOffsets)
|
|
{
|
|
Vector3 pos = new(offset.X, 0.3625f, -0.6f + offset.Z);
|
|
table.AddChild(new CollisionShape3D
|
|
{
|
|
Position = pos,
|
|
Shape = new BoxShape3D { Size = new Vector3(0.06f, 0.725f, 0.06f) },
|
|
});
|
|
MeshInstance3D leg = new()
|
|
{
|
|
Position = pos,
|
|
Mesh = new BoxMesh { Size = new Vector3(0.06f, 0.725f, 0.06f) },
|
|
};
|
|
leg.SetSurfaceOverrideMaterial(0, MakeMaterial(wood * 0.8f));
|
|
table.AddChild(leg);
|
|
}
|
|
AddChild(table);
|
|
}
|
|
|
|
private void SpawnProp(PropSpec spec)
|
|
{
|
|
RigidBody3D body = new()
|
|
{
|
|
Name = spec.Name,
|
|
Mass = spec.Mass,
|
|
Position = spec.Position,
|
|
PhysicsMaterialOverride = new PhysicsMaterial { Bounce = spec.Bounce, Friction = spec.Friction },
|
|
ContinuousCd = spec.Mass < 0.1f,
|
|
ContactMonitor = true,
|
|
MaxContactsReported = 4,
|
|
CollisionMask = 0b1101, // world + player body + hands
|
|
};
|
|
body.AddToGroup("prop");
|
|
|
|
if (spec.Radius > 0f)
|
|
{
|
|
body.AddChild(new CollisionShape3D { Shape = new SphereShape3D { Radius = spec.Radius } });
|
|
MeshInstance3D mesh = new()
|
|
{
|
|
Mesh = new SphereMesh { Radius = spec.Radius, Height = spec.Radius * 2f },
|
|
};
|
|
mesh.SetSurfaceOverrideMaterial(0, MakeMaterial(spec.Color));
|
|
body.AddChild(mesh);
|
|
}
|
|
else
|
|
{
|
|
body.AddChild(new CollisionShape3D { Shape = new BoxShape3D { Size = spec.Box } });
|
|
MeshInstance3D mesh = new()
|
|
{
|
|
Mesh = new BoxMesh { Size = spec.Box },
|
|
};
|
|
mesh.SetSurfaceOverrideMaterial(0, MakeMaterial(spec.Color));
|
|
body.AddChild(mesh);
|
|
}
|
|
|
|
float halfHeight = spec.Radius > 0f ? spec.Radius : spec.Box.Y * 0.5f;
|
|
body.AddChild(new Label3D
|
|
{
|
|
Text = spec.Name,
|
|
FontSize = 64,
|
|
PixelSize = 0.0004f,
|
|
OutlineSize = 8,
|
|
Billboard = BaseMaterial3D.BillboardModeEnum.Enabled,
|
|
Position = new Vector3(0, halfHeight + 0.1f, 0),
|
|
});
|
|
|
|
AddChild(body);
|
|
}
|
|
|
|
private static StandardMaterial3D MakeMaterial(Color color) => new()
|
|
{
|
|
AlbedoColor = color,
|
|
Roughness = 0.7f,
|
|
};
|
|
}
|