From: Kevin A. <ka...@us...> - 2004-09-25 20:46:00
|
Update of /cvsroot/pythoncard/PythonCard/samples/gravity In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21259 Added Files: .cvsignore gravity.py gravity.rsrc.py Log Message: added gravity sample --- NEW FILE: .cvsignore --- .cvsignore *.pyc *.log .DS_Store --- NEW FILE: gravity.py --- #!/usr/bin/python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2004/09/25 20:45:47 $" """ # KEA 2004-09-25 # based on the excellent work by Keith Peters # http://www.bit-101.com/tutorials/gravity.html # I started with the doodle sample, so this sample still # contains some cruft from PythonCard import clipboard, dialog, graphic, model import wx import os import random import time def pointInRect(xy, rect): x, y = xy left, top, right, bottom = rect if x >= left and x <= right and y >= top and y <= bottom: return True else: return False class Sprite(object): def __init__(self, canvas): self.canvas = canvas class BallSprite(Sprite): def __init__(self, canvas, x, y, radius, color='red'): Sprite.__init__(self, canvas) self.x = x self.y = y self.oldx = x self.oldy = y self.radius = radius self.color = color self.xspeed = random.random() * 30 self.yspeed = random.random() * 30 self.gravity = 2 self.drag = .98 self.bounce = .9 self.dragging = False def move(self): # this is sort of pointless right now # but maybe the dragging code could be moved # into the class in which case we might need # to know if we're dragging if not self.dragging: self.x += self.xspeed self.y += self.yspeed rightedge, bottomedge = self.canvas.size # bounce when we hit the edge if (self.x - self.radius) < 0: self.x = self.radius self.xspeed = -self.xspeed * self.bounce elif (self.x + self.radius) > rightedge: self.x = rightedge - self.radius self.xspeed = -self.xspeed * self.bounce if (self.y - self.radius) < 0: self.y = self.radius self.yspeed = -self.yspeed * self.bounce elif (self.y + self.radius) > bottomedge: self.y = bottomedge - self.radius self.yspeed = -self.yspeed * self.bounce self.xspeed = self.xspeed * self.drag self.yspeed = self.yspeed * self.drag + self.gravity else: self.xspeed = self.x - self.oldx self.yspeed = self.y - self.oldy self.oldx = self.x self.oldy = self.y #print "speed", self.xspeed, self.yspeed self.draw() def draw(self): self.canvas.setFillColor(self.color) #self.canvas.foregroundColor = self.color self.canvas.drawCircle((self.x, self.y), self.radius) class Gravity(model.Background): def on_initialize(self, event): self.x = 0 self.y = 0 self.dragging = False self.animate = False self.filename = None self.color = self.components.btnColor.backgroundColor # leave it black for now #self.components.bufOff.foregroundColor = self.color self.sprites = [] self.initSizers() def initSizers(self): sizer1 = wx.BoxSizer(wx.VERTICAL) sizer2 = wx.BoxSizer(wx.HORIZONTAL) comp = self.components flags = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.ALIGN_BOTTOM # Mac wxButton needs 7 pixels on bottom and right macPadding = 7 sizer2.Add(comp.btnColor, 0, flags, macPadding) sizer2.Add(comp.btnAnimate, 0, flags, macPadding) sizer2.Add(comp.btnStop, 0, flags, macPadding) sizer1.Add(sizer2, 0) sizer1.Add(comp.bufOff, 1, wx.EXPAND) sizer1.Fit(self) sizer1.SetSizeHints(self) self.panel.SetSizer(sizer1) self.panel.SetAutoLayout(1) self.panel.Layout() def on_btnAnimate_mouseClick(self, event): event.target.enabled = False canvas = self.components.bufOff canvas.autoRefresh = False self.sprites.append(BallSprite(self.components.bufOff, 20, 20, 14, self.color)) # use the last ball added self.animate = True avgfps = 0 frame = 0 startTime = time.time() while self.animate: canvas.clear() for ball in self.sprites: ball.move() canvas.redraw() #time.sleep(.01) # give the user a chance to click Stop frame += 1 self.statusBar.text = "Average FPS: %f" % (frame / (time.time() - startTime)) wx.Yield() def on_btnStop_mouseClick(self, event): self.animate = False self.components.btnAnimate.enabled = True def on_close(self, event): self.animate = False event.skip() def on_bufOff_mouseDown(self, event): #event.target.drawLine((self.x, self.y), (self.x + 1, self.y + 1)) # figure out which ball the user clicked on, if any # i want to search the list from back to front # but I don't change the list in place, so I make a copy # is there a way to iterate over a list in reverse without # using something awkward like # for i in range(len(self.sprites) - 1, -1, -1): sprites = self.sprites[:] sprites.reverse() for ball in sprites: radius = ball.radius x = ball.x y = ball.y #print "point", event.position #print "rect", x - radius, y - radius, x + radius, y + radius if pointInRect(event.position, (x - radius, y - radius, x + radius, y + radius)): self.dragging = ball ball.dragging = True x, y = event.position self.dx = ball.x - x self.dy = ball.y - y #print self.dx, self.dy break # on a mouseLeave we will no longer # get drag messages, so we could end dragging # at that point, just keep the current behavior def on_bufOff_mouseDrag(self, event): if self.dragging: x, y = event.position ball = self.dragging ball.x = x + self.dx ball.y = y + self.dy # reraw all the objects self.components.bufOff.clear() for ball in self.sprites: ball.move() self.components.bufOff.redraw() def on_bufOff_mouseUp(self, event): if self.dragging: self.dragging.dragging = False self.dragging = None # older Doodle code # I'm keeping it around in case I need it later def on_bufOff_mouseEnter(self, event): self.x, self.y = event.position ## def on_bufOff_mouseDown(self, event): ## self.x, self.y = event.position ## event.target.drawLine((self.x, self.y), (self.x + 1, self.y + 1)) ## ## def on_bufOff_mouseDrag(self, event): ## x, y = event.position ## event.target.drawLine((self.x, self.y), (x, y)) ## self.x = x ## self.y = y def on_btnColor_mouseClick(self, event): result = dialog.colorDialog(self, color=self.color) if result.accepted: #self.components.bufOff.foregroundColor = result.color event.target.backgroundColor = result.color self.color = result.color def openFile(self): result = dialog.openFileDialog(None, "Import which file?") if result.accepted: path = result.paths[0] os.chdir(os.path.dirname(path)) self.filename = path bmp = graphic.Bitmap(self.filename) self.components.bufOff.drawBitmap(bmp, (0, 0)) def on_menuFileOpen_select(self, event): self.openFile() def on_menuFileSaveAs_select(self, event): if self.filename is None: path = '' filename = '' else: path, filename = os.path.split(self.filename) result = dialog.saveFileDialog(None, "Save As", path, filename) if result.accepted: path = result.paths[0] fileType = graphic.bitmapType(path) print fileType, path try: bmp = self.components.bufOff.getBitmap() bmp.SaveFile(path, fileType) return 1 except: return 0 else: return 0 def on_menuEditCopy_select(self, event): clipboard.setClipboard(self.components.bufOff.getBitmap()) def on_menuEditPaste_select(self, event): bmp = clipboard.getClipboard() if isinstance(bmp, wx.Bitmap): self.components.bufOff.drawBitmap(bmp) def on_editClear_command(self, event): self.components.bufOff.clear() if __name__ == '__main__': app = model.Application(Gravity) app.MainLoop() --- NEW FILE: gravity.rsrc.py --- { 'application':{ 'type':'Application', 'name':'Doodle', 'backgrounds': [ { 'type':'Background', 'name':'bgDoodle', 'title':'Doodle PythonCard Application', 'size':( 310, 300 ), 'style':['resizeable'], 'statusBar':1, 'menubar': { 'type':'MenuBar', 'menus': [ { 'type':'Menu', 'name':'menuFile', 'label':'&File', 'items': [ { 'type':'MenuItem', 'name':'menuFileOpen', 'label':'&Open...\tCtrl+O' }, { 'type':'MenuItem', 'name':'menuFileSaveAs', 'label':'Save &As...' }, { 'type':'MenuItem', 'name':'fileSep1', 'label':'-' }, { 'type':'MenuItem', 'name':'menuFileExit', 'label':'E&xit\tAlt+X', 'command':'exit' } ] }, { 'type':'Menu', 'name':'menuEdit', 'label':'&Edit', 'items': [ { 'type':'MenuItem', 'name':'menuEditCopy', 'label':'&Copy\tCtrl+C'}, { 'type':'MenuItem', 'name':'menuEditPaste', 'label':'&Paste\tCtrl+V'}, { 'type':'MenuItem', 'name':'editSep1', 'label':'-' }, { 'type':'MenuItem', 'name':'menuEditClear', 'label':'&Clear', 'command':'editClear'} ] } ] }, 'components': [ { 'type':'Button', 'name':'btnColor', 'position':(0, 0), 'label':'Color', 'backgroundColor':'blue', }, { 'type':'Button', 'name':'btnAnimate', 'position':(100, 0), 'label':'Animate' }, { 'type':'Button', 'name':'btnStop', 'position':(200, 0), 'label':'Stop' }, { 'type':'BitmapCanvas', 'name':'bufOff', 'position':(0, 30), 'size':(300, 230) }, ] } ] } } |