ajout d'un terrain infini et la possibilité de planter n'importe où

This commit is contained in:
2025-11-30 16:53:07 +01:00
parent 72ffa0b222
commit 8917a02a7b
63 changed files with 2847 additions and 1190 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cd62k5urdpw3i"
path="res://.godot/imported/blue_rect.png-d2bf0f89bd9a318145a3150338e6ed14.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://stages/terrain/planet/assets/textures/blue_rect.png"
dest_files=["res://.godot/imported/blue_rect.png-d2bf0f89bd9a318145a3150338e6ed14.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bvangyp301tsp"
path="res://.godot/imported/green_rect.png-2cde15567ae810adb5864776d70ef438.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://stages/terrain/planet/assets/textures/green_rect.png"
dest_files=["res://.godot/imported/green_rect.png-2cde15567ae810adb5864776d70ef438.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://yl4dg6gerykb"
path="res://.godot/imported/green_tiles.png-24cb2e8d3d77d0f127478dc375fc7791.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://stages/terrain/planet/assets/textures/green_tiles.png"
dest_files=["res://.godot/imported/green_tiles.png-24cb2e8d3d77d0f127478dc375fc7791.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bi08trir23od2"
path="res://.godot/imported/red_rect.png-2c97ffc5003cb92590914f11ff4ed41d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://stages/terrain/planet/assets/textures/red_rect.png"
dest_files=["res://.godot/imported/red_rect.png-2c97ffc5003cb92590914f11ff4ed41d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ddecvei4l62gn"
path="res://.godot/imported/red_tiles.png-0bb5056d42a3159163beb701fb8aa247.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://stages/terrain/planet/assets/textures/red_tiles.png"
dest_files=["res://.godot/imported/red_tiles.png-0bb5056d42a3159163beb701fb8aa247.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=false
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://02nuoqleo4yu"
path="res://.godot/imported/rock_cristal_texture.png-33ee9694873f9aa2e8604c502b12dee5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://stages/terrain/planet/assets/textures/rock_cristal_texture.png"
dest_files=["res://.godot/imported/rock_cristal_texture.png-33ee9694873f9aa2e8604c502b12dee5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bmdb63witojeg"
path="res://.godot/imported/round_red_tiles.png-7f838ac911f20be784ac93821bd5d5ba.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://stages/terrain/planet/assets/textures/round_red_tiles.png"
dest_files=["res://.godot/imported/round_red_tiles.png-7f838ac911f20be784ac93821bd5d5ba.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -1,48 +1,6 @@
[gd_scene load_steps=10 format=3 uid="uid://tsi5j1uxppa4"]
[gd_scene load_steps=2 format=3 uid="uid://tsi5j1uxppa4"]
[ext_resource type="Script" uid="uid://d1mp5sguc0b6u" path="res://stages/terrain/planet/scripts/planet.gd" id="1_y7d8a"]
[ext_resource type="Shader" uid="uid://bglep64ppn74p" path="res://common/vfx/materials/shaders/textures_data_filter.gdshader" id="3_6qoee"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_3v4ta"]
frequency = 0.04
offset = Vector3(0, 10, 0)
fractal_weighted_strength = 1.0
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_7jtco"]
width = 50
height = 50
noise = SubResource("FastNoiseLite_3v4ta")
seamless_blend_skirt = 0.0
[sub_resource type="Gradient" id="Gradient_ydx6d"]
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_6cs2h"]
gradient = SubResource("Gradient_ydx6d")
width = 1
[sub_resource type="Gradient" id="Gradient_qxify"]
offsets = PackedFloat32Array(0)
colors = PackedColorArray(0, 0, 0, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_sd6ll"]
gradient = SubResource("Gradient_qxify")
width = 1
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hyapw"]
shader = ExtResource("3_6qoee")
shader_parameter/data_texture = SubResource("NoiseTexture2D_7jtco")
shader_parameter/data_texture_size = Vector2(120, 120)
shader_parameter/data_texture_threshold = 0.5
shader_parameter/texture_0 = SubResource("GradientTexture1D_6cs2h")
shader_parameter/texture_1 = SubResource("GradientTexture1D_sd6ll")
shader_parameter/texture_scale = 5.0
[node name="Planet" type="Node2D"]
script = ExtResource("1_y7d8a")
[node name="Polygon2D2" type="Polygon2D" parent="."]
visible = false
material = SubResource("ShaderMaterial_hyapw")
position = Vector2(-10, -10)
polygon = PackedVector2Array(10, 10, 10, 110, 110, 110, 110, 10)

View File

@@ -0,0 +1,9 @@
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://b3vnia5tb6pil"]
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_4m73r"]
[ext_resource type="Texture2D" uid="uid://bnrjnvceprxfn" path="res://stages/terrain/planet/assets/textures/garden_background_texture.png" id="2_4m73r"]
[resource]
shader = ExtResource("1_4m73r")
shader_parameter/red_overlay_tex = ExtResource("2_4m73r")
shader_parameter/scale = 0.006944444

View File

@@ -0,0 +1,9 @@
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://85ap1buim1ha"]
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_v8wor"]
[ext_resource type="Texture2D" uid="uid://c3t26nlbnkxg7" path="res://stages/terrain/planet/assets/textures/garden_decontamined_background_texture.png" id="2_v8wor"]
[resource]
shader = ExtResource("1_v8wor")
shader_parameter/red_overlay_tex = ExtResource("2_v8wor")
shader_parameter/scale = 0.006944444

View File

@@ -0,0 +1,9 @@
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://dpxu8yeee4qi1"]
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_6vcas"]
[ext_resource type="Texture2D" uid="uid://bnrjnvceprxfn" path="res://stages/terrain/planet/assets/textures/garden_background_texture.png" id="2_x0w2y"]
[resource]
shader = ExtResource("1_6vcas")
shader_parameter/red_overlay_tex = ExtResource("2_x0w2y")
shader_parameter/scale = 0.006944444

View File

@@ -0,0 +1,11 @@
[gd_resource type="ShaderMaterial" load_steps=4 format=3 uid="uid://d365ovfmi3d0s"]
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_xr5ia"]
[ext_resource type="Texture2D" uid="uid://beqx4rmgthkql" path="res://stages/terrain/planet/assets/textures/rock_background_texture.png" id="2_ieaec"]
[ext_resource type="Texture2D" uid="uid://02nuoqleo4yu" path="res://stages/terrain/planet/assets/textures/rock_cristal_texture.png" id="2_sc014"]
[resource]
shader = ExtResource("1_xr5ia")
shader_parameter/red_overlay_tex = ExtResource("2_ieaec")
shader_parameter/green_overlay_tex = ExtResource("2_sc014")
shader_parameter/scale = 0.006944444

File diff suppressed because it is too large Load Diff

View File

@@ -1,137 +1,164 @@
@tool
extends Node2D
class_name Chunk
const UNIT_PER_PIXEL = 30
var coord : Vector2i
var size : Vector2i
var planet : Planet
var wall_threshold = 0.4
var noise_image : Image
var entity_generated : bool
var planet_seed : int
var wall_threshold = 0.6
var decontamination_threshold = 0.15
var cristal_threshold = 0.08
var rock_noise_image : Noise = null
var decontamination_noise_image : Noise = null
const CHUNK_TEXTURE_SCALE : float = 3.0
const DEFAULT_CHUNK_BACKGROUND_MATERIAL : ShaderMaterial = preload("res://stages/terrain/planet/resources/materials/default_chunk_material.tres")
const NOISE_IMAGE_SIZE := 150
const LOOT_NUMBER : Array[int] = [2,3,4]
const LOOT_ITEM_NUMBER : Array[int] = [1,2]
var chunk_background_material
const ROCK_NOISE_FREQUENCY := 0.01
const DECONTAMINATION_NOISE_FREQUENCY := 0.01
var generation_thread: Thread
@export_tool_button("Update", "Callable") var update_action = func():
planet_seed = randi()
setup()
var data : ChunkData
func _init(
_coord : Vector2i,
_size : Vector2i,
_planet : Planet,
_entity_generated = false
_data : ChunkData,
_planet : Planet = null,
):
coord = _coord
size = _size
planet = _planet
entity_generated = _entity_generated
planet = _planet
if planet:
planet_seed = planet.data.planet_seed
data = _data
func _ready():
noise_image = generate_noise()
generate_background_sprite()
global_position = coord * size
generate_walls()
if not entity_generated:
generate_loot()
setup()
func generate_noise() -> Image:
var image_size = Vector2i(
roundi(float(size.x) / UNIT_PER_PIXEL),
roundi(float(size.y) / UNIT_PER_PIXEL)
)
var noise: FastNoiseLite = FastNoiseLite.new()
noise.seed = planet.data.planet_seed
noise.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
noise.frequency = 0.05
noise.fractal_weighted_strength = 1.0
noise.offset = Vector3(
image_size.x * coord.x,
image_size.y * coord.y,
1
)
func setup():
rock_noise_image = generate_noise(planet_seed + 1, ROCK_NOISE_FREQUENCY)
decontamination_noise_image = generate_noise(planet_seed + 2, DECONTAMINATION_NOISE_FREQUENCY)
var image = noise.get_image(
image_size.x,
image_size.y,
1.0,
)
generation_thread = Thread.new()
generation_thread.start(
func ():
generate_rocks()
generate_ground()
generate_decontamination()
)
return image
global_position = data.chunk_coord * (Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE)
queue_redraw()
func generate_background_sprite() -> Polygon2D:
var sprite :Polygon2D = generate_polygon_sprite()
func unload():
for x in range(Planet.CHUNK_TILE_SIZE):
for y in range(Planet.CHUNK_TILE_SIZE):
var global_coord = Vector2i(x, y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord
planet.rock_layer.erase_cell(global_coord)
planet.ground_layer.erase_cell(global_coord)
planet.decontamination_layer.erase_cell(global_coord)
sprite.texture = ImageTexture.create_from_image(noise_image)
# Debug
# func _draw():
# draw_rect(
# Rect2(Vector2.ZERO, Vector2.ONE * Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE),
# Color.WHITE,
# false,
# 3
# )
var background_material = DEFAULT_CHUNK_BACKGROUND_MATERIAL.duplicate_deep()
# for x in range(NOISE_IMAGE_SIZE):
# for y in range(NOISE_IMAGE_SIZE):
# var noise_value = rock_noise_image.get_noise_2d(
# x,
# y
# )
# draw_rect(
# Rect2(Vector2i(x,y) * Planet.CHUNK_SIZE / NOISE_IMAGE_SIZE, Vector2i.ONE * Planet.CHUNK_SIZE / NOISE_IMAGE_SIZE),
# Color.WHITE * ((noise_value+1)/2),
# true,
# )
background_material.set_shader_parameter("data_texture", ImageTexture.create_from_image(noise_image))
background_material.set_shader_parameter("data_texture_size", size)
background_material.set_shader_parameter("data_texture_threshold", wall_threshold)
background_material.set_shader_parameter("texture_scale", CHUNK_TEXTURE_SCALE)
func generate_noise(
noise_seed : int,
frequency := 0.01
) -> Noise:
var noise_image_size := NOISE_IMAGE_SIZE * Vector2i.ONE
var noise: FastNoiseLite = FastNoiseLite.new()
noise.seed = noise_seed
noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
noise.frequency = 0.01
noise.fractal_type = FastNoiseLite.FRACTAL_NONE
noise.fractal_weighted_strength = 1.0
noise.offset = Vector3(
noise_image_size.x * data.chunk_coord.x,
noise_image_size.y * data.chunk_coord.y,
1
)
sprite.material = background_material
return noise
return sprite
func get_tile_value_from_noise(tile_position : Vector2i, noise : Noise) -> float:
var val = noise.get_noise_2d(
floori(float(tile_position.x * NOISE_IMAGE_SIZE) / Planet.CHUNK_TILE_SIZE),
floori(float(tile_position.y * NOISE_IMAGE_SIZE) / Planet.CHUNK_TILE_SIZE)
)
return (val + 1)/2
func generate_polygon_sprite() -> Polygon2D:
var sprite = Polygon2D.new()
sprite.polygon = PackedVector2Array([
Vector2(0,0),
Vector2(size.x, 0),
Vector2(size.x, size.y),
Vector2(0, size.y),
])
func generate_rocks():
var cristals : Array[Vector2i] = []
var rocks : Array[Vector2i] = []
for x in range(Planet.CHUNK_TILE_SIZE):
for y in range(Planet.CHUNK_TILE_SIZE):
var tile_type := get_generated_rock_type(Vector2i(x, y))
var global_coord = Vector2i(x, y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord
if tile_type == RockLayer.TileType.CRISTAL:
cristals.append(global_coord)
elif tile_type == RockLayer.TileType.ROCK:
rocks.append(global_coord)
planet.rock_layer.mutex.lock()
planet.rock_layer.place_rocks(cristals, RockLayer.TileType.CRISTAL)
planet.rock_layer.place_rocks(rocks, RockLayer.TileType.ROCK)
planet.rock_layer.mutex.unlock()
func get_generated_rock_type(coord : Vector2i) -> RockLayer.TileType:
var tile_value : float = get_tile_value_from_noise(coord, rock_noise_image)
var saved_diff := data.get_rock_tile_diff(coord)
sprite.z_index = -100
if (
(saved_diff == ChunkData.TileDiff.PRESENT or tile_value < wall_threshold)
and saved_diff != ChunkData.TileDiff.ABSENT
):
return RockLayer.TileType.CRISTAL if tile_value < cristal_threshold else RockLayer.TileType.ROCK
return RockLayer.TileType.EMPTY
add_child(sprite)
func generate_ground():
planet.ground_layer.mutex.lock()
for x in range(Planet.CHUNK_TILE_SIZE):
for y in range(Planet.CHUNK_TILE_SIZE):
planet.ground_layer.place_ground(Vector2i(x,y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord)
planet.ground_layer.mutex.unlock()
return sprite
func generate_decontamination():
var decontamination_tiles : Array[Vector2i] = []
for x in range(Planet.CHUNK_TILE_SIZE):
for y in range(Planet.CHUNK_TILE_SIZE):
var coord = Vector2i(x,y)
var tile_value : float = get_tile_value_from_noise(coord, decontamination_noise_image)
var saved_diff := data.get_decontamination_tile_diff(coord)
if (
(saved_diff == ChunkData.TileDiff.PRESENT or tile_value < decontamination_threshold)
and saved_diff != ChunkData.TileDiff.ABSENT
):
decontamination_tiles.append(Vector2i(x,y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord)
planet.decontamination_layer.mutex.lock()
planet.decontamination_layer.place_decontaminations(decontamination_tiles)
planet.decontamination_layer.mutex.unlock()
func generate_walls():
var static_body = StaticBody2D.new()
add_child(static_body)
var wall_resolution_factor = 25
for x in range(1, size.x, wall_resolution_factor):
for y in range(1, size.y, wall_resolution_factor):
if is_wall(Vector2(x, y)):
var new_collision_shape = CollisionShape2D.new()
new_collision_shape.shape = CircleShape2D.new()
new_collision_shape.shape.radius = wall_resolution_factor / 2.
static_body.add_child(new_collision_shape)
new_collision_shape.global_position = Vector2i(x, y) + coord * size + Vector2i.ONE * 5
func generate_loot(number : int = LOOT_NUMBER.pick_random()):
for i in range(number):
var loot : UndergroundLoot = (UndergroundLootData.SCENE.instantiate() as UndergroundLoot)
loot.item_number = LOOT_ITEM_NUMBER.pick_random()
var max_placement_try = 10
var valid_coord = false
while max_placement_try > 0 and not valid_coord:
var random_position = Vector2(
randf_range(0, size.x),
randf_range(0, size.y)
)
if not is_wall(random_position):
planet.add_entity(loot, random_position + Vector2(coord * size))
valid_coord = true
else :
max_placement_try -= 1
func get_pixel_point(point : Vector2) -> Vector2i:
var vec : Vector2 = Vector2(point) / UNIT_PER_PIXEL - Vector2.ONE
return Vector2i(
roundi(vec.x + 0.5),
roundi(vec.y + 0.5)
)
func is_wall(game_point : Vector2) -> bool:
var pixel_point = get_pixel_point(game_point)
return noise_image.get_pixel(pixel_point.x, pixel_point.y).r < wall_threshold
func _exit_tree():
generation_thread.wait_to_finish()

View File

@@ -0,0 +1,62 @@
extends Resource
class_name ChunkData
enum TileDiff { NO_DIFF,PRESENT,ABSENT }
@export var chunk_coord : Vector2i
@export var rock_tiles_diff : Dictionary[String, TileDiff]
@export var decontamination_tiles_diff : Dictionary[String, TileDiff]
func _init(
_chunk_coord : Vector2i
):
chunk_coord = _chunk_coord
#region ------------------ Generic Tile ------------------
func get_coord_key(coord : Vector2i) -> String:
return "%d:%d" % [coord.x, coord.y]
func get_tile_diff(
coord : Vector2i,
tiles_diff : Dictionary[String, TileDiff]
) -> TileDiff:
if not has_diff(coord, tiles_diff):
return TileDiff.NO_DIFF
return tiles_diff[get_coord_key(coord)]
func update_tile_diff(
coord : Vector2i,
diff : TileDiff,
tiles_diff : Dictionary[String, TileDiff]
):
tiles_diff[get_coord_key(coord)] = diff
func has_diff(
coord : Vector2i,
tiles_diff : Dictionary[String, TileDiff]
):
return tiles_diff.has(get_coord_key(coord))
#region ------------------ Rock ------------------
func get_rock_tile_diff(coord : Vector2i) -> TileDiff:
return get_tile_diff(coord, rock_tiles_diff)
func update_rock_tile_diff(coord : Vector2i, diff : TileDiff):
update_tile_diff(coord, diff, rock_tiles_diff)
func has_rock_tile_diff(coord : Vector2i):
return has_diff(coord, rock_tiles_diff)
#region ------------------ Decontamination ------------------
func get_decontamination_tile_diff(coord : Vector2i) -> TileDiff:
return get_tile_diff(coord, decontamination_tiles_diff)
func update_decontamination_tile_diff(coord : Vector2i, diff : TileDiff):
update_tile_diff(coord, diff, decontamination_tiles_diff)
func has_decontamination_tile_diff(coord : Vector2i):
return has_diff(coord, decontamination_tiles_diff)

View File

@@ -0,0 +1 @@
uid://clqa88okc325t

View File

@@ -1,48 +1,18 @@
extends Node2D
class_name Garden
const GARDEN_TEXTURE_SCALE : float = 3.0
var contamination_material : ShaderMaterial = preload("res://stages/terrain/planet/resources/materials/ground_contamination.tres")
var contamination_sprite : Polygon2D
var contamination_texture : Texture2D
var decontamination_surface : float
var plants : Array[Plant]
var planet_data : PlanetData
var size = PlanetData.DEFAULT_GARDEN_SIZE
func _init(_planet_data : PlanetData, _initial_plants : Array[Plant] = []):
planet_data = _planet_data
plants = _initial_plants
# update_garden_score()
func _ready():
contamination_sprite = generate_contamination_terrain_sprite()
decontamination_surface = planet_data.get_decontamination_surface()
for p in plants:
p.harvested.connect(_on_plant_harvested)
p.state_changed.connect(_on_plant_state_changed)
# update_garden_score()
func generate_contamination_terrain_sprite() -> Polygon2D:
if not planet_data.garden_contamination:
planet_data.generate_default_contamination()
var sprite :Polygon2D = generate_polygon_sprite(size, 1)
contamination_texture = ImageTexture.create_from_image(planet_data.garden_contamination.image)
contamination_material.set_shader_parameter("data_texture", contamination_texture)
contamination_material.set_shader_parameter("data_texture_size", size)
contamination_material.set_shader_parameter("texture_scale", GARDEN_TEXTURE_SCALE)
sprite.material = contamination_material
return sprite
func get_score():
var score = 0
@@ -88,30 +58,3 @@ func remove_plant(p: Plant):
func update_garden_score():
planet_data.garden_score = get_score()
func impact_contamination(impact_position : Vector2, impact_radius : int, contamination : bool = false):
planet_data.impact_contamination(impact_position, impact_radius, 0. if contamination else 1.)
if contamination_texture:
contamination_texture.update(planet_data.garden_contamination.image)
func generate_polygon_sprite(s : Vector2 = size, order : int = 0) -> Polygon2D:
var sprite = Polygon2D.new()
sprite.polygon = PackedVector2Array([
Vector2(0,0),
Vector2(s.x, 0),
Vector2(s.x, s.y),
Vector2(0, s.y),
])
sprite.z_index = -100 + order
add_child(sprite)
return sprite
func is_in_garden(point : Vector2) -> bool:
return planet_data.is_in_garden(point)
func is_there_contamination(point : Vector2) -> bool:
return planet_data.get_contamination(point) < 0.5

View File

@@ -8,7 +8,17 @@ signal pass_day_ended(planet : Planet)
const PASS_DAY_ANIMATION_TIME : float = 1.5
const DEFAULT_DAY_LIMIT : int = 7
const PLANET_TEXTURE_SCALE : float = 5.0
const TILE_SET : TileSet = preload("res://stages/terrain/planet/resources/planet_tileset.tres")
const TILE_SCALE = 1
const TILE_SIZE : int = roundi(TILE_SET.tile_size.x * TILE_SCALE)
const GROUND_TILE_MAP_MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/ground_planet_tilemap.tres")
const CONTAMINATION_TILE_MAP_MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/contamination_planet_tilemap.tres")
const ORIGIN_CHUNK_HOLE_RADIUS = 5
const CHUNK_TILE_SIZE : int = 20
const CHUNK_SIZE = CHUNK_TILE_SIZE * TILE_SIZE
const CHUNK_LOAD_DISTANCE : int = 1
const CHUNK_UNLOAD_DISTANCE : int = 2
@export_group("Loot")
@export var first_loot_number : int = 3
@@ -19,157 +29,178 @@ var data : PlanetData
var contamination_texture : ImageTexture
var day_limit = DEFAULT_DAY_LIMIT
var rock_layer : RockLayer
var ground_layer : GroundLayer
var decontamination_layer : DecontaminationLayer
var garden : Garden = null
var generated_chunks_objects : Array[Vector2i] = []
var generated_chunks : Dictionary[String,Chunk] = {}
func _init():
data = GameInfo.game_data.current_planet_data
func _ready():
data = GameInfo.game_data.current_planet_data
entity_container.position = PlanetData.DEFAULT_GARDEN_SIZE/2
load_entities(data.entities_saved_data)
entity_container.position = TILE_SIZE * CHUNK_TILE_SIZE * Vector2.ONE / 2
load_entities(data.entities_saved_data)
var plants : Array[Plant] = []
for e in entity_container.get_children():
if e is Plant:
plants.append(e)
var plants : Array[Plant] = []
for e in entity_container.get_children():
if e is Plant:
plants.append(e)
garden = Garden.new(data, plants)
add_child(garden)
garden = Garden.new(data, plants)
add_child(garden)
if len(GameInfo.game_data.unlocked_plant_types) == 0:
quota_reward.trigger_reward()
if len(GameInfo.game_data.unlocked_plant_types) == 0:
quota_reward.trigger_reward()
generate_first_entities()
generate_first_entities()
AudioManager.enter_planet()
AudioManager.enter_planet()
if player:
generate_near_chunks(player)
ground_layer = GroundLayer.new(self)
add_child(ground_layer)
rock_layer = RockLayer.new(self)
add_child(rock_layer)
decontamination_layer = DecontaminationLayer.new(self)
add_child(decontamination_layer)
if player:
generate_near_chunks(player)
func _process(_d):
if player:
generate_near_chunks(player)
if player:
generate_near_chunks(player)
remove_far_chunks(player)
# queue_redraw()
# queue_redraw()
# func _draw():
# var factor = 20
# for x in range(terrain_size.x / factor):
# for y in range(terrain_size.y / factor):
# var point = Vector2(x, y) * factor
# var factor = 20
# for x in range(terrain_size.x / factor):
# for y in range(terrain_size.y / factor):
# var point = Vector2(x, y) * factor
# draw_circle(
# point,
# factor/10,
# Color.BLUE if garden.is_there_contamination(point) else Color.RED,
# true
# )
# draw_circle(
# point,
# factor/10,
# Color.BLUE if garden.is_there_contamination(point) else Color.RED,
# true
# )
#region ------------------ Generation ------------------
func generate_first_entities():
if not (Vector2i.ZERO in data.generated_chunk_entities):
# Generate shovel
drop_item(Shovel.new(), PlanetData.DEFAULT_GARDEN_SIZE/2 + Vector2(0, 100))
if not (Vector2i.ZERO in data.generated_chunk_entities):
# Generate shovel
drop_item(Shovel.new(), entity_container.global_position + Vector2(0, 100))
# Generate first loots
generate_loot(first_loot_number)
data.generated_chunk_entities.append(Vector2i.ZERO)
func get_chunk_key(coord) -> String:
return "%d:%d" % [coord.x, coord.y]
func generate_near_chunks(p : Player):
var player_chunk_coord = Vector2i(
floor(p.global_position.x / PlanetData.DEFAULT_GARDEN_SIZE.x),
floor(p.global_position.y / PlanetData.DEFAULT_GARDEN_SIZE.y)
)
for x in [-1, 0, 1]:
for y in [-1, 0, 1]:
var coord = Vector2i(x,y) + player_chunk_coord
if coord != Vector2i.ZERO and generated_chunks_objects.find(coord) == -1:
generate_chunk(coord)
var player_chunk_coord = Math.get_chunk_from_pos(p.global_position)
for x in range(-CHUNK_LOAD_DISTANCE, CHUNK_LOAD_DISTANCE+1):
for y in range(-CHUNK_LOAD_DISTANCE, CHUNK_LOAD_DISTANCE+1):
var coord : Vector2i = Vector2i(x,y) + player_chunk_coord
if not generated_chunks.has(get_chunk_key(coord)):
generate_chunk(coord)
func remove_far_chunks(p : Player):
var player_chunk_coord = Vector2i(
floor(p.global_position.x / (CHUNK_TILE_SIZE * TILE_SIZE)),
floor(p.global_position.y / (CHUNK_TILE_SIZE * TILE_SIZE))
)
for chunk in generated_chunks.values():
var chunk_coord = chunk.data.chunk_coord
if player_chunk_coord.distance_to(chunk_coord) > CHUNK_UNLOAD_DISTANCE:
remove_chunk(chunk)
func generate_chunk(coord : Vector2i):
if generated_chunks_objects.find(coord) == -1:
generated_chunks_objects.append(coord)
var new_chunk = Chunk.new(
coord,
PlanetData.DEFAULT_GARDEN_SIZE,
self,
(data.generated_chunk_entities.find(coord) != -1)
)
add_child(new_chunk)
data.generated_chunk_entities.append(coord)
var chunk_data := data.get_or_create_chunk_data(coord)
if coord == Vector2i(0,0):
create_hole_in_chunk(chunk_data, ORIGIN_CHUNK_HOLE_RADIUS)
var chunk_key = get_chunk_key(coord)
if not generated_chunks.has(chunk_key):
var new_chunk = Chunk.new(
chunk_data,
self
)
generated_chunks[chunk_key] = new_chunk
add_child(new_chunk)
data.generated_chunk_entities.append(coord)
func create_hole_in_chunk(chunk_data : ChunkData, hole_radius : int):
var hole_center = Vector2i.ONE * floori(CHUNK_TILE_SIZE/2.)
for x in range(CHUNK_TILE_SIZE):
for y in range(CHUNK_TILE_SIZE):
var coord = Vector2i(x,y)
if coord.distance_to(hole_center) < hole_radius:
chunk_data.update_rock_tile_diff(
coord,
ChunkData.TileDiff.ABSENT
)
func remove_chunk(chunk : Chunk):
generated_chunks.erase(get_chunk_key(chunk.data.chunk_coord))
chunk.unload()
chunk.queue_free()
func save():
data.entities_saved_data = save_entities()
data.entities_saved_data = save_entities()
#endregion
#region ------------------ Usage ------------------
func plant(
type : PlantType,
plant_position : Vector2,
plant_mutations : Array[PlantMutation] = []
type : PlantType,
plant_position : Vector2,
plant_mutations : Array[PlantMutation] = []
) -> bool:
if garden.is_in_garden(plant_position):
var new_plant = garden.plant(type, plant_mutations)
add_entity(new_plant, plant_position)
return true
return false
var new_plant = garden.plant(type, plant_mutations)
add_entity(new_plant, plant_position)
return true
func pass_day():
for e : Node2D in entity_container.get_children():
if e.has_method("_start_pass_day"):
e._start_pass_day()
pass_day_started.emit(self)
await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
for e : Node2D in entity_container.get_children():
if e.has_method("_start_pass_day"):
e._start_pass_day()
pass_day_started.emit(self)
await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
pass_day_proceeded.emit(self)
data.day += 1
data.quota_days -= 1
for e : Node2D in entity_container.get_children():
if e.has_method("_pass_day"):
e._pass_day()
pass_day_ended.emit(self)
await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
for e : Node2D in entity_container.get_children():
if e.has_method("_end_pass_day"):
e._end_pass_day()
pass_day_proceeded.emit(self)
data.day += 1
data.quota_days -= 1
for e : Node2D in entity_container.get_children():
if e.has_method("_pass_day"):
e._pass_day()
pass_day_ended.emit(self)
await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
for e : Node2D in entity_container.get_children():
if e.has_method("_end_pass_day"):
e._end_pass_day()
garden.update_garden_score()
garden.update_garden_score()
if data.garden_score >= data.get_quota_score():
reach_quota()
elif data.quota_days <= 0:
day_limit_exceed.emit(self)
if data.garden_score >= data.get_quota_score():
reach_quota()
elif data.quota_days <= 0:
day_limit_exceed.emit(self)
save()
func generate_loot(number : int):
for i in range(number):
var loot : UndergroundLoot = (UndergroundLootData.SCENE.instantiate() as UndergroundLoot)
loot.item_number = loot_item_number.pick_random()
var loot_random_range = UndergroundLoot.LOOTED_ITEM_RANDOM_RANGE
add_entity(
loot,
Vector2(
randf_range(loot_random_range, garden.size.x),
randf_range(loot_random_range, garden.size.y)
)
)
save()
func reach_quota():
data.quota += 1
quota_reward.trigger_reward()
await quota_reward.reward_chosen
garden.update_garden_score()
if data.garden_score >= data.get_quota_score():
reach_quota()
data.quota_days = data.get_quota_duration()
data.quota += 1
quota_reward.trigger_reward()
await quota_reward.reward_chosen
garden.update_garden_score()
if data.garden_score >= data.get_quota_score():
reach_quota()
data.quota_days = data.get_quota_duration()
#endregion

View File

@@ -3,97 +3,85 @@ class_name PlanetData
signal new_quota_started(planet_data : PlanetData)
signal plant_gaining_score(p : Plant, amount : int)
signal contamination_updated(decontamination_surface : float)
signal updated(planet_data : PlanetData)
const MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE = 3000
const DEFAULT_GARDEN_SIZE = Vector2(1500,1500)
@export var garden_size : Vector2 = Vector2(2000,2000)
@export var garden_contamination : TerrainData
@export var planet_seed : int
@export var quota : int = 0 :
set(v):
quota = v
is_quota_announced = false
new_quota_started.emit(self)
set(v):
quota = v
is_quota_announced = false
new_quota_started.emit(self)
@export var is_quota_announced : bool = false
@export var garden_score : int = 0 :
set(v):
garden_score = v
updated.emit(self)
set(v):
garden_score = v
updated.emit(self)
@export var day : int = 1
@export var planet_seed : int
@export var quota_days : int = get_quota_duration() :
set(v):
quota_days = v
updated.emit(self)
set(v):
quota_days = v
updated.emit(self)
@export var entities_saved_data : Array[EntityData] = []
@export var score_by_plant : Array[int] = []
@export var generated_chunk_entities : Array[Vector2i]
@export var tutorial_step : int = 0
@export var chunks_data : Dictionary[String, ChunkData]
func _init(_base_size : Vector2 = DEFAULT_GARDEN_SIZE):
planet_seed = randi()
garden_size = _base_size
garden_contamination = TerrainData.new(garden_size)
garden_contamination.draw_random_zone(
MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE,
garden_size/2,
planet_seed
)
contamination_updated.emit(get_decontamination_surface())
planet_seed = randi()
garden_size = _base_size
#region ------------------ Contamination ------------------
func impact_contamination(position : Vector2, impact_radius : float, to_value : float = 1.):
garden_contamination.draw_circle(
position,
impact_radius,
to_value
)
contamination_updated.emit(get_decontamination_surface())
#region ------------------ Chunks ------------------
func is_in_garden(point):
return (
point.x > 0
and point.y > 0
and point.x < garden_size.x
and point.y < garden_size.y)
func get_coord_id(coord):
return "%d:%d" % [coord.x, coord.y]
func get_contamination(point : Vector2) -> float:
return garden_contamination.get_value(point)
func has_chunk_data(coord : Vector2i) -> bool:
return chunks_data.has(get_coord_id(coord))
func get_decontamination_coverage() -> float:
return garden_contamination.get_value_coverage()
func add_chunk_data(coord : Vector2i, data : ChunkData):
chunks_data[get_coord_id(coord)] = data
func get_decontamination_surface() -> float:
return garden_contamination.get_value_surface()
func get_chunk_data(coord : Vector2i) -> ChunkData:
return chunks_data[get_coord_id(coord)]
#endregion
func get_or_create_chunk_data(coord : Vector2i) -> ChunkData:
if has_chunk_data(coord):
return get_chunk_data(coord)
else:
var new_chunk_data = ChunkData.new(coord)
add_chunk_data(coord, new_chunk_data)
return new_chunk_data
#region ------------------ Quotas ------------------
func get_quota_score(q : int = quota) -> int:
var first_quotas = [
4,
10,
20,
40,
80,
]
var first_quotas = [
4,
10,
20,
40,
80,
]
if quota >= len(first_quotas):
return pow(q, 3)
else:
return first_quotas[q]
if quota >= len(first_quotas):
return pow(q, 3)
else:
return first_quotas[q]
func get_quota_duration(_q = quota) -> int:
return 7
return 7
#endregion
#region ------------------ Score ------------------
func plant_has_gained_score(plant : Plant, amount : int):
plant_gaining_score.emit(plant, amount)
plant_gaining_score.emit(plant, amount)
#endregion

View File

@@ -1,105 +0,0 @@
extends Resource
class_name TerrainData
const UNIT_PER_PIXEL = 30
@export var image : Image
@export var image_size : Vector2i
func _init(terrain_size : Vector2):
image_size = terrain_size / UNIT_PER_PIXEL
image = Image.create(
image_size.x,
image_size.y,
false,
Image.Format.FORMAT_L8
)
func draw_random_zone(
zone_max_surface : float,
zone_position : Vector2i,
random_seed : int,
):
var noise: Noise = FastNoiseLite.new()
noise.seed = random_seed
noise.noise_type = FastNoiseLite.TYPE_CELLULAR
noise.frequency = 0.1
var noise_image_size : Vector2i = Vector2i.ONE * (image_size)
var noise_image_center = noise_image_size / 2
var noise_image = noise.get_image(
noise_image_size.x,
noise_image_size.y,
1.0,
)
ImageTools.flatten(noise_image, 0.5)
ImageTools.draw_circle(
noise_image,
noise_image_center,
int(round(80./float(UNIT_PER_PIXEL))),
Color.WHITE,
)
var random_step = 1
var zone_radius = noise_image_size.x - random_step
while get_value_surface(noise_image) > zone_max_surface:
zone_radius -= random_step
ImageTools.draw_circle(
noise_image,
noise_image_center,
zone_radius,
Color.BLACK,
true
)
image.blit_rect(
noise_image,
Rect2i(
Vector2i.ZERO,
noise_image_size
),
Vector2i(zone_position / UNIT_PER_PIXEL) - noise_image_size/2
)
func draw_circle(position : Vector2, impact_radius : float, to_value : float = 1.):
ImageTools.draw_circle(
image,
position / UNIT_PER_PIXEL,
roundi(impact_radius / UNIT_PER_PIXEL),
Color(1., 1., 1., to_value)
)
func is_in_image(pixel_point : Vector2i):
return (
pixel_point.x > 0
and pixel_point.y > 0
and pixel_point.x < image.get_width()
and pixel_point.y < image.get_height())
func is_in_terrain(point : Vector2):
return is_in_image(get_pixel_point(point))
func get_value(point : Vector2) -> float:
var pixel_point : Vector2i = get_pixel_point(point)
if (is_in_image(pixel_point)):
return image.get_pixel(
pixel_point.x,
pixel_point.y
).r
return 0
func get_value_coverage(i : Image = image) -> float:
return ImageTools.get_color_coverage(i)
func get_value_surface(i : Image = image) -> float:
return float(ImageTools.get_color_pixel_count(i)) * UNIT_PER_PIXEL
func get_pixel_point(point : Vector2) -> Vector2i:
var vec : Vector2 = Vector2(point) / UNIT_PER_PIXEL - Vector2.ONE
return Vector2i(
roundi(vec.x + 0.5),
roundi(vec.y + 0.5)
)

View File

@@ -1 +0,0 @@
uid://we5pyyr1n06v

View File

@@ -0,0 +1,33 @@
@tool
extends PlanetLayer
class_name DecontaminationLayer
const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/decontamination_planet_tilemap.tres")
const DECONTAMINATION_TILE_TERRAIN_SET : int = 0
const DECONTAMINATION_TILE_TERRAIN : int = 2
func setup():
material = MATERIAL
z_index = -99
func place_decontamination(coord : Vector2i, save = false):
place_decontaminations([coord], save)
func place_decontaminations(coords : Array[Vector2i], save = false):
set_cells_terrain_connect(
coords,
DECONTAMINATION_TILE_TERRAIN_SET,
DECONTAMINATION_TILE_TERRAIN
)
if save:
for coord in coords:
var chunk_coord = Vector2i(
floori(coord.x / float(Planet.CHUNK_TILE_SIZE)),
floori(coord.y / float(Planet.CHUNK_TILE_SIZE)),
)
(planet.data
.get_chunk_data(chunk_coord)
.update_decontamination_tile_diff(coord, ChunkData.TileDiff.PRESENT))
func is_decontamined(coord : Vector2i) -> bool:
return has_cell(coord)

View File

@@ -0,0 +1 @@
uid://2p41t6efxudd

View File

@@ -0,0 +1,18 @@
@tool
extends PlanetLayer
class_name GroundLayer
const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/ground_planet_tilemap.tres")
const GROUND_TILE_SOURCE_ID : int = 0
const GROUND_TILE_ATLAS_COORD : Vector2i = Vector2i.ZERO
func setup():
material = MATERIAL
z_index = -100
func place_ground(tile_position : Vector2i):
set_cell(
tile_position,
GROUND_TILE_SOURCE_ID,
GROUND_TILE_ATLAS_COORD,
)

View File

@@ -0,0 +1 @@
uid://cui423qbula4a

View File

@@ -0,0 +1,36 @@
@abstract
extends TileMapLayer
class_name PlanetLayer
var planet : Planet
@onready var mutex : Mutex = Mutex.new()
func _init(
_planet : Planet = null
):
planet = _planet
func _ready():
tile_set = Planet.TILE_SET
scale = Vector2.ONE * Planet.TILE_SCALE
navigation_enabled = false
setup()
func setup():
pass
func get_all_neighbors_cell(coord : Vector2i) -> Array[Vector2i]:
var neighbors : Array[Vector2i] = []
for x in [-1, 0, 1]:
for y in [-1, 0, 1]:
var neighbor = Vector2i(
coord.x + x,
coord.y + y
)
if coord != neighbor:
neighbors.append(neighbor)
return neighbors
func has_cell(tile_position : Vector2i) -> bool:
return get_cell_source_id(tile_position) != -1

View File

@@ -0,0 +1 @@
uid://cyqmcmgeb76cp

View File

@@ -0,0 +1,87 @@
@tool
extends PlanetLayer
class_name RockLayer
const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/rock_planet_tilemap.tres")
const ROCK_TILE_TERRAIN_SET : int = 0
const ROCK_TILE_TERRAIN : int = 0
const CRISTAL_TILE_TERRAIN : int = 1
const CRISTAL_LOOT_CHANCE : float = 1
enum TileType { EMPTY,ROCK,CRISTAL }
func setup():
material = MATERIAL
z_index = 2
func place_rock(coord : Vector2i, type := TileType.ROCK):
if type != TileType.EMPTY:
set_cells_terrain_connect(
[coord],
ROCK_TILE_TERRAIN_SET,
ROCK_TILE_TERRAIN if type == TileType.ROCK else CRISTAL_TILE_TERRAIN
)
func place_rocks(coords : Array[Vector2i], type := TileType.ROCK):
if type != TileType.EMPTY:
set_cells_terrain_connect(
coords,
ROCK_TILE_TERRAIN_SET,
ROCK_TILE_TERRAIN if type == TileType.ROCK else CRISTAL_TILE_TERRAIN
)
func remove_rocks(coords : Array[Vector2i], save = false):
set_cells_terrain_connect(
coords,
ROCK_TILE_TERRAIN_SET,
-1
)
if save:
for coord in coords:
var chunk_coord = Vector2i(
floori(coord.x / float(Planet.CHUNK_TILE_SIZE)),
floori(coord.y / float(Planet.CHUNK_TILE_SIZE)),
)
var chunk_tile_coord : Vector2i = coord - chunk_coord * Planet.CHUNK_TILE_SIZE
(planet.data
.get_chunk_data(chunk_coord)
.update_rock_tile_diff(chunk_tile_coord, ChunkData.TileDiff.ABSENT))
func dig_rocks(coords : Array[Vector2i]) -> bool:
var has_rock = false
for coord in coords:
if has_tile(coord):
has_rock = true
loot_rock(coord)
if has_rock:
remove_rocks(coords, true)
return has_rock
func loot_rock(coord : Vector2i):
if get_tile_type(coord) == TileType.CRISTAL and randf() < CRISTAL_LOOT_CHANCE:
if len(GameInfo.game_data.unlocked_plant_types):
var loot = Seed.new(
GameInfo.game_data.unlocked_plant_types.pick_random()
)
planet.drop_item(
loot,
coord * Planet.TILE_SIZE + Vector2i.ONE * floori(Planet.TILE_SIZE/2.),
floor(Planet.TILE_SIZE/2.)
)
func update_cells(coords : Array[Vector2i]):
for coord in coords:
if has_tile(coord):
place_rock(coord)
func has_tile(coord : Vector2i) -> bool:
return has_cell(coord)
func get_tile_type(coord : Vector2i) -> TileType:
if has_tile(coord):
return TileType.CRISTAL if get_cell_tile_data(coord).terrain == CRISTAL_TILE_TERRAIN else TileType.ROCK
return TileType.EMPTY

View File

@@ -0,0 +1 @@
uid://cjys51dllryqk

View File

@@ -5,9 +5,8 @@ const BORDER_WIDTH = 100
var player : Player
@export var import_entities_from_node : Node2D = null
@export var entity_container : Node2D
@onready var entity_container : Node2D = create_entity_container()
func instantiate_entity(s: PackedScene, entity_position : Vector2):
var entity = s.instantiate() as Node2D
@@ -23,15 +22,18 @@ func add_entity(entity : Node2D, entity_global_position : Vector2 = Vector2.ZERO
else:
entity.get_parent().remove_child(entity)
enroll_entity(entity)
container.add_child(entity)
entity.global_position = entity_global_position
func enroll_entity(entity : Node2D):
if "terrain" in entity:
entity.terrain = self
if entity is Player:
player = entity
container.add_child(entity)
entity.global_position = entity_global_position
func save_entities() -> Array[EntityData]:
var saved_entities_data : Array[EntityData] = []
for e in entity_container.get_children():
@@ -42,6 +44,9 @@ func save_entities() -> Array[EntityData]:
return saved_entities_data
func load_entities(saved_entities_data : Array[EntityData]):
for static_entity in entity_container.get_children():
enroll_entity(static_entity)
for save_data in saved_entities_data:
var entity = save_data.load()
if entity:
@@ -57,14 +62,6 @@ func create_entity_container() -> Node2D:
add_child(container)
if import_entities_from_node:
for child in import_entities_from_node.get_children():
add_entity(
child,
child.global_position + (container.global_position - import_entities_from_node.global_position),
container
)
return container
func drop_item(item: Item, item_position : Vector2, random_displacement_factor = 0) -> ItemObject:

View File

@@ -11,16 +11,17 @@
[node name="GameGui" parent="CanvasLayer" instance=ExtResource("2_dw1sv")]
[node name="TruckInterior" parent="." node_paths=PackedStringArray("import_entities_from_node") instance=ExtResource("1_ycq4y")]
[node name="TruckInterior" parent="." node_paths=PackedStringArray("entity_container") instance=ExtResource("1_ycq4y")]
position = Vector2(0, 0)
import_entities_from_node = NodePath("../Entities")
entity_container = NodePath("Entities")
[node name="Entities" type="Node2D" parent="TruckInterior"]
y_sort_enabled = true
[node name="Player" parent="TruckInterior/Entities" instance=ExtResource("5_dw1sv")]
position = Vector2(51, 492)
[node name="Camera" type="Camera2D" parent="."]
position = Vector2(385, 343)
script = ExtResource("2_063c3")
metadata/_custom_type_script = "uid://d1nsr56bh1a1y"
[node name="Entities" type="Node2D" parent="."]
[node name="Player" parent="Entities" instance=ExtResource("5_dw1sv")]
position = Vector2(51, 492)