IVE WANTED THIS FOR SO LONG, I loved the game of life but I could never make it, this seriously made my month! Thank you!
@iaknihs
3 жыл бұрын
Very welcome, glad you like it!
@davidphillips9366
3 жыл бұрын
I’m so glad you made this tutorial! I’m still a beginner with coding and I tried to make Conways Game of Life in Godot last year and couldn’t find any good resources and tried to figure it out myself with little success.
@iaknihs
3 жыл бұрын
Glad I could help!
@russellg3775
2 жыл бұрын
Excellent, very clear and concise, danke schön!
@shoespeak
2 жыл бұрын
thank you so much! i learned a lot here
@rystal
2 жыл бұрын
This is extremely helpful!
@YoDrTentacles
Жыл бұрын
Looking great here - If anyone has trouble with automation, make sure to check your height and width variables versus your tile size. For anyone wanting to slow it down, simply attach a timer, put it on autostart and connect its timeout to the update_field function. In process, restart the timer anytime it is stopped.
@argentinadriving
2 жыл бұрын
great video! I did the GoL in javascript and wanted to do it on godot, but I'm very new at it so I was having many performance issues, this video helped me a lot, thanks!! EDIT: I found my issue: forgot to set the camera as "current" XD
@sneper53
2 жыл бұрын
no github, no source codes🥲
@kingofnothing2260
2 күн бұрын
Can you do this with collision between them and a player, and to have them shoot at the player?
@thornedev1507
2 жыл бұрын
oh god. you made me realize how shitty my laptop is, it freezes between each frame change and i only have 3 cells oscillating 😩😩 great tutorial btw!!
@iaknihs
2 жыл бұрын
oof. There are more efficient ways to get this done, since there is some overhead for using tilemaps, but since Godot has no built-in matrix objects, it gets more complicated there. (probably easier with C# than GDScript I imagine). It can also be parallelized to speed it up more. Solutions using the GPU directly are possible, too which can be significantly faster than using CPU, but I don't know shaders well enough to tell if this is possible using the shader features provided by Godot right now. Basically, if you absolutely need that extra performance, this can still be sped up *a lot*, but Tilemaps are by far the easiest of these options.
@srn8386
2 жыл бұрын
@@iaknihs if i create water with this method it will be low fps right?
@iaknihs
2 жыл бұрын
@@srn8386 larger games which use cellular automata as features usually have to do a lot of optimisation. If you have a lot of things going on, working with a tilemap would most likely be much too slow. There are lots of techniques for optimising these things (and science papers written on the topic), but the more frames you want out of it, the more you'll have to code yourself. Looking at Noita for example, where every pixel of the game world is simulated in a process similar to this, you'd need efficient systems made specifically for this. You'd probably want to work with something that is fairly close to the hardware. I wouldn't say it's impossible to do with Godot, but you'd have to code almost everything from scratch, losing most of the benefits of the Godot engine.
@laylaannkingson1966
3 жыл бұрын
I would love it to zoom in and out, maybe you could use the mouse wheel to make a video about it, please.
@iaknihs
3 жыл бұрын
Thanks for watching! Since the video already has a Camera2D node on it, you can essentially use the same setup, but adjust the camera's zoom.x and zoom.y values whenever a scroll_up / scroll_down action happens (can just add actions for those to the Input Map). Will probably do videos on zooming (in both 2D and 3D) sometime.
@zephy6446
3 жыл бұрын
Hey man, amazing video! I was wonder how I would be able to paint cells instead of clicking once to draw. I tried having the InputEventMouseMotion trigger inside the _process(delta) function and that works... but I get this weird glitch where the cell would be flickering and it wouldn't place consistently. Anyways, again, amazing video and thank you for the Godot content!
@iaknihs
3 жыл бұрын
Thanks for watching!
@zephy6446
3 жыл бұрын
@@iaknihs How would you implement being able to paint with the mouse?
@iaknihs
3 жыл бұрын
You won't get full accuracy this way, but the easiest option is check if mouse key is down right now (I put.is_action_pressed) instead of just pressed and update each frame in process or physics process. Could also adjust for mouse moving too far in one frame by checking several points in a line between old and new mouse position.. To avoid toggling instantly, you would need to have a check if a certain tile is the same one you just flipped previously, could remember that in a variable and reset it on mouse released.
@LenHarms
3 жыл бұрын
Here's some code I added into @iaknihs code. Press "spacebar" to pause, "C" to clear, left mouse to add, right mouse to erase. extends TileMap const TILE_SIZE = 64 export(int) var width export(int) var height var playing:bool = false var temp_field var cam_zoom = 1000 var painting:bool = false var erasing:bool = false func _ready(): var width_px = width * TILE_SIZE var height_px = height * TILE_SIZE var cam = get_node("Camera2D") cam.position = Vector2(width_px, height_px) / 2 cam.zoom = Vector2(width_px, height_px) / Vector2(cam_zoom, cam_zoom) clear_field() func clear_field(): temp_field = [] for x in range(width): var temp = [] for y in range(height): set_cell(x, y, 0) temp.append(0) temp_field.append(temp) func _input(event): if event.is_action_pressed("click_left"): painting = true if event.is_action_released("click_left"): painting = false if event.is_action_pressed("click_right"): erasing = true if event.is_action_released("click_right"): erasing = false if event.is_action_pressed("toggle_play"): playing = !playing if event.is_action_pressed("clear_key"): if !playing: clear_field() if event.is_action_pressed("zoom_in"): if cam_zoom < 2000: cam_zoom += 100 get_node("Camera2D").zoom = Vector2(6400, 6400) / Vector2(cam_zoom, cam_zoom) print("zoom: " + str(cam_zoom)) if event.is_action_pressed("zoom_out"): if cam_zoom > 700: cam_zoom -= 100 get_node("Camera2D").zoom = Vector2(6400, 6400) / Vector2(cam_zoom, cam_zoom) print("zoom: " + str(cam_zoom)) func _process(delta): if painting: var pos = (get_local_mouse_position() / TILE_SIZE).floor() set_cellv(pos, 1)#- get_cellv(pos)) if erasing: var pos = (get_local_mouse_position() / TILE_SIZE).floor() set_cellv(pos, 0) update_field() func update_field(): if !playing: return for x in range(width): for y in range(height): var live_neighbors = 0 for x_off in [-1, 0, 1]: for y_off in [-1, 0, 1]: if x_off != y_off or x_off != 0: if get_cell(x + x_off, y + y_off) == 1: live_neighbors += 1 if get_cell(x, y) == 1: if live_neighbors in [2, 3]: temp_field[x][y] = 1 else: temp_field[x][y] = 0 else: if live_neighbors in [3]: temp_field[x][y] = 1 else: temp_field[x][y] = 0 for x in range(width): for y in range(height): set_cell(x, y, temp_field[x][y])
@jeremiahmcelroy2726
5 ай бұрын
For future people an easy implementation is this in _Process. Mine is in c# but the concept is the same. This will only keep drawing/keep deleting based on the first one you clicked on. Naturally define your LastClickedCellPos and LastClickedCell at the top. I'm in godot 4 so some of these functions might look different if someone is on an older version if (Input.IsActionPressed("place")) { var clickedCellPos = LocalToMap(GetLocalMousePosition()); var clickedCell = GetCellSourceId(0, clickedCellPos); if ((LastClickedCellPos == Vector2I.MaxValue && LastClickedCell == -1) || (clickedCellPos != LastClickedCellPos && 1 - clickedCell != LastClickedCell)) { LastClickedCellPos = clickedCellPos; LastClickedCell = clickedCell; SetCell(0, clickedCellPos, 1 - clickedCell, new Vector2I(0, 0)); } } if (Input.IsActionJustReleased("place")) { LastClickedCellPos = Vector2I.MaxValue; LastClickedCell = -1; }
@vowo4931
2 жыл бұрын
someone can explain me the update_field part? i mean i didnt understand what is x_off and y _off etc and how they set the tiles in the different places(im newer) update i think i got it but what about get_cell(x+x_off, y+y_off) mmm i dont understand
@iaknihs
2 жыл бұрын
get_cell fetches the current value of the cell at a position. Since any cell in game of life is updated based on its neighbours, updating cell (x, y) needs us to know the current state of (x, y+1), (x+1,y),... off is just short for offset relative to the current x, y value
@vowo4931
2 жыл бұрын
@@iaknihs thanks for explain :D I finally do cellular automata with tileset set cell, but my water is low fps only works fine at 100 x 50 resolution
@jackliberson
2 жыл бұрын
Thank you but how can you make speed slower/faster?
@iaknihs
2 жыл бұрын
Instead of calling 'update_field()' directly in _process() you can use a timer and run a step each timeout. The maximum possible speed depends on your hardware, the size of the map, and if you're running in-editor or a more optimized compiled build. Additionally, while tilemaps are a simple way to explain and visualize how this works, they are nowhere near the most efficient. Rendering a grid manually without tiles should be significantly faster. Computing cells in parallel would be a lot faster on most modern machines. Using compute shaders (afaik will be possible without plugins in Godot 4's Vulkan implementation) should be really quite fast. But the more speed and cells you want, the more difficult it becomes to implement.
@schlagsaite1378
9 ай бұрын
Please update for 4.*
@iaknihs
9 ай бұрын
will try to get to it soon, trying to make updates on many of my old videos now
@schlagsaite1378
9 ай бұрын
@@iaknihsThank You. Looking forward to it, because i'm struggling with the new tilemap system.
Пікірлер: 31