Compare commits

...

22 commits

Author SHA1 Message Date
352535eaa2 version increment 2024-11-09 19:53:38 -05:00
f2fa87dbe9 show hanging mesh if in_cone 2024-11-09 19:53:31 -05:00
5f01f6a0cc highlight box on in_dist 2024-11-09 19:53:11 -05:00
9e9dfdddd3 fix phantom tail bug 2024-11-09 19:52:52 -05:00
745e7ece53 just color shader/mat 2024-11-09 19:52:32 -05:00
509449da84 switch case boxmode 2024-11-09 19:52:14 -05:00
bf66637bce step box mode deltabools 2024-11-09 19:52:02 -05:00
91b3f69bf4 start snake centered 2024-11-09 19:51:05 -05:00
659c30abcf BoxMode data 2024-11-09 19:50:54 -05:00
e31f5e184f hanging mesh update 2024-11-09 19:50:10 -05:00
cb9342d4d2 bug(s) 2024-11-09 19:49:38 -05:00
ca8849818f box held 2024-11-09 01:57:35 -05:00
6fc7e38851 grip btn 2024-11-09 01:52:10 -05:00
b4d0551cb5 mount unmount notes 2024-11-09 01:01:36 -05:00
ea2dfbffd0 intro 2024-11-09 01:01:24 -05:00
eea0d766c8 target audience/experience 2024-11-09 01:00:51 -05:00
eccb2836c2 reprioritize 2024-11-09 00:59:28 -05:00
84f2933c6f version increment 2024-11-09 00:56:05 -05:00
6181e4ae49 false tail 2024-11-08 23:20:49 -05:00
8167ab990b headmove tail move deltabools 2024-11-08 23:20:38 -05:00
41ae92a37e extend clamp caps as needed 2024-11-08 22:40:57 -05:00
6c3b1a2ae0 clamps 2024-11-08 22:38:19 -05:00
9 changed files with 148 additions and 34 deletions

33
Assets/justcolor.hlsl Normal file
View file

@ -0,0 +1,33 @@
#include "stereokit.hlsli"
//--name = dofdev/justcolor
//--color:color = 1, 1, 1, 1
float4 color;
struct vsIn {
float4 pos : SV_Position;
float3 norm : NORMAL0;
};
struct psIn {
float4 pos : SV_POSITION;
float4 color : COLOR0;
uint view_id : SV_RenderTargetArrayIndex;
};
psIn vs(vsIn input, uint id : SV_InstanceID) {
psIn o;
o.view_id = id % sk_view_count;
id = id / sk_view_count;
float3 world = mul(float4(input.pos.xyz, 1), sk_inst[id].world).xyz;
o.pos = mul(float4(world, 1), sk_viewproj[o.view_id]);
float3 normal = normalize(mul(input.norm, (float3x3)sk_inst[id].world));
o.color = color * sk_inst[id].color;
return o;
}
float4 ps(psIn input) : SV_TARGET {
return input.color;
}

BIN
Assets/meshes/assets.glb (Stored with Git LFS)

Binary file not shown.

View file

@ -2,8 +2,8 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dofdev.snake"
android:versionCode="7"
android:versionName="1.07"
android:versionCode="11"
android:versionName="1.15"
android:installLocation="auto"
>
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="32" />

View file

