def random_start(self, fish): #move a fish to a random position from off the screen this means it can swim on without anyone noticing if random.random() > 0.5: fish.pos = self.pos + V(self.dim.x + fish.size, 0) fish.pos.y = self.dim.y * random.random() else: fish.pos = self.pos - V(fish.size, 0) fish.pos.y = self.dim.y * random.random()
def intersection(self,a,b,c,d): a = V(a[0],a[1]) b = V(b[0],b[1]) c = V(c[0],c[1]) d = V(d[0],d[1]) cd = d-c ab = b-a u = (a.cross(ab)-c.cross(ab))/cd.cross(ab) l = (c.cross(cd)-a.cross(cd))/ab.cross(cd) if u>=0 and u<= 1 and l >= 0 and l <= 1: return (u * cd + c).get_p() else: return (0,1000)
def __init__(self, fsh, time, bounds): self.bounds = bounds #the bounds of the water it might fall into self.g = V(0, 120) #the gravity the fish will fall under self.time = time self.timel = 2 + random.random() #the length of the animation self.startt = 0 #the time the animation starts self.fsh = fsh #the fish that will be animated self.startp = V() #the start position and velocity self.startv = V() self.anim = False #is the fish currently being animated self.endscale = 0.5 #the size of the fish at the end of the animation self.moved = False #has the boat been moved self.movedt = 0 #the time when the boat has been moved
def seperation(self, fish, minDistance): if len(fish) < 1: return V() distance = 0 numClose = 0 distsum = V() for boid in fish: distance = (self.pos - boid.pos).length() if distance < minDistance and distance != 0: numClose += 1 distsum += (boid.pos - self.pos) / distance**2 if numClose == 0: return V() return (-distsum / numClose).normalize()
def sharkawarness(self, fish): #avoid the sharks it can see if len(fish) < 1: return V() distance = 0 numClose = 0 distsum = V() for boid in fish: distance = (self.pos - boid.pos).length() if distance < self.per * 2 and distance != 0 and isinstance( boid, Shark): numClose += 1 distsum += (boid.pos - self.pos) / distance**2 if numClose == 0: return V() return (-distsum / numClose).normalize()
def seperation(self, fish, minDistance): #avoid touching other fish if len(fish) < 1: # if there are no fish can't move away from them return V() count = 0 distsum = V() distance = 0 for boid in fish: #count each fish if they are close enough and aren't the original fish distance = (self.pos - boid.pos).length() if distance < minDistance and not self is boid and distance != 0: count += 1 distsum += (boid.pos - self.pos) / distance**2 #add the distance with more ephasis on fish that are closer if count == 0: #check for divide by zero error return V() return (-distsum / count).normalize() #move away from where the average is
def allign(self, fish): if len(fish) < 1: return V() #if there is no fish you can't align to them # calculate the average velocities of the other boids avg = V() #store the average velocity count = 0 #number of fish around for boid in fish: #count each fish if they are close enough and aren't the original fish if (boid.pos - self.pos).length() < self.per and not self is boid: count += 1 avg += boid.vel if count > 0: #check for divide by zero error avg /= count #take the mean #move our velocity towards the others return ( avg).normalize() #normalize it so only the direction matters else: return V()
def cohesion(self, fish): if len(fish) < 1: return V( ) #if there is no fish then you can't be attracted to them # calculate the average distances from the other boids com = V() count = 0 for boid in fish: #count each fish if they are close enough and arent the original fish if (boid.pos - self.pos).length() < self.per and not self is boid: com += (boid.pos - self.pos ) # add the vector to this new position count += 1 if count > 0 and com != V(): #check for divide by zero error com /= count #take the mean # move our velocity towards the centre of mass return com.normalize() #normalize it so only the direction matter else: return V()
def __init__(self, bounds, imgl, imgr, time, die): self.die = die #keep a reference of what to call when the fish dies e.g. its been caught self.bounds = bounds #what are the boundaries of the water self.max_vel = 75 #what is the max speed of the fish self.imgr = imgr #what images self.imgl = imgl self.time = time #keep track of the time self.size = 25 #what is the size of the fish self.scale = 1 #what is the scale of the fish image self.per = self.size * 3 #how far can the fish see self.fixed = False #is the position of the fish fixed self.pos = V(random.random() * bounds.dim.x + bounds.pos.x, random.random() * bounds.dim.y + bounds.pos.y) #set the position of the fish angle = random.random() * math.pi * 2 #angle the fish randomle self.vel = V( math.cos(angle), math.sin(angle) ) * 20 #set the velocity in the angle of the direction of the fish self.anim = Anim(self, time, bounds) #add the animation handler
def draw(self, canvas): #calculate the angle of the fish from the direction of the velocity a = self.vel.angle(V(0, 1)) if self.vel.x > 0: img = self.imgr #if moving right use the right image a = math.pi / 2 - a else: a -= math.pi / 2 img = self.imgl #if moving left use the left image img.pos = self.pos #set the image position to the fish position old = img.scale #set the scale of the image img.scale = old * self.scale img.draw(canvas, rotation=a) #draw the image img.scale = old
def repel( self, fish ): #repel fish from the top and bottom so they don't hit the boundary as much a = self.pos.y + fish.size b = self.pos.y + self.dim.y - fish.size r = (b - a) / 2 p = -(fish.pos.y - r - a) / r safe = 0.8 if abs(p) < safe: p = 0 else: if p > 0: p -= safe else: p += safe p *= 1 / (1 - safe) return V(0, p)
def __init__(self, count, dim, time, die): self.fish = [ ] # a list containing all the fish objects in this school of fish self.time = time # a time object to control when the fish are paused self.lastFrameTime = self.time.time() random.seed(time.time()) addr = os.getcwd() #the left and right sprite sheet of the fish to be shared across them to improve performance and fix transparency issue self.imgr = SS("file:///" + addr + "/images/right.png", (2, 2), time=400, scale=0.2, timehand=self.time) self.imgl = SS("file:///" + addr + "/images/left.png", (2, 2), time=400, scale=0.2, timehand=self.time) #create half of the fish that will be beneanth the sharks -- thanks dave cohen for this idea for i in range(int(count / 2)): self.fish.append( Fsh(Bounds(V(0, 0.325 * dim[1]), V(dim[0], dim[1] * 0.675)), self.imgl, self.imgr, time, die)) self.shrl = SS("file:///" + addr + "/images/Sharkleft.png", (5, 1), time=600, scale=1, timehand=self.time) # the shark sprite sheets self.shrr = SS("file:///" + addr + "/images/Sharkright.png", (5, 1), time=600, scale=1, timehand=self.time) #create sharks for i in range(1): self.fish.append( Shark(Bounds(V(0, 0.325 * dim[1]), V(dim[0], dim[1] * 0.675)), self.shrl, self.shrr, time, die)) #the rest of the fish for i in range(int(count / 2)): self.fish.append( Fsh(Bounds(V(0, 0.325 * dim[1]), V(dim[0], dim[1] * 0.675)), self.imgl, self.imgr, time, die)) t = threading.Thread(target=self.update, args=()) t.start()
def correct(self, fish): #correct the fishes position if it goes out of the bounds of the water. return V(self.cord(self.pos.x, self.pos.x + self.dim.x, fish), self.cora(self.pos.y, self.pos.y + self.dim.y, fish))