Open Technical Blog
Wednesday, 5 September 2012
Bouncing Ball 01
This script shows a basic structure for an animation in PyGtk. The following techniques are adopted:
Object-oriented style for the moving object.
Cairo for graphics.
Timer trigger for animation.
Mouse click detection on window.
Source Code
# Title : Bouncing ball animation # Author : Michael Mui # Date : 16/08/2012 # Version : 0.1 # Description : The following techniques are adopted # 1. Object-oriented style for the moving object # 2. Employ Cairo for graphics # 3. Use timer trigger for animation # 4. Detect mouse click event on window import pygtk pygtk.require('2.0') import gtk, math, gobject class ball: def __init__(self): self.x = 100 # x of centre self.y = 50 # y of centre self.r = 30 # radius self.w = 10 # width of border self.sx = 1 # x speed self.sy = 1 # y speed def draw(self,pDrwCntxt,pWidth,pHeight): # check boundaries if self.x < self.r+self.w: # hit left boundary self.x = self.r+self.w self.sx = -self.sx elif self.x > pWidth-self.r-self.w: # hit right boundary self.x = pWidth-self.r-self.w self.sx = -self.sx if self.y < self.r+self.w: # hit top boundary self.y = self.r+self.w self.sy = -self.sy elif self.y > pHeight-self.r-self.w: # hit bottom boundary self.y = pHeight-self.r-self.w self.sy = -self.sy # draw circle pDrwCntxt.set_line_width(self.w) pDrwCntxt.set_source_rgb(0.7, 0.2, 0.0) pDrwCntxt.arc(self.x, self.y, self.r, 0, 2*math.pi) pDrwCntxt.stroke_preserve() pDrwCntxt.set_source_rgb(0.9, 0.9, 0.7) pDrwCntxt.fill() def change_speed(self,pChange): if self.sx > 0: self.sx += pChange else: self.sx -= pChange if self.sy > 0: self.sy += pChange else: self.sy -= pChange def move(self): self.x += self.sx self.y += self.sy class strMsg: def __init__(self): self.x = 10 self.y = 25 self.s = 15 self.str = 'Click Me (Left, Right)' def draw(self,pDrwCntxt,pWidth,pHeight): pDrwCntxt.move_to(self.x,pHeight-self.y) pDrwCntxt.set_font_size(self.s) pDrwCntxt.set_source_rgb(0, 0, 0) pDrwCntxt.show_text(self.str) pDrwCntxt.stroke() class Base: def __init__(self): self.Win = gtk.Window(gtk.WINDOW_TOPLEVEL) self.Win.set_size_request(300,200) self.Win.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.Win.connect("button_press_event", self.ButPress_event) self.Win.connect("delete_event", self.WinDelete_event) self.Msg = '' mArea = gtk.DrawingArea() mArea.connect("expose-event",self.expose) self.Win.add(mArea) self.Win.show_all() self.Ball01 = ball() self.Msg01 = strMsg() # define a timer: trigger at each 1/20 s self.timer = gobject.timeout_add(50, self.timeOutTrigger) # timeout trigger def timeOutTrigger(self): self.Ball01.move() # redraw window self.Win.queue_draw() # keep timer running return True # stop timer running # return False # Window delete event def WinDelete_event(self, widget, event, data=None): gtk.main_quit() return False # Mouse button capture event def ButPress_event(self, widget, event): mbutt = '' mstep = 1 # which button was clicked? if event.button == 1: mStr1 = "Left click" mbutt = 'l' elif event.button == 2: mStr1 = "Middle click" elif event.button == 3: mStr1 = "Right click" mbutt = 'r' # was it a multiple click? if event.type == gtk.gdk.BUTTON_PRESS: mStr2 = "Single click" mstep = 1 elif event.type == gtk.gdk._2BUTTON_PRESS: mStr2 = "Double click" mstep = 2 elif event.type == gtk.gdk._3BUTTON_PRESS: mStr2 = "Triple click" mstep = 3 # message and action if mbutt == 'l': self.Ball01.change_speed(mstep) elif mbutt == 'r': self.Ball01.change_speed(-mstep) self.Msg01.str = 'Speed:' + str(abs(self.Ball01.sx)) + \ ' ' + mStr1 + ', ' + mStr2 # redraw window self.Win.queue_draw() def expose(self, widget, event): mcr = widget.window.cairo_create() mw = widget.window.get_size()[0] mh = widget.window.get_size()[1] # draw ball self.Ball01.draw(mcr,mw,mh) # draw text self.Msg01.draw(mcr,mw,mh) if __name__ == "__main__": base = Base() # define gtk widgets gtk.main()
No comments:
Post a Comment
Newer Post
Older Post
Home
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment