Refactored map generation

This commit is contained in:
Bas
2020-05-17 14:29:16 +02:00
parent 0afd6a0905
commit e270f02bae
69 changed files with 815 additions and 439 deletions

View File

@@ -98,7 +98,7 @@ LightmapSettings:
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
m_UseShadowmask: 0
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
@@ -464,7 +464,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 79be679884da2154dacd80be9669d5dc, type: 3}
m_Name:
m_EditorClassIdentifier:
selectedPark: Crazy Castle.sv6
selectedPark: Blackpool.sv6
--- !u!4 &1347800243
Transform:
m_ObjectHideFlags: 0
@@ -514,37 +514,74 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 8f4353bcde699fe4dbc7f9641bcd509e, type: 3}
m_Name:
m_EditorClassIdentifier:
pathPrefab: {fileID: 6681454114598486694, guid: d5e4b199bf0e87b47b14b43c86d8c12f,
type: 3}
trackPrefab: {fileID: 3460111253241373034, guid: ac7c5b20c9776c2458a7c5f077e645f0,
type: 3}
smallSceneryPrefab: {fileID: 4881190563108725493, guid: e5123beefdc062f42b5e3fb98e104cef,
type: 3}
entrancePrefab: {fileID: 67614980614369834, guid: b3a4fb9191c251d44b6aadea9354fba3,
type: 3}
wallPrefab: {fileID: 6613264330481197744, guid: 3c5d91e604076ff43b5c7556fe1c89e5,
type: 3}
largeSceneryPrefab: {fileID: 8665094481412155395, guid: ab17a95a8234f8e42b1bcde029bf4720,
type: 3}
bannerPrefab: {fileID: 1690927267108533612, guid: 3ffc06cfa16e4e24a9c7526f41ba500f,
type: 3}
generatePath: 1
generateTrack: 1
generateSmallScenery: 1
generateEntrance: 0
generateWall: 1
generateLargeScenery: 0
generateBanner: 0
surfaceShader: {fileID: -6465566751694194690, guid: c5119169087bdc14bb9a8a4b72cab9e7,
type: 3}
surfaceTextureField: Surface
edgeShader: {fileID: -6465566751694194690, guid: 5be9d4f19d70f504d90b782f27c81015,
type: 3}
edgeTextureField: Edge
waterShader: {fileID: -6465566751694194690, guid: f2b2dbc11d613b9478c958f95f47ef17,
type: 3}
waterTextureField: Water
waterRefractionField: WaterRefraction
generationFlags: 125
surfaceGenerator:
id: 0
pathGenerator:
id: 1
trackGenerator:
id: 2
smallSceneryGenerator:
id: 3
entranceGenerator:
id: 4
wallGenerator:
id: 5
largeSceneryGenerator:
id: 6
bannerGenerator:
id: 7
references:
version: 1
00000000:
type: {class: SurfaceGenerator, ns: Generation.Retro, asm: Assembly-CSharp}
data:
surfaceShader: {fileID: -6465566751694194690, guid: c5119169087bdc14bb9a8a4b72cab9e7,
type: 3}
surfaceTextureField: Surface
edgeShader: {fileID: -6465566751694194690, guid: 5be9d4f19d70f504d90b782f27c81015,
type: 3}
edgeTextureField: Edge
waterShader: {fileID: -6465566751694194690, guid: f2b2dbc11d613b9478c958f95f47ef17,
type: 3}
waterTextureField: Water
waterRefractionField: WaterRefraction
00000001:
type: {class: PrefabGenerator, ns: Generation, asm: Assembly-CSharp}
data:
prefab: {fileID: 6681454114598486694, guid: d5e4b199bf0e87b47b14b43c86d8c12f,
type: 3}
00000002:
type: {class: PrefabGenerator, ns: Generation, asm: Assembly-CSharp}
data:
prefab: {fileID: 3460111253241373034, guid: ac7c5b20c9776c2458a7c5f077e645f0,
type: 3}
00000003:
type: {class: SmallSceneryGenerator, ns: Generation.Retro, asm: Assembly-CSharp}
data:
crossShape: {fileID: 4881190563108725493, guid: e5123beefdc062f42b5e3fb98e104cef,
type: 3}
00000004:
type: {class: PrefabGenerator, ns: Generation, asm: Assembly-CSharp}
data:
prefab: {fileID: 67614980614369834, guid: b3a4fb9191c251d44b6aadea9354fba3,
type: 3}
00000005:
type: {class: WallGenerator, ns: Generation.Retro, asm: Assembly-CSharp}
data:
prefab: {fileID: 6613264330481197744, guid: 3c5d91e604076ff43b5c7556fe1c89e5,
type: 3}
textureField: Wall
00000006:
type: {class: PrefabGenerator, ns: Generation, asm: Assembly-CSharp}
data:
prefab: {fileID: 8665094481412155395, guid: ab17a95a8234f8e42b1bcde029bf4720,
type: 3}
00000007:
type: {class: PrefabGenerator, ns: Generation, asm: Assembly-CSharp}
data:
prefab: {fileID: 1690927267108533612, guid: 3ffc06cfa16e4e24a9c7526f41ba500f,
type: 3}
--- !u!4 &1491562770
Transform:
m_ObjectHideFlags: 0

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b02a7a3993994bc438ff2aae967a46de
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using OpenRCT;
namespace Generation
{
/// <summary>
/// A generator that creates the tile elements.
/// </summary>
public interface IElementGenerator
{
/// <summary>
/// Creates a tile element at the specified position.
/// </summary>
void CreateElement(int x, int y, ref TileElement tile);
/// <summary>
/// Initialises the generator for the specified map, before new elements
/// are created.
/// </summary>
void StartGenerator(Map map);
/// <summary>
/// Finalizes the created elements and finishes the generator.
/// </summary>
void FinishGenerator();
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 208e55b7f2c341549806949cefabc5a2
guid: d4f42a2eb53ba834699e03e64789137c
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 36b553d098048e14a9b38ca185a1895a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using OpenRCT;
using UnityEngine;
namespace Generation
{
/// <summary>
/// A simple generator that spawns the specified prefab for the given tile element.
/// </summary>
public class PrefabGenerator : IElementGenerator
{
[SerializeField] GameObject prefab;
Map map;
/// <inheritdoc/>
public void StartGenerator(Map map)
{
this.map = map;
}
/// <inheritdoc/>
public void FinishGenerator()
{
map = null;
}
/// <inheritdoc/>
public void CreateElement(int x, int y, ref TileElement tile)
{
Vector3 position = Map.TileCoordsToUnity(x, tile.baseHeight, y);
Quaternion rotation = Quaternion.Euler(0, 90 * tile.Rotation + 90, 0);
GameObject.Instantiate(prefab, position, rotation, map.transform);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: fb5b2ad3f981c4b4983569596d3e5cb0
guid: 74099863aa18bdc4f9b805afc6f8d7ed
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 502c2cce8f36f2244b516fb69a1a282b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
using OpenRCT;
using UnityEngine;
namespace Generation.Retro
{
/// <summary>
/// A generator for small scenery tile elements.
/// </summary>
public class SmallSceneryGenerator : IElementGenerator
{
[Header("Meshes")]
[SerializeField] GameObject crossShape;
Map map;
/// <inheritdoc/>
public void StartGenerator(Map map)
{
this.map = map;
}
/// <inheritdoc/>
public void FinishGenerator()
{
map = null;
}
/// <inheritdoc/>
public void CreateElement(int x, int y, ref TileElement tile)
{
float pos_x = x;
float pos_y = tile.baseHeight;
float pos_z = y;
SmallSceneryElement smallScenery = tile.AsSmallScenery();
SmallSceneryEntry entry = OpenRCT2.GetSmallSceneryEntry(smallScenery.EntryIndex);
SmallSceneryFlags flags = entry.Flags;
// If not a full tile, move small scenery to the correct quadrant.
if ((flags & SmallSceneryFlags.FullTile) == 0)
{
const float distanceToQuadrant = (Map.TileCoordsToVector3Multiplier / 4);
byte quadrant = smallScenery.Quadrant;
switch (quadrant)
{
case 0: pos_x -= distanceToQuadrant; pos_z -= distanceToQuadrant; break;
case 1: pos_x -= distanceToQuadrant; pos_z += distanceToQuadrant; break;
case 2: pos_x += distanceToQuadrant; pos_z += distanceToQuadrant; break;
case 3: pos_x += distanceToQuadrant; pos_z -= distanceToQuadrant; break;
}
}
// Instantiate the element.
GameObject obj = InstantiateElement(crossShape, pos_x, pos_y, pos_z, (90 * tile.Rotation + 90));
ApplySprite(obj, ref tile);
}
/// <summary>
/// Instantiates the prefab in the place of a tile element.
/// </summary>
GameObject InstantiateElement(GameObject prefab, float x, float y, float z, float rotation)
{
Vector3 position = Map.TileCoordsToUnity(x, y, z);
Quaternion quatRot = Quaternion.Euler(0, rotation, 0);
return GameObject.Instantiate(prefab, position, quatRot, map.transform);
}
/// <summary>
/// Gets the sprite of the tile element and applies it to the gameobject.
/// </summary>
static void ApplySprite(GameObject obj, ref TileElement tile)
{
uint imageIndex = OpenRCT2.GetSmallSceneryImageIndex(tile, 0);
Texture2D texture = GraphicsFactory.ForImageIndex(imageIndex).ToTexture2D(TextureWrapMode.Clamp);
MeshRenderer renderer = obj.GetComponentInChildren<MeshRenderer>();
renderer.material.SetTexture("_BaseMap", texture);
// Set the visual scale of the model.
float width = (texture.width * Map.PixelPerUnitMultiplier);
obj.transform.localScale = new Vector3(width, texture.height * Map.PixelPerUnitMultiplier, width);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28af2eb3d2845f444837f44047f843eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,17 +1,18 @@
using System.Collections.Generic;
using OpenRCT;
using UnityEngine;
namespace OpenRCT2.Unity
namespace Generation.Retro
{
public partial class Map
public partial class SurfaceGenerator
{
[SerializeField] Shader surfaceShader;
[SerializeField] string surfaceTextureField;
[SerializeField] string surfaceTextureField = "Surface";
[SerializeField] Shader edgeShader;
[SerializeField] string edgeTextureField;
[SerializeField] string edgeTextureField = "Edge";
[SerializeField] Shader waterShader;
[SerializeField] string waterTextureField;
[SerializeField] string waterRefractionField;
[SerializeField] string waterTextureField = "Water";
[SerializeField] string waterRefractionField = "WaterRefraction";
const byte TypeSurface = 1;
@@ -19,7 +20,7 @@ namespace OpenRCT2.Unity
const byte TypeWater = 3;
readonly List<RequestedImage> images = new List<RequestedImage>();
List<RequestedImage> images;
/// <summary>

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a733e2964083f9c418ebee1921b299ec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,9 +1,15 @@
using System;
using System.Collections.Generic;
using MeshBuilding;
using OpenRCT;
using UnityEngine;
namespace OpenRCT2.Unity
namespace Generation.Retro
{
public partial class Map
/// <summary>
/// A generator that generates the surface of a map.
/// </summary>
public partial class SurfaceGenerator : IElementGenerator
{
// For now we only use these two water sprites.
static readonly uint WaterImageIndex = OpenRCT2.GetWaterImageIndex();
@@ -11,52 +17,52 @@ namespace OpenRCT2.Unity
const byte NoWater = 0;
Map map;
MeshBuilder surfaceMeshBuilder;
/// <summary>
/// Initializes the required components for building the surface.
/// </summary>
void SetupSurfaceMesh()
/// <inheritdoc/>
public void StartGenerator(Map map)
{
this.map = map;
surfaceMeshBuilder = new MeshBuilder();
images = new List<RequestedImage>();
}
/// <summary>
/// Finishes surface building and returns the mesh.
/// </summary>
Mesh FinalizeSurfaceMesh()
/// <inheritdoc/>
public void FinishGenerator()
{
Mesh mesh = surfaceMeshBuilder.ToMesh();
mesh.name = "Map";
mesh.RecalculateNormals();
map.Mesh = mesh;
map.Materials = GenerateSurfaceMaterials();
surfaceMeshBuilder = null;
return mesh;
images = null;
}
/// <summary>
/// Generates a surface tile along with the edges.
/// </summary>
void GenerateSurface(ref TileElement tile, int x, int y)
/// <inheritdoc/>
public void CreateElement(int x, int y, ref TileElement tile)
{
/* Surface coords to Unity:
*
* ^ W N
* | S E
* y
* x -->
*/
*
* ^ W N
* | S E
* y
* x -->
*/
SurfaceElement surface = tile.AsSurface();
SurfaceSlope slope = surface.Slope;
int baseHeight = tile.baseHeight;
Vertex north = GetSurfaceCorner(x + 1, y + 1, baseHeight, slope, SurfaceSlope.NorthUp);
Vertex east = GetSurfaceCorner(x + 1, y, baseHeight, slope, SurfaceSlope.EastUp);
Vertex south = GetSurfaceCorner(x, y, baseHeight, slope, SurfaceSlope.SouthUp);
Vertex west = GetSurfaceCorner(x, y + 1, baseHeight, slope, SurfaceSlope.WestUp);
Vertex east = GetSurfaceCorner(x + 1, y, baseHeight, slope, SurfaceSlope.EastUp);
Vertex south = GetSurfaceCorner(x, y, baseHeight, slope, SurfaceSlope.SouthUp);
Vertex west = GetSurfaceCorner(x, y + 1, baseHeight, slope, SurfaceSlope.WestUp);
uint surfaceImage = OpenRCT2.GetSurfaceImageIndex(tile, x, y, 0);
int surfaceSubmesh = PushImageIndex(surfaceImage, TypeSurface);
@@ -72,22 +78,22 @@ namespace OpenRCT2.Unity
{
surfaceMeshBuilder.AddQuad(north, east, south, west, surfaceSubmesh);
}
// Water
int waterHeight = surface.WaterHeight;
if (waterHeight != NoWater)
{
float waterVertexHeight = (waterHeight * TileHeightMultiplier * TileHeightStep);
float waterVertexHeight = (waterHeight * Map.TileHeightMultiplier * Map.TileHeightStep);
Vertex waterNorth = new Vertex(north.position.x, waterVertexHeight, north.position.z, Vector3.up, north.uv);
Vertex waterEast = new Vertex(east.position.x, waterVertexHeight, east.position.z, Vector3.up, east.uv);
Vertex waterEast = new Vertex(east.position.x, waterVertexHeight, east.position.z, Vector3.up, east.uv);
Vertex waterSouth = new Vertex(south.position.x, waterVertexHeight, south.position.z, Vector3.up, south.uv);
Vertex waterWest = new Vertex(west.position.x, waterVertexHeight, west.position.z, Vector3.up, west.uv);
Vertex waterWest = new Vertex(west.position.x, waterVertexHeight, west.position.z, Vector3.up, west.uv);
int waterSubmesh = PushImageIndex(WaterImageIndex, TypeWater);
surfaceMeshBuilder.AddQuad(waterNorth, waterEast, waterSouth, waterWest, waterSubmesh);
}
// Edges
uint edgeImage = OpenRCT2.GetSurfaceEdgeImageIndex(tile);
int edgeSubmesh = PushImageIndex(edgeImage, TypeEdge);
@@ -104,20 +110,20 @@ namespace OpenRCT2.Unity
/// </summary>
void TryAddSurfaceEdge(MeshBuilder builder, Vertex leftTop, Vertex rightTop, int x, int y, int offsetX, int offsetY, int waterHeight, SurfaceSlope leftOtherCorner, SurfaceSlope rightOtherCorner, int submesh)
{
SurfaceElement other = tiles[x + offsetX, y + offsetY].Surface;
SurfaceElement other = map.Tiles[x + offsetX, y + offsetY].Surface;
int baseHeight = other.BaseHeight;
SurfaceSlope otherSlope = other.Slope;
if (waterHeight != NoWater && other.WaterHeight != waterHeight)
{
// Render water edge at different height
float waterY = (waterHeight * TileHeightMultiplier * TileHeightStep);
float waterY = (waterHeight * Map.TileHeightMultiplier * Map.TileHeightStep);
leftTop.position.y = waterY;
rightTop.position.y = waterY;
}
float leftBottomY = GetSurfaceCornerHeight(baseHeight, otherSlope, leftOtherCorner) * TileHeightMultiplier;
float rightBottomY = GetSurfaceCornerHeight(baseHeight, otherSlope, rightOtherCorner) * TileHeightMultiplier;
float leftBottomY = GetSurfaceCornerHeight(baseHeight, otherSlope, leftOtherCorner) * Map.TileHeightMultiplier;
float rightBottomY = GetSurfaceCornerHeight(baseHeight, otherSlope, rightOtherCorner) * Map.TileHeightMultiplier;
if (leftTop.position.y > leftBottomY || rightTop.position.y > rightBottomY)
{
@@ -145,9 +151,9 @@ namespace OpenRCT2.Unity
int height = GetSurfaceCornerHeight(startHeight, surfaceSlope, surfaceCorner);
Vector3 position = new Vector3(
x * TileCoordsToVector3Multiplier,
height * TileHeightMultiplier,
y * TileCoordsToVector3Multiplier
x * Map.TileCoordsToVector3Multiplier,
height * Map.TileHeightMultiplier,
y * Map.TileCoordsToVector3Multiplier
);
return new Vertex(position, Vector3.zero, new Vector2(x, y));
@@ -164,7 +170,7 @@ namespace OpenRCT2.Unity
// Lift corner vertex up
if ((slope & corner) != 0)
height += TileHeightStep;
height += Map.TileHeightStep;
if ((slope & (int)SurfaceSlope.DoubleHeight) != 0)
{
@@ -175,9 +181,10 @@ namespace OpenRCT2.Unity
// Check if all corners except opposite are raised.
if (corners == (allcornersup & ~opposite))
height += TileHeightStep;
height += Map.TileHeightStep;
}
return height;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb755727c9ed637499a59fb3df9d04f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using OpenRCT;
using UnityEngine;
namespace Generation.Retro
{
/// <summary>
/// A generator for wall elements.
/// </summary>
public class WallGenerator : IElementGenerator
{
[SerializeField] GameObject prefab;
[SerializeField] string textureField = "Wall";
Map map;
/// <inheritdoc/>
public void StartGenerator(Map map)
{
this.map = map;
}
/// <inheritdoc/>
public void FinishGenerator()
{
map = null;
}
/// <inheritdoc/>
public void CreateElement(int x, int y, ref TileElement tile)
{
Vector3 position = Map.TileCoordsToUnity(x, tile.baseHeight, y);
Quaternion rotation = Quaternion.Euler(0, (90 * tile.Rotation + 90), 0);
GameObject obj = GameObject.Instantiate(prefab, position, rotation, map.transform);
// Apply the wall sprite
uint imageIndex = OpenRCT2.GetWallImageIndex(tile, 0);
Texture2D texture = GraphicsFactory.ForImageIndex(imageIndex).ToTexture2D(TextureWrapMode.Repeat);
MeshRenderer renderer = obj.GetComponentInChildren<MeshRenderer>();
renderer.material.SetTexture(textureField, texture);
// Set the visual scale of the model.
obj.transform.localScale = new Vector3(1, (tile.clearanceHeight - tile.baseHeight), 1);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f4ba4537bc24da48af64bfcbdd42462
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: cc0a1a7abd6241847b5f5de53b3a98f5
guid: 55200e5041359b948a5d542b6d81106f
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,6 +1,6 @@
using UnityEngine;
namespace OpenRCT2.Unity
namespace OpenRCT
{
/// <summary>
/// Static class to access OpenRCT2-Unity configuration.

View File

@@ -4,7 +4,7 @@ using System.Linq;
using UnityEditor;
using UnityEngine;
namespace OpenRCT2.Unity
namespace OpenRCT
{
/// <summary>
/// An editor that helps configuring OpenRCT2 settings in Unity, for example

View File

@@ -1,6 +1,6 @@
using System;
namespace OpenRCT2.Unity
namespace OpenRCT
{
/// <summary>
/// Flags of ownership of a specific tile.

Some files were not shown because too many files have changed in this diff Show More