Fish aquarium

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Fish aquarium

Post by neil »

Fish aquarium simulator. Let the fish avoid each other.

Code: Select all

' fish Aquarium by neil improvements by dodicat
' fish graphics by badidea and dodicat

Screenres 800,600,32,1
Randomize
Setmouse 0,0,0
Const W As Integer = 800   
Const H As Integer = 600

Type Fish
    X As Single              
    Y As Single              
    DX As Single             
    DY As Single             
    C As Ulong 
    r As Long=15
    m As Long=15*15
End Type

Dim Shared Fsh(1 To 25) As Fish
Dim Shared NumFish As Integer

Sub InitializeFish()
    NumFish = 25   ' Number of fish
    For i As Integer = 1 To NumFish
        Fsh(i).X = Rnd * W
        Fsh(i).Y = Rnd * H
        Fsh(i).DX = Rnd * 2 - 1
        Fsh(i).DY = Rnd * 2 - 1
        Fsh(i).C = Rgb(Rnd * 255, Rnd * 255, Rnd * 255)
    Next i
End Sub

Function DetectFishCollisions( B1 As Fish,B2 As Fish) As Single 'save some cpu if they are well seperated
    Dim As Long xdiff = B2.x-B1.x
    Dim As Long ydiff = B2.y-B1.y
    If Abs(xdiff) > (B2.r+B1.r) Then Return 0
    If Abs(ydiff) > (B2.r+B1.r) Then Return 0
    Var L=Sqr(xdiff*xdiff+ydiff*ydiff)
    If L<=(B2.r+B1.r) Then Function=L Else Function=0
End Function

Sub Check_FishCollisions(b() As Fish)
    For n1 As Long=Lbound(b) To Ubound(b)-1
        For n2 As Long=n1+1 To Ubound(b)
            Dim As Single  L= DetectFishCollisions(b(n1),b(n2))
            If L Then
                Dim As Single  impulsex=(b(n1).x-b(n2).x)
                Dim As Single  impulsey=(b(n1).y-b(n2).y)
                Dim As Single ln=Sqr(impulsex*impulsex+impulsey*impulsey)
                impulsex/=ln'normalize the impulse
                impulsey/=ln
                'set one Fish to nearest non overlap position
                b(n1).x=b(n2).x+(b(n2).r+b(n1).r)*impulsex
                b(n1).y=b(n2).y+(b(n2).r+b(n1).r)*impulsey
                
                Dim As Single  impactx=b(n1).dx-b(n2).dx
                Dim As Single  impacty=b(n1).dy-b(n2).dy
                Dim As Single  dot=impactx*impulsex+impacty*impulsey
                'handle mass
                Dim As Single  mn2=b(n1).m/(b(n1).m+b(n2).m),mn1=b(n2).m/(b(n1).m+b(n2).m)
                b(n1).dx-=dot*impulsex*2*mn1
                b(n1).dy-=dot*impulsey*2*mn1
                b(n2).dx+=dot*impulsex*2*mn2
                b(n2).dy+=dot*impulsey*2*mn2
                '=======  collisionds done =====
            End If
            
        Next n2
    Next n1
End Sub


Sub MoveFish()
    For i As Integer = 1 To NumFish
        Fsh(i).X = Fsh(i).X + Fsh(i).DX
        Fsh(i).Y = Fsh(i).Y + Fsh(i).DY
        If Fsh(i).x<20 Then fsh(i).x=20: Fsh(i).DX = -Fsh(i).DX
        If Fsh(i).x>w-20 Then Fsh(i).x=w-20:Fsh(i).DX = -Fsh(i).DX
        If Fsh(i).Y < 20 Then Fsh(i).Y=20: Fsh(i).DY = -Fsh(i).DY
        If Fsh(i).Y > H -20 Then Fsh(i).Y=H-20:Fsh(i).DY = -Fsh(i).DY
    Next i
End Sub

Sub DrawOneFish(i As Integer) ' i = fish index
    With Fsh(i)
        Circle(.X, .Y + 5), 12, .C, 3.1416 * 0.15, 3.1416 * 0.85
        Circle(.X, .Y - 5), 12, .C, 3.1416 * 1.15, 3.1416 * 1.85
        If int(.DX) > 0 Then
            Line(.X - 10, .Y)- Step(-10,+5), .C
            Line(.X - 10, .Y)- Step(-10,-5), .C
            Line(.X - 20, .Y - 5)- Step(0,+10), .C
        Elseif int(.DX) < 0 Then
            Line(.X + 10, .Y)- Step(+10,+5), .C
            Line(.X + 10, .Y)- Step(+10,-5), .C
            Line(.X + 20, .Y - 5)- Step(0,+10), .C
        Else
            'weird fish
            Circle(.X - 3, .Y - 1), 2, .C
            Circle(.X + 3, .Y - 1), 2, .C
        End If
    End With
