samples/gol2.rb
# encoding: utf-8
# Creative Commons BY-SA : Regis d'Aubarede <regis.aubarede@gmail.com>
# LGPL
require_relative '../lib/Ruiby'
require 'pp'
Ruiby.app width: 1000, height: 700, title: "Game of Analogic Life" do
def freemap() l=[]; MAXC.times { l << [0]*MAXL } ; l end
MAXC=MAXL=120
PASX=default_width/MAXC
PASY=(default_width)/MAXL
@oldmat=freemap()
@mat=freemap()
@run=false
stack do
def formula(opoids,poids)
#--#
opoids>30 ? (opoids<82 ? (poids*1.0003) : poids*0.99 ) : ((opoids<10 && opoids>1) ? (100-poids/2) : (poids*0.93))
#--#
end
@formula = File.read(__FILE__).split("#-"+"-#")[1].strip
flowi {
labeli "Life Formula : "
@edit=entry(@formula)
buttoni("enter") { instance_eval " def formula(opoids,poids) #{@edit.text} ; end" }
}
@cv=canvas(self.default_width,self.default_height) do
on_canvas_draw { |w,cr|
MAXC.times { |col| MAXL.times { |li|
coul=1.0-(@mat[col][li] / 100.0)
r,g,b=coul,coul,coul
r=coul*2 if coul<0.4
g*=2 if coul>0.8
b*=2 if coul>0.4
cr.set_source_rgba(r,g,b)
cr.rectangle(col*PASX,li*PASY,PASX,PASY)
cr.fill()
}}
}
on_canvas_button_press{ |w,e|
no= [e.x/PASX,e.y/PASY] ;
c=(@mat[no.first][no.last]>50 ? 0 : 100)
[-2,-1, 0, 1,+2].each { |col_off| [-2,-1, 0, 1,2].each { |li_off| @mat[no.first+col_off][no.last+li_off]= c}}
no
}
end
flowi do
button " clear " do @mat=freemap() ; @cv.redraw end
button " random " do
rand(MAXC*MAXL/10).times { @mat[rand(MAXC)][rand(MAXL)]=rand(10..90) }
@cv.redraw
end
button " start " do @run=true ;end
button " stop " do @run=false ; end
button " 3D " do do_timeline(@mat) end
end
end
anim 200 do game() if @run ; @cv.redraw ; (make_curve() ; @ccc.redraw) if @ccc end
def game()
mat2=@oldmat
MAXC.times do |col| MAXL.times do |li|
poids= 0; n=0
[-1, 0, 1].each { |col_off| [-1, 0, 1].each { |li_off|
next if col_off == 0 && li_off == 0
next if col+col_off < 0 || li+li_off < 0
next if col+col_off >= MAXC || li+li_off >= MAXL
poids += @mat[col + col_off][li + li_off]
n+=1
} }
c=formula(@mat[col][li],poids/n)
mat2[col][li] = ((c<0) ? 0 : (c>100 ? 100 : c))
end end
@oldmat,@mat=@mat,mat2 if @run # seem that GTK:Timer use threading...?
end
# end component()
def do_timeline(mat)
return unless mat
dialog_async("3D view",response: proc { |w,e| @ccc=false ; false }) do
make_curve()
@ccc=canvas(1000,800) do
on_canvas_draw do |w,cr|
color=Ruiby_dsl.html_color("#774433")
color1=Ruiby_dsl.html_color("#334477")
cr.set_line_width(2)
@ll.reverse.each_with_index do |line,i|
cr.set_source_rgba((color.red-i*200)/65000.0, (color.green+i*200)/65000.0, color.blue/65000.0, 1)
pt0,*poly=*line
cr.move_to(*pt0)
poly.each {|px| cr.line_to(*px) }
cr.fill
cr.set_source_rgba((color1.red)/65000.0, (color1.green+i)/65000.0, (color1.blue-i*200)/65000.0, 1)
pt0,*poly=*line
cr.move_to(*pt0)
poly.each {|px| cr.line_to(*px) }
cr.stroke
end
end
end
end
end
def make_curve()
mat=@mat
@ll=[]
0.step(MAXL-1,5).each_with_index do |l,ic|
lline=[]
0.step(MAXC-1,1).each do |c|
value=mat[c][l]
lline << [(c+ic*3)*5,400+(400-value*4-ic*10)]
end
@ll << [lline[0].tap {|pt| pt[1]=800}]+lline+[lline[-1].tap {|pt| pt[1]=800}]
end
end
end