Gerador de ilhas

Ruído multiplicado por uma máscara radial e pintado numa Image faixa por faixa. Clique para outra ilha.

O editor acima está rodando este projeto. Mude uma linha e ele recarrega.

Classes do Godot usadas

FastNoiseLiteImageImageTexture

O código

scripts/main.gd
extends Node

const MAP: Vector2i = Vector2i(320, 180)
const PIXEL: float = 4.0
const SEED: int = 20260814

const BANDS: Array = [
	{limit = 0.28, color = '#161c2c'},
	{limit = 0.40, color = '#2a2f3d'},
	{limit = 0.46, color = '#f3d48d'},
	{limit = 0.60, color = '#8eef97'},
	{limit = 0.74, color = '#4c9c60'},
	{limit = 0.86, color = '#8da5f3'},
	{limit = 2.00, color = '#e6ecff'},
]

var rng: RandomNumberGenerator = RandomNumberGenerator.new()
var map: Sprite2D
var label: Label


func _ready() -> void:
	_add_background()

	map = Sprite2D.new()
	map.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
	map.scale = Vector2(PIXEL, PIXEL)
	map.position = get_viewport().get_visible_rect().size * 0.5
	add_child(map)

	label = Label.new()
	label.position = Vector2(28, 22)
	label.add_theme_color_override('font_color', Color('#e6ecff'))
	label.add_theme_color_override('font_shadow_color', Color('#12141a'))
	label.add_theme_constant_override('shadow_offset_y', 2)
	add_child(label)

	rng.seed = SEED
	_generate(SEED)

	print('click for another island, the first one always comes from SEED')


func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.pressed:
		_generate(rng.randi())


func _generate(island_seed: int) -> void:
	var noise: FastNoiseLite = FastNoiseLite.new()
	noise.seed = island_seed
	noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
	noise.fractal_octaves = 5
	noise.frequency = 0.016

	var image: Image = Image.create(MAP.x, MAP.y, false, Image.FORMAT_RGBA8)
	var center: Vector2 = Vector2(MAP) * 0.5
	var radius: float = MAP.y * 0.54

	for y in MAP.y:
		for x in MAP.x:
			var falloff: float = clampf(1.0 - (Vector2(x, y) - center).length() / radius, 0.0, 1.0)
			var value: float = noise.get_noise_2d(x, y) * 0.5 + 0.5
			image.set_pixel(x, y, _band_color(value * pow(falloff, 0.55) * 1.35))

	map.texture = ImageTexture.create_from_image(image)
	label.text = 'seed %d, click for another' % island_seed


func _band_color(height: float) -> Color:
	for band in BANDS:
		if height < band.limit:
			return Color(band.color)

	return Color(BANDS[BANDS.size() - 1].color)


func _add_background() -> void:
	var background: ColorRect = ColorRect.new()
	background.color = Color('#12141a')
	# ColorRect defaults to MOUSE_FILTER_STOP and would eat the click before _unhandled_input
	background.mouse_filter = Control.MOUSE_FILTER_IGNORE
	add_child(background)
	background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)

Mais exemplos de Procedural