From 6662dc0c8035aeee0a2b7abe1b9b40c73ca0c8d3 Mon Sep 17 00:00:00 2001 From: Martin Opat Date: Sun, 21 Dec 2025 14:24:45 +0100 Subject: [PATCH 1/4] Implemented proper backgrund tilemap / tilestep --- .../{ => background}/bg-far-placeholder.jpg | Bin .../bg-far-placeholder.jpg.import | 6 +- .../molecular/assets/background/bg-near.png | Bin 0 -> 450 bytes .../assets/background/bg-near.png.import | 40 +++++++++ .../molecular/assets/background/bg.png | Bin 0 -> 960 bytes .../molecular/assets/background/bg.png.import | 40 +++++++++ .../assets/background}/dirt-specs.png | Bin .../assets/background}/dirt-specs.png.import | 6 +- .../molecular/molecular_stage.tscn | 81 ++++++++++++++---- evolve-die-repeat/project.godot | 4 + 10 files changed, 155 insertions(+), 22 deletions(-) rename evolve-die-repeat/molecular/assets/{ => background}/bg-far-placeholder.jpg (100%) rename evolve-die-repeat/molecular/assets/{ => background}/bg-far-placeholder.jpg.import (73%) create mode 100644 evolve-die-repeat/molecular/assets/background/bg-near.png create mode 100644 evolve-die-repeat/molecular/assets/background/bg-near.png.import create mode 100644 evolve-die-repeat/molecular/assets/background/bg.png create mode 100644 evolve-die-repeat/molecular/assets/background/bg.png.import rename evolve-die-repeat/{ => molecular/assets/background}/dirt-specs.png (100%) rename evolve-die-repeat/{ => molecular/assets/background}/dirt-specs.png.import (75%) diff --git a/evolve-die-repeat/molecular/assets/bg-far-placeholder.jpg b/evolve-die-repeat/molecular/assets/background/bg-far-placeholder.jpg similarity index 100% rename from evolve-die-repeat/molecular/assets/bg-far-placeholder.jpg rename to evolve-die-repeat/molecular/assets/background/bg-far-placeholder.jpg diff --git a/evolve-die-repeat/molecular/assets/bg-far-placeholder.jpg.import b/evolve-die-repeat/molecular/assets/background/bg-far-placeholder.jpg.import similarity index 73% rename from evolve-die-repeat/molecular/assets/bg-far-placeholder.jpg.import rename to evolve-die-repeat/molecular/assets/background/bg-far-placeholder.jpg.import index c59d610..4d29676 100644 --- a/evolve-die-repeat/molecular/assets/bg-far-placeholder.jpg.import +++ b/evolve-die-repeat/molecular/assets/background/bg-far-placeholder.jpg.import @@ -3,15 +3,15 @@ importer="texture" type="CompressedTexture2D" uid="uid://dnlrq8gxiix6" -path="res://.godot/imported/bg-far-placeholder.jpg-f6a73992ff3dd38240865e4558592bbf.ctex" +path="res://.godot/imported/bg-far-placeholder.jpg-01304d9c071eca65de57b4adc0479e81.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://molecular/assets/bg-far-placeholder.jpg" -dest_files=["res://.godot/imported/bg-far-placeholder.jpg-f6a73992ff3dd38240865e4558592bbf.ctex"] +source_file="res://molecular/assets/background/bg-far-placeholder.jpg" +dest_files=["res://.godot/imported/bg-far-placeholder.jpg-01304d9c071eca65de57b4adc0479e81.ctex"] [params] diff --git a/evolve-die-repeat/molecular/assets/background/bg-near.png b/evolve-die-repeat/molecular/assets/background/bg-near.png new file mode 100644 index 0000000000000000000000000000000000000000..7fc99e91f52f0759463072c9a1030faca7ed1a9c GIT binary patch literal 450 zcmV;z0X_bSP)(xCg{KEOEzJJ0;(y2AcXF;sMr3iK8Y!?UJbRn4aZk z+5>8rO$)FN&a;9XOo<1?`d{W4%!#nP03vNC&{6_8YL8Gt2)QlO?2v9}Z`svTm$FyC zX=RUpSLQuGUrVs#?91)pB00d4Tr~o6&QqBuT2Qx4M5E-D6gNOYi6qWG}Dg>DoIhRgC|7f4_6nz?+P-GM5vPS-`xhCJB-S zMFLUAk0#NgtQwJ^ z+AHETq@enEe5fkV@EMHwa-XuP7x*YZFI{R+MDkXRH+$}VOfBipP+;x)<$==2DOETn zeUQvOCsk>3-si`Gy&|J2=|ey-g+fBbjhxuzyvMGAoOnco3V>U8->CM(MPw$4HLPS| zWv&{hT?1=Gg*VrzHE5LmZ2TAxjKVL0op>4ov3P6+gsE^(MFiT9$Ze_qHGN+q4~dt7 zr1Y=)VIibt6A0S2l5hF)L*qcqi!2|E${M8pxce=h&)J2of!IKLrlWTK)9&X=ZD)^V))Icq-?Wds_Od`_PhsomiE|JEWjGN=YfAq>@$Lh6UjSaswJw zg6GiNe`p{rZOC{-Qv>wI@Jxi-cZJp87V*)>ZWa=$@jwhC5Ib{Me<&;j@eDsKXJVE+ zA1Iv`z~V*hp656u!I7R#DW&WC`&-vf9k#7+PsIyXk~uHL4kS^}51qngFjku=SjIw; zI8;P9Ri-eygtc58D8+hQt{N31YBLiJhIk-F5~jY``_}%->qsvi`dc|EZSu-Yq<|Ve z!)>TzZPwR^|JaZsiM#%{pQiC?Dl6E1E!o2fw7{d1LwOS?XjB-3*(|@Qq&b!=*;`S_ zs@LM_VN46WH Date: Sun, 21 Dec 2025 15:14:51 +0100 Subject: [PATCH 2/4] Added simple periodic boundary --- evolve-die-repeat/molecular/molecular_player.gd | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/evolve-die-repeat/molecular/molecular_player.gd b/evolve-die-repeat/molecular/molecular_player.gd index d6b6672..732e8c2 100644 --- a/evolve-die-repeat/molecular/molecular_player.gd +++ b/evolve-die-repeat/molecular/molecular_player.gd @@ -20,4 +20,15 @@ func _process(delta): move_and_collide(speed * velocity * delta) #position += speed * velocity * delta - position = position.clamp(Vector2.ZERO, screen_size) + position = get_boundaried_position(position) + + # periodic boundary + +func get_boundaried_position(position): + ## clamp + #return position.clamp(Vector2.ZERO, screen_size) + + ## periodic + position.x = wrapf(position.x, 0, screen_size.x) + position.y = wrapf(position.y, 0, screen_size.y) + return position From 4160361145caa27fa112148e5bcfab12b26f9c8e Mon Sep 17 00:00:00 2001 From: Martin Opat Date: Fri, 2 Jan 2026 13:17:55 +0100 Subject: [PATCH 3/4] Periodic boundary now applies to prey too --- evolve-die-repeat/game_manager.gd | 19 +++++++++++++++++++ evolve-die-repeat/game_manager.gd.uid | 1 + .../molecular/molecular_player.gd | 16 +++------------- .../molecular/nucleotide_prey.gd | 7 +++++-- evolve-die-repeat/project.godot | 4 ++++ 5 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 evolve-die-repeat/game_manager.gd create mode 100644 evolve-die-repeat/game_manager.gd.uid diff --git a/evolve-die-repeat/game_manager.gd b/evolve-die-repeat/game_manager.gd new file mode 100644 index 0000000..f55f894 --- /dev/null +++ b/evolve-die-repeat/game_manager.gd @@ -0,0 +1,19 @@ +extends Node + +var screen_size = Vector2(1920.0, 1080.0) # Default screen size (this is a float for some reason) + +# TODO: This needs to be called from a script inheriting a CharacterBody2D (e.g. the player) +# Alternative would be to pass the player reference to this script (which might be better?) +func init_screen_size(x:float, y:float) -> void: + screen_size.x = x + screen_size.y = y + +# This can take a vector of any size (but should be 2d, other components are unused) +func get_boundaried_position(position): + ## clamp + #return position.clamp(Vector2.ZERO, screen_size) + + ## periodic + position.x = wrapf(position.x, 0, screen_size.x) + position.y = wrapf(position.y, 0, screen_size.y) + return position diff --git a/evolve-die-repeat/game_manager.gd.uid b/evolve-die-repeat/game_manager.gd.uid new file mode 100644 index 0000000..9f3528c --- /dev/null +++ b/evolve-die-repeat/game_manager.gd.uid @@ -0,0 +1 @@ +uid://vsbibc5fanou diff --git a/evolve-die-repeat/molecular/molecular_player.gd b/evolve-die-repeat/molecular/molecular_player.gd index 732e8c2..ec6b3bb 100644 --- a/evolve-die-repeat/molecular/molecular_player.gd +++ b/evolve-die-repeat/molecular/molecular_player.gd @@ -1,11 +1,11 @@ extends CharacterBody2D @export var speed = 200 -var screen_size var damage = 1 func _ready(): - screen_size = get_viewport_rect().size + var screen_size = get_viewport_rect().size + GameManager.init_screen_size(screen_size.x, screen_size.y) func _process(delta): velocity = Vector2.ZERO @@ -20,15 +20,5 @@ func _process(delta): move_and_collide(speed * velocity * delta) #position += speed * velocity * delta - position = get_boundaried_position(position) + position = GameManager.get_boundaried_position(position) - # periodic boundary - -func get_boundaried_position(position): - ## clamp - #return position.clamp(Vector2.ZERO, screen_size) - - ## periodic - position.x = wrapf(position.x, 0, screen_size.x) - position.y = wrapf(position.y, 0, screen_size.y) - return position diff --git a/evolve-die-repeat/molecular/nucleotide_prey.gd b/evolve-die-repeat/molecular/nucleotide_prey.gd index c778e73..489d0b4 100644 --- a/evolve-die-repeat/molecular/nucleotide_prey.gd +++ b/evolve-die-repeat/molecular/nucleotide_prey.gd @@ -16,8 +16,11 @@ func _process(delta: float) -> void: func _physics_process(delta: float) -> void: self.move(Vector3(randfn(0, 1), randfn(0, 1), 0)) -func move(destination: Vector3) -> void: - move_and_collide(Vector2(destination.x, destination.y)) +func move(motion: Vector3) -> void: + move_and_collide(Vector2(motion.x, motion.y)) # Moves along the given vector + + # Apply boundary to new position + position = GameManager.get_boundaried_position(position) func die() -> void: sprite.play("Dying") diff --git a/evolve-die-repeat/project.godot b/evolve-die-repeat/project.godot index ac94b83..614572a 100644 --- a/evolve-die-repeat/project.godot +++ b/evolve-die-repeat/project.godot @@ -15,6 +15,10 @@ run/main_scene="uid://drgv154ei1vrl" config/features=PackedStringArray("4.5", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +GameManager="*res://game_manager.gd" + [global_group] player="All scenes that constitute players should be added here." From 8de3ee2c9a720bdc9b8f2c8eec88901dbed9db24 Mon Sep 17 00:00:00 2001 From: Martin Opat Date: Fri, 2 Jan 2026 22:03:29 +0100 Subject: [PATCH 4/4] Prey is now reflected to be smooth across periodic boundary too --- evolve-die-repeat/game_manager.gd | 4 + .../molecular/molecular_player.gd | 2 +- .../molecular/nucleotide_prey.gd | 109 +++++++++++++++++- evolve-die-repeat/molecular/preyManager.gd | 1 + 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/evolve-die-repeat/game_manager.gd b/evolve-die-repeat/game_manager.gd index f55f894..2366d1f 100644 --- a/evolve-die-repeat/game_manager.gd +++ b/evolve-die-repeat/game_manager.gd @@ -1,6 +1,10 @@ extends Node var screen_size = Vector2(1920.0, 1080.0) # Default screen size (this is a float for some reason) +var viewport_size + +func _ready() -> void: + viewport_size = get_viewport().get_visible_rect().size # TODO: This needs to be called from a script inheriting a CharacterBody2D (e.g. the player) # Alternative would be to pass the player reference to this script (which might be better?) diff --git a/evolve-die-repeat/molecular/molecular_player.gd b/evolve-die-repeat/molecular/molecular_player.gd index ec6b3bb..8bb7b2d 100644 --- a/evolve-die-repeat/molecular/molecular_player.gd +++ b/evolve-die-repeat/molecular/molecular_player.gd @@ -3,7 +3,7 @@ extends CharacterBody2D @export var speed = 200 var damage = 1 -func _ready(): +func _ready() -> void: var screen_size = get_viewport_rect().size GameManager.init_screen_size(screen_size.x, screen_size.y) diff --git a/evolve-die-repeat/molecular/nucleotide_prey.gd b/evolve-die-repeat/molecular/nucleotide_prey.gd index 489d0b4..723004a 100644 --- a/evolve-die-repeat/molecular/nucleotide_prey.gd +++ b/evolve-die-repeat/molecular/nucleotide_prey.gd @@ -2,16 +2,30 @@ extends AbstractPrey2D @onready var sprite = get_node("AnimatedSprite2D") +# Mirroed sprites for periodic boundary +var mirrorSprite1: Node2D +var mirrorSprite2: Node2D +var mirrorSprite3: Node2D + + # Called when the node enters the scene tree for the first time. func _ready() -> void: $AnimatedSprite2D.animation = "Healthy" $AnimatedSprite2D.play() - pass # Replace with function body. + + mirrorSprite1 = sprite.duplicate() + mirrorSprite2 = sprite.duplicate() + mirrorSprite3 = sprite.duplicate() + + add_child(mirrorSprite1) + add_child(mirrorSprite2) + add_child(mirrorSprite3) # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: - return + # Boundary mirroring + _handle_wrapping() func _physics_process(delta: float) -> void: self.move(Vector3(randfn(0, 1), randfn(0, 1), 0)) @@ -42,3 +56,94 @@ func handle_collision_player(player): self.die() else: sprite.play("Injured") + +# FIXME: Doesn't work with injured sprite +# Mirroring table: +# |---|---|---|---| +# | 4 | 3 | 4 | 3 | +# |---|===|===|---| +# | 1 ǁ 2 | 1 ǁ 2 | +# |---ǁ---|---ǁ---| +# | 4 ǁ 3 | 4 ǁ 3 | +# |---|===|===|---| +# | 1 | 2 | 1 | 2 | +# |---|---|---|---| +# If less than viewport size away from an edge, mirror over that edge (for seamless boundary) +# NOTE: For this to look correctly the camera size should be smaller than half the screen port (in +# any one dimension. Ideally, the difference between camera size and half the screen port is +# at least the size of the prey sprite) +func _handle_wrapping(): + mirrorSprite1.visible = false + mirrorSprite2.visible = false + mirrorSprite3.visible = false + + # TODO: Assume viewport size << screen size and only draw according to GameManager.viewport_size + # Find corresponding section of the screen + if position.x < GameManager.screen_size.x/2 and position.y < GameManager.screen_size.y/2: + # 2 + mirrorSprite1.visible = true + mirrorSprite2.visible = true + mirrorSprite3.visible = true + + # Right + #mirrorSprite1.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y) + mirrorSprite1.position = Vector2(GameManager.screen_size.x, 0) + # Diag + #mirrorSprite2.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y + GameManager.screen_size.y) + mirrorSprite3.position = Vector2(GameManager.screen_size.x, GameManager.screen_size.y) + # Bottom + #mirrorSprite3.position = Vector2(sprite.position.x, sprite.position.y + GameManager.screen_size.y) + mirrorSprite2.position = Vector2(0, GameManager.screen_size.y) + + + elif position.x < GameManager.screen_size.x/2: + # 3 + mirrorSprite1.visible = true + mirrorSprite2.visible = true + mirrorSprite3.visible = true + + # Top + #mirrorSprite1.position = Vector2(sprite.position.x, sprite.position.y - GameManager.screen_size.y) + mirrorSprite1.position = Vector2(0, - GameManager.screen_size.y) + # Diag + #mirrorSprite2.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y - GameManager.screen_size.y) + mirrorSprite2.position = Vector2(GameManager.screen_size.x, - GameManager.screen_size.y) + # Right + #mirrorSprite3.position = Vector2(sprite.position.x + GameManager.screen_size.x, sprite.position.y) + mirrorSprite3.position = Vector2(GameManager.screen_size.x, 0) + + + elif position.y < GameManager.screen_size.y/2: + # 1 + mirrorSprite1.visible = true + mirrorSprite2.visible = true + mirrorSprite3.visible = true + + # Left + #mirrorSprite1.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y) + mirrorSprite1.position = Vector2(- GameManager.screen_size.x, 0) + # Bottom + #mirrorSprite2.position = Vector2(sprite.position.x, sprite.position.y + GameManager.screen_size.y) + mirrorSprite2.position = Vector2(0, GameManager.screen_size.y) + # Diag + #mirrorSprite3.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y + GameManager.screen_size.y) + mirrorSprite3.position = Vector2(- GameManager.screen_size.x, GameManager.screen_size.y) + + + else: + # 4 + mirrorSprite1.visible = true + mirrorSprite2.visible = true + mirrorSprite3.visible = true + + # Left + #mirrorSprite1.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y) + mirrorSprite1.position = Vector2(- GameManager.screen_size.x, 0) + # Diag + #mirrorSprite2.position = Vector2(sprite.position.x - GameManager.screen_size.x, sprite.position.y - GameManager.screen_size.y) + mirrorSprite2.position = Vector2(- GameManager.screen_size.x, - GameManager.screen_size.y) + # Top + #mirrorSprite3.position = Vector2(sprite.position.x, sprite.position.y - GameManager.screen_size.y) + mirrorSprite3.position = Vector2(0, - GameManager.screen_size.y) + + diff --git a/evolve-die-repeat/molecular/preyManager.gd b/evolve-die-repeat/molecular/preyManager.gd index f170db1..4bea20d 100644 --- a/evolve-die-repeat/molecular/preyManager.gd +++ b/evolve-die-repeat/molecular/preyManager.gd @@ -25,3 +25,4 @@ func spawn_creature(scene, position: Vector2) -> void: var instance = scene.instantiate() instance.position = position add_child(instance) +