From 4f67fd3c4f556a0d7fa6c9f6d08e05ffe8d2d10e Mon Sep 17 00:00:00 2001 From: Zacharie Guet Date: Sat, 31 Aug 2024 15:24:44 +0200 Subject: [PATCH] Setup terrains system --- objects/Map.tscn | 9 ++ objects/Map7C51.tmp | 7 ++ objects/Map9254.tmp | 7 ++ objects/MapEC4B.tmp | 7 ++ project.godot | 4 + scenes/Scanners.tscn | 44 ++++++++++ scenes/Terrain.tscn | 7 ++ scripts/map.gd | 2 + scripts/scanners.gd | 11 +++ scripts/shaders/Scanner.gdshader | 48 ++++++++++ scripts/terrain.gd | 145 +++++++++++++++++++++++++++++++ 11 files changed, 291 insertions(+) create mode 100644 objects/Map.tscn create mode 100644 objects/Map7C51.tmp create mode 100644 objects/Map9254.tmp create mode 100644 objects/MapEC4B.tmp create mode 100644 scenes/Scanners.tscn create mode 100644 scenes/Terrain.tscn create mode 100644 scripts/map.gd create mode 100644 scripts/scanners.gd create mode 100644 scripts/shaders/Scanner.gdshader create mode 100644 scripts/terrain.gd diff --git a/objects/Map.tscn b/objects/Map.tscn new file mode 100644 index 0000000..a65d5f3 --- /dev/null +++ b/objects/Map.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=3 format=3 uid="uid://d3hul8b7hlmj7"] + +[ext_resource type="Script" path="res://scripts/map.gd" id="1_3np0o"] +[ext_resource type="PackedScene" uid="uid://6ferubyu2uy1" path="res://scenes/Scanners.tscn" id="1_6mlj0"] + +[node name="Map" type="Node2D"] +script = ExtResource("1_3np0o") + +[node name="Scanners" parent="." instance=ExtResource("1_6mlj0")] diff --git a/objects/Map7C51.tmp b/objects/Map7C51.tmp new file mode 100644 index 0000000..76d6c35 --- /dev/null +++ b/objects/Map7C51.tmp @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://d3hul8b7hlmj7"] + +[ext_resource type="PackedScene" uid="uid://6ferubyu2uy1" path="res://scenes/Scanners.tscn" id="1_6mlj0"] + +[node name="Map" type="Node2D"] + +[node name="Scanners" parent="." instance=ExtResource("1_6mlj0")] diff --git a/objects/Map9254.tmp b/objects/Map9254.tmp new file mode 100644 index 0000000..76d6c35 --- /dev/null +++ b/objects/Map9254.tmp @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://d3hul8b7hlmj7"] + +[ext_resource type="PackedScene" uid="uid://6ferubyu2uy1" path="res://scenes/Scanners.tscn" id="1_6mlj0"] + +[node name="Map" type="Node2D"] + +[node name="Scanners" parent="." instance=ExtResource("1_6mlj0")] diff --git a/objects/MapEC4B.tmp b/objects/MapEC4B.tmp new file mode 100644 index 0000000..76d6c35 --- /dev/null +++ b/objects/MapEC4B.tmp @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://d3hul8b7hlmj7"] + +[ext_resource type="PackedScene" uid="uid://6ferubyu2uy1" path="res://scenes/Scanners.tscn" id="1_6mlj0"] + +[node name="Map" type="Node2D"] + +[node name="Scanners" parent="." instance=ExtResource("1_6mlj0")] diff --git a/project.godot b/project.godot index 790aba0..aaef820 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,10 @@ run/main_scene="res://Game.tscn" config/features=PackedStringArray("4.3", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +GameTerrain="*res://scenes/Terrain.tscn" + [editor] version_control/plugin_name="GitPlugin" diff --git a/scenes/Scanners.tscn b/scenes/Scanners.tscn new file mode 100644 index 0000000..05966a5 --- /dev/null +++ b/scenes/Scanners.tscn @@ -0,0 +1,44 @@ +[gd_scene load_steps=8 format=3 uid="uid://6ferubyu2uy1"] + +[ext_resource type="Script" path="res://scripts/scanners.gd" id="1_orxwo"] +[ext_resource type="Shader" path="res://scripts/shaders/Scanner.gdshader" id="2_8t6wf"] + +[sub_resource type="Gradient" id="Gradient_pafyk"] +offsets = PackedFloat32Array(0, 0.22549, 0.51634, 0.813725, 1) +colors = PackedColorArray(0.66677, 0.166288, 0, 1, 0.41, 0.328, 0, 1, 0, 0, 0, 1, 0, 0.592306, 0, 1, 0, 0.964706, 0.580392, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_mpkd3"] +gradient = SubResource("Gradient_pafyk") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_yl6st"] +shader = ExtResource("2_8t6wf") +shader_parameter/dimension = 1 +shader_parameter/gradient = SubResource("GradientTexture1D_mpkd3") + +[sub_resource type="Gradient" id="Gradient_sc8ss"] +interpolation_mode = 1 +offsets = PackedFloat32Array(0, 0.316568, 0.695266) +colors = PackedColorArray(1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_a7oi7"] +gradient = SubResource("Gradient_sc8ss") +fill_from = Vector2(0, 1) +fill_to = Vector2(1, 1) + +[node name="Scanners" type="Node2D"] +script = ExtResource("1_orxwo") + +[node name="Data" type="Sprite2D" parent="."] +visible = false +centered = false + +[node name="Fertility" type="Sprite2D" parent="."] +visible = false +material = SubResource("ShaderMaterial_yl6st") +centered = false + +[node name="Water" type="Sprite2D" parent="."] +visible = false +material = SubResource("ShaderMaterial_yl6st") +texture = SubResource("GradientTexture2D_a7oi7") +centered = false diff --git a/scenes/Terrain.tscn b/scenes/Terrain.tscn new file mode 100644 index 0000000..4cda06b --- /dev/null +++ b/scenes/Terrain.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://bifyi58itph4i"] + +[ext_resource type="Script" path="res://scripts/terrain.gd" id="1_5hbti"] + +[node name="Terrain" type="Node2D"] +position = Vector2(391, 198) +script = ExtResource("1_5hbti") diff --git a/scripts/map.gd b/scripts/map.gd new file mode 100644 index 0000000..3fbebfb --- /dev/null +++ b/scripts/map.gd @@ -0,0 +1,2 @@ +class_name Map +extends Node2D diff --git a/scripts/scanners.gd b/scripts/scanners.gd new file mode 100644 index 0000000..8a8bbf9 --- /dev/null +++ b/scripts/scanners.gd @@ -0,0 +1,11 @@ +class_name Scanners +extends Node2D + +func _ready(): + for sprite in [$Water, $Fertility, $Data]: + sprite.texture = GameTerrain.get_texture() + sprite.scale = Vector2(GameTerrain.MAP_RATIO,GameTerrain.MAP_RATIO,) + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/scripts/shaders/Scanner.gdshader b/scripts/shaders/Scanner.gdshader new file mode 100644 index 0000000..4922da0 --- /dev/null +++ b/scripts/shaders/Scanner.gdshader @@ -0,0 +1,48 @@ +shader_type canvas_item; + +#define pow2(x) (x * x) +#define iResolution 1.0/SCREEN_PIXEL_SIZE + +uniform sampler2D gradient : source_color, filter_nearest; +uniform int dimension; + +const float alpha = 0.3; +const float strength = 0.5; +const float pi = atan(1.0) * 4.0; +const int samples = 35; +const float sigma = float(samples) * 0.25; + +float gaussian(vec2 i) { + return 1.0 / (2.0 * pi * pow(sigma,2)) * exp(-((pow(i.x,2) + pow(i.y,2)) / (2.0 * pow(sigma,2)))); +} + +vec3 blur(sampler2D sp, vec2 uv, vec2 scale) { + vec3 col = vec3(0.0); + float accum = 0.0; + float weight; + vec2 offset; + + for (int x = -samples / 2; x < samples / 2; ++x) { + for (int y = -samples / 2; y < samples / 2; ++y) { + offset = vec2(float(x), float(y)); + weight = gaussian(offset); + col += texture(sp, uv + scale * offset).rgb * weight; + accum += weight; + } + } + + return col / accum; +} + +void fragment() { + vec2 ps = vec2(1.0) / iResolution.xy * .000001 * strength; + vec2 uv = UV ; + + vec3 pixel_color = blur(TEXTURE, uv, ps ); + float value = pixel_color.x; + if (dimension == 1) value = pixel_color.y; + if (dimension == 2) value = pixel_color.z; + + COLOR = texture(gradient, vec2(value, 0)); + COLOR.a = alpha; +} \ No newline at end of file diff --git a/scripts/terrain.gd b/scripts/terrain.gd new file mode 100644 index 0000000..6ea6604 --- /dev/null +++ b/scripts/terrain.gd @@ -0,0 +1,145 @@ +extends Node2D + +enum Stats {WATER, FERTILITY, TEMPERATURE} + +const TERRAIN_SIZE = Vector2i(300, 300) +const LEVELS_NUMBER : int = 10 +const MAP_RATIO = 4; + +@onready var image := Image.create_empty( + TERRAIN_SIZE.x, + TERRAIN_SIZE.y, + true, + Image.Format.FORMAT_RGBF +) +@onready var texture : ImageTexture = ImageTexture.create_from_image(image) + +var sum := 0.0 + +signal terrain_updated + +func _ready(): + setup_texture(Vector3i()) + +func map_to_pixel( + position : Vector2 +) -> Vector2i : + return Vector2i( + int(position.x / MAP_RATIO), + int(position.y / MAP_RATIO) + ) + +func color_value_to_level( + color_value : float +) -> int: + return roundi(color_value*LEVELS_NUMBER) - LEVELS_NUMBER/2 + +func color_to_levels( + color: Color +) -> Vector3i : + return Vector3i( + color_value_to_level(color.r), + color_value_to_level(color.g), + color_value_to_level(color.b), + ) + +func level_to_color_value( + level : int +) -> float: + var limited_level = max( + min( + level, + LEVELS_NUMBER/2 + ), + -LEVELS_NUMBER/2 + ) + return float(limited_level+LEVELS_NUMBER/2)/LEVELS_NUMBER + +func levels_to_color( + levels: Vector3i +) -> Color : + return Color( + level_to_color_value(levels.x), + level_to_color_value(levels.y), + level_to_color_value(levels.z) + ) + +func modification_to_levels( + stat: Stats, + modification: int +) -> Vector3i : + var levels = Vector3i() + match stat: + Stats.WATER: + levels.x = modification + Stats.FERTILITY: + levels.y = modification + Stats.TEMPERATURE: + levels.z = modification + return levels + +func modify_pixel( + pixel_pos: Vector2i, + stat: Stats, + modification: int, +): + var actual_levels = color_to_levels(image.get_pixelv(pixel_pos)) + var modification_levels = modification_to_levels(stat, modification) + var calculated_levels = actual_levels + modification_levels + set_pixel(pixel_pos, calculated_levels) + +func set_pixel( + pixel_pos: Vector2i, + level: Vector3i, +): + image.set_pixelv(pixel_pos, levels_to_color(level)) + +func modify_zone( + center: Vector2, + radius: float, + stat : Stats, + modification: int +): + var pixel_center = map_to_pixel(center) + var pixel_radius = int(radius / MAP_RATIO) + for x in range(pixel_center.x - pixel_radius, pixel_center.x + pixel_radius + 1) : + for y in range(pixel_center.y - pixel_radius, pixel_center.y + pixel_radius + 1): + if pow(x - pixel_center.x,2) + pow(y - pixel_center.y,2) <= pow(pixel_radius,2): + modify_pixel( + Vector2i(x, y), + stat, + modification + ) + update_texture() + +func modify_rect( + pos: Vector2, + size: Vector2, + stat : Stats, + modification: int +): + var pixel_pos = map_to_pixel(pos) + var pixel_size = map_to_pixel(size) + for x in range(pixel_pos.x, pixel_pos.x+pixel_size.x) : + for y in range(pixel_pos.y, pixel_pos.y+pixel_size.y): + modify_pixel( + Vector2i(x, y), + stat, + modification + ) + update_texture() + +func setup_texture( + levels : Vector3i +): + for x in range(0, TERRAIN_SIZE.x) : + for y in range(0, TERRAIN_SIZE.y): + set_pixel(Vector2i(x,y), levels) + update_texture() + +func update_texture(): + emit_signal("terrain_updated") + texture.update(image) + +func get_texture(): + return texture