@ -23,9 +23,10 @@ adb shell ip -f inet addr show wlan0
adb connect 192.168.1.219
# publish build
# increment version in Platforms/Android/AndroidManifest.xml
dotnet publish -c Release Projects/Android/snake.Android.csproj
adb install Projects/Android/bin/Release/net7.0-android/com.dofdev.snake-Signed.apk
# adb install Projects/Android/bin/Release/net7.0-android/com.dofdev.snake-Signed.apk
# upload quest
source .env
@ -41,16 +42,30 @@ sdkmanager "platforms;android-33" "build-tools;33.0.0"
```
todo
track steps out of box
if > x then snake get's pulled/slips out of the box
reprioritize beta testing (new user exp)
i want the player to feel clever weighing options to balance risk and reward as they live with their choices(tail)
meaning they should only fail due to their own choices/shortsightedness
*breaking out of the box is sort of like thinking out of the box which give them the feeling of being clever
check to see how far out of box (with some warning)
if (too far out || more segments out of box than in)than slip out of box from gravity
if going up slipping out due to gravity doesn't make sense so
just prevent the snake from going too far up instead (soft pause)?
target audience/experience
~13-18-year-olds who enjoy competitive, skill-based, solo gaming
seated experience on the Meta Quest 3/3S
moderate learning curve
stylized visuals
fun to play daily for a couple weeks or so
start outside of the box (about 6-9 segments long)
snake is moving like normal but is parented to an offset pose that keeps their head centered
so you can easily get a feel for how the snake moves
(sort of like writhing around in zero g)
*dreamlike*
wake up in box
mount/unmount box for orbital_view || handheld || desk/space view
if placed within 15 degree cone of head view then
mount (zero out relative x offset)
bug(s)
food.spawn fails to find a spot and defaults to zero
this means gravity could affect things even when in box
and breaking through the box and coiling up on yourself allows you to fill the space strategically
the food could even be affected by gravity so everything kind of starts of 2d
and 3d feels like an awesome treat/clever trick the user can play rather than an overwhelming paradigm shift
```

View file

@ -10,9 +10,15 @@ static class Arts
static Material mat_mono = new Material("mono.hlsl");
static Material mat_unlit = new Material("unlit.hlsl");
static Material mat_backbox = new Material("backbox.hlsl");
static Material mat_justcolor = new Material("justcolor.hlsl");
static Quat food_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);
public static void Init()
{
foreach (ModelNode node in assets_model.Nodes)
@ -55,7 +61,17 @@ static class Arts
Hierarchy.Push(Mono.box_pose.ToMatrix(Mono.box_scale));
meshes["InsideOut"].Draw(mat_unlit, Matrix.Identity);
meshes["InsideOut"].Draw(mat_backbox, Matrix.Identity);
meshes["Corrugation"].Draw(mat_unlit, Matrix.Identity);
meshes["Corrugation"].Draw(
Mono.in_dist.state ? mat_justcolor : mat_unlit,
Matrix.Identity
);
if (Mono.in_cone.state)
{
meshes["Hanging"].Draw(
mat_unlit,
Matrix.Identity
);
}
if (Mono.menu)
{
meshes["Tape"].Draw(mat_mono, Matrix.Identity);
@ -76,7 +92,7 @@ static class Arts
}
// snake
float snake_t = Maths.smooth_stop((float)Mono.step_t);
float snake_t = headmove.state ? Maths.u_clamp(Maths.smooth_stop((float)Mono.step_t) * 3.0f) : 1.0f;
bool food_next = (Mono.snake[0] + Mono.snake_dir) == Mono.food;
if (!food_next)
{
@ -100,7 +116,7 @@ static class Arts
)
);
for (int i = 1; i < Mono.snake_len - 1; i++)
for (int i = 1; i < Mono.snake_len; i++)
{
float scale = 1.0f;
if ((int)((Time.Total - Mono.eat_timestamp) * Mono.snake_len / Mono.step_step) == i)
@ -116,18 +132,19 @@ static class Arts
)
);
}
// tail
if (Mono.grow_buffer > 0) { snake_t = 0.0f; }
int i_tail = Mono.snake_len - 1;
Vec3 tail_dir = Vec3.Direction(Mono.snake[i_tail - 1].ToVec3, Mono.snake[i_tail].ToVec3);
meshes["Segment"].Draw(
mat_mono,
Matrix.TRS(
Mono.snake[i_tail].ToVec3 + (tail_dir * (float)(snake_t) * 0.7f),
Quat.LookDir(tail_dir),
V.XYZ(1, 1, (float)(1.0 - snake_t))
)
);
// false tail
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(
mat_mono,
Matrix.TRS(
Mono.snake[i_tail].ToVec3 + (tail_dir * (float)(snake_t) * 0.7f),
Quat.LookDir(tail_dir),
V.XYZ(1, 1, (float)(1.0 - snake_t))
)
);
}
// holes
foreach (KeyValuePair<XYZi, XYZi> hole in Mono.holes)
@ -181,4 +198,14 @@ static class Arts
// }
// }
}
public static void Step()
{
XYZi snake_head = Mono.snake[0];
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;
last_tailpos = snake_tail;
}
}

View file

@ -10,8 +10,8 @@ public static class Maths
public static int u_index(int s_index, int s_len) => s_len + s_index;
public static int s_index(int u_index, int u_len) => u_index - u_len;
public static float s_scalar(float u_scalar) => (u_scalar * 2.0f) - 1.0f;
public static float u_scalar(float s_scalar) => (1.0f + s_scalar) * 0.5f;
public static float s_scalar(float u_scalar) => (u_scalar * 2.0f) - 1.0f;
public static int min(int a, int b) => Math.Min(a, b);
public static float min(float a, float b) => Math.Min(a, b);
@ -20,6 +20,11 @@ public static class Maths
public static float max(float a, float b) => Math.Max(a, b);
public static double max(double a, double b) => Math.Max(a, b);
public static float u_clamp(float x, float cap = 1.0f) => min(cap, max(0.0f, x));
public static double u_clamp(double x, double cap = 1.0) => min(cap, max(0.0, x));
public static float s_clamp(float x, float cap = 1.0f) => min(cap, max(-cap, x));
public static double s_clamp(double x, double cap = 1.0) => min(cap, max(-cap, x));
public static int abs(int x) => Math.Abs(x);
public static float abs(float x) => Math.Abs(x);
public static double abs(double x) => Math.Abs(x);

View file

@ -30,11 +30,22 @@ static class Mono
public static XYZi food = new(2, 0, 0);
public static double eat_timestamp = 0.0;
public enum BoxMode
{
Float = -1,
Hold = 0,
Mount = 1,
}
// start mounted & in_cone
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()
{
for (int i = 0; i < snake.Length; i++)
{
snake[i] = new XYZi(0, 1, 0);
snake[i] = new XYZi(0, 0, 0);
}
}
@ -58,7 +69,27 @@ static class Mono
}
else
{
box_pose.position = Rig.head.position + Rig.head.orientation * V.XYZ(0, -(SD_Y + 0.5f) * box_scale, -32 * 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;
in_cone.Step(Vec3.AngleBetween(
Rig.head.orientation * Vec3.Forward,
Vec3.Direction(box_pose.position, Rig.head.position)
) < 15.0f);
switch (box_mode)
{
case BoxMode.Float:
if (pickup) { box_mode = BoxMode.Hold; }
break;
case BoxMode.Hold:
box_pose.position = Rig.r_con_stick.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, -32 * U.cm);
if (pickup) { box_mode = BoxMode.Hold; }
break;
}
}
XYZi next_pos = snake[0] + Rig.new_dir;

View file

@ -52,6 +52,7 @@ class Program
Mono.step_time -= Mono.step_step;
Mono.Step();
Arts.Step();
}
Arts.Frame();

View file

@ -7,6 +7,7 @@ static class Rig
public static Pose head = Pose.Identity;
public static DeltaBool btn_trigger = new(false);
public static DeltaBool btn_grip = new(false);
public static Vec3 fullstick = Vec3.Up;
public static Pose r_con_stick = Pose.Identity;
@ -37,9 +38,10 @@ static class Rig
}
else
{
Hand r_hand = Input.Hand(Handed.Right);
// Hand r_hand = Input.Hand(Handed.Right);
Controller r_con = Input.Controller(Handed.Right);
btn_trigger.Step(r_con.trigger > 0.5f);
btn_grip.Step(r_con.grip > 0.5f);
bool con_tracked = r_con.trackedPos > TrackState.Lost;
Input.HandVisible(Handed.Max, !con_tracked);