Skip to content

Commit

Permalink
Story #3 Enhanced level generation
Browse files Browse the repository at this point in the history
- Now more stable
- Added level abstraction level class composed of rooms
- The path from spawn to end is now open (no walls)
  • Loading branch information
Feinte75 committed Oct 24, 2015
1 parent 52d5a7c commit 1035373
Show file tree
Hide file tree
Showing 12 changed files with 450 additions and 152 deletions.
Binary file modified Assets/Prefab/Environment/CubicWall.prefab
Binary file not shown.
Binary file modified Assets/Scene/SceneGenerator.unity
Binary file not shown.
33 changes: 33 additions & 0 deletions Assets/Scripts/ProceduralGeneration/Facing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using UnityEngine;

namespace Procedural
{
public enum Facing
{
NORTH,
SOUTH,
EAST,
WEST
}

public static class Extension {
public static Facing Opposite(this Facing facing) {
switch (facing) {
case Facing.EAST:
return Facing.WEST;
case Facing.WEST:
return Facing.EAST;
case Facing.NORTH:
return Facing.SOUTH;
case Facing.SOUTH:
return Facing.NORTH;

default:
return Facing.NORTH;
}
}
}

}

8 changes: 8 additions & 0 deletions Assets/Scripts/ProceduralGeneration/Facing.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions Assets/Scripts/ProceduralGeneration/Level.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Procedural
{
public class Level
{
private int levelWidth = 10;
private int levelHeight = 10;
private List<Vector2> layout;
private Room[,] rooms;
private Vector2 endPosition = new Vector2 (6, 6);

public Level (int levelWidth, int levelHeight, List<Vector2> layout, Room[,] rooms)
{
this.levelWidth = levelWidth;
this.levelHeight = levelHeight;
this.layout = layout;
this.rooms = rooms;
}

public List<Vector2> Layout {
get {
return this.layout;
}
}

public Room[,] Rooms {
get {
return this.rooms;
}
}
}
}

8 changes: 8 additions & 0 deletions Assets/Scripts/ProceduralGeneration/Level.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Assets/Scripts/ProceduralGeneration/LevelGenerationStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using UnityEngine;

