How would I turn the machines? [CONCEPT HELP]

Firstly, I will quickly explain how my game would work.

You can place machines and conveyors and connect them to move stuff around and process them. What you can do when placing the machines is rotate them (I’m not inventing the wheel)

How I would try to do it is have a table of all the space grid.
For example purposes, X is an occupied spaces by the machine, O is a free space and P is the placing point and from where it rotates

{O, O, O, O, O,
O, O, O, O, O,
O, O, O, O, O, means that every space is empty and unoccupied, so you can
O, O, O, O, O, place anything anywhere basically.
O, O, O, O, O}

Now, I have a table of every machine’s space in a module like that

{X, O, X,
X, P, X}

The checks for collision and things like that should be easy, I know what to do. What I’m worried about is how to rotate it from the placing point. (P if you have paid attention)

Going from this:

{O, O, O, O, O,
O, X, O, X, O
O, X, P, X, O
O, O, O, O, O,
O, O, O, O, O}

To this:

{O, O, O, O, O,
O, O, X, X, O,
O, O, P, O, O,
O, O, X, X, O,
O, O, O, O, O}

So, how would I go around to doing that? Should I just make 4 variations of every machines for every 90 degree turns or is there some clever code?

If you want more information about how I’m gonna do it to help the issue further, I can share more information about the details.

Any response is appreciated because last time I had no real answers. Thanks again! :boom:

1 Like

there’s probably a mathematical way to do this but my go-to idea would be to use the rotation to change the “front” face and have every attached tile be offset based on the “front” face, so if a tile is always 1 left relative to the front face it will keep it’s rotation if you rotate the front face 180 degrees

I don’t understand what you mean. In English please?

here I’ll just write some psuedocode

local xAxis = Vector2.new(0, 1)
local yAxis = Vector2.new(1, 0)
local otherPositions = {...}

function whenIWantToPlaceThis()
    for _, otherPosition in otherPositions do
        actualPos = xAxis * otherPosition.X + yAxis * otherPosition.Y
    end
end

there’s definitely a way to only declare one lookVector and convert it to x and y components but I can’t think of it off the top of my head. Since there’s only 4 possible rotations it’s definitely more than possible to simply make it cycle through all 4 predefined directions as well

Thanks for the reply.

Although it can be good for general purpose building games (with simple patterns, like 1x1x1 or 2x1x1, for example), I want to be able to make almost any shape possible. That’s why I put a complicated shape in my question (a U with the placement position at the bottom middle).

I thought of an idea, you can tell me if it has potential or if I’m wasting my time. Basically, I make every pattern have a odd-square number (like 9 or 25). I can itterate each x value and put them in the first (or last) row of the z tables.

Since you like pseudo-code, here’s some:

function RotateSquareTable(MachineTable)

local ReturnTable = {}
local SqrtTable = math.sqrt(#MachineTable)

for i = 1, SqrtTable do
 ReturnTable[i] = {}
end

for i, v in MachineTable do --the "z" row

 for i2, v2 in v do --the "x" row

  table.insert(ReturnTable[i2][i] , "O, X or P" SqrtTable - i2)

 end

end

end

Again, any response is appreciated. Thanks for your time.

you mention any shape possible which this system would work for. You just make a list of offsets where you want an item, and exclude ones where you don’t. For example, with a U shape you would just not include a tile at 1, 0 (directly in front of the lookVector)

Thats funny, I had an identical idea a while back, literally the exact same.

I didn’t get very far with the prototyping, but I did solve what you’re trying to solve, so I’ll detail how I did it here:

To store the machine’s “structure”, I made a class called “assembly”.
This class would have an array of vector2’s, each representing a tile within the assembly. It’s easier to explain with an example.

Take your machine:
X, _, X
X, P, X

Since P is the anchor, the 5 tiles in this machine would be represented as follows: (pseudocode)

machine = assembly.new()
machine.tiles = {
 {0,0}, -- this represents P
 {1,0}, -- this is one right of P
 {1,1}, -- this is one right and one up from P
 {-1,0}. -- self explanatory
 {-1,-1}, -- ...
}

In my pseudocode here, I used arrays to represent the tiles, but you could use vector 2s, or create a class for it. (for example, a tile may have a position relative to the anchor, but also a type, such as block or input or output or power connection etc).

Then, in the local script which displays the hologram when you’re placing the machine, you can iterate over the tiles in the machine object and use the offsets to position the hologram.

Rotating:
I used matrix multipliation to rotate the assemblies.

Rotation matrix for anticlockwise rotation.
image

I can explain in more detail if you’d like, but thats the basics of it - matrices for the rotations.

Oh wow, thanks a lot!

Although I have heard of matrixes (like the movie), I know nothing about them. Could you inform me in how to do it? I’m having a headache trying to code the values with for loops and indexes.

Let point be an array, where the 1st element (lua :sad:) is the x-component and the 2nd element is the y-component of the point.

So for example, {1,0} represents 1 on the x relative to some point, and 0 on the y.

You can use this function to rotate it 90 degrees anticlockwise:
image

Below is the code I used to drawing the points in a machine.

for index, space in pairs(assembly.Spaces) do
	for x = 0, rotate_index-1 do 
		space = rotate(space)
	end
	local modifiedPosition = gridPosition + Vector3.new(Constants.VOXEL_SIZE * (space[1] + anchor[1]), 0, Constants.VOXEL_SIZE * (space[2] + anchor[2]))
	hologram[index].Position = modifiedPosition
end

Here, grid position was just my mouse cursor locked to the grid.

If you want to know more about matrices and why that function actually rotates, read on.

First, I’d suggest getting familiar with matrices:

You can also read my reply on this post, it’s practically identical. (I had misinterpreted what OP had said) Detect if a block or an assembly can rotate?

Then it’s understanding linear transformations. Essentially, say we have a vector, we can multiply that vector by a matrix to make it translate, rotate, stretch, enlarge, reflect, zero, etc.
Depending on the matrix we use, a different transformation will be applied to the vector.

For example, take the matrix:
image

If we multiply this matrix by say the vector (1,0), we actually get (1,0) as the result.
So it’s for this reason this matrix is called the identity matrix, it just returns whatever you multiply it by. It’s equivalent to multiplying by one normally, like 5 * 1 is just five, 32 * 1 is just 32 and so on.

But let’s take this matrix:
image

Imagine the vector (1,0):

Multiple (1,0), by that matrix and we get (0,1)

Essentially, it’s taken the vector and rotated it 90 degrees anticlockwise about the origin. Thats what that matrix does.

This is what I use to make that rotate function from earlier.
image

right sorry if any of this was incoherent or whatnot, please ask questions!

function rotateMatrix90Degrees(matrix)
    local numRows = #matrix
    local numCols = #matrix[1]
    local rotated = {}

    -- Initialize the rotated matrix with the right dimensions
    for i = 1, numCols do
        rotated[i] = {}
    end

    -- Transpose and reverse the rows
    for row = 1, numRows do
        for col = 1, numCols do
            rotated[col][numRows - row + 1] = matrix[row][col]
        end
    end

    return rotated
end

Didn’t really test this code in this case but, it is almost like something I’ve done in the past. Good luck.

Thank you Matrix God.

After re seeing my old system, I think yours is better because it is more editable. Plus, Vectors are easier to work with than tables in my opinion. I will mark your post as the solution.

Thanks again for your time and help!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.