https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
1. Any live cell with two or three live neighbours survives.
2. Any dead cell with three live neighbours becomes a live cell.
3. All other live cells die in the next generation. Similarly, all other dead cells stay dead.
With different pixel shapes and some simple rules you get some interesting moving shapes
The rendering of this automaton is a little bit slow (2500 images), maybe interestin to create it with GDIP and see the difference in speed.
- Add the black_pixel.png to an Images folder.
- Disable the run checkbox and click on the white surface to draw your own images and press run to see them evolving and moving.
Update: changed controls to new gui
Code: Select all
#Requires AutoHotKey v2.0-beta.3
; when the pixels are high, best to prevent updating of activeX control
#SingleInstance force
A_MaxHotkeysPerInterval := 500
Speed := 00
NumbImages:=2
NumbLoops:= 10000000
xMax := 100
yMax := 100
Pixelsize := 8
global MyGui := Gui()
myGui.MarginX := 0
myGui.MarginY := 0
global WB := MyGui.Add("ActiveX", "w" xMax*Pixelsize " h" yMax*Pixelsize, "mshtml:").Value
; goEdSpeed := MyGui.AddSlider("yp xp+50 w100 Range0-1000 ToolTip", Speed)
; MyGui.Add("Button", "xm w50", "Clear").OnEvent("Click", ButtonClear)
; MyGui.Add("Button", "yp xp+60 w50", "Ex 1").OnEvent("Click", ButtonEx1)
; MyGui.Add("Button", "yp xp+60 w50", "Reload").OnEvent("Click", ButtonReload)
; goOutput := MyGui.AddEdit("w100", 0)
; goOutput2 := MyGui.AddEdit("w100", 0 )
MyGui.OnEvent("Close", Gui_Close)
MyGui.OnEvent("Escape", Gui_Close)
Gui3 := Gui("+AlwaysOnTop -DPIScale +ToolWindow")
Gui3.Title := "Settings"
Gui3.AddGroupBox("w100 h50", "Speed")
goSpeed := Gui3.AddSlider("yp+14 xp+6 w88 -Tabstop tooltip range0-1000", Speed)
goButtonRun := Gui3.AddButton("xm w100", "Stop")
goButtonRun.OnEvent("Click", ButtonRun)
goButtonClear := Gui3.AddButton("w100", "Clear")
goButtonClear.OnEvent("Click", ButtonClear)
goButtonReload := Gui3.AddButton("w100", "Reload")
goButtonReload.OnEvent("Click", ButtonReload)
goOutput := Gui3.AddEdit("w100", 0)
goOutput2 := Gui3.AddEdit("w100", 0)
goOutput3 := Gui3.AddEdit("w100", xMax "x" yMax)
global Pixels := Map()
; Construction the grid
loop xMax{
xPos := A_Index
Pixels[A_index] := Map()
loop yMax {
yPos := A_Index
Pixels[xPos][yPos] := Object()
Pixels[xPos][yPos].state := 0
Pixels[xPos][yPos].state := Random(0,1)
Pixels[xPos][yPos].state := (InStr(xPos, 1)) or (InStr(xPos, 1)) ? 1 : 0
img := WB.CreateElement("img")
img.style.position := "absolute"
Pixels[xPos][yPos].img := img
img.src := A_ScriptDir "\Images\Black_pixel.png"
img.style.left := (xPos-1)*Pixelsize "px"
img.style.top := (yPos-1)*Pixelsize "px"
img.style.height := Pixelsize "px"
img.style.width := Pixelsize "px"
WB.Body.AppendChild(img)
if !Pixels[xPos][yPos].state{
img.style.visibility := "hidden"
}
}
}
; Pixels[2][1].state := 1
; Pixels[2][2].state := 1
; Pixels[2][3].state := 1
MyGui.Show("x10")
MyGui.GetPos(&XWin, &YWin, &WWin, &HWin)
Gui3.Show("NA w120 x" XWin + WWin " y" YWin)
loop xMax {
xPos := A_Index
loop yMax {
yPos := A_Index
if !Pixels[xPos][yPos].state {
Pixels[xPos][yPos].img.style.visibility := "hidden"
} else {
Pixels[xPos][yPos].img.style.visibility := "visible"
}
}
}
Time := A_TickCount
loop{
loop {
if (goButtonRun.Text = "Stop") {
break
}
}
if (goSpeed.Value != 0) {
Sleep(goSpeed.Value)
}
loop xMax {
xPos := A_Index
loop yMax {
yPos := A_Index
Neighbourgs := CountNeigbourgs(xPos, Ypos)
if Pixels[xPos][yPos].state{ ; live cells stay alive if 2 or 3 neighbourgs
if (Neighbourgs = 2 or Neighbourgs = 3) {
Pixels[xPos][yPos].stateNew := 1
} else {
Pixels[xPos][yPos].stateNew := 0
}
}
else { ; Death cells come alive if 3 neighbourgs
if (Neighbourgs = 3) {
Pixels[xPos][yPos].stateNew := 1
} else {
Pixels[xPos][yPos].stateNew := 0
}
}
}
}
;update Pixels
loop xMax {
xPos := A_Index
loop yMax {
yPos := A_Index
if (Pixels[xPos][yPos].stateNew != Pixels[xPos][yPos].state){
if !Pixels[xPos][yPos].stateNew {
Pixels[xPos][yPos].img.style.visibility := "hidden"
} else {
Pixels[xPos][yPos].img.style.visibility := "visible"
}
}
Pixels[xPos][yPos].state := Pixels[xPos][yPos].stateNew
}
}
if (A_Tickcount != Time) {
goOutput.Value := Round(1000 / (A_Tickcount - Time), 3)
goOutput2.Value := (goOutput2.Value * (A_index - 1) + 1000 / (A_Tickcount - Time)) / A_index
}
Time := A_TickCount
}
Return
CountNeigbourgs(xPos,Ypos){
Result := 0
Try Result += Pixels[xPos - 1][yPos - 1].State
Try Result += Pixels[xPos - 0][yPos - 1].State
Try Result += Pixels[xPos + 1][yPos - 1].State
Try Result += Pixels[xPos - 1][yPos + 0].State
Try Result += Pixels[xPos + 1][yPos + 0].State
Try Result += Pixels[xPos - 1][yPos + 1].State
Try Result += Pixels[xPos + 0][yPos + 1].State
Try Result += Pixels[xPos + 1][yPos + 1].State
;MsgBox(Result)
return Result
}
~LButton::{
global
MouseGetPos(&MouseX1, &MouseY1, &MouseWin, &MouseControl)
if (MouseControl = "AtlAxWin1") {
ControlGetPos(&ControlX, &ControlY, , , MouseControl, MouseWin)
MouseX := Round((MouseX1 - ControlX)/Pixelsize+.5)
MouseY := Round((MouseY1 - ControlY) / Pixelsize+0.5)
;ToolTip(MouseX "," MouseY "-" Pixels[MouseX][MouseY].state)
if(Pixels[MouseX][MouseY].HasOwnProp("state")) {
Pixels[MouseX][MouseY].state := !Pixels[MouseX][MouseY].state
} else {
Pixels[MouseX][MouseY].state := true
}
if !Pixels[MouseX][MouseY].state {
Pixels[MouseX][MouseY].img.style.visibility := "hidden"
} else {
Pixels[MouseX][MouseY].img.style.visibility := "visible"
}
}
}
ButtonClear(*){
global
goButtonRun.Text := "Start"
Sleep(500)
loop xMax {
xPos := A_Index
loop yMax {
yPos := A_Index
Pixels[xPos][yPos].state := 0
if !Pixels[xPos][yPos].state {
Pixels[xPos][yPos].img.style.visibility := "hidden"
} else {
Pixels[xPos][yPos].img.style.visibility := "visible"
}
}
}
}
ButtonEx1(*){
global
GOL_Clean()
Pixels[2][9].state := 1
Pixels[3][7].state := 1
Pixels[3][9].state := 1
Pixels[4][8].state := 1
Pixels[4][9].state := 1
GOL_Update()
}
ButtonRun(*) {
if (goButtonRun.text = "Stop") {
goButtonRun.text := "Start"
} else {
goButtonRun.text := "Stop"
}
}
Gui_Close(*) {
ExitApp
}
ButtonReload(*) {
Reload
}
GOL_Clean() {
global
loop xMax {
xPos := A_Index
loop yMax {
yPos := A_Index
Pixels[xPos][yPos].state := 0
}
}
}
GOL_Update(){
global
loop xMax {
xPos := A_Index
loop yMax {
yPos := A_Index
if !Pixels[xPos][yPos].state {
Pixels[xPos][yPos].img.style.visibility := "hidden"
} else {
Pixels[xPos][yPos].img.style.visibility := "visible"
}
}
}
}