#!/usr/bin/python import wx from time import sleep from thread import start_new_thread from random import randrange from math import sin,cos,pi,sqrt CONST_DT = 0.1 CONST_G = 9.8 CONST_EY = 0.8 CONST_EX = 0.8 CONST_ALPHA = 2.0/5.0 CONST_NBALLS = 5 CONST_STOPAT = 50.0 class BallPanel(wx.Panel): def __init__(self,parent): wx.Panel.__init__(self,parent) self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_TIMER, self.OnTimer) self.SetBackgroundColour("white") self.timer = wx.Timer(self) self.timer.Start(10) self.balls = [] a = pi/(2.0*CONST_NBALLS) for i in range(CONST_NBALLS): b = Ball(35.0,35.0,10.0) b.velocity = [50.0*cos(i*a),0.0] self.balls.append(b) self.time = 0 self.active = True def Start(self): start_new_thread(self.Simulate,()) def OnPaint(self, evt): dc = wx.PaintDC(self) for i in range(CONST_NBALLS): self.balls[i].DrawHistory(dc) for i in range(CONST_NBALLS): self.balls[i].Draw(dc) dc.SetPen(wx.Pen(wx.Colour(0,0,0))) dc.DrawText("time: %.2f" % self.time,2,2) def OnTimer(self, evt): self.Refresh(True) def Simulate(self): while self.active: self.time += CONST_DT for i in range(CONST_NBALLS): self.balls[i].Update(CONST_DT,self.GetClientSizeTuple()) if not self.active: break if not self.active: break if self.time >= CONST_STOPAT: break sleep(0.1) class Ball: def __init__(self,x=0,y=0,r=20): self.position = [x,y] self.velocity = [0.0,0.0] self.r = r self.history = [] def DrawHistory(self,dc): dc.SetPen(wx.Pen(wx.Colour(255,0,0))) dc.DrawLines(self.history) def Draw(self,dc): dc.SetBrush(wx.Brush(wx.Colour(102,102,102))) dc.DrawCircle(self.position[0],self.position[1],self.r) def Update(self,dt,bounds): self.velocity[1] += CONST_G * dt self.position[0] += self.velocity[0]*dt self.position[1] += self.velocity[1]*dt if (self.position[1] + self.r) >= bounds[1]: self.velocity[1] *= -CONST_EY self.position[1] = bounds[1]-self.r elif (self.position[1] - self.r) <= 0: self.velocity[1] *= -CONST_EY self.position[1] = self.r if (self.position[0] + self.r) >= bounds[0]: self.velocity[0] *= -CONST_EX self.position[0] = bounds[0]-self.r elif (self.position[0] - self.r) <= 0: self.velocity[0] *= -CONST_EX self.position[0] = self.r self.history.append(wx.Point(self.position[0],self.position[1])) class BallApp(wx.App): def __init__(self,w,h): wx.App.__init__(self,0) frm = wx.Frame(None) frm.SetClientSize(wx.Size(w,h)) frm.Bind(wx.EVT_CLOSE, self.OnFrameClose) self.bpn = BallPanel(frm) frm.Show(True) self.bpn.Start() def OnFrameClose(self,evt): self.bpn.active = False self.ExitMainLoop() def OnExit(self): self.bpn.active = False if __name__ == '__main__': app = BallApp(800,600) app.MainLoop()