From ad54c1706adcba9c7687faea87d39dff3b03bd83 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Tue, 28 Jul 2020 20:41:43 +0100 Subject: [PATCH] Added grass growth using random ticks --- project/blocky_game/blocks/voxel_library.tres | 4 + project/blocky_game/blocky_game.gd | 1 + project/blocky_game/blocky_game.tscn | 8 +- project/blocky_game/random_ticks.gd | 82 +++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 project/blocky_game/random_ticks.gd diff --git a/project/blocky_game/blocks/voxel_library.tres b/project/blocky_game/blocks/voxel_library.tres index 89ee1c7..1001799 100644 --- a/project/blocky_game/blocks/voxel_library.tres +++ b/project/blocky_game/blocks/voxel_library.tres @@ -22,24 +22,28 @@ collision_aabbs = [ AABB( 0, 0, 0, 1, 1, 1 ) ] voxel_name = "grass" geometry_type = 2 custom_mesh = ExtResource( 1 ) +random_tickable = true collision_aabbs = [ AABB( 0, 0, 0, 1, 1, 1 ) ] [sub_resource type="Voxel" id=4] voxel_name = "log_x" geometry_type = 2 custom_mesh = ExtResource( 4 ) +random_tickable = true collision_aabbs = [ AABB( 0, 0, 0, 1, 1, 1 ) ] [sub_resource type="Voxel" id=5] voxel_name = "log_y" geometry_type = 2 custom_mesh = ExtResource( 3 ) +random_tickable = true collision_aabbs = [ AABB( 0, 0, 0, 1, 1, 1 ) ] [sub_resource type="Voxel" id=6] voxel_name = "log_z" geometry_type = 2 custom_mesh = ExtResource( 5 ) +random_tickable = true collision_aabbs = [ AABB( 0, 0, 0, 1, 1, 1 ) ] [sub_resource type="Voxel" id=7] diff --git a/project/blocky_game/blocky_game.gd b/project/blocky_game/blocky_game.gd index 8f245fc..546b088 100644 --- a/project/blocky_game/blocky_game.gd +++ b/project/blocky_game/blocky_game.gd @@ -10,3 +10,4 @@ func _unhandled_input(event): if event.scancode == KEY_L: # Toggle shadows _light.shadow_enabled = not _light.shadow_enabled + diff --git a/project/blocky_game/blocky_game.tscn b/project/blocky_game/blocky_game.tscn index 51448fb..af3cf2c 100644 --- a/project/blocky_game/blocky_game.tscn +++ b/project/blocky_game/blocky_game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=13 format=2] +[gd_scene load_steps=14 format=2] [ext_resource path="res://blocky_game/blocks/voxel_library.tres" type="VoxelLibrary" id=1] [ext_resource path="res://blocky_game/blocks/terrain_material.tres" type="Material" id=2] @@ -9,6 +9,7 @@ [ext_resource path="res://blocky_game/blocks/stairs/stairs_nx.obj" type="ArrayMesh" id=7] [ext_resource path="res://blocky_terrain/debug_info.gd" type="Script" id=8] [ext_resource path="res://blocky_game/blocks/terrain_material_foliage.tres" type="Material" id=9] +[ext_resource path="res://blocky_game/random_ticks.gd" type="Script" id=10] [sub_resource type="ProceduralSky" id=1] sky_top_color = Color( 0.268204, 0.522478, 0.847656, 1 ) @@ -52,6 +53,7 @@ environment = SubResource( 2 ) stream = SubResource( 3 ) voxel_library = ExtResource( 1 ) viewer_path = NodePath("../CharacterAvatar") +generate_collisions = false material/0 = ExtResource( 2 ) material/1 = ExtResource( 3 ) material/2 = ExtResource( 9 ) @@ -65,6 +67,7 @@ script = ExtResource( 8 ) [node name="MeshInstance" type="MeshInstance" parent="."] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 7.3175 ) +visible = false mesh = ExtResource( 7 ) material/0 = null @@ -74,3 +77,6 @@ gravity = 40.0 jump_force = 8.0 head = NodePath("../CharacterAvatar/Camera") terrain = NodePath("../VoxelTerrain") + +[node name="RandomTicks" type="Node" parent="."] +script = ExtResource( 10 ) diff --git a/project/blocky_game/random_ticks.gd b/project/blocky_game/random_ticks.gd new file mode 100644 index 0000000..714c3cb --- /dev/null +++ b/project/blocky_game/random_ticks.gd @@ -0,0 +1,82 @@ +# Implements random cellular automata behavior of the terrain, +# such as growth of grass and crops, fire etc. + +extends Node + +# Takes effect in a large radius around the player +const RADIUS = 100 +# How many voxels are affected per frame +const VOXELS_PER_FRAME = 256 + +onready var _terrain = get_node("../VoxelTerrain") +onready var _avatar = get_node("../CharacterAvatar") +onready var _voxel_tool = _terrain.get_voxel_tool() + +var _grass_dirs = [ + Vector3(-1, 0, 0), + Vector3(1, 0, 0), + Vector3(0, 0, -1), + Vector3(0, 0, 1), + Vector3(-1, 0, -1), + Vector3(1, 0, -1), + Vector3(-1, 0, 1), + Vector3(1, 0, 1), + + Vector3(-1, 1, 0), + Vector3(1, 1, 0), + Vector3(0, 1, -1), + Vector3(0, 1, 1), + Vector3(-1, 1, -1), + Vector3(1, 1, -1), + Vector3(-1, 1, 1), + Vector3(1, 1, 1), + + Vector3(-1, -1, 0), + Vector3(1, -1, 0), + Vector3(0, -1, -1), + Vector3(0, -1, 1), + Vector3(-1, -1, -1), + Vector3(1, -1, -1), + Vector3(-1, -1, 1), + Vector3(1, -1, 1) +] + + +func _ready(): + _voxel_tool.set_channel(VoxelBuffer.CHANNEL_TYPE) + + +func _process(delta): + #var time_before = OS.get_ticks_usec() + + _grass_dirs.shuffle() + + var center = _avatar.transform.origin.floor() + var r = RADIUS + var area = AABB(center - Vector3(r, r, r), 2 * Vector3(r, r, r)) + _voxel_tool.run_blocky_random_tick( + area, VOXELS_PER_FRAME, funcref(self, "_random_tick_callback"), 16) + + #var time_spent = OS.get_ticks_usec() - time_before + #print("Spent ", time_spent) + + +func _random_tick_callback(pos: Vector3, value: int): + if value == 2: + # Grass + var attempts = 1 + var ra = randf() + if ra < 0.15: + attempts = 2 + if ra < 0.03: + attempts = 3 + + for i in attempts: + for di in len(_grass_dirs): + var npos = pos + _grass_dirs[di] + var nv = _voxel_tool.get_voxel(npos) + if nv == 1: + var above = _voxel_tool.get_voxel(npos + Vector3(0, 1, 0)) + if above == 0: + _voxel_tool.set_voxel(npos, 2) + break