|
Post by bluatigro on Apr 23, 2018 12:20:37 GMT
this i want to do a long time : create a array of boid's that togeter form a swarm or flock or scool
this can be used for sheep [ flock ] brids [ swarm ] and fish [ scool ]
i m not jet ready to code this
a flock , swarm or scool has 4 instruction's : 1 : steer to the midle swarm 2 : don't hit nabor's 3 : steer to the same direction of swarm 4 : some random stering
and in case of a predator : 5 : steer away from predator
until now i coded only rule 4 :
WindowWidth = DisplayWidth WindowHeight = DisplayHeight global winx , winy , pi , animalmax , state$ winx = WindowWidth winy = WindowHeight pi = atn( 1 ) * 4 animalmax = 20 state$ = "left right forwart" dim a.angle( animalmax ) , a.state$( animalmax ) , a.tel( animalmax ) dim a.x( animalmax ) , a.y( animalmax ) nomainwin open "boids sim" for graphics as #m #m "trapclose [quit]" for i = 0 to 36 call sprite.clear 60 , 60 '' a1 = 0 '' b1 = 25 '' a2 = 10 '' b2 = -25 '' a3 = -10 '' b3 = -25 '' call rotate a1,b1 , i * pi / 18 '' call rotate a2,b2 , i * pi / 18 '' call rotate a3,b3 , i * pi / 18 '' call sprite.triangle a1 + 30 , b1 + 30 _ '' , a2 + 30 , b2 + 30 , a3 + 30 , b3 + 30 , "blue" call sprite.ellipse 30,30 , 30,30 _ , "red" , "red" , 1 a = 7 b = 7 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 10 , 10 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 5 , 5 _ , "black" , "black" , 1 a = -7 b = 7 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 10 , 10 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 5 , 5 _ , "black" , "black", 1
call sprite.getbmp "q" ; i anim$ = anim$ + " q" ; i next i for i = 0 to animalmax #m "addsprite animal_" ; i ; anim$ a.x( i ) = range( 0 , winx - 60 ) a.y( i ) = range( 0 , winy - 60 ) dice = int( range( 0 , 36 ) ) #m "spriteimage animal_" ; i ; " q" _ ; dice a.angle( i ) = dice a.state$( i ) = "forwart" a.tel( i ) = int( range( 0 , 50 ) ) next i #m "fill green" #m "getbmp bbmp 0 0 1 1" #m "background bbmp" timer 40 , [timer] wait [quit] close #m end [timer] scan for i = 0 to animalmax dx = 0 dy = 1 #m "spritexy? animal_" ; i ; " x y" select case a.state$( i ) case "left" a.angle( i ) = ( a.angle( i ) + 1 ) mod 36 case "right" a.angle( i ) = ( a.angle( i ) - 1 ) mod 36 case else '' forwart end select #m "spriteimage animal_" ; i ; " q" ; a.angle( i ) a.tel( i ) = a.tel( i ) - 1 if a.tel <= 0 then a.tel( i ) = int( range( 10 , 70 ) ) a.state$( i ) = word$( state$ , int( range( 1 , 4 ) ) ) end if call rotate dx , dy , a.angle( i ) * pi / 18 a.x( i ) = a.x( i ) + dx a.y( i ) = a.y( i ) + dy if a.x( i ) < 0 then a.x( i ) = winx - 60 if a.x( i ) > winx - 60 then a.x( i ) = 0 if a.y( i ) < 0 then a.y( i ) = winy - 60 if a.y( i ) > winy - 60 then a.y( i ) = 0 x = int( a.x( i ) ) y = int( a.y( i ) ) #m "spritexy animal_" ; i _ ; " " ; x ; " " ; y next i #m "drawsprites" wait
function range( low , high ) range = rnd(0) * ( high - low ) + low end function
sub rotate byref k , byref l , r s = sin( r ) c = cos( r ) hk = k * c - l * s hl = k * s + l * c k = hk l = hl end sub
function atan2( x , y ) if y = 0 then if x > 0 then angle = pi / 2 else if x < 0 then angle = 0 - pi / 2 else atan2 = 20 exit function end if end if end if if x < 0 then angle = atn( x / y ) + pi else angle = atn( x / y ) end if if angle < 0-pi then angle = angle + pi * 2 end if if angle > pi then angle = angle - pi * 2 end if atan2 = angle end function
''bluatigro 23 apr 2017 ''sprite module
[sprite] global sprite.width , sprite.height return
sub sprite.clear w , h #m "fill white" #m "goto 0 " ; h #m "size 1" #m "down" #m "color black" #m "backcolor black" #m "boxfilled " ; w ; " " ; h * 2 #m "up" sprite.width = w sprite.height = h end sub
sub swap byref a , byref b h = a a = b b = h end sub
sub sprite.triangle x1 , y1 , x2 , y2 , x3 , y3 , clr$ if y1 = y2 then y1 = y1 - 1e-10 if y2 = y3 then y3 = y3 + 1e-10 if y1 > y3 then call swap y1 , y3 call swap x1 , x3 end if if y1 > y2 then call swap y1 , y2 call swap x1 , x2 end if if y2 > y3 then call swap y2 , y3 call swap x2 , y3 end if #m "size 1" for i = y1 to y3 a = x1 + ( x3 - x1 ) * (i-y1) / ( y3 - y1 ) if i < y2 then b = x1 + ( x2 - x1 ) * (i-y1) / ( y2 - y1 ) else b = x2 + ( x3 - x2 ) * (i-y2) / ( y3 - y2 ) end if #m "color black" #m "down" #m "line " ; a ; " " ; i _ ; " " ; b ; " " ; i #m "up" #m "color " ; clr$ #m "down" #m "line " ; a ; " " ; i + sprite.height _ ; " " ; b ; " " ; i + sprite.height #m "up"
next i #m "flush" end sub
sub sprite.rectangle x1,y1,x2,y2,clr$ #m "goto " ; x1 ; " " ; y1 #m "size 1" #m "color black" #m "backcolor black" #m "down" #m "boxfilled " ; x2 ; " " ; y2 #m "up" #m "goto " ; x1 ; " " ; y1 + sprite.height #m "color " ; clr$ #m "backcolor " ; clr$ #m "down" #m "boxfilled " ; x2 ; " " ; y2 + 60 #m "up" end sub
sub sprite.ellipse x,y,dx,dy,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "ellipsefilled " ; dx ; " " ; dy #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "ellipsefilled " ; dx ; " " ; dy #m "up" end sub
sub sprite.pie x,y,dx,dy,a,b,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" end sub
sub sprite.line x1,y1 , x2,y2 , clr$ , size #m "color black" #m "size " ; size #m "down" #m "line " ; x1 ; " " ; y1 _ ; " " ; x2 ; " " ; y2 #m "up" #m "color " ; clr$ #m "down" #m "line " ; x1 ; " " ; y1 + sprite.height _ ; " " ; x2 ; " " ; y2 + sprite.height #m "up" end sub
sub sprite.getbmp bmp$ #m "getbmp " ; bmp$ ; " 0 0 " _ ; sprite.width ; " " ; sprite.height * 2 end sub
error : if i use the triangle code i get strage effect's
|
|
|
Post by B+ on Apr 23, 2018 13:04:27 GMT
Hi bluatigro, I tried your code and those critters are cute! all it takes is a bubble with 2 eyes. To me, they are just kind of floating around randomly? The flocking and/or schooling is not apparent, maybe try having them flock and school around current mouse position? Also scanning the code, I am not seeing detection of closeness of 1 critter to all the others, maybe I missed it? Also it would be cool if the eyes were pointed into the direction they are moving.
|
|
|
Post by bluatigro on Apr 24, 2018 5:25:38 GMT
@ b+ : i did not jet implement the other code i only build the random steer code this is on the edge on what i can code
i want help whit the other stering rules
update : i aperently did not post the last version so here it is :
''bluatigro 24 apr 2018 ''boid's sim
WindowWidth = DisplayWidth WindowHeight = DisplayHeight global winx , winy , pi , animalmax , state$ winx = WindowWidth winy = WindowHeight pi = atn( 1 ) * 4 animalmax = 20 state$ = "left right forwart" dim a.angle( animalmax ) , a.state$( animalmax ) , a.tel( animalmax ) dim a.x( animalmax ) , a.y( animalmax ) nomainwin open "boids sim" for graphics as #m #m "trapclose [quit]" for i = 0 to 36 call sprite.clear 60 , 60 '' a1 = 0 '' b1 = 25 '' a2 = 10 '' b2 = -25 '' a3 = -10 '' b3 = -25 '' call rotate a1,b1 , i * pi / 18 '' call rotate a2,b2 , i * pi / 18 '' call rotate a3,b3 , i * pi / 18 '' call sprite.triangle a1 + 30 , b1 + 30 _ '' , a2 + 30 , b2 + 30 , a3 + 30 , b3 + 30 , "blue" call sprite.ellipse 30,30 , 30,30 _ , "red" , "red" , 1 a = 7 b = 7 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 10 , 10 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 5 , 5 _ , "black" , "black" , 1 a = -7 b = 7 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 10 , 10 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 5 , 5 _ , "black" , "black", 1
call sprite.getbmp "q" ; i anim$ = anim$ + " q" ; i next i for i = 0 to animalmax #m "addsprite animal_" ; i ; anim$ a.x( i ) = range( 0 , winx - 60 ) a.y( i ) = range( 0 , winy - 60 ) dice = int( range( 0 , 36 ) ) #m "spriteimage animal_" ; i ; " q" _ ; dice a.angle( i ) = dice a.state$( i ) = "forwart" a.tel( i ) = int( range( 0 , 50 ) ) next i #m "fill green" #m "getbmp bbmp 0 0 1 1" #m "background bbmp" #m "when characerInput [key]" #m "setfocus" timer 40 , [timer] wait [key] key$ = right$( Inkey$ , 1 ) if key$ <> chr$( _VK_ESCAPE ) then wait [quit] close #m end [timer] scan for i = 0 to animalmax dx = 0 dy = 1 #m "spritexy? animal_" ; i ; " x y" select case a.state$( i ) case "left" a.angle( i ) = ( a.angle( i ) + 1 ) mod 36 case "right" a.angle( i ) = ( a.angle( i ) - 1 ) mod 36 case else '' forwart end select #m "spriteimage animal_" ; i ; " q" ; a.angle( i ) a.tel( i ) = a.tel( i ) - 1 if a.tel <= 0 then a.tel( i ) = int( range( 10 , 70 ) ) a.state$( i ) = word$( state$ , int( range( 1 , 4 ) ) ) end if call rotate dx , dy , a.angle( i ) * pi / 18 a.x( i ) = a.x( i ) + dx a.y( i ) = a.y( i ) + dy if a.x( i ) < 0 then a.x( i ) = winx - 60 if a.x( i ) > winx - 60 then a.x( i ) = 0 if a.y( i ) < 0 then a.y( i ) = winy - 60 if a.y( i ) > winy - 60 then a.y( i ) = 0 x = int( a.x( i ) ) y = int( a.y( i ) ) #m "spritexy animal_" ; i _ ; " " ; x ; " " ; y next i #m "drawsprites" wait
function range( low , high ) range = rnd(0) * ( high - low ) + low end function
sub rotate byref k , byref l , r s = sin( r ) c = cos( r ) hk = k * c - l * s hl = k * s + l * c k = hk l = hl end sub
function atan2( x , y ) if y = 0 then if x > 0 then angle = pi / 2 else if x < 0 then angle = 0 - pi / 2 else atan2 = 20 exit function end if end if end if if x < 0 then angle = atn( x / y ) + pi else angle = atn( x / y ) end if if angle < 0-pi then angle = angle + pi * 2 end if if angle > pi then angle = angle - pi * 2 end if atan2 = angle end function
''bluatigro 23 apr 2017 ''sprite module
[sprite] global sprite.width , sprite.height return
sub sprite.clear w , h #m "fill white" #m "goto 0 " ; h #m "size 1" #m "down" #m "color black" #m "backcolor black" #m "boxfilled " ; w ; " " ; h * 2 #m "up" sprite.width = w sprite.height = h end sub
sub swap byref a , byref b h = a a = b b = h end sub
sub sprite.triangle x1 , y1 , x2 , y2 , x3 , y3 , clr$ if y1 = y2 then y1 = y1 - 1e-10 if y2 = y3 then y3 = y3 + 1e-10 if y1 > y3 then call swap y1 , y3 call swap x1 , x3 end if if y1 > y2 then call swap y1 , y2 call swap x1 , x2 end if if y2 > y3 then call swap y2 , y3 call swap x2 , y3 end if #m "size 1" for i = y1 to y3 a = x1 + ( x3 - x1 ) * (i-y1) / ( y3 - y1 ) if i < y2 then b = x1 + ( x2 - x1 ) * (i-y1) / ( y2 - y1 ) else b = x2 + ( x3 - x2 ) * (i-y2) / ( y3 - y2 ) end if #m "color black" #m "down" #m "line " ; a ; " " ; i _ ; " " ; b ; " " ; i #m "up" #m "color " ; clr$ #m "down" #m "line " ; a ; " " ; i + sprite.height _ ; " " ; b ; " " ; i + sprite.height #m "up"
next i #m "flush" end sub
sub sprite.rectangle x1,y1,x2,y2,clr$ #m "goto " ; x1 ; " " ; y1 #m "size 1" #m "color black" #m "backcolor black" #m "down" #m "boxfilled " ; x2 ; " " ; y2 #m "up" #m "goto " ; x1 ; " " ; y1 + sprite.height #m "color " ; clr$ #m "backcolor " ; clr$ #m "down" #m "boxfilled " ; x2 ; " " ; y2 + 60 #m "up" end sub
sub sprite.ellipse x,y,dx,dy,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "ellipsefilled " ; dx ; " " ; dy #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "ellipsefilled " ; dx ; " " ; dy #m "up" end sub
sub sprite.pie x,y,dx,dy,a,b,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" end sub
sub sprite.line x1,y1 , x2,y2 , clr$ , size #m "color black" #m "size " ; size #m "down" #m "line " ; x1 ; " " ; y1 _ ; " " ; x2 ; " " ; y2 #m "up" #m "color " ; clr$ #m "down" #m "line " ; x1 ; " " ; y1 + sprite.height _ ; " " ; x2 ; " " ; y2 + sprite.height #m "up" end sub
sub sprite.getbmp bmp$ #m "getbmp " ; bmp$ ; " 0 0 " _ ; sprite.width ; " " ; sprite.height * 2 end sub
|
|
|
Post by B+ on Apr 24, 2018 15:32:34 GMT
Ah, well that explains it! I think I will give it a go myself, without sprites for testing. It might be interesting...
|
|
|
Post by B+ on Apr 24, 2018 18:35:10 GMT
Here is some code for early test to get the critters pointed at the mouse (and where they will heading): 'Mouse school early test.txt for JB 2.0 B+ 2018-04-24
'from: star mouse chaser.bas 01 - back to JB 'from: star mouse chaser.bas for SmallBASIC 0.12.0 2015-11-09 MGA/B+ 'from: code is based on code: mouse chaser by tsh73 'for the Just Basic contest, November 2008, I am 7 years late 'AND Combined with (mostly from here): 'Arrow test.txt for Just Basic v1.01 [B+=MGA] 2017-05-09
NoMainWin global xmax, ymax, pi, mx, my xmax = 1200 : ymax = 700 : pi = acs(-1)
WindowWidth = xmax + 8 WindowHeight = ymax + 32 UpperLeftX = 100 UpperLeftY = 40 Open "Mouse school early test" For Graphics_nsb_nf As #g #g "trapclose quit" #g "setfocus" #g "when leftButtonUp lButtonUp" #g "when characterInput charIn" #g "when mouseMove move" #g "down" #g "fill black" #g "color yellow"
na = 200 dim x(na), y(na) for i = 1 to na x(i) = rand(0, xmax) y(i) = rand(0, ymax) next
while 1 scan #g "cls" #g "fill black" for i = 1 to na ra = atan2(my-y(i), mx-x(i)) ' + pi kind of interesting too call arrow x(i), y(i), ra, .2*sqr((mx-x(i))^2 + (my-y(i))^2) next #g "flush" call pause 1000 wend wait
'---------------- windows setup calls
sub quit H$ close #H$ end end sub
sub lButtonUp H$, mx, my 'must have handle and mouse x,y call quit H$ end sub
sub charIn H$, c$ call quit H$ end sub
sub move H$, MouseX, MouseY mx = MouseX my = MouseY end sub
'--------------- important subs for this program
sub arrow x0, y0, rAngle, distance x2 = x0 - .1 * distance * cos(rAngle - .25 * pi) y2 = y0 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - .1 * distance * cos(rAngle + .25 * pi) y2 = y0 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - distance * cos(rAngle) y2 = y0 - distance * sin(rAngle) #g "line ";x0;" ";y0;" ";x2;" ";y2 for i = .8 * distance to distance step 3 x1 = x0 - i * cos(rAngle) y1 = y0 - i * sin(rAngle) x2 = x1 - .1 * distance * cos(rAngle - .25 * pi) y2 = y1 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 x2 = x1 - .1 * distance * cos(rAngle + .25 * pi) y2 = y1 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 next end sub
Function atan2(y,x) 'thanks Andy Amaya 'atan2 is a function which determines the angle between points 'x1, y1 and x2, y2. The angle returned is in radians 'The angle returned is always in the range of '-PI to PI radians (-180 to 180 degrees) '============================================================== 'NOTE the position of Y and X arguments 'This keeps atan2 function same as other language versions '============================================================== If x = 0 Then If y < 0 Then atan2 = -1.5707963267948967 Else atan2 = 1.5707963267948967 End If Else chk = atn(y/x) If x < 0 Then If y < 0 Then chk = chk - 3.1415926535897932 Else chk = chk + 3.1415926535897932 End If End If atan2 = chk End If End Function
'----------------- supplementary handy subs
sub pause mil 'tsh version has scan built-in t0 = time$("ms") while time$("ms") < t0 + mil : scan : wend end sub
function rand(lo, hi) rand = int((hi - lo + 1) * rnd(0)) + lo end function
I will probably be using tsh73 stuff from mouse chaser later.
|
|
|
Post by B+ on Apr 24, 2018 20:37:22 GMT
When on the move, they sure bunch up fast! 'Mouse school bunching critters.txt for JB 2.0 B+ 2018-04-24
'from: star mouse chaser.bas 01 - back to JB 'from: star mouse chaser.bas for SmallBASIC 0.12.0 2015-11-09 MGA/B+ 'from: code is based on code: mouse chaser by tsh73 'for the Just Basic contest, November 2008, I am 7 years late 'AND Combined with 'Arrow test.txt for Just Basic v1.01 [B+=MGA] 2017-05-09
NoMainWin global xmax, ymax, pi, mx, my xmax = 1200 : ymax = 700 : pi = acs(-1)
WindowWidth = xmax + 8 WindowHeight = ymax + 32 UpperLeftX = 100 UpperLeftY = 40 Open "Mouse school" For Graphics_nsb_nf As #g #g "trapclose quit" #g "setfocus" #g "when leftButtonUp lButtonUp" #g "when characterInput charIn" #g "when mouseMove move" #g "down" #g "fill black" #g "color yellow"
na = 100 dim x(na), y(na), v(na) for i = 1 to na x(i) = rand(0, xmax) y(i) = rand(0, ymax) v(i) = rand(100, 500) next
while 1 scan #g "cls" #g "fill black" for i = 1 to na d = sqr((mx - x(i))^2 + (my - y(i))^2) ra = atan2(my - y(i), mx - x(i)) ' + pi kind of interesting too call critter x(i), y(i), ra, .05 * d x(i) = x(i) + .05 * v(i) * cos(ra) y(i) = y(i) + .05 * v(i) * sin(ra) next #g "flush" call pause 100 wend wait
'---------------- windows setup calls
sub quit H$ close #H$ end end sub
sub lButtonUp H$, mx, my 'must have handle and mouse x,y call quit H$ end sub
sub charIn H$, c$ call quit H$ end sub
sub move H$, MouseX, MouseY mx = MouseX my = MouseY end sub
'--------------- important subs for this program
sub critter x, y, ra, s #g "color black" #g "backcolor darkgreen" #g "place ";x;" ";y;"; circlefilled ";s x1 = x + .75*s * cos(ra - pi/9) y1 = y + .75*s * sin(ra - pi/9) x2 = x + .75*s * cos(ra + pi/9) y2 = y + .75*s * sin(ra + pi/9) #g "color white" #g "backcolor white" #g "place ";x1;" ";y1;"; circlefilled ";.25*s #g "place ";x2;" ";y2;"; circlefilled ";.25*s x3 = x1 + .125 * s * cos(ra) y3 = y1 + .125 * s * sin(ra) x4 = x2 + .125 * s * cos(ra) y4 = y2 + .125 * s * sin(ra) #g "color black" #g "backcolor black" #g "place ";x3;" ";y3;"; circlefilled ";.125*s #g "place ";x4;" ";y4;"; circlefilled ";.125*s end sub
sub arrow x0, y0, rAngle, distance x2 = x0 - .1 * distance * cos(rAngle - .25 * pi) y2 = y0 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - .1 * distance * cos(rAngle + .25 * pi) y2 = y0 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - distance * cos(rAngle) y2 = y0 - distance * sin(rAngle) #g "line ";x0;" ";y0;" ";x2;" ";y2 for i = .8 * distance to distance step 3 x1 = x0 - i * cos(rAngle) y1 = y0 - i * sin(rAngle) x2 = x1 - .1 * distance * cos(rAngle - .25 * pi) y2 = y1 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 x2 = x1 - .1 * distance * cos(rAngle + .25 * pi) y2 = y1 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 next end sub
Function atan2(y,x) 'thanks Andy Amaya 'atan2 is a function which determines the angle between points 'x1, y1 and x2, y2. The angle returned is in radians 'The angle returned is always in the range of '-PI to PI radians (-180 to 180 degrees) '============================================================== 'NOTE the position of Y and X arguments 'This keeps atan2 function same as other language versions '============================================================== If x = 0 Then If y < 0 Then atan2 = -1.5707963267948967 Else atan2 = 1.5707963267948967 End If Else chk = atn(y/x) If x < 0 Then If y < 0 Then chk = chk - 3.1415926535897932 Else chk = chk + 3.1415926535897932 End If End If atan2 = chk End If End Function
'----------------- supplementary handy subs
sub pause mil 'tsh version has scan built-in t0 = time$("ms") while time$("ms") < t0 + mil : scan : wend end sub
function rand(lo, hi) rand = int((hi - lo + 1) * rnd(0)) + lo end function
|
|
|
Post by tsh73 on Apr 24, 2018 20:55:48 GMT
Well, making size proportional distance to mouse makes some strange effects They move away - like far far away, in distant galaxy long time ago But on mouse move they suddenly gets BIGGER
|
|
|
Post by B+ on Apr 24, 2018 21:35:56 GMT
Well, making size proportional distance to mouse makes some strange effects They move away - like far far away, in distant galaxy long time ago But on mouse move they suddenly gets BIGGER Well hopefully we can turn that frown upside down. I gave the critters constant radius and have code to keep them separated temporarily. Looking about as I envisioned it. 'Mouse school critters separated.txt for JB 2.0 B+ 2018-04-24
'from: star mouse chaser.bas 01 - back to JB 'from: star mouse chaser.bas for SmallBASIC 0.12.0 2015-11-09 MGA/B+ 'from: code is based on code: mouse chaser by tsh73 'for the Just Basic contest, November 2008, I am 7 years late 'AND Combined with 'Arrow test.txt for Just Basic v1.01 [B+=MGA] 2017-05-09 ' Thanks to STxAxTIC at QB64 for method to separate particles ' Give critters constant radius
NoMainWin global xmax, ymax, pi, mx, my xmax = 1200 : ymax = 700 : pi = acs(-1)
WindowWidth = xmax + 8 WindowHeight = ymax + 32 UpperLeftX = 100 UpperLeftY = 40 Open "Mouse school" For Graphics_nsb_nf As #g #g "trapclose quit" #g "setfocus" #g "when leftButtonUp lButtonUp" #g "when characterInput charIn" #g "when mouseMove move" #g "down" #g "fill black" #g "color yellow"
na = 30 dim x(na), y(na), v(na), r(na) for i = 1 to na x(i) = rand(0, xmax) y(i) = rand(0, ymax) v(i) = rand(5, 20) r(i) = rand(5, 20) next
while 1 scan #g "cls" #g "fill black" for i = 1 to na 'radian angle to mouse ra = atan2(my - y(i), mx - x(i)) ' + pi kind of interesting too 'draw it call critter x(i), y(i), ra, r(i)
'separate critters for next frame and further down i line FOR j = i + 1 TO na scan
' The following is STATIC's adjustment of ball positions if overlapping ' before calcultion of new positions from collision ' Displacement vector and its magnitude. Thanks STxAxTIC ! nx = x(j) - x(i) ny = y(j) - y(i) nm = SQR(nx ^ 2 + ny ^ 2) IF nm < 10 + r(i) + r(j) THEN nx = nx / nm ny = ny / nm
' Regardless of momentum exchange, separate the balls along the lone connecting them. WHILE nm < 10 + r(i) +r(j) scan flub = 10 ' massively increased for JB to speed up code
x(j) = x(j) + flub * nx y(j) = y(j) + flub * ny
x(i) = x(i) - flub * nx y(i) = y(i) - flub * ny
nx = x(j) - x(i) ny = y(j) - y(i) nm = SQR(nx ^ 2 + ny ^ 2) nx = nx / nm ny = ny / nm wend end if next x(i) = x(i) + v(i) * cos(ra) y(i) = y(i) + v(i) * sin(ra) next #g "flush" call pause 100 wend wait
'---------------- windows setup calls
sub quit H$ close #H$ end end sub
sub lButtonUp H$, mx, my 'must have handle and mouse x,y call quit H$ end sub
sub charIn H$, c$ call quit H$ end sub
sub move H$, MouseX, MouseY mx = MouseX my = MouseY end sub
'--------------- important subs for this program
sub critter x, y, ra, s #g "color black" #g "backcolor darkgreen" #g "place ";x;" ";y;"; circlefilled ";s x1 = x + .75*s * cos(ra - pi/9) y1 = y + .75*s * sin(ra - pi/9) x2 = x + .75*s * cos(ra + pi/9) y2 = y + .75*s * sin(ra + pi/9) #g "color white" #g "backcolor white" #g "place ";x1;" ";y1;"; circlefilled ";.25*s #g "place ";x2;" ";y2;"; circlefilled ";.25*s x3 = x1 + .125 * s * cos(ra) y3 = y1 + .125 * s * sin(ra) x4 = x2 + .125 * s * cos(ra) y4 = y2 + .125 * s * sin(ra) #g "color black" #g "backcolor black" #g "place ";x3;" ";y3;"; circlefilled ";.125*s #g "place ";x4;" ";y4;"; circlefilled ";.125*s end sub
sub arrow x0, y0, rAngle, distance x2 = x0 - .1 * distance * cos(rAngle - .25 * pi) y2 = y0 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - .1 * distance * cos(rAngle + .25 * pi) y2 = y0 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - distance * cos(rAngle) y2 = y0 - distance * sin(rAngle) #g "line ";x0;" ";y0;" ";x2;" ";y2 for i = .8 * distance to distance step 3 x1 = x0 - i * cos(rAngle) y1 = y0 - i * sin(rAngle) x2 = x1 - .1 * distance * cos(rAngle - .25 * pi) y2 = y1 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 x2 = x1 - .1 * distance * cos(rAngle + .25 * pi) y2 = y1 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 next end sub
Function atan2(y,x) 'thanks Andy Amaya 'atan2 is a function which determines the angle between points 'x1, y1 and x2, y2. The angle returned is in radians 'The angle returned is always in the range of '-PI to PI radians (-180 to 180 degrees) '============================================================== 'NOTE the position of Y and X arguments 'This keeps atan2 function same as other language versions '============================================================== If x = 0 Then If y < 0 Then atan2 = -1.5707963267948967 Else atan2 = 1.5707963267948967 End If Else chk = atn(y/x) If x < 0 Then If y < 0 Then chk = chk - 3.1415926535897932 Else chk = chk + 3.1415926535897932 End If End If atan2 = chk End If End Function
'----------------- supplementary handy subs
sub pause mil 'tsh version has scan built-in t0 = time$("ms") while time$("ms") < t0 + mil : scan : wend end sub
function rand(lo, hi) rand = int((hi - lo + 1) * rnd(0)) + lo end function
|
|
|
Post by bluatigro on Apr 25, 2018 11:21:04 GMT
update : added a predator the predator does not move jet made function's of stering rules so i can test then 1 by 1
see the report after the function cal on how wel they work
rem : random.walk is not a stering rule
''bluatigro 24 apr 2018 ''boid's sim
WindowWidth = DisplayWidth WindowHeight = DisplayHeight global winx , winy , pi , animalmax , state$ winx = WindowWidth winy = WindowHeight pi = atn( 1 ) * 4 animalmax = 20 state$ = "left right forwart" dim a.angle( animalmax ) , a.state$( animalmax ) , a.tel( animalmax ) dim a.x( animalmax ) , a.y( animalmax ) , ry( animalmax ) , dist( animalmax ) nomainwin open "boids sim" for graphics as #m #m "trapclose [quit]" for i = 0 to 36 call sprite.clear 60 , 60 '' a1 = 0 '' b1 = 25 '' a2 = 10 '' b2 = -25 '' a3 = -10 '' b3 = -25 '' call rotate a1,b1 , i * pi / 18 '' call rotate a2,b2 , i * pi / 18 '' call rotate a3,b3 , i * pi / 18 '' call sprite.triangle a1 + 30 , b1 + 30 _ '' , a2 + 30 , b2 + 30 , a3 + 30 , b3 + 30 , "blue" call sprite.ellipse 30,30 , 30,30 _ , "blue" , "blue" , 1 a = 10 b = 10 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 ,7 _ , "black" , "black" , 1 a = -10 b = 10 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 , 7 _ , "black" , "black", 1
call sprite.getbmp "q" ; i anim$ = anim$ + " q" ; i call sprite.clear 60 , 60 '' a1 = 0 '' b1 = 25 '' a2 = 10 '' b2 = -25 '' a3 = -10 '' b3 = -25 '' call rotate a1,b1 , i * pi / 18 '' call rotate a2,b2 , i * pi / 18 '' call rotate a3,b3 , i * pi / 18 '' call sprite.triangle a1 + 30 , b1 + 30 _ '' , a2 + 30 , b2 + 30 , a3 + 30 , b3 + 30 , "blue" call sprite.ellipse 30,30 , 30,30 _ , "red" , "red" , 1 a = 10 b = 13 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 , 7 _ , "black" , "black" , 1 a = -10 b = 13 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 , 7 _ , "black" , "black", 1
call sprite.getbmp "p" ; i pred$ = pred$ + " p" ; i next i for i = 0 to animalmax #m "addsprite animal_" ; i ; anim$ a.x( i ) = range( 0 , winx - 60 ) a.y( i ) = range( 0 , winy - 60 ) dice = int( range( 0 , 36 ) ) #m "spriteimage animal_" ; i ; " q" _ ; dice a.angle( i ) = dice a.state$( i ) = "forwart" a.tel( i ) = int( range( 0 , 50 ) ) ry( i ) = i next i #m "addsprite predator " ; pred$ #m "spritexy predator 100 100" #m "fill darkgreen" #m "getbmp bbmp 0 0 1 1" #m "background bbmp" #m "when characterInput [key]" #m "setfocus" timer 40 , [timer] wait [key] key$ = right$( Inkey$ , 1 ) if key$ <> chr$( _VK_ESCAPE ) then wait [quit] close #m end [timer] scan for i = 0 to animalmax dx = 0 dy = 1 dangle = 0 '' dangle = random.walk( i ) ''not jet good '' dangle = dangle + dont.hit.nabor( i ) ''gives crash '' dangle = dangle + steer.to.center( i ) ''not jet good dangle = dabgle + steer.as.others( i ) ''works dangle = dangle + steer.random( i ) ''works '' dangle = dangle + avoid.predator( i ) ''not jet good
a.angle( i ) = a.angle( i ) + dangle no = int2( a.angle( i ) ) if no < 0 then no = no + 36 #m "spriteimage animal_" ; i ; " q" ; no call rotate dx , dy , a.angle( i ) * pi / 18 a.x( i ) = a.x( i ) + dx a.y( i ) = a.y( i ) + dy if a.x( i ) < 0 then a.x( i ) = winx - 60 if a.x( i ) > winx - 60 then a.x( i ) = 0 if a.y( i ) < 0 then a.y( i ) = winy - 60 if a.y( i ) > winy - 60 then a.y( i ) = 0 x = int( a.x( i ) ) y = int( a.y( i ) ) #m "spritexy animal_" ; i ; " " ; x ; " " ; y next i #m "drawsprites" wait function random.walk( i ) a.tel( i ) = a.tel( i ) - 1 if a.tel( i ) < 0 then a.tel( i ) = range( 5 , 18 ) a.state$( i ) = word$( state$ , int( range( 1 , 4 ) ) ) end if uit = 0 select case a.state$( i ) case "left" uit = 1 case "right" uit = -1 case else end select random.walk = uit end function ''stering rules function avoid.predator( i ) i.x = a.x( i ) i.y = a.y( i ) #m "spritexy? predator p.x p.y" hoek = atan2( p.x - i.x , p.y - i.y ) / pi * 18 q = hoek - a.angle( i ) if q < 0 then q = q + 36 d = length( p.x - i.x , p.y - i.y ) + 1 if d < 90 then if q < 9 then uit = 2 / d end if if q > 27 then uit = -2 / d end if end if avoid.predator = uit end function function steer.random( i ) steer.random = range( -1 , 1 ) end function function steer.as.others( i ) i.a = a.angle( i ) uit = 0 for j = 0 to animalmax j.a = a.angle( j ) uit = uit + ( j.a - i.a ) mod 36 next j steer.as.others = uit / animalmax / 36 end function function steer.to.center( i ) i.x = a.x( i ) i.y = a.y( i ) swarm.x = 0 swarm.y = 0 for j = 0 to animalmax swarm.x = swarm.x + a.x( j ) swarm.y = swarm.y + a.y( j ) next j swarm.x = swarm.x / animalmax swarm.y = swarm.y / animalmax hoek = atan2( swarm.x - i.x , swarm.y - i.y ) / pi * 18 i.a = a.angle( i ) q = hoek - i.a if q < 0 then q = q + 36 if q < 18 then uit = -2 else uit = 2 end if steer.to.center = uit end function function dont.hit.nabor( i ) i.x = a.x( i ) i.y = a.y( i ) for j = 0 to animalmax j.x = a.x( j ) j.y = a.y( j ) dist( j ) = length( i.x - j.x , i.y - j.y ) next j for high = 1 to animalmax for low = 0 to high - 1 if dist( ry( high ) ) < dist( ry( low ) ) then help = ry( high ) ry( high ) = ry( low ) ry( low ) = help end if next low next high b = a.angle( ry( 0 ) ) uit = 0 for j = 1 to 5 a = int2( animal.angle( ry( 0 ) , ry( j ) ) / pi * 36 ) if b < a then uit = uit - 1 / j end if if b > a then uit = uit + 1 / j end if next j dont.hit.nabor = uit end function ''end stering rules function animal.angle( a1 , a2 ) angle = atan2( a.x( a2 ) - a.x( a1 ) , a.y( a2 ) - a.y( a1 ) ) end function function length( x , y ) length = sqr( x ^ 2 + y ^ 2 ) end function function range( low , high ) range = rnd(0) * ( high - low ) + low end function function int2( x ) if sign( x ) = -1 then x = x + 1 int2 = int( x ) end function function sign( x ) uit = 0 if x < 0 then uit = -1 if x > 0 then uit = 1 sign = uit end function sub rotate byref k , byref l , r s = sin( r ) c = cos( r ) hk = k * c - l * s hl = k * s + l * c k = hk l = hl end sub
function atan2( x , y ) if y = 0 then if x > 0 then angle = pi / 2 else if x < 0 then angle = 0 - pi / 2 else atan2 = 20 exit function end if end if end if if x < 0 then angle = atn( x / y ) + pi else angle = atn( x / y ) end if if angle < 0-pi then angle = angle + pi * 2 end if if angle > pi then angle = angle - pi * 2 end if atan2 = angle end function
''bluatigro 23 apr 2017 ''sprite module
[sprite] global sprite.width , sprite.height return
sub sprite.clear w , h #m "fill white" #m "goto 0 " ; h #m "size 1" #m "down" #m "color black" #m "backcolor black" #m "boxfilled " ; w ; " " ; h * 2 #m "up" sprite.width = w sprite.height = h end sub
sub swap byref a , byref b h = a a = b b = h end sub
sub sprite.triangle x1 , y1 , x2 , y2 , x3 , y3 , clr$ if y1 = y2 then y1 = y1 - 1e-10 if y2 = y3 then y3 = y3 + 1e-10 if y1 > y3 then call swap y1 , y3 call swap x1 , x3 end if if y1 > y2 then call swap y1 , y2 call swap x1 , x2 end if if y2 > y3 then call swap y2 , y3 call swap x2 , y3 end if #m "size 1" for i = y1 to y3 a = x1 + ( x3 - x1 ) * (i-y1) / ( y3 - y1 ) if i < y2 then b = x1 + ( x2 - x1 ) * (i-y1) / ( y2 - y1 ) else b = x2 + ( x3 - x2 ) * (i-y2) / ( y3 - y2 ) end if #m "color black" #m "down" #m "line " ; a ; " " ; i _ ; " " ; b ; " " ; i #m "up" #m "color " ; clr$ #m "down" #m "line " ; a ; " " ; i + sprite.height _ ; " " ; b ; " " ; i + sprite.height #m "up"
next i #m "flush" end sub
sub sprite.rectangle x1,y1,x2,y2,clr$ #m "goto " ; x1 ; " " ; y1 #m "size 1" #m "color black" #m "backcolor black" #m "down" #m "boxfilled " ; x2 ; " " ; y2 #m "up" #m "goto " ; x1 ; " " ; y1 + sprite.height #m "color " ; clr$ #m "backcolor " ; clr$ #m "down" #m "boxfilled " ; x2 ; " " ; y2 + 60 #m "up" end sub
sub sprite.ellipse x,y,dx,dy,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "ellipsefilled " ; dx ; " " ; dy #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "ellipsefilled " ; dx ; " " ; dy #m "up" end sub
sub sprite.pie x,y,dx,dy,a,b,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" end sub
sub sprite.line x1,y1 , x2,y2 , clr$ , size #m "color black" #m "size " ; size #m "down" #m "line " ; x1 ; " " ; y1 _ ; " " ; x2 ; " " ; y2 #m "up" #m "color " ; clr$ #m "down" #m "line " ; x1 ; " " ; y1 + sprite.height _ ; " " ; x2 ; " " ; y2 + sprite.height #m "up" end sub
sub sprite.getbmp bmp$ #m "getbmp " ; bmp$ ; " 0 0 " _ ; sprite.width ; " " ; sprite.height * 2 end sub
|
|
|
Post by bluatigro on Apr 26, 2018 13:15:48 GMT
update : i added a red circle in this circle the blue boid's shoot steer away from the predator they do not seem to react on the red predator and sometimes they stick to the predator so avoid.predator() has error
WHERE DO THESE STRIPES COME FROM ?
''bluatigro 24 apr 2018 ''boid's sim
WindowWidth = DisplayWidth WindowHeight = DisplayHeight global winx , winy , pi , animalmax , state$ winx = WindowWidth winy = WindowHeight pi = atn( 1 ) * 4 animalmax = 20 state$ = "left right forwart" dim a.angle( animalmax ) , a.state$( animalmax ) , a.tel( animalmax ) dim a.x( animalmax ) , a.y( animalmax ) , ry( animalmax ) , dist( animalmax ) nomainwin open "boids sim" for graphics as #m #m "trapclose [quit]" for i = 0 to 36 call sprite.clear 60 , 60 '' a1 = 0 '' b1 = 25 '' a2 = 10 '' b2 = -25 '' a3 = -10 '' b3 = -25 '' call rotate a1,b1 , i * pi / 18 '' call rotate a2,b2 , i * pi / 18 '' call rotate a3,b3 , i * pi / 18 '' call sprite.triangle a1 + 30 , b1 + 30 _ '' , a2 + 30 , b2 + 30 , a3 + 30 , b3 + 30 , "blue" call sprite.ellipse 30,30 , 30,30 _ , "blue" , "blue" , 1 a = 10 b = 10 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 ,7 _ , "black" , "black" , 1 a = -10 b = 10 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 , 7 _ , "black" , "black", 1
call sprite.getbmp "q" ; i anim$ = anim$ + " q" ; i call sprite.clear 60 , 60 '' a1 = 0 '' b1 = 25 '' a2 = 10 '' b2 = -25 '' a3 = -10 '' b3 = -25 '' call rotate a1,b1 , i * pi / 18 '' call rotate a2,b2 , i * pi / 18 '' call rotate a3,b3 , i * pi / 18 '' call sprite.triangle a1 + 30 , b1 + 30 _ '' , a2 + 30 , b2 + 30 , a3 + 30 , b3 + 30 , "blue" call sprite.ellipse 30,30 , 30,30 _ , "red" , "red" , 1 a = 10 b = 13 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 , 7 _ , "black" , "black" , 1 a = -10 b = 13 call rotate a,b , i * pi / 18 call sprite.ellipse a + 30 , b + 30 , 15 , 15 _ , "black" , "white" , 1 call sprite.ellipse a + 30 , b + 30 , 7 , 7 _ , "black" , "black", 1
call sprite.getbmp "p" ; i pred$ = pred$ + " p" ; i next i for i = 0 to animalmax #m "addsprite animal_" ; i ; anim$ a.x( i ) = range( 0 , winx - 60 ) a.y( i ) = range( 0 , winy - 60 ) dice = int( range( 0 , 36 ) ) #m "spriteimage animal_" ; i ; " q" _ ; dice a.angle( i ) = dice a.state$( i ) = "forwart" a.tel( i ) = int( range( 0 , 50 ) ) ry( i ) = i next i #m "addsprite predator " ; pred$ #m "spritexy predator 100 100" #m "fill darkgreen" #m "goto 130 130" #m "color red" #m "size 5" #m "down" #m "circle 130" #m "up" #m "getbmp bbmp 0 0 " ; winx ; " " ; winy #m "background bbmp" #m "when characterInput [key]" #m "setfocus" timer 40 , [timer] wait [key] key$ = right$( Inkey$ , 1 ) if key$ <> chr$( _VK_ESCAPE ) then wait [quit] close #m end [timer] scan for i = 0 to animalmax dx = 0 dy = 1 dangle = 0 '' dangle = random.walk( i ) ''not jet good '' dangle = dangle + dont.hit.nabor( i ) ''gives crash '' dangle = dangle + steer.to.center( i ) ''not jet good '' dangle = dangle + steer.as.others( i ) ''works '' dangle = dangle + steer.random( i ) ''works dangle = dangle + avoid.predator( i ) ''not jet good
a.angle( i ) = a.angle( i ) + dangle no = int2( a.angle( i ) ) if no < 0 then no = no + 36 #m "spriteimage animal_" ; i ; " q" ; no call rotate dx , dy , a.angle( i ) * pi / 18 a.x( i ) = a.x( i ) + dx a.y( i ) = a.y( i ) + dy if a.x( i ) < 0 then a.x( i ) = winx - 60 if a.x( i ) > winx - 60 then a.x( i ) = 0 if a.y( i ) < 0 then a.y( i ) = winy - 60 if a.y( i ) > winy - 60 then a.y( i ) = 0 x = int( a.x( i ) ) y = int( a.y( i ) ) #m "spritexy animal_" ; i ; " " ; x ; " " ; y next i #m "drawsprites" wait function random.walk( i ) a.tel( i ) = a.tel( i ) - 1 if a.tel( i ) < 0 then a.tel( i ) = range( 5 , 18 ) a.state$( i ) = word$( state$ , int( range( 1 , 4 ) ) ) end if uit = 0 select case a.state$( i ) case "left" uit = 1 case "right" uit = -1 case else end select random.walk = uit end function function avoid.predator( i ) i.x = a.x( i ) i.y = a.y( i ) #m "spritexy? predator p.x p.y" hoek = atan2( p.x - i.x , p.y - i.y ) if hoek = 20 then exit function hoek = hoek * 18 / pi q = hoek - a.angle( i ) if q < 0 then q = q + 36 d = length( p.x - i.x , p.y - i.y ) + 1 if d < 130 then if q < 9 then uit = 10 / d end if if q > 27 then uit = -10 / d end if end if avoid.predator = uit end function function steer.random( i ) steer.random = range( -1 , 1 ) end function function steer.as.others( i ) i.a = a.angle( i ) uit = 0 for j = 0 to animalmax j.a = a.angle( j ) uit = uit + ( j.a - i.a ) mod 36 next j steer.as.others = uit / animalmax / 36 end function function steer.to.center( i ) i.x = a.x( i ) i.y = a.y( i ) swarm.x = 0 swarm.y = 0 for j = 0 to animalmax swarm.x = swarm.x + a.x( j ) swarm.y = swarm.y + a.y( j ) next j swarm.x = swarm.x / animalmax swarm.y = swarm.y / animalmax hoek = atan2( swarm.x - i.x , swarm.y - i.y ) if hoek = 20 then exit function hoek = hoek * 18 / pi i.a = a.angle( i ) q = hoek - i.a if q < 0 then q = q + 36 if q < 18 then uit = -2 else uit = 2 end if steer.to.center = uit end function function dont.hit.nabor( i ) i.x = a.x( i ) i.y = a.y( i ) for j = 0 to animalmax j.x = a.x( j ) j.y = a.y( j ) dist( j ) = length( i.x - j.x , i.y - j.y ) next j for high = 1 to animalmax for low = 0 to high - 1 if dist( ry( high ) ) < dist( ry( low ) ) then help = ry( high ) ry( high ) = ry( low ) ry( low ) = help end if next low next high b = a.angle( ry( 0 ) ) uit = 0 for j = 1 to 5 a = int2( animal.angle( ry( 0 ) , ry( j ) ) / pi * 36 ) if b < a then uit = uit - 1 / j end if if b > a then uit = uit + 1 / j end if next j dont.hit.nabor = uit end function function animal.angle( a1 , a2 ) angle = atan2( a.x( a2 ) - a.x( a1 ) _ , a.y( a2 ) - a.y( a1 ) ) end function function length( x , y ) length = sqr( x ^ 2 + y ^ 2 ) end function function range( low , high ) range = rnd(0) * ( high - low ) + low end function function int2( x ) if sign( x ) = -1 then x = x + 1 int2 = int( x ) end function function sign( x ) uit = 0 if x < 0 then uit = -1 if x > 0 then uit = 1 sign = uit end function sub rotate byref k , byref l , r s = sin( r ) c = cos( r ) hk = k * c - l * s hl = k * s + l * c k = hk l = hl end sub
function atan2( x , y ) if y = 0 then if x > 0 then angle = pi / 2 else if x < 0 then angle = 0 - pi / 2 else atan2 = 20 exit function end if end if end if if x < 0 then angle = atn( x / y ) + pi else angle = atn( x / y ) end if if angle < 0 - pi then angle = angle + pi * 2 end if if angle > pi then angle = angle - pi * 2 end if atan2 = angle end function
''bluatigro 23 apr 2017 ''sprite module
[sprite] global sprite.width , sprite.height return
sub sprite.clear w , h #m "fill white" #m "goto 0 " ; h #m "size 1" #m "down" #m "color black" #m "backcolor black" #m "boxfilled " ; w ; " " ; h * 2 #m "up" sprite.width = w sprite.height = h end sub
sub swap byref a , byref b h = a a = b b = h end sub
sub sprite.triangle x1 , y1 , x2 , y2 , x3 , y3 , clr$ if y1 = y2 then y1 = y1 - 1e-10 if y2 = y3 then y3 = y3 + 1e-10 if y1 > y3 then call swap y1 , y3 call swap x1 , x3 end if if y1 > y2 then call swap y1 , y2 call swap x1 , x2 end if if y2 > y3 then call swap y2 , y3 call swap x2 , y3 end if #m "size 1" for i = y1 to y3 a = x1 + ( x3 - x1 ) * (i-y1) / ( y3 - y1 ) if i < y2 then b = x1 + ( x2 - x1 ) * (i-y1) / ( y2 - y1 ) else b = x2 + ( x3 - x2 ) * (i-y2) / ( y3 - y2 ) end if #m "color black" #m "down" #m "line " ; a ; " " ; i _ ; " " ; b ; " " ; i #m "up" #m "color " ; clr$ #m "down" #m "line " ; a ; " " ; i + sprite.height _ ; " " ; b ; " " ; i + sprite.height #m "up"
next i #m "flush" end sub
sub sprite.rectangle x1,y1,x2,y2,clr$ #m "goto " ; x1 ; " " ; y1 #m "size 1" #m "color black" #m "backcolor black" #m "down" #m "boxfilled " ; x2 ; " " ; y2 #m "up" #m "goto " ; x1 ; " " ; y1 + sprite.height #m "color " ; clr$ #m "backcolor " ; clr$ #m "down" #m "boxfilled " ; x2 ; " " ; y2 + 60 #m "up" end sub
sub sprite.ellipse x,y,dx,dy,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "ellipsefilled " ; dx ; " " ; dy #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "ellipsefilled " ; dx ; " " ; dy #m "up" end sub
sub sprite.pie x,y,dx,dy,a,b,clr$,bclr$,size #m "goto " ; x ; " " ; y #m "size " ; size #m "down" #m "color black" #m "backcolor black" #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" #m "goto " ; x ; " " ; y + sprite.height #m "down" #m "color " ; clr$ #m "backcolor " ; bclr$ #m "piefilled " ; dx ; " " ; dy _ ; " " ; a ; " " ; b #m "up" end sub
sub sprite.line x1,y1 , x2,y2 , clr$ , size #m "color black" #m "size " ; size #m "down" #m "line " ; x1 ; " " ; y1 _ ; " " ; x2 ; " " ; y2 #m "up" #m "color " ; clr$ #m "down" #m "line " ; x1 ; " " ; y1 + sprite.height _ ; " " ; x2 ; " " ; y2 + sprite.height #m "up" end sub
sub sprite.getbmp bmp$ #m "getbmp " ; bmp$ ; " 0 0 " _ ; sprite.width ; " " ; sprite.height * 2 end sub
|
|
|
Post by B+ on Apr 26, 2018 15:33:04 GMT
Hmm... all the new code is crossed out?
I noticed a red critter, predator in previous code but no reactions by other critters which just flow over the screen one side to opposite, random wiggling.
Bluatigro, you might be having trouble getting angles correctly because the normal or standard way to use arc tan for two points is to use the y difference on top, the numerator, and the x difference below as the denominator. But depending how you set things up the opposite might work.
I would try a vastly simplified study of getting the angles between two circles and moving them closer or repelling each other before adding all the other complications. This is what I tried to demo with the arrows code.
|
|
|
Post by B+ on Apr 26, 2018 17:14:01 GMT
Here is Mouse school with left mouse clicking toggling predator/prey modes:
''Mouse school critter attract or repell.txt for JB 2.0 B+ 2018-04-26
'from: star mouse chaser.bas 01 - back to JB 'from: star mouse chaser.bas for SmallBASIC 0.12.0 2015-11-09 MGA/B+ 'from: code is based on code: mouse chaser by tsh73 'for the Just Basic contest, November 2008, I am 7 years late 'AND Combined with 'Arrow test.txt for Just Basic v1.01 [B+=MGA] 2017-05-09 ' Thanks to STxAxTIC at QB64 for method to separate particles ' Give critters constant radius
NoMainWin global xmax, ymax, pi, mx, my, predatorMode xmax = 1200 : ymax = 700 : pi = acs(-1)
WindowWidth = xmax + 8 WindowHeight = ymax + 32 UpperLeftX = 100 UpperLeftY = 40 Open "Mouse school - left click mouse to toggle mouse as predator / prey" For Graphics_nsb_nf As #g #g "trapclose quit" #g "setfocus" #g "when leftButtonUp lButtonUp" #g "when characterInput charIn" #g "when mouseMove move" #g "down" #g "fill blue" #g "color yellow"
na = 30 dim x(na), y(na), v(na), r(na) for i = 1 to na x(i) = rand(0, xmax) y(i) = rand(0, ymax) v(i) = rand(5, 20) r(i) = rand(5, 20) next predatorMode = 0 while 1 scan #g "cls" #g "fill blue" if predatorMode then #g "color brown" #g "backcolor darkred" else #g "color white" #g "backcolor green" end if #g "place ";mx;" ";my;"; circlefilled ";40 for i = 1 to na 'radian angle to mouse ra = atan2(my - y(i), mx - x(i)) ' + pi kind of interesting too 'draw it call critter x(i), y(i), ra, r(i)
'separate critters for next frame and further down i line FOR j = i + 1 TO na scan
' The following is STATIC's adjustment of ball positions if overlapping ' before calcultion of new positions from collision ' Displacement vector and its magnitude. Thanks STxAxTIC ! nx = x(j) - x(i) ny = y(j) - y(i) nm = SQR(nx ^ 2 + ny ^ 2) IF nm < 10 + r(i) + r(j) THEN nx = nx / nm ny = ny / nm
' Regardless of momentum exchange, separate the balls along the lone connecting them. WHILE nm < 10 + r(i) +r(j) scan flub = 10 ' massively increased for JB to speed up code
x(j) = x(j) + flub * nx y(j) = y(j) + flub * ny
x(i) = x(i) - flub * nx y(i) = y(i) - flub * ny
nx = x(j) - x(i) ny = y(j) - y(i) nm = SQR(nx ^ 2 + ny ^ 2) nx = nx / nm ny = ny / nm wend end if next if predatorMode then x(i) = x(i) + v(i) * cos(ra+pi) y(i) = y(i) + v(i) * sin(ra+pi) else x(i) = x(i) + v(i) * cos(ra) y(i) = y(i) + v(i) * sin(ra) end if next #g "flush" call pause 100 wend wait
'---------------- windows setup calls
sub quit H$ close #H$ end end sub
sub lButtonUp H$, mx, my 'must have handle and mouse x,y if predatorMode then predatorMode = 0 else predatorMode = 1 end sub
sub charIn H$, c$ call quit H$ end sub
sub move H$, MouseX, MouseY mx = MouseX my = MouseY end sub
'--------------- important subs for this program
sub critter x, y, ra, s #g "color black" #g "backcolor darkgreen" #g "place ";x;" ";y;"; circlefilled ";s if predatorMode then x1 = x + .75*s * cos(ra - pi/9 + pi) y1 = y + .75*s * sin(ra - pi/9 + pi) x2 = x + .75*s * cos(ra + pi/9 + pi) y2 = y + .75*s * sin(ra + pi/9 + pi) else x1 = x + .75*s * cos(ra - pi/9) y1 = y + .75*s * sin(ra - pi/9) x2 = x + .75*s * cos(ra + pi/9) y2 = y + .75*s * sin(ra + pi/9) end if #g "color white" #g "backcolor white" #g "place ";x1;" ";y1;"; circlefilled ";.25*s #g "place ";x2;" ";y2;"; circlefilled ";.25*s if predatorMode then x3 = x1 + .125 * s * cos(ra + pi) y3 = y1 + .125 * s * sin(ra + pi) x4 = x2 + .125 * s * cos(ra + pi) y4 = y2 + .125 * s * sin(ra + pi) else x3 = x1 + .125 * s * cos(ra) y3 = y1 + .125 * s * sin(ra) x4 = x2 + .125 * s * cos(ra) y4 = y2 + .125 * s * sin(ra) end if #g "color black" #g "backcolor black" #g "place ";x3;" ";y3;"; circlefilled ";.125*s #g "place ";x4;" ";y4;"; circlefilled ";.125*s end sub
sub arrow x0, y0, rAngle, distance x2 = x0 - .1 * distance * cos(rAngle - .25 * pi) y2 = y0 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - .1 * distance * cos(rAngle + .25 * pi) y2 = y0 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x0;" ";y0;" ";x2;" ";y2 x2 = x0 - distance * cos(rAngle) y2 = y0 - distance * sin(rAngle) #g "line ";x0;" ";y0;" ";x2;" ";y2 for i = .8 * distance to distance step 3 x1 = x0 - i * cos(rAngle) y1 = y0 - i * sin(rAngle) x2 = x1 - .1 * distance * cos(rAngle - .25 * pi) y2 = y1 - .1 * distance * sin(rAngle - .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 x2 = x1 - .1 * distance * cos(rAngle + .25 * pi) y2 = y1 - .1 * distance * sin(rAngle + .25 * pi) #g "line ";x1;" ";y1;" ";x2;" ";y2 next end sub
Function atan2(y,x) 'thanks Andy Amaya 'atan2 is a function which determines the angle between points 'x1, y1 and x2, y2. The angle returned is in radians 'The angle returned is always in the range of '-PI to PI radians (-180 to 180 degrees) '============================================================== 'NOTE the position of Y and X arguments 'This keeps atan2 function same as other language versions '============================================================== If x = 0 Then If y < 0 Then atan2 = -1.5707963267948967 Else atan2 = 1.5707963267948967 End If Else chk = atn(y/x) If x < 0 Then If y < 0 Then chk = chk - 3.1415926535897932 Else chk = chk + 3.1415926535897932 End If End If atan2 = chk End If End Function
'----------------- supplementary handy subs
sub pause mil 'tsh version has scan built-in t0 = time$("ms") while time$("ms") < t0 + mil : scan : wend end sub
function rand(lo, hi) rand = int((hi - lo + 1) * rnd(0)) + lo end function
|
|
|
Post by B+ on Apr 26, 2018 18:00:23 GMT
Oh hey! I decided to look up boid, thinking bluatigro might be trying for bird, I ran into this almost immediately: www.youtube.com/watch?v=GUkjC-69vawand the one right after too, (not any more) www.youtube.com/watch?v=QbUPfMXXQIYcool! Boid Rules (these can be turned on or off, so you get all kinds of variations of "behavior"): 1. Avoid barriers / obstacles 2. Head in same direction as your "radial" group 3. Head or Group towards "center of gravity" so to speak 4. Space out while grouping, don't get too close or overlap. I was using mouse position as centering / obstacle toggle. In video's I liked how they formed particular groups, not just one big one around mouse position.
|
|
|
Post by bluatigro on Apr 27, 2018 6:42:09 GMT
b+ : i m not trying to hunt the mouse but i m trying that the swarm steers itself it is looking like what i want
|
|
|
Post by B+ on Apr 27, 2018 16:01:19 GMT
Ha! Now that I've seen the videos, I know what I want which is probably closer to what you have in mind too!
I also want to see if I could work it out myself before looking for help.
I did do a thing with dots moving around randomly and drawing lines to each other if they were within a certain distance of each other. These connected points are the groupings I think that are needed for boid watching.
PS I called the snippets: Networking xxx, I made several versions. I will look into translating to JB.
|
|