namespace Procedural
{
public interface LevelGenerationStrategy
{
Level generateLevel();
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

225 changes: 93 additions & 132 deletions Assets/Scripts/ProceduralGeneration/LevelGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,149 +1,110 @@
using UnityEngine;
using System;
using System.Collections.Generic;

public class LevelGenerator : MonoBehaviour
namespace Procedural
{
[Tooltip("Put here Wall Prefab ! ")]
public Transform wall;
public int minimumDistance = 6;
public int maximumDistance = 10;
public Vector2 endPosition = new Vector2(6, 6);
public int levelWidth = 10;
public int levelHeight = 10;

private Room[,] level;
private List<Vector2> layout;

private Transform environment; // Stores the roo object for the environment

enum Facing
{
NORTH,
SOUTH,
EAST,
WEST
}

// Use this for initialization
void Start()
{
int nbIter = 0;
float elapsedTime = Time.realtimeSinceStartup;

GameObject obj = new GameObject ("Environment");
environment = obj.GetComponent<Transform> ();

level = new Room[levelWidth, levelHeight];
layout = new List<Vector2> (10);
while (findPath(0, 0, minimumDistance) == false) {
nbIter ++;
if(nbIter > 2) {
Debug.Log("Path not found");
break;

}
public class LevelGenerator : MonoBehaviour
{
[Tooltip("Put here Wall Prefab ! ")]
public Transform wall;
public int minimumDistance = 6;
public int maximumDistance = 10;
public Vector2 startingPosition = new Vector2 (0, 0);
public Vector2 endPosition = new Vector2 (6, 6);
public int levelWidth = 10;
public int levelHeight = 10;
public LevelGenerationStrategy levelGenerationStrategy;

private Transform environment; // Stores the roo object for the environment
// Use this for initialization
void Start ()
{
int nbIter = 0;
float elapsedTime = Time.realtimeSinceStartup;

GameObject obj = new GameObject ("Environment");
environment = obj.GetComponent<Transform> ();

levelGenerationStrategy = new RecursiveGeneration (levelWidth, levelHeight, startingPosition, endPosition, minimumDistance, maximumDistance);
Level level = levelGenerationStrategy.generateLevel ();

foreach (Vector2 v in level.Layout) {
generateRoom (level.Rooms[(int)v.x, (int)v.y]);
}
}

elapsedTime = Time.realtimeSinceStartup - elapsedTime;
Debug.Log ("Number of iteration : " + nbIter);
Debug.Log ("Generation time : " + elapsedTime);
Debug.Log ("Number of Rooms : " + layout.Count);
Debug.Log ("Rooms Layout: ");
foreach(Vector2 v in layout) {
Debug.Log(v);
generateSquare(10, 10, level[(int)v.x, (int)v.y].getPosition() * 10);
public void instanciateWall (Vector2 position)
{
Transform wallInstance = (Transform)Instantiate (wall, new Vector3 (position.x, position.y, 0), Quaternion.identity);
wallInstance.localScale = new Vector2 (0.5f, 0.5f);
wallInstance.SetParent (environment);
}

}

private bool findPath(int x, int y, int minDistance)
{
Debug.Log("Starting find Path : x = " + x +" y = " + y + " distance = " + minDistance);

if ((x == endPosition.x && y == endPosition.y) && (minDistance <= 0) && (minDistance > -(maximumDistance - minimumDistance))) {
addRoomToLayout (x, y);
return true;
}

if (!validPosition(x, y))
return false;

addRoomToLayout (x, y);

Facing r = (Facing)Random.Range(0, 4);
Debug.Log("r : " + r);
switch (r)
{
case Facing.NORTH:
if (findPath(x, y + 1, minDistance - 1) == true) return true;
goto case Facing.SOUTH;

case Facing.SOUTH:
if (findPath(x, y - 1, minDistance - 1) == true) return true;
goto case Facing.EAST;

case Facing.EAST:
if (findPath(x + 1, y, minDistance - 1) == true) return true;
goto case Facing.WEST;

case Facing.WEST:
if (findPath(x - 1, y, minDistance - 1) == true) return true;
break;

default:
Debug.Log("Error");
break;
}
layout.RemoveAt(layout.Count - 1);
level [x, y] = null;
return false;
}

private void addRoomToLayout(int x, int y) {
layout.Add(new Vector2(x, y));
level [x, y] = new Room (new Vector2 (x, y));
}

private bool validPosition(int x, int y)
{
foreach(Vector2 position in layout) {
if(position.x == x && position.y == y)
return false;
/**
* Generate a bordered square (not filled) beginning at position
*/
private void generateSquare (int width, int height, Vector2 position)
{

for (int i = 0; i <= width; i++) {
for (int j = 0; j <= height; j++) {
if (i == 0 || i == width || j == 0 || j == height) {

Transform wallInstance = (Transform)Instantiate (wall, new Vector3 (i + position.x, j + position.y, 0), Quaternion.identity);
wallInstance.SetParent (environment);
}
}
}
}
return (((x >= 0) && (x < levelWidth)) && ((y >= 0) && (y < levelHeight)));
}

private void generateRoom (Room room)
{
int width = room.Width;
int height = room.Height;
Vector2 position = room.getPosition ();

foreach (Facing facing in room.getFacings()) {
int i, j;
i = j = 0;

switch (facing) {
case Facing.EAST:
i = width;
goto case Facing.WEST;

case Facing.WEST:
for (j = 0; j < height; j++) {
Transform wallInstance = (Transform)Instantiate (wall, new Vector3 (i + position.x, j + position.y, 0), Quaternion.identity);
wallInstance.SetParent (environment);
}
break;

case Facing.NORTH:
j = height;
goto case Facing.SOUTH;

case Facing.SOUTH:
for (i = 0; i < width; i++) {
Transform wallInstance = (Transform)Instantiate (wall, new Vector3 (i + position.x, j + position.y, 0), Quaternion.identity);
wallInstance.SetParent (environment);
}
break;

private void instanciateWall(Vector2 position) {
Transform wallInstance = (Transform) Instantiate(wall, new Vector3(position.x, position.y, 0), Quaternion.identity);
wallInstance.localScale = new Vector2 (0.5f, 0.5f);
wallInstance.SetParent(environment);
}

/**
* Generate a bordered square (not filled) beginning at position
*/
private void generateSquare(int width, int height, Vector2 position) {

for (int i = 0; i <= width; i++) {
for (int j = 0; j <= height; j++) {
if(i == 0 || i == width || j == 0 || j == height) {

Transform wallInstance = (Transform) Instantiate(wall, new Vector3(i + position.x, j + position.y, 0), Quaternion.identity);
wallInstance.SetParent(environment);
}
}
}
}

/**
* Generate Horizontal platform beginning at position
*/
private void generatePlatform(int width, Vector2 position) {

/**
* Generate Horizontal platform beginning at position
*/
private void generatePlatform (int width, Vector2 position)
{

for (int i = 0; i <= width; i++) {
Transform wallInstance = (Transform) Instantiate(wall, new Vector3(i + position.x, position.y, 0), Quaternion.identity);
wallInstance.SetParent(environment);
for (int i = 0; i <= width; i++) {
Transform wallInstance = (Transform)Instantiate (wall, new Vector3 (i + position.x, position.y, 0), Quaternion.identity);
wallInstance.SetParent (environment);
}
}
}
}
}
Loading

0 comments on commit 1035373

Please sign in to comment.