How to random place sprites but make sure they aren't touching?
Hi,
I've been trying for 2 days now to complete this task. I'll explain as much as I can. Effectively this is kind of a kid's puzzle game where they have to drag a character image from the bottom of the screen into a character shaped hole in the background. So, I have a group of sprites that I'm applying a diffuse shader to for the silhouettes. However, I don't want the toddler to be able to just memorize the pattern of where the pieces go so I'm randomizing the placement of the silhouettes on the screen. For the most part this is working ok, except for those times when the random positions overlap. I had attempted to use BoxCollider2D to determine if they were overlapping, but since all the sprites are generated at the same time and the physics doesn't have a chance to update in between, this doesn't work. At present I'm using the attached code to generate the potential Rect for each sprite and check for collissions, but for some reason it sometimes detects the collission, but other times doesn't. This is doing my head in. This is the full class code. Thanks guys.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PuzzleScene : MonoBehaviour {
Level level;
Transform itemPanel;
Transform gameArea;
Rect gameBounds;
public float worldScreenHeight;
public float worldScreenWidth;
List<GameObject> silhouettes = new List<GameObject>();
void Start () {
level = LevelManager.getLevelByName (GameManager.level);
itemPanel = GameObject.Find ("ItemPanelContent").transform;
gameArea = GameObject.Find ("Background").transform;
getWorldSize ();
setBackground ();
populateItems ();
}
void getWorldSize() {
worldScreenHeight = Camera.main.orthographicSize *2f;
worldScreenWidth = worldScreenHeight / Screen.height * Screen.width;
}
void setBackground() {
SpriteRenderer sr = gameArea.gameObject.GetComponent<SpriteRenderer> ();
sr.sprite = Resources.Load<Sprite>(level.Background);
float scaleX = worldScreenWidth / sr.sprite.bounds.size.x;
float scaleY = worldScreenHeight / sr.sprite.bounds.size.y;
gameArea.localScale = new Vector3(scaleX, scaleY, 1);
gameBounds = getSpriteRect (gameArea.gameObject);
}
void populateItems() {
for (int i = 0; i < level.Items.Count; i++) {
GameObject item = createItem (level.Items [i]);
item.transform.SetParent (itemPanel);
GameObject sil = createSilhouette (level.Items [i]);
sil.transform.SetParent (gameArea);
silhouettes.Add (sil);
}
}
GameObject createItem(LevelItem item) {
GameObject obj = Instantiate(Resources.Load ("PuzzlePiece") as GameObject, transform);
Image spr = obj.GetComponent<Image>();
obj.name = item.Name;
spr.sprite = Resources.Load<Sprite> (item.Sprite);
return obj;
}
GameObject createSilhouette(LevelItem item) {
GameObject obj = Instantiate(Resources.Load ("Silhouette") as GameObject, transform);
SpriteRenderer spr = obj.GetComponent<SpriteRenderer>();
spr.sprite = Resources.Load<Sprite> (item.Sprite);
obj.name = item.Name;
float ppu = spr.sprite.pixelsPerUnit;
float unitSize = 100 / ppu;
float scaleX = unitSize / spr.sprite.bounds.size.x;
float scaleY = unitSize / spr.sprite.bounds.size.y;
obj.transform.localScale = new Vector3 (scaleX, scaleY, 1);
do {
randomPosition(obj);
} while (isColliding(obj));
return obj;
}
bool isColliding(GameObject obj) {
Rect testRect = getSpriteRect (obj);
foreach (GameObject obje in silhouettes) {
Rect r = getSpriteRect (obje);
if (r.Overlaps(testRect)) {
return true;
}
};
return false;
}
void randomPosition(GameObject obj) {
obj.transform.position = new Vector3 (Random.Range (-5f, 5f), Random.Range (-2f, 2f), 0);
}
Rect getSpriteRect(GameObject obj) {
Vector3 pos = obj.transform.position;
SpriteRenderer sr = obj.GetComponent<SpriteRenderer> ();
Rect tmpr = new Rect ();
Vector3 min = pos + sr.bounds.min;
Vector3 max = pos + sr.bounds.max;
min.Scale (obj.transform.localScale);
max.Scale (obj.transform.localScale);
tmpr.min = new Vector2 (min.x, min.y);
tmpr.max = new Vector2 (max.x, max.y);
return tmpr;
}
}
Answer by jamb84 · Jan 13, 2017 at 12:43 AM
Figured it out. I wasn't taking into account the center of the rect.
Rect getSpriteRect(GameObject obj) {
Vector3 pos = obj.transform.position;
SpriteRenderer sr = obj.GetComponent<SpriteRenderer> ();
Rect tmpr = new Rect (obj.transform.position, sr.bounds.size);
tmpr.center = tmpr.min;
return tmpr;
}
Your answer
Follow this Question
Related Questions
Selective Collision Detection 2 Answers
My collision is not detecting 1 Answer
Best way to do Collision detection when you have multiple enemies/allies around you 0 Answers
Checking for collisions 1 Answer
Detect edge collision...? 0 Answers