def random_spot_away_from_hero(hero, mindist = 20.0): """Calculate a random spot that is at least mindist away from the hero.""" dist = 0.0 # We use a brute-force: while we have not found a good point, choose a random # point and calculate its distance. Rinse and repeat until a good point is found. while dist < mindist: x, y = random(WIDTH), random(HEIGHT) dist = distance(x, y, hero.x, hero.y) return x, y
def update(self, hero, blobs): # Increase and decrease the size based on the speed of the blob self.size = abs(sin(self.seed+FRAME/(5.0-self.speed*2.0)) * 2.0+self.seed) + 4.0 # This code implements the chase behaviour of the blobs. # First, calculate the angle between ourselves and the hero self.angle = angle(self.x, self.y, hero.x, hero.y) # Then, move in that direction using the moving speed self.x, self.y = coordinates(self.x, self.y, self.speed, self.angle) # Calculate if I'm not bumping into another blob. If I am, calculate a new # jump to an empty spot on the board. for blob in blobs: if blob is not self and abs(distance(self.x, self.y, blob.x, blob.y)) < blob.size*2: self.x, self.y = random_spot_away_from_hero(hero)
def draw(): global hero, blobs, gameover, starttime, endtime # To make things a little more interesting, we rotate and scale the canvas while # the game is running. For this to work, we need corner-mode transformations. transform(CORNER) # Move to the middle of the screen to set the rotation. This makes sure the rotation # isn't applied from a corner, but from the middle of the screen. translate(WIDTH/2, HEIGHT/2) # The rotation amount and speed is linked to the current FRAME. The farther in the game, # the faster and bigger the rotation gets rotate(sin(FRAME/70.0)*FRAME/10.0) # The speed of the saling is also linked to the current FRAME. scale(0.6 + abs(sin(FRAME/100.0)*0.4)) # Move the canvas back. The rotation is now applied. translate(-WIDTH/2, -HEIGHT/2) # Draw a rectangle, defining the playing field stroke(0) nofill() rect(0,0,WIDTH,HEIGHT-STATUS_BAR_HEIGHT) nostroke() # The following functions apply when the game is not over, # in other words when we are still playing. if not gameover: # Check the keys and move the hero accordingly. # The min and max lines keep the hero within the bounds # of the playing field if keydown: if keycode == KEY_UP: hero.y -= hero.speed hero.y = max(hero.size, hero.y) if keycode == KEY_DOWN: hero.y += hero.speed hero.y = min(WIDTH-hero.size, hero.y) if keycode == KEY_LEFT: hero.x -= hero.speed hero.x = max(hero.size, hero.x) if keycode == KEY_RIGHT: hero.x += hero.speed hero.x = min(WIDTH-hero.size, hero.x) # Update the blobs. This part is the actual "intelligence" of the game. # This routine also calculates if one of the blobs hits your hero, in # which case the game is over. for blob in blobs: blob.update(hero, blobs) if abs(distance(hero.x, hero.y, blob.x, blob.y)) < blob.size + hero.size: gameover = True # The endtime stores how long we survived. endtime = time.time() # Draw everything. This is done even when the game is over. hero.draw() for blob in blobs: blob.draw() # The status indicators are drawn on-screen without all the funky rotations # and scaling. Reset the canvas. reset() # The time to display is either the endtime (on gameover), or the current time. if endtime is not None: t = endtime - starttime else: t = time.time()-starttime # Draw the time fontsize(12) fill(0,0.6) rect(0,HEIGHT-STATUS_BAR_HEIGHT, WIDTH, STATUS_BAR_HEIGHT) fill(1) text("%.2f seconds" % t, 5, HEIGHT-2) # If the game is over, scale up the hero to get a black screen # and draw the "GAME OVER" message if gameover: if hero.size < 500: hero.size += 30.0 fill(1) text("GAME OVER", (WIDTH/2.0)-textwidth("game over")/2.0, HEIGHT/2)