def initSounds(self): #Hit sound from: #https://www.freesound.org/people/radiopassiveboy/sounds/219266/ self.soundHit = Sound("SFX/hit.ogg") #Mistake sound from: #https://www.freesound.org/people/zerolagtime/sounds/49238/ self.soundMiss = Sound("SFX/miss.ogg")
def __init__(self): Screen.__init__(self) self.sel = (0, 0) self.options = {"AUDIO": (("Play", lambda: Settings.AUDIO == 1, lambda: setattr(Settings, "AUDIO", 1) or Sound.cycleMusic()), ("Mute", lambda: Settings.AUDIO == 0, lambda: setattr(Settings, "AUDIO", 0) or Sound.stop_all(False))), "GRAPHICS": (("High", lambda: Settings.GRAPHICS == 2, lambda: setattr(Settings, "GRAPHICS", 2)), ("Medium", lambda: Settings.GRAPHICS == 1, lambda: setattr(Settings, "GRAPHICS", 1)), ("Low", lambda: Settings.GRAPHICS == 0, lambda: setattr(Settings, "GRAPHICS", 0))), "~": (("Return to Main Menu", lambda: False, lambda: MainMenu),)}
def play(self, audio_file): if self._is_playing: return try: self._is_playing = 1 self._snd = Sound.open(audio_file) if self._snd.state() == EOpen: self._snd.stop() # Avoids runtime errors self._snd.play(callback=self._stop()) except Exception, e: # NOTE: Log the error properly # debug('[Audio] - %s' % (str(e)), level='error') pass
def tick(self, surface, delta, fontmap): scr = None # Paint the background surface.fill(pygame.color.Color("#222222")) # Paint title go = fontmap["title"].render("Credits", True, pygame.color.Color("#FFFFFF")) (w, h) = fontmap["title"].size("Credits") surface.blit(go, (Constants.WIDTH // 2 - w // 2, 60)) # Paint the sections yoff = -200 for section in ("krx\nProgrammer and Special Effects", "RedSoxFan\nProgrammer", "Spetsnaz\nGame Idea", "s.a.x Software\nSaxMono Font", "Game Made In\nPython with pygame", "Sound Effects Made In\nBFXR + LabChirp", "Music By\nSiriusBeat", "EXE Creation\npy2exe with pygame2exe script"): for i, text in enumerate(section.split("\n")): ttype = "msgtitle" if i == 0 else "msgbody" col = pygame.color.Color("#CCCCCC" if ttype == "msgtitle" else "#888888") sc = fontmap[ttype].render(text, True, col) (w, h) = fontmap[ttype].size(text) surface.blit(sc, (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT // 2 - h // 2 + yoff)) yoff += h + 2 yoff += 15 # Paint the return to main menu message txt = "Press <enter> to return to the Main Menu" msg = fontmap["hud"].render(txt, True, pygame.color.Color("#999999")) (w, h) = fontmap["hud"].size(txt) surface.blit(msg, (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT - h - 10)) # Check to see if enter is pressed if Keyboard.released(pygame.K_RETURN): Sound.play('menuselect') scr = MainMenu return scr
def tick(self, surface, delta, fontmap): scr = None # Paint the background surface.fill(pygame.color.Color("#222222")) # Paint the title ttl = fontmap["title"].render(Constants.TITLE, True, pygame.color.Color("#FFFFFF")) (w, h) = fontmap["title"].size(Constants.TITLE) surface.blit(ttl, (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT // 4 + h // 2)) # Paint the options msel = -1 for i, option in enumerate(MainMenu.options): # Get the bounding box (w, h) = fontmap["option"].size(option) (x, y) = (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT // 2 + i * h * 2) # Determine if the option is highlighted or if the mouse is hovering over it m = Mouse.getX() in xrange(x, x + w) and Mouse.getY() in xrange(y, y + h) msel = i if m else msel s = self.sel == i or m # Paint the option txt = fontmap["option"].render(option, True, pygame.color.Color("#00FF00" if s else "#CCCCCC")) surface.blit(txt, (x, y)) # Check for input if len(MainMenu.options) > 0: if Keyboard.released(pygame.K_DOWN): # If not at bottom, move the selection down Sound.play('menumove') self.sel = min(self.sel + 1, len(MainMenu.options) - 1) elif Keyboard.released(pygame.K_UP): # If not at top, move the selection up Sound.play('menumove') self.sel = max(0, self.sel - 1) elif Keyboard.released(pygame.K_RETURN): # Select the highlighted option Sound.play('menuselect') scr = MainMenu.screens[self.sel] elif msel >= 0 and Mouse.leftReleased(): # Select the option that mouse is hovering over Sound.play('menuselect') scr = MainMenu.screens[msel] return scr
def __init__(self): """Initialize running class.""" self.config = ConfigParser() self.config.read('settings.ini') self.size_x = self.config.getint('screen', 'size_x') self.size_y = self.config.getint('screen', 'size_y') with open('languages.dat', 'rb') as lang_file: self.phrases = pickle.load(lang_file)[self.config.get( 'total', 'language')] self.speech = Speech(self.config) self.speech.speak(self.phrases['start']) pygame.init() pygame.font.init() pygame.mixer.init() self.screen = pygame.display.set_mode((self.size_x, self.size_y)) pygame.display.set_caption(self.phrases['title']) self.music = Music(self.config.getfloat('audio', 'music_volume')) self.sounds = Sound(self.config.getfloat('audio', 'sound_volume')) self.board = Board(self.config, self.screen, self.sounds) self.player = Player(self.board, self.speech, self.phrases) self.game_over = True self.win = False self.STOPPED_PLAYING = pygame.USEREVENT + 1 pygame.mixer.music.set_endevent(self.STOPPED_PLAYING) self.fontObj = pygame.font.SysFont('arial', 50) self.clock = pygame.time.Clock() random.seed() self.music_play() self.new_game()
def __init__(self, z=0, x=0, y=0, enemy=None): super().__init__(z, x, y) # This unit's health self.health = 100 self.heart_rate = 10 # lower = faster heart animation speed self.bullets = [] self.blocks = pygame.sprite.Group( ) # What sprites am I not allowd to cross? self.interactables = pygame.sprite.Group() self.hazards = [] # similar to interactables but dangerous! self.enemies = pygame.sprite.Group() self.stepTile = 0 self.direction = 0 self.angle = 0 self.last_hit = pygame.time.get_ticks() self.move_timer = pygame.time.get_ticks() self.moveSpeed = 150 self.delta = 512 self.screen = None self.sounds = Sound() self.walk_sound = pygame.mixer.Sound('../assets/player/walk.wav') self.walk_timer = pygame.time.get_ticks() self.room = None # Where the player is positioned self.x = x self.y = y self.camera = None self.items = None # set up by in engine in game.py self.inventory = {0: "None"} self.active_item = 0 self.sheet = Spritesheet_Ext( '../assets/map assets/sprite sheets/Horror City - Frankenstein MV/Characters/$Dr Frankenstien.png', 32, 48, 3, 4, 4, [96, 188], .5) self.sprites = self.sheet.sprites self.image = self.sprites[self.stepTile].image # timers self.shoot_timer = 20 self.shoot_counter = self.shoot_timer self.spotted_timer = 30 self.spotted_counter = self.spotted_timer self.interaction_timer = 20 self.interaction_counter = self.interaction_timer self.interaction_counter_prev = -1 self.interaction_timeout = 10 # raycast init self.raycast_increments = 15 self.raycast_points = [ 0 for i in range(360 // self.raycast_increments) ] self.sight_coords = [(-1, -1), (-1, -1), (-1, -1), (-1, -1)] self.rect = self.image.get_rect( center=(self.x, self.y) ) # the players collision mask, this determines when the player collides with things self.rect.width = self.rect.width // 2 self.rect.height = self.rect.height // 2 # How big the world is, so we can check for boundries self.world_size = (Settings.width, Settings.height) # Which collision detection function? self.collide_function = pygame.sprite.collide_rect self.collisions = [] # For collision detection, we need to compare our sprite # with collideable sprites. However, we have to remap # the collideable sprites coordinates since they change. # For performance reasons I created this sprite so we # don't have to create more memory each iteration of # collision detection. self.collider = Drawable() self.collider.image = pygame.Surface( [Settings.tile_size, Settings.tile_size]) self.collider.rect = pygame.Rect(0, 0, 16, 16) self.cpoint = Drawable() self.cpoint.image = pygame.Surface( [Settings.tile_size, Settings.tile_size]) self.cpoint.rect = pygame.Rect(0, 0, 1, 1) # Overlay self.font = pygame.font.Font('freesansbold.ttf', 32) self.overlay = self.font.render( str(self.health) + " 4 lives", True, (0, 0, 0))
class Player(Character): """This is a sample class for a player object. A player is a character, is a drawable, and an updateable object. This class should handle everything a player does, such as moving, throwing/shooting, collisions, etc. It was hastily written as a demo but should direction. """ def __init__(self, z=0, x=0, y=0, enemy=None): super().__init__(z, x, y) # This unit's health self.health = 100 self.heart_rate = 10 # lower = faster heart animation speed self.bullets = [] self.blocks = pygame.sprite.Group( ) # What sprites am I not allowd to cross? self.interactables = pygame.sprite.Group() self.hazards = [] # similar to interactables but dangerous! self.enemies = pygame.sprite.Group() self.stepTile = 0 self.direction = 0 self.angle = 0 self.last_hit = pygame.time.get_ticks() self.move_timer = pygame.time.get_ticks() self.moveSpeed = 150 self.delta = 512 self.screen = None self.sounds = Sound() self.walk_sound = pygame.mixer.Sound('../assets/player/walk.wav') self.walk_timer = pygame.time.get_ticks() self.room = None # Where the player is positioned self.x = x self.y = y self.camera = None self.items = None # set up by in engine in game.py self.inventory = {0: "None"} self.active_item = 0 self.sheet = Spritesheet_Ext( '../assets/map assets/sprite sheets/Horror City - Frankenstein MV/Characters/$Dr Frankenstien.png', 32, 48, 3, 4, 4, [96, 188], .5) self.sprites = self.sheet.sprites self.image = self.sprites[self.stepTile].image # timers self.shoot_timer = 20 self.shoot_counter = self.shoot_timer self.spotted_timer = 30 self.spotted_counter = self.spotted_timer self.interaction_timer = 20 self.interaction_counter = self.interaction_timer self.interaction_counter_prev = -1 self.interaction_timeout = 10 # raycast init self.raycast_increments = 15 self.raycast_points = [ 0 for i in range(360 // self.raycast_increments) ] self.sight_coords = [(-1, -1), (-1, -1), (-1, -1), (-1, -1)] self.rect = self.image.get_rect( center=(self.x, self.y) ) # the players collision mask, this determines when the player collides with things self.rect.width = self.rect.width // 2 self.rect.height = self.rect.height // 2 # How big the world is, so we can check for boundries self.world_size = (Settings.width, Settings.height) # Which collision detection function? self.collide_function = pygame.sprite.collide_rect self.collisions = [] # For collision detection, we need to compare our sprite # with collideable sprites. However, we have to remap # the collideable sprites coordinates since they change. # For performance reasons I created this sprite so we # don't have to create more memory each iteration of # collision detection. self.collider = Drawable() self.collider.image = pygame.Surface( [Settings.tile_size, Settings.tile_size]) self.collider.rect = pygame.Rect(0, 0, 16, 16) self.cpoint = Drawable() self.cpoint.image = pygame.Surface( [Settings.tile_size, Settings.tile_size]) self.cpoint.rect = pygame.Rect(0, 0, 1, 1) # Overlay self.font = pygame.font.Font('freesansbold.ttf', 32) self.overlay = self.font.render( str(self.health) + " 4 lives", True, (0, 0, 0)) def get_x(self): return self.rect.x def get_y(self): return self.rect.y def move_left(self, time): self.angle = 180 now = pygame.time.get_ticks() if now - self.move_timer < self.moveSpeed: return self.get_animation(1) amount = self.delta * time try: if self.x - amount < 0: raise OffScreenLeftException else: self.x = self.x - amount now = pygame.time.get_ticks() if now - self.walk_timer > 300: self.walk_sound.play() self.walk_timer = now self.update(0) while (len(self.collisions) != 0): self.x = self.x + amount self.update(0) except: pass def move_right(self, time): self.angle = 0 now = pygame.time.get_ticks() if now - self.move_timer < self.moveSpeed: return self.get_animation(2) self.collisions = [] amount = self.delta * time try: if self.x + amount > self.world_size[0] - Settings.tile_size: raise OffScreenRightException else: self.x = self.x + amount now = pygame.time.get_ticks() if now - self.walk_timer > 300: self.walk_sound.play() self.walk_timer = now self.update(0) while (len(self.collisions) != 0): self.x = self.x - amount self.update(0) except: pass def move_up(self, time): self.angle = 270 now = pygame.time.get_ticks() if now - self.move_timer < self.moveSpeed: return self.get_animation(3) self.collisions = [] amount = self.delta * time try: if self.y - amount < 0: raise OffScreenTopException else: self.y = self.y - amount now = pygame.time.get_ticks() if now - self.walk_timer > 300: self.walk_sound.play() self.walk_timer = now self.update(0) if len(self.collisions) != 0: self.y = self.y + amount self.update(0) self.collisions = [] except: pass def move_down(self, time): self.angle = 90 now = pygame.time.get_ticks() if now - self.move_timer < self.moveSpeed: return self.get_animation(0) self.collisions = [] amount = self.delta * time try: if self.y + amount > self.world_size[1] - Settings.tile_size: raise OffScreenBottomException else: self.y = self.y + amount now = pygame.time.get_ticks() if now - self.walk_timer > 300: self.walk_sound.play() self.walk_timer = now self.update(0) if len(self.collisions) != 0: self.y = self.y - amount self.update(0) self.collisions = [] except: pass def get_animation(self, dir): self.move_timer = pygame.time.get_ticks() if self.direction != dir: self.direction = dir self.stepTile = 0 + (3 * dir) else: self.stepTile = ((self.stepTile + 1) % 3) + (3 * dir) self.image = self.sprites[self.stepTile].image def lineofsight_raycast(self, length, direction, precise=0): xx = int(self.rect.x + 16) yy = int(self.rect.y + 16) r = radians(direction) dirx = int(cos(r)) diry = int(sin(r)) # necessary for light raycasting if precise: dirx = cos(r) diry = sin(r) # find where the raycast SHOULD end up assuming nothing blocking it end_position = (xx + dirx * length, yy + diry * length) tempx = xx tempy = yy # loop through all positions in range for i in range(0, length, 8): self.cpoint.x = self.cpoint.rect.x = tempx self.cpoint.y = self.cpoint.rect.y = tempy # line of sight runs into wall if pygame.sprite.spritecollideany(self.cpoint, self.blocks) != None: end_position = (tempx, tempy) break # line of sight runs into enemy elif pygame.sprite.spritecollideany( self.cpoint, self.enemies) != None and not precise: # find the specific enemy that has spotted the player for enemy in self.enemies: # check if the correct enemy has been found if pygame.sprite.collide_rect(self.cpoint, enemy): if not dirx: self.spotted_by_enemy( enemy, 0, copysign(-1, enemy.y - self.y)) # set enemy state else: self.spotted_by_enemy( enemy, copysign(1, enemy.x - self.x), 0) end_position = (xx, yy) break tempx = xx + dirx * i tempy = yy + diry * i return end_position def light_raycast(self, length): for i in range(0, 360, self.raycast_increments): direction = i condition0 = (self.angle == 0 and (i >= 330 or i <= 30)) condition90 = (self.angle == 90 and (i <= 120 and i >= 60)) condition180 = (self.angle == 180 and (i <= 210 and i >= 150)) condition270 = (self.angle == 270 and (i <= 300 and i >= 240)) # extend the raycast if near player movement direction if condition0 or condition90 or condition180 or condition270: ray = self.lineofsight_raycast(length * 3, direction, 1) self.raycast_points[i // self.raycast_increments] = ray else: ray = self.lineofsight_raycast(length, direction, 1) self.raycast_points[i // self.raycast_increments] = ray def lineofsight_right(self, length): self.sight_coords[0] = self.lineofsight_raycast(length, 0) return self.sight_coords[0] def lineofsight_left(self, length): self.sight_coords[1] = self.lineofsight_raycast(length, 180) return self.sight_coords[1] def lineofsight_up(self, length): self.sight_coords[2] = self.lineofsight_raycast(length, 90) return self.sight_coords[2] def lineofsight_down(self, length): self.sight_coords[3] = self.lineofsight_raycast(length, 270) return self.sight_coords[3] def spotted_by_enemy(self, enemy, dirx, diry): # the 'trapped' state is state 3, enemies should be unable to move in this case if enemy.state == 3: return enemy.state = 2 # enemy chase state is 2 enemy.sight_counter = enemy.sight_timeout # reset the enemy chase timer enemy.target = self enemy.dirx = dirx # target x direction to move to enemy.diry = diry # target y direction to move to # increase heart rate and set counter for when to catch breath self.spotted_counter = self.spotted_timer self.heart_rate = 3 return def interact(self, time): # check to make sure the player is in range of an interactable object if not pygame.sprite.spritecollideany(self, self.interactables): return # check for interaction buffer if self.interaction_counter > self.interaction_timer: return # player must wait before another action # set the interaction timer, must be held to complete action if self.interaction_counter <= 0: self.interaction_counter = self.interaction_timer + 10 # reset interaction timer self.interaction_timeout = 10 # loop through the interactable sprite group for sprite in self.interactables: if pygame.sprite.collide_rect(self, sprite): # check for door opening case if sprite.isDoor == 1: self.sounds.play_door_sound() sprite.changeRoom() # run the door opening code return self.inventory[self.active_item] = sprite.contents else: # decrement timer self.interaction_counter -= 1 def use_active_item(self, time): # get direction player is facing, important for placing items r = radians(self.direction) tarx = self.rect.x + int(cos(r)) * 3 tary = self.rect.y + int(sin(r)) * 3 # beartrap use code if self.inventory[self.active_item] == "beartrap": self.create_physical_item(0, 1, BearTrap(tarx, tary)) # lantern use code elif self.inventory[self.active_item] == "lantern": self.create_physical_item(0, 0, Lantern(tarx - 64, tary - 64)) # rancid meat elif self.inventory[self.active_item] == "rancidmeat": self.create_physical_item(0, 1, RancidMeat(tarx, tary)) self.inventory[ self.active_item] = "None" # empty out the current inventory slot def create_physical_item(self, impassable, hazard, item): if impassable: self.blocks.append(item) if hazard: self.hazards.append(item) # add a new object to the list of entities created from user input self.items.append(item) def reset_all_timers(self): self.shoot_counter = self.shoot_timer self.spotted_counter = self.spotted_timer self.interaction_counter = self.interaction_timer def update(self, time): if (self.sight_coords[0][0] < 0): # light raycasts stuff (drawing happens in engine!) self.light_raycast(50) # events which should not occur on every update call if time != 0: self.shoot_counter -= 1 self.spotted_counter -= 1 if self.spotted_counter <= 0: self.heart_rate = 10 # necessary counter buffer so the player can't spam interactions # all other interaction updates occur in the interaction function if self.interaction_counter > self.interaction_timer: self.interaction_counter -= 1 # run all line of sight raycasts self.lineofsight_right(200) self.lineofsight_left(200) self.lineofsight_up(200) self.lineofsight_down(200) # light raycasts stuff (drawing happens in engine!) self.light_raycast(50) # check for redundant action meter display elif self.interaction_counter < self.interaction_timer: keys_pressed = pygame.key.get_pressed() # get all pressed keys # check to make sure the player is still pressing the interact button if keys_pressed[pygame.K_e] != 1: # if the action meter is display (meaning the player pressed e) but has stopped pressing the interact button # change the counter values so that the overlay stops showing the action meter self.interaction_counter = self.interaction_timer + 10 # collision stuffs self.collisions = [] prevrect = (self.get_x(), self.get_y()) self.collider.x = self.collider.rect.x = self.rect.x = self.x self.collider.y = self.collider.rect.y = self.rect.y = self.y for sprite in self.blocks: self.collider.rect.x = sprite.x self.collider.rect.y = sprite.y if pygame.sprite.collide_rect(self, self.collider): self.collisions.append(sprite) if pygame.sprite.spritecollideany(self, self.enemies): self.reset_room() def ouch(self): now = pygame.time.get_ticks() if now - self.last_hit > 1000: self.health = self.health - 10 self.last_hit = now def reset_room(self): self.room.engine.changeRoom(self.room.current_room) self.x = self.resetx self.y = self.resety def getX(self): return self.x def getY(self): return self.y
def tick(self, surface, delta, platforms): msgs = [] if self.disphealth > self.health: self.disphealth = Arithmetic.clamp(self.health, self.maxhealth, self.disphealth - ceil((self.disphealth - self.health) / 30.0)) if Settings.GRAPHICS >= 2 and self.innerfire: self.generateInnerFire() # If alive, tick if self.health > 0: # Check for a resize if Keyboard.down(Constants.GROW_KEY): width = min(self.rect.width + Constants.SIZE_INTERVAL, Constants.MAX_PLAYER_WIDTH) height = min(self.rect.height + Constants.SIZE_INTERVAL, Constants.MAX_PLAYER_HEIGHT) self.image = pygame.transform.scale(self.image, (width, height)).convert_alpha() center = self.rect.center self.rect.size = self.image.get_rect().size self.rect.center = center self.__draw_image() elif Keyboard.down(Constants.SHRINK_KEY): width = max(Constants.MIN_PLAYER_WIDTH, self.rect.width - Constants.SIZE_INTERVAL) height = max(Constants.MIN_PLAYER_HEIGHT, self.rect.height - Constants.SIZE_INTERVAL) self.image = pygame.transform.scale(self.image, (width, height)).convert_alpha() center = self.rect.center self.rect.size = self.image.get_rect().size self.rect.center = center self.__draw_image() # If not in the center, fall to center of the screen if self.rect.centery < Constants.HEIGHT // 4: self.rect.y += ceil(Constants.GRAVITY / Constants.FPS * delta) self.rect.y = min(Constants.HEIGHT // 4, self.rect.y) else: self.ready = True # Check collision with platforms for p in pygame.sprite.spritecollide(self, platforms, False): if not p.can_break(self.force): msgs.append(Message("Splat\n-%d" % self.health, self.rect.right + 100, self.rect.centery, "bad")) self.health = 0 break elif p.can_splinter(self.force): Sound.play('hit{}'.format(randint(1, 3))) self.health = max(0, self.health - p.damage) self.destroyPlatform(p, True) p.kill() msgs.append(Message("Splinter\n-%d" % p.damage, self.rect.right + 100, self.rect.centery, "bad")) else: Sound.play('hit{}'.format(randint(1, 3))) self.destroyPlatform(p, False) p.kill() else: # Death sequence if self.rect.width > 2: # Shrink until tiny width = Arithmetic.clamp(2, Constants.MAX_PLAYER_WIDTH, self.rect.width - 3 * Constants.SIZE_INTERVAL) height = Arithmetic.clamp(2, Constants.MAX_PLAYER_HEIGHT, self.rect.height - 3 * Constants.SIZE_INTERVAL) self.image = pygame.transform.scale(self.image, (width, height)).convert_alpha() center = self.rect.center self.rect.size = self.image.get_rect().size self.rect.center = center self.__draw_image() elif not self.sploded: # splode Sound.play('explode') self.sploded = True self.innerfire = False self.image.fill(pygame.Color(0, 0, 0)) # Line particles for i in xrange(randint(20, 40)): angle = random() * 2.0 * pi speed = random() * 5.0 + 2.5 rotRate = random() * (0.5 * pi) - (0.25 * pi) size = randint(3, 17) self.particles.append(FlippyLineParticle([self.rect.center[0], self.rect.center[1]], size, [speed * cos(angle), speed * sin(angle)], pygame.Color(0, 255, 0), random() * 2.0 * pi, rotRate, mingfx=1)) # Fire particles for i in xrange(randint(200, 500)): angle = random() * 2.0 * pi speed = random() * 5.0 + 1.0 size = randint(1, 3) self.particles.append(FadingParticle([self.rect.center[0], self.rect.center[1]], size, [speed * cos(angle), speed * sin(angle)], pygame.Color(0, 255, 0), 6, mingfx=1)) # If on screen, paint if self.rect.bottom > 0: surface.blit(self.image, (self.rect.x, self.rect.y)) return msgs
def tick(self, surface, delta, fontmap): scr = None # Paint the background surface.fill(pygame.color.Color("#222222")) # Paint title go = fontmap["title"].render("Info", True, pygame.color.Color("#FFFFFF")) (w, h) = fontmap["title"].size("Info") surface.blit(go, (Constants.WIDTH // 2 - w // 2, 100)) # Paint the sections yoff = 200 for section in ("Objective\nTo get as far down the abyss as possible", "Controls\nUp Arrow - Grow\nDown Arrow - Shrink", "How To Play\n[Grow or shrink the player to either reduce or increase force. You " "will need to have enough force to break the platform (40% of the width). If you " "don't, you will splat and die. Also, if you have enough force to break the " "platform, but not cleanly (60% of the width), you will cause the platform " "to splinter, which will damage you.]"): for i, text in enumerate(section.split("\n")): ttype = "msgtitle" if i == 0 else "msgbody" col = pygame.color.Color("#CCCCCC" if ttype == "msgtitle" else "#888888") if text.startswith("[") and text.endswith("]"): words = text[1:-1].split(" ") text = "" while len(words) > 0: (w, h) = fontmap[ttype].size("%s %s" % (text, words[0])) if w < Constants.WIDTH - 20: text = "%s %s" % (text, words[0]) words = words[1:] else: sc = fontmap[ttype].render(text, True, col) (w, h) = fontmap[ttype].size(text) surface.blit(sc, (Constants.WIDTH // 2 - w // 2, yoff)) yoff += h + 2 text = "" if len(text) > 0: sc = fontmap[ttype].render(text, True, col) (w, h) = fontmap[ttype].size(text) surface.blit(sc, (Constants.WIDTH // 2 - w // 2, yoff)) yoff += h + 2 else: # Line sc = fontmap[ttype].render(text, True, col) (w, h) = fontmap[ttype].size(text) surface.blit(sc, (Constants.WIDTH // 2 - w // 2, yoff)) yoff += h + 2 yoff += 20 # Paint the return to main menu message txt = "Press <enter> to return to the Main Menu" msg = fontmap["hud"].render(txt, True, pygame.color.Color("#999999")) (w, h) = fontmap["hud"].size(txt) surface.blit(msg, (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT - h - 10)) # Check to see if enter is pressed if Keyboard.released(pygame.K_RETURN): Sound.play('menuselect') scr = MainMenu return scr
def tick(self, surface, delta, fontmap): scr = None # Paint the background surface.fill(pygame.color.Color("#222222")) # Paint the title ttl = fontmap["title"].render("Settings", True, pygame.color.Color("#FFFFFF")) (w, h) = fontmap["title"].size("Settings") surface.blit(ttl, (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT // 4 + h // 2)) # Paint the options mcb = None yoff = 0 for i, key in enumerate(sorted(self.options.keys())): # Get the bounding box (w, h) = fontmap["msgtitle"].size(key.replace("~", "")) (x, y) = (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT // 2 + yoff) # Paint the option txt = fontmap["msgtitle"].render(key.replace("~", ""), True, pygame.color.Color("#CCCCCC")) surface.blit(txt, (x, y)) yoff += h + 2 for j, (txt, val, cb) in enumerate(self.options[key]): # Get the bounding box (w, h) = fontmap["msgbody"].size(txt) (x, y) = (Constants.WIDTH // 2 - w // 2, Constants.HEIGHT // 2 + yoff) # Determine if the option is highlighted or if the mouse is hovering over it m = Mouse.getX() in xrange(x, x + w) and Mouse.getY() in xrange(y, y + h) mcb = cb if m else mcb s = self.sel == (i, j) or m # Paint the option col = "#008800" if val() else "#CCCCCC" txt = fontmap["msgbody"].render(txt, True, pygame.color.Color("#00FF00" if s else col)) surface.blit(txt, (x, y)) yoff += h + 2 yoff += 20 # Check for input if len(MainMenu.options) > 0: if Keyboard.released(pygame.K_DOWN): # If not at bottom, move the selection down if self.sel[1] < len(self.options[sorted(self.options.keys())[self.sel[0]]]) - 1: self.sel = (self.sel[0], self.sel[1] + 1) Sound.play('menumove') elif self.sel[0] < len(self.options.keys()) - 1: self.sel = (self.sel[0] + 1, 0) Sound.play('menumove') elif Keyboard.released(pygame.K_UP): # If not at top, move the selection up if self.sel[1] > 0: self.sel = (self.sel[0], self.sel[1] - 1) Sound.play('menumove') elif self.sel[0] > 0: self.sel = (self.sel[0] - 1, len(self.options[sorted(self.options.keys())[self.sel[0] - 1]]) - 1) Sound.play('menumove') elif Keyboard.released(pygame.K_RETURN): # Select the highlighted option scr = self.options[sorted(self.options.keys())[self.sel[0]]][self.sel[1]][2]() Sound.play('menuselect') elif mcb is not None and Mouse.leftReleased(): # Select the option that mouse is hovering over scr = mcb() Sound.play('menuselect') return scr
def __init__(self): """Initialize running class.""" self.config = ConfigParser() self.config.read('settings.ini') if self.config.getboolean('total', 'debug'): if getattr(sys, 'frozen', False): self.logger = Logger( os.path.join(os.path.dirname(sys.executable), self.__class__.__name__)) else: self.logger = Logger( os.path.join(os.getcwd(), self.__class__.__name__)) self.log = logging.getLogger() self.log.info(__name__ + ': ' + 'def ' + self.__init__.__name__ + '(): ' + self.__init__.__doc__) self.size_x = self.config.getint('screen', 'size_x') self.size_y = self.config.getint('screen', 'size_y') with open('languages.dat', 'rb') as lang_file: self.phrases = pickle.load(lang_file)[self.config.get( 'total', 'language')] self.speech = Speech(self.config) self.speech.speak(self.phrases['start'], True) pygame.init() pygame.font.init() pygame.mixer.init() self.screen = pygame.display.set_mode((self.size_x, self.size_y)) pygame.display.set_caption(self.phrases['title']) self.music = Music(self.config.getfloat('audio', 'music_volume')) self.sounds = Sound(self.config.getfloat('audio', 'sound_volume')) self.menu = Menu(self.config, self.screen, self.speech, self.phrases, self.sounds) self.menu_flag = True menu_functions = [self.new_game, self.rules, self.help, self.exit] self.menu.set_functions(menu_functions) self.board = Board(self.config, self.screen, self.sounds) self._ai = AI(self.board, self.speech, self.phrases) self.player = Player(self.board, self.speech, self.phrases, self._ai) self._ai.gamer = self.player self._ai.player.behaviors.set_controllers(self._ai) self.running = True self.game_over = True self.win = False self.handle_numbers = {'K_' + str(num): num for num in range(1, 10)} self.handle_numbers.update( {'K_KP' + str(num): num for num in range(1, 10)}) self.font_obj = pygame.font.SysFont('arial', 50) self.clock = pygame.time.Clock() self.music_play() self.menu.activate(self.menu_flag)
# Copyright (c) 2005 Nokia Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import e32 from audio import Sound SLEEP = 7 player = Sound() player.open(u'c:\\Baby_One_More_Time.mid') player.play() e32.ao_sleep(SLEEP - 2) player.stop() #does not close the file player.open(u'c:\\foobar.wav') player.record() e32.ao_sleep(SLEEP) player.stop() player.close() #needed for sound flushing, otherwise not written
class PygameGame(object): def __init__(self, width=1500, height=850,fps=60, title="My Game"): (self.width, self.height) = (width, height) self.fps = fps self.title = title iconPath = os.path.normpath("Pictures/icon.png") self.icon = pygame.image.load(iconPath) self.initModes() self.initBeats() self.initTracking() #Create an event that will trigger when the song finishes. self.PLAYBACK_END = pygame.USEREVENT + 1 #Global delay of 450ms seems the best, as there is a noticeable delay #in pygame audio otherwise. #Need to start time a second early because we add a beat a second early. self.audioDelay = -1.45 self.timeElapsed = 0 + self.audioDelay #We want the game to end a bit after the song playback ends, so we add #a delayed end timer self.endDelay = 2.0 self.countdown = None #Preinitializing with this buffer value helps with audio lag. pygame.mixer.pre_init(buffer=1024) pygame.mixer.init() self.initSounds() pygame.display.set_icon(self.icon) pygame.init() pygame.font.init() def initTracking(self): self.combo = 0 self.maxCombo = 0 self.score = 0 self.prevAddition = 0 self.lastBeatHit = (0, 0) self.hits = pygame.sprite.Group() self.hitKill = 0.5 def initModes(self): self.inGame = True self.inMenu = True self.songSelect = False self.instructions = False self.playSong = False self.scoreScreen = False self.paused = False self.error = False def initMenu(self): #Needed for copy/paste support. pygame.scrap.init() #Menu picture from: https://goo.gl/bwppX2 path = "Pictures/menu.png" path = os.path.normpath(path) self.menu = pygame.image.load(path) self.menu.convert() self.menuButtons = pygame.sprite.Group() self.initMenuButtons() path = "Pictures/loading.png" path = os.path.normpath(path) self.loadScreen = pygame.image.load(path) self.loadScreen.convert() path = "Pictures/paused.png" path = os.path.normpath(path) self.pauseScreen = pygame.image.load(path) self.pauseScreen.convert() def initMenuButtons(self): (logoX, logoY) = (50, 275) (logoW, logoH) = (700, 300) logoPath = "Pictures/Logo.png" logo = Button(logoPath, logoX, logoY, logoW, logoH) (playX, playY) = (850, 210) (playW, playH) = (500, 200) playPath = "Pictures/Buttons/Play.png" self.playButton = Button(playPath, playX, playY, playW, playH) (howToX, howToY) = (850, 460) (howToW, howToH) = (500, 150) howToPath = "Pictures/Buttons/HowTo.png" self.howToButton = Button(howToPath, howToX, howToY, howToW, howToH) logo.add(self.menuButtons) self.playButton.add(self.menuButtons) self.howToButton.add(self.menuButtons) def initMenuMusic(self): #Menu music taken from: http://www.newgrounds.com/audio/listen/438759 menuMusicPath = "SFX/menu.ogg" pygame.mixer.music.load(menuMusicPath) #Repeat menu music indefinitely. pygame.mixer.music.play(loops=-1) def initBeats(self): self.r = 50 self.beats = pygame.sprite.Group() #Having a separate queue allows for indexing (so we can pull the most #recent beat) self.beatQueue = deque() #Choices of color for beats: Red, Blue, Green, Orange self.colorChoices = [(255,0,0),(0,0,255),(24,226,24),(247,162,15)] self.beatColor = (0, 0, 0) self.shuffleColor() #Needed in order to properly randomize beat positions. self.prevX = None self.prevY = None self.maxDist = 200 self.minDist = 100 self.beatNum = 1 self.beatNumMax = 4 self.initBeatTiming() self.initScoring() def initScoring(self): self.scoreBad = 50 self.scoreGood = 100 self.scorePerfect = 300 self.misses = 0 self.bads = 0 self.goods = 0 self.perfects = 0 def initBeatTiming(self): #Beats appear a second early (beatApproach), and the width between the #different scores is dictated by windowWidth. self.beatApproach = 1.0 self.windowWidth = 0.06 self.goodLate = self.beatApproach + self.windowWidth self.badLate = self.goodLate + self.windowWidth self.missLate = self.badLate + self.windowWidth self.beatKill = self.missLate + self.windowWidth self.perfectEarly = self.beatApproach - self.windowWidth self.goodEarly = self.perfectEarly - self.windowWidth self.badEarly = self.goodEarly - self.windowWidth self.missEarly = self.badEarly - self.windowWidth def initSong(self, path): self.songPath = os.path.normpath(self.songPath) startTime = time.time() self.song = Song(self.songPath) self.times = self.song.getBeatTimes() self.nextBeat = self.times.pop(0) pygame.mixer.music.load(self.songPath) endTime = time.time() loadTime = abs(endTime - startTime) #Necessary offset, or else song and game go out of sync. self.timeElapsed -= loadTime def initSounds(self): #Hit sound from: #https://www.freesound.org/people/radiopassiveboy/sounds/219266/ self.soundHit = Sound("SFX/hit.ogg") #Mistake sound from: #https://www.freesound.org/people/zerolagtime/sounds/49238/ self.soundMiss = Sound("SFX/miss.ogg") def initHowTo(self): self.howToItems = pygame.sprite.Group() (x, y) = (250, 100) (width, height) = (1200, 700) path = "Pictures/HowTo.png" howToPlay = Button(path, x, y, width, height) (x, y) = (260, 50) (width, height) = (600, 50) path = "Pictures/HowToHeader.png" howToHeader = Button(path, x, y, width, height) (x, y) = (50, 50) (width, height) = (175, 750) path = "Pictures/Buttons/Back.png" self.toMenu = Button(path, x, y, width, height) howToPlay.add(self.howToItems) howToHeader.add(self.howToItems) self.toMenu.add(self.howToItems) def initSongSelect(self): self.songSelItems = pygame.sprite.Group() #Spacing between song select buttons. spacing = 5 + 120 self.initInput() (x, y, width, height) = (50, 50, 800, 175) path = "Pictures/TextInput.png" self.textInput = Button(path, x, y, width, height) self.textInput.add(self.songSelItems) (x, y0, width, height) = (950, 50, 500, 120) applePath = "Pictures/Song Select/badAppleBox.png" self.badAppleBox = Button(applePath, x, y0, width, height) self.badAppleBox.add(self.songSelItems) y1 = y0 + spacing bonePath = "Pictures/Song Select/bonetrousleBox.png" self.bonetrousleBox = Button(bonePath, x, y1, width, height) self.bonetrousleBox.add(self.songSelItems) y2 = y1 + spacing dummyPath = "Pictures/Song Select/dummyBox.png" self.dummyBox = Button(dummyPath, x, y2, width, height) self.dummyBox.add(self.songSelItems) #I hate you, arbitrary 20-line limit. self.initSongSelect2(x, width, height, y2, spacing) def initSongSelect2(self, x, width, height, y2, spacing): y3 = y2 + spacing megaPath = "Pictures/Song Select/megalovaniaBox.png" self.megalovaniaBox = Button(megaPath, x, y3, width, height) self.megalovaniaBox.add(self.songSelItems) y4 = y3 + spacing rhinePath = "Pictures/Song Select/rhinestoneBox.png" self.rhinestoneBox = Button(rhinePath, x, y4, width, height) self.rhinestoneBox.add(self.songSelItems) y5 = y4 + spacing goodPath = "Pictures/Song Select/feelgoodBox.png" self.feelgoodBox = Button(goodPath, x, y5, width, height) self.feelgoodBox.add(self.songSelItems) self.backSmallGrp = pygame.sprite.GroupSingle() (width, height) = (175, 175) (x, y) = (50, self.height - 50 - height) path = "Pictures/Buttons/BackSmall.png" self.backSmall = Button(path, x, y, width, height) self.backSmall.add(self.backSmallGrp) self.initError() self.initTextClear() def initInput(self): menuFont = "Fonts/SourceCodePro-Regular.ttf" font = pygame.font.Font(menuFont, 25) textColor = (217, 230, 255) self.usrSong = eztext.Input(color=textColor, maxlength=50, x=70, y=150, font=font) def initError(self): self.oops = pygame.sprite.GroupSingle() (x, y) = (50, 250) (width, height) = (800, 350) path = "Pictures/Error.png" self.errorMessage = Button(path, x, y, width, height) self.errorMessage.add(self.oops) def initTextClear(self): self.clearTextGrp = pygame.sprite.GroupSingle() (x, y) = (860, 50) (width, height) = (40, 175) path = "Pictures/Buttons/Clear.png" self.clearText = Button(path, x, y, width, height) self.clearText.add(self.clearTextGrp) def run(self): clock = pygame.time.Clock() self.screen = pygame.display.set_mode((self.width, self.height)) pygame.display.set_caption(self.title) self.initMenu() self.initHowTo() self.initSongSelect() while self.inGame: self.mainLoop(clock) pygame.font.quit() pygame.mixer.quit() pygame.quit() ############################################################################### ########################### Loop code starts here ############################# ############################################################################### def mainLoop(self, clock): if not pygame.mixer.music.get_busy(): self.initMenuMusic() while self.inMenu: self.menuLoop(clock) while self.instructions: self.instructionLoop(clock) while self.songSelect: self.songSelectLoop(clock) if self.playSong: pygame.mixer.music.play() pygame.mixer.music.set_endevent(self.PLAYBACK_END) while self.playSong: self.songLoop(clock) while self.scoreScreen: self.scoreScreenLoop(clock) for event in pygame.event.get(): if event.type == pygame.QUIT: self.inGame = False self.mainLoopUpdate() def menuLoop(self, clock): clock.tick(self.fps) self.screen.blit(self.menu, (0, 0)) self.menuButtons.draw(self.screen) pygame.display.flip() for event in pygame.event.get(): if event.type == pygame.QUIT: self.inGame = False self.inMenu = False elif ((event.type == pygame.MOUSEBUTTONDOWN) and (event.button == 1)): self.mousePressed() def instructionLoop(self, clock): clock.tick(self.fps) self.screen.blit(self.menu, (0, 0)) self.howToItems.draw(self.screen) pygame.display.flip() for event in pygame.event.get(): if event.type == pygame.QUIT: self.inGame = False self.instructions = False elif event.type == pygame.KEYDOWN: if (event.key == pygame.K_ESCAPE): self.soundMiss.play() self.instructions = False self.inMenu = True elif ((event.type == pygame.MOUSEBUTTONDOWN) and (event.button == 1)): self.mousePressed() def songSelectLoop(self, clock): clock.tick(self.fps) events = pygame.event.get() self.songSelUpdate(events) if self.error: self.oops.draw(self.screen) pygame.display.flip() for event in events: if event.type == pygame.QUIT: self.inGame = False self.songSelect = False elif event.type == pygame.KEYDOWN: if (event.key == pygame.K_ESCAPE): self.soundMiss.play() self.songSelect = False self.inMenu = True elif ((event.type == pygame.MOUSEBUTTONDOWN) and (event.button == 1)): self.mousePressed() def songLoop(self, clock): #tick_busy_loop is more expensive (more accurate too) than just #clock.tick, but this is necessary in a rhythm game. tick = clock.tick_busy_loop(self.fps) / 1000 #Convert to seconds if not self.paused: pygame.mixer.music.unpause() self.timeElapsed += tick self.gameTimerFired(self.timeElapsed, tick) for event in pygame.event.get(): self.actEvent(event) if self.paused: pygame.mixer.music.pause() if self.countdown != None: self.countdown -= tick if self.countdown <= 0: self.playSong = False self.scoreScreen = True self.songLoopUpdate() def scoreScreenLoop(self, clock): clock.tick(self.fps) if not pygame.mixer.music.get_busy(): self.initMenuMusic() for event in pygame.event.get(): if event.type == pygame.QUIT: self.inGame = False self.scoreScreen = False elif event.type == pygame.KEYDOWN: if (event.key == pygame.K_ESCAPE): self.soundMiss.play() self.scoreScreen = False self.songSelect = True self.reset() elif ((event.type == pygame.MOUSEBUTTONDOWN) and (event.button == 1)): self.mousePressed() self.screen.blit(self.menu, (0, 0)) self.scoreItems.draw(self.screen) self.printScoreText() pygame.display.flip() def mainLoopUpdate(self): BLACK = (0, 0, 0) self.screen.fill(BLACK) pygame.display.flip() def songSelUpdate(self, events): self.screen.blit(self.menu, (0, 0)) self.backSmallGrp.draw(self.screen) self.songSelItems.draw(self.screen) self.clearTextGrp.draw(self.screen) self.usrSong.update(events) self.usrSong.draw(self.screen) def songLoopUpdate(self): if not self.paused: BLACK = (0, 0, 0) self.screen.fill(BLACK) self.printText() self.hits.draw(self.screen) self.beats.draw(self.screen) if self.countdown != None: fadeOut = pygame.Surface((self.width, self.height)) BLACK = (0, 0, 0) fadeOut.fill(BLACK) alpha = int((1 - self.countdown/self.endDelay) * 255) alpha = max(alpha, 0) fadeOut.set_alpha(alpha) self.screen.blit(fadeOut, (0,0)) if self.paused: self.screen.blit(self.pauseScreen, (0,0)) pygame.display.flip() def actEvent(self, event): if event.type == pygame.QUIT: self.inGame = False self.playSong = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.paused = not self.paused if self.paused: if event.key == pygame.K_r: self.reset() self.songSelect = True return elif not self.paused: if (event.key == pygame.K_z or event.key == pygame.K_x): self.beatPressed() if not self.paused: if event.type == pygame.MOUSEBUTTONDOWN: self.beatPressed() elif event.type == self.PLAYBACK_END: if (self.combo > self.maxCombo): self.maxCombo = self.combo self.initScoreScreen() self.countdown = self.endDelay def mousePressed(self): (x, y) = pygame.mouse.get_pos() click = MousePointer(x, y) if self.inMenu: self.checkMenuCollision(click) elif self.instructions: self.checkHowToCollision(click) elif self.songSelect: self.checkSongSelCollision(click) elif self.scoreScreen: self.checkScoreCollision(click) def checkMenuCollision(self, click): if pygame.sprite.collide_rect(self.playButton, click): self.soundHit.play() self.songSelect = True self.inMenu = False elif pygame.sprite.collide_rect(self.howToButton, click): self.soundHit.play() self.instructions = True self.inMenu = False def checkHowToCollision(self, click): if pygame.sprite.collide_rect(self.toMenu, click): self.soundMiss.play() self.instructions = False self.inMenu = True def checkSongSelCollision(self, click): self.checkSelectedSong(click) if pygame.sprite.collide_rect(self.clearText, click): self.soundMiss.play() self.usrSong.clear() if pygame.sprite.collide_rect(self.backSmall, click): self.soundMiss.play() self.songSelect = False self.inMenu = True if pygame.sprite.spritecollideany(click, self.songSelItems): self.soundHit.play() self.play() def checkSelectedSong(self, click): if pygame.sprite.collide_rect(self.badAppleBox, click): self.songPath = "Songs/Bad Apple.mp3" elif pygame.sprite.collide_rect(self.bonetrousleBox, click): self.songPath = "Songs/Bonetrousle.ogg" elif pygame.sprite.collide_rect(self.dummyBox, click): self.songPath = "Songs/Dummy!.ogg" elif pygame.sprite.collide_rect(self.megalovaniaBox, click): self.songPath = "Songs/MEGALOVANIA.ogg" elif pygame.sprite.collide_rect(self.rhinestoneBox, click): self.songPath = "Songs/Rhinestone Eyes.ogg" elif pygame.sprite.collide_rect(self.feelgoodBox, click): self.songPath = "Songs/Feel Good Inc.ogg" elif pygame.sprite.collide_rect(self.textInput, click): self.songPath = self.usrSong.value.replace('"', "") def checkScoreCollision(self, click): if pygame.sprite.collide_rect(self.backScore, click): self.soundMiss.play() self.scoreScreen = False self.songSelect = True self.reset() def initScoreScreen(self): self.scoreItems = pygame.sprite.Group() (x, y) = (50, 50) (width, height) = (1400, 650) path = "Pictures/Score.png" howToPlay = Button(path, x, y, width, height) (x, y) = (50, 720) (width, height) = (1400, 80) path = "Pictures/Buttons/BackScore.png" self.backScore = Button(path, x, y, width, height) howToPlay.add(self.scoreItems) self.backScore.add(self.scoreItems) def printScoreText(self): (width, height) = self.screen.get_size() textScore = str(self.score) (xScore, yScore) = (1390, 90) scoreSize = 70 scoreText = StText(self.screen, textScore, scoreSize, xScore, yScore, "ne") textCombo = str(self.maxCombo) + "x" (xCombo, yCombo) = (110, 240) comboSize = 80 comboText = StText(self.screen, textCombo, comboSize, xCombo, yCombo) self.printTimingText() def printTimingText(self): textScore = str(self.perfects) (xScore, yScore) = (620, 445) scoreSize = 50 scoreText = StText(self.screen, textScore, scoreSize, xScore, yScore) textScore = str(self.goods) (xScore, yScore) = (1190, 445) scoreSize = 50 scoreText = StText(self.screen, textScore, scoreSize, xScore, yScore) textScore = str(self.bads) (xScore, yScore) = (620, 540) scoreSize = 50 scoreText = StText(self.screen, textScore, scoreSize, xScore, yScore) textScore = str(self.misses) (xScore, yScore) = (1190, 540) scoreSize = 50 scoreText = StText(self.screen, textScore, scoreSize, xScore, yScore) def play(self): self.screen.blit(self.loadScreen, (0, 0)) pygame.display.flip() #If custom path doesn't work (crashes), then we go back to song select. try: self.initSong(self.songPath) except: self.error = True return pygame.mixer.music.stop() self.songSelect = False self.playSong = True #Resets variables to prepare for next song. def reset(self): pygame.mixer.music.stop() self.error = False self.countdown = None self.playSong = False self.paused = False self.combo = 0 self.maxCombo = 0 self.score = 0 self.prevAddition = 0 self.lastBeatHit = (0, 0) self.hits = pygame.sprite.Group() self.timeElapsed = 0 + self.audioDelay self.beats = pygame.sprite.Group() self.beatQueue = deque() self.beatNum = 1 self.initScoring() pygame.mixer.music.set_endevent() ############################################################################### ########################### Game code starts here ############################# ############################################################################### def beatPressed(self): if (len(self.beatQueue) == 0): return (x, y) = pygame.mouse.get_pos() click = MousePointer(x, y) #Only the oldest beat placed can be clicked on. beat = self.beatQueue[0] if (pygame.sprite.collide_circle(beat, click)): mistake = self.addScore(beat.clock, beat) if (mistake == None): return elif mistake: self.mistake(beat) else: self.soundHit.play() self.combo += 1 beat.dying() self.beatQueue.popleft() self.addHit(beat) #Returns True if a mistake is made, None if player clicks early, and #increments score otherwise. def addScore(self, time, beat): if (time >= self.missLate): return True elif (time >= self.badLate): addition = self.scoreBad elif (time >= self.goodLate): addition = self.scoreGood elif (time >= self.perfectEarly): addition = self.scorePerfect elif (time >= self.goodEarly): addition = self.scoreGood elif (time >= self.badEarly): addition = self.scoreBad elif (time >= self.missEarly): return True else: return None self.scoreTrack(addition) return False #Increments counter for each hit type. def scoreTrack(self, addition): mult = self.getComboMult() self.score = int(self.score + (addition * mult)) self.prevAddition = addition if (addition == self.scoreBad): self.bads += 1 elif (addition == self.scoreGood): self.goods += 1 elif (addition == self.scorePerfect): self.perfects += 1 #Based off how osu! calculates this, from: https://osu.ppy.sh/wiki/Score def getComboMult(self): return (1 + self.combo/25) #Checks internal clocks of each beat. def gameTimerFired(self, time, tick): if (time + self.beatApproach) >= self.nextBeat: if len(self.times) > 0: self.addBeat() self.nextBeat = self.times.pop(0) for beat in self.beats: beat.update(tick) if ((beat.killClock == None) and (beat.clock >= self.beatKill)): beat.dying() self.beatQueue.remove(beat) self.mistake(beat) for hit in self.hits: hit.update(tick) if ((hit.killClock == None) and (hit.clock >= self.hitKill)): hit.dying() def addBeat(self): #Can't let beat go off-screen. (offsetW, offsetH) = (self.width-self.r, self.height-self.r) if (self.prevX == None) and (self.prevY == None): x = random.randint(0+self.r, offsetW) y = random.randint(0+self.r, offsetH) #Biasing in effect here. If beat position is in the edge 1/4 of the #screen, it will push the next beat to the center of the screen. If #it's in the center already, it's completely random. else: if (self.prevX < self.width // 4): xMult = 1 elif (self.prevX > 3*(self.width // 4)): xMult = -1 else: xMult = random.choice([-1, 1]) if (self.prevY < self.height // 4): yMult = 1 elif (self.prevY > 3*(self.height // 4)): yMult = -1 else: yMult = random.choice([-1, 1]) dx = random.randint(self.minDist, self.maxDist) * xMult dy = random.randint(self.minDist, self.maxDist) * yMult (x, y) = (self.prevX + dx, self.prevY + dy) (self.prevX, self.prevY) = (x, y) beat = Beat(x, y, self.beatColor, self.beatNum) beat.add(self.beats) self.beatQueue.append(beat) self.updateOrdinal() #Updates number drawn on the beat. def updateOrdinal(self): self.beatNum += 1 if self.beatNum > self.beatNumMax: self.beatNum = 1 self.shuffleColor() def mistake(self, beat): if (self.combo > self.maxCombo): self.maxCombo = self.combo #Only play noise when the player has a decent-sized combo. #Otherwise it's annoying as hell. if (self.combo >= 10): self.soundMiss.play() self.combo = 0 xColor = (255, 0, 0) (x, y) = beat.getPos() text = "x" size = 100 missText = Text(self.screen, text, size, x, y, "center", xColor) missText.add(self.hits) self.misses += 1 #Change color of beats. def shuffleColor(self): newColor = random.choice(self.colorChoices) while (newColor == self.beatColor): newColor = random.choice(self.colorChoices) self.beatColor = newColor #Prints combo and score on screen. def printText(self): (width, height) = self.screen.get_size() textScore = str(self.score) (xScore, yScore) = (width-10, 0) scoreSize = 60 scoreText = Text(self.screen, textScore, scoreSize, xScore, yScore,"ne") textCombo = str(self.combo) + "x" (xCombo, yCombo) = (10, height) comboSize = 75 comboText = Text(self.screen, textCombo, comboSize, xCombo, yCombo,"sw") def addHit(self, beat): colorPerfect = (125, 200, 255) colorGood = (88, 255, 88) colorBad = (255, 226, 125) (x, y) = beat.getPos() text = str(self.prevAddition) if (self.prevAddition == self.scorePerfect): color = colorPerfect elif (self.prevAddition == self.scoreGood): color = colorGood elif (self.prevAddition == self.scoreBad): color = colorBad else: return size = 50 hitText = Text(self.screen, text, size, x, y, "center", color) hitText.add(self.hits)