Compare commits
25 commits
6d495d8307
...
134d897e51
Author | SHA1 | Date | |
---|---|---|---|
134d897e51 | |||
6eb4f60b8f | |||
877107a935 | |||
f287485d93 | |||
a27dc1cb53 | |||
8772be83cc | |||
5388e34d61 | |||
3a22e80c2a | |||
04afda9ba9 | |||
59a1cef9af | |||
dce6cf6c14 | |||
5b69e88859 | |||
b6794508f6 | |||
eeafaec61e | |||
23f81af2ed | |||
64e7b2ea2f | |||
4762ebc184 | |||
91b91d9a4f | |||
57970e7c72 | |||
be291f1d37 | |||
a4516dd5d6 | |||
a234c5fd22 | |||
1cc71b113b | |||
35e3a813f2 | |||
94bad62aa6 |
8 changed files with 181 additions and 55 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,6 +7,7 @@ bin/
|
|||
obj/
|
||||
|
||||
Raw/
|
||||
_frames/
|
||||
|
||||
.vscode
|
||||
anchors.txt
|
|
@ -2,8 +2,8 @@
|
|||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.dofdev.snake"
|
||||
android:versionCode="17"
|
||||
android:versionName="1.27"
|
||||
android:versionCode="29"
|
||||
android:versionName="1.32"
|
||||
android:installLocation="auto"
|
||||
>
|
||||
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="32" />
|
||||
|
|
14
readme.md
14
readme.md
|
@ -62,7 +62,7 @@ todo
|
|||
fun to play daily for a couple weeks or so
|
||||
playable with a half engaging vid or conversation in the background
|
||||
|
||||
my tempo
|
||||
my tempo (zen mode *after initial release*)
|
||||
on l_con tap (a) btn to step, and repeatedly to set tempo
|
||||
once a tempo has been set you can stop tapping and you'll coast at that tempo
|
||||
if you tap again it resets the tempo latch, so if you just tapped once it's an easy way to pause
|
||||
|
@ -74,6 +74,18 @@ todo
|
|||
this makes it easier to play alongside a video, as your attention span can drift in and out
|
||||
and you can take tougher parts slower
|
||||
|
||||
user prompt
|
||||
for start and any other times we need to communicate simple instructions to the player
|
||||
|
||||
[!] snake can accidentally cover the menu
|
||||
|
||||
make depth easier to judge
|
||||
pseudo light source is coming from your face (maybe at a diagonal *higher up* angler fish)
|
||||
need some surface detail on the box faces (that fit within the art style)
|
||||
|
||||
benchmark
|
||||
need to be able to play without moving/turning the box
|
||||
|
||||
bug(s)
|
||||
...
|
||||
|
||||
|
|
21
src/Arts.cs
21
src/Arts.cs
|
@ -42,10 +42,12 @@ static class Arts
|
|||
|
||||
public static void Frame()
|
||||
{
|
||||
// background
|
||||
if (Device.DisplayBlend == DisplayBlend.Opaque)
|
||||
bool vr = Device.DisplayBlend == DisplayBlend.Opaque;
|
||||
// render hands if not in mixed reality
|
||||
// Input.HandVisible(Handed.Max, vr);
|
||||
if (vr)
|
||||
{
|
||||
|
||||
// background standin if no passthrough
|
||||
}
|
||||
|
||||
// fullstick
|
||||
|
@ -65,7 +67,9 @@ static class Arts
|
|||
);
|
||||
|
||||
// box
|
||||
Hierarchy.Push(Mono.box_pose.ToMatrix(Mono.box_scale));
|
||||
// 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);
|
||||
Hierarchy.Push(Mono.box_pose.ToMatrix(box_scale));
|
||||
// meshes["InsideOut"].Draw(mat_unlit, Matrix.Identity);
|
||||
meshes["InsideOut"].Draw(
|
||||
mat_box,
|
||||
|
@ -116,7 +120,9 @@ static class Arts
|
|||
);
|
||||
}
|
||||
|
||||
string face = food_next ? "Face1Eat" : "Face0Default";
|
||||
string face = "Face0Default";
|
||||
face = Mono.grow_buffer > 0 ? "Face2Eaten" : face;
|
||||
face = food_next ? "Face1Eat" : face;
|
||||
meshes[face].Draw(
|
||||
mat_mono,
|
||||
Matrix.TRS(
|
||||
|
@ -143,7 +149,8 @@ static class Arts
|
|||
);
|
||||
}
|
||||
// false tail
|
||||
if (tailmove.state && snake_t < 1.0f) {
|
||||
if (tailmove.state && snake_t < 1.0f)
|
||||
{
|
||||
int i_tail = Maths.min(Mono.snake_len, Mono.snake.Length - 1);
|
||||
Vec3 tail_dir = Vec3.Direction(Mono.snake[i_tail - 1].ToVec3, Mono.snake[i_tail].ToVec3);
|
||||
meshes["Segment"].Draw(
|
||||
|
@ -233,7 +240,7 @@ static class Arts
|
|||
public static void Step()
|
||||
{
|
||||
XYZi snake_head = Mono.snake[0];
|
||||
XYZi snake_tail = Mono.snake[Mono.snake_len -1];
|
||||
XYZi snake_tail = Mono.snake[Mono.snake_len - 1];
|
||||
headmove.Step(snake_head != last_headpos);
|
||||
tailmove.Step(snake_tail != last_tailpos);
|
||||
last_headpos = snake_head;
|
||||
|
|
74
src/Mono.cs
74
src/Mono.cs
|
@ -5,17 +5,20 @@ namespace snake;
|
|||
|
||||
static class Mono
|
||||
{
|
||||
public static double game_time = 0.0;
|
||||
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 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 float box_scale = 1.333f * U.cm;
|
||||
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),
|
||||
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);
|
||||
|
||||
|
@ -52,12 +55,21 @@ static class Mono
|
|||
|
||||
public static void Frame()
|
||||
{
|
||||
if (Rig.btn_trigger.delta == +1)
|
||||
if (Rig.btn_back.delta == +1)
|
||||
{
|
||||
menu = !menu;
|
||||
SFX.click.PlayBox(new XYZi(0, 0, Mono.SD_Z + 1));
|
||||
}
|
||||
|
||||
if (menu)
|
||||
{
|
||||
// just one btn(resume) in menu rn
|
||||
if (Rig.btn_select.delta == +1)
|
||||
{
|
||||
menu = false;
|
||||
}
|
||||
}
|
||||
|
||||
// flatscreen dev controls
|
||||
if (Device.Name == "Simulator")
|
||||
{
|
||||
|
@ -107,7 +119,7 @@ static class Mono
|
|||
public static void Step()
|
||||
{
|
||||
// eat tail
|
||||
if (snake[0] + snake_dir == snake[snake_len-1])
|
||||
if (snake[0] + snake_dir == snake[snake_len - 1])
|
||||
{
|
||||
snake_len--;
|
||||
grow_buffer = 0;
|
||||
|
@ -152,14 +164,11 @@ static class Mono
|
|||
}
|
||||
|
||||
// slither
|
||||
if (!menu)
|
||||
for (int i = snake.Length - 1; i > 0; i--)
|
||||
{
|
||||
for (int i = snake.Length - 1; i > 0; i--)
|
||||
{
|
||||
snake[i] = snake[i - 1];
|
||||
}
|
||||
snake[0] += snake_dir;
|
||||
snake[i] = snake[i - 1];
|
||||
}
|
||||
snake[0] += snake_dir;
|
||||
|
||||
in_box.Step(box_space.InRange(snake[0]));
|
||||
if (in_box.delta != 0) // 1 just in -1 just out
|
||||
|
@ -189,7 +198,9 @@ static class Mono
|
|||
|
||||
SFX.crisp_nom.PlayBox(snake[0]);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
(bool viable, XYZi cell) = Feed();
|
||||
eaten_latch.Step(!viable);
|
||||
if (eaten_latch.delta == -1)
|
||||
|
@ -209,9 +220,11 @@ static class Mono
|
|||
// 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 = snake[0];
|
||||
for (int step = 0; step < 5; step++)
|
||||
{
|
||||
viable_step = false;
|
||||
int min_dist = 100;
|
||||
XYZi min_cell = new();
|
||||
int[] dir_indices = GetShuffledIndices(directions);
|
||||
|
@ -225,9 +238,14 @@ static class Mono
|
|||
min_dist = tail_dist;
|
||||
min_cell = dir_cell;
|
||||
viable = true;
|
||||
viable_step = true;
|
||||
}
|
||||
}
|
||||
cell = min_cell;
|
||||
if (viable_step)
|
||||
{
|
||||
tail_fill[min_cell] = -1; // prevent backtracking
|
||||
cell = min_cell;
|
||||
}
|
||||
// if (min_dist <= 1)
|
||||
// {
|
||||
// break;
|
||||
|
@ -249,7 +267,7 @@ static class Mono
|
|||
XYZi _sv = queue.Dequeue();
|
||||
int currentDistance = fill_array[_sv];
|
||||
|
||||
// check all 4 directions
|
||||
// check all 6 directions
|
||||
foreach (XYZi dir in directions)
|
||||
{
|
||||
XYZi newV = _sv + dir;
|
||||
|
@ -273,9 +291,7 @@ static class Mono
|
|||
for (int i = indices.Length - 1; i > 0; i--)
|
||||
{
|
||||
int j = System.Random.Shared.Next(i + 1);
|
||||
int temp = indices[i];
|
||||
indices[i] = indices[j];
|
||||
indices[j] = temp;
|
||||
(indices[j], indices[i]) = (indices[i], indices[j]);
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
@ -283,23 +299,23 @@ static class Mono
|
|||
// directions for moving in the grid
|
||||
static readonly XYZi[] directions = new XYZi[]
|
||||
{
|
||||
new XYZi(-1, 0, 0), // lft
|
||||
new XYZi(+1, 0, 0), // rht
|
||||
new XYZi(0, -1, 0), // dwn
|
||||
new XYZi(0, +1, 0), // up
|
||||
new XYZi(0, 0, -1), // fwd
|
||||
new XYZi(0, 0, +1), // back
|
||||
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 XYZi(-1, -1, -1),
|
||||
new XYZi(-1, -1, +1),
|
||||
new XYZi(-1, +1, -1),
|
||||
new XYZi(-1, +1, +1),
|
||||
new XYZi(+1, -1, -1),
|
||||
new XYZi(+1, -1, +1),
|
||||
new XYZi(+1, +1, -1),
|
||||
new XYZi(+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),
|
||||
new(+1, +1, +1)
|
||||
};
|
||||
|
||||
static XYZi InsetCell(XYZi cell)
|
||||
|
|
|
@ -15,7 +15,7 @@ class Program
|
|||
{
|
||||
appName = "snake",
|
||||
assetsFolder = "Assets",
|
||||
blendPreference = DisplayBlend.Blend,
|
||||
blendPreference = DisplayBlend.AnyTransparent,
|
||||
// overlayApp = true,
|
||||
// overlayPriority = 1,
|
||||
depthMode = DepthMode.D32,
|
||||
|
@ -29,12 +29,16 @@ class Program
|
|||
|
||||
Renderer.Scaling = 2;
|
||||
World.OcclusionEnabled = true;
|
||||
// Device.DisplayBlend = DisplayBlend.Blend;
|
||||
Device.DisplayBlend = DisplayBlend.AnyTransparent;
|
||||
Renderer.EnableSky = false;
|
||||
Renderer.ClearColor = new Color(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
Rig.Init();
|
||||
Mono.Init();
|
||||
Arts.Init();
|
||||
|
||||
VCam.Init();
|
||||
|
||||
// Core application loop
|
||||
SK.Run(() =>
|
||||
{
|
||||
|
@ -42,20 +46,62 @@ class Program
|
|||
Mono.Frame();
|
||||
|
||||
// stepper
|
||||
if (Time.Total > 3.0)
|
||||
{
|
||||
Mono.step_time += Time.Step;
|
||||
Mono.step_t = Maths.min(Mono.step_time, Mono.step_step) / Mono.step_step;
|
||||
}
|
||||
if (Mono.step_time > Mono.step_step)
|
||||
{
|
||||
Mono.step_time -= Mono.step_step;
|
||||
// if (Time.Total > 3.0) return; // buffer app loading [!] relace with user prompt to start (spawn box in hand or something)
|
||||
|
||||
Mono.Step();
|
||||
Arts.Step();
|
||||
if (!Mono.menu)
|
||||
{
|
||||
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.grow_buffer > 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Arts.Frame();
|
||||
|
||||
VCam.Frame();
|
||||
});
|
||||
}
|
||||
}
|
10
src/Rig.cs
10
src/Rig.cs
|
@ -6,8 +6,9 @@ static class Rig
|
|||
{
|
||||
public static Pose head = Pose.Identity;
|
||||
|
||||
public static DeltaBool btn_trigger = new(false);
|
||||
public static DeltaBool btn_select = new(false);
|
||||
public static DeltaBool btn_grip = new(false);
|
||||
public static DeltaBool btn_back = new(false);
|
||||
|
||||
public static Vec3 fullstick = Vec3.Up;
|
||||
public static Pose r_con_stick = Pose.Identity;
|
||||
|
@ -26,7 +27,8 @@ static class Rig
|
|||
// flatscreen dev controls
|
||||
if (Device.Name == "Simulator")
|
||||
{
|
||||
btn_trigger.Step(Input.Key(Key.MouseLeft).IsActive());
|
||||
btn_select.Step(Input.Key(Key.MouseLeft).IsActive());
|
||||
btn_back.Step(Input.Key(Key.MouseRight).IsActive());
|
||||
|
||||
if (Input.Key(Key.A).IsJustActive()) new_dir = new(-1, 0, 0);
|
||||
if (Input.Key(Key.S).IsJustActive()) new_dir = new(+1, 0, 0);
|
||||
|
@ -44,11 +46,11 @@ static class Rig
|
|||
|
||||
bool con_tracked = r_con.trackedPos > TrackState.Lost;
|
||||
// bool hand_tracked = Input.HandSource(Handed.Right) > HandSource.None;
|
||||
Input.HandVisible(Handed.Max, false); // hide hands
|
||||
if (con_tracked)
|
||||
{
|
||||
btn_trigger.Step(r_con.trigger > 0.5f);
|
||||
btn_select.Step(r_con.x1.IsActive() || r_con.trigger > 0.5f);
|
||||
btn_grip.Step(r_con.grip > 0.5f);
|
||||
btn_back.Step(r_con.x2.IsActive());
|
||||
|
||||
Vec2 stick = r_con.stick;
|
||||
Quat stick_rot = Quat.FromAngles(stick.y * -90, 0, stick.x * +90);
|
||||
|
|
42
src/VCam.cs
Normal file
42
src/VCam.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using StereoKit;
|
||||
|
||||
namespace snake;
|
||||
|
||||
static class VCam
|
||||
{
|
||||
// [!] clear directory before recording
|
||||
// or better yet just overwrite and then delete anything that wasn't overwritten at the end
|
||||
// [!] write documentation for making a video
|
||||
// for example a kdenlive project file that is preconfigured for 60fps VP9 transparent webm etc
|
||||
|
||||
public static float t = 0.0f; // use this to stage loops *start by rotating 360 degrees
|
||||
public static int frame_index = 0;
|
||||
public static bool recording = false;
|
||||
public static Pose pose = new(0, 0, 0);
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void Frame()
|
||||
{
|
||||
if (Input.Key(Key.N).IsJustActive())
|
||||
{
|
||||
recording = !recording;
|
||||
}
|
||||
|
||||
pose.position = Input.Head.position;
|
||||
pose.orientation = Input.Head.orientation;
|
||||
if (recording)
|
||||
{
|
||||
frame_index++;
|
||||
Renderer.Screenshot(
|
||||
$"_frames/test_{frame_index:D4}.png",
|
||||
pose,
|
||||
1280,
|
||||
720
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue