466 lines
No EOL
10 KiB
C#
466 lines
No EOL
10 KiB
C#
using UnityEngine;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using NaughtyAttributes;
|
|
using Random = UnityEngine.Random;
|
|
using ExtensionMethods;
|
|
using UnityEngine.XR;
|
|
|
|
[ExecuteInEditMode]
|
|
public class Monolith : MonoBehaviour
|
|
{
|
|
// Then monolith the pieces (exist
|
|
// = data render and spawn(manual mono -> auto sim)
|
|
// input class fed to sim and render
|
|
// , then move, then impact)
|
|
|
|
public Worm leftWorm, rightWorm;
|
|
|
|
public Piece piece;
|
|
public Piece enemy;
|
|
|
|
public Voxel[] voxels = new Voxel[48];
|
|
public int vIndex = 0;
|
|
|
|
public Simulate simulate = new Simulate();
|
|
public Render render;
|
|
|
|
[Header("References")]
|
|
public Camera cam;
|
|
|
|
void OnEnable()
|
|
{
|
|
render.Enable(this);
|
|
}
|
|
|
|
void OnDisable()
|
|
{
|
|
render.Disable();
|
|
}
|
|
|
|
[Button]
|
|
public void LightPass()
|
|
{
|
|
Lighting.CreateTexture3D();
|
|
}
|
|
|
|
[Button]
|
|
public void Reset()
|
|
{
|
|
voxels = new Voxel[voxels.Length];
|
|
voxels[0] = new Voxel(Vector3Int.zero);
|
|
|
|
leftWorm.pos = rightWorm.pos = Vector3Int.zero;
|
|
leftWorm.dirIndex = rightWorm.dirIndex = 0;
|
|
}
|
|
|
|
[Button]
|
|
public void Step()
|
|
{
|
|
simulate.Step(this);
|
|
}
|
|
|
|
InputDevice headset;
|
|
void Start()
|
|
{
|
|
headset = InputDevices.GetDeviceAtXRNode(XRNode.Head);
|
|
|
|
testPos = piece.pos + Vector3.forward * 0.4f;
|
|
testVel = Vector3.down;
|
|
}
|
|
|
|
Vector3Int Voxelcast(Vector3Int from, Vector3Int step)
|
|
{
|
|
Vector3Int vPos = from;
|
|
int i = 0;
|
|
while (i < 15)
|
|
{
|
|
vPos += step;
|
|
if (!InVoxel(vPos))
|
|
{
|
|
vPos -= step;
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
return vPos;
|
|
}
|
|
|
|
Vector3 testPos;
|
|
Vector3Int voxelPos(Vector3 pos)
|
|
{
|
|
return new Vector3Int(Mathf.RoundToInt(pos.x), Mathf.RoundToInt(pos.y), Mathf.RoundToInt(pos.z));
|
|
}
|
|
public Vector3 testVel;
|
|
float Bound(Vector3 pos, int axis, int dir)
|
|
{
|
|
Vector3Int step = Vector3Int.zero;
|
|
step[axis] = dir;
|
|
|
|
float bound = Mathf.Infinity * dir;
|
|
float closest = Mathf.Infinity;
|
|
for (int i = 0; i < allDirs.Length; i++)
|
|
{
|
|
Vector3 d = (Vector3)allDirs[i] * 0.2f;
|
|
d[axis] = 0;
|
|
Vector3 vPos = Voxelcast(voxelPos(pos + d), step);
|
|
float dist = Mathf.Abs(vPos[axis] - pos[axis]);
|
|
if (dist < closest)
|
|
{
|
|
bound = vPos[axis];
|
|
closest = dist;
|
|
}
|
|
}
|
|
// when hit ?
|
|
return bound + (0.2f * dir);
|
|
}
|
|
|
|
bool InVoxel(Vector3Int pos)
|
|
{
|
|
for (int i = 0; i < voxels.Length; i++)
|
|
{
|
|
if (voxels[i].pos == pos)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool jumpBtn = false;
|
|
|
|
|
|
Vector3 onTouchPos, oldTouchPos;
|
|
Vector2 camAngle = new Vector2(30, 45);
|
|
Vector2 camAngleVel, oldCamAngleVel;
|
|
float delay;
|
|
[ReadOnly]
|
|
public bool movePiece;
|
|
void Update()
|
|
{
|
|
Vector3 mousePos = Input.mousePosition;
|
|
Transform camForm = cam.transform;
|
|
|
|
// orbitcam
|
|
Quaternion headsetRot = Quaternion.identity;
|
|
headset.TryGetFeatureValue(CommonUsages.deviceRotation, out headsetRot);
|
|
if (headsetRot != null)
|
|
{
|
|
camForm.rotation = headsetRot;
|
|
}
|
|
camForm.position = camForm.rotation * Vector3.back * 10;
|
|
|
|
|
|
InputDevice mainCon = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
|
|
Vector2 wasd = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
|
|
Vector2 joystick = Vector2.zero;
|
|
mainCon.TryGetFeatureValue(CommonUsages.primary2DAxis, out joystick);
|
|
|
|
Vector2 input = wasd + joystick;
|
|
|
|
testVel.x += input.x * 6 * Time.deltaTime;
|
|
testVel.z += input.y * 6 * Time.deltaTime;
|
|
|
|
if (input.sqrMagnitude == 0)
|
|
{
|
|
testVel.x *= 1 - (60 * Time.deltaTime);
|
|
testVel.z *= 1 - (60 * Time.deltaTime);
|
|
}
|
|
|
|
mainCon.TryGetFeatureValue(CommonUsages.primaryButton, out jumpBtn);
|
|
if (Input.GetKeyDown(KeyCode.Space) || (jumpBtn && Mathf.Abs(testVel.y) < 0.1f))
|
|
{
|
|
testVel.y = 8;
|
|
}
|
|
|
|
|
|
// holding
|
|
float gravStr = 1;
|
|
if ((!Input.GetKey(KeyCode.Space) && !jumpBtn) || testVel.y < 0)
|
|
{
|
|
gravStr = 3;
|
|
}
|
|
|
|
testVel.y += -9.81f * gravStr * Time.deltaTime;
|
|
testVel = Vector3.ClampMagnitude(testVel, 60);
|
|
|
|
// Graphics.DrawMesh(render.meshPieceDebug,
|
|
// voxelPos(testPos), Quaternion.identity,
|
|
// render.matPieceDebug, 0
|
|
// );
|
|
|
|
// bounds/clamp
|
|
Vector3 toPos = testPos + testVel * Time.deltaTime;
|
|
|
|
int w = 0;
|
|
while (w < 3)
|
|
{
|
|
Vector3 clampPos = new Vector3(
|
|
Mathf.Clamp(toPos.x, Bound(testPos, 0, -1), Bound(testPos, 0, 1)),
|
|
Mathf.Clamp(toPos.y, Bound(testPos, 1, -1), Bound(testPos, 1, 1)),
|
|
Mathf.Clamp(toPos.z, Bound(testPos, 2, -1), Bound(testPos, 2, 1))
|
|
);
|
|
|
|
// find smallest clamp
|
|
// make only that clamp and clamp check again
|
|
// smallest?
|
|
// how'bout largest?
|
|
float largest = 0;
|
|
int largeIndex = -1;
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
float dist = Mathf.Abs(toPos[i] - clampPos[i]);
|
|
if (dist > largest)
|
|
{
|
|
largeIndex = i;
|
|
largest = dist;
|
|
}
|
|
}
|
|
|
|
if (largeIndex > -1)
|
|
{
|
|
toPos[largeIndex] = clampPos[largeIndex];
|
|
testVel[largeIndex] *= -0.25f; // Bounce
|
|
|
|
// UnityEditor.EditorApplication.isPaused = true;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
w++;
|
|
}
|
|
|
|
|
|
|
|
testPos = toPos;
|
|
|
|
Graphics.DrawMesh(render.meshPieceDebug,
|
|
testPos, Quaternion.identity,
|
|
render.matPieceDebug, 0
|
|
);
|
|
|
|
|
|
// for (int i = 0; i < allDirs.Length; i++)
|
|
// {
|
|
// Graphics.DrawMesh(render.meshPieceDebug,
|
|
// testPos + allDirs[i], Quaternion.identity,
|
|
// render.matPieceDebug, 0
|
|
// );
|
|
// }
|
|
|
|
return;
|
|
|
|
// touchPos
|
|
// touchDown
|
|
// touching
|
|
// touchUp
|
|
|
|
if (Input.GetMouseButtonDown(0))
|
|
{
|
|
onTouchPos = mousePos;
|
|
|
|
Vector3 screenCenter = new Vector3(Screen.width / 2, Screen.height / 2, onTouchPos.z);
|
|
movePiece = Vector3.Distance(onTouchPos, screenCenter) < 32;
|
|
}
|
|
|
|
if (movePiece)
|
|
{
|
|
if (Input.GetMouseButtonUp(0) && Vector2.Distance(mousePos, cam.WorldToScreenPoint(piece.pos)) > 32)
|
|
{
|
|
Vector2 inputAngle = mousePos - cam.WorldToScreenPoint(piece.pos);
|
|
float closestAngle = 180;
|
|
int dirIndex = 0;
|
|
for (int i = 0; i < dirs.Length; i++)
|
|
{
|
|
float angle = Vector2.Angle(
|
|
inputAngle,
|
|
cam.WorldToScreenPoint(piece.pos + dirs[i]) - cam.WorldToScreenPoint(piece.pos)
|
|
);
|
|
// pick out of closest available
|
|
if (angle < closestAngle && !Outside(piece.pos + dirs[i]))
|
|
{
|
|
dirIndex = i;
|
|
closestAngle = angle;
|
|
}
|
|
}
|
|
|
|
if (closestAngle < 60)
|
|
{
|
|
while (!Outside(piece.pos))
|
|
{
|
|
piece.pos += dirs[dirIndex];
|
|
}
|
|
piece.pos -= dirs[dirIndex];
|
|
|
|
if (piece.pos == enemy.pos)
|
|
{
|
|
enemy.pos = voxels[Random.Range(0, voxels.Length)].pos;
|
|
}
|
|
}
|
|
|
|
movePiece = false;
|
|
}
|
|
|
|
camAngleVel = Vector2.zero;
|
|
}
|
|
else
|
|
{
|
|
if (Input.GetMouseButton(0))
|
|
{
|
|
Vector3 offset = (mousePos - oldTouchPos) / 3f;
|
|
camAngleVel = new Vector2(-offset.y, offset.x) / Time.deltaTime;
|
|
|
|
if (camAngleVel.sqrMagnitude > 0 || delay < Time.time)
|
|
{
|
|
oldCamAngleVel = camAngleVel;
|
|
delay = Time.time + 0.1f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
camAngleVel *= 1 - (6 * Time.deltaTime);
|
|
}
|
|
|
|
if (Input.GetMouseButtonUp(0))
|
|
{
|
|
camAngleVel = oldCamAngleVel;
|
|
}
|
|
}
|
|
|
|
camAngle += camAngleVel * Time.deltaTime;
|
|
camAngle.x = Mathf.Clamp(camAngle.x, -60f, 60f);
|
|
camForm.rotation = Quaternion.Euler(Vector3.up * camAngle.y) * Quaternion.Euler(Vector3.right * camAngle.x);
|
|
|
|
oldTouchPos = mousePos;
|
|
|
|
// vr chess? infinite dungeon crawler ZENCORE
|
|
// just 3d the movement patterns
|
|
// twist cursor game
|
|
// input is none
|
|
// simulate is monolithed entirely
|
|
// part of simulate is to generate the level
|
|
|
|
|
|
// pathing needs a refactor
|
|
// we learned quite a bit
|
|
// what paths are interesting in 3D?
|
|
// build for that, don't just translate chess movement patterns
|
|
|
|
// chess takeaways
|
|
// long shots from well placed pieces
|
|
// hook shots from knights
|
|
|
|
// consider gravities constraints
|
|
// fall | cling walls | cling ceiling
|
|
// jump | climb fly |
|
|
|
|
// what do I want to do?
|
|
|
|
camPivot = render.lerpPos;
|
|
camForm.position = camPivot + Quaternion.LookRotation(camForm.rotation * Vector3.forward) * Vector3.back * 24;
|
|
}
|
|
|
|
Vector3 camPivot;
|
|
|
|
[HideInInspector]
|
|
public Vector3Int[] dirs = new Vector3Int[] {
|
|
new Vector3Int(-1, 0, 0), new Vector3Int(0, -1, 0), new Vector3Int(0, 0, -1),
|
|
new Vector3Int(1, 0, 0), new Vector3Int(0, 1, 0), new Vector3Int(0, 0, 1)
|
|
};
|
|
|
|
[HideInInspector]
|
|
public Vector3Int[] allDirs = new Vector3Int[] {
|
|
new Vector3Int(-1, 0, 0),
|
|
new Vector3Int(0, -1, 0),
|
|
new Vector3Int(0, 0, -1),
|
|
new Vector3Int(-1, -1, 0),
|
|
new Vector3Int(0, -1, -1),
|
|
new Vector3Int(-1, 0, -1),
|
|
|
|
new Vector3Int(1, 0, 0),
|
|
new Vector3Int(0, 1, 0),
|
|
new Vector3Int(0, 0, 1),
|
|
new Vector3Int(1, 1, 0),
|
|
new Vector3Int(0, 1, 1),
|
|
new Vector3Int(1, 0, 1),
|
|
|
|
new Vector3Int(-1, 1, 0),
|
|
new Vector3Int(0, -1, 1),
|
|
new Vector3Int(1, 0, -1),
|
|
new Vector3Int(1, -1, 0),
|
|
new Vector3Int(0, 1, -1),
|
|
new Vector3Int(-1, 0, 1)
|
|
};
|
|
|
|
public bool Outside(Vector3Int pos)
|
|
{
|
|
for (int v = 0; v < voxels.Length; v++)
|
|
{
|
|
if (pos == voxels[v].pos) { return false; }
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class Voxel
|
|
{
|
|
public Vector3Int pos;
|
|
|
|
public Voxel(Vector3Int pos)
|
|
{
|
|
this.pos = pos;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class Worm
|
|
{
|
|
public Vector3Int pos;
|
|
public int dirIndex;
|
|
|
|
public Worm(Vector3Int pos)
|
|
{
|
|
this.pos = pos;
|
|
this.dirIndex = 0;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class Piece
|
|
{
|
|
public Vector3Int pos;
|
|
public int[] pattern;
|
|
// a pattern is the change in dirIndex at x Step
|
|
// cant be a dir change at zero
|
|
|
|
public Piece(Vector3Int pos)
|
|
{
|
|
this.pos = pos;
|
|
}
|
|
}
|
|
|
|
namespace ExtensionMethods
|
|
{
|
|
public static class MyExtensions
|
|
{
|
|
public static int Rollover(this int index, int by, int length)
|
|
{
|
|
int rollover = index + by;
|
|
int delta = rollover - length;
|
|
if (delta >= 0)
|
|
{
|
|
rollover = delta;
|
|
}
|
|
|
|
return rollover;
|
|
}
|
|
}
|
|
} |