def __init__(self, screen): super(PlatformingScene, self).__init__(screen) self.background_drawn = False self.headersize = 30 self.camera = pygame.rect.Rect(0, 0, game_constants.w, game_constants.h) self.special_chars = SpecialChars() self.movelist = [] self.time_elapsed = 0 self.health = Health(5) self.score = Score(screen) self.player = Player( (screen.get_width() / 2, screen.get_height() / 2 - 30)) self.playergroup = RenderUpdatesDraw(self.player) self.platforms = {} self.platforms[game_constants.h - 80] = [ general.Box(-10000, game_constants.h - 80, 20000, 16) ] self.statics = RenderUpdatesDraw() self.statics.add(self.platforms.values()[0]) self.screenstatics = RenderUpdatesDraw() self.actives = RenderUpdatesDraw() self.powerups = RenderUpdatesDraw() self.place_platforms() self.player.colliders = self.screenstatics self.header = pygame.Surface((screen.get_width(), self.headersize)) self.header.fill(Color.BLACK) self.background = pygame.Surface(screen.get_size()).convert() gradiation = 128.0 for i in xrange(int(gradiation)): color = (150 - (i * 150 / gradiation), 150 - (i * 150 / gradiation), 200) rect = (0, i * game_constants.h / gradiation, game_constants.w, game_constants.h / gradiation + 1) self.background.fill(color, rect) # Move sprites into or out of 'screenstatics' group based on whether they're in camera self.screencheck() # fixme: rearchitect this self.challenging = False
def __init__(self, screen): super(PlatformingScene, self).__init__(screen) self.background_drawn = False self.headersize = 30 self.camera = pygame.rect.Rect(0, 0, game_constants.w, game_constants.h) self.special_chars = SpecialChars() self.movelist = [] self.time_elapsed = 0 self.health = Health(5) self.score = Score(screen) self.player = Player((screen.get_width() / 2, screen.get_height() / 2 - 30)) self.playergroup = RenderUpdatesDraw(self.player) self.platforms = {} self.platforms[game_constants.h - 80] = [general.Box(-10000, game_constants.h - 80, 20000, 16)] self.statics = RenderUpdatesDraw() self.statics.add(self.platforms.values()[0]) self.screenstatics = RenderUpdatesDraw() self.actives = RenderUpdatesDraw() self.powerups = RenderUpdatesDraw() self.place_platforms() self.player.colliders = self.screenstatics self.header = pygame.Surface((screen.get_width(), self.headersize)) self.header.fill(Color.BLACK) self.background = pygame.Surface(screen.get_size()).convert() gradiation = 128.0 for i in xrange(int(gradiation)): color = (150 - (i * 150 / gradiation), 150 - (i * 150 / gradiation), 200) rect = (0, i * game_constants.h / gradiation, game_constants.w, game_constants.h / gradiation + 1) self.background.fill(color, rect) # Move sprites into or out of 'screenstatics' group based on whether they're in camera self.screencheck() # fixme: rearchitect this self.challenging = False
class PlatformingScene(BaseScene): """ Class for the main playable game environment. """ def __init__(self, screen): super(PlatformingScene, self).__init__(screen) self.background_drawn = False self.headersize = 30 self.camera = pygame.rect.Rect(0, 0, game_constants.w, game_constants.h) self.special_chars = SpecialChars() self.movelist = [] self.time_elapsed = 0 self.health = Health(5) self.score = Score(screen) self.player = Player( (screen.get_width() / 2, screen.get_height() / 2 - 30)) self.playergroup = RenderUpdatesDraw(self.player) self.platforms = {} self.platforms[game_constants.h - 80] = [ general.Box(-10000, game_constants.h - 80, 20000, 16) ] self.statics = RenderUpdatesDraw() self.statics.add(self.platforms.values()[0]) self.screenstatics = RenderUpdatesDraw() self.actives = RenderUpdatesDraw() self.powerups = RenderUpdatesDraw() self.place_platforms() self.player.colliders = self.screenstatics self.header = pygame.Surface((screen.get_width(), self.headersize)) self.header.fill(Color.BLACK) self.background = pygame.Surface(screen.get_size()).convert() gradiation = 128.0 for i in xrange(int(gradiation)): color = (150 - (i * 150 / gradiation), 150 - (i * 150 / gradiation), 200) rect = (0, i * game_constants.h / gradiation, game_constants.w, game_constants.h / gradiation + 1) self.background.fill(color, rect) # Move sprites into or out of 'screenstatics' group based on whether they're in camera self.screencheck() # fixme: rearchitect this self.challenging = False def lazy_redraw(self): return False def fill_level(self, height): platform_level = self.platforms.setdefault(height, []) max_right = self.camera.right + game_constants.w min_left = self.camera.left - game_constants.w # cull platforms that have gone too far -- TODO this doesn't work yet bad_platforms = [ p for p in platform_level if p.rect.left > max_right or p.rect.right < min_left ] [platform_level.remove(p) for p in bad_platforms] [self.statics.remove(p) for p in bad_platforms] # add on platforms until the limit is reached if not len(platform_level): leftmost = random.randint(-game_constants.w, game_constants.w) rightmost = leftmost = random.randint(-game_constants.w, game_constants.w) else: leftmost = min([p.rect.left for p in platform_level]) rightmost = max([p.rect.right for p in platform_level]) while rightmost < max_right: new_start = rightmost + random.randint(150, 300) new_width = random.randint(200, 1000) new_width = new_width - new_width % 16 # Cut off to the nearest multiple of 16 new_p = Platform(new_start, height, new_width, 16) platform_level.append(new_p) self.statics.add(new_p) rightmost = new_start + new_width while leftmost > min_left: new_start = leftmost - random.randint(150, 300) new_width = random.randint(200, 1000) new_width = new_width - new_width % 16 # Cut off to the nearest multiple of 16 new_p = Platform(new_start - new_width, height, new_width, 16) platform_level.append(new_p) self.statics.add(new_p) leftmost = new_start - new_width def place_platforms(self): # Generate platforms based on camera position: Make sure there are always platforms extending at least as far as +-4*game_constants.w, +-4*game_constants.h from the player max_height = self.camera.top - 2 * game_constants.h lowest = max(self.platforms.keys()) highest = min(self.platforms.keys()) for h in range(highest, lowest, 80): self.fill_level(h) while highest > max_height: highest -= 80 self.fill_level(highest) def draw_background(self): self.screen.blit(self.background, (0, 0)) self.screen.blit(self.header, (0, 0)) pygame.display.update() self.background_drawn = True def draw_header(self): dirty = [] self.screen.set_clip(0, 0, game_constants.w, self.headersize) # Only draw in header area self.score.clear(self.screen, self.header) self.health.clear(self.screen, self.header) dirty += self.score.draw(self.screen, self.time_elapsed) dirty += self.health.draw(self.screen) return dirty def draw(self): if not self.background_drawn: self.draw_background() self.camshift() header_dirty = self.draw_header() dirty = [] # Don't draw over header self.screen.set_clip(0, self.headersize, game_constants.w, game_constants.h) rect_sources = [ self.screenstatics, self.powerups, self.actives, self.playergroup, self.player.bullets, ] for rect_source in rect_sources: rect_source.clear(self.screen, self.background) for rect_source in rect_sources: dirty += rect_source.draw(self.screen, self.camera) # hack: repaint selected_opponent to make sure it's visible if self.player.selected_opponent: dirty += [ self.player.selected_opponent.draw(self.screen, self.camera) ] # Constrain all dirty rectangles in main game area to main game area. dirty = [ dirty_rect.clip(self.screen.get_clip()) for dirty_rect in dirty ] return header_dirty + dirty def camshift(self): newpos = self.player.rect bounds = self.camera.inflate(-game_constants.w + 50, -game_constants.h + 100) # Move the screen if we're near the edge if newpos.right > bounds.right: self.camera = self.camera.move(newpos.right - bounds.right, 0) elif newpos.left < bounds.left: self.camera = self.camera.move(newpos.left - bounds.left, 0) if newpos.bottom > bounds.bottom: self.camera = self.camera.move(0, newpos.bottom - bounds.bottom) elif newpos.top < bounds.top: self.camera = self.camera.move(0, newpos.top - bounds.top) self.screencheck() def screencheck(self): """Classify objects by whether they are on the screen""" for platform_level in self.platforms.values(): for platform in platform_level: if platform not in self.screenstatics: # This platform wasn't on the screen: is it now? if platform.rect.colliderect(self.camera): self.screenstatics.add(platform) # If it's a platform (has the attribute'word') give it an # identifying word while it's onscreen if hasattr(platform, 'word'): platform.word = Word(self.special_chars.new(), platform.font) else: # This platform is on the screen: is it gone now? if not platform.rect.colliderect(self.camera): self.screenstatics.remove(platform) # If it's a platform (has the attribute'word') # and it's out of camera, free up its symbol for later use if hasattr(platform, 'word'): self.special_chars.release(platform.word.string) platform.word = None for sprite in self.powerups.sprites(): if not sprite.rect.colliderect( self.camera.inflate(game_constants.w, 0)): sprite.kill() for sprite in self.actives.sprites( ): # need a list because we're going to delete from it # Opponents are allowed to be a full screen width outside of camera, but no further if not sprite.rect.colliderect( self.camera.inflate(game_constants.w, 0)): if sprite == self.player.selected_opponent: self.player.selected_opponent = None sprite.kill() def is_reachable(self, platform): player_rect = self.player.rect """ Is it possible for the player to jump to this platform in the concievable future? """ # Test 1: the platform must be within jumping height if player_rect.bottom - game_constants.maxjump_height < platform.rect.top < player_rect.bottom: # Test 2: the player cannot be under the platform if (player_rect.right < platform.rect.left): # Test 3: the path from the player position to the optimal jump position must be contiguous jumpdist = platform.rect.left - player_rect.right if jumpdist < game_constants.maxjump_width: # Maximum distance that can be jumped return True else: start = (player_rect.right, player_rect.bottom) size = (jumpdist - game_constants.maxjump_width, 1) testrect = pygame.rect.Rect(start, size) for collider in self.screenstatics: if collider.rect.contains(testrect): return True elif (player_rect.left > platform.rect.right): # Test 3: the path from the player position to the optimal jump position must be contiguous jumpdist = player_rect.left - platform.rect.right if jumpdist < game_constants.maxjump_width: # Maximum distance that can be jumped return True else: start = (platform.rect.right + game_constants.maxjump_width, player_rect.bottom) size = (jumpdist - game_constants.maxjump_width, 1) testrect = pygame.rect.Rect(start, size) for collider in self.screenstatics: if collider.rect.contains(testrect): return True def tick(self, elapsed): self.place_platforms() self.time_elapsed += elapsed for direction in self.movelist: self.player.direct(direction) for active_obj in self.actives: active_obj.tick(self.player.rect.center) for powerup in self.powerups: powerup.tick() for screenstatic in self.screenstatics: # Objects on the screen # Only platforms have a 'word' attribute if hasattr(screenstatic, 'word'): # Will it be possible to get to this object without having to walk on air screenstatic.reachable = self.is_reachable(screenstatic) self.player.tick() if (self.health.value() <= 0): self.switch_to = GameOverScene(self.screen) def type_special(self, key): # Typing a special character for platform_level in self.platforms.values(): for platform in platform_level: if hasattr(platform, 'word'): # HACK to ignore bottom platform if platform.reachable and self.camera.colliderect( platform.rect): if key == platform.contents(): return platform
class PlatformingScene(BaseScene): """ Class for the main playable game environment. """ def __init__(self, screen): super(PlatformingScene, self).__init__(screen) self.background_drawn = False self.headersize = 30 self.camera = pygame.rect.Rect(0, 0, game_constants.w, game_constants.h) self.special_chars = SpecialChars() self.movelist = [] self.time_elapsed = 0 self.health = Health(5) self.score = Score(screen) self.player = Player((screen.get_width() / 2, screen.get_height() / 2 - 30)) self.playergroup = RenderUpdatesDraw(self.player) self.platforms = {} self.platforms[game_constants.h - 80] = [general.Box(-10000, game_constants.h - 80, 20000, 16)] self.statics = RenderUpdatesDraw() self.statics.add(self.platforms.values()[0]) self.screenstatics = RenderUpdatesDraw() self.actives = RenderUpdatesDraw() self.powerups = RenderUpdatesDraw() self.place_platforms() self.player.colliders = self.screenstatics self.header = pygame.Surface((screen.get_width(), self.headersize)) self.header.fill(Color.BLACK) self.background = pygame.Surface(screen.get_size()).convert() gradiation = 128.0 for i in xrange(int(gradiation)): color = (150 - (i * 150 / gradiation), 150 - (i * 150 / gradiation), 200) rect = (0, i * game_constants.h / gradiation, game_constants.w, game_constants.h / gradiation + 1) self.background.fill(color, rect) # Move sprites into or out of 'screenstatics' group based on whether they're in camera self.screencheck() # fixme: rearchitect this self.challenging = False def lazy_redraw(self): return False def fill_level(self, height): platform_level = self.platforms.setdefault(height, []) max_right = self.camera.right + game_constants.w min_left = self.camera.left - game_constants.w # cull platforms that have gone too far -- TODO this doesn't work yet bad_platforms = [p for p in platform_level if p.rect.left > max_right or p.rect.right < min_left] [platform_level.remove(p) for p in bad_platforms] [self.statics.remove(p) for p in bad_platforms] # add on platforms until the limit is reached if not len(platform_level): leftmost = random.randint(-game_constants.w, game_constants.w) rightmost = leftmost = random.randint(-game_constants.w, game_constants.w) else: leftmost = min([p.rect.left for p in platform_level]) rightmost = max([p.rect.right for p in platform_level]) while rightmost < max_right: new_start = rightmost + random.randint(150, 300) new_width = random.randint(200, 1000) new_width = new_width - new_width % 16 # Cut off to the nearest multiple of 16 new_p = Platform(new_start, height, new_width, 16) platform_level.append(new_p) self.statics.add(new_p) rightmost = new_start + new_width while leftmost > min_left: new_start = leftmost - random.randint(150, 300) new_width = random.randint(200, 1000) new_width = new_width - new_width % 16 # Cut off to the nearest multiple of 16 new_p = Platform(new_start - new_width, height, new_width, 16) platform_level.append(new_p) self.statics.add(new_p) leftmost = new_start - new_width def place_platforms(self): # Generate platforms based on camera position: Make sure there are always platforms extending at least as far as +-4*game_constants.w, +-4*game_constants.h from the player max_height = self.camera.top - 2 * game_constants.h lowest = max(self.platforms.keys()) highest = min(self.platforms.keys()) for h in range(highest, lowest, 80): self.fill_level(h) while highest > max_height: highest -= 80 self.fill_level(highest) def draw_background(self): self.screen.blit(self.background, (0, 0)) self.screen.blit(self.header, (0, 0)) pygame.display.update() self.background_drawn = True def draw_header(self): dirty = [] self.screen.set_clip(0, 0, game_constants.w, self.headersize) # Only draw in header area self.score.clear(self.screen, self.header) self.health.clear(self.screen, self.header) dirty += self.score.draw(self.screen, self.time_elapsed) dirty += self.health.draw(self.screen) return dirty def draw(self): if not self.background_drawn: self.draw_background() self.camshift() header_dirty = self.draw_header() dirty = [] # Don't draw over header self.screen.set_clip(0, self.headersize, game_constants.w, game_constants.h) rect_sources = [ self.screenstatics, self.powerups, self.actives, self.playergroup, self.player.bullets, ] for rect_source in rect_sources: rect_source.clear(self.screen, self.background) for rect_source in rect_sources: dirty += rect_source.draw(self.screen, self.camera) # hack: repaint selected_opponent to make sure it's visible if self.player.selected_opponent: dirty += [self.player.selected_opponent.draw(self.screen, self.camera)] # Constrain all dirty rectangles in main game area to main game area. dirty = [dirty_rect.clip(self.screen.get_clip()) for dirty_rect in dirty] return header_dirty + dirty def camshift(self): newpos = self.player.rect bounds = self.camera.inflate(-game_constants.w + 50, -game_constants.h + 100) # Move the screen if we're near the edge if newpos.right > bounds.right: self.camera = self.camera.move(newpos.right - bounds.right, 0) elif newpos.left < bounds.left: self.camera = self.camera.move(newpos.left - bounds.left, 0) if newpos.bottom > bounds.bottom: self.camera = self.camera.move(0, newpos.bottom - bounds.bottom) elif newpos.top < bounds.top: self.camera = self.camera.move(0, newpos.top - bounds.top) self.screencheck() def screencheck(self): """Classify objects by whether they are on the screen""" for platform_level in self.platforms.values(): for platform in platform_level: if platform not in self.screenstatics: # This platform wasn't on the screen: is it now? if platform.rect.colliderect(self.camera): self.screenstatics.add(platform) # If it's a platform (has the attribute'word') give it an # identifying word while it's onscreen if hasattr(platform, 'word'): platform.word = Word(self.special_chars.new(), platform.font) else: # This platform is on the screen: is it gone now? if not platform.rect.colliderect(self.camera): self.screenstatics.remove(platform) # If it's a platform (has the attribute'word') # and it's out of camera, free up its symbol for later use if hasattr(platform, 'word'): self.special_chars.release(platform.word.string) platform.word = None for sprite in self.powerups.sprites(): if not sprite.rect.colliderect(self.camera.inflate(game_constants.w, 0)): sprite.kill() for sprite in self.actives.sprites(): # need a list because we're going to delete from it # Opponents are allowed to be a full screen width outside of camera, but no further if not sprite.rect.colliderect(self.camera.inflate(game_constants.w, 0)): if sprite == self.player.selected_opponent: self.player.selected_opponent = None sprite.kill() def is_reachable(self, platform): player_rect = self.player.rect """ Is it possible for the player to jump to this platform in the concievable future? """ # Test 1: the platform must be within jumping height if player_rect.bottom - game_constants.maxjump_height < platform.rect.top < player_rect.bottom: # Test 2: the player cannot be under the platform if (player_rect.right < platform.rect.left): # Test 3: the path from the player position to the optimal jump position must be contiguous jumpdist = platform.rect.left - player_rect.right if jumpdist < game_constants.maxjump_width: # Maximum distance that can be jumped return True else: start = (player_rect.right, player_rect.bottom) size = (jumpdist - game_constants.maxjump_width, 1) testrect = pygame.rect.Rect(start, size) for collider in self.screenstatics: if collider.rect.contains(testrect): return True elif (player_rect.left > platform.rect.right): # Test 3: the path from the player position to the optimal jump position must be contiguous jumpdist = player_rect.left - platform.rect.right if jumpdist < game_constants.maxjump_width: # Maximum distance that can be jumped return True else: start = (platform.rect.right + game_constants.maxjump_width, player_rect.bottom) size = (jumpdist - game_constants.maxjump_width, 1) testrect = pygame.rect.Rect(start, size) for collider in self.screenstatics: if collider.rect.contains(testrect): return True def tick(self, elapsed): self.place_platforms() self.time_elapsed += elapsed for direction in self.movelist: self.player.direct(direction) for active_obj in self.actives: active_obj.tick(self.player.rect.center) for powerup in self.powerups: powerup.tick() for screenstatic in self.screenstatics: # Objects on the screen # Only platforms have a 'word' attribute if hasattr(screenstatic, 'word'): # Will it be possible to get to this object without having to walk on air screenstatic.reachable = self.is_reachable(screenstatic) self.player.tick() if (self.health.value() <= 0): self.switch_to = GameOverScene(self.screen) def type_special(self, key): # Typing a special character for platform_level in self.platforms.values(): for platform in platform_level: if hasattr(platform, 'word'): # HACK to ignore bottom platform if platform.reachable and self.camera.colliderect(platform.rect): if key == platform.contents(): return platform