minijam-166/scripts/terrain.gd
2024-09-01 12:41:08 +02:00

164 lines
3.5 KiB
GDScript

extends Node2D
enum Stats {WATER, FERTILITY, PRESENCE}
const TERRAIN_SIZE = Vector2i(300, 300)
const LEVELS_NUMBER : int = 20
const MAP_RATIO = 8;
@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
func _ready():
setup_texture(Vector3i(0, 0, -5))
func map_to_pixel(
pos : Vector2
) -> Vector2i :
return Vector2i(
int(pos.x / MAP_RATIO),
int(pos.y / MAP_RATIO)
)
func is_on_map(pos: Vector2) -> bool:
return pos.x >= 0 and pos.x <= TERRAIN_SIZE.x * MAP_RATIO and pos.y >= 0 and pos.y <= TERRAIN_SIZE.y * MAP_RATIO
func color_value_to_level(
color_value : float
) -> int:
return roundi(color_value*LEVELS_NUMBER) - float(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,
float(LEVELS_NUMBER)/2
),
-float(LEVELS_NUMBER)/2
)
return float(limited_level+float(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.PRESENCE:
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 not is_on_map(Vector2i(x, y)):
continue
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 get_stat(
pos: Vector2,
stat : Stats
) -> int:
var pixel_pos = map_to_pixel(pos)
var levels = color_to_levels(image.get_pixelv(pixel_pos))
match stat:
Stats.WATER:
return levels.x
Stats.FERTILITY:
return levels.y
Stats.PRESENCE:
return levels.z
_:
return 0
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():
texture.update(image)
func get_texture():
return texture