Newbie cant generate a chessboard in Godot 3 - c#

I'm new to godot 3.4! My first project is a orthographic chess make. I cant generate the chess board.
I've wrote the following script trying to generate the chessboard:
using Godot;
using System;
public class TileSpawner : Spatial {
[Export] private readonly Material lightSquare;
[Export] private readonly Material darkSquare;
private bool isLight = false;
public override void _Ready() {
Vector2 coordinates = new Vector2(0, 0);
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++) {
coordinates.x = x; coordinates.y = y;
AddChild(MakeTile(coordinates));
}
}
private MeshInstance MakeTile(Vector2 coordinates) {
MeshInstance mesh = new MeshInstance() {
Mesh = new CubeMesh() {
Material = isLight ? lightSquare : darkSquare
}
};
mesh.Translate(new Vector3(-coordinates.x, 0, coordinates.y) + new Vector3(coordinates.x/2, 0, -coordinates.y/2));
mesh.Scale = new Vector3(1.0f, 0.2f, 1.0f);
isLight = !isLight;
return mesh;
}
}
and the result its flickery...
one object overlapping other
so I added this line on the MakeTile function to see the problem clearly:
mesh.Translate(isLight ? Vector3.Up : Vector3.Down);
and got something like this.there's two big block in place small 64 tiles
not sure what's going on. I've been trying to solve this for 4 hours.

#Theraot answer was promising but didn't changed any thing.
My Solution:
Step 1: Create a scene containing the dark and light square mesh.
Step 2: Go Scene(On the top left corner of the screen) > Convert To... > MeshLibrary.
Step 3: Tick the "Merge With Existing" Checkbox and save the file as name.meshlib
Step 4: Create a GridMap on the scene you want your chessboard to be in.
Step 5: Load the name.meshlib on the GridMap Node and attach the following script:
using Godot;
using System;
public class FillWithTile : GridMap {
public override void _Ready() {
Vector2 coordinates = new Vector2(0, 0);
for (int y = -4; y < 4; y++)
for (int x = -4; x < 4; x++) {
coordinates.x = x; coordinates.y = y;
MakeTile(coordinates);
}
}
private void MakeTile(Vector2 coordinates) {
SetCellItem((int)coordinates.x, 0, (int)coordinates.y, (coordinates.x % 2 == 0) != (coordinates.y % 2 == 0)?1:0);
}
}

We are going to make a Transform:
var t = new Transform(
x_axis,
y_axis,
z_axis,
origin
);
So, let us define the components we used there. First for origin I'm going to guess that leaving it zero is fine. You will be able to change it to move the board.
var origin = Vector3.Zero;
And I'm also assuming the axis can be in the usual directions, just scaled:
var x_axis = Vector3.Right;
var y_axis = Vector3.Up * 2.0f;
var z_axis = Vector3.Back;
Alternatively, do you want them rotated? You could do something like this:
var x_axis = (Vector3.Right + Vector3.Back).Normalized();
var y_axis = Vector3.Up * 2.0f;
var z_axis = (Vector3.Back + Vector3.Left).Normalized();
Addendum: The scale is too big. The tiles are taking up the area of four cells. So shrink on the x and z axis by half:
var x_axis = Vector3.Right * 0.5f;
var y_axis = Vector3.Up * 2.0f;
var z_axis = Vector3.Back * 0.5f;
Or for the other case:
var x_axis = (Vector3.Right + Vector3.Back).Normalized() * 0.5f;
var y_axis = Vector3.Up * 2.0f;
var z_axis = (Vector3.Back + Vector3.Left).Normalized() * 0.5f;
Now, do you remember I said this is the Transform?
var t = new Transform(
x_axis,
y_axis,
z_axis,
origin
);
Well, not quite. We are going to displace it according to the coordinates we got, like this:
var t = new Transform(
x_axis,
y_axis,
z_axis,
origin + x_axis * coordinates.x + z_axis * coordinates.y
);
Addendum: I think you need to compensate for halving the scale by doubling the offset here: origin + x_axis * coordinates.x * 2.0f + z_axis * coordinates.y * 2.0f
And set it to the mesh:
mesh.Transform = t;
Addendum: the decision of light vs dark si wrong. It goes by rows and switching, like this:
10101010
10101010
…
Here is an alternative algorithm:
isLight = (((int)coordinates.x) % 2 == 0) != (((int)coordinates.y) % 2 == 0)

