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; } } }