factor/extra/boids/boids.factor

160 lines
4.2 KiB
Factor

! Copyright (C) 2008 Eduardo Cavazos.
! Copyright (C) 2011 Anton Gorenko.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays boids.simulation calendar classes kernel
literals locals math math.functions math.trig models namespaces
opengl opengl.demo-support opengl.gl sequences threads ui
ui.gadgets ui.gadgets.borders ui.gadgets.buttons
ui.gadgets.frames ui.gadgets.grids ui.gadgets.labeled
ui.gadgets.labels ui.gadgets.packs ui.gadgets.sliders ui.render ;
QUALIFIED-WITH: models.range mr
IN: boids
TUPLE: boids-gadget < gadget paused boids behaviours dt ;
CONSTANT: initial-population 100
CONSTANT: initial-dt 5
: initial-behaviours ( -- seq )
1.0 75 -0.1 <cohesion>
1.0 40 -0.5 <alignment>
1.0 25 -1.0 <separation>
3array ;
: <boids-gadget> ( -- gadget )
boids-gadget new
t >>clipped?
${ width height } >>pref-dim
initial-population random-boids >>boids
initial-behaviours >>behaviours
initial-dt >>dt ;
M: boids-gadget ungraft*
t >>paused drop ;
: vec>deg ( vec -- deg )
first2 rect> arg rad>deg ; inline
: draw-boid ( boid -- )
dup pos>> [
vel>> vec>deg 0 0 1 glRotated
GL_TRIANGLES [
-6.0 4.0 glVertex2f
-6.0 -4.0 glVertex2f
8.0 0.0 glVertex2f
] do-state
] with-translation ;
: draw-boids ( boids -- )
0.0 0.0 0.0 0.5 glColor4f
[ draw-boid ] each ;
M:: boids-gadget draw-gadget* ( boids-gadget -- )
origin get
[ boids-gadget boids>> draw-boids ] with-translation ;
: iterate-system ( boids-gadget -- )
dup [ boids>> ] [ behaviours>> ] [ dt>> ] tri
simulate >>boids drop ;
:: start-boids-thread ( gadget -- )
[
[ gadget paused>> ]
[
gadget iterate-system
gadget relayout-1
10 milliseconds sleep
] until
] in-thread ;
TUPLE: range-observer quot ;
M: range-observer model-changed
[ range-value ] dip quot>> call( value -- ) ;
: connect ( range-model quot -- )
range-observer boa swap add-connection ;
:: behavior-panel ( behavior -- gadget )
2 3 <frame> { 2 4 } >>gap { 0 0 } >>filled-cell
"weight" <label> { 0 0 } grid-add
behavior weight>> 100 * >fixnum 0 0 200 1 mr:<range>
dup [ 100.0 / behavior weight<< ] connect
horizontal <slider> { 1 0 } grid-add
"radius" <label> { 0 1 } grid-add
behavior radius>> 0 0 100 1 mr:<range>
dup [ behavior radius<< ] connect
horizontal <slider> { 1 1 } grid-add
"angle" <label> { 0 2 } grid-add
behavior angle-cos>> acos rad>deg >fixnum 0 0 180 1 mr:<range>
dup [ deg>rad cos behavior angle-cos<< ] connect
horizontal <slider> { 1 2 } grid-add
behavior class-of name>> <labeled-gadget> ;
:: set-population ( n boids-gadget -- )
boids-gadget [
dup length n - dup 0 >
[ head* ]
[ neg random-boids append ] if
] change-boids drop ;
: pause-toggle ( boids-gadget -- )
dup paused>> not [ >>paused ] keep
[ drop ] [ start-boids-thread ] if ;
: randomize-boids ( boids-gadget -- )
[ length random-boids ] change-boids drop ;
:: simulation-panel ( boids-gadget -- gadget )
<pile> { 2 2 } >>gap
2 2 <frame> { 4 4 } >>gap { 0 0 } >>filled-cell
"population" <label> { 0 0 } grid-add
initial-population 0 0 200 10 mr:<range>
dup [ boids-gadget set-population ] connect
horizontal <slider> { 1 0 } grid-add
"speed" <label> { 0 1 } grid-add
boids-gadget dt>> 0 1 10 1 mr:<range>
dup [ boids-gadget dt<< ] connect
horizontal <slider> { 1 1 } grid-add
add-gadget
<shelf> { 2 2 } >>gap
"pause" [ drop boids-gadget pause-toggle ]
<border-button> add-gadget
"randomize" [ drop boids-gadget randomize-boids ]
<border-button> add-gadget
add-gadget
"simulation" <labeled-gadget> ;
:: create-gadgets ( -- gadgets )
<shelf>
<boids-gadget> :> boids-gadget
boids-gadget [ start-boids-thread ] keep
add-gadget
<pile> { 2 2 } >>gap 1.0 >>fill
boids-gadget simulation-panel
add-gadget
boids-gadget behaviours>>
[ behavior-panel add-gadget ] each
add-gadget
{ 2 2 } <border> ;
MAIN-WINDOW: boids { { title "Boids" } }
create-gadgets
>>gadgets ;