def interact(self,player): # box can be broken from flopping if player.flopping == player.flop_stun and self.overlap(player.hit_box()): self.destroy(True) # get them goodies return # otherwise, indestructable platform Body.interact(self,player)
def __init__(self,position,color,line_color = (0,0,0),line_width = 2,floating=False): Body.__init__(self,position,self.size,True,True,[0,0]) self.shapes.append(Shape(self.self_shape(),color,line_color = line_color,line_width = line_width)) # add visible shape for box self.destruct_counter = -1 self.floating = floating self.fruit = 0 self.lives = 0 self.bounces = -1 self.hit_box = None # no hit box unless boom_box and exploding
def __init__(self, position, size, floating=False): Body.__init__(self, position, size, True, True, [0, 0]) self.destruct_counter = -1 self.hit_box = None # no hit box unless boom_box and exploding self.animate = 0 self.floating = floating self.direction = 1 self.switchers = [] self.animators = [] self.shift_path = [np.array([0, 0])] self.destroy_sound = fruit_sound
def move(self): if not self.floating and not isinstance( self.resting_on, Body) and self.solid and self.corporeal: self.vel[1] += G if isinstance(self, Looper): Looper.move(self) else: Body.move(self) if self.vel[0] != 0: self.direction = copysign(1.0, self.vel[0])
def draw(self, canvas, zero=np.array([0, 0])): self.animate += 1 + 3 * (any(self.vel != 0)) self.animate %= len(self.shift_path) for s in self.switchers: # switch eyes, wings, feet, etc depending on direction s[0].visible = self.direction == -1 s[1].visible = self.direction == 1 for a in self.animators: a.shift(self.shift_path[self.animate]) Body.draw(self, canvas, zero) for a in self.animators: a.shift(-self.shift_path[self.animate])
def interact(self, player): if player.overlap(self.hit_box): player.get_hit( ) # not using self.hit_player(player) because this should never kill baddie dim, gap = Body.overlap_dim(self, player) if dim == 1 and (self.pos[1] > player.pos[1]): # player on top self.destroy() player.bounce(-1) elif dim != -1: #otherwise touching is a problem for the player self.hit_player( player ) # invulnerability takes care of multiple hits from one interaction
def __init__(self, position): Body.__init__(self, position, protector_size, False, False, [0, 0]) self.shapes.append( Shape(self.self_shape([1.1, 1.1]), protector_color, None, line_width=2, visible=False)) self.shapes.append( Shape(self.self_shape(), protector_line_color, None, line_width=2)) self.shapes.append( Shape(self.self_shape([0.9, 0.9]), protector_color, None, line_width=2)) self.shapes.append( Shape(self.self_shape([0.1, 0.1]), eye_color, None, line_width=2)) self.shapes[-1].shift(self.size * [0.3, -0.3]) # eye facing one way self.shapes.append( Shape(self.self_shape([0.1, 0.1]), eye_color, None, line_width=2)) # add visible shape self.shapes[-1].shift(self.size * [-0.3, -0.3]) # eye facing the other way
def break_or_bounce(self,player): dim,side,converging = Body.interact(self,player) # solid interactions if dim == 1: # self and player collide vertically bounce = converging # must be converging to bounce if bounce and self.bounces>0: self.bounces -=1 # box breaks if last allowable bounce or it is falling break_box = (bounce and (self.bounces == 0 or self.vel[1]>0)) # edge cases where box must break: player on a solid object and hitting underside if side == 1 and isinstance(player.resting_on,Body): break_box = True bounce = False # no need to bounce player.jumping = 0 # no longer jumping, buddy return break_box, bounce*side # return side if bouncing else: # not colliding vertically, no break or bounce return False, False
def move(self): if not self.floating and not isinstance(self.resting_on,Body) and self.solid and self.corporeal: self.vel[1] += G Body.move(self)
def destroy(self, get_goodies=False): Body.destroy(self) # make non-corporeal # add goodies to the status if DESERVED self.player.current_status.gobble_box(self,get_goodies)
def draw(self,canvas,zero = np.array([0,0])): if self.destruct_counter == self.destruct_length: # remove box self.shapes[0].color = None self.shapes[0].line_color = None Body.draw(self,canvas,zero)
def play_level(num, keyboard, gameDisplay, clock, status): # Object holding all level Bodies and scenery level = Level(num) # right now level 0 # Object to determine what to draw on screen (anything non overlapping isn't drawn) screen = Body([level.player_start[0], display_size[1] / 2], np.array(display_size) / 2, corporeal=True, solid=False, velocity=[0, 0]) #level.background_list.append(screen2) death_delay = 60 # time after player's death that the level keeps tickin' crashed = 0 # start with a completed crash cycle to initalize everything paused = False # generate character character = Player(level.player_start) crashed = 0 level.reset() character.current_status = status game_over = False while not game_over: # play the game ############################################################################## # Note keyboard inputs and store them (including pausing) keyboard.handle_keys(pygame.event.get()) if keyboard.paused or keyboard.quit: # toggle pause if paused: if keyboard.quit: keyboard.quit = False break #quit! paused = not paused keyboard.paused = False keyboard.quit = False if paused: pause_menu.draw(gameDisplay) gameDisplay.blit(text, textRect) if not paused: ############################################################################## # Handle player death and level reset if crashed or character.pos[1] > ( 1.5 * display_size[1]): # player off screen = dead! if crashed == death_delay: # reset crash-o-meter crashed = 0 # restore everything since last checkpoint level.reset() # reset character's state, position, box count, and decrease lives character.reset() character.pos = level.player_start * 1.0 # gotta copy. character.current_status.counters[ 'boxes'] = level.boxes_killed # reset keyboard keyboard.reset() else: crashed += 1 if crashed == 2: # just died, play ouch sound! ouch_sound() if character.current_status.counters['lives'] == 0: game_over = True else: character.current_status.counters['lives'] -= 1 ############################################################################## # Move every non-player object and resolve their interactions, including explosions level.move_objects() level.explosions(character) # these can also affect character ############################################################################## # [if player is alive] Evolve its state, move it, and resolve interactions with other bodies if not crashed: # if player is dead, skip this part # determine player's state and velocity, then move character.evolve(keyboard) character.move() # sort box_list so that closest bodies interact first: prevents e.g. diagonally breaking boxes level.box_list = sorted(level.box_list, key=lambda x: sum( (character.pos - x.pos)**2), reverse=False) # squeeze = [[False,False],[False,False]] # all objects interact with the player (destroy boxes, get fruit, land on platforms, etc) level.interact(character) # some of these interactions might have killed ya. Then ya dead! if character.protection < 0: crashed = 1 ############################################################################## # Prepare canvas and draw visuals # fill display with sky color and set center position for screen (only overlapping objects will draw) gameDisplay.fill(level.sky) screen.pos = np.array([character.pos[0], display_size[1] / 2 ]) # location of the center of the screen # move all non-corporeal objects to the foreground, draw all bodies, and clean foreground list of dead objects level.draw_level(gameDisplay, screen, character) # game over! if game_over: pause_menu.draw(gameDisplay) gameDisplay.blit(text2, textRect2) # sleep(0.1) # turned on for debugging pygame.display.update() clock.tick(35)
import numpy as np #from time import sleep # Custom classes and functions from Super_Classes import Body, Shape from Player import Player from Constants import display_size, spikey_box, attack_color, character_color, eye_color from Level import Level from Make_Sounds import ouch_sound, thud_sound from os import path filepath = path.join(path.dirname(__file__), '') ## Define pause menu shapes and font pause_menu = Body(np.array(display_size) / 2, np.array(display_size) / 4) pause_menu.shapes.append( Shape(spikey_box([ pause_menu.size[0] + display_size[1] / 50, pause_menu.size[1] + display_size[1] / 50 ]), color=attack_color, line_color=(0, 0, 0), line_width=10)) pause_menu.shapes.append( Shape(pause_menu.self_shape(), color=character_color, line_color=None, line_width=10)) font = pygame.font.SysFont(filepath + 'freesansbold.ttf', int(pause_menu.size[1] * 0.8))
def explode(self): #second input not used, just to allow for polymorphism self.hit_box = Body(self.pos, self.size * self.explosion_size) boom_sound() # boom
def __init__(self, position): super().__init__(position, player_size, corporeal=True, solid=True, velocity=[0, 0]) self.crouching = False self.reset() self.shape_dict = { 'body': Shape(self.self_shape([0.95, 0.9]), character_color, line_color=None, line_width=None) } self.shape_dict['body'].shift([0, -self.size[1] * 0.1]) self.shape_dict['legs'] = Shape(self.self_shape([0.9, 0.01]), legs_color, line_color=None, line_width=None) self.shape_dict['legs'].shift([0, self.size[1] * .97]) self.shape_dict['legs'].nodes[-1] = (0, 0) self.shape_dict['crouch_body'] = Shape(self.self_shape(), character_color, line_color=None, line_width=None) self.shape_dict['hand'] = Shape(spikey_box(self.size * [0.2, 0.25], spike_sides=[0, 0, 1, 0]), hand_color, line_color=None, line_width=None) self.shape_dict['hand'].shift([0, self.size[1] * 0.3]) self.shape_dict['eye'] = Shape(self.self_shape([0.1, 0.1]), eye_color, line_color=None, line_width=None) self.shape_dict['eye'].shift([0, -self.size[1] * 0.7]) for i in self.shape_dict.values( ): # create standard list for holding shapes so they can be accessed both ways self.shapes.append(i) self.jump_anticipation = jump_anticipation self.jump_recency = 0 self.animate = 0 self.shift_path = animate_path(player_size[0] * np.array([0.05, 0.1]), [2.0, 4.0], animate_length) # hitbox for attack self.attack_box = Body([0, 0], player_size * attack_fraction, solid=False) # self.attack_box.shapes.append(Shape(self.attack_box.self_shape(),color = (255,0,0),line_color = None)) self.attack_box.shapes.append( Shape(spikey_box(self.attack_box.size, [1, 1, 1, 1]), color=attack_color, line_color=None)) # self.attack_box.shapes[-1].shift(self.attack_box.size*[0,-attack_fraction[1]+1.0]) # hitbox for slide self.slide_box = Body( [0, 0], player_size * np.array([slide_fraction, crouch_fraction * 0.9], dtype='float'), solid=False) self.slide_box.shapes.append( Shape(spikey_box(self.slide_box.size, [0, 1, 0, 1]), color=attack_color, line_color=None)) # add outline # hitbox for flop self.flop_box = Body( [0, 0], player_size * np.array([flop_width, crouch_fraction], dtype='float'), solid=False) self.flop_box.shapes.append( Shape(spikey_box(self.flop_box.size, [0, 0, 1, 0]), color=attack_color, line_color=None)) # add outline self.protector = Protector(self.pos - self.size * [self.direction, 1.0]) Box.player = self # all boxes are now linked to this player!
def draw(self, canvas, zero, direction): self.shapes[-1].visible = direction == -1 self.shapes[-2].visible = direction == 1 Body.draw(self, canvas, zero)