Starling - squared tile map and positioning - starling-framework

I'm making a tile game in Action Script 3 / Starling.
Suppose I have a scenario like this:
+----+----+----+----+----+
| | | | | | 0th row - highest
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+
| | | | | | 3rd row - lowest
+----+----+----+----+----+
In this example, I have a 5x4 tile scenario. In a real gameplay I'll have a 100x100 tile scenario.
This squared map is for an RPG game, where each square could be occupied by an object or a character. Objects can be like trees, which are high and would hide the objects behind.
The key concept here is "hiding objects behind", and the greater is the row number, the "nearest" to the screen it will be, and if the row number is N, rows from 0 to N-1 will be hidden (actually "overlapped") by objects in the layer N (example: if a character is standing on position (x=1,y=2) having a height of 2, and a tree is standing at position (x=1,y=3), the tree would completely overlap the character "above".
I thought about a possible alternative:
If I have the current Starling sprite (which was created by Starling itself passing its class to the Starling constructor), and create one Sprite (sub-sprite) for each row, attaching it to the parent sprite:
private var rows:Vector.<Sprite> = null;
public function createMapRows(nRows:int) {
this.rows = new Vector.<Sprite>();
for(var r:int = 0; r < nRows; r++) {
this.addChild(new Sprite());
}
}
If a character moves left or right, it would remain on the same layer. If a character moves up, I could move the player from the Nth created sprite to the (N-1)th created sprite keeping its (X,Y) coordinates AND performing the 'move up' animation. If a character moves down, I could move the player from the Nth created sprite to the (N-1)th created sprite keeping its (X,Y) coordinates AND performing the 'move down' animation.
I believe this would work but I'm concerned about one aspect: performance.
My Question is: Is this the best way to accomplish this regarding memory performance? Or could be a better solution which does not involve the N+1* problem? (Actually, if the first question has a "NO" answer, I'd like an alternative).
(* No, it's not the N+1 problem regarding database records :p, but amount of sprites).

One thing is to make you'r own sprite instance for every row or just for the objects of that row.
I would do it like this:
The base Sprite object contains all the ground tiles cause there are always under everything else.
And on top of that I would make a Sprite filled with all the objects for that row.
Clouds
Row 0 objects
Row 1 objects
Row 2 objects <-- player is here at the moment
Row 3 objects
BaseLayer - ground tiles
And, like you mentioned before, if the player goes north or south just addChild the player Sprite so the right row Sprite.

Related

Checking if something is in the way or not in a 3d environment while also snapping to a different object

I have written some code that snaps a cylinder to an existing cylinder using a for loop on a gameobject list I call cylinders. Below is the code I use for "snapping" the cylinder to another cylinder using the mouse position and a "translucentPrefab". I would like to know if there is another object obstructing the placement. For performance reasons I would like to avoid using another for loop through my list to check each position. Is there any good solution for this. Could I use a "fake" 2d array since I mostly use full integer boxes and set squares to occupied in that array. Or is there a smarter approach?
`if (worldMousePosition.x > centerPoint.x && Vector3.Distance(worldMousePosition, centerPoint) < snappingRange)
{
translucentPrefab.transform.position = rightPosition;
snapped = true;
left = false;
if (renderer != null)
{
// Set the prefab material to translucent and green
material.color = new Color(0, 1, 1, 0.5f);
}
}`
I have tried using box colliders in many ways to check in the same space as the new cylinder, however all attempts have been a faliure.
I suggest you to use Physics.SphereCastAll at point where you cursor is and just iterate over all object that SphereCastAll returns.
And if you don't want objects to count toward physics you can add special physic layer for just this. And that adjust collision matrix.

Unity3D Arange multiple gameobjects on top of cube without falling

This is for a board game. Each tile (a cube) can have up to 6 tokens on top. What happens is based on some logic, I move a token to the top center of cube (which works fine). When another token come into the same tile surface, I want any tokens already on the surface to move away and give room to the incoming tile.
Right now, since these tokens have rigidbodies they get pushed away, but I don't have much control over how those tokens should be placed. Main problem is I need to utilize the surface area of the cube to determine exact point a tile should move. I don't want it to fall or push away from the cube bounds.
I was thinking to place 6 empty gameobjects as children in the cube that has possible areas a token can move on the surface. But then the child local coordinates and token coordinates are different.
What kind of approaches are available?
An approach would be creating a script for the block like the one below containing.
An index of how many tokens are currently present on it and
An array of vector2 positions (consider a 3*3 matrix )
And a distance from center value to multiple with the positions.
So when adding a token to the cube you'll have to pass the cube tiles position (it will be the center of the cube tile so I called it cubeCenter) and the token to be added.
first check whether the index is -1, meaning there are not tokens so place the token in the center(cubeCenter) and increment the index to 0.
else
change the position of the previous token to pos[index]*distanceFromCubeCenter +cubeCenter, increment the index and set new token's position to cubeCenter.
Consider if the cube tile is at (3,0,3) and there is already a token in the center so the index will be 0. if another token comes then the position of the old token will be will be (-1*0.3+3,0,-1*0.3+3) =(2.7,0,2.7) and will place the token like the bottom left in your image and the new token will be in the center. Similarly, if another token comes then the token in the center will go to (3,0,2.7) like the bottom center of your image.
3*3 matrix but in this case, only 5 positions are used.
| (-1,0,1) |(0,0,1) |(1,0,1) |
| (-1,0,0) |(0,0,0) |(1,0,0) |
| (-1,0,-1)|(0,0,-1)|(1,0,-1)|
the code is in 3d since I saw the blue z-axis, you will have to change it depending on how you are storing/moving the tokens.
int index = -1;
public Vector3[] pos; //(-1,0,-1),(0,0,-1),(1,,0,0),(-1,,0,1),(0,0,1)
public float distanceFromCubeCenter = 0.3f; // spacing from the center of the cube
public void AddToCube(Vector3 cubeCenter,GameObject token)
{
if (index == -1) //only for the first token on cube
{
token.transform.position = cubeCenter;
index++; // increment index to 0
}
else
{
previousTokenOnThisCube.transform.position = pos[index] * distanceFromCubeCenter + cubeCenter;
index++;
token.transform.position = cubeCenter;
}
}

JavaFX 8 - How to erase a part of background making it transparent

I have a Pane and inside it I have a Rectangle shape.
The Pane has a red background. What I want is that, in the part where the rectangle is placed, the background is transparent.
This is the code:
Pane pane=new Pane();
pane.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
Rectangle rect=new Rectangle(50,50,50,50, Color.YELLOW);
pane.getChildren().add(rect);
This is the result
This is what I want
In the second picture the grey color is the background color of the stage.
I tried to play with the blending mode but I didn't succeed.
To accomplish your goal, you could try to use 2 instances of Rectangle instead of a Pane and a Rectangle. By doing so, you could use the static substract method of the Shape class to substract the two areas from one another:
Shape.substract(Rect_1, Rect_2);
As stated by Oracle, the method does exactly what you want to do:
public static Shape subtract(Shape shape1,
Shape shape2)
Returns a new Shape which is created by subtracting the specified second shape from the first shape.
The operation works with geometric areas occupied by the input shapes. For a single Shape such area includes the area occupied by the fill if the shape has a non-null fill and the area occupied by the stroke if the shape has a non-null stroke. So the area is empty for a shape with null stroke and null fill. The area of an input shape considered by the operation is independent on the type and configuration of the paint used for fill or stroke. Before the final operation the areas of the input shapes are transformed to the parent coordinate space of their respective topmost parent nodes.
The resulting shape will include areas that were contained only in the first shape and not in the second shape.
shape1 - shape2 = result
+----------------+ +----------------+ +----------------+
|################| |################| | |
|############## | | ##############| |## |
|############ | | ############| |#### |
|########## | | ##########| |###### |
|######## | | ########| |######## |
|###### | | ######| |###### |
|#### | | ####| |#### |
|## | | ##| |## |
+----------------+ +----------------+ +----------------+
Parameters:
shape1 - the first shape
shape2 - the second shape
Returns:
the created Shape
Source

What is the best way to evenly distribute objects to fill a curved space in Unity 3D?

I would like to fill this auditorium seating area with chairs (in the editor) and have them all face the same focal point (the stage). I will then be randomly filling the chairs with different people (during runtime). After each run the chairs should stay the same, but the people should be cleared so that during the next run the crowd looks different.
The seating area does not currently have a collider attached to it, and neither do the chairs or people.
I found this code which has taken care of rotating the chairs so they target the same focal point. But I'm still curious if there are any better methods to do this.
//C# Example (LookAtPoint.cs)
using UnityEngine;
[ExecuteInEditMode]
public class LookAtPoint : MonoBehaviour
{
public Vector3 lookAtPoint = Vector3.zero;
void Update()
{
transform.LookAt(lookAtPoint);
}
}
Additional Screenshots
You can write a editor script to automatically place them evenly. In this script,
I don't handle world and local/model space in following code. Remember to do it when you need to.
Generate parallel rays that come from +y to -y in a grid. The patch size of this grid depends on how big you chair and the mesh(curved space) is. To get a proper patch size. Get the bounding box of a chair(A) and the curved space mesh(B), and then devide them(B/A) and use the result as the patch size.
Mesh chairMR;//Mesh of the chair
Mesh audiMR;//Mesh of the auditorium
var patchSizeX = audiMR.bounds.size.X;
var patchSizeZ = audiMR.bounds.size.Z;
var countX = audiMR.bounds.size.x / chairMR.bounds.size.x;
var countZ = audiMR.bounds.size.z / chairMR.bounds.size.z;
So the number of rays you need to generate is about countX*countZ. Patch size is (patchSizeX, patchSizeZ).
Then, origin points of the rays can be determined:
//Generate parallel rays that come form +y to -y.
List<Ray> rays = new List<Ray>(countX*countZ);
for(var i=0; i<countX; ++i)
{
var x = audiMR.bounds.min.x + i * sizeX + tolerance /*add some tolerance so the placed chairs not intersect each other when rotate them towards the stage*/;
for(var i=0; i<countZ; ++i)
{
var z = audiMR.bounds.min.z + i * sizeZ + tolerance;
var ray = new Ray(new Vector3(x, 10000, z), Vector3.down);
//You can also call `Physics.Raycast` here too.
}
}
Get postions to place chairs.
attach a MeshCollider to your mesh temporarily
foreach ray, Physics.Raycast it (you can place some obstacles on places that will not have a chair placed. Set special layer for those obstacles.)
get hit point and create a chair at the hit point and rotate it towards the stage
Reuse these hit points to place your people at runtime.
Convert each of them into a model/local space point. And save them into json or asset via serialization for later use at runtime: place people randomly.

How to keep node from moving off of (outside of) another node

I have a few square-shaped nodes (like floor tiles) going along the screen and I'd like to restrict my player (P) node to moving within these nodes.
---------------------------------
| | P | | | | | | | <- Want no movement allowed
--------------------------------- outside of these squares.
| |
-------------
| | | | ...
-------------
I'm wondering if there's an elegant way to do this with SpriteKit Physics, that doesn't involve putting invisible blocks all the way around the floor.
Thanks!
An SKConstraint object describes a mathematical constraint on a node’s position or orientation.
You can use SKConstraint to keep a node a certain distance from a specific point in horizontal axis:
let center = size.width/2.0, difference = CGFloat(170.0)
let leftConstraint = SKConstraint.positionX(SKRange(constantValue: center - difference))
let rightConstraint = SKConstraint.positionX(SKRange(constantValue: center + difference))
player.constraints = [leftConstraint, rightConstraint]
You can also decide to enable or disable a certain constraint during the game:
leftConstraint.enabled = false
You use edge based physics bodies, not volume based physics bodies. So in your construction of the physics body, look for anything with edge in the constructor. Now, if you want to be able to walk between the tiles, you will have to create 1 physics body for the outer wall of your floor, because doing it tile by tile will mean you will be stuck in individual tiles.