Added TileTypeInfo to store tile masks.

main
Martin Felis 2023-12-29 09:26:43 +01:00
parent 883e256101
commit 7d0e0b23bd
15 changed files with 162 additions and 63 deletions

View File

@ -1,6 +1,17 @@
using System;
using Godot;
public class Entity : KinematicBody {
[Flags]
public enum EntityMaskEnum {
Obstacle = 1 << 1,
Ground = 1 << 2,
Water = 1 << 3
}
[Export(PropertyHint.Flags, "Obstacle,Ground,Water")]
public int EntityMask { get; set; }
public Vector3 Velocity { get; set; } = Vector3.Zero;
public float RotationalVelocity { get; set; } = 0;

View File

@ -5,7 +5,7 @@
[resource]
shader = ExtResource( 1 )
shader_param/DeepWaterColor = Color( 0, 0, 0.6, 1 )
shader_param/WaterColor = Color( 0, 0, 0.7, 1 )
shader_param/WaterColor = Color( 0, 0, 0.698039, 1 )
shader_param/LightWaterColor = Color( 0, 0, 1, 1 )
shader_param/SandColor = Color( 0.8, 0.8, 0.1, 1 )
shader_param/GrassColor = Color( 0, 0.6, 0, 1 )

View File

@ -56,7 +56,7 @@ void fragment() {
// COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
COLOR.rgb = color_ramp(texture_color.r * texture(TextureMask, UV).r);
COLOR.a = 0.8;
COLOR.a = 1.0;
// COLOR.rgb = vec3(1, 0, 0);
}

View File

@ -114,6 +114,11 @@ Right={
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":68,"unicode":0,"echo":false,"script":null)
]
}
ToggleMainMenu={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":16777217,"unicode":0,"echo":false,"script":null)
]
}
[layer_names]

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=14 format=2]
[gd_scene load_steps=15 format=2]
[ext_resource path="res://ui/WorldGeneratorWidget.gd" type="Script" id=1]
[ext_resource path="res://entities/Player.tscn" type="PackedScene" id=2]
@ -7,6 +7,7 @@
[ext_resource path="res://utils/TileHighlight.tscn" type="PackedScene" id=5]
[ext_resource path="res://ui/DebugStatsContainer.gd" type="Script" id=6]
[ext_resource path="res://scenes/World.tscn" type="PackedScene" id=7]
[ext_resource path="res://ui/WorldGeneratorUI.tscn" type="PackedScene" id=8]
[ext_resource path="res://scenes/Game.cs" type="Script" id=9]
[ext_resource path="res://entities/Chest.tscn" type="PackedScene" id=11]
[ext_resource path="res://entities/Axe.tscn" type="PackedScene" id=14]
@ -352,6 +353,7 @@ script = ExtResource( 15 )
[node name="NavigationSystem" type="Node" parent="."]
[node name="Player" parent="." instance=ExtResource( 2 )]
EntityMask = 2
WorldNode = NodePath("../World")
[node name="WorldInfo" parent="Player" index="2"]
@ -371,6 +373,7 @@ input_ray_pickable = false
[node name="Chest" parent="Entities" instance=ExtResource( 11 )]
transform = Transform( -0.825665, 0, 0.56416, 0, 1, 0, -0.56416, 0, -0.825665, -3.27709, 0, 1.02593 )
EntityMask = 3
[node name="World" parent="." instance=ExtResource( 7 )]
@ -379,9 +382,60 @@ transform = Transform( 0.328059, -0.878387, 0.347583, 0, 0.367946, 0.929847, -0.
shadow_enabled = true
directional_shadow_mode = 0
[node name="GameMenu" type="Control" parent="."]
visible = false
anchor_left = 0.1
anchor_top = 0.1
anchor_right = 0.9
anchor_bottom = 0.9
[node name="Panel" type="Panel" parent="GameMenu"]
anchor_right = 1.0
anchor_bottom = 1.0
[node name="MainMenu" type="VBoxContainer" parent="GameMenu/Panel"]
visible = false
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -41.0
margin_top = -10.0
margin_right = 41.0
margin_bottom = 10.0
[node name="NewGameButton" type="Button" parent="GameMenu/Panel/MainMenu"]
margin_right = 82.0
margin_bottom = 20.0
text = "New Game"
[node name="QuitButton" type="Button" parent="GameMenu/Panel/MainMenu"]
margin_top = 24.0
margin_right = 82.0
margin_bottom = 44.0
text = "Quit"
[node name="WorldGeneratorUI" parent="GameMenu/Panel" instance=ExtResource( 8 )]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -143.5
margin_top = -160.0
margin_right = 143.5
margin_bottom = 160.0
[node name="VBoxContainer" parent="GameMenu/Panel/WorldGeneratorUI" index="0"]
margin_left = 0.0
margin_top = 41.0
margin_right = 287.0
margin_bottom = 279.0
[connection signal="toggled" from="DebugContainer/DebugStatsContainer/DebugMenuButton" to="DebugContainer/DebugStatsContainer" method="_on_DebugMenuButton_toggled"]
[connection signal="value_changed" from="Generator Container/WorldGeneratorWidget/HBoxContainer/WorldSizeSlider" to="Generator Container/WorldGeneratorWidget" method="_on_HSlider_value_changed"]
[connection signal="toggled" from="Generator Container/WorldGeneratorWidget/ShowTexturesCheckButton" to="Generator Container/WorldGeneratorWidget" method="_on_ShowTexturesCheckButton_toggled"]
[editable path="Player"]
[editable path="Player/Geometry/PirateAsset"]
[editable path="World"]
[editable path="GameMenu/Panel/WorldGeneratorUI"]

View File

@ -2,14 +2,17 @@ using System.Diagnostics;
using Godot;
public class HexTile3D : Spatial {
public enum TileType {
Undefined,
Sand,
Grass,
DeepGrass
}
public class TileTypeInfo {
public readonly string Name;
public readonly Color Color;
public readonly ushort TileTypeMask;
public static TileType[] ValidTileTypes = { TileType.Sand, TileType.Grass, TileType.DeepGrass };
public TileTypeInfo(string name, Color color, ushort tileTypeMask) {
Name = name;
Color = color;
TileTypeMask = tileTypeMask;
}
}
// scene nodes
private MeshInstance _mesh;
@ -44,8 +47,6 @@ public class HexTile3D : Spatial {
}
}
public TileType Type { get; set; }
private HexTile3D() {
_hexGrid = new HexGrid();
}
@ -61,8 +62,6 @@ public class HexTile3D : Spatial {
Mesh = GetNode<MeshInstance>("Mesh");
Debug.Assert(Mesh != null);
Type = TileType.Undefined;
}

View File

@ -1,6 +1,6 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://materials/IslandColorRampShader.tres" type="Material" id=1]
[ext_resource path="res://materials/WorldTileTypeMaterial.tres" type="Material" id=1]
[sub_resource type="OpenSimplexNoise" id=3]
seed = 57

View File

@ -161,7 +161,6 @@ public class StreamContainer : Spatial {
} else {
HexTile3D tile3D = _unusedTiles.Dequeue();
tile3D.OffsetCoords = coord;
tile3D.Type = TileWorld.GetTileTypeAtOffset(coord);
Transform tileTransform = tile3D.Transform;
tileTransform.origin.y = TileWorld.GetHeightAtOffset(coord);
tile3D.Transform = tileTransform;
@ -191,7 +190,6 @@ public class StreamContainer : Spatial {
Transform tileTransform = tile3D.Transform;
tileTransform.origin.y = TileWorld.GetHeightAtOffset(offsetCoords);
tile3D.Transform = tileTransform;
tile3D.Type = TileWorld.GetTileTypeAtOffset(offsetCoords);
_tileToInstanceIndex[tile3D] = _tileToInstanceIndex.Count;
@ -238,7 +236,6 @@ public class StreamContainer : Spatial {
int instanceIndex = _tileToInstanceIndex[tile3D];
_tileMultiMesh.Multimesh.SetInstanceTransform(instanceIndex, _deactivatedTileTransform);
tile3D.Type = HexTile3D.TileType.Undefined;
_unusedTiles.Enqueue(tile3D);
_coordToTile.Remove(coord);
RemovedCoords.Add(coord);

View File

@ -372,16 +372,6 @@ public class TileWorld : Spatial {
&& (int)Math.Clamp(offsetCoord.y, -(float)Size / 2, (float)Size / 2 - 1) == (int)offsetCoord.y);
}
public HexTile3D.TileType GetTileTypeAtOffset(Vector2 offsetCoord) {
if (!IsOffsetCoordValid(offsetCoord)) {
return HexTile3D.TileType.Undefined;
}
return HexTile3D.ValidTileTypes[_tileTypeRandom.Next(HexTile3D.ValidTileTypes.Length)];
}
public Vector2 OffsetToTextureCoord(Vector2 offsetCoord) {
Vector2 mapSize = Vector2.One * Size;
Vector2 textureCoord = (offsetCoord + mapSize / 2).PosMod(mapSize);

View File

@ -2,7 +2,7 @@
[ext_resource path="res://scenes/TileWorld.cs" type="Script" id=1]
[ext_resource path="res://icon.png" type="Texture" id=2]
[ext_resource path="res://materials/IslandColorRampShader.tres" type="Material" id=3]
[ext_resource path="res://materials/WorldTileTypeMaterial.tres" type="Material" id=3]
[ext_resource path="res://materials/IslandHeightmapFalloffShader.tres" type="Material" id=4]
[ext_resource path="res://entities/rockB.tscn" type="PackedScene" id=5]
[ext_resource path="res://entities/rockC.tscn" type="PackedScene" id=6]

View File

@ -19,10 +19,9 @@ public class World : Spatial {
public int ChunkSize = 14;
public const int NumChunkRows = 3;
public const int NumChunkColumns = NumChunkRows;
private static readonly Color RockColor = new(0.5f, 0.5f, 0.4f);
private static readonly Color GrassColor = new(0, 0.4f, 0);
private static readonly Color DarkGrassColor = new(0.05882353f, 0.5411765f, 0.05882353f);
private static readonly Color LightWaterColor = new(0.05882353f, 0.05882353f, 0.8627451f);
private readonly System.Collections.Generic.Dictionary<int, HexTile3D.TileTypeInfo> _tileTypeInfos = new();
private readonly Godot.Collections.Dictionary<Vector2, WorldChunk> _cachedWorldChunks;
private readonly List<Vector2> _addedChunkIndices = new();
@ -41,7 +40,6 @@ public class World : Spatial {
// delegate void OnCoordClicked(Vector2 world_pos);
// other members
private Vector2 _centerPlaneCoord;
private Vector2 _chunkIndexNorthEast;
private Vector2 _chunkIndexSouthWest;
private Array<Spatial> _grassAssets;
@ -62,7 +60,6 @@ public class World : Spatial {
public GenerationState State = GenerationState.Empty;
public Vector2 WorldTextureCoordinateOffset;
// ui elements
// scene nodes
@ -124,6 +121,24 @@ public class World : Spatial {
foreach (Spatial asset in GetNode<Node>("Assets/Trees").GetChildren()) {
_treeAssets.Add(asset);
}
_tileTypeInfos[0] = new HexTile3D.TileTypeInfo("Undefined", Colors.Black, 0xffff);
LoadTileTypeInfo("DeepWater", (int)Entity.EntityMaskEnum.Water);
LoadTileTypeInfo("Water", (int)Entity.EntityMaskEnum.Water);
LoadTileTypeInfo("LightWater", (int)Entity.EntityMaskEnum.Water);
LoadTileTypeInfo("Sand", (int)Entity.EntityMaskEnum.Ground);
LoadTileTypeInfo("Grass", (int)Entity.EntityMaskEnum.Ground);
LoadTileTypeInfo("Forest", (int)Entity.EntityMaskEnum.Ground);
LoadTileTypeInfo("Rock", (int)Entity.EntityMaskEnum.Ground);
LoadTileTypeInfo("Sand", (int)Entity.EntityMaskEnum.Ground);
}
private void LoadTileTypeInfo(string tileTypeName, ushort tileTypeMask) {
ShaderMaterial worldTileTypeShaderMaterial =
GD.Load<ShaderMaterial>("res://materials/WorldTileTypeMaterial.tres");
Color tileTypeColor = (Color)worldTileTypeShaderMaterial.GetShaderParam(tileTypeName + "Color");
_tileTypeInfos[tileTypeColor.ToRgba32()] = new HexTile3D.TileTypeInfo(tileTypeName, tileTypeColor, tileTypeMask);
}
public void InitNoiseGenerator() {
@ -232,18 +247,18 @@ public class World : Spatial {
foreach (int textureCoordU in Enumerable.Range(0, chunk.Size)) {
foreach (int textureCoordV in Enumerable.Range(0, chunk.Size)) {
Color colorValue = chunk.TileTypeImage.GetPixel(textureCoordU, textureCoordV);
Vector2 textureCoord = new(textureCoordU, textureCoordV);
Vector2 offsetCoord = chunk.ChunkIndex * ChunkSize + textureCoord;
if (IsColorEqualApprox(colorValue, RockColor)) {
HexTile3D.TileTypeInfo tileTypeInfo = GetTileTypeInfoAtOffset(offsetCoord);
if (tileTypeInfo.Name == "Rock") {
Spatial rockAsset = SelectAsset(textureCoord, _rockAssets, environmentRandom, 0.15);
if (rockAsset != null) {
chunk.Entities.AddChild(rockAsset);
MarkCellUnwalkable(HexGrid.GetHexAtOffset(offsetCoord));
}
} else if (IsColorEqualApprox(colorValue, GrassColor) ||
IsColorEqualApprox(colorValue, DarkGrassColor)) {
} else if (tileTypeInfo.Name == "Grass" || tileTypeInfo.Name == "DarkGrass") {
Spatial grassAsset = SelectAsset(textureCoord, _grassAssets, environmentRandom, 0.15);
if (grassAsset != null) {
chunk.Entities.AddChild(grassAsset);
@ -431,7 +446,7 @@ public class World : Spatial {
_heightmapTexture.CreateFromImage(_heightmapImage);
_viewTileTypeTexture = new ImageTexture();
_viewTileTypeTexture.CreateFromImage(_tileTypeMapImage);
_viewTileTypeTexture.CreateFromImage(_tileTypeMapImage, (uint)Texture.FlagsEnum.ConvertToLinear);
WorldTextureCoordinateOffset = _chunkIndexSouthWest * worldChunkSize;
@ -463,27 +478,46 @@ public class World : Spatial {
public float GetHexCost(Entity entity, HexCell cell) {
float nextHexCost = HexGrid.GetHexCost(cell);
if (nextHexCost != 0) {
Vector2 nextOffset = cell.OffsetCoords;
Vector2 chunkIndex = GetChunkIndexFromOffsetCoord(nextOffset);
Color tileTypeColor = GetTileTypeColorAtOffset(nextOffset);
if (!_cachedWorldChunks.ContainsKey(chunkIndex)) {
return 0;
}
WorldChunk chunk = _cachedWorldChunks[chunkIndex];
Vector2 textureCoordinate = nextOffset - Vector2.One * ChunkSize * chunkIndex;
Color tileTypeColor = chunk.TileTypeImage.GetPixel((int)textureCoordinate.x, (int)textureCoordinate.y);
if (!IsColorEqualApprox(tileTypeColor, GrassColor) &&
!IsColorEqualApprox(tileTypeColor, DarkGrassColor)) {
if (_tileTypeInfos.TryGetValue(tileTypeColor.ToRgba32(), out HexTile3D.TileTypeInfo info)) {
int tileTypeMask = info.TileTypeMask;
if ((entity.EntityMask ^ tileTypeMask) != 0) {
nextHexCost = 0;
}
}
// GD.Print("Could not find tile type info for color " + tileTypeColor);
}
return nextHexCost;
}
private HexTile3D.TileTypeInfo GetTileTypeInfoAtOffset(Vector2 offsetCoord) {
Color tileTypeColor = GetTileTypeColorAtOffset(offsetCoord);
if (_tileTypeInfos.TryGetValue(tileTypeColor.ToRgba32(), out HexTile3D.TileTypeInfo info)) {
return info;
}
return _tileTypeInfos[0];
}
public Color GetTileTypeColorAtOffset(Vector2 offsetCoord) {
Vector2 chunkIndex = GetChunkIndexFromOffsetCoord(offsetCoord);
if (!_cachedWorldChunks.ContainsKey(chunkIndex)) {
return Colors.Black;
}
WorldChunk chunk = _cachedWorldChunks[chunkIndex];
Vector2 textureCoordinate = offsetCoord - Vector2.One * ChunkSize * chunkIndex;
Color tileTypeColor = chunk.TileTypeImage.GetPixel((int)textureCoordinate.x, (int)textureCoordinate.y);
return tileTypeColor;
}
public float GetMoveCost(Entity entity, HexCell currentHex, HexCell nextHex) {
if (GetHexCost(entity, nextHex) == 0) {
return 0;
@ -706,11 +740,21 @@ public class World : Spatial {
}
public void OnTileClicked(HexTile3D tile) {
if (State != GenerationState.Done) {
return;
}
EmitSignal("TileClicked", tile);
}
public void OnTileHovered(HexTile3D tile) {
if (State != GenerationState.Done) {
return;
}
EmitSignal("TileHovered", tile);
HexTile3D.TileTypeInfo tileTypeInfo = GetTileTypeInfoAtOffset(tile.OffsetCoords);
GD.Print("Hover on TileType " + tileTypeInfo.Name + " color: " + tileTypeInfo.Color);
}
public void OnBlockingSpatialRemoved(Spatial spatialNode) {

View File

@ -31,7 +31,7 @@ public class WorldChunk : Spatial {
public Viewport HeightmapOffscreenViewport;
[Export] public Texture NavigationMap;
public bool NoiseTextureCheckerboardOverlay = true;
public bool NoiseTextureCheckerboardOverlay = false;
// signals
[Signal]

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=10 format=2]
[ext_resource path="res://scenes/WorldChunk.cs" type="Script" id=1]
[ext_resource path="res://materials/IslandColorRampShader.tres" type="Material" id=2]
[ext_resource path="res://materials/WorldTileTypeMaterial.tres" type="Material" id=2]
[ext_resource path="res://assets/TestHeightmap.tres" type="Texture" id=3]
[ext_resource path="res://assets/4x4checkerColor.png" type="Texture" id=4]
[ext_resource path="res://addons/gdhexgrid/icon.png" type="Texture" id=6]

View File

@ -12,7 +12,6 @@ public class NavigationTests : Spatial {
private EditorUI _editorUi;
private World _world;
private StreamContainer _streamContainer;
private Player _player;
private NavigationComponent _playerNavigationComponent;

View File

@ -2,7 +2,7 @@ extends CenterContainer
onready var SeedLineEdit: LineEdit
onready var ChunkSizeSpinBox: SpinBox
onready var GameScene: PackedScene = preload ("res://scenes/Game.tscn")
#onready var GameScene: PackedScene = preload ("res://scenes/Game.tscn")
func _ready():
SeedLineEdit = find_node("SeedLineEdit")
@ -19,8 +19,8 @@ func _on_RefreshSeedButton_pressed():
func _on_GenerateButton_pressed():
var game_scene_instance = GameScene.instance()
# var game_scene_instance = GameScene.instance()
self.visible = false
get_tree().get_root().add_child(game_scene_instance)
game_scene_instance.StartNewGame(int(SeedLineEdit.text), int(ChunkSizeSpinBox.value))
# get_tree().get_root().add_child(game_scene_instance)
# game_scene_instance.StartNewGame(int(SeedLineEdit.text), int(ChunkSizeSpinBox.value))