Related

Mandelbrot Set function crashes

i made a sim for the Mandelbrot Set function, zn + 1 = power(zn) + c
and it work but when i get to the point were the function is unstable it crashes, now i have a boolen that when true makes a wire that connects all the circles, when its false its fine(dosent crash) but when its on it does, the code works like this:
start:
building a list of circles and making there pos by the equation, and then crating a wire between the circle and the last circle,
update:
then when you move the circle it uses the already made list of gameobj to update there pos.
you can try it here:
build
github:
git
but it crashes:(, heres the code:
private void updateCircles()
{
StartUpdateCircles();
}
private void StartCircles()
{
float x = BlackCircle.anchoredPosition.x;
float y = BlackCircle.anchoredPosition.y;
AllCircles.Add(BlackCircle.gameObject);
for (int i = 1; i < itarations; i++)
{
Vector2 RedCircleVec2 = RedCircle.anchoredPosition;
Vector2 LastCircleVec2 = AllCircles[i - 1].GetComponent<RectTransform>().anchoredPosition;
GameObject Circle = Instantiate(BlackCircle.gameObject, Vector3.zero, Quaternion.identity);
Circle.transform.SetParent(CanvasPerent);
AllCircles.Add(Circle);
x = Mathf.Pow(x, 2);
x -= Mathf.Pow(LastCircleVec2.y, 2);
x += RedCircleVec2.x;
y = (2 * LastCircleVec2.x
* LastCircleVec2.y) + RedCircleVec2.y;
Circle.GetComponent<RectTransform>().anchoredPosition = new Vector2(x, y);
if (HasWire)
{
GameObject wire = GenrateWireStart(LastCircleVec2
, Circle.GetComponent<RectTransform>().anchoredPosition);
AllWires.Add(wire);
}
}
}
private void StartUpdateCircles()
{
float x = BlackCircle.anchoredPosition.x;
float y = BlackCircle.anchoredPosition.y;
for (int i = 1; i < itarations; i++)
{
Vector2 RedCircleVec2 = RedCircle.anchoredPosition;
Vector2 LastCircleVec2 = AllCircles[i - 1].GetComponent<RectTransform>().anchoredPosition;
RectTransform ICircle = AllCircles[i].GetComponent<RectTransform>();
x = Mathf.Pow(x, 2);
x -= Mathf.Pow(LastCircleVec2.y, 2);
x += RedCircleVec2.x;
y = (2 * LastCircleVec2.x
* LastCircleVec2.y) + RedCircleVec2.y;
ICircle.anchoredPosition = new Vector2(x, y);
if (HasWire)
{
GenrateWireUpdate(LastCircleVec2
,ICircle.anchoredPosition, i);
}
}
}
public GameObject GenrateWireStart(Vector2 NodeA, Vector2 NodeB)
{
GameObject Connector = new GameObject("connector", typeof(Image));
Connector.transform.SetParent(CanvasPerent);
RectTransform ConnectorRT = Connector.GetComponent<RectTransform>();
ConnectorRT.anchorMin = new Vector2(0, 0);
ConnectorRT.anchorMax = new Vector2(0, 0);
Connector.GetComponent<Image>().color = new Color(0f, 0f, 0f, 0.25f);
Vector2 dir = (NodeB - NodeA).normalized;
float distance = Vector2.Distance(NodeA, NodeB);
ConnectorRT.sizeDelta = new Vector2(distance, 0.005f);
ConnectorRT.position = NodeA + dir * distance * .5f;
ConnectorRT.localEulerAngles = new Vector3(0, 0, UtilsClass.GetAngleFromVectorFloat(dir));
return Connector;
}
public void GenrateWireUpdate(Vector2 NodeA, Vector2 NodeB, int i)
{
RectTransform ConnectorRT = AllWires[i - 1].GetComponent<RectTransform>();
Vector2 dir = (NodeB - NodeA).normalized;
float distance = Vector2.Distance(NodeA, NodeB);
ConnectorRT.sizeDelta = new Vector2(distance, 0.005f);
ConnectorRT.position = NodeA + dir * distance * .5f;
ConnectorRT.localEulerAngles = new Vector3(0, 0, UtilsClass.GetAngleFromVectorFloat(dir));
}
pls help, thank you.
I looked briefly into your code and you seem to get some invalid positions like infinite / undefined from your calculations or just some positions too far away for Unity.
I could remove these by simply limiting positions to e.g.
x = Mathf.Clamp(Mathf.Pow(x, 2), -Screen.width, Screen.width);
x = Mathf.Clamp(x - Mathf.Pow(LastCircleVec2.y, 2), -Screen.width, Screen.width);
x = Mathf.Clamp(x + RedCircleVec2.x, -Screen.width, Screen.width);
y = Mathf.Clamp((2 * LastCircleVec2.x * LastCircleVec2.y) + RedCircleVec2.y, -Screen.width, Screen.width);
which simply limits all positions to some off-screen max positions

Create a hexagonal grid where I can get the position of the corners

I find a lot of examples of creating a hex grid like the following. But I'm having a hard time understanding how I might have a list of the corners in a hex grid. Basically I'd want a character to move along the line of the grid instead of the center. so I want to grab the position of the next corner in the hex grid and move them there.
I was thinking of using a basic hex grid code to create the prefabs in the right place and then just add empty game objects on each corner of the prefab, but then I have a bunch of overlapping positions that are shared corners for each hexagon. I thought I could delete them if they are overlapping but it just all seems too brute force and hard to keep track of. I'd love to hear some ideas on approaching something like this. By the way I'd also want to know the center of the hex besides knowing the corners.
this code successfully creates a hex grid pattern where I can add a hex shaped game object to instance.
using UnityEngine;
public class Grid : MonoBehaviour
{
public Transform hexPrefab;
public int gridWidth = 11;
public int gridHeight = 11;
float hexWidth = 1.732f;
float hexHeight = 2.0f;
public float gap = 0.0f;
Vector3 startPos;
void Start()
{
AddGap();
CalcStartPos();
CreateGrid();
}
void AddGap()
{
hexWidth += hexWidth * gap;
hexHeight += hexHeight * gap;
}
void CalcStartPos()
{
float offset = 0;
if (gridHeight / 2 % 2 != 0)
offset = hexWidth / 2;
float x = -hexWidth * (gridWidth / 2) - offset;
float z = hexHeight * 0.75f * (gridHeight / 2);
startPos = new Vector3(x, 0, z);
}
Vector3 CalcWorldPos(Vector2 gridPos)
{
float offset = 0;
if (gridPos.y % 2 != 0)
offset = hexWidth / 2;
float x = startPos.x + gridPos.x * hexWidth + offset;
float z = startPos.z - gridPos.y * hexHeight * 0.75f;
return new Vector3(x, 0, z);
}
void CreateGrid()
{
for (int y = 0; y < gridHeight; y++)
{
for (int x = 0; x < gridWidth; x++)
{
Transform hex = Instantiate(hexPrefab) as Transform;
Vector2 gridPos = new Vector2(x, y);
hex.position = CalcWorldPos(gridPos);
hex.parent = this.transform;
hex.name = "Hexagon" + x + "|" + y;
}
}
}
}

Making a hollow voxel cone

I'm trying to create a voxel-style cone shape in C#. I've got the cone building using cubes, but can't work out how to only build the outer layer (make it hollow) rather than build a solid cone as shown in the pic.
The code so far (Edited from someone else's script)
// Create a cone made of cubes. Can be called at runtime
public void MakeVoxelCone()
{
for (int currentLength = 0; currentLength < maxLength; currentLength++)
MakeNewLayer(currentLength);
}
// Make a new layer of cubes on the cone
private void MakeNewLayer(int currentLength)
{
center = new Vector3(0, currentLength, 0);
for (int x = -currentLength; x < currentLength; x++)
{
for (int z = -currentLength; z < currentLength; z++)
{
// Set position to spawn cube
Vector3 pos = new Vector3(x, currentLength, z);
// The distance to the center of the cone at currentLength point
float distanceToMiddle = Vector3.Distance(pos, center);
// Create another layer of the hollow cone
if (distanceToMiddle < currentLength)
{
// Add all cubes to a List array
Cubes.Add(MakeCube(pos));
}
}
}
}
// Create the cube and set its properties
private GameObject MakeCube(Vector3 position)
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.GetComponent<Renderer>().material.color = Color.blue;
if (!AddCollider)
Destroy(cube.GetComponent<BoxCollider>());
cube.transform.position = position;
cube.transform.parent = transform;
cube.name = "cube [" + position.y + "-" + position.x + "," + position.z + "]";
return cube;
}
I think its probably simple, but cant figure it out.
Maybe something about the if (distanceToMiddle < currentLength) part, but swapping < for == breaks the whole shape.
#Jax297 >= (currentLength-1) Closer, but not correct just yet. Now its a pyramid with a cone cut out.
assuming your currentlength is the outer diameter you have to introduce a thickness vareable and compare to currentleght - thickness, so there is a inner diameter to be kept free
(currentLength - thickness) < distanceToMiddle && distanceToMiddle < currentLength
If you want to create a "empty" cone. Try to describe that shape in English first.
Create a circle at height going from 0...h with increasing radius for each step from 0..r
So now you need to find equation of a circle (should take you back to HS trig): sin(theta)^2 + cos(theta)^2 = radius:
Now you want to create this circle while increasing the height.
This will create only the empty cone you wish.
Here's an quick implementation (adjust as needed):
public List<GameObject> instantiatedObjects = new List<GameObject>();
public GameObject rootParent;
public int numOfRows = 10;
public int incrementPerRow = 4;
public float radiusStep = 0.5f;
public float height = 5;
[Button]
public void CreateVoxelCone()
{
// first one. root object.
rootParent = GameObject.CreatePrimitive(PrimitiveType.Cube);
rootParent.name = "Pivot";
rootParent.transform.position = Vector3.zero;
var itemsForThisRow = incrementPerRow;
var heightStep = height / numOfRows;
// for each row...
for (int i = 0; i < numOfRows; i++)
{
// create items in a circle
var radianStep = Mathf.PI * 2 / itemsForThisRow;
for (float j = 0; j < Mathf.PI*2; j=j+radianStep)
{
var newPosition = new Vector3(Mathf.Cos(j) * radiusStep * i, heightStep * i, Mathf.Sin(j) * radiusStep*i);
var point = GameObject.CreatePrimitive(PrimitiveType.Cube);
point.name = ($"Row: {i}, {j}");
point.transform.SetParent(rootParent.transform);
point.transform.localPosition = newPosition;
instantiatedObjects.Add(point);
}
itemsForThisRow += incrementPerRow;
}
}
[Button]
public void CleanUp()
{
DestroyImmediate(rootParent);
}

Generate x amount of points between two points

I have made a line in the following way:
public class MyLineRenderer : MonoBehaviour {
LineRenderer lineRenderer;
public Vector3 p0, p1;
// Use this for initialization
void Start () {
lineRenderer = gameObject.GetComponent<LineRenderer>();
lineRenderer.positionCount = 2;
lineRenderer.SetPosition(0, p0);
lineRenderer.SetPosition(1, p1);
}
}
How can I find, for example, 10 points on the line that are equally spaced from end to the other?
You can use Vector3.Lerp to generate a point between two points. Passing 0.5 to its t parameter will make it give you the middle position between PositionA and PositionB.
To generate multiple points between two points, you just have to use Vector3.Lerp in loop.
Here is a function to do this:
void generatePoints(Vector3 from, Vector3 to, Vector3[] result, int chunkAmount)
{
//divider must be between 0 and 1
float divider = 1f / chunkAmount;
float linear = 0f;
if (chunkAmount == 0)
{
Debug.LogError("chunkAmount Distance must be > 0 instead of " + chunkAmount);
return;
}
if (chunkAmount == 1)
{
result[0] = Vector3.Lerp(from, to, 0.5f); //Return half/middle point
return;
}
for (int i = 0; i < chunkAmount; i++)
{
if (i == 0)
{
linear = divider / 2;
}
else
{
linear += divider; //Add the divider to it to get the next distance
}
// Debug.Log("Loop " + i + ", is " + linear);
result[i] = Vector3.Lerp(from, to, linear);
}
}
USAGE:
//The two positions to generate point between
Vector3 positionA = new Vector3(0, 0, 0);
Vector3 positionB = new Vector3(254, 210, 50);
//The number of points to generate
const int pointsCount = 10;
//Where to store those number of points
private Vector3[] pointsResult;
void Start()
{
pointsResult = new Vector3[pointsCount];
generatePoints(positionA, positionB, pointsResult, pointsCount);
}
The 10 different array points are now stored in the pointsResult variable.
If you want to include the first point of the line renderer in the array, you can do the following:
int amnt = 10; // if you want 10 points
Vector3[] points = new Vector3[amnt]; // your array of points
for (int x = 0; x < amnt; x++)
{
points[x] = new Vector3((p1.x - p0.x) * x / (amnt-1),
(p1.y - p0.y) * x / (amnt-1),
(p1.z - p0.z) * x / (amnt-1)); // we divide by amnt - 1 here because we start at 0
}

Spawning items at sides of a spline

I have just done the Curves and Splines Tutorials from the catlikecoding.com website (http://catlikecoding.com/unity/tutorials/curves-and-splines/) and after finishing it I came up with an idea. I would like to spawn the items from the SplineDecorator at the same distance from the spline at both sides of the spline. I have tried duplicating the for loop and instantiating the newItem twice but at different position but it doenst work as I want to. Here's the Spline Decorator script that takes a spline and then Instantiate some items along the its path
using UnityEngine;
public class SplineDecorator : MonoBehaviour
{
public BezierSpline spline;
public int frequency;
public float distanceBetweenItems;
public bool lookForward;
public Transform[] items;
private void Awake()
{
if (frequency <= 0 || items == null || items.Length == 0)
{
return;
}
float stepSize = 1f / (frequency * items.Length);
for (int p = 0, f = 0; f < frequency; f++)
{
for (int i = 0; i < items.Length; i++, p++)
{
Transform item = Instantiate(items[i]) as Transform;
Vector3 position = spline.GetPoint(p * stepSize);
item.transform.localPosition = new Vector3(position.x + distanceBetweenItems, position.y, position.z);
if (lookForward)
{
item.transform.LookAt(position + spline.GetDirection(p * stepSize));
}
item.transform.parent = transform;
}
}
}
}
You don't define exactly what "at both sides" means to you, so I'm not sure if this is what you're looking for, but maybe this will get you on the right track.
I replaced the inner loop with the following and got a sort of "race track" feel with distanceBetweenItems = 2:
Transform item = Instantiate(items[i]) as Transform;
Transform item2 = Instantiate(items[i]) as Transform;
Vector3 position = spline.GetPoint(p * stepSize);
Vector3 direction = spline.GetDirection(p * stepSize);
Vector3 cross = Vector3.Cross(direction, Vector3.up);
Vector3 delta = cross.normalized * (distanceBetweenItems/2);
item.transform.localPosition = new Vector3(position.x + delta.x, position.y + delta.y, position.z + delta.z);
item2.transform.localPosition = new Vector3(position.x - delta.x, position.y - delta.y, position.z - delta.z);
if (lookForward)
{
item.transform.LookAt( position + spline.GetDirection(p * stepSize));
item2.transform.LookAt(position + spline.GetDirection(p * stepSize));
}
item.transform.parent = transform;
item2.transform.parent = transform;
What I've done here is use Vector3.Cross() (Unity Documentation) to find the line perpendicular to both the spline and Vector3.up. Then I calculate how far along that line to go by normalizing it and multiplying it by half of distanceBetweenItems. (So that, combined, they're distanceBetweenItems apart.)
If you instead wanted something like tracing the wingtips of a plane flying that spline, you'll need to replace the Vector.up above. The simplest way is to replace it with the 'binormal vector', though there are issues with that. This pdf I just found talks a little about it, and might get you on the right path.
(Goofing around, I was able to get a reasonable approximation by replacing the Vector3 cross = ... line with Vector3 cross = Vector3.Cross(direction, direction - spline.GetDirection(p * stepSize + 0.01f));, though it's screwy on sharp bends, non-mirrored vertices, and at the start/end loop.)

Categories