// Update is called once per frame void Update() { if (mode == EditableModelMode.Trileset) { return; } if (Input.GetKey(KeyCode.E)) { if (Input.GetMouseButtonDown(0)) { RaycastHit rh; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out rh)) { Vector3 hitPointWorld = rh.point - ((rh.normal / 16 / 2) * 1.1f); IntPos hitPosArray = IntPos.Vector3ToIntPos((hitPointWorld * 16) + Vector3.one * 8); if (hitPosArray.isContained(0, 16)) { if (data.Contains(hitPosArray)) { data.Remove(hitPosArray); } UpdateMesh(); } } } if (Input.GetMouseButtonDown(1)) { RaycastHit rh; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out rh)) { Vector3 hitPointWorld = rh.point + ((rh.normal / 16 / 2) * 1.1f); IntPos hitPosArray = IntPos.Vector3ToIntPos((hitPointWorld * 16) + Vector3.one * 8); if (hitPosArray.isContained(0, 16)) { if (!data.Contains(hitPosArray)) { data.Add(hitPosArray); } UpdateMesh(); } } } } }
private bool _ShowBlockAtPosition(IntPos pos) { bool opResult = false; try { if (_blocks[pos.x, pos.y, pos.z] != (byte)BLOCK_ID.AIR) { _blockArray[pos.x, pos.y, pos.z] = (Instantiate(blockDatabase.GetBlockPrefab(_blocks[pos.x, pos.y, pos.z]), pos.Vec3(), Quaternion.identity)); _blockArray[pos.x, pos.y, pos.z].transform.SetParent(theWorld.transform); opResult = true; } } catch (System.Exception ex) { Debug.Log("Error: PlaceBlock: " + ex.Message); } return(opResult); }
/// <summary> /// Remove a block from the world and replace it with air. Will NOT remove air blocks /// </summary> /// <param name="blockPos"></param> /// <returns> /// true if the operation succeeded /// </returns> public bool RemoveBlock(IntPos blockPos) { bool opResult = false; try { if (_blocks[blockPos.x, blockPos.y, blockPos.z] != (byte)BLOCK_ID.AIR) { // fill with air _blocks[blockPos.x, blockPos.y, blockPos.z] = (byte)BLOCK_ID.AIR; Destroy(_blockArray[blockPos.x, blockPos.y, blockPos.z]); _UpdateBlockNeighborhood(blockPos); opResult = true; } } catch (System.Exception ex) { Debug.Log("Error: RemoveBlock: " + ex.Message); } return(opResult); }
public static bool[,,] GetModelDataFromTrile(Trile trile) { int size = 16; TrixelState[,,] states = new TrixelState[size, size, size]; bool[,,] returnArray = new bool[size, size, size]; Vector3[] dirs = new Vector3[] { Vector3.up, Vector3.down, Vector3.right, Vector3.left, Vector3.forward, Vector3.back }; //Pass 1, put the mesh collider into the array's data. for (int x = -1; x < size + 2; x++) { for (int y = -1; y < size + 2; y++) { for (int z = -1; z < size + 2; z++) { try { states[x, y, z] = TrixelState.Unchecked; } catch { } foreach (Vector3 d in dirs) { Vector3 pos = (((new Vector3(x, y, z) - Vector3.one / 2) / size) - Vector3.one / 2) + importerCollider.transform.position; RaycastHit rh; if (Physics.Raycast(new Ray(pos, d), out rh, 1f / size)) { rh.point -= importerCollider.transform.position; IntPos hitPos = IntPos.Vector3ToIntPos((rh.point * 16) - rh.normal / 2) + (size / 2); try { states[hitPos.x, hitPos.y, hitPos.z] = TrixelState.isCollider; } catch { } } } } } } //Pass 2, check if each trixel exposed to in any of the 6 cardinal directions. for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { for (int z = 0; z < size; z++) { int blockCount = 0; foreach (Vector3 d in dirs) { Vector3 currPos = new Vector3(x, y, z); IntPos currPosInt = new IntPos(x, y, z); bool isBlocked = false; while (currPosInt.isContained(0, size)) { TrixelState getState = states[currPosInt.x, currPosInt.y, currPosInt.z]; if (getState == TrixelState.isCollider || getState == TrixelState.isNotExposedToEdge) { isBlocked = true; break; } currPos += d; currPosInt = IntPos.Vector3ToIntPos(currPos); } if (isBlocked) { blockCount++; } } if (blockCount == 6) { states[x, y, z] = TrixelState.isNotExposedToEdge; } else { states[x, y, z] = TrixelState.isExposedToEdge; } } } } //Pass 3, check if each trixel is exposed to a trixel that's exposed to air. //This is actually done twice, just in case. for (int i = 0; i < 2; i++) { TrixelState[,,] tempStates = new TrixelState[16, 16, 16]; for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { for (int z = 0; z < size; z++) { tempStates[x, y, z] = states[x, y, z]; } } } for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { for (int z = 0; z < size; z++) { if (states[x, y, z] != TrixelState.isNotExposedToEdge) { continue; } bool isBlocked = true; foreach (Vector3 d in dirs) { Vector3 currPos = new Vector3(x, y, z); IntPos currPosInt = new IntPos(x, y, z); while (currPosInt.isContained(0, size)) { TrixelState getState = states[currPosInt.x, currPosInt.y, currPosInt.z]; if (getState == TrixelState.isExposedToEdge) { isBlocked = false; break; } else if (getState == TrixelState.isCollider || getState == TrixelState.isNotExposedToEdge) { break; } currPos += d; currPosInt = IntPos.Vector3ToIntPos(currPos); } if (!isBlocked) { tempStates[x, y, z] = TrixelState.isExposedToEdge; break; } } } } } states = tempStates; } for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { for (int z = 0; z < size; z++) { if (states[x, y, z] == TrixelState.isCollider || states[x, y, z] == TrixelState.isNotExposedToEdge) { returnArray[x, y, z] = true; } else if (states[x, y, z] == TrixelState.isExposedToEdge) { returnArray[x, y, z] = false; } } } } importerCollider.gameObject.SetActive(false); return(returnArray); }
public static float DistanceSqr(IntPos i1, IntPos i2) { return((i1 - i2).sqrMagnitude); }
public RemoveBlockCommand(byte blockTypeAtPosition, IntPos targetPosition) { m_targetPosition = targetPosition; blockTypeToRemove = blockTypeAtPosition; }
public RemoveBlockCommand(Vector3 targetPosition) { m_targetPosition = new IntPos(targetPosition); blockTypeToRemove = s_world.GetBlockID(m_targetPosition); }
public AddBlockCommand(byte placedBlockType, Vector3 targetPosition) { m_targetPosition = new IntPos(targetPosition); blockType = placedBlockType; m_targetOrientation = new IntPos(0, 1, 0); }
public AddBlockCommand(byte placedBlockType, IntPos targetPosition, IntPos targetOrientation) { m_targetPosition = targetPosition; blockType = placedBlockType; m_targetOrientation = targetOrientation; }
// Update is called once per frame void Update() { if (itemsHaveChanged) { _loadItemsFromEquippedList(); itemsHaveChanged = false; } bool raycastHit = false; RaycastHit hit; // only collide raycast with Blocks layer int layerMaskBlocksOnly = LayerMask.GetMask("Blocks"); // Does the ray intersect any objects excluding the player layer if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, m_maxBlockPlacingRange, layerMaskBlocksOnly)) { raycastHit = true; Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow); } else { Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 10, Color.white); } // Input Function if (Input.anyKeyDown) { int numberKey = 0; if (int.TryParse(Input.inputString, out numberKey)) { if ((numberKey > 0) && (numberKey < 8)) { // remap from 1234567890 to 0123456789 (because of keyboard layout) toolbarSlotSelection = (numberKey + 9) % 10; if (activeItems[toolbarSlotSelection].transform.childCount > 0) { string itemName = activeItems[toolbarSlotSelection].transform.GetChild(0).gameObject.name; int bracketIndex = itemName.IndexOf("("); itemName = itemName.Substring(0, bracketIndex); blockTypeSelection = (BLOCK_ID)System.Enum.Parse(typeof(BLOCK_ID), itemName.ToUpper()); _hideSelectors(); selectors[toolbarSlotSelection].SetActive(true); } } } } currentlySelectedBlockUI.text = blockDatabase.GetProperties((BLOCK_ID)blockTypeSelection).m_description; // if selection within range if (raycastHit) { // determine if block place position is too close to the player Vector3 blockPlacePosition = new IntPos((hit.point) + (hit.normal * 0.5f) + new Vector3(0.5f, 0.5f, 0.5f)).Vec3();//(new IntPos(((hit.point) + (hit.normal * 0.1f))).Vec3() + new Vector3(0.5f, 0.5f, 0.5f)); IntPos integerPlacePosition = new IntPos(blockPlacePosition); // position of the block the raycast hit IntPos hitBlockPosition = new IntPos((hit.point) + (hit.normal * -0.5f) + new Vector3(0.5f, 0.5f, 0.5f)); byte hitBlockType = world.GetBlockID(hitBlockPosition); // get all properties of the block the raycast hit BlockProperties hitBlockProperties = blockDatabase.GetProperties((BLOCK_ID)hitBlockType); // show description text for block blockDescriptionUI.text = hitBlockProperties.m_description; // put visible ghost block there and make it visible ghostBlock.transform.position = blockPlacePosition; ghostBlock.gameObject.SetActive(true); { // Debug block selection Debug.DrawRay(blockPlacePosition, new Vector3(0.5f, 0.0f, 0.0f), Color.red); Debug.DrawRay(blockPlacePosition, new Vector3(0.0f, 0.5f, 0.0f), Color.green); Debug.DrawRay(blockPlacePosition, new Vector3(0.0f, 0.0f, 0.5f), Color.blue); Debug.DrawRay(blockPlacePosition, new Vector3(0.0f, -0.5f, 0.0f), Color.yellow); } // Place Block if ((Input.GetButtonDown("PlaceBlock"))) { // determine if block place position is too close to the player if (!ghostBlock.IsColliding() && hitBlockProperties.m_canBePlacedUpon) { Debug.Log("Placing block!"); Command cmd = new AddBlockCommand((byte)blockTypeSelection, integerPlacePosition); if (Execute(ref cmd)) { // send notification that a Block was placed NotifyAll(gameObject, OBSERVER_EVENT.PLACED_BLOCK); } } // endif ghostBlock colliding else { Debug.Log("Cannot place block--Entity is in the way!"); } } // Remove Block if (Input.GetButtonDown("RemoveBlock")) { Debug.Log("Removing block!"); Command cmd = new RemoveBlockCommand(hitBlockType, hitBlockPosition); Execute(ref cmd); } } else // endif raycast hit { ghostBlock.gameObject.SetActive(false); blockDescriptionUI.text = ""; } // Undo Last if (Input.GetButtonDown("Cancel") || Input.GetKeyDown(KeyCode.Backspace)) { if (commandList.Count > 0) { var lastAction = commandList.Last; if (lastAction.Value.IsCompleted()) { lastAction.Value.Undo(); } else { Debug.Log("Could not Undo! Action not completed! Removing uncompleted action"); } commandList.RemoveLast(); } else { Debug.Log("Could not Undo! Nothing to Undo!"); } } }
public void Regenerate(bool fromSavedMap) { if (!fromSavedMap) { RemoveAllBlocksFromWorld(); _blocks = new byte[width, height, depth]; _blockArray = new GameObject[width, height, depth]; MakeAllAir(); float rand = Random.Range(MinPower, MaxPower); float offsetX = Random.Range(-1024.0f, 1024.0f); float offsetY = Random.Range(-1024.0f, 1024.0f); // Generation for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { for (int z = 0; z < depth; z++) { if (y < Mathf.PerlinNoise((x + offsetX) / rand, (z + offsetY) / rand) * height * 0.5) { _blocks[x, y, z] = (byte)Random.Range(1, 3); } } } } } // Private Methods _InstantiateBlocksFromVoxelData(); Vector3 playerSpawnPos = new Vector3(width * 0.5f, height + 10.0f, depth * 0.5f); ball.transform.position = playerSpawnPos + new Vector3(1.0f, -1.0f, 0.0f); tpBuilding.transform.position = playerSpawnPos + new Vector3(0.0f, -4.0f, 0.0f); spawnPoint.transform.position = playerSpawnPos; player.transform.position = spawnPoint.transform.position; // spawn temple IntPos playerPos = new IntPos(player.transform.position); if (!fromSavedMap) { // create platform int spawnPlatformWidth = 3; _GeneratePlatform(playerPos.x, playerPos.z, spawnPlatformWidth, 2, 5, BLOCK_ID.MARBLE); _GeneratePlatform(playerPos.x, playerPos.z, 1, 1, 1, BLOCK_ID.MARBLE); _GenerateColumn(playerPos.x - spawnPlatformWidth, playerPos.z - spawnPlatformWidth); _GenerateColumn(playerPos.x + spawnPlatformWidth, playerPos.z + spawnPlatformWidth); _GenerateColumn(playerPos.x - spawnPlatformWidth, playerPos.z + spawnPlatformWidth); _GenerateColumn(playerPos.x + spawnPlatformWidth, playerPos.z - spawnPlatformWidth); _StackBlockOnSurface(playerPos.x, playerPos.z, (byte)BLOCK_ID.COLUMN_BASE); // create walls around world _GenerateWalls((byte)BLOCK_ID.MARBLE, (uint)height / 2); } }
// update neighboring blocks to a passed position so that Block Gameobjects are spawned only when they can be seen private void _UpdateBlockNeighborhood(IntPos pos) { // if the center block is transparent, then its neighborhood might need to have blocks added to it if (blockDatabase.IsTransparent((BLOCK_ID)_blocks[pos.x, pos.y, pos.z])) { //// x { IntPos newPos = pos; newPos.x += 1; // if there is no gameobject next to it... if (_blockArray[newPos.x, newPos.y, newPos.z] == null) { // fill that gameobject spot with the corresponding block type that should be in that voxel (if it is supposed to be air then PlaceBlock will not place one) _ShowBlockAtPosition(newPos); } } { IntPos newPos = pos; newPos.x -= 1; if (_blockArray[newPos.x, newPos.y, newPos.z] == null) { _ShowBlockAtPosition(newPos); } } //// y { IntPos newPos = pos; newPos.y += 1; if (_blockArray[newPos.x, newPos.y, newPos.z] == null) { _ShowBlockAtPosition(newPos); } } { IntPos newPos = pos; newPos.y -= 1; if (_blockArray[newPos.x, newPos.y, newPos.z] == null) { _ShowBlockAtPosition(newPos); } } //// z { IntPos newPos = pos; newPos.z += 1; if (_blockArray[newPos.x, newPos.y, newPos.z] == null) { _ShowBlockAtPosition(newPos); } } { IntPos newPos = pos; newPos.z -= 1; if (_blockArray[newPos.x, newPos.y, newPos.z] == null) { _ShowBlockAtPosition(newPos); } } } else { // The target block is opaque, therefore some blocks may need to be hidden // TODO: hide blocks that are no longer visible because of an addition of a block on top of it } }
/// <summary> /// Place a block into the world, will NOT place air blocks /// </summary> /// <param name="blockTypeID"></param> /// <param name="blockPos"></param> /// <returns> /// true if the operation succeeded /// </returns> public bool PlaceBlock(byte blockTypeID, IntPos blockPos) { return(PlaceBlock(blockTypeID, blockPos.x, blockPos.y, blockPos.z)); }
public byte GetBlockID(IntPos blockPos) { return(_blocks[blockPos.x, blockPos.y, blockPos.z]); }