End Sub

Function DrawAllFish() As Single
    Dim As Single e
    Screenlock
    Cls
    For i As Integer = 1 To NumFish
        e+=(Fsh(i).dx*Fsh(i).dx + Fsh(i).dy*Fsh(i).dy)
        DrawOneFish(i)
    Next i
    Screenunlock
    Return e
End Function

Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
    Static As Double timervalue,lastsleeptime,t3,frames
    Var t=Timer
    frames+=1
    If (t-t3)>=1 Then t3=t:fps=frames:frames=0
    Var sleeptime=lastsleeptime+((1/myfps)-T+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    lastsleeptime=sleeptime
    timervalue=T
    Return sleeptime
End Function


Sub Start()
    Dim As Long fps
    InitializeFish()
    Do
        MoveFish()
        Check_FishCollisions(fsh())
        Var ke= DrawAllFish()
        Windowtitle "Runaway check " & ke & ","& " fps= " & fps
        Sleep regulate (60,fps)
    Loop Until Inkey() <> ""
End Sub

Start
Last edited by neil on Jan 22, 2024 1:54, edited 4 times in total.
badidea
Posts: 2593
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Fish aquarium

Post by badidea »

Try this for DrawFish:

Code: Select all

Sub DrawFish()
   Screenlock
   Cls
   For i As Integer = 1 To NumFish
     'CirCle(Fsh(i).X, Fsh(i).Y), 10,Fsh(i).C
     CirCle(Fsh(i).X, Fsh(i).Y + 5), 12, Fsh(i).C, 3.1416 * 0.15, 3.1416 * 0.85
     CirCle(Fsh(i).X, Fsh(i).Y - 5), 12, Fsh(i).C, 3.1416 * 1.15, 3.1416 * 1.85
     line(Fsh(i).X - 10, Fsh(i).Y)- step(-10,+5), Fsh(i).C
     line(Fsh(i).X - 10, Fsh(i).Y)- step(-10,-5), Fsh(i).C
     line(Fsh(i).X - 20, Fsh(i).Y - 5)- step(0,+10), Fsh(i).C
   Next i
  Screenunlock
End Sub
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Fish aquarium

Post by neil »

@badidea
I tried your DrawFish. How could the code be changed so the fish can't swim backwards?
David Watson
Posts: 58
Joined: May 15, 2013 16:48
Location: England

Re: Fish aquarium

Post by David Watson »

Check out this aquarium:
https://itsfoss.com/asciiquarium/
BasicCoder2
Posts: 3909
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Fish aquarium

Post by BasicCoder2 »

neil wrote:
How could the code be changed so the fish can't swim backwards?
You need two drawings, one for a fish moving left and one for a fish moving right.

FreeBasic allows you to make use of bitmaps so you could use images.

Here is a program that creates two images, one with a fish looking right and one with a fish looking left.

Code: Select all

screenres 640,480,32  'required before creating a bitmap
color rgb(0,0,0),rgb(255,255,255)  'see black outline of fish against white

dim shared as any ptr fish1    'pointer to bitmap
fish1 = imagecreate(32,16)     'create a bitmap pointed to by fish1
dim shared as any ptr fish2    'pointer to bitmap
fish2 = imagecreate(32,16)     'create a bitmap pointed to by fish2

dim as integer datum

for j as integer = 0 to 15
    for i as integer = 0 to 31
        read datum
        if datum = 0 then
            pset fish1,(i,j),rgb(255,0,255)  'magenta
            pset fish2,(31-i,j),rgb(255,0,255)
        else
            pset fish1,(i,j),rgb(0,0,0)  'black
            pset fish2,(31-i,j),rgb(0,0,0)
        end if
    next i
next j

'give fish a color
paint fish1,(16,7),rgb(200,40,40),rgb(0,0,0)  'red color black outline

put (100,100),fish1,trans  'put image on screen at 100,100

'give fish a color
paint fish2,(16,7),rgb(120,140,240),rgb(0,0,0)  'blue color black outline

put (200,100),fish2,trans  'put image on screen at 200,100

sleep

bsave "fish1.bmp",fish1
bsave "fish2.bmp",fish2

        
data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0
data 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0
data 1,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0
data 1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0
data 1,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0
data 1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0
data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1
data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1
data 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1
data 1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0
data 1,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0
data 1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0
data 1,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0
data 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0
data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0
data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0
Here is a demo program that uses those images.

Code: Select all

screenres 640,480,32
color rgb(0,0,0),rgb(180,180,255) 'light blue background

dim shared as any ptr fish1,fish2
fish1 = imagecreate(32,16)
fish2 = imagecreate(32,16)
bload "fish1.bmp",fish1
bload "fish2.bmp",fish2

type FISH
    as integer x      'position of image
    as integer y
    as integer w      'width and height of image
    as integer h
    as integer xd     'change in x position
    as integer yd     'change in y position
    as any ptr image  'image of fish
end type

dim shared as FISH bob  'create a FISH type called bob

'intialize bob variables
bob.x = 0
bob.y = 240
bob.w = 32
bob.h = 16
bob.xd = 1
bob.yd = 0
bob.image = fish1


sub drawBob()
    screenlock
    cls
    put (bob.x,bob.y),bob.image,trans  'draw image of bob
    screenunlock
end sub

sub moveBob()
    bob.x = bob.x + bob.xd
    bob.y = bob.y + bob.yd
    
    if bob.x + bob.w = 639 then
        bob.xd = -bob.xd
        bob.image = fish2
    end if
    
    if bob.x = 0 then
        bob.xd = -bob.xd 
        bob.image = fish1
    end if
    
end sub
    

do
    drawBob()
    moveBob()
    sleep 2
loop until multikey(&H01)

neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Fish aquarium

Post by neil »

@BasicCoder2
Nice fish. Thank You!
Did you use a sprite editor?

After seeing your fish, I thought of a game idea. You're on a boat in the ocean, and you're searching for a sunken ship that has a ton of gold and silver. Your scuba diving and finally locate the sunken ship. and you're just starting to bring up the gold and silver bars to the boat. But now there are sharks you have to avoid, and there are also pirates to look out for. Also, do not run out of oxygen. It sounds simple, but I know how complicated and time-consuming game programming is.
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Fish aquarium

Post by neil »

@David Watson
Acsii aquarium nice.
Thanks!
badidea
Posts: 2593
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Fish aquarium

Post by badidea »

neil wrote: Jan 21, 2024 1:21 @badidea
I tried your DrawFish. How could the code be changed so the fish can't swim backwards?

Code: Select all

' fish aquarium by neil 
' fish graphics by badidea

ScreenRes 800,600,32,1
Randomize
Setmouse 0,0,0
Const W As Integer = 800   
Const H As Integer = 600

Type Fish
  X As Integer              
  Y As Integer              
  DX As Integer             
  DY As Integer             
  C As UInteger             
End Type

Dim Shared Fsh(100) As Fish
Dim Shared NumFish As Integer

Sub InitializeFish()
  NumFish = 25   ' Number of fish
  For i As Integer = 1 To NumFish
   Fsh(i).X = Rnd * W
   Fsh(i).Y = Rnd * H
   Fsh(i).DX = Rnd * 2 - 1
   Fsh(i).DY = Rnd * 2 - 1
   Fsh(i).C = RGB(Rnd * 255, Rnd * 255, Rnd * 255)
  Next i
End Sub

Sub MoveFish()
  For i As Integer = 1 To NumFish
   Fsh(i).X = Fsh(i).X + Fsh(i).DX
  Fsh(i).Y = Fsh(i).Y + Fsh(i).DY
   If Fsh(i).X < 0 Or Fsh(i).X > W Then
     Fsh(i).DX = -Fsh(i).DX
   End If
   If Fsh(i).Y < 0 Or Fsh(i).Y > H Then
     Fsh(i).DY = -Fsh(i).DY
   End If
  Next i
End Sub

Sub DrawOneFish(i as integer) ' i = fish index
  With Fsh(i)
    CirCle(.X, .Y + 5), 12, .C, 3.1416 * 0.15, 3.1416 * 0.85
    CirCle(.X, .Y - 5), 12, .C, 3.1416 * 1.15, 3.1416 * 1.85
    if .DX > 0 then
      line(.X - 10, .Y)- step(-10,+5), .C
      line(.X - 10, .Y)- step(-10,-5), .C
      line(.X - 20, .Y - 5)- step(0,+10), .C
    elseif .DX < 0 then
      line(.X + 10, .Y)- step(+10,+5), .C
      line(.X + 10, .Y)- step(+10,-5), .C
      line(.X + 20, .Y - 5)- step(0,+10), .C
    else
      'weird fish
      CirCle(.X - 3, .Y - 1), 2, .C
      CirCle(.X + 3, .Y - 1), 2, .C
    endif
  end with
End Sub

Sub DrawAllFish()
  Screenlock
  Cls
  For i As Integer = 1 To NumFish
    DrawOneFish(i)
  Next i
  Screenunlock
End Sub

Sub Start()
  InitializeFish()
  Do
    MoveFish()
    DrawAllFish()
    Sleep 10
  Loop Until Inkey() <> ""
End Sub

Start
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Fish aquarium

Post by dodicat »

Let the fish avoid each other.

Code: Select all

 ' fish aquarium by neil 
' fish graphics by badidea

Screenres 800,600,32,1
Randomize
Setmouse 0,0,0
Const W As Integer = 800   
Const H As Integer = 600

Type Fish
    X As Single              
    Y As Single              
    DX As Single             
    DY As Single             
    C As Ulong 
    r As Long=15
    m As Long=15*15
End Type

Dim Shared Fsh(1 To 25) As Fish
Dim Shared NumFish As Integer

Sub InitializeFish()
    NumFish = 25   ' Number of fish
    For i As Integer = 1 To NumFish
        Fsh(i).X = Rnd * W
        Fsh(i).Y = Rnd * H
        Fsh(i).DX = Rnd * 2 - 1
        Fsh(i).DY = Rnd * 2 - 1
        Fsh(i).C = Rgb(Rnd * 255, Rnd * 255, Rnd * 255)
    Next i
End Sub

Function DetectFishCollisions( B1 As Fish,B2 As Fish) As Single 'save some cpu if they are well seperated
    Dim As Long xdiff = B2.x-B1.x
    Dim As Long ydiff = B2.y-B1.y
    If Abs(xdiff) > (B2.r+B1.r) Then Return 0
    If Abs(ydiff) > (B2.r+B1.r) Then Return 0
    Var L=Sqr(xdiff*xdiff+ydiff*ydiff)
    If L<=(B2.r+B1.r) Then Function=L Else Function=0
End Function

Sub Check_FishCollisions(b() As Fish)
    For n1 As Long=Lbound(b) To Ubound(b)-1
        For n2 As Long=n1+1 To Ubound(b)
            Dim As Single  L= DetectFishCollisions(b(n1),b(n2))
            If L Then
                Dim As Single  impulsex=(b(n1).x-b(n2).x)
                Dim As Single  impulsey=(b(n1).y-b(n2).y)
                Dim As Single ln=Sqr(impulsex*impulsex+impulsey*impulsey)
                impulsex/=ln'normalize the impulse
                impulsey/=ln
                'set one Fish to nearest non overlap position
                b(n1).x=b(n2).x+(b(n2).r+b(n1).r)*impulsex
                b(n1).y=b(n2).y+(b(n2).r+b(n1).r)*impulsey
                
                Dim As Single  impactx=b(n1).dx-b(n2).dx
                Dim As Single  impacty=b(n1).dy-b(n2).dy
                Dim As Single  dot=impactx*impulsex+impacty*impulsey
                'handle mass
                Dim As Single  mn2=b(n1).m/(b(n1).m+b(n2).m),mn1=b(n2).m/(b(n1).m+b(n2).m)
                b(n1).dx-=dot*impulsex*2*mn1
                b(n1).dy-=dot*impulsey*2*mn1
                b(n2).dx+=dot*impulsex*2*mn2
                b(n2).dy+=dot*impulsey*2*mn2
                '=======  collisionds done =====
            End If
            
        Next n2
    Next n1
End Sub


Sub MoveFish()
    For i As Integer = 1 To NumFish
        Fsh(i).X = Fsh(i).X + Fsh(i).DX
        Fsh(i).Y = Fsh(i).Y + Fsh(i).DY
        If Fsh(i).x<20 Then fsh(i).x=20: Fsh(i).DX = -Fsh(i).DX
        If Fsh(i).x>w-20 Then Fsh(i).x=w-20:Fsh(i).DX = -Fsh(i).DX
        If Fsh(i).Y < 20 Then Fsh(i).Y=20: Fsh(i).DY = -Fsh(i).DY
        If Fsh(i).Y > H -20 Then Fsh(i).Y=H-20:Fsh(i).DY = -Fsh(i).DY
    Next i
End Sub

Sub DrawOneFish(i As Integer) ' i = fish index
    With Fsh(i)
        Circle(.X, .Y + 5), 12, .C, 3.1416 * 0.15, 3.1416 * 0.85
        Circle(.X, .Y - 5), 12, .C, 3.1416 * 1.15, 3.1416 * 1.85
        If int(.DX) > 0 Then
            Line(.X - 10, .Y)- Step(-10,+5), .C
            Line(.X - 10, .Y)- Step(-10,-5), .C
            Line(.X - 20, .Y - 5)- Step(0,+10), .C
        Elseif int(.DX) < 0 Then
            Line(.X + 10, .Y)- Step(+10,+5), .C
            Line(.X + 10, .Y)- Step(+10,-5), .C
            Line(.X + 20, .Y - 5)- Step(0,+10), .C
        Else
            'weird fish
            Circle(.X - 3, .Y - 1), 2, .C
            Circle(.X + 3, .Y - 1), 2, .C
        End If
    End With
End Sub

Function DrawAllFish() As Single
    Dim As Single e
    Screenlock
    Cls
    For i As Integer = 1 To NumFish
        e+=(Fsh(i).dx*Fsh(i).dx + Fsh(i).dy*Fsh(i).dy)
        DrawOneFish(i)
    Next i
    Screenunlock
    Return e
End Function

Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
    Static As Double timervalue,lastsleeptime,t3,frames
    Var t=Timer
    frames+=1
    If (t-t3)>=1 Then t3=t:fps=frames:frames=0
    Var sleeptime=lastsleeptime+((1/myfps)-T+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    lastsleeptime=sleeptime
    timervalue=T
    Return sleeptime
End Function


Sub Start()
    Dim As Long fps
    InitializeFish()
    Do
        MoveFish()
        Check_FishCollisions(fsh())
        Var ke= DrawAllFish()
        Windowtitle "Runaway check " & ke & ","& " fps= " & fps
        Sleep regulate (60,fps)
    Loop Until Inkey() <> ""
End Sub

Start   
Last edited by dodicat on Jan 21, 2024 18:44, edited 1 time in total.
badidea
Posts: 2593
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Fish aquarium

Post by badidea »

dodicat wrote: Jan 21, 2024 14:03 Let the fish avoid each other.
The fish go crazy after a while and then start to disappear until only 1 is left.
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Fish aquarium

Post by neil »

@badidea
On my PC, after a while, there were none left.
It kind of seems like a video game.
Maybe it should be called fish pong.
Good one, Dodicat.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Fish aquarium

Post by dodicat »

neil wrote: Jan 21, 2024 17:42 @badidea
On my PC, after a while, there were none left.
It kind of seems like a video game.
Maybe it should be called fish pong.
Good one, Dodicat.
We had fish runaway using integer in the fish fields.
They are happy now with a float
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Fish aquarium

Post by neil »

@dodicat
It's really cool what you did. This is a nice demo.

Nice float ><(((('> <'))))><
neil
Posts: 594
Joined: Mar 17, 2022 23:26

Re: Fish aquarium

Post by neil »

Update: I replaced my opening aquarium post with dodicat's improvements.
BasicCoder2
Posts: 3909
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Fish aquarium

Post by BasicCoder2 »

Sprites do have an advantage in that they look nice, animation is simpler and overlap is easier to implement.

Here is my take on using the graphic commands to draw the fish.
I have drawn the collision rectangle around each fish however this can be commented out.

Code: Select all

'some useful defines
Const Pi = 4 * Atn(1)
Dim Shared As Double TwoPi = 8 * Atn(1)
Dim Shared As Double RtoD = 180 / Pi   ' radians * RtoD = degrees
Dim Shared As Double DtoR = Pi / 180   ' degrees * DtoR = radians

const MAPW = 640
const MAPH = 480

screenres 640,480,32
color rgb(0,0,0),rgb(200,200,255):cls

type FISH
    as integer x
    as integer y
    as integer w  'rectangle dimensions
    as integer h
    as integer xd
    as integer yd
    as ulong   c
end type

const FishCount = 10
Dim Shared Fsh(FishCount) As FISH

function testCollision(b1 as FISH,b2 as FISH) as boolean
    return b2.y < b1.y+b1.h and b2.y+b2.h > b1.y and b2.x < b1.x+b1.w and b2.x+b2.w > b1.x
end function

'inialize fish
for i as integer = 0 to FishCount-1
    
    'random position
    fsh(i).x = int(rnd(1)* (MAPW-55))
    fsh(i).y = int(rnd(1)* (MAPH-27))
    fsh(i).h = 26
    fsh(i).w = 54
    
    'random direction
    fsh(i).xd = int(rnd(1)*3)-1
    fsh(i).yd = int(rnd(1)*3)-1
    
    'radom color
    fsh(i).c  = rgb(int(rnd(1)*256),int(rnd(1)*256),int(rnd(1)*256))
    
next i

'reposition any overlaps
dim as integer flag = 0
do
    flag = 0
    for i as integer = 0 to FishCount-1 'for each position
        for j as integer = i to FishCount-1 'compare with other positions
            if i<>j then  'don't compare with self
                if testCollision(fsh(i),fsh(j)) then 'collission
                    flag = 1  'collision flag
                    fsh(i).x = int(rnd(1)* (MAPW-14)) 'try new position
                    fsh(i).y = int(rnd(1)* (MAPH-34))
                end if
            end if
        next j
    next i
loop until flag = 0
    
            

sub drawFish(f as FISH)
    dim as integer xc,yc  'center of drawing
    if f.xd <= 0 then
        'center around which to draw fish
        xc = f.x + 21
        yc = f.y + 13
        Circle (xc,yc), 20,rgb(0,0,0),20*DtoR , 340*DtoR, .6
        line (xc+20,yc-5)-(xc+32,yc-11),rgb(0,0,0)
        line (xc+20,yc+5)-(xc+32,yc+11),rgb(0,0,0)
        line (xc+32,yc-11)-(xc+32,yc+11),rgb(0,0,0)
        circle (xc-10,yc-3),3,rgb(0,0,0),,,,f
        circle (xc-8,yc),10,rgb(0,0,0),300*DtoR,40*DtoR
        paint (xc,yc),f.c,rgb(0,0,0)
        line (f.x,f.y)-(f.x+54,f.y+26),rgb(255,255,0),b
        circle (xc,yc),1,rgb(0,0,0)
    else
        xc = f.x + 33
        yc = f.y + 13
        Circle (xc,yc), 20,rgb(0,0,0),200*DtoR , 160*DtoR, .6
        line (xc-20,yc-5)-(xc-32,yc-11),rgb(0,0,0)
        line (xc-20,yc+5)-(xc-32,yc+11),rgb(0,0,0)
        line (xc-32,yc-11)-(xc-32,yc+11),rgb(0,0,0)
        circle (xc+10,yc-3),3,rgb(0,0,0),,,,f
        circle (xc+8,yc),10,rgb(0,0,0),140*DtoR,240*DtoR
        paint (xc,yc),f.c,rgb(0,0,0)
        line (f.x,f.y)-(f.x+54,f.y+26),rgb(255,255,0),b
        circle (xc,yc),1,rgb(0,0,0)
     end if
end sub

sub drawAllFish()
    screenlock
    cls
    for i as integer = 0 to fishCount-1
        drawFish(fsh(i))
        draw string (fsh(i).x-3,fsh(i).y),str(i)
    next i
    screenunlock
end sub

sub moveFish()
    for i as integer = 0 to fishCount-1
        
        'random changes in direction at random times
        if int(rnd(1)*200)=5 then 'change direction
            'random direction
            fsh(i).xd = int(rnd(1)*3)-1
            fsh(i).yd = int(rnd(1)*3)-1
        end if
        
        'move fish
        fsh(i).x = fsh(i).x + fsh(i).xd
        fsh(i).y = fsh(i).y + fsh(i).yd
        
        'test for collisions
        for j as integer = 0 to fishCount-1
            if i<>j then
                
                if testCollision(fsh(i),fsh(j)) then
                    
                    'undo move
                    fsh(i).x = fsh(i).x - fsh(i).xd
                    fsh(i).y = fsh(i).y - fsh(i).yd
                    
                    'change direction
                    fsh(i).xd = -fsh(i).xd
                    fsh(i).yd = -fsh(i).yd
                   
                end if
            end if
        next j
        
        'hit borders
        if (fsh(i).x  <= 0) or (fsh(i).x + 58) >= MAPW then
            fsh(i).xd = -fsh(i).xd
        end if
        
        if (fsh(i).y  <= 0) or (fsh(i).y + 28) >= MAPH then
            fsh(i).yd = -fsh(i).yd
        end if

        
    next i
end sub


do
    drawAllFish()
    moveFish()
    sleep 20
loop until multikey(&H01)

Post Reply