Gododin Gododin Documentation

Linked repository source

examples/bunny_mark/project/gd_bunnies.gd

This read-only view comes from the file in the Gododin repository. It retains its design, example or evidence context.

Download the original file · Return to the guide

class_name GdBunnies
extends Node2D

# GDScript baseline: one driver loop over scene-owned Sprite2D instances.
# Its integer identity and f32 Vector2 operations are replay-checked against
# pure Odin outside measurement. This is not a per-bunny script callback test.
const FIXED_DT := 0.01666666753590107 # exact f32(1/60), shared with Odin
const POPULATION_SEED := 20260911
const TEXTURE := preload("res://assets/bunny.png")
const DRAW_SCALE := 14.0 / 64.0 # the shared 14px quad, from a 64px texture
var speed_scale := 1.0
var gravity := 900.0
var draw_scale := DRAW_SCALE
var _velocities := PackedVector2Array()
var sprites: Array[Sprite2D] = []

# The u32 LCG uses products below 2^63 before masking in GDScript. The seed is
# an argument so an authored preset can seed all three arms identically; the
# canonical value stays POPULATION_SEED.
static func parameter(index: int, seed: int = POPULATION_SEED) -> PackedFloat32Array:
	var state := seed ^ ((index * 2654435761) & 0xffffffff)
	state = (state * 1664525 + 1013904223) & 0xffffffff
	var px := 40 + ((state >> 16) % 1200)
	state = (state * 1664525 + 1013904223) & 0xffffffff
	var py := 40 + ((state >> 16) % 640)
	state = (state * 1664525 + 1013904223) & 0xffffffff
	var vx := ((state >> 16) % 481) - 240
	state = (state * 1664525 + 1013904223) & 0xffffffff
	var vy := ((state >> 16) % 481) - 240
	state = (state * 1664525 + 1013904223) & 0xffffffff
	return PackedFloat32Array([px, py, vx, vy, 0.5 + float(state >> 24) / 256.0])

func set_count(count: int, seed: int = POPULATION_SEED, texture: Texture2D = TEXTURE, scale_factor: float = DRAW_SCALE) -> void:
	clear_all()
	draw_scale = scale_factor
	_velocities.resize(count)
	for index in count:
		var p := parameter(index, seed)
		var sprite := Sprite2D.new()
		sprite.texture = texture
		sprite.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
		sprite.position = Vector2(p[0], p[1])
		sprite.scale = Vector2.ONE * (p[4] * scale_factor)
		add_child(sprite)
		sprites.append(sprite)
		_velocities[index] = Vector2(p[2], p[3])

func clear_all() -> void:
	for sprite in sprites:
		sprite.free()
	sprites.clear()
	_velocities.clear()

func step_fixed() -> void:
	var gravity_step := Vector2(0, gravity * FIXED_DT)
	var travel_dt := speed_scale * FIXED_DT
	for index in sprites.size():
		var sprite := sprites[index]
		var velocity := _velocities[index] + gravity_step
		var position := sprite.position + velocity * travel_dt
		if position.x > 1280:
			position.x = 1280
			velocity.x = -velocity.x
		elif position.x < 0:
			position.x = 0
			velocity.x = -velocity.x
		if position.y > 720:
			position.y = 720
			velocity.y = -velocity.y
		elif position.y < 0:
			position.y = 0
			velocity.y = -velocity.y
		_velocities[index] = velocity
		sprite.position = position

# A readback of actual live state, allocated only by the untimed verification.
func state_buffer() -> PackedFloat32Array:
	var values := PackedFloat32Array()
	values.resize(sprites.size() * 5)
	for i in sprites.size():
		values[i*5] = sprites[i].position.x
		values[i*5+1] = sprites[i].position.y
		values[i*5+2] = _velocities[i].x
		values[i*5+3] = _velocities[i].y
		values[i*5+4] = sprites[i].scale.x / draw_scale
	return values