# ASKBliG # ~~~~~~~ # # Aka, "Breakout." Kind-of. # Input arguments: # ~~~~~~~~~~~~~~~ # # Width -- (standard) width of board # Height -- (standard) height of board # Rows -- number of rows of bricks # Game play # ~~~~~~~~~ # The user may move the mouse to move the paddle. Pressing any mouse # button will create a new ball; up to four balls may be active at # one time. Press 'n' to start a new game. # Game scoring # ~~~~~~~~~~~~ # # Good things-- # # Hit wall: +10 pts # Hit paddle: +20 pts # Hit brick: +100 pts # Hit ball: +200 pts # # Bad things-- # # Loose ball: -400 pts # Being alive: -1 pt/frame # # The player starts a game with 1000 points; the game is over when # the score reaches zero. # Known bugs: # ~~~~~~~~~~ # # - Balls will sometimes go through a wall and get lost. # - When the system slows down too much, mouse movement events are # seen sporadically; it should really be using MousePosition() to # place the paddle, put for some reason this routine it tremendously # slow when the paddle moves. Strange. import ihEvent # For interpreting event messages import ihApp # Very basic application framework on top of # the iHTML core. Veeerry basic. # Class: HitMask # Superclass: none # # This class is used to make checking for object collisions more efficient. # It divides the play area into horizontal strips, and keeps track of which # objects are in each strip. This way an object only needs to check those # in its own strip, rather than the entire playfield. # # The class current divides the playfield into strips of 20 pixels; it # should be more intelligent about this, as the overall efficiency of the # system is extremely dependent on this constant. Too large, and objects # have to check more hits than necessary; too large, and they have to check # many individual strips to find all the collisions. # # This class can also probably stand to be improved a bit -- it might # be more effecient to have the strips contain dictionaries rather than # arrays. class HitMask: # Create class. 'height' is the total height, in pixels, of the # playfield. def __init__(self,height): self.height = height self.last = (height-1)/20 if( self.last < 1 ): self.last = 1 #self.masks = [[]] * (self.last+1) self.masks = [] for i in range(0,self.last+1): self.masks.append([]) # Add a new piece to the HitMask, who's top is located at 'y' and # which is 'height' pixels tall. def AddPiece(self,piece,y,height): #print 'Add range for %s, y=%s, height=%s' % (piece,y,height) #print self.make_range(y,height) for i in self.make_range(y,height): self.masks[i].append(piece) # Remove a piece from the HitMask, who's top is located at 'y' and # which is 'height' pixels tall. def RemPiece(self,piece,y,height): #print 'Rem range for %s, y=%s, height=%s' % (piece,y,height) #print self.make_range(y,height) try: for i in self.make_range(y,height): self.masks[i].remove(piece) except ValueError: pass # Update the position of a piece -- it was located at 'oldy' and # was 'oldheight' pixels tall; it is now located at 'newy' and is # 'newheight' pixels tall. def MovePiece(self,piece,oldy,oldheight,newy,newheight): oldy1, oldy2 = self.get_range(oldy,oldheight) newy1, newy2 = self.get_range(newy,newheight) if( oldy1 != newy1 or oldy2 != newy2 ): #print 'Moving:',piece if( oldy1 < newy1 ): for i in range(oldy1,newy1+1): try: self.masks[i].remove(piece) except: pass if( newy1 < oldy1 ): for i in range(oldy1,newy1+1): self.masks[i].append(piece) if( oldy2 > newy2 ): for i in range(newy2-1,oldy2): try: self.masks[i].remove(piece) except: pass if( newy2 > oldy2 ): for i in range(oldy2-1,newy2): self.masks[i].append(piece) # Return an array of the strips which an object with the given # position and height will need to check for hits. def PieceMask(self,y,height): y1,y2 = self.get_range(y,height) #print 'Get range: from %s to %s' % (y1,y2) return self.masks[y1:y2] # ** # ** Private functions # ** # Return the range of strips covered by the given dimensions. def get_range(self,y,height): y1 = y/20 if( y1 < 0 ): y1 = 0 elif( y1 > self.last ): y1 = self.last y2 = ((y+height-1)/20)+1 if( y2 < 1 ): y2 = 1 elif( y2 > (self.last+1) ): y2 = (self.last+1) return y1,y2 # Create an array range for the given dimensions. def make_range(self,y,height): y1 = y/20 if( y1 < 0 ): y1 = 0 elif( y1 > self.last ): y1 = self.last y2 = ((y+height-1)/20)+1 if( y2 < 1 ): y2 = 1 elif( y2 > (self.last+1) ): y2 = (self.last+1) #print 'y1=%s, y2=%s, last=%s' % (y1,y2,self.last) return range(y1,y2) # Class: GamePiece # Superclass: none # # This class defines the components common to all pieces used by the # game. This includes the bricks, balls, paddle, etc. It also may # optionally make use of a HitMask object which the piece is to be # put in. # Universal game piece -- defines all common functionality and structure. class GamePiece: # Class initialization. Arguments are: # # app: (required positional) the main application class. Must be # a subclass of a widget, and define the functions LogScore(), # RemoveBrick(), RemoveBall(), and have member variables # background, foreground, shine_color, shadow_color. # [Yes, this isn't the best. :p] # hit_mask: (required positional) a HitMask object in which to place # this piece. If 'None', it is not used. # x: (optional keyword) the initial x position # y: (optional keyword) the initial y position # width: (optional keyword) the initial width in pixels # height: (optional keyword) the initial height in pixels # xvel: (optional keyword) the initial x velocity # yvel: (optional keyword) the initial y velocity # movable: (optional keyword) boolean -- can this piece be moved? # hitable: (optional keyword) hitable -- can this piece be touched? # color: (optional keyword) color to draw piece in # pixmap: (optional keyword) pixmap to draw piece with; overrides color def __init__(self,app,hit_mask,x=0,y=0,width=0,height=0,xvel=0,yvel=0, movable=0,hitable=1,color=None,pixmap=None,**leftovers): self.app = app self.hit_mask = hit_mask self.x = x self.y = y self.width = width self.height = height self.xvel = xvel self.yvel = yvel if hit_mask: hit_mask.AddPiece(self,y,height) self.movable = movable self.hitable = hitable self.color = color or self.app.foreground self.pixmap = pixmap if pixmap: self.width = pixmap.Dimensions()[2] self.height = pixmap.Dimensions()[3] # Change the position of the piece. Keeps the HitMask up-to-date. def SetPosition(self,x,y): if( self.hit_mask ): self.hit_mask.MovePiece(self,self.y,self.height, y,self.height) self.x = x self.y = y # Change the size of the piece. Keeps the HitMask up-to-date. def SetSize(self,width,height): if( self.hit_mask ): self.hit_mask.RemPiece(self,self.y,self.height) self.width = width self.height = height if( self.hit_mask ): self.hit_mask.AddPiece(self,self.y,self.height) # Check for collisions. 'pieces' is an array of pieces which should # be checked; for any collision found between this piece and one in # in the array, both piece's 'do_hit()' method is called. # This should probably be changed to take better advantage of the # HitMask. def Hit(self,pieces): for other in pieces: if not self is other: # print 'Did %s hit %s?' % (self.__class__,other.__class__) # print '(%s,%s)/(%sx%s) to (%s,%s)/(%sx%s)' \ # % ( self.x,self.y,self.width,self.height, # other.x,other.y,other.width,other.height ) if ( self.x < (other.x+other.width) and (self.x+self.width) > other.x and self.y < (other.y+other.height) and (self.y+self.height) > other.y and self.hitable and other.hitable ): # print 'HIT: (%s,%s)/(%sx%s) to (%s,%s)/(%sx%s)' \ # % ( self.x,self.y,self.width,self.height, # other.x,other.y,other.width,other.height ) self.do_hit(other) other.do_hit(self) # Draw the piece's graphic in the drawable 'where'. If a pixmap is # available, that is used; otherwise, it is by default drawn as a # rectangle in the piece's color. def Draw(self,where): if self.pixmap: where.Paste(self.x,self.y,self.pixmap) else: where.ForePen(self.color) where.FillRectangle(self.x,self.y,self.width,self.height) # Erase the piece's graphic in the drawable 'where'. Draws a # rectangle in the background color. def Erase(self,where): if self.pixmap: where.ForePen(self.app.background) where.FillRectangle(self.x,self.y,self.width,self.height) else: where.ForePen(self.app.background) where.FillRectangle(self.x,self.y,self.width,self.height) # Change state for next frame. By default does no action. def Step(self): pass # nothing # ** # ** The rest are private method. # ** # Do action when hit by another object. Must be defined by sub-class. def do_hit(self,other): raise AccessError, 'undefined method do_hit() called.' # Class: Wall # Superclass: GamePiece # # Implements the functionality for a wall piece. This basically involves # incrementing the player's score by 10 when hit by a ball. class Wall(GamePiece): def __init__(self,app,hit_mask,**keys): # Do superclass initialization. apply(GamePiece.__init__,(self,app,hit_mask),keys) def do_hit(self,other): if other.__class__ == Ball: self.app.LogScore(10) # Class: Brick # Superclass: GamePiece # # Implements the functionality for a wall piece. This involves # incrementing the player's score by 100 when hit by a ball, and asking # the main class to remove this brick. class Brick(GamePiece): def __init__(self,app,hit_mask,**keys): # Do superclass initialization. apply(GamePiece.__init__,(self,app,hit_mask),keys) def do_hit(self,other): if other.__class__ == Ball: self.app.LogScore(100) self.app.RemoveBrick(self) # Class: InvisibleDeath # Superclass: GamePiece # # Creates a piece which removes a ball whenever it is touched, and # decrements the player's score by 400. It does not draw on to the # playfield. This class is used to bound the bottom of the screen, # below the paddle. class InvisibleDeath(GamePiece): def __init__(self,app,hit_mask,**keys): # Do superclass initialization. apply(GamePiece.__init__,(self,app,hit_mask),keys) def Draw(self,where): pass def Erase(self,where): pass def do_hit(self,other): if other.__class__ == Ball: self.app.LogScore(-400) self.app.RemoveBall(other) # Class: InvisibleCleaner # Superclass: GamePiece # # Creates a piece which removes a ball whenever it is touched, but # does not decrement the player's score. It does not draw on to the # playfield. This class is used behind the walls, to catch any # balls which somehow [through a bug in the program :p] make it through # them. class InvisibleCleaner(GamePiece): def __init__(self,app,hit_mask,**keys): # Do superclass initialization. apply(GamePiece.__init__,(self,app,hit_mask),keys) def Draw(self,where): pass def Erase(self,where): pass def do_hit(self,other): if other.__class__ == Ball: self.app.RemoveBall(other) # Class: Paddle # Superclass: GamePiece # # Implement the game paddle. This piece positions itself so that # it is centered on its current (x,y) location, and adds 20 to the # player's score when hit by a ball. It also doesn't allow itself # to be moved through walls. class Paddle(GamePiece): def __init__(self,app,hit_mask,**keys): # Do superclass initialization. apply(GamePiece.__init__,(self,app,hit_mask),keys) self.xvel = 0 self.yvel = 0 def do_mouse(self,ev,x,y): oldx = self.x oldy = self.y self.SetPosition(x - (self.width/2),y - (self.height/2)) if( self.x != oldx): self.xvel = self.x - oldx if( self.y != oldy): self.yvel = self.y - oldy def do_hit(self,other): if other.__class__ == Ball: self.app.LogScore(20) elif other.__class__ == Wall: # print 'myx=%s, myw=%s; othx=%s, othw=%s' % (self.x,self.width, # other.x,other.width) if( other.width < other.height ): if( (other.x+(other.width/2)) < (self.x+(self.width/2)) ): self.x = other.x+other.width if( (other.x+(other.width/2)) > (self.x+(self.width/2)) ): self.x = other.x-self.width else: if( (other.y+(other.height/2)) < (self.y+(self.height/2)) ): self.y = other.y+other.height if( (other.y+(other.height/2)) > (self.y+(self.height/2)) ): self.y = other.y-self.height # Class: Ball # Superclass: GamePiece # # Implement the game ball. This piece's default draw style is a # filled circle; it automatically moves itself when stepped, increments # the player's score by 100 when hit by another ball [giving a total # score of 200], and tries to bounce itself off other objects. The # latter is sometimes not too successful, however.# The class changes its default xvel and yvel to 1. class Ball(GamePiece): def __init__(self,app,hit_mask,**keys): # Change default velocities. if not keys.has_key('xvel'): keys['xvel'] = 1 if not keys.has_key('yvel'): keys['yvel'] = 1 # Do superclass initialization. apply(GamePiece.__init__,(self,app,hit_mask),keys) def Draw(self,where): if self.pixmap: where.Paste(self.x,self.y,self.pixmap) else: where.ForePen(self.color) where.FillArc(self.x,self.y,self.width,self.height) def Step(self): if( self.xvel < -7 ): self.xvel = -7 if( self.xvel > 7 ): self.xvel = 7 if( self.yvel < -7 ): self.yvel = -7 if( self.yvel > 7 ): self.yvel = 7 self.SetPosition(self.x + self.xvel,self.y + self.yvel) def do_hit(self,other): if other.__class__ == Ball: self.app.LogScore(100) # Note this is called once for each ball. if( other.width < other.height ): self.xvel = -self.xvel if other.__class__ != Wall: if( self.y < other.y ): self.yvel = -abs(self.yvel) elif( (self.y+self.height) > (other.y+other.height) ): self.yvel = abs(self.yvel) self.yvel = self.yvel + other.yvel else: self.yvel = -self.yvel if other.__class__ != Wall: if( self.x < other.x ): self.xvel = -abs(self.xvel) elif( (self.x+self.width) > (other.x+other.width) ): self.xvel = abs(self.xvel) self.xvel = self.xvel + other.xvel self.Step() # Class: Points # Superclass: GamePiece # # A game piece which keeps track of and displays the player's score. # Defaults to 'hitable' being 0 and a width which will theoretically # hold a "large" score. Also supports a new argument 'points' which # defines the initial score. class Points(GamePiece): def __init__(self,app,hit_mask,**keys): if not keys.has_key('hitable'): keys['hitable'] = 0 if( not keys.has_key('width') ): tw,th,asc,desc = app.TextExtent(' High: 88888 / Current: 88888 ') print 'text width',tw keys['width'] = tw # Do superclass initialization. apply(GamePiece.__init__,(self,app,hit_mask),keys) if( keys.has_key('points') ): self.points = keys['points'] else: self.points = 1000 self.high = self.points # Add a point of the given 'amount' [may be negative] to the running # total. If this is a new maximum score, take it. def AddPoints(self,amount): self.points = self.points + amount if( self.points > self.high ): self.high = self.points # Is the game over? def IsOver(self): return self.points < 0 def Draw(self,where): view = 'High: %5d / Current: %5d' % (self.high,self.points) w,h,a,d = where.TextExtent(view) where.ForePen(self.app.shadow_color) where.DrawText(self.x+self.width-w+1, self.y+(self.height/2)-(h/2)+a+1, view, -1) where.ForePen(self.app.shine_color) where.DrawText(self.x+self.width-w-1, self.y+(self.height/2)-(h/2)+a-1, view, -1) where.ForePen(self.color) where.DrawText(self.x+self.width-w, self.y+(self.height/2)-(h/2)+a, view, -1) def do_hit(self,other): pass # Class: ihEmbed # Superclass: iHTML Application # # Our top-level class. class ihEmbed(ihApp.Application): # Log a change in the user's scored -- called by the pieces. def LogScore(self,points): if( not self.is_demo ): self.points.AddPoints(points) # Remove the given 'ball' from the playfield. Also removes it # from the HitMask, which isn't good; the ball should be doing this # itself, nie? def RemoveBall(self,ball): self.ball_count = self.ball_count - 1 try: self.move_pieces.remove(ball) except ValueError: pass self.hit_mask.RemPiece(ball,ball.y,ball.height) # Remove the given 'brick' from the playfield. Also removes it # from the HitMask, which isn't good; the brick should be doing this # itself, nie? def RemoveBrick(self,brick): self.brick_count = self.brick_count - 1 brick.Erase(self.buffer) try: self.fixed_pieces.remove(brick) except ValueError: pass self.hit_mask.RemPiece(brick,brick.y,brick.height) if( self.brick_count == 0 ): self.build_bricks() self.draw_all() # Main application entry. def __init__(self,rows=6,**args): # Send all arguments up to parent initialization. apply(ihApp.Application.__init__,(self,),args) # Retrieve arguments self.rows = rows # Retrieve basic app colors self.foreground = self.ForePen() self.background = self.BackPen() self.wall_color = self.foreground self.shine_color = self.MakeColor(1,1,1) self.shadow_color = self.MakeColor(0,0,0) self.ball_color = self.MakeColor(1,1,0) self.brick_color = self.MakeColor(.9,.3,.2) self.paddle_color = self.MakeColor(0,0,.4) # Create buffer to draw in. self.buffer = self.MakePixmap(self.Dimensions()[2], self.Dimensions()[3]) # Initialize mouse coordinates self.mouse_x = 0 self.mouse_y = 0 self.is_demo = 0 # Find dimensions for playfield self.find_dimens() # Create initial game pieces. self.start_game() # Draw initial image into buffer and start game. self.draw_all() self.update() # ** # ** All other methods are private # ** # Find dimensions for screen. This sets a ton of member variable # which I am not going to document, so there. [Hey! It's a # dynamically interpreted language! You're -supposed- to be quick # and loose with your variables. ;)] def find_dimens(self): x, y, w, h = self.Dimensions() tw,th,asc,desc = self.TextExtent('88888888888') bor = 10 self.width = w self.height = h self.inner_width = w-(bor*2) self.inner_height = h-(bor*2) self.text_height = th self.border_width = bor self.brick_top = bor*3 + th self.border_width = 10 self.brick_width = (self.inner_width/10)-4 self.paddle_width = w/15 self.paddle_height = bor self.ball_width = 8 # Create pictures for some game pieces self.brick_pic = self.MakePixmap(self.brick_width,bor) self.brick_pic.ForePen(self.brick_color) self.brick_pic.FillRectangle(0,0,self.brick_width,bor) self.brick_pic.ForePen(self.shadow_color) self.brick_pic.DrawLine(0,bor-1,self.brick_width-1,bor-1) self.brick_pic.DrawLine(self.brick_width-1,0,self.brick_width-1,bor-1) self.brick_pic.ForePen(self.shine_color) self.brick_pic.DrawLine(0,0,self.brick_width-1,0) self.brick_pic.DrawLine(0,0,0,bor-2) bw = self.ball_width self.ball_pic = self.MakePixmap(bw,bw) self.ball_pic.ForePen(self.background) self.ball_pic.FillRectangle(0,0,bw,bw) self.ball_pic.ForePen(self.ball_color) self.ball_pic.FillArc(0,0,bw,bw) self.ball_pic.ForePen(self.shine_color) self.ball_pic.DrawArc(0,0,bw,bw,90,270) self.ball_pic.ForePen(self.shadow_color) self.ball_pic.DrawArc(0,0,bw,bw,270,90) self.paddle_pic = self.MakePixmap(self.paddle_width,bor) self.paddle_pic.ForePen(self.paddle_color) self.paddle_pic.FillRectangle(0,0,self.paddle_width,bor) self.paddle_pic.ForePen(self.shadow_color) self.paddle_pic.DrawLine(0,bor-1,self.paddle_width-1,bor-1) self.paddle_pic.DrawLine(self.paddle_width-1,0, self.paddle_width-1,bor-1) self.paddle_pic.ForePen(self.shine_color) self.paddle_pic.DrawLine(0,0,self.paddle_width-1,0) self.paddle_pic.DrawLine(0,0,0,bor-2) # Start a new game. Initializes the arrays holding pieces, creates # a HitMask for the game, creates the pieces. def start_game(self): self.move_pieces = [] # All pieces which can move self.fixed_pieces = [] # All pieces which are fixed in place self.ball_count = 0 self.brick_count = 0 w, h = self.width, self.height th = self.text_height bor = self.border_width inw, inh = self.inner_width, self.inner_height self.hit_mask = HitMask(h) self.ball_count = 0 self.brick_count = 0 self.paddle = Paddle(self, self.hit_mask, x=w/2, y=self.height-self.paddle_height, width=w/15, height=bor, color=self.paddle_color, pixmap=self.paddle_pic) self.points = Points(self, None, x=bor*2, y=bor*2, width = w-(bor*4), height=th+(th/2), color = self.foreground, points=1000) self.fixed_pieces.append(Wall(self, self.hit_mask, x=0, y=0, width=bor, height=h, color=self.wall_color)) self.fixed_pieces.append(InvisibleCleaner(self, self.hit_mask, x=-(bor*2), y=-(bor*2), width=(bor*2), height=h+(bor*2), color=self.wall_color)) self.fixed_pieces.append(Wall(self, self.hit_mask, x=w-bor, y=0, width=bor, height=h, color=self.wall_color)) self.fixed_pieces.append(InvisibleCleaner(self, self.hit_mask, x=w, y=-(bor*2), width=(bor*2), height=h+(bor*2), color=self.wall_color)) self.fixed_pieces.append(Wall(self, self.hit_mask, x=bor, y=0, width=w-(bor*2), height=bor, color=self.wall_color)) self.fixed_pieces.append(InvisibleCleaner(self, self.hit_mask, x=0, y=-(bor*2), width=w, height=(bor*2), color=self.wall_color)) self.fixed_pieces.append(InvisibleDeath(self, self.hit_mask, x=0, y=h+bor, width=w, height=(bor*2), color=self.wall_color)) self.move_pieces.append(self.paddle) self.build_bricks() # Build the columns of bricks. Builds 'self.cols' number of columns. def build_bricks(self): top = self.brick_top for i in range(self.rows): for j in range(10): self.brick_count = self.brick_count + 1 self.fixed_pieces.append(Brick(self, self.hit_mask, x = ((self.inner_width*j) /10)+2+self.border_width, y = top, width = (self.inner_width/10)-4, height = self.border_width, color = self.brick_color, pixmap = self.brick_pic)) top = top + self.border_width*2 #self.move_pieces.append(Ball(self,x=w/2,y=h/2,width=8,height=8, # xvel=2,yvel=2,color=self.ball_color)) #print 'Mask array=' #print self.hit_mask.masks # Draw the entire playfield in the buffer. This is only done when # something drastically changes. def draw_all(self): self.buffer.ForePen(self.background) self.buffer.FillRectangle(0,0,self._Widget_.Dimensions()[2], self._Widget_.Dimensions()[3]) for i in self.move_pieces: i.Draw(self.buffer) for i in self.fixed_pieces: i.Draw(self.buffer) self.points.Draw(self.buffer) self.redraw() # Redraw the main window. This just involves copying the buffer in # to it. def redraw(self): self.Paste(0,0,self.buffer) self.Flush() pass # Erase all of the dynamic pieces. def erase_pieces(self): for i in self.move_pieces: i.Erase(self.buffer) self.points.Erase(self.buffer) # Draw all of the dynamic pieces. def draw_pieces(self): for i in self.move_pieces: i.Draw(self.buffer) self.points.Draw(self.buffer) # Update the game. Erase all pieces, step all pieces, get mouse # position and move paddle, check for collisions, redraw display. def update(self): #print self.MouseState() self.FutureCall(.05,self.update) self.erase_pieces() self.LogScore(-(self.ball_count)/2 - 1) for i in self.move_pieces: i.Step() # For some reason, MousePosition() seems to be deadly slow # when the mouse is moving in the window... HUH? #self.mouse_x, self.mouse_y = self.MousePosition() #print self.MousePosition() if( self.is_demo ): lowest = None follow = None for i in self.move_pieces: if( i.__class__ == Ball ): if( not lowest or i.y > lowest.y ): lowest = i if( i.yvel >= 0 and (not follow or i.y > follow.y) ): follow = i if( not follow ): follow = lowest if( follow ): if( follow.x > (self.mouse_x+10) ): self.mouse_x = self.mouse_x+10 elif( follow.x < (self.mouse_x-10) ): self.mouse_x = self.mouse_x-10 else: self.mouse_x = follow.x if( (not lowest) or lowest.y < (self.height/2) ): self.add_ball(self.mouse_x,self.mouse_y) if( self.mouse_x < self.border_width ): self.mouse_x = self.border_width if( self.mouse_x > (self.width-self.border_width) ): self.mouse_x = self.width-self.border_width if( self.mouse_y < self.border_width ): self.mouse_y = self.border_width if( self.mouse_y > (self.height-self.border_width) ): self.mouse_y = self.height-self.border_width self.paddle.do_mouse(None,self.mouse_x,self.height-self.paddle_height) for i in self.move_pieces: #print 'PieceMask:' #print self.hit_mask.PieceMask(i.y,i.height) for j in self.hit_mask.PieceMask(i.y,i.height): #print j # Problem -- if a piece occurs in more than one slice, we # may hit it twice. i.Hit(j) self.draw_pieces() if( self.points.IsOver() ): self.start_game() self.draw_all() else: self.redraw() # Handle redraw events. def OnRedraw(self,ev,x,y,w,h): self.redraw() # Handle keypress events. def OnKeyPress(self,ev,key,state): keystr = chr(key) if( keystr == 'n' ): self.is_demo = 0 self.points.AddPoints(-100000) if( keystr == 'd' ): self.is_demo = 1 # Handle mouse events. def add_ball(self,x,y): if( self.ball_count < 4 ): self.ball_count = self.ball_count + 1 self.move_pieces.append(Ball(self, self.hit_mask, x=self.paddle.x +(self.paddle.width/2)-4, y=self.paddle.y-8, width=self.ball_width, height=self.ball_width, xvel=self.paddle.xvel, yvel=-5, color=self.ball_color, pixmap=self.ball_pic)) def OnMouse(self,ev,x,y,state,hit): if( ev.Code == ihEvent.CodeNames['MousePress'] ): self.add_ball(x,y) if( not self.is_demo ): self.mouse_x = x self.mouse_y = y __export__ = ['ihEmbed']
Dianne Kyra Hackborn <hackbod@angryredplanet.com> | Last modified: Wed Aug 14 14:33:18 PDT 1996 |