# Created by Leo from: C:\Python23\Tom\leo\boids.leo # << pyboids_main declarations >> #!/usr/bin/python -OO """This is a hack of, ---------------------------------------------------------------------------- MODULE: pyboids_main.py - Python boids!!! Flocking behavior fun! ---------------------------------------------------------------------------- This is the main function/module for pyboids. The display window is created here as well as the boids themselves. Within the BoidListObj class the boids follow a few simple rules (3 main ones and a couple not-so-neccessary ones). NOTE: This code is based on the pseudo-code by Conrad Parker found at: http://www.cse.unsw.edu.au/~conradp/boids/pseudocode.html His pseudo-code is based a famous algorithm by Craig Reynolds: http://www.red3d.com/cwr/boids/ URLs current as of 2001-03-26 Those URLs should give you a better understanding of what is going on. I don't want to completely rehash what they said. Also, I spent a LOT of time commenting this code, so it should be fairly easy to follow. NOTE: That is my biggest pet peeve with other code I have seen. NOT ENOUGH COMMENTS! So what if it doubles the size of your code, at least people can see what is going on! --- rant over --- ---------------------------------------------------------------------------- License: GPL: http://www.gnu.org/copyleft/gpl.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---------------------------------------------------------------------------- Created: 20000607 -taw: Todd Warner Updated: 20010406 -taw ---------------------------------------------------------------------------- """ from random import randint, gauss,choice,sample import threading import wx#,Image,image_view import wx.lib.mixins.listctrl as listmix import tarfile import wx.lib.evtmgr as EventManager from sys import exit, argv, path import os,time,math,copy,glob,string,StringIO # -- end -- << pyboids_main declarations >> # << pyboids_main methods >> (1 of 10) class taw_3DMath: # << taw_3DMath methods >> (1 of 13) def __init__(self): pass # << taw_3DMath methods >> (2 of 13) def flt2Int(self, f ): """ This function converts a float to an integer. It is done only at the remedial level. It looks at the tenth digit and rounds according to the, if 5+ then round up, else, round down. PRE: A float. POST: none. RET: A integer vector. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ x = int( f * 10 ) - int( f ) * 10 if x >= 5 or x <= -5: if x < 0: x = -1 else: x = 1 f = int( f + x ) return f # << taw_3DMath methods >> (3 of 13) def flt2IntVec(self, v ): """ This function converts a vector of floats to one of integers. It is done only at the remedial level. It looks at the tenth digit and rounds according to the, if 5+ then round up, else, round down. PRE: A float vector. POST: none. RET: A integer vector. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ for i in xrange( 3 ): # Could have used FltToInt here... did this for one less function call. x = int( v[i] * 10 ) - int( v[i] ) * 10 if x >= 5 or x <= -5: if x < 0: x = -1 else: x = 1 v[i] = int( v[i] + x ) return v # << taw_3DMath methods >> (4 of 13) def dist2Pts(self, p1, p2 ): """ This function will compute the distance between two points. PRE: p1 & p2 are points implemented as lists with three members (x, y, z). POST: none. RET: The distance as a FLOAT! -1.0 if error. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ if not p1 or not p2: return None #print type(p1) dx = p1[0] - p2[0] dy = p1[1] - p2[1] dz = p1[2] - p2[2] return math.sqrt( dx*dx + dy*dy + dz*dz ) # << taw_3DMath methods >> (5 of 13) # self.dist2PtsI( p1, p2 ) def maxRDist(self, v1, v2 ): """ The will compute the largest *RECTANGULAR* distance between two vectors. PRE: v1 & v2 are 3D vectors implemented as lists with three members (x, y, z). POST: none. RET: The max distance as a FLOAT! -1.0 if error. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ dx = math.fabs( v1[0] - v2[0] ) dy = math.fabs( v1[1] - v2[1] ) dz = math.fabs( v1[2] - v2[2] ) if dx < dy: m = dy else: m = dx if m < dz: m = dz return m # << taw_3DMath methods >> (6 of 13) # self.maxRDist( v1, v2 ) def limVec(self, v, lim ): """ This will take the largest component, see if smaller than lim. If so, then scale everything down to the factor of that multiple. I.e. making a vector with largest limit <= lim. PRE: A vector: v. A limiting value: lim. POST: none. RET: A vector with largest component vector <= lim. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ vl = copy.deepcopy( v ) try: m = math.fabs( v[0] ) if m < math.fabs( v[1] ): m = math.fabs( v[1] ) if m < math.fabs( v[2] ): m = math.fabs( v[2] ) except OverflowError, e: print e print "m:", m print "v:", v print "lim:", lim if m <= lim: return vl f = lim/m vl = self.scale( v, f ) return vl # << taw_3DMath methods >> (7 of 13) def addVec(self, v1, v2 ): """ Add two vectors together. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ #DEBUG: print v1, v2 v = [ v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2] ] return v # << taw_3DMath methods >> (8 of 13) def subVec(self, v1, v2 ): """ Subtract two vectors: v1 - v2. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ v = [ v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2] ] return v # << taw_3DMath methods >> (9 of 13) def dotProd(self, v1,v2 ): """ Calculate the dot product of two vectors. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] # << taw_3DMath methods >> (10 of 13) def calcMagnitude(self, v1 ): """ Calculate the magnitude of a vector. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ return math.sqrt( v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] ) # << taw_3DMath methods >> (11 of 13) def calcApproxAngle(self, v1, v2 ): """ DON'T USE THIS.... it is not finished. Calculate the approximate angle between two vectors. Created: 2000-06-07 -taw: Todd Warner Updated: 2001-03-21 -taw """ # Didn't use self.calcMagnitude in order to boost speed. v1Mag = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] v2Mag = v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2] v = self.dotProd( v1, v2 ) cosTheta = v / ( v1Mag * v2Mag ) angTable = [ 0, ## 0, 0.523598775, ## math.pi/6, 0.785398163, ## math.pi/4, 1.047197551, ## math.pi/3, 1.570796327, ## math.pi/2, 2.094395102, ## 2*math.pi/3, 2.35619449, ## 3*math.pi/4, 2.617993878, ## 5*math.pi/6, 3.141592654, ## math.pi, 4.71238898, ## 3*math.pi/2, 6.283185307 ## 2*math.pi ] index = -1 smallest = cosTheta for i in angTable: index = index +1 diff = math.fabs( cosTheta - i ) if diff < smallest: smallest = diff angTable = [ 0, ## 0, 30, ## math.pi/6, 45, ## math.pi/4, 60, ## math.pi/3, 90, ## math.pi/2, 120, ## 2*math.pi/3, 135, ## 3*math.pi/4, 150, ## 5*math.pi/6, 180, ## math.pi, 270, ## 3*math.pi/2, 360 ## 2*math.pi ] smallest = 0 return smallest # << taw_3DMath methods >> (12 of 13) def translate(self, p, tp ): """ This function will compute a translated point. NOTE: Same as AddVec(v1, v2) PRE: p = pt to translate. t = pt to translate with. POST: none. RET: A new, translated point. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ newP = [ p[0] + tp[0], p[1] + tp[1], p[2] + tp[2] ] return newP # << taw_3DMath methods >> (13 of 13) # self.translate( p, tp ): def scale(self, p, factor ): """ This function will compute a scale. PRE: p = pt to translate. factor = factor to scale by. POST: none. RET: A new, scaleed point. Created: 2000-06-07 -taw: Todd Warner Updated: 2000-06-07 -taw """ newP = [ p[0] * factor, p[1] * factor, p[2] * factor ] return newP # self.scale( p, tp ): # -- end -- << taw_3DMath methods >> # << pyboids_main methods >> (2 of 10) # My modules -taw class BoidFrame(wx.Frame): """ Initializes and displays GUI window environment. This simply displays the GUI environment where the flocks... flock. Only two windows function at the moment: the main "root" window which displays the canvas that the "birds" or whatnot fly in, and a second windows that just displays "about"-type information. Created: 20000613 -taw: Todd Warner Updated: 20000619 -taw """ # << class BoidFrame methods >> (1 of 24) def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title,wx.Point(0,0),wx.DefaultSize) dlg = wx.ProgressDialog("wxBoids Loading","Loading Lake",maximum = 210, parent=self, style = wx.PD_APP_MODAL) fishtar = tarfile.open('fish.tar','r:bz2') af = fishtar.extractfile('watter3.jpg') #nw = StringIO.StringIO(watter.read()) self.landbmp = wx.ImageFromStream(af) #self.landbmp = wx.Image('c:\\python23\\tom3\\watter3.jpg', wx.BITMAP_TYPE_JPEG) self.boberdebth = 640 self.snagflag = False self.watterrough =(-1,0,0,0,0,0,0,0,1)#(-2,-1,0,1,2) self.zdebth = 0.0 self.iscast = False self.reel = False self.boatbob = (0,0) self.rodfactor = 0 self.fishescaught = [] self.wormmetric = .25 self.rodflag = True self.linetension = 0 self.tmptms = 0 self.israining = False self.fishtyp= {0:'Bird',1:'Circle',2:'Bug',3:'Pink fish',4:'',5:'',6:'Goldfish',7:'None'} self.BoidList = [BoidListObj(5),BoidListObj(7,3,(0,1),(0,1)),BoidListObj(3,3,(0,1),(1,2,3,4,5)),BoidListObj(3,6),BoidListObj(5,3),BoidListObj(2,3),BoidListObj(2,1,(0,1,2,3,4)),BoidListObj(2,6,range(5))] wx.SafeYield() wx.SafeYield() maintimerID = wx.NewId() self.maintimer = wx.Timer(self, maintimerID) self.Bind(wx.EVT_TIMER, self.OnTimer) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.Bind(wx.EVT_PAINT, self.OnPaint) self.terrathing_sizer = wx.BoxSizer(wx.VERTICAL) self.lakepanel_sizer = wx.BoxSizer(wx.HORIZONTAL) self.terra_thing = wx.ScrolledWindow( self, -1, wx.Point(0, 0),wx.Size(640,480), style=wx.SUNKEN_BORDER) self.terrathing_sizer.Add(self.terra_thing, 0, wx.EXPAND) self.terra_thing.Bind(wx.EVT_MOTION, self.OnMouseMove) self.terra_thing.Bind(wx.EVT_RIGHT_UP, self.OnMouseLD) self.terra_thing.Bind(wx.EVT_LEFT_UP, self.OnMouseLU) self.terra_thing.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLdown) self.lakepanel = wx.Panel(self, -1) self.terrathing_sizer.Add(self.lakepanel, 0, wx.EXPAND) self.drag = wx.Slider(self.lakepanel,-1, 0, 0, 10, wx.Point(0, 0),wx.DefaultSize, wx.SL_HORIZONTAL ) self.dragvalue = 0 self.tension_gauge = wx.Gauge(self.lakepanel, -1, 10, wx.Point(0, 0),wx.DefaultSize, wx.GA_HORIZONTAL|wx.GA_SMOOTH ) self.tension_gauge.SetForegroundColour(wx.Color(0,0,150)) self.tension_gauge.SetValue(0) self.lakepanel_sizer.Add(self.tension_gauge, 2, wx.EXPAND) self.lakepanel_sizer.Add(self.drag, 2, wx.EXPAND) self.Bind(wx.EVT_SCROLL, self.SetTension(),self.drag) StartButtonID = wx.NewId() self.StartButton = wx.Button(self.lakepanel, StartButtonID, "Go", wx.Point(20, 20)) self.lakepanel_sizer.Add(self.StartButton , 1, wx.EXPAND) wx.EVT_BUTTON(self, StartButtonID, self.OnGoClick) self.StartButton.SetBackgroundColour(wx.BLUE) self.StartButton.SetForegroundColour(wx.WHITE) self.StartButton.SetDefault() StopButtonID = wx.NewId() self.StopButton = wx.Button(self.lakepanel, StopButtonID, "Stop", wx.Point(260, 20)) self.StopButton.SetBackgroundColour(wx.RED) self.StopButton.SetForegroundColour(wx.WHITE) self.lakepanel_sizer.Add(self.StopButton , 1, wx.EXPAND) wx.EVT_BUTTON(self, StopButtonID, self.OnStopClick) self.BoberButton = wx.Button(self.lakepanel, -1, "Bober") self.Bind(wx.EVT_BUTTON, self.BoberDebth, self.BoberButton) self.lakepanel_sizer.Add(self.BoberButton , 1, wx.EXPAND) self.lakepanel.SetSizer(self.lakepanel_sizer) self.lakepanel.SetAutoLayout(1) self.lakepanel_sizer.Fit(self.lakepanel) self.tackle_and_clock_sizer = wx.BoxSizer(wx.HORIZONTAL) self.main_sizer = wx.BoxSizer(wx.HORIZONTAL) self.button_sizer = wx.BoxSizer(wx.VERTICAL) self.text_sizer = wx.BoxSizer(wx.HORIZONTAL) self.fishlist = FishListCtrlPanel(self) self.bobermeter = wx.Window( self, -1, wx.Point(0, 0),wx.DefaultSize, style=wx.SUNKEN_BORDER) self.FishButton = wx.Button(self, -1, "Let Fish Go") self.Bind(wx.EVT_BUTTON, self.LetFishGo,self.FishButton) self.tackle_and_clock_sizer.Add(self.FishButton, 1, wx.EXPAND) self.tackle_and_clock_sizer.Add( self.bobermeter, 1, wx.EXPAND) self.text_sizer.Add(self.tackle_and_clock_sizer, 1, wx.EXPAND) self.button_sizer.Add(self.fishlist,15, wx.EXPAND) self.button_sizer.Add(self.text_sizer, 10, wx.EXPAND) self.main_sizer.Add(self.button_sizer, 10, wx.EXPAND) self.main_sizer.Add(self.terrathing_sizer, 16, wx.EXPAND) self.SetSizer(self.main_sizer) self.SetAutoLayout(1) self.main_sizer.Fit(self) dlg.Update(20, "Loading Pinkfish") self.lourback = wx.ImageFromStream(fishtar.extractfile('lourback.bmp') ) #self.lourback = wx.Image('c:\\python23\\tom3\\lourback.bmp', wx.BITMAP_TYPE_BMP) self.worm = wx.ImageFromStream(fishtar.extractfile('worm.bmp') ).ConvertToBitmap() #self.worm = wx.Image('c:\\python23\\tom3\\worm.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() wormM = wx.ImageFromStream(fishtar.extractfile('wormM.bmp') ).ConvertToBitmap() #wormM = wx.Image('c:\\python23\\tom3\\wormM.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() mask = wx.Mask(wormM, wx.BLACK) self.worm.SetMask(mask) self.BBass = wx.ImageFromStream(fishtar.extractfile('bassbig.bmp') ).ConvertToBitmap() #self.BBass = wx.Image('c:\\python23\\tom3\\bassbig.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() BBassM = wx.ImageFromStream(fishtar.extractfile('bassbigM.bmp') ).ConvertToBitmap() #BBassM = wx.Image('c:\\python23\\tom3\\bassbigM.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() mask = wx.Mask(BBassM, wx.BLACK) self.BBass.SetMask(mask) self.fish1 = wx.ImageFromStream(fishtar.extractfile('pinkfish1.jpg') ).ConvertToBitmap() #self.fish1 = wx.Image('c:\\python23\\tom3\\pinkfish1.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() self.fish1M = wx.ImageFromStream(fishtar.extractfile('pinkfish1M.gif') ).ConvertToBitmap() #self.fish1M = wx.Image('c:\\python23\\tom3\\pinkfish1M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish2M = wx.ImageFromStream(fishtar.extractfile('pinkfish2M.gif') ).ConvertToBitmap() #self.fish2M = wx.Image('c:\\python23\\tom3\\pinkfish2M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish3M = wx.ImageFromStream(fishtar.extractfile('pinkfish3M.gif') ).ConvertToBitmap() #self.fish3M = wx.Image('c:\\python23\\tom3\\pinkfish3M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish4M = wx.ImageFromStream(fishtar.extractfile('pinkfish4M.gif') ).ConvertToBitmap() #self.fish4M = wx.Image('c:\\python23\\tom3\\pinkfish4M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish5M = wx.ImageFromStream(fishtar.extractfile('pinkfish5M.gif') ).ConvertToBitmap() #self.fish5M = wx.Image('c:\\python23\\tom3\\pinkfish5M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish6M = wx.ImageFromStream(fishtar.extractfile('pinkfish6M.gif') ).ConvertToBitmap() #self.fish6M = wx.Image('c:\\python23\\tom3\\pinkfish6M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish7M = wx.ImageFromStream(fishtar.extractfile('pinkfish7M.gif') ).ConvertToBitmap() #self.fish7M = wx.Image('c:\\python23\\tom3\\pinkfish7M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish8M = wx.ImageFromStream(fishtar.extractfile('pinkfish8M.gif') ).ConvertToBitmap() #self.fish8M = wx.Image('c:\\python23\\tom3\\pinkfish8M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish9M = wx.ImageFromStream(fishtar.extractfile('pinkfish9M.gif') ).ConvertToBitmap() #self.fish9M = wx.Image('c:\\python23\\tom3\\pinkfish9M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() self.fish10M = wx.ImageFromStream(fishtar.extractfile('pinkfish10M.gif') ).ConvertToBitmap() #self.fish10M = wx.Image('c:\\python23\\tom3\\pinkfish10M.gif', wx.BITMAP_TYPE_GIF).ConvertToBitmap() mask = wx.Mask(self.fish1M, wx.BLACK) self.fish1.SetMask(mask) self.fish2 = wx.ImageFromStream(fishtar.extractfile('pinkfish2.jpg') ).ConvertToBitmap() #self.fish2 = wx.Image('c:\\python23\\tom3\\pinkfish2.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish2M, wx.BLACK) self.fish2.SetMask(mask) self.fish3 = wx.ImageFromStream(fishtar.extractfile('pinkfish3.jpg') ).ConvertToBitmap() #self.fish3 = wx.Image('c:\\python23\\tom3\\pinkfish3.jpg',wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish3M, wx.BLACK) self.fish3.SetMask(mask) self.fish4 = wx.ImageFromStream(fishtar.extractfile('pinkfish4.jpg') ).ConvertToBitmap() #self.fish4 = wx.Image('c:\\python23\\tom3\\pinkfish4.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish4M, wx.BLACK) self.fish4.SetMask(mask) self.fish5 = wx.ImageFromStream(fishtar.extractfile('pinkfish5.jpg') ).ConvertToBitmap() #self.fish5 = wx.Image('c:\\python23\\tom3\\pinkfish5.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish5M, wx.BLACK) self.fish5.SetMask(mask) self.fish6 = wx.ImageFromStream(fishtar.extractfile('pinkfish6.jpg') ).ConvertToBitmap() #self.fish6 = wx.Image('c:\\python23\\tom3\\pinkfish6.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish6M, wx.BLACK) self.fish6.SetMask(mask) self.fish7 = wx.ImageFromStream(fishtar.extractfile('pinkfish7.jpg') ).ConvertToBitmap() #self.fish7 = wx.Image('c:\\python23\\tom3\\pinkfish7.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish7M, wx.BLACK) self.fish7.SetMask(mask) self.fish8 = wx.ImageFromStream(fishtar.extractfile('pinkfish8.jpg') ).ConvertToBitmap() #self.fish8 = wx.Image('c:\\python23\\tom3\\pinkfish8.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish8M, wx.BLACK) self.fish8.SetMask(mask) self.fish9 = wx.ImageFromStream(fishtar.extractfile('pinkfish9.jpg') ).ConvertToBitmap() #self.fish9 = wx.Image('c:\\python23\\tom3\\pinkfish9.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish9M, wx.BLACK) self.fish9.SetMask(mask) self.fish10 = wx.ImageFromStream(fishtar.extractfile('pinkfish10.jpg') ).ConvertToBitmap() #self.fish10 = wx.Image('c:\\python23\\tom3\\pinkfish10.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() mask = wx.Mask(self.fish10M, wx.BLACK) self.fish10.SetMask(mask) dlg.Update(20, "Loading Boat and reel") self.boat = wx.ImageFromStream(fishtar.extractfile('boat.bmp') ).ConvertToBitmap() #self.boat = wx.Image('c:\\python23\\tom3\\boat.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() boatmask = wx.ImageFromStream(fishtar.extractfile('boatM.bmp') ).ConvertToBitmap() #boatmask = wx.Image('c:\\python23\\tom3\\boatM.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() mask = wx.Mask(boatmask, wx.BLACK) self.boat.SetMask(mask) self.Stipple = wx.ImageFromStream(fishtar.extractfile('watter1.jpg') ).ConvertToBitmap() #self.Stipple = wx.Image('c:\\python23\\tom3\\watter1.jpg', wx.BITMAP_TYPE_JPEG).ConvertToBitmap() self.rod = wx.ImageFromStream(fishtar.extractfile('reel1.bmp') ).ConvertToBitmap() #self.rod = wx.Image('c:\\python23\\tom3\\reel1.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() rodmask= wx.ImageFromStream(fishtar.extractfile('reel1M.bmp') ).ConvertToBitmap() #rodmask = wx.Image('c:\\python23\\tom3\\reel1M.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() mask = wx.Mask(rodmask, wx.BLACK) self.rod.SetMask(mask) self.rodbent = wx.ImageFromStream(fishtar.extractfile('reel1B.bmp') ).ConvertToBitmap() #self.rodbent = wx.Image('c:\\python23\\tom3\\reel1B.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() rodbentmask = wx.ImageFromStream(fishtar.extractfile('reel1BM.bmp') ).ConvertToBitmap() #rodbentmask = wx.Image('c:\\python23\\tom3\\reel1BM.bmp', wx.BITMAP_TYPE_BMP).ConvertToBitmap() mask = wx.Mask(rodbentmask, wx.BLACK) self.rodbent.SetMask(mask) self.tmpbmp = self.landbmp.ConvertToBitmap() self.rodddy = self.rod self.pinklist = {} dlg.Update(50, "Loading Goldfish") self.goldlist = {} dirlist = ['East','North','NorthEast','NorthWest','South','SouthEast','SouthWest','West'] mainlist = ['0goldie.bmp', '1goldie-0.bmp', '2goldie-1.bmp', '3goldie-2.bmp', '4goldie-3.bmp', '5goldie-4.bmp', '6goldie-5.bmp', '7goldie-6.bmp', '8goldie-7.bmp', '9goldie-8.bmp', '10goldie-9.bmp', '11goldie.bmp', '12goldie-0.bmp', '13goldie-1.bmp', '14goldie-2.bmp', '15goldie-3.bmp', '16goldie-4.bmp', '17goldie-5.bmp', '18goldie-6.bmp', '19goldie-7.bmp', '20goldie-8.bmp', '21goldie-9.bmp', '22goldie.bmp', '23goldie-0.bmp', '24goldie-1.bmp', '25goldie-2.bmp', '26goldie-3.bmp', '27goldie-4.bmp', '28goldie-5.bmp', '29goldie-6.bmp', '30goldie-7.bmp', '31goldie-8.bmp', '32goldie-9.bmp', '33goldie.bmp', '34goldie-0.bmp', '35goldie-1.bmp', '36goldie-2.bmp', '37goldie-3.bmp', '38goldie-4.bmp', '39goldie-5.bmp', '40goldie-6.bmp', '41goldie-7.bmp', '42goldie-8.bmp', '43goldie-9.bmp', '44goldie.bmp', '45goldie-0.bmp', '46goldie-1.bmp', '47goldie-2.bmp', '48goldie-3.bmp', '49goldie-4.bmp', '50goldie-5.bmp', '51goldie-6.bmp', '52goldie-7.bmp', '53goldie-8.bmp', '54goldie-9.bmp', '55goldie.bmp', '56goldie-0.bmp', '57goldie-1.bmp', '58goldie-2.bmp', '59goldie-3.bmp', '60goldie-4.bmp', '61goldie-5.bmp', '62goldie-6.bmp', '63goldie-7.bmp', '64goldie-8.bmp', '65goldie-9.bmp', '66goldie.bmp', '67goldie-0.bmp', '68goldie-1.bmp', '69goldie-2.bmp', '70goldie-3.bmp', '71goldie-4.bmp', '72goldie-5.bmp', '73goldie-6.bmp', '74goldie-7.bmp', '75goldie-8.bmp', '76goldie-9.bmp', '77goldie.bmp', '78goldie-0.bmp', '79goldie-1.bmp', '80goldie-2.bmp', '81goldie-3.bmp', '82goldie-4.bmp', '83goldie-5.bmp', '84goldie-6.bmp', '85goldie-7.bmp', '86goldie-8.bmp', '87goldie-9.bmp'] tmpdir = [] mainiter = iter(mainlist) for i in dirlist: for j in range(11): tmpdir.append(wx.ImageFromStream(fishtar.extractfile(mainiter.next())).ConvertToBitmap()) self.goldlist[i] = tmpdir dlg.Update(150, "Loading Goldfish") mainlist = ['0goldieM.bmp', '1goldieM-0.bmp', '2goldieM-1.bmp', '3goldieM-2.bmp', '4goldieM-3.bmp', '5goldieM-4.bmp', '6goldieM-5.bmp', '7goldieM-6.bmp', '8goldieM-7.bmp', '9goldieM-8.bmp', '10goldieM-9.bmp', '11goldieM.bmp', '12goldieM-0.bmp', '13goldieM-1.bmp', '14goldieM-2.bmp', '15goldieM-3.bmp', '16goldieM-4.bmp', '17goldieM-5.bmp', '18goldieM-6.bmp', '19goldieM-7.bmp', '20goldieM-8.bmp', '21goldieM-9.bmp', '22goldieM.bmp', '23goldieM-0.bmp', '24goldieM-1.bmp', '25goldieM-2.bmp', '26goldieM-3.bmp', '27goldieM-4.bmp', '28goldieM-5.bmp', '29goldieM-6.bmp', '30goldieM-7.bmp', '31goldieM-8.bmp', '32goldieM-9.bmp', '33goldieM.bmp', '34goldieM-0.bmp', '35goldieM-1.bmp', '36goldieM-2.bmp', '37goldieM-3.bmp', '38goldieM-4.bmp', '39goldieM-5.bmp', '40goldieM-6.bmp', '41goldieM-7.bmp', '42goldieM-8.bmp', '43goldieM-9.bmp', '44goldieM.bmp', '45goldieM-0.bmp', '46goldieM-1.bmp', '47goldieM-2.bmp', '48goldieM-3.bmp', '49goldieM-4.bmp', '50goldieM-5.bmp', '51goldieM-6.bmp', '52goldieM-7.bmp', '53goldieM-8.bmp', '54goldieM-9.bmp', '55goldieM.bmp', '56goldieM-0.bmp', '57goldieM-1.bmp', '58goldieM-2.bmp', '59goldieM-3.bmp', '60goldieM-4.bmp', '61goldieM-5.bmp', '62goldieM-6.bmp', '63goldieM-7.bmp', '64goldieM-8.bmp', '65goldieM-9.bmp', '66goldieM.bmp', '67goldieM-0.bmp', '68goldieM-1.bmp', '69goldieM-2.bmp', '70goldieM-3.bmp', '71goldieM-4.bmp', '72goldieM-5.bmp', '73goldieM-6.bmp', '74goldieM-7.bmp', '75goldieM-8.bmp', '76goldieM-9.bmp', '77goldieM.bmp', '78goldieM-0.bmp', '79goldieM-1.bmp', '80goldieM-2.bmp', '81goldieM-3.bmp', '82goldieM-4.bmp', '83goldieM-5.bmp', '84goldieM-6.bmp', '85goldieM-7.bmp', '86goldieM-8.bmp', '87goldieM-9.bmp'] tmpdir = [] mainiter = iter(mainlist) for i in dirlist: for j in range(11): mask = wx.Mask(wx.ImageFromStream(fishtar.extractfile(mainiter.next())).ConvertToBitmap(), wx.Color(0,0,0)) self.goldlist[i][j].SetMask(mask) wx.SafeYield() dlg.Update(150, "Finishing Up") #for i in mainlist: # globlist = glob.glob(i + '\\*') # globlist.sort() # globlist.insert(0,globlist[-1]) # del globlist[-1] # count = 0 # for j in globlist: # mask = wx.Mask(wx.Image(j, wx.BITMAP_TYPE_BMP).ConvertToBitmap(), wx.Color(0,0,0)) # self.goldlist[os.path.split(i)[1]][count].SetMask(mask) # count += 1 # wx.SafeYield() self.mousepos = [0,0] self.bobermeterSetRange(640) self.bobermeterSetValue(0) fishtar.close() dlg.Destroy() wx.SafeYield() # << class BoidFrame methods >> (2 of 24) def OnTimer(self, event): for i in self.BoidList: i.MoveAll() #pyimg = wx.ImageFromBitmap(self.BoidList.canvas) #self.BoidList.DrawAll() #dcimg = WXToPIL(pyimg) #self.terra_thing.set_image(dcimg) #win = self.terra_thing.get_image_window() if randint(0,5) == 3: self.SetWether() self.boatbob = (choice(self.watterrough),choice(self.watterrough)) dc = wx.ClientDC(self.terra_thing) self.terra_thing.PrepareDC(dc)# link with class dc.BeginDrawing()# draw to the DC self.DrawAll(dc) #dc.DrawBitmapPoint(self.BoidList.canvas,wx.Point( 0, 0), 0) dc.EndDrawing() del dc tmplist = [] if self.iscast: if self.rodflag: self.rodddy = self.rodbent self.rodfactor = 0 else: if not self.snagflag: if self.zdebth > 30: self.zdebth = self.zdebth - 30 else: if self.mousepos[1] <= 300: self.mousepos[1] = self.mousepos[1] + 30 self.setfeed(True) elif self.mousepos[1] > 359: self.mousepos[1] = self.mousepos[1] - 30 self.setfeed(True) elif self.mousepos[0] <= 229: self.mousepos[0] = self.mousepos[0] + 10 self.setfeed(True) elif self.mousepos[0] >= 269: self.mousepos[0] = self.mousepos[0] - 10 self.setfeed(True) else: self.iscast = False self.rodflag = True self.rodddy = self.rodbent self.rodddy = self.rod self.rodfactor = 2 self.Drawrod(self.mousepos) self.zdebth += 1.1 self.bobermeterSetValue(int(self.zdebth)) #self.display1.SetLabel(str(self.zdebth)) if self.zdebth >= self.BoidList[0].WORLD_DIM[2]: self.zdebth = self.BoidList[0].WORLD_DIM[2] elif self.zdebth >= self.boberdebth: self.zdebth = self.boberdebth count = -1 for i in self.BoidList: count += 1 i.foodlocal = (i.foodlocal[0],i.foodlocal[1],int(self.zdebth)) if i.snaglist != []: if tmplist == []: tmplist= [[i.snaglist,i.boidType,count],] self.snagflag = True i.fightlist = range(-int(i.snaglist[6]+2),int(i.snaglist[6]+2) + self.drag.GetValue()-1 + self.rodfactor ) #print i.fightlist self.linetension = int(i.snaglist[6]) + self.drag.GetValue() if i.snagdrag == False: tmplist = ['go',] i.snaglist = [] #print 'snagdrad drag',i.snagdrag,tmplist if tmplist != []: if self.snagflag == True: if tmplist[0] != 'go': if self.fishescaught == []: self.fishescaught.append(tmplist[0]) tmpinlist = False for i in self.fishescaught[:]: if i[0][4] == tmplist[0][0][4]: self.mousepos = [i[0][0][0]+15,i[0][0][1]+15] self.zdebth = i[0][0][2] tmpinlist = True break if not tmpinlist: self.fishescaught.append(tmplist[0]) self.snagflag = False self.setfeed(False) #for i in self.BoidList: # i.feed = False if tmplist[0] == 'go': tmplist = [] self.PopulateList() self.linetension = 0 self.rodddy = self.rod self.iscast = False self.zdebth = 0 self.tmptms = self.linetension self.linetension = abs(self.linetension + choice(self.watterrough)) self.SetTension() self.linetension = self.tmptms # << class BoidFrame methods >> (3 of 24) def OnPaint(self, event): dc = wx.PaintDC(self) self.PrepareDC(dc) dc.DrawBitmapPoint(self.tmpbmp, wx.Point(0,0), 0) # << class BoidFrame methods >> (4 of 24) def BoberDebth(self, event): self.maintimer.Stop() dlg = wx.TextEntryDialog(self, 'What is your new bobber debth?','Bobber', str(self.boberdebth/10)) dlg.SetValue( str(self.boberdebth/10)) if dlg.ShowModal() == wx.ID_OK: self.boberdebth = int(float(dlg.GetValue())*10) if self.boberdebth > 640: self.boberdebth = 640 elif self.boberdebth < 0: self.boberdebth = 0 self.bobermeterSetRange(self.boberdebth) wx.SafeYield() dlg.Destroy() self.maintimer.Start(100) # << class BoidFrame methods >> (5 of 24) def SetWether(self): self.watterrough = [-1,0,0,0,0,0,0,0,1] newrough =[] for i in range(-randint(0,4),randint(0,4)): for j in range(randint(1,3)): newrough.append(i) if newrough != []: self.watterrough = newrough if randint(0,10) == 7: self.israining = True else: self.israining = False # << class BoidFrame methods >> (6 of 24) def bobermeterSetValue(self,zdebth): y = int(self.wormmetric * zdebth) tmpbmp = self.lourback.ConvertToBitmap() dc = wx.ClientDC(self.bobermeter) self.bobermeter.PrepareDC(dc)# link with class bdc = wx.MemoryDC() fdc = wx.MemoryDC() fdc.SelectObject(tmpbmp) gotcha = False for i in self.BoidList: if i.snagdrag: gotcha = True if not gotcha: bdc.SelectObject(self.worm) fdc.BlitPointSize(wx.Point(45,y), wx.Size(23,40), bdc, wx.Point(0,0), wx.COPY, True) else: bdc.SelectObject(self.BBass) fdc.BlitPointSize(wx.Point(0,y), wx.Size(66,81), bdc, wx.Point(0,0), wx.COPY, True) del bdc del fdc dc.BeginDrawing()# draw to the DC dc.DrawBitmapPoint(tmpbmp, wx.Point(0,0), 0) pypen = wx.Pen(wx.Color(0,245,235),1) pypen.SetStipple(self.Stipple) dc.SetPen(pypen) #dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.DrawLinePoint(wx.Point(50,0),wx.Point(50,y)) dc.EndDrawing() # << class BoidFrame methods >> (7 of 24) def bobermeterSetRange(self,boberdebth): self.wormmetric = 160.0 / boberdebth # << class BoidFrame methods >> (8 of 24) def BoberDebthw(self, caller): caller.BoberDebth(None) # << class BoidFrame methods >> (9 of 24) def LetFishGo(self, event): self.maintimer.Stop() if self.fishlist.currentItem >= 0: count = -1 for i in self.fishescaught: count += 1 if i[0][4] == self.fishlist.getColumnText(self.fishlist.currentItem, 0): dlg = wx.TextEntryDialog(self, 'Do you want to rename this fish?','Bye Bye Fishy', i[0][4]) dlg.SetValue( i[0][4]) if dlg.ShowModal() == wx.ID_OK: i[0][4] = dlg.GetValue() i[0][0]=[299,392,1] self.BoidList[i[2]].theList.append(i[0]) del self.fishescaught[count] self.PopulateList() wx.SafeYield() dlg.Destroy() self.maintimer.Start(100) # << class BoidFrame methods >> (10 of 24) def LetFishGow(self,caller): caller.LetFishGo(None) # << class BoidFrame methods >> (11 of 24) def SetTension(self): dragdiff = self.drag.GetValue() - self.dragvalue self.linetension = self.linetension + dragdiff + self.rodfactor try: self.tension_gauge.SetForegroundColour(wx.Color(int(25.5 * self.linetension),0,150)) self.tension_gauge.SetValue(self.linetension) self.dragvalue = self.drag.GetValue() except OverflowError: i = self.fishescaught[-1] self.tmptms = 0 self.iscast = False self.rodflag = True self.rodddy = self.rodbent self.zdebth = 0 self.BoidList[i[2]].theList.append(i[0]) self.BoidList[i[2]].snagdrag = False self.BoidList[i[2]].feed = False self.BoidList[i[2]].snaglist = [] del self.fishescaught[-1] self.tension_gauge.SetForegroundColour(wx.Color(0,0,150)) self.tension_gauge.SetValue(0) self.dragvalue = self.drag.GetValue() # << class BoidFrame methods >> (12 of 24) def DrawAll(self,mdc): if self.israining: self.OnRain(mdc) self.tmpbmp = self.landbmp.ConvertToBitmap() bdc = wx.MemoryDC() fdc = wx.MemoryDC() fdc.SelectObject(self.tmpbmp) for i in self.BoidList: #mdc.SetPen(wx.Pen(wx.NamedColour('blue'), 1)) x1, y1, xr,yr,x2 ,y2 = 0,0,0,0,0,0 if i.boidType == 1: # if circles, change size... i.BOID_MAX_SIZE = i.BOID_MAX_SIZE/2 i.BOID_MIN_SIZE = i.BOID_MIN_SIZE/2 elif i.boidType == 2: # if dashes, change size... i.BOID_MAX_SIZE = 8 i.BOID_MIN_SIZE = 4 elif i.boidType == 3: # if dashes, change size... i.BOID_MAX_SIZE = 50 i.BOID_MIN_SIZE = 14 # If I shuffle the list, I get more natural flight patterns, BUT, # it is definitely a performance hit. i.theList = i.ShuffleList(i.theList) # **theList shuffle(opt) #mdc.BeginDrawing() for each in i.theList: if each[4] != 'hidden': #global BOID_MAX_SIZE,BOID_MIN_SIZE fact = (i.BOID_MAX_SIZE/2 - i.BOID_MIN_SIZE) * each[0][2]/i.WORLD_DIM[2] + i.BOID_MIN_SIZE/2 #self.display1.SetValue(int(fact)) #print 'factm each[0][2]',fact,each[0][2] if fact < 0: fact = 1 if i.boidType == 0: # lines - slowest, but coolest. flapPos = randint(0,3) # from random. x1 = y1 = xr = yr = 0 if flapPos == 0: # Down. xl = each[0][0] - fact yl = each[0][1] + fact xr = each[0][0] + fact yr = each[0][1] + fact elif flapPos == 1: # A little down. xl = each[0][0] - fact*2/3 yl = each[0][1] + fact/3 xr = each[0][0] + fact*2/3 yr = each[0][1] + fact/3 elif flapPos == 2: # UP # A little up. xl = each[0][0] - fact*2/3 yl = each[0][1] - fact/3 xr = each[0][0] + fact*2/3 yr = each[0][1] - fact/3 elif flapPos == 3: # UP. xl = each[0][0] - fact yl = each[0][1] - fact xr = each[0][0] + fact yr = each[0][1] - fact xc = each[0][0] yc = each[0][1] fdc.SetPen(wx.Pen(wx.NamedColour('WHITE'), 1)) fdc.DrawLinePoint(wx.Point(xl, yl), wx.Point(xc, yc)) fdc.DrawLinePoint(wx.Point(xc, yc), wx.Point( xr, yr)) each[2] = each[2] + 1 elif i.boidType == 1: xl = each[0][0] yl = each[0][1] fdc.SetPen(wx.Pen(wx.NamedColour('YELLOW'), 1)) fdc.DrawCirclePoint(wx.Point(xl, yl) , choice((1,2,3))) each[2] = each[2] + 1 elif i.boidType == 2: # dots / dashs -- speedy! x1 = each[0][0] - fact y1 = each[0][1] x2 = each[0][0] + fact y2 = each[0][1] dc.SetPen(wx.Pen(wx.NamedColour('BLACK'), 1)) fdc.DrawLinePoint(wx.Point(x1,y1), wx.Point(x2,y2)) each[2] = each[2] + 1 #bool BlitPointSize(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, wxDC* source, wxCoord xsrc, wxCoord ysrc, int logicalFunc = wxCOPY, bool useMask = false, wxCoord xsrcMask = -1, wxCoord ysrcMask = -1) elif i.boidType == 3: # Fish! x1 = each[0][0] y1 = each[0][1] h,w = 10,10 fact = int(fact) if fact-3 == 1: #fdc.DrawBitmapPoint(self.fish1, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish1) w,h = self.fish1.GetWidth(), self.fish1.GetHeight() elif fact-3 == 2: #fdc.DrawBitmapPoint(self.fish2, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish2) w,h = self.fish2.GetWidth(), self.fish2.GetHeight() elif fact-3 == 3: #fdc.DrawBitmapPoint(self.fish3, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish3) w,h = self.fish3.GetWidth(), self.fish3.GetHeight() elif fact-3 == 4: #fdc.DrawBitmapPoint(self.fish4, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish4) w,h = self.fish4.GetWidth(), self.fish4.GetHeight() elif fact-3 == 5: #fdc.DrawBitmapPoint(self.fish5, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish5) w,h = self.fish5.GetWidth(), self.fish5.GetHeight() elif fact-3 == 6: #fdc.DrawBitmapPoint(self.fish6, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish6) w,h = self.fish6.GetWidth(), self.fish6.GetHeight() elif fact-3 == 7: #fdc.DrawBitmapPoint(self.fish7,wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish7) w,h = self.fish7.GetWidth(), self.fish7.GetHeight() elif fact-3 == 8: #fdc.DrawBitmapPoint(self.fish8, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish8) w,h = self.fish8.GetWidth(), self.fish8.GetHeight() elif fact-3 == 9: #fdc.DrawBitmapPoint(self.fish9, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish9) w,h = self.fish9.GetWidth(), self.fish9.GetHeight() elif fact-3 == 10: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish10) w,h = self.fish10.GetWidth(), self.fish10.GetHeight() else: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.fish10) w,h = self.fish10.GetWidth(), self.fish10.GetHeight() fdc.BlitPointSize(wx.Point(x1,y1), wx.Size(w,h), bdc, wx.Point(0,0), wx.COPY, True) each[2] = each[2] + 1 #bool elif i.boidType == 4: # Bass Fish! x1 = each[0][0] y1 = each[0][1] #print int(fact) h,w = 10,10 fact = int(fact) if fact-3 == 1: #fdc.DrawBitmapPoint(self.fish1, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][0]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 2: #fdc.DrawBitmapPoint(self.fish2, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][1]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 3: #fdc.DrawBitmapPoint(self.fish3, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][2]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 4: #fdc.DrawBitmapPoint(self.fish4, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][3]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 5: #fdc.DrawBitmapPoint(self.fish5, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][4]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 6: #fdc.DrawBitmapPoint(self.fish6, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][5]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 7: #fdc.DrawBitmapPoint(self.fish7,wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][6]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 8: #fdc.DrawBitmapPoint(self.fish8, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][7]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 9: #fdc.DrawBitmapPoint(self.fish9, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][8]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() elif fact-3 == 10: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][9]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() else: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][10]) w,h = self.baslist[each[3]][0].GetWidth(), self.baslist[each[3]][0].GetHeight() fdc.BlitPointSize(wx.Point(x1,y1), wx.Size(w,h), bdc, wx.Point(0,0), wx.COPY, True) each[2] = each[2] + 1 #bool elif i.boidType == 5: # New pink Fish! x1 = each[0][0] y1 = each[0][1] #print int(fact) h,w = 10,10 fact = int(fact) if fact-3 == 1: #fdc.DrawBitmapPoint(self.fish1, wx.Point(x1,y1), 0)# bdc.SelectObject(self.pinklist[each[3]][0]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 2: #fdc.DrawBitmapPoint(self.fish2, wx.Point(x1,y1), 0)# bdc.SelectObject(self.pinklist[each[3]][1]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 3: #fdc.DrawBitmapPoint(self.fish3, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][2]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 4: #fdc.DrawBitmapPoint(self.fish4, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][3]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 5: #fdc.DrawBitmapPoint(self.fish5, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][4]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 6: #fdc.DrawBitmapPoint(self.fish6, wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][5]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 7: #fdc.DrawBitmapPoint(self.fish7,wx.Point(x1,y1), 0)# bdc.SelectObject(self.baslist[each[3]][6]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 8: #fdc.DrawBitmapPoint(self.fish8, wx.Point(x1,y1), 0)# bdc.SelectObject(self.pinklist[each[3]][7]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 9: #fdc.DrawBitmapPoint(self.fish9, wx.Point(x1,y1), 0)# bdc.SelectObject(self.pinklist[each[3]][8]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() elif fact-3 == 10: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.pinklist[each[3]][9]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() else: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.pinklist[each[3]][10]) w,h = self.pinklist[each[3]][0].GetWidth(), self.pinklist[each[3]][0].GetHeight() fdc.BlitPointSize(wx.Point(x1,y1), wx.Size(w,h), bdc, wx.Point(0,0), wx.COPY, True) each[2] = each[2] + 1 #bool elif i.boidType == 6: #Goldfish x1 = each[0][0] y1 = each[0][1] #print int(fact) h,w = 10,10 fact = int(fact) if fact-3 == 1: #fdc.DrawBitmapPoint(self.fish1, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][0]) w,h = self.goldlist[each[3]][0].GetWidth(), self.goldlist[each[3]][0].GetHeight() elif fact-3 == 2: #fdc.DrawBitmapPoint(self.fish2, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][1]) w,h = self.goldlist[each[3]][1].GetWidth(), self.goldlist[each[3]][1].GetHeight() elif fact-3 == 3: #fdc.DrawBitmapPoint(self.fish3, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][2]) w,h = self.goldlist[each[3]][2].GetWidth(), self.goldlist[each[3]][2].GetHeight() elif fact-3 == 4: #fdc.DrawBitmapPoint(self.fish4, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][3]) w,h = self.goldlist[each[3]][3].GetWidth(), self.goldlist[each[3]][3].GetHeight() elif fact-3 == 5: #fdc.DrawBitmapPoint(self.fish5, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][4]) w,h = self.goldlist[each[3]][4].GetWidth(), self.goldlist[each[3]][4].GetHeight() elif fact-3 == 6: #fdc.DrawBitmapPoint(self.fish6, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][5]) w,h = self.goldlist[each[3]][5].GetWidth(), self.goldlist[each[3]][5].GetHeight() elif fact-3 == 7: #fdc.DrawBitmapPoint(self.fish7,wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][6]) w,h = self.goldlist[each[3]][6].GetWidth(), self.goldlist[each[3]][6].GetHeight() elif fact-3 == 8: #fdc.DrawBitmapPoint(self.fish8, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][7]) w,h = self.goldlist[each[3]][7].GetWidth(), self.goldlist[each[3]][7].GetHeight() elif fact-3 == 9: #fdc.DrawBitmapPoint(self.fish9, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][8]) w,h = self.goldlist[each[3]][8].GetWidth(), self.goldlist[each[3]][8].GetHeight() elif fact-3 == 10: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][9]) w,h = self.goldlist[each[3]][9].GetWidth(), self.goldlist[each[3]][9].GetHeight() else: #fdc.DrawBitmapPoint(self.fish10, wx.Point(x1,y1), 0)# bdc.SelectObject(self.goldlist[each[3]][10]) w,h = self.goldlist[each[3]][10].GetWidth(), self.goldlist[each[3]][10].GetHeight() fdc.BlitPointSize(wx.Point(x1,y1), wx.Size(w,h), bdc, wx.Point(0,0), wx.COPY, True) each[2] = each[2] + 1 #bool bdc.SelectObject(self.boat) w,h = self.boat.GetWidth(), self.boat.GetHeight() fdc.BlitPointSize(wx.Point( 239+self.boatbob[0],372+self.boatbob[1]), wx.Size(w,h), bdc, wx.Point(0,0), wx.COPY, True) bdc.SelectObject(self.rodddy) w,h = self.rodddy.GetWidth(), self.rodddy.GetHeight() fdc.BlitPointSize(wx.Point(230+self.boatbob[0],322+self.boatbob[1]), wx.Size(w,h), bdc, wx.Point(0,0), wx.COPY, True) del bdc del fdc #mdc.DrawBitmapPoint(self.boat,wx.Point( 239,442), 0) #mdc.DrawBitmapPoint(self.rod,wx.Point(299,392), 0) mdc.DrawBitmapPoint(self.tmpbmp, wx.Point(0,0), 0) # << class BoidFrame methods >> (13 of 24) def OnGoClick(self, event): self.maintimer.Start(100) # << class BoidFrame methods >> (14 of 24) def OnStopClick(self, event): self.maintimer.Stop() # << class BoidFrame methods >> (15 of 24) def OnMouseMove(self, event): if not self.iscast: tmpm = event.GetLogicalPosition(wx.ClientDC(self.terra_thing)) self.mousepos = [tmpm[0],tmpm[1]] #print self.mousepos self.Drawrod(self.mousepos) # << class BoidFrame methods >> (16 of 24) def OnMouseLD(self, event): #print 'event righ up' self.iscast = False self.zdebth = 0 # << class BoidFrame methods >> (17 of 24) def setfeed(self, yummy): if yummy: for i in self.BoidList: i.feed = True i.foodlocal = (self.mousepos[0],self.mousepos[1],self.zdebth) else: for i in self.BoidList: i.feed = False # << class BoidFrame methods >> (18 of 24) def OnMouseLU(self, event): #print 'event left up' if not self.iscast: tmpm = event.GetLogicalPosition(wx.ClientDC(self.terra_thing)) self.mousepos = [tmpm[0],tmpm[1]] self.iscast = True self.setfeed(True) #for i in self.BoidList: # i.feed = True # i.foodlocal = (self.mousepos[0],self.mousepos[1],self.zdebth) else: self.rodflag = True # << class BoidFrame methods >> (19 of 24) def OnMouseLdown(self, event): if self.iscast: self.rodflag = False # << class BoidFrame methods >> (20 of 24) def Drawrod(self,pt): dc = wx.ClientDC(self.terra_thing) self.terra_thing.PrepareDC(dc)# link with class dc.BeginDrawing()# draw to the DC if self.iscast: pypen = wx.Pen(wx.Color(0,245,235),1) pypen.SetStipple(self.Stipple) dc.SetPen(pypen) dc.SetBrush(wx.TRANSPARENT_BRUSH) #dc.SetPen(wx.Pen(wx.Color(0,245,235),1)) dc.DrawLinePoint(wx.Point(249+self.boatbob[0],329+self.boatbob[1]),wx.Point(pt[0],pt[1])) rad = choice((2,3,4)) dc.DrawCirclePoint(wx.Point(pt[0],pt[1]), rad) dc.DrawCirclePoint(wx.Point(pt[0],pt[1]), rad *2) dc.DrawCirclePoint(wx.Point(pt[0],pt[1]), rad *3) else: dc.SetPen(wx.Pen('WHITE')) dc.DrawLinePoint(wx.Point(249+self.boatbob[0],329+self.boatbob[1]),wx.Point(pt[0],pt[1])) dc.EndDrawing() del dc # << class BoidFrame methods >> (21 of 24) def OnRain(self,dc): pt = [randint(0, 640), randint(0, 480)] pypen = wx.Pen(wx.Color(0,245,235),1) pypen.SetStipple(self.Stipple) dc.SetPen(pypen) dc.SetBrush(wx.TRANSPARENT_BRUSH) for i in range(randint(10,20)): rad = choice((2,3,4)) dc.DrawCirclePoint(wx.Point(pt[0],pt[1]), rad) dc.DrawCirclePoint(wx.Point(pt[0],pt[1]), rad *2) dc.DrawCirclePoint(wx.Point(pt[0],pt[1]), rad *3) # << class BoidFrame methods >> (22 of 24) def OnCloseWindow(self, event): self.maintimer.Stop() self.Destroy() # << class BoidFrame methods >> (23 of 24) def PopulateList(self): self.fishlist.list.ClearAll() self.fishlist.list.InsertColumn(0, 'Name') self.fishlist.list.InsertColumn(1,'Type' , wx.LIST_FORMAT_RIGHT) self.fishlist.list.InsertColumn(2, 'Weight') self.fishlist.list.SetColumnWidth(0, 50) self.fishlist.list.SetColumnWidth(1, 50) self.fishlist.list.SetColumnWidth(2, 50) for i in self.fishescaught: self.fishlist.list.InsertStringItem(0, i[0][4]) self.fishlist.list.SetStringItem( 0,1,self.fishtyp[i[1]]) self.fishlist.list.SetStringItem(0,2, str(i[0][6] + (abs(i[0][6] - time.time())/1000000000)) ) # << class BoidFrame methods >> (24 of 24) def PopulateListw(self,caller): caller.PopulateList() # -- end -- << class BoidFrame methods >> # << pyboids_main methods >> (3 of 10) class BoidListObj: """ This class defines a list of boids, what those boids are and the actions available to that boid/list. The static public variables are: boidType: 0, 1, 2, 3 (bird-like, circle, dash, square) s: The class semaphore object. canvas: The canvas that the boids are draw onto. The public methods are: __init__(self, n=None) DrawAll(self, initialYN=None) ScatterLogic(self) MoveAll(self) Rule1(self, b) Rule2(self, b) Rule3(self, b) LimitVelocity(self, b) BoundPosition(self, b) ShuffleList(self, l) Each member of the list is a boid with these attributes: [pt, vel, objNum]: A pt: [x, y, z] --- i.e., a position. A vel: [x, y, z] --- i.e., a vector. An objNum: ... --- a number generated by Tk. Each object is assigned a unique value to track on the canvas. Created: 20000607 -taw: Todd Warner Updated: 20010326 -taw """ # << class BoidListObj methods >> (1 of 12) def __init__(self, n = 1, boidtyp = 0, pfreq = (0,1),beha=(),thenamelist = None,theagelist = None,weightlist = None): self.beha = beha #range(11) for pause freguency self.pfreq = pfreq#range(11) for scatter freguency self.WORLD_DIM = [640, 480, 640] self.swimdir = 'West' self.snagdrag = False self.fightlist = (1,) self.edgemapflag = False #self.BIRDS = 0 # birdlike (lines) -- coolest but slowest #self.CIRCLES = 1 # faster #self.DASHS = 2 # bee-like -- fastest #self.SQUARES = 3 # NOT IMPLEMENTED YET # NEIGHBOR_THRESH -> closest to each other that they feel comfortable. # VELOCITY_LIM -> Max velocity of a boid. # Rule of thumb: NEIGHBOR_THRESH needs to be <= in comparison to VELOCITY_LIM. # I am not completely sure why, but, if not, flocking pattern # is not natural. self.NEIGHBOR_THRESH = 10 # -- toying with: int(WORLD_DIM[0]/10) self.VELOCITY_LIM = 10 # -- and int(NEIGHBOR_THRESH) self.EAT_THRESH = 25 self.feed = False self.snaglist = [] self.foodlocal = (0,0,0) # Current: roughly 8 to 50 pixels in width (Make sure divisible by 2): self.BOID_MAX_SIZE = 40 self.BOID_MIN_SIZE = 8 self.xMaxoffsetD = {} self.xMinoffsetD = {} self.yMaxoffsetD = {} self.yMinoffsetD = {} self.boidType= boidtyp self.coords = [] self.theList = [] # Timer used with tScatter/tTighten. # NOTE: from taw_time: Timer() #self.timer = Timer() # Probably should implement this as num. # of steps as opposed to real system # time. #self.waitTimer = Timer() # Used for sleepTimer here and there. # Occasionally the flock is scattered, and then regrouped. These two # variables store the values used to compute how much time, in seconds, # to do each. # tScatter: [time to run based on the other two parameters, # mean time (used for normal randomness) of performance, # standard deviation] # tTighten: [ ... ditto ... ] self.tScatter = [ 3.0, 3.0, 1.0] self.tTighten = [20.0, 20.0, 5.0] # Here you can turn on(1) and off(-1) the rules. # I use 1 and -1 instead of 1 and 0 'cuz it is nice to toggle using # just a [(previous value) * (-1)] switch. self.r1Tog = 1 self.r2Tog = 1 # Not implemented yet. self.r3Tog = 1 # Not implemented yet. if thenamelist: nitr = iter(thenamelist) else: nitr = None if theagelist: agitr = iter(theagelist) else: agitr = None if weightlist: wgitr = iter(weightlist) else: wgitr = None pt = [randint(0, self.WORLD_DIM[0]), randint(0, self.WORLD_DIM[1]), randint(0, self.WORLD_DIM[2])] #pt = [self.WORLD_DIM[0]/2,self.WORLD_DIM[1]/2,self.WORLD_DIM[2]/2] vel = [gauss(0.0, self.VELOCITY_LIM/2), # Initial velocity. gauss(0.0, self.VELOCITY_LIM/2), gauss(0.0, self.VELOCITY_LIM/2)] objNum = 0 # Object number (for Tkinter - we will save # a unique object number later on when drawing. nme = 'hidden' age = time.time() weight = float(randint(1,30))/10.0 self.theList.append([pt, vel, objNum,self.swimdir,nme,age,weight]) #pt = [self.WORLD_DIM[0]/2,self.WORLD_DIM[1]/2,self.WORLD_DIM[2]/2] pt = [randint(0, self.WORLD_DIM[0]), randint(0, self.WORLD_DIM[1]), randint(0, self.WORLD_DIM[2])] vel = [gauss(0.0, self.VELOCITY_LIM/2), # Initial velocity. gauss(0.0, self.VELOCITY_LIM/2), gauss(0.0, self.VELOCITY_LIM/2)] objNum = 0 nme = 'hidden' age = time.time() weight = float(randint(1,30))/10.0 self.theList.append([pt, vel, objNum,self.swimdir,nme,age,weight]) for i in xrange(n): pt = [self.WORLD_DIM[0]/2,self.WORLD_DIM[1]/2,self.WORLD_DIM[2]/2] #pt = [randint(0, self.WORLD_DIM[0]), # randint(0, self.WORLD_DIM[1]), # randint(0, self.WORLD_DIM[2])] vel = [gauss(0.0, self.VELOCITY_LIM/2), # Initial velocity. gauss(0.0, self.VELOCITY_LIM/2), gauss(0.0, self.VELOCITY_LIM/2)] objNum = 0 # Object number (for Tkinter - we will save # a unique object number later on when drawing. if nitr: name = nitr.next() else: name = string.capitalize(string.join(sample(string.ascii_lowercase,10),'')) if agitr: age = agitr.next() else: age = time.time() if agitr: weight = agitr.next() else: weight = float(randint(1,30))/10.0 self.theList.append([pt, vel, objNum,self.swimdir,name,age,weight]) # Append new boid on #self.DrawAll() # Do the initial draw. # << class BoidListObj methods >> (2 of 12) def DrawAll(self): #global BOID_MAX_SIZE,BOID_MIN_SIZE self.canvas = wx.EmptyBitmap(self.WORLD_DIM[0], self.WORLD_DIM[1]) mdc = wx.MemoryDC() mdc.SelectObject(self.canvas) mdc.Clear() mdc.SetPen(wx.Pen(wx.NamedColour('blue'), 1)) x1, y1, xr,yr,x2 ,y2 = 0,0,0,0,0,0 """ Method of class BoidListObj. This method will draw all boids on the list to the canvas. PRE: theList, and canvas are initialized. initialYN == True if drawing for the first time. POST: All boids on the list are drawn to the canvas. """ if self.boidType == 1: # if circles, change size... self.BOID_MAX_SIZE = self.BOID_MAX_SIZE/2 self.BOID_MIN_SIZE = self.BOID_MIN_SIZE/2 elif self.boidType == 2: # if dashes, change size... self.BOID_MAX_SIZE = 8 self.BOID_MIN_SIZE = 4 # If I shuffle the list, I get more natural flight patterns, BUT, # it is definitely a performance hit. self.theList = self.ShuffleList(self.theList) # **theList shuffle(opt) mdc.BeginDrawing() for each in self.theList: #global BOID_MAX_SIZE,BOID_MIN_SIZE fact = (self.BOID_MAX_SIZE/2 - self.BOID_MIN_SIZE) * each[0][2]/self.WORLD_DIM[2] + self.BOID_MIN_SIZE/2 if fact < 0: fact = 1 if self.boidType == 0: # lines - slowest, but coolest. flapPos = randint(0,3) # from random. x1 = y1 = xr = yr = 0 if flapPos == 0: # Down. xl = each[0][0] - fact yl = each[0][1] + fact xr = each[0][0] + fact yr = each[0][1] + fact elif flapPos == 1: # A little down. xl = each[0][0] - fact*2/3 yl = each[0][1] + fact/3 xr = each[0][0] + fact*2/3 yr = each[0][1] + fact/3 elif flapPos == 2: # UP # A little up. xl = each[0][0] - fact*2/3 yl = each[0][1] - fact/3 xr = each[0][0] + fact*2/3 yr = each[0][1] - fact/3 elif flapPos == 3: # UP. xl = each[0][0] - fact yl = each[0][1] - fact xr = each[0][0] + fact yr = each[0][1] - fact xc = each[0][0] yc = each[0][1] mdc.DrawLinePoint(wx.Point(xl, yl), wx.Point(xc, yc)) mdc.DrawLinePoint(wx.Point(xc, yc), wx.Point( xr, yr)) each[2] = each[2] + 1 elif self.boidType == 1: xul = each[0][0] - fact yul = each[0][1] - fact xlr = each[0][0] + fact ylr = each[0][1] + fact mdc.DrawCirclePoint(wx.Point(xul, yul) , int(abs(xul - yul)/2)) each[2] = each[2] + 1 elif self.boidType == 2: # dots / dashs -- speedy! x1 = each[0][0] - fact y1 = each[0][1] x2 = each[0][0] + fact y2 = each[0][1] mdc.DrawLinePoint(wx.Point(x1,y1), wx.Point(x2,y2)) each[2] = each[2] + 1 mdc.EndDrawing() del mdc # << class BoidListObj methods >> (3 of 12) def ScatterLogic(self): """ Method of class BoidListObj. This method simply toggles whether Rule1 (boids head to center of of group) is on or off (1 or -1 -- not 1 or 0). PRE: self.timer has been initialized. self.tScatter[X,X,X] & self.tTighten[X,X,X] have been initialized. POST: The timer is checked. If time, then self.r1Tog is toggled. RET: The toggle value. """ if self.tScatter[0] > 0 and self.tTighten[0] > 0: # NOTE: from random: gauss # Ok... we are meant to change things, so... if self.r1Tog == False: # scattering while self.tScatter[0] <= 0: #self.waitTimer.sleepTimer( 0.05 ) self.tScatter[0] = gauss(self.tScatter[1],self.tScatter[2]) #toggle = toggle * -1 #print "It's safe now.\tTightening the flock..." elif self.r1Tog == True: # tightening while self.tTighten[0] <= 0.0: #self.waitTimer.sleepTimer( 0.05 ) self.tTighten[0] = gauss(self.tTighten[1], self.tTighten[2]) #toggle = toggle * -1 #print "Predator shows up!\tScattering the flock..." #return toggle # << class BoidListObj methods >> (4 of 12) def Snagfish(self,bitelist): if bitelist == []: return if self.boidType < 3: return b = choice( bitelist) for each in range(len(self.theList)-1): if b == self.theList[each]: self.snaglist = self.theList[each] self.snagdrag = True # << class BoidListObj methods >> (5 of 12) def MoveAll(self): """ Method of class BoidListObj. This method moves all of the boids based on the 3 main rules and various other factors. Basically, all of the influencing vectors are added together and used as an offset to the original velocity vector. Finally the velocity is limited to something sensible. PRE: self.theList and boids are intialized. POST: o Rule 1 toggles on (1) or off (-1) dependent on timer. o Each boid given a new velocity vector and position. """ feedlist = [] #self.r1Tog = self.ScatterLogic() if randint(0,10) in self.pfreq: self.ScatterLogic() self.r1Tog = False else: self.ScatterLogic() self.r1Tog = True lsccnt = - 1 for each in self.theList: lsccnt += 1 # vCntBias (Rule1): head towards center of the flock. # vBckOff (Rule2): back off from crowding your neighbor. # vAvVBias (Rule3): try to fly the same speed as the others. # vBound: head back if near a wall. if self.snagdrag and self.snaglist == each: if not (int(each[0][0]) in (298,299,300) and int(each[0][1]) in (390,391,392) and int(each[0][2]) in (0,1,2)): if each[0][0] > 299: each[0][0] =each[0][0] - choice(self.fightlist) elif each[0][0] < 299: each[0][0] =each[0][0] + choice(self.fightlist) if each[0][1] > 392: each[0][1] =each[0][1] - choice(self.fightlist) elif each[0][1] < 392: each[0][1] =each[0][1] + choice(self.fightlist) if each[0][2] > 1: each[0][2] =each[0][2] - choice(self.fightlist) elif each[0][2] < 1: each[0][2] =each[0][2] + choice(self.fightlist) if self.r1Tog == True: r1Tog = 1 else: r1Tog = -1 vCntBias = DMath.scale(self.Rule1(each), float(r1Tog)) vBckOff = DMath.scale(self.Rule3(each), float(self.r3Tog)) if self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0: self.swimdir = 'East' elif self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0: self.swimdir = 'NorthEeast' elif self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0: self.swimdir = 'SouthWest' elif self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0: self.swimdir = 'South' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0: self.swimdir = 'North' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0: self.swimdir = 'NorthWest' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0: self.swimdir = 'SouthEast' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0: self.swimdir = 'West' each[3] = self.swimdir else: del self.theList[lsccnt] self.snagdrag = False break elif randint(0,10) in self.beha: pass else: # NOTE: from taw_3DMath: DMath.scale, DMath.translate if self.r1Tog == True: r1Tog = 1 else: r1Tog = -1 vCntBias = DMath.scale(self.Rule1(each), float(r1Tog)) vBckOff = DMath.scale(self.Rule3(each), float(self.r3Tog)) if self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0: self.swimdir = 'East' elif self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0: self.swimdir = 'NorthEeast' elif self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0: self.swimdir = 'SouthWest' elif self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0: self.swimdir = 'South' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]<0: self.swimdir = 'North' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0 and self.Rule3(each)[0]>=0: self.swimdir = 'NorthWest' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]<0: self.swimdir = 'SouthEast' elif self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0 and self.Rule3(each)[0]>=0: self.swimdir = 'West' each[3] = self.swimdir vAvVBias = DMath.scale(self.Rule2(each), float(self.r2Tog)) vBound = self.BoundPosition(each) each[1] = DMath.translate(each[1], vCntBias) each[1] = DMath.translate(each[1], vBckOff) each[1] = DMath.translate(each[1], vAvVBias) each[1] = DMath.translate(each[1], vBound) each[1] = self.LimitVelocity(each) # Don't fly too fast! each[0] = DMath.translate(each[1], each[0]) # add offset. if self.feed: self.Snagfish(self.Rule4(self.foodlocal)) # << class BoidListObj methods >> (6 of 12) def Rule1(self, b): # RULE #1: Shoot for the percieved center of the flock. """ Method of class BoidListObj. This method will average all of the positions of all of the boids not including the current boid. Then subtract this value from the position of the current boid to get the perceived center of the flock. Finally, a step-size is figured (a velocity towards the center). This is done with an arbitrary value for now. PRE: theList and boids are initialized. b: the current boid. RET: The velocity offset to head towards the center of the flock. """ # NOTE: from taw_3DMath: DMath.scale, DMath.translate, DMath.subVec pc = [0.0, 0.0, 0.0] for each in self.theList: if b != each: pc = DMath.translate(pc, each[0]) fact = float(len(self.theList)) - 1.0 fact = 1.0/fact pc = DMath.scale(pc, fact) pc = DMath.subVec(pc, b[0]) fact = 1.0/100.0 # Proportion pc = DMath.scale(pc, fact) return pc # ----- def BoidListObj.Rule1(self, b) # << class BoidListObj methods >> (7 of 12) def Rule2(self, b): # RULE #2: Don't get too close to your neighbor. """ Method of class BoidListObj. This method will determine if we are too close to anyone in particular. If we are then attempt to head in the exact opposite direction. PRE: self.theList and boids are initialized. b: the current boid. RET: If too close, a vector in the opposite direction, or a zerovector. """ c = [0.0, 0.0, 0.0] # NOTE: from taw_3DMath: DMath.subVec, DMath.calcMagnitude for each in self.theList: if b != each: diffPos = DMath.subVec(b[0], each[0]) dist = DMath.calcMagnitude(diffPos) if dist < self.NEIGHBOR_THRESH: c = DMath.subVec(c, diffPos) return c # << class BoidListObj methods >> (8 of 12) def Rule3(self, b): # RULE #3: Try to match velocities: """ Method of class BoidListObj. This method has the current boid (b) attempt to match the velocity of the average of the rest of the flock. PRE: self.theList and boids are initialized. b: the current boid. RET: The perceived velocity of the flock DMath.scaled to an arbitrary step-size (1/8th in this case). """ pv = [0.0, 0.0, 0.0] # NOTE: from taw_3DMath: DMath.scale, DMath.translate, DMath.subVec for each in self.theList: if b != each: pv = DMath.translate(pv, each[1]) fact = float(len(self.theList)) - 1.0 fact = 1.0/fact pv = DMath.scale(pv, fact) # velocities are averaged. fact = 1.0/8.0 pv = DMath.subVec(pv, b[1]) # The difference is found # between the current and ave. pv = DMath.scale(pv, fact) # The velocity used is 1/8th # of that factor. return pv # << class BoidListObj methods >> (9 of 12) def Rule4(self, pt): # RULE #2: Don't get too close to your neighbor. """ Method of class BoidListObj. This method will determine if food is close to anyone in particular. PRE: self.theList and boids are initialized. pt: food point """ bitelist = [] for each in self.theList: if each[4] != 'hidden': diffPos = DMath.subVec(pt, each[0]) dist = DMath.calcMagnitude(diffPos) if dist < self.EAT_THRESH: bitelist.append(each) return bitelist # << class BoidListObj methods >> (10 of 12) def LimitVelocity(self, b): """ Method of class BoidListObj. This (commented out region) is the method done in his pseudocode. The one used in practice is from his actual code. I had the problem of boids getting in a straight line with this original block of code. PRE: self.theList and boids initialized. b: the current boid. RET: A more limited velocity if moving a bit too fast. """ ##mag = taw_3DMath.DMath.calcMagnitude(b[1]) ##if mag > VELOCITY_LIM: ## mag = VELOCITY_LIM/mag ## return taw_3DMath.DMath.scale(b[1], mag) ##return b[1] # His method used in his program - Probably used for performance. # NOTE: from taw_3DMath: DMath.limVec return DMath.limVec(b[1], self.VELOCITY_LIM) # << class BoidListObj methods >> (11 of 12) def BoundPosition(self, b): """ Method of class BoidListObj. This function will get a boid to turn a bit upon hitting one of the "walls" of the world's dimensions. PRE: A boids current velocity vector. RET: A vector to influence the boid to fly in a new direction. """ x = int(b[0][0]) y = int(b[0][1]) z = int(b[0][2]) if self.edgemapflag: xMin = self.xMinoffsetD[y] #print self.xMinoffsetD[y] xMax = self.WORLD_DIM[0] - self.xMaxoffsetD[y] yMin = self.yMinoffsetD[x] yMax = self.WORLD_DIM[1] - self.yMaxoffsetD[x] zMin = 5.0 zMax = self.WORLD_DIM[2] - 5.0 else: offset = -5.0 # Make nonzero of want the boids to begin turn at pt # before/after one of the walls. xMin = 0.0 - offset xMax = self.WORLD_DIM[0] + offset yMin = 0.0 - offset yMax = self.WORLD_DIM[1] + offset zMin = 0.0 - offset zMax = self.WORLD_DIM[2] + offset v = [0.0, 0.0, 0.0] #factor = 50 - velocityLim # I am not sure why I did this. factor = 0 #if factor < 0: # factor = 5 if x < xMin - factor: v[0] = 10.0 elif x > xMax + factor: v[0] = -10.0 if y < yMin - factor: v[1] = 10.0 elif y > yMax + factor: v[1] = -10.0 if z < zMin - factor: v[2] = 10.0 elif z > zMax + factor: v[2] = -10.0 return v # << class BoidListObj methods >> (12 of 12) def ShuffleList(self, l): l2 = [] while l != []: i = randint(0, len(l)-1) l2.append(l.pop(i)) l = l2 return l # -- end -- << class BoidListObj methods >> """ Method of class BoidListObj. This function will randomly shuffle any list. I used this to simulate picking (without replacement) any boid from the "bag" of boids. PRE: Any list (the list of boids). POST: The list is randomly reordered. RET: The new list. """ # NOTE: from random: randint # << pyboids_main methods >> (4 of 10) class FishListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): # << class FishListCtrl methods >> def __init__(self, parent, ID, pos=wx.DefaultPosition,size=wx.DefaultSize, style=0): wx.ListCtrl.__init__(self, parent, ID, pos, size, style) listmix.ListCtrlAutoWidthMixin.__init__(self) # -- end -- << class FishListCtrl methods >> # << pyboids_main methods >> (5 of 10) class FishListCtrlPanel(wx.Panel, listmix.ColumnSorterMixin): # << class FishListCtrlPanel methods >> (1 of 22) def __init__(self, parent): wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS) self.parent = parent tID = wx.NewId() self.currentItem = None #self.il = wx.ImageList(16, 16) #self.idx1 = self.il.Add(images.getSmilesBitmap()) #self.sm_up = self.il.Add(images.getSmallUpArrowBitmap()) #self.sm_dn = self.il.Add(images.getSmallDnArrowBitmap()) self.list = FishListCtrl(self, tID, style=wx.LC_REPORT | wx.SUNKEN_BORDER| wx.LC_EDIT_LABELS) #| wxLC_NO_HEADER | wxLC_VRULES | wxLC_HRULES ) #self.list.SetImageList(self.il, wx.IMAGE_LIST_SMALL) #self.PopulateList() self.list.InsertColumn(0,'Name' ) self.list.InsertColumn(1, 'Type', wx.LIST_FORMAT_RIGHT) self.list.InsertColumn(2, 'Weight') self.list.SetColumnWidth(0, 50) self.list.SetColumnWidth(1, 50) self.list.SetColumnWidth(2, 50) # Now that the list exists we can init the other base class, # see wxPython/lib/mixins/listctrl.py #self.itemDataMap = musicdata self.itemDataMap = {} listmix.ColumnSorterMixin.__init__(self, 3) #self.SortListItems(0, True) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list) self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected, self.list) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, self.list) self.Bind(wx.EVT_LIST_DELETE_ITEM, self.OnItemDelete, self.list) self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list) self.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnColRightClick, self.list) self.Bind(wx.EVT_LIST_COL_BEGIN_DRAG, self.OnColBeginDrag, self.list) self.Bind(wx.EVT_LIST_COL_DRAGGING, self.OnColDragging, self.list) self.Bind(wx.EVT_LIST_COL_END_DRAG, self.OnColEndDrag, self.list) self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginEdit, self.list) self.list.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick) self.list.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) # for wxMSW self.list.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightClick) # for wxGTK self.list.Bind(wx.EVT_RIGHT_UP, self.OnRightClick) # << class FishListCtrlPanel methods >> (2 of 22) def GetListCtrl(self): return self.list # << class FishListCtrlPanel methods >> (3 of 22) def GetSortImages(self): #return (self.sm_dn, self.sm_up) pass # << class FishListCtrlPanel methods >> (4 of 22) def OnRightDown(self, event): self.x = event.GetX() self.y = event.GetY() #self.log.WriteText("x, y = %s\n" % str((self.x, self.y))) item, flags = self.list.HitTest((self.x, self.y)) if flags & wx.LIST_HITTEST_ONITEM: self.list.Select(item) event.Skip() # << class FishListCtrlPanel methods >> (5 of 22) def getColumnText(self, index, col): item = self.list.GetItem(index, col) return item.GetText() # << class FishListCtrlPanel methods >> (6 of 22) def OnItemSelected(self, event): ##print event.GetItem().GetTextColour() self.currentItem = event.m_itemIndex event.Skip() # << class FishListCtrlPanel methods >> (7 of 22) def OnItemDeselected(self, evt): pass # << class FishListCtrlPanel methods >> (8 of 22) def OnItemActivated(self, event): self.currentItem = event.m_itemIndex event.Skip() # << class FishListCtrlPanel methods >> (9 of 22) def OnBeginEdit(self, event): #self.log.WriteText("OnBeginEdit") event.Allow() # << class FishListCtrlPanel methods >> (10 of 22) def OnItemDelete(self, event): #self.log.WriteText("OnItemDelete\n") pass # << class FishListCtrlPanel methods >> (11 of 22) def OnColClick(self, event): #self.log.WriteText("OnColClick: %d\n" % event.GetColumn()) event.Skip() # << class FishListCtrlPanel methods >> (12 of 22) def OnColRightClick(self, event): item = self.list.GetColumn(event.GetColumn()) #self.log.WriteText("OnColRightClick: %d %s\n" %(event.GetColumn(), (item.GetText(), item.GetAlign(), item.GetWidth(), item.GetImage()))) # << class FishListCtrlPanel methods >> (13 of 22) def OnColBeginDrag(self, event): #self.log.WriteText("OnColBeginDrag\n") pass ## Show how to not allow a column to be resized #if event.GetColumn() == 0: # event.Veto() # << class FishListCtrlPanel methods >> (14 of 22) def OnColDragging(self, event): #self.log.WriteText("OnColDragging\n") pass # << class FishListCtrlPanel methods >> (15 of 22) def OnColEndDrag(self, event): #self.log.WriteText("OnColEndDrag\n") pass # << class FishListCtrlPanel methods >> (16 of 22) def OnDoubleClick(self, event): #self.log.WriteText("OnDoubleClick item %s\n" % self.list.GetItemText(self.currentItem)) event.Skip() # << class FishListCtrlPanel methods >> (17 of 22) def OnRightClick(self, event): #self.log.WriteText("OnRightClick %s\n" % self.list.GetItemText(self.currentItem)) # only do this part the first time so the events are only bound once if not hasattr(self, "popupID1"): self.popupID1 = wx.NewId() self.popupID2 = wx.NewId() self.popupID3 = wx.NewId() self.popupID4 = wx.NewId() self.Bind(wx.EVT_MENU, self.OnPopupOne, id=self.popupID1) self.Bind(wx.EVT_MENU, self.OnPopupTwo, id=self.popupID2) self.Bind(wx.EVT_MENU, self.OnPopupThree, id=self.popupID3) self.Bind(wx.EVT_MENU, self.OnPopupFour, id=self.popupID4) # make a menu menu = wx.Menu() # add some items menu.Append(self.popupID1, 'Let Me Go') menu.Append(self.popupID2,"Free All Fish" ) menu.Append(self.popupID3, "Set Bobber Debth" ) menu.Append(self.popupID4,"Clear All and repopulate") # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. self.PopupMenu(menu, (self.x, self.y)) menu.Destroy() # << class FishListCtrlPanel methods >> (18 of 22) def OnPopupOne(self, event): self.parent.LetFishGow(self.parent) # << class FishListCtrlPanel methods >> (19 of 22) def OnPopupTwo(self, event): self.parent.BoberDebthw(self.parent) # << class FishListCtrlPanel methods >> (20 of 22) def OnPopupThree(self, event): self.parent.BoberDebthw(self.parent) # << class FishListCtrlPanel methods >> (21 of 22) def OnPopupFour(self, event): self.parent.PopulateListw(self.parent) # << class FishListCtrlPanel methods >> (22 of 22) def OnSize(self, event): w,h = self.GetClientSizeTuple() self.list.SetDimensions(0, 0, w, h) # -- end -- << class FishListCtrlPanel methods >> # << pyboids_main methods >> (6 of 10) class PyApp(wx.App): # << class PyApp methods >> def OnInit(self): # Create an instance of our customized Frame class frame = BoidFrame(None, -1, "wx Boids") frame.Show(True)# Tell wxWindows that this is our main window self.SetTopWindow(frame) # Return a success flag return True # -- end -- << class PyApp methods >> # << pyboids_main methods >> (7 of 10) def RunList(howMany, steps, whichThread, win): """ This function creates a list of "howMany" boids that will run through "steps" number of steps. PRE: howMany: Number of boids to create. Make this sensible. More than 50 will really bog most processers down (e.g. mine is an AMD 475 MHz). steps: Number of steps to take before ending. If 0 then run indefinately. Created: 20000613 -taw: Todd Warner Updated: 20010326 -taw """ print "It has begun!" howMany = int(howMany) if 0 == howMany: print "No boids created. This thread ending...." threadOneRunningFlag = threadTwoRunningFlag = True return l = BoidListObj(howMany) print "Created", howMany, "boids" if steps: it = int(steps) else: it = 0 count = 1 while howMany: # The main processing loop. l.DrawAll() l.MoveAll() pyimg = wx.ImageFromBitmap(l.canvas) dcimg = WXToPIL(pyimg) evt = UpdateBoids(dcimg = dcimg) wx.PostEvent(win, evt) #if E.isSet(): # Set when GUI window is closed (see way above this). # break if count == it: break if it: count = count +1 print "Simulation ended!" # << pyboids_main methods >> (8 of 10) def WXToPIL(image, mode = 'RGBA'): "convert a wx.Image to a PIL RGBA image" imageData = image.GetData() size = (image.GetWidth(), image.GetHeight()) imagePIL = Image.fromstring('RGB', size, imageData) if mode != 'RGB': imagePIL = imagePIL.convert(mode) return imagePIL # << pyboids_main methods >> (9 of 10) def Welcome(): """ Self explanatory. Created: 20000613 -taw: Todd Warner Updated: 20000619 -taw """ print "\n\n\n\n\n\n" # Can anyone tell me how to clear the screen? print "\n\nF l o c k i n g S i m u l a t o r - ", version print "(c) Copyright Todd Warner ", date print """ Released under the GNU Public License: http://www.gnu.org/copyleft/gpl.html This simulation builds roughly off of computer animator Craig Reynold's boid algorithm. Pseudocode (by Conrad Partker) can be found at: http://www.cse.unsw.edu.au/~conradp/boids/pseudocode.html This multi-threaded application was entirely written in Python after having just learned the languarge. Enjoy! -------------------------------------------------------------------------------- """ # << pyboids_main methods >> (10 of 10) def Usage(): """ Self explanatory. Created: 20000613 -taw: Todd Warner Updated: 20000619 -taw """ print """ ########## ## ## USAGE:", name, " ## ## The number of steps is optional (for testing only) ## ## Example: [tw@trixie pyboids]$ nice -10 ./pyboids.py 10 5 ## or: [tw@trixie pyboids]$ nice -10 ./pyboids.py 10 5 300 ## ########## """ # -- end -- << pyboids_main methods >> DMath = taw_3DMath() app = PyApp(0) # Create an instance of the application class app.MainLoop() # Tell it to start processing events