Compare commits
4 commits
dd6206c5a0
...
3da9aba2d4
Author | SHA1 | Date | |
---|---|---|---|
3da9aba2d4 | |||
915dca82e5 | |||
caf4608310 | |||
104617e55e |
7 changed files with 114 additions and 617 deletions
|
@ -1,6 +1,6 @@
|
||||||
#include "stereokit.hlsli"
|
#include "stereokit.hlsli"
|
||||||
|
|
||||||
//--name = dofdev/backbox
|
//--name = dofdev/backface
|
||||||
//--color:color = 1, 1, 1, 1
|
//--color:color = 1, 1, 1, 1
|
||||||
|
|
||||||
float4 color;
|
float4 color;
|
281
src/Arts.cs
281
src/Arts.cs
|
@ -9,17 +9,12 @@ static class Arts
|
||||||
static Dictionary<string, Mesh> meshes = new();
|
static Dictionary<string, Mesh> meshes = new();
|
||||||
static Material mat_mono = new Material("mono.hlsl");
|
static Material mat_mono = new Material("mono.hlsl");
|
||||||
static Material mat_unlit = new Material("unlit.hlsl");
|
static Material mat_unlit = new Material("unlit.hlsl");
|
||||||
static Material mat_box = new Material("unlit.hlsl");
|
static Material mat_both = new Material("unlit.hlsl");
|
||||||
static Material mat_backbox = new Material("backbox.hlsl");
|
static Material mat_backface = new Material("backface.hlsl");
|
||||||
static Material mat_justcolor = new Material("justcolor.hlsl");
|
static Material mat_justcolor = new Material("justcolor.hlsl");
|
||||||
|
|
||||||
public static Vec3 box_shake = new(0, 0, 0);
|
public static Vec3 shake = new(0, 0, 0);
|
||||||
static Quat food_ori = Quat.Identity;
|
// static Quat spin_ori = Quat.Identity;
|
||||||
|
|
||||||
static XYZi last_headpos = new(0, 0, 0);
|
|
||||||
static DeltaBool headmove = new(false);
|
|
||||||
static XYZi last_tailpos = new(0, 0, 0);
|
|
||||||
static DeltaBool tailmove = new(false);
|
|
||||||
|
|
||||||
static TextStyle text_style;
|
static TextStyle text_style;
|
||||||
|
|
||||||
|
@ -39,12 +34,12 @@ static class Arts
|
||||||
Color.White
|
Color.White
|
||||||
);
|
);
|
||||||
|
|
||||||
mat_backbox.FaceCull = Cull.Front;
|
mat_backface.FaceCull = Cull.Front;
|
||||||
mat_backbox.Transparency = Transparency.Add;
|
mat_backface.Transparency = Transparency.Add;
|
||||||
mat_backbox.DepthTest = DepthTest.LessOrEq;
|
mat_backface.DepthTest = DepthTest.LessOrEq;
|
||||||
mat_backbox.DepthWrite = false;
|
mat_backface.DepthWrite = false;
|
||||||
|
|
||||||
mat_box.Chain = mat_backbox;
|
mat_both.Chain = mat_backface;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Frame()
|
public static void Frame()
|
||||||
|
@ -57,224 +52,14 @@ static class Arts
|
||||||
// background standin if no passthrough
|
// background standin if no passthrough
|
||||||
}
|
}
|
||||||
|
|
||||||
// fullstick
|
|
||||||
Mesh.Sphere.Draw(
|
|
||||||
mat_unlit,
|
|
||||||
Matrix.TS(
|
|
||||||
Rig.r_con_stick.position,
|
|
||||||
5 * U.mm
|
|
||||||
),
|
|
||||||
Color.White
|
|
||||||
);
|
|
||||||
Lines.Add(
|
|
||||||
Rig.r_con_stick.position + V.XYZ(0, 0, 0),
|
|
||||||
Rig.r_con_stick.position + Rig.fullstick * 1.5f * U.cm,
|
|
||||||
Color.White,
|
|
||||||
2 * U.mm
|
|
||||||
);
|
|
||||||
|
|
||||||
// box
|
|
||||||
box_shake = Vec3.Lerp(box_shake, Vec3.Zero, Time.Stepf / 0.333f);
|
|
||||||
// scale in
|
|
||||||
float box_scale = Mono.box_scale; // Maths.min(Maths.smooth_stop(Maths.u_scalar(Time.Totalf - 3)) * Mono.box_scale, Mono.box_scale);
|
|
||||||
Vec3 box_pos = Mono.box_pose.position + (box_shake * U.cm * 0.333f);
|
|
||||||
Matrix box_m4 = Matrix.TRS(
|
|
||||||
box_pos,
|
|
||||||
Mono.box_pose.orientation,
|
|
||||||
box_scale
|
|
||||||
);
|
|
||||||
|
|
||||||
// hanger
|
|
||||||
if (Mono.in_cone.state && Mono.box_mode == Mono.BoxMode.Hold || Mono.box_mode == Mono.BoxMode.Mount)
|
|
||||||
{
|
|
||||||
float box_head_dist = Vec3.Distance(box_pos, Rig.head.position);
|
|
||||||
Lines.Add(
|
|
||||||
box_m4 * V.XYZ(0, Mono.SD_Y - 0.5f, 0),
|
|
||||||
Rig.head.position + Rig.head.orientation * V.XYZ(0, 6 * U.cm, -box_head_dist),
|
|
||||||
Color.Hex(0x808080FF).ToLinear(),
|
|
||||||
1.0f * U.mm
|
|
||||||
);
|
|
||||||
Lines.Add(
|
|
||||||
Rig.head.position + Rig.head.orientation * V.XYZ(0, 6 * U.cm, -box_head_dist),
|
|
||||||
Rig.head.position + Rig.head.orientation * V.XYZ(0, 6 * U.cm, 0),
|
|
||||||
Color.Hex(0x808080FF).ToLinear(),
|
|
||||||
1.0f * U.mm
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// box contents
|
|
||||||
Hierarchy.Push(box_m4);
|
|
||||||
// meshes["InsideOut"].Draw(mat_unlit, Matrix.Identity);
|
|
||||||
meshes["InsideOut"].Draw(
|
|
||||||
mat_box,
|
|
||||||
Matrix.Identity
|
|
||||||
);
|
|
||||||
meshes["Corrugation"].Draw(
|
|
||||||
Mono.in_dist.state ? mat_justcolor : mat_unlit,
|
|
||||||
Matrix.Identity
|
|
||||||
);
|
|
||||||
if (Mono.menu)
|
|
||||||
{
|
|
||||||
meshes["Tape"].Draw(mat_mono, Matrix.Identity);
|
|
||||||
meshes["uiRestart"].Draw(
|
|
||||||
mat_unlit,
|
|
||||||
Matrix.TR(
|
|
||||||
V.XYZ(-1.333f, 0, Mono.SD_Z - 0.5f + 0.1f),
|
|
||||||
Quat.FromAngles(90, 0, 0)
|
|
||||||
),
|
|
||||||
Color.Hex(0x928CA7FF).ToLinear()
|
|
||||||
);
|
|
||||||
meshes["uiPlay"].Draw(
|
|
||||||
mat_unlit,
|
|
||||||
Matrix.TR(
|
|
||||||
V.XYZ(0, 0, Mono.SD_Z - 0.5f + 0.1f),
|
|
||||||
Quat.FromAngles(90, 0, 0)
|
|
||||||
),
|
|
||||||
Color.Hex(0x333333FF).ToLinear()
|
|
||||||
);
|
|
||||||
meshes["uiConfig"].Draw(
|
|
||||||
mat_unlit,
|
|
||||||
Matrix.TR(
|
|
||||||
V.XYZ(+1.333f, 0, Mono.SD_Z - 0.5f + 0.1f),
|
|
||||||
Quat.FromAngles(90, 0, 0)
|
|
||||||
),
|
|
||||||
Color.Hex(0x928CA7FF).ToLinear()
|
|
||||||
);
|
|
||||||
meshes["uiCursor"].Draw(
|
|
||||||
mat_unlit,
|
|
||||||
Matrix.TR(
|
|
||||||
V.XYZ(0, 0, Mono.SD_Z - 0.5f + 0.2f),
|
|
||||||
Quat.FromAngles(90, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// slash
|
|
||||||
float slash_t = headmove.state ? Maths.u_clamp(Maths.smooth_stop((float)Mono.step_t) * 3.0f) : 1.0f;
|
|
||||||
if (!Mono.menu && !Mono.food_next.state)
|
|
||||||
{
|
|
||||||
meshes["Tongue"].Draw(
|
|
||||||
mat_mono,
|
|
||||||
Matrix.TRS(
|
|
||||||
Mono.slash[0].ToVec3,
|
|
||||||
Quat.LookDir(Rig.fullstick),
|
|
||||||
V.XYZ(1, 1, 0.666f + Maths.smooth_stop((float)Mono.step_t) * 0.333f)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
string face = "Face0Default";
|
|
||||||
face = Mono.grow_buffer > 0 ? "Face2Eaten" : face;
|
|
||||||
face = Mono.in_box.delta != 0 ? "Face3Bump" : face;
|
|
||||||
face = Mono.food_next.state ? "Face1Eat" : face;
|
|
||||||
meshes[face].Draw(
|
|
||||||
mat_mono,
|
|
||||||
Matrix.TRS(
|
|
||||||
Mono.slash[0].ToVec3 - (Mono.slash_dir.ToVec3 * (float)(1.0 - slash_t) * 0.3f),
|
|
||||||
Quat.LookDir(Mono.slash_dir.ToVec3),
|
|
||||||
V.XYZ(1, 1, (float)(slash_t))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
for (int i = 1; i < Mono.slash_len; i++)
|
|
||||||
{
|
|
||||||
float scale = 1.0f;
|
|
||||||
if ((int)((Time.Total - Mono.eat_timestamp) * Mono.slash_len / Mono.step_step) == i)
|
|
||||||
{
|
|
||||||
scale = 1.1f;
|
|
||||||
}
|
|
||||||
meshes["Segment"].Draw(
|
|
||||||
mat_mono,
|
|
||||||
Matrix.TRS(
|
|
||||||
Mono.slash[i].ToVec3,
|
|
||||||
Quat.LookAt(Mono.slash[i].ToVec3, Mono.slash[i - 1].ToVec3),
|
|
||||||
scale
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// false tail
|
|
||||||
if (tailmove.state && slash_t < 1.0f)
|
|
||||||
{
|
|
||||||
int i_tail = Maths.min(Mono.slash_len, Mono.slash.Length - 1);
|
|
||||||
Vec3 tail_dir = Vec3.Direction(Mono.slash[i_tail - 1].ToVec3, Mono.slash[i_tail].ToVec3);
|
|
||||||
meshes["Segment"].Draw(
|
|
||||||
mat_mono,
|
|
||||||
Matrix.TRS(
|
|
||||||
Mono.slash[i_tail].ToVec3 + (tail_dir * (float)(slash_t) * 0.7f),
|
|
||||||
Quat.LookDir(tail_dir),
|
|
||||||
V.XYZ(1, 1, (float)(1.0 - slash_t))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// holes
|
|
||||||
foreach (KeyValuePair<XYZi, XYZi> hole in Mono.holes)
|
|
||||||
{
|
|
||||||
Vec3 hole_normal = V.XYZ(
|
|
||||||
Maths.abs(hole.Value.x) * Maths.sign(hole.Key.x),
|
|
||||||
Maths.abs(hole.Value.y) * Maths.sign(hole.Key.y),
|
|
||||||
Maths.abs(hole.Value.z) * Maths.sign(hole.Key.z)
|
|
||||||
);
|
|
||||||
// Vec3 hole_world_normal = Mono.box_pose.orientation * hole_normal;
|
|
||||||
// Vec3 hole_world = Mono.box_pose.ToMatrix(Mono.box_scale) * V.XYZ(
|
|
||||||
// hole.Key.x - hole.Value.x * 0.5f,
|
|
||||||
// hole.Key.y - hole.Value.y * 0.5f,
|
|
||||||
// hole.Key.z - hole.Value.z * 0.5f
|
|
||||||
// );
|
|
||||||
// Vec3 cam_dir = (Rig.head.orientation * Vec3.Forward);
|
|
||||||
// Vec3 hole_view_dir = Vec3.Direction(hole_world, Rig.head.position);
|
|
||||||
// bool back_hole = Vec3.Dot(hole_world_normal, hole_view_dir) < 0.0;
|
|
||||||
bool hole_flip = Vec3.Dot(hole_normal, hole.Value.ToVec3) < 0.0;
|
|
||||||
|
|
||||||
meshes[hole_flip ? "Hole" : "HoleFlip"].Draw(
|
|
||||||
mat_box,
|
|
||||||
Matrix.TRS(
|
|
||||||
hole.Key.ToVec3,
|
|
||||||
Quat.LookDir(hole.Value.ToVec3),
|
|
||||||
1
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// food
|
|
||||||
if (!Mono.food_next.state)
|
|
||||||
{
|
|
||||||
food_ori *= Quat.FromAngles(
|
|
||||||
90 * Time.Stepf,
|
|
||||||
30 * Time.Stepf,
|
|
||||||
10 * Time.Stepf
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Mono.eaten == 0)
|
|
||||||
{
|
|
||||||
// starting egg
|
|
||||||
bool in_slash = Mono.s_array[new XYZi(0, 0, 0)] > -1;
|
|
||||||
meshes["Egg"].Draw(
|
|
||||||
mat_mono,
|
|
||||||
Matrix.TRS(
|
|
||||||
Vec3.Zero,
|
|
||||||
in_slash ? Quat.Identity : food_ori,
|
|
||||||
in_slash ? 1 : 0.5f
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// food
|
|
||||||
if (!Mono.eaten_latch.state)
|
|
||||||
{
|
|
||||||
float food_t = Mono.eaten_latch.delta == -1 ? Maths.smooth_stop((float)Mono.step_t) : 1;
|
|
||||||
meshes["Food"].Draw(
|
meshes["Food"].Draw(
|
||||||
mat_mono,
|
mat_mono,
|
||||||
Matrix.TRS(
|
Matrix.TRS(
|
||||||
Mono.food.ToVec3,
|
Vec3.Zero,
|
||||||
food_ori,
|
Quat.Identity,
|
||||||
food_t
|
1.0f
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// particles
|
// particles
|
||||||
Particle[] particles = VFX.particles;
|
Particle[] particles = VFX.particles;
|
||||||
|
@ -291,17 +76,18 @@ static class Arts
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// menu
|
||||||
|
Matrix m4_menu = Mono.menu_pose.ToMatrix(Mono.menu_scale);
|
||||||
|
Hierarchy.Push(m4_menu);
|
||||||
|
|
||||||
// score
|
// score
|
||||||
char[] score_txt = Mono.slash_len.ToString("000").ToCharArray();
|
char[] score_txt = Mono.score.ToString("000").ToCharArray();
|
||||||
Quat score_ori = Quat.LookDir(Rig.head.position - Mono.box_pose.position);
|
|
||||||
Vec3 score_pos = score_ori * V.XYZ(0, -Mono.SD_Y - 1.5f, -Mono.SD_Z - 1);
|
|
||||||
for (int i = 0; i < score_txt.Length; i++)
|
for (int i = 0; i < score_txt.Length; i++)
|
||||||
{
|
{
|
||||||
Text.Add(
|
Text.Add(
|
||||||
score_txt[i].ToString(),
|
score_txt[i].ToString(),
|
||||||
Matrix.TRS(
|
Matrix.TS(
|
||||||
score_pos + score_ori * V.XYZ((1 - i) * 0.4f, 0, 0),
|
V.XYZ(0, 0, 0),
|
||||||
score_ori,
|
|
||||||
48
|
48
|
||||||
),
|
),
|
||||||
text_style
|
text_style
|
||||||
|
@ -309,34 +95,5 @@ static class Arts
|
||||||
}
|
}
|
||||||
|
|
||||||
Hierarchy.Pop();
|
Hierarchy.Pop();
|
||||||
|
|
||||||
// for (int sx = -Mono.head_fill.Xslen; Mono.head_fill.InX(sx); sx++)
|
|
||||||
// {
|
|
||||||
// for (int sy = -Mono.head_fill.Yslen; Mono.head_fill.InY(sy); sy++)
|
|
||||||
// {
|
|
||||||
// for (int sz = -Mono.head_fill.Zslen; Mono.head_fill.InZ(sz); sz++)
|
|
||||||
// {
|
|
||||||
// Vec3 pos = Mono.box_pose.ToMatrix(U.cm) * V.XYZ(sx, sy, sz);
|
|
||||||
// Text.Add(
|
|
||||||
// (Mono.head_fill[new XYZi(sx, sy, sz)] + Mono.tail_fill[new XYZi(sx, sy, sz)]).ToString(),
|
|
||||||
// Matrix.TRS(
|
|
||||||
// pos,
|
|
||||||
// Quat.LookAt(pos, Input.Head.position),
|
|
||||||
// 0.1f
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Step()
|
|
||||||
{
|
|
||||||
XYZi slash_head = Mono.slash[0];
|
|
||||||
XYZi slash_tail = Mono.slash[Mono.slash_len - 1];
|
|
||||||
headmove.Step(slash_head != last_headpos);
|
|
||||||
tailmove.Step(slash_tail != last_tailpos);
|
|
||||||
last_headpos = slash_head;
|
|
||||||
last_tailpos = slash_tail;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
49
src/Maths.cs
49
src/Maths.cs
|
@ -45,6 +45,53 @@ public static class Maths
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float lerp(float a, float b, float t) => a + (b - a) * t;
|
public static float lerp(float a, float b, float t) => a + (b - a) * t;
|
||||||
|
|
||||||
|
// directions for moving in the grid
|
||||||
|
public static readonly XYZi[] directions = new XYZi[]
|
||||||
|
{
|
||||||
|
new(-1, 0, 0), // lft
|
||||||
|
new(+1, 0, 0), // rht
|
||||||
|
new(0, -1, 0), // dwn
|
||||||
|
new(0, +1, 0), // up
|
||||||
|
new(0, 0, -1), // fwd
|
||||||
|
new(0, 0, +1), // back
|
||||||
|
};
|
||||||
|
public static readonly XYZi[] corners = new XYZi[]
|
||||||
|
{
|
||||||
|
new(-1, -1, -1),
|
||||||
|
new(-1, -1, +1),
|
||||||
|
new(-1, +1, -1),
|
||||||
|
new(-1, +1, +1),
|
||||||
|
new(+1, -1, -1),
|
||||||
|
new(+1, -1, +1),
|
||||||
|
new(+1, +1, -1),
|
||||||
|
new(+1, +1, +1)
|
||||||
|
};
|
||||||
|
|
||||||
|
public static XYZi InsetCell(XYZi cell)
|
||||||
|
{
|
||||||
|
// [!] don't inset past 0
|
||||||
|
return new(
|
||||||
|
cell.x - Maths.sign(cell.x),
|
||||||
|
cell.y - Maths.sign(cell.y),
|
||||||
|
cell.z - Maths.sign(cell.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] GetShuffledIndices<T>(T[] array)
|
||||||
|
{
|
||||||
|
int[] indices = new int[array.Length];
|
||||||
|
for (int i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
indices[i] = i;
|
||||||
|
}
|
||||||
|
for (int i = indices.Length - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
int j = System.Random.Shared.Next(i + 1);
|
||||||
|
(indices[j], indices[i]) = (indices[i], indices[j]);
|
||||||
|
}
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeltaBool
|
public class DeltaBool
|
||||||
|
@ -101,6 +148,8 @@ public struct XYZi
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> HashCode.Combine(x, y, z);
|
=> HashCode.Combine(x, y, z);
|
||||||
|
|
||||||
|
public static readonly XYZi Zero = new XYZi(0, 0, 0);
|
||||||
|
|
||||||
public StereoKit.Vec3 ToVec3
|
public StereoKit.Vec3 ToVec3
|
||||||
=> StereoKit.V.XYZ(x, y, z);
|
=> StereoKit.V.XYZ(x, y, z);
|
||||||
|
|
||||||
|
|
337
src/Mono.cs
337
src/Mono.cs
|
@ -5,83 +5,47 @@ namespace slash;
|
||||||
|
|
||||||
static class Mono
|
static class Mono
|
||||||
{
|
{
|
||||||
public static double game_time = 0.0;
|
public static double game_time;
|
||||||
public static double step_step = 60.0 / 80; // 80|100|120 bpm
|
|
||||||
public static double step_time = 0.0;
|
|
||||||
public static double step_t = 0.0;
|
|
||||||
|
|
||||||
public static double intro_skip = 0.0;
|
public static int score;
|
||||||
public static bool intro = true; // press to move until x condition or hold to skip
|
|
||||||
public static bool menu = true;
|
|
||||||
|
|
||||||
public static Pose box_pose = new(0, -3 * U.cm, -10 * U.cm);
|
public static DeltaBool menu;
|
||||||
public static float box_dist = 32 * U.cm;
|
public static Pose menu_pose;
|
||||||
public static float box_scale = 1.333f * U.cm;
|
public static float menu_scale;
|
||||||
public const int SD_X = 3, SD_Y = 2, SD_Z = 3;
|
|
||||||
public static SpatialArray<int>
|
|
||||||
box_space = new(SD_X - 1, SD_Y - 1, SD_Z - 1, -1),
|
|
||||||
s_array = new(SD_X, SD_Y, SD_Z, -1),
|
|
||||||
tail_fill = new(SD_X, SD_Y, SD_Z, -1);
|
|
||||||
|
|
||||||
static void update_s_array()
|
public enum Mode
|
||||||
{
|
|
||||||
s_array.Clear(-1);
|
|
||||||
for (int i = 0; i < slash_len; i++)
|
|
||||||
{
|
|
||||||
s_array[slash[i]] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static XYZi[] slash = new XYZi[
|
|
||||||
Maths.u_length(SD_X) * Maths.u_length(SD_Y) * Maths.u_length(SD_Z)
|
|
||||||
];
|
|
||||||
public static int slash_len = 1;
|
|
||||||
public static int grow_buffer = 3;
|
|
||||||
public static XYZi slash_dir = new(0, 0, 1);
|
|
||||||
public static DeltaBool in_box = new(true);
|
|
||||||
public static Dictionary<XYZi, XYZi> holes = new();
|
|
||||||
public static XYZi food = new(0, 0, 0); // [!] start random to keep new game fresh?
|
|
||||||
public static int eaten = 0;
|
|
||||||
public static DeltaBool eaten_latch = new(false);
|
|
||||||
public static DeltaBool food_next = new(false);
|
|
||||||
public static double eat_timestamp = 0.0;
|
|
||||||
|
|
||||||
public enum BoxMode
|
|
||||||
{
|
{
|
||||||
Float = -1,
|
Float = -1,
|
||||||
Hold = 0,
|
Hold = 0,
|
||||||
Mount = 1,
|
Mount = 1,
|
||||||
}
|
}
|
||||||
// start mounted & in_cone
|
public static Mode mode;
|
||||||
public static BoxMode box_mode = BoxMode.Mount;
|
|
||||||
public static DeltaBool in_cone = new(true);
|
|
||||||
public static DeltaBool in_dist = new(false);
|
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < slash.Length; i++)
|
game_time = 0.0;
|
||||||
{
|
menu = new(true);
|
||||||
slash[i] = new XYZi(0, 0, 0);
|
menu_pose = new(0, 0, 0);
|
||||||
}
|
menu_scale = 1 * U.cm;
|
||||||
update_s_array();
|
mode = Mode.Mount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Frame()
|
public static void Frame()
|
||||||
{
|
{
|
||||||
if (Rig.btn_back.delta == +1)
|
if (Rig.btn_back.delta == +1)
|
||||||
{
|
{
|
||||||
menu = !menu;
|
menu.Step(!menu.state);
|
||||||
SFX.click.PlayBox(new XYZi(0, 0, Mono.SD_Z + 1));
|
SFX.click.PlayMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menu)
|
if (menu.state)
|
||||||
{
|
{
|
||||||
// just one btn(resume) in menu rn
|
// just one btn(resume) in menu rn
|
||||||
if (Rig.btn_select.delta == +1)
|
if (Rig.btn_select.delta == +1)
|
||||||
{
|
{
|
||||||
Rig.btn_select.delta = 0; // [!] hacky capture
|
Rig.btn_select.delta = 0; // [!] hacky capture
|
||||||
menu = false;
|
menu.Step(false);
|
||||||
SFX.click.PlayBox(new XYZi(0, 0, Mono.SD_Z + 1));
|
SFX.click.PlayMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,260 +59,33 @@ static class Mono
|
||||||
Quat.FromAngles(0, -sx * 180.0f * Time.Stepf, 0)
|
Quat.FromAngles(0, -sx * 180.0f * Time.Stepf, 0)
|
||||||
);
|
);
|
||||||
// orbital_view
|
// orbital_view
|
||||||
box_pose.position = Input.Head.position + Input.Head.orientation * V.XYZ(0, -0 * U.cm, -10 * U.cm);
|
// box_pose.position = Input.Head.position + Input.Head.orientation * V.XYZ(0, -0 * U.cm, -10 * U.cm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
in_dist.Step(Vec3.Distance(Rig.r_con_stick.position, box_pose.position) < 6 * U.cm);
|
// in_dist.Step(Vec3.Distance(Rig.r_con_stick.position, box_pose.position) < 6 * U.cm);
|
||||||
bool pickup = in_dist.state && Rig.btn_grip.delta == +1;
|
// bool pickup = in_dist.state && Rig.btn_grip.delta == +1;
|
||||||
in_cone.Step(Vec3.AngleBetween(
|
// in_cone.Step(Vec3.AngleBetween(
|
||||||
Rig.head.orientation * Vec3.Forward,
|
// Rig.head.orientation * Vec3.Forward,
|
||||||
Vec3.Direction(box_pose.position, Rig.head.position)
|
// Vec3.Direction(box_pose.position, Rig.head.position)
|
||||||
) < 15.0f);
|
// ) < 15.0f);
|
||||||
switch (box_mode)
|
// switch (mode)
|
||||||
{
|
|
||||||
case BoxMode.Float:
|
|
||||||
if (pickup) { box_mode = BoxMode.Hold; }
|
|
||||||
break;
|
|
||||||
case BoxMode.Hold:
|
|
||||||
box_pose.position = Rig.r_con_stick.position;
|
|
||||||
box_dist = Vec3.Distance(box_pose.position, Rig.head.position);
|
|
||||||
if (Rig.btn_grip.delta == -1) { box_mode = in_cone.state ? BoxMode.Mount : BoxMode.Float; }
|
|
||||||
break;
|
|
||||||
case BoxMode.Mount:
|
|
||||||
// orbital_view
|
|
||||||
box_pose.position = Rig.head.position + Rig.head.orientation * V.XYZ(0, -(SD_Y + 0.5f) * box_scale, -box_dist);
|
|
||||||
if (pickup) { box_mode = BoxMode.Hold; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XYZi next_pos = slash[0] + Rig.new_dir;
|
|
||||||
bool neck_break = next_pos == slash[1];
|
|
||||||
if (!neck_break && !food_next.state)
|
|
||||||
{
|
|
||||||
slash_dir = Rig.new_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
food_next.Step(!Mono.eaten_latch.state && (Mono.slash[0] + Mono.slash_dir) == Mono.food);
|
|
||||||
if (food_next.delta == +1)
|
|
||||||
{
|
|
||||||
SFX.maw.PlayBox(Mono.slash[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Step()
|
|
||||||
{
|
|
||||||
// eat tail
|
|
||||||
if (slash[0] + slash_dir == slash[slash_len - 1])
|
|
||||||
{
|
|
||||||
slash_len--;
|
|
||||||
grow_buffer = 0;
|
|
||||||
}
|
|
||||||
else if (s_array[slash[0] + slash_dir] > -1)
|
|
||||||
{
|
|
||||||
// lose condition
|
|
||||||
bool stuck = true;
|
|
||||||
for (int i = 0; i < directions.Length; i++)
|
|
||||||
{
|
|
||||||
if (s_array[slash[0] + directions[i]] == -1)
|
|
||||||
{
|
|
||||||
stuck = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stuck)
|
|
||||||
{
|
|
||||||
Log.Info("your stuck");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool in_or_around_box = s_array.InRange(slash[0] + slash_dir);
|
|
||||||
if (!in_or_around_box)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eaten_latch.delta != +1)
|
|
||||||
{
|
|
||||||
if (slash_len == slash.Length)
|
|
||||||
{
|
|
||||||
// win condition
|
|
||||||
Log.Info("full slash");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (grow_buffer > 0)
|
|
||||||
{
|
|
||||||
slash_len++;
|
|
||||||
grow_buffer--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// slither
|
|
||||||
for (int i = slash.Length - 1; i > 0; i--)
|
|
||||||
{
|
|
||||||
slash[i] = slash[i - 1];
|
|
||||||
}
|
|
||||||
slash[0] += slash_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
in_box.Step(box_space.InRange(slash[0]));
|
|
||||||
if (in_box.delta != 0) // 1 just in -1 just out
|
|
||||||
{
|
|
||||||
holes.Add(slash[0], slash_dir);
|
|
||||||
SFX.punch_through.PlayBox(slash[0]);
|
|
||||||
Arts.box_shake += slash_dir.ToVec3;
|
|
||||||
}
|
|
||||||
if (holes.ContainsKey(slash[slash_len - 1]))
|
|
||||||
{
|
|
||||||
holes.Remove(slash[slash_len - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_s_array();
|
|
||||||
|
|
||||||
// eat
|
|
||||||
if (!eaten_latch.state)
|
|
||||||
{
|
|
||||||
eaten_latch.Step(food == slash[0]);
|
|
||||||
if (eaten_latch.delta == +1)
|
|
||||||
{
|
|
||||||
eat_timestamp = Time.Total;
|
|
||||||
grow_buffer += 3;
|
|
||||||
eaten++;
|
|
||||||
|
|
||||||
VFX.Play(slash[0]);
|
|
||||||
SFX.crisp_nom.PlayBox(slash[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
(bool viable, XYZi cell) = Feed();
|
|
||||||
eaten_latch.Step(!viable);
|
|
||||||
if (eaten_latch.delta == -1)
|
|
||||||
{
|
|
||||||
food = cell;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static (bool, XYZi) Feed()
|
|
||||||
{
|
|
||||||
// [!] handle out of the box exception on tail
|
|
||||||
// by making the spatial arrays encapsulate the layer outside of the box
|
|
||||||
tail_fill.Clear(-1);
|
|
||||||
Gas(tail_fill, slash[slash_len - 1]);
|
|
||||||
|
|
||||||
// step from head using directions towards the tail
|
|
||||||
// and stop at either 1 cell away from the tail or 5 spaces away from the head
|
|
||||||
bool viable = false;
|
|
||||||
bool viable_step = false;
|
|
||||||
XYZi cell = slash[0];
|
|
||||||
for (int step = 0; step < 5; step++)
|
|
||||||
{
|
|
||||||
viable_step = false;
|
|
||||||
int min_dist = 100;
|
|
||||||
XYZi min_cell = new();
|
|
||||||
int[] dir_indices = GetShuffledIndices(directions);
|
|
||||||
for (int i = 0; i < directions.Length; i++)
|
|
||||||
{
|
|
||||||
XYZi dir = directions[dir_indices[i]];
|
|
||||||
XYZi dir_cell = cell + dir;
|
|
||||||
int tail_dist = tail_fill[dir_cell];
|
|
||||||
if (tail_dist > 1 && tail_dist < min_dist && box_space.InRange(dir_cell))
|
|
||||||
{
|
|
||||||
min_dist = tail_dist;
|
|
||||||
min_cell = dir_cell;
|
|
||||||
viable = true;
|
|
||||||
viable_step = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (viable_step)
|
|
||||||
{
|
|
||||||
tail_fill[min_cell] = -1; // prevent backtracking
|
|
||||||
cell = min_cell;
|
|
||||||
}
|
|
||||||
// if (min_dist <= 1)
|
|
||||||
// {
|
// {
|
||||||
|
// case Mode.Float:
|
||||||
|
// if (pickup) { mode = Mode.Hold; }
|
||||||
|
// break;
|
||||||
|
// case Mode.Hold:
|
||||||
|
// box_pose.position = Rig.r_con_stick.position;
|
||||||
|
// box_dist = Vec3.Distance(box_pose.position, Rig.head.position);
|
||||||
|
// if (Rig.btn_grip.delta == -1) { mode = in_cone.state ? Mode.Mount : Mode.Float; }
|
||||||
|
// break;
|
||||||
|
// case Mode.Mount:
|
||||||
|
// // orbital_view
|
||||||
|
// box_pose.position = Rig.head.position + Rig.head.orientation * V.XYZ(0, -(SD_Y + 0.5f) * box_scale, -box_dist);
|
||||||
|
// if (pickup) { mode = Mode.Hold; }
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return (viable, cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
// space fill algorithm
|
|
||||||
static void Gas(SpatialArray<int> fill_array, XYZi sv)
|
|
||||||
{
|
|
||||||
Queue<XYZi> queue = new Queue<XYZi>();
|
|
||||||
queue.Enqueue(sv);
|
|
||||||
fill_array[sv] = 0;
|
|
||||||
|
|
||||||
while (queue.Count > 0)
|
|
||||||
{
|
|
||||||
XYZi _sv = queue.Dequeue();
|
|
||||||
int currentDistance = fill_array[_sv];
|
|
||||||
|
|
||||||
// check all 6 directions
|
|
||||||
foreach (XYZi dir in directions)
|
|
||||||
{
|
|
||||||
XYZi newV = _sv + dir;
|
|
||||||
|
|
||||||
if (fill_array.InRange(newV) && fill_array[newV] == -1 && s_array[newV] == -1)
|
|
||||||
{
|
|
||||||
fill_array[newV] = currentDistance + 1;
|
|
||||||
queue.Enqueue(newV);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int[] GetShuffledIndices<T>(T[] array)
|
|
||||||
{
|
|
||||||
int[] indices = new int[array.Length];
|
|
||||||
for (int i = 0; i < array.Length; i++)
|
|
||||||
{
|
|
||||||
indices[i] = i;
|
|
||||||
}
|
|
||||||
for (int i = indices.Length - 1; i > 0; i--)
|
|
||||||
{
|
|
||||||
int j = System.Random.Shared.Next(i + 1);
|
|
||||||
(indices[j], indices[i]) = (indices[i], indices[j]);
|
|
||||||
}
|
|
||||||
return indices;
|
|
||||||
}
|
|
||||||
|
|
||||||
// directions for moving in the grid
|
|
||||||
static readonly XYZi[] directions = new XYZi[]
|
|
||||||
{
|
|
||||||
new(-1, 0, 0), // lft
|
|
||||||
new(+1, 0, 0), // rht
|
|
||||||
new(0, -1, 0), // dwn
|
|
||||||
new(0, +1, 0), // up
|
|
||||||
new(0, 0, -1), // fwd
|
|
||||||
new(0, 0, +1), // back
|
|
||||||
};
|
|
||||||
static readonly XYZi[] corners = new XYZi[]
|
|
||||||
{
|
|
||||||
new(-1, -1, -1),
|
|
||||||
new(-1, -1, +1),
|
|
||||||
new(-1, +1, -1),
|
|
||||||
new(-1, +1, +1),
|
|
||||||
new(+1, -1, -1),
|
|
||||||
new(+1, -1, +1),
|
|
||||||
new(+1, +1, -1),
|
|
||||||
new(+1, +1, +1)
|
|
||||||
};
|
|
||||||
|
|
||||||
static XYZi InsetCell(XYZi cell)
|
|
||||||
{
|
|
||||||
// [!] don't inset past 0
|
|
||||||
return new(
|
|
||||||
cell.x - Maths.sign(cell.x),
|
|
||||||
cell.y - Maths.sign(cell.y),
|
|
||||||
cell.z - Maths.sign(cell.z)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,55 +49,9 @@ class Program
|
||||||
// stepper
|
// stepper
|
||||||
// if (Time.Total > 3.0) return; // buffer app loading [!] relace with user prompt to start (spawn box in hand or something)
|
// if (Time.Total > 3.0) return; // buffer app loading [!] relace with user prompt to start (spawn box in hand or something)
|
||||||
|
|
||||||
if (!Mono.menu)
|
if (!Mono.menu.state)
|
||||||
{
|
{
|
||||||
Mono.game_time += Time.Step;
|
Mono.game_time += Time.Step;
|
||||||
if (Mono.intro)
|
|
||||||
{
|
|
||||||
Mono.step_time = Maths.min(Mono.step_time + Time.Step, Mono.step_step);
|
|
||||||
Mono.step_t = Maths.u_clamp(Maths.min(Mono.step_time, Mono.step_step) / Mono.step_step);
|
|
||||||
if (Rig.btn_select.delta == +1)
|
|
||||||
{
|
|
||||||
Mono.step_time = 0.0;
|
|
||||||
Mono.step_t = 0.0;
|
|
||||||
|
|
||||||
Mono.Step();
|
|
||||||
Arts.Step();
|
|
||||||
|
|
||||||
if (Mono.eaten > 0)
|
|
||||||
{
|
|
||||||
Mono.intro = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Rig.btn_select.state)
|
|
||||||
{
|
|
||||||
Mono.intro_skip += Time.Step;
|
|
||||||
if (Mono.intro_skip >= 1.0)
|
|
||||||
{
|
|
||||||
Mono.intro = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Rig.btn_select.delta == -1)
|
|
||||||
{
|
|
||||||
Mono.intro_skip = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Mono.step_time = Maths.min(Mono.step_time + Time.Step, Mono.step_step);
|
|
||||||
Mono.step_t = Maths.u_clamp(Maths.min(Mono.step_time, Mono.step_step) / Mono.step_step);
|
|
||||||
if (Mono.step_time >= Mono.step_step)
|
|
||||||
{
|
|
||||||
Mono.step_time -= Mono.step_step;
|
|
||||||
Mono.step_t = 0.0;
|
|
||||||
|
|
||||||
|
|
||||||
Mono.Step();
|
|
||||||
Arts.Step();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VFX.Frame();
|
VFX.Frame();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ namespace slash;
|
||||||
|
|
||||||
static class SFX
|
static class SFX
|
||||||
{
|
{
|
||||||
public static void PlayBox(this Sound sound, XYZi pos)
|
public static void PlayMenu(this Sound sound)
|
||||||
{
|
{
|
||||||
sound.Play(Mono.box_pose.ToMatrix(Mono.box_scale) * pos.ToVec3);
|
sound.Play(Mono.menu_pose.ToMatrix(Mono.menu_scale) * Vec3.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Sound click = Sound.FromFile("sfx/click.mp3");
|
public static Sound click = Sound.FromFile("sfx/click.mp3");
|
||||||
|
|
|
@ -39,9 +39,9 @@ static class VFX
|
||||||
particle.pos += particle.vel * Time.Stepf;
|
particle.pos += particle.vel * Time.Stepf;
|
||||||
float scl_rad = particle.scl * 0.5f * 0.333f;
|
float scl_rad = particle.scl * 0.5f * 0.333f;
|
||||||
Vec3 next_pos = V.XYZ(
|
Vec3 next_pos = V.XYZ(
|
||||||
Maths.s_clamp(particle.pos.x, Mono.SD_X - 0.5f - scl_rad),
|
Maths.s_clamp(particle.pos.x, 1 - 0.5f - scl_rad),
|
||||||
Maths.s_clamp(particle.pos.y, Mono.SD_Y - 0.5f - scl_rad),
|
Maths.s_clamp(particle.pos.y, 1 - 0.5f - scl_rad),
|
||||||
Maths.s_clamp(particle.pos.z, Mono.SD_Z - 0.5f - scl_rad)
|
Maths.s_clamp(particle.pos.z, 1 - 0.5f - scl_rad)
|
||||||
);
|
);
|
||||||
if (next_pos.x != particle.pos.x || next_pos.y != particle.pos.y || next_pos.z != particle.pos.z)
|
if (next_pos.x != particle.pos.x || next_pos.y != particle.pos.y || next_pos.z != particle.pos.z)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue