Browse Source

Adding processing of world

pull/1/head
Ryan Reed 1 year ago
parent
commit
e386b4889e
2 changed files with 126 additions and 15 deletions
  1. +95
    -12
      world.gd
  2. +31
    -3
      world.tscn

+ 95
- 12
world.gd View File

@ -1,46 +1,129 @@
## Conway's Game of Life
## Rules:
## 1. Any cell with >2 neighbors survives
## 2. Any dead cell with 3 live neighbors becomes alive
## 3. All other cells die (all dead cells remaing dead)
## Rule 1 - Any live cell with fewer than two live neighbours dies (underpopulation)
## Rule 2 - Any live cell with two or three live neighbours lives
## Rule 3 - Any live cell with more than three live neighbours dies (overpopulation)
## Rule 4 - Any dead cell with epos.xactly three live neighbours becomes a live cell (reproduction)
extends Node2D
enum CellStates {
DEAD,
ALIVE,
}
@onready var generation_counter: Label = $CanvasLayer/Debug/VBoxContainer/GenerationCounter
@onready var generation_timer: Timer = $GenerationTimer
@onready var living_cells_counter: Label = $CanvasLayer/Debug/VBoxContainer/LivingCellsCounter
@onready var world_seed_label: Label = $CanvasLayer/Debug/VBoxContainer/WorldSeed
@export var world_seed: int
@export var cell_size: Vector2 = Vector2(16, 16)
@export var cell_size: Vector2 = Vector2(64, 64)
@export var cell_texture: Texture2D
@export var world_size: Vector2 = Vector2(128, 128)
@export var world_size: Vector2 = Vector2(8, 8)
var cell_instance
var generation: int = 1
var world: Array = []
var total_living: int = 0
func _ready() -> void:
if world_seed: seed(world_seed)
if not world_seed:
world_seed = randi()
seed(world_seed)
world_seed_label.text = "World Seeed: %s" % world_seed
generate_world()
# Create the cell using the rendering server
func create_cell(location: Vector2) -> RID:
## Check a cell against the Conway rules
func check_cell_rules(pos: Vector2) -> void:
var neighbors := count_living_neighbors(pos)
var currently_alive = world[pos.x][pos.y] is RID
# Rule 1 - Any live cell with fewer than two live neighbours dies (underpopulation)
if currently_alive and neighbors < 2:
kill_cell(pos)
return
# Rule 2 - Any live cell with two or three live neighbours lives
elif currently_alive and (neighbors == 2 or neighbors == 3):
total_living += 1
return
# Rule 3 - Any live cell with more than three live neighbours dies (overpopulation)
elif currently_alive and neighbors > 3:
kill_cell(pos)
return
# Rule 4 - Any dead cell with epos.xactly three live neighbours becomes a live cell (reproduction)
elif not currently_alive and neighbors == 3:
total_living += 1
world[pos.x][pos.y] = create_cell(pos)
return
func count_living_neighbors(pos: Vector2) -> int:
var count := 0
var x_min = 0 if pos.x - 1 < 0 else pos.x - 1
var y_min = 0 if pos.y - 1 < 0 else pos.y - 1
var x_max = world_size.x if pos.x + 2 > world_size.x else pos.x + 2
var y_max = world_size.y if pos.y + 2 > world_size.y else pos.y + 2
for x in range(x_min, x_max):
for y in range(y_min, y_max):
if x == pos.x and y == pos.y: continue # Current cell - Don't count
if world[x][y] is RID:
count += 1
return count
func process_generation() -> void:
generation += 1
total_living = 0
for x in range(world_size.x):
for y in range(world_size.y):
check_cell_rules(Vector2(x, y))
## Create the cell using the rendering server
func create_cell(pos: Vector2) -> RID:
var rs = RenderingServer
cell_instance = rs.canvas_item_create()
rs.canvas_item_set_parent(cell_instance, get_canvas_item())
var rect: Rect2 = Rect2(-cell_size.x/2, -cell_size.y/2, cell_size.x, cell_size.y) # Centered with cell size
rs.canvas_item_add_texture_rect(cell_instance, rect, cell_texture)
var location_fixed = Vector2(location.x * cell_size.x, location.y * cell_size.y)
var trans = Transform2D(0, location_fixed)
var pos_fixed = Vector2(pos.x * cell_size.x, pos.y * cell_size.y)
var trans = Transform2D(0, pos_fixed)
rs.canvas_item_set_transform(cell_instance, trans)
return cell_instance
func kill_cell(pos: Vector2) -> void:
if not world[pos.x][pos.y] is RID: return
RenderingServer.free_rid(world[pos.x][pos.y])
world[pos.x][pos.y] = CellStates.DEAD
## Generate the world with the initial cells
func generate_world() -> void:
for x in range(world_size.x):
world.append([])
for y in range(world_size.y):
if randi_range(0, 1):
total_living += 1
world[x].append(create_cell(Vector2(x, y)))
else:
world[x].append(0)
world[x].append(CellStates.DEAD)
func _on_generation_timer_timeout() -> void:
process_generation()
generation_counter.text = "Generation: %s" % generation
living_cells_counter.text = "Living Cells: %s" % total_living
generation_timer.start()

+ 31
- 3
world.tscn View File

@ -5,13 +5,41 @@
[ext_resource type="PackedScene" uid="uid://cy6vsgu8o0rad" path="res://scenes/fps_counter/fps_counter.tscn" id="3_ves6s"]
[node name="World" type="Node2D"]
position = Vector2(-152, 0)
script = ExtResource("1_wavft")
world_seed = 123
cell_texture = ExtResource("2_8r6bn")
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="FPSCounter" parent="CanvasLayer" instance=ExtResource("3_ves6s")]
[node name="Debug" type="MarginContainer" parent="CanvasLayer"]
offset_right = 40.0
offset_bottom = 40.0
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/Debug"]
layout_mode = 2
[node name="FPSCounter" parent="CanvasLayer/Debug/VBoxContainer" instance=ExtResource("3_ves6s")]
layout_mode = 2
text = "FPS: 0"
[node name="WorldSeed" type="Label" parent="CanvasLayer/Debug/VBoxContainer"]
layout_mode = 2
text = "World Seed: 0"
[node name="GenerationCounter" type="Label" parent="CanvasLayer/Debug/VBoxContainer"]
layout_mode = 2
text = "Generation: 1"
[node name="LivingCellsCounter" type="Label" parent="CanvasLayer/Debug/VBoxContainer"]
layout_mode = 2
text = "Living Cells: 0"
[node name="Camera2D" type="Camera2D" parent="."]
position = Vector2(576, 320)
position = Vector2(464, 200)
[node name="GenerationTimer" type="Timer" parent="."]
wait_time = 0.05
one_shot = true
autostart = true
[connection signal="timeout" from="GenerationTimer" to="." method="_on_generation_timer_timeout"]

Loading…
Cancel
Save