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
# 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