conways-life

Conway's game of life in Godot4
git clone git://bsandro.tech/conways-life
Log | Files | Refs | README | LICENSE

main.gd (2157B)


      1 extends Node
      2 
      3 var field_w:int
      4 var field_h:int
      5 var cell_w:int
      6 var cell_h:int
      7 var field:Array[Array]
      8 
      9 @export var cell_scene:PackedScene
     10 @export var tick_timer:Timer
     11 
     12 func _init():
     13 	pass
     14 
     15 # Called when the node enters the scene tree for the first time.
     16 func _ready():
     17 	var cell = cell_scene.instantiate()
     18 	cell.position = Vector2(0, 0)
     19 	add_child(cell)
     20 	print("cell is alive:", cell.is_alive)
     21 
     22 	cell_w = cell.texture.get_width() * cell.transform.get_scale().x
     23 	cell_h = cell.texture.get_height() * cell.transform.get_scale().y
     24 	print("cell size: ", cell_w, "x", cell_h)
     25 
     26 	field_w = get_viewport().size.x / cell_w
     27 	field_h = get_viewport().size.y / cell_h
     28 
     29 	print("field size: ", field_w, "x", field_h)
     30 
     31 	field.resize(field_h)
     32 	for y in range(field_h):
     33 		field[y].resize(field_w)
     34 		for x in range(field_w):
     35 			field[y][x] = cell_scene.instantiate()
     36 			field[y][x].position = Vector2(x*cell_w, y*cell_h)
     37 			add_child(field[y][x])
     38 
     39 	remove_child(cell)
     40 
     41 	randomize_field()
     42 	tick_timer.start()
     43 
     44 # Called every frame. 'delta' is the elapsed time since the previous frame.
     45 func _process(_delta):
     46 	pass
     47 
     48 func randomize_field():
     49 	for y in range(field_h):
     50 		for x in range(field_w):
     51 			field[y][x].is_alive_next = randi_range(0, 1)
     52 
     53 func update_field():
     54 	for y in range(field_h):
     55 		for x in range(field_w):
     56 			field[y][x].update()
     57 
     58 func render_field():
     59 	for y in range(field_h):
     60 		for x in range(field_w):
     61 			field[y][x].visible = field[y][x].is_alive
     62 
     63 func tick_field():
     64 	for y in range(field_h):
     65 		for x in range(field_w):
     66 			field[y][x].is_alive_next = tick_cell(x, y)
     67 
     68 func tick_cell(x:int, y:int):
     69 	var sum:int = sum_area(x, y)
     70 	if field[y][x].is_alive: # alive cell
     71 		if sum < 3 || sum > 4: # cell dies
     72 			return false
     73 		else: # cell lives
     74 			return true
     75 	else: # dead cell
     76 		if sum == 3: # cell comes alive
     77 			return true
     78 		else: # cell stays dead
     79 			return false
     80 
     81 func sum_area(x:int, y:int): # sum 3x3 area all around the cell
     82 	var cnt:int = 0;
     83 	for xx in range(x-1, x+2):
     84 		for yy in range(y-1, y+2):
     85 			if xx>=0 && yy>=0 && xx<field_w && yy<field_h:
     86 				cnt += field[yy][xx].val();
     87 	return cnt
     88 
     89 func _on_tick():
     90 	update_field()
     91 	render_field()
     92 	tick_field()