class Game: def __init__(self, screen_width=120, screen_height=70): self.screen_width = screen_width self.screen_height = screen_height libtcod.console_init_root(self.screen_width, self.screen_height, 'Heliopause', False) self.buffer = libtcod.ConsoleBuffer(self.screen_width, self.screen_height) self.console = libtcod.console_new(self.screen_width, self.screen_height) self.galaxy_map_console = libtcod.console_new(self.screen_width, self.screen_height) self.set_minimap(20) self.targeting_width = 20 self.targeting_height = 26 self.targeting_buffer = libtcod.ConsoleBuffer(self.targeting_width, self.targeting_height) self.targeting_console = libtcod.console_new(self.targeting_width, self.targeting_height) libtcod.console_set_default_foreground(self.targeting_console, libtcod.white) libtcod.console_set_default_background(self.targeting_console, libtcod.black) self.ship_info_width = 20 self.ship_info_height = 8 self.ship_info_buffer = libtcod.ConsoleBuffer(self.ship_info_width, self.ship_info_height) self.ship_info_console = libtcod.console_new(self.ship_info_width, self.ship_info_height) libtcod.console_set_default_foreground(self.ship_info_console, libtcod.white) libtcod.console_set_default_background(self.ship_info_console, libtcod.black) self.message_height = 4 self.message_width = self.screen_width self.messages = collections.deque([]) self.message_console = libtcod.console_new(self.message_width, self.message_height) libtcod.console_set_default_foreground(self.message_console, libtcod.white) libtcod.console_set_default_background(self.message_console, libtcod.black) self.landing_screen_width = self.screen_width / 2 - 2 self.landing_screen_height = self.screen_height - 4 self.landing_console = libtcod.console_new(self.landing_screen_width, self.landing_screen_height) libtcod.console_set_default_foreground(self.landing_console, libtcod.white) libtcod.console_set_default_background(self.landing_console, libtcod.black) self.mouse = libtcod.Mouse() self.key = libtcod.Key() galaxy_seed, ship_value = self.title_screen_loop() # Loading Screen libtcod.console_set_default_background(self.console, libtcod.black) libtcod.console_clear(self.console) self.galaxy = Galaxy(self.screen_width, self.screen_height, seed=galaxy_seed) self.sector, self.starfield, self.nebula = self.galaxy.sectors[self.galaxy.current_sector].load_sector(self.console, self.buffer) starting_planet = self.sector.planets[randrange(1, len(self.sector.planets))] self.player_ship = Ship(self.sector, starting_planet.sector_position_x, starting_planet.sector_position_y, ship_value=ship_value) self.add_message("Taking off from {0}".format(starting_planet.name)) self.current_screen = 'flight' # self.add_message("Nebula Colors: r:{0} g:{1} b:{2}".format( # round(self.nebula.r_factor,2), # round(self.nebula.g_factor,2), # round(self.nebula.b_factor,2))) def title_screen_loop(self): self.current_screen = 'title' self.sector = Sector(self.screen_width, self.screen_height, self.buffer) self.starfield = Starfield(self.sector, max_stars=50) self.nebula = Nebula(self.sector, r_factor=random(), g_factor=random(), b_factor=random(), seed=randrange(1,1000000)) self.ships = [ [ Ship(self.sector, 0, 0), [self.screen_width/2-16, self.screen_height/2-8] ] for i in range(1) ] done = False xpos = 0.0 speed = 3 galaxy_starting_seed = str(randrange(1,1000000)) cursor_blinked = 0.0 cursor = collections.deque(['|', '']) title = [ ' _ _ _ _', '| | | | | (_)', '| |__| | ___| |_ ___ _ __ __ _ _ _ ___ ___', '| __ |/ _ \\ | |/ _ \\| \'_ \\ / _` | | | / __|/ _ \\', '| | | | __/ | | (_) | |_) | (_| | |_| \\__ \\ __/', '|_| |_|\\___|_|_|\\___/| .__/ \\__,_|\\__,_|___/\\___|', ' | |', ' |_|', ] while not done: libtcod.sys_check_for_event(libtcod.KEY_PRESSED|libtcod.KEY_RELEASED|libtcod.EVENT_MOUSE, self.key, self.mouse) self.starfield.scroll(0.0, speed) self.starfield.draw() self.sector.update_visibility(xpos, 0) xpos += speed self.nebula.draw() for ship, position in self.ships: # ship.heading += math.radians(10) # if math.degrees(ship.heading) > 350: # ship.heading = 0 ship.draw(startx=position[0], starty=position[1], hq2x=True) self.buffer.blit(self.console) t = time.clock() if t > cursor_blinked + 0.5: cursor_blinked = t cursor.rotate() for index, line in enumerate(title): libtcod.console_print_ex(self.console, (self.screen_width/2)-26, 10+index, libtcod.BKGND_NONE, libtcod.LEFT, line) libtcod.console_print_ex(self.console, 1, self.screen_height-2, libtcod.BKGND_NONE, libtcod.LEFT, "Starting Seed: {0}{1}".format(galaxy_starting_seed, cursor[0])) libtcod.console_blit(self.console, 0, 0, self.screen_width, self.screen_height, 0, 0, 0) libtcod.console_flush() self.buffer.clear(self.sector.background[0], self.sector.background[1], self.sector.background[2]) # player_action = self.handle_keys_titlescreen() if self.key.pressed and self.key.vk == libtcod.KEY_ESCAPE: exit(0) elif self.key.pressed and self.key.vk == libtcod.KEY_ENTER: done = True elif self.key.pressed and self.key.vk == libtcod.KEY_BACKSPACE: if galaxy_starting_seed: galaxy_starting_seed = galaxy_starting_seed[:-1] elif self.key.pressed: key_character = chr(self.key.c) if key_character in '1234567890': galaxy_starting_seed += key_character elif key_character == 'G': for ship, position in self.ships: ship.ship_value = getrandbits(32) ship.load_ship_sprites() ship_value = self.ships[0][0].ship_value del(self.ships) return int(galaxy_starting_seed), ship_value def set_minimap(self, size): self.minimap_width = size+3 self.minimap_height = size+3 self.minimap_buffer = libtcod.ConsoleBuffer(self.minimap_width, self.minimap_height) self.minimap_console = libtcod.console_new(self.minimap_width, self.minimap_height) libtcod.console_set_default_foreground(self.minimap_console, libtcod.white) libtcod.console_set_default_background(self.minimap_console, libtcod.black) def new_sector(self): index, distance = self.sector.closest_planet(self.player_ship) # if self.sector.distance_from_center(self.player_ship) > 500: if distance > 500: fade_speed = 10 # Fade out for fade in range(255,0,-1*fade_speed): libtcod.console_set_fade(fade,libtcod.black) libtcod.console_flush() self.sector.clear_selected_planet() self.galaxy.current_sector = self.galaxy.sectors[self.galaxy.current_sector].neighbors[self.galaxy.targeted_sector_index] self.galaxy.targeted_sector_index = 0 self.sector, self.starfield, self.nebula = self.galaxy.sectors[self.galaxy.current_sector].load_sector(self.console, self.buffer) self.player_ship.sector = self.sector self.player_ship.dead_stop() self.player_ship.velocity = int(self.player_ship.speed_limit / 2) self.player_ship.face_system_center() self.player_ship.about_face() self.player_ship.velocity_angle = self.player_ship.heading self.player_ship.apply_thrust() self.clear_messages() self.add_message("Arriving in {0}".format(self.galaxy.sectors[self.galaxy.current_sector].name)) # self.add_message("Nebula Colors: r:{0} g:{1} b:{2}".format( # round(self.nebula.r_factor,2), # round(self.nebula.g_factor,2), # round(self.nebula.b_factor,2))) # Fade in libtcod.console_set_fade(0,libtcod.black) self.render_all() for fade in range(0,255,fade_speed): libtcod.console_set_fade(fade,libtcod.black) libtcod.console_flush() else: self.add_message("You are not far enough from the nearest planet to jump") def check_for_collisions(self): asteroid_to_delete = None for index, asteroid in enumerate(self.sector.asteroids): for p in self.sector.particles: if p.bullet: if asteroid.sector_position_x < p.sector_position_x < asteroid.sector_position_x+asteroid.width and \ asteroid.sector_position_y+1 < p.sector_position_y < asteroid.sector_position_y+1+asteroid.width: asteroid.hp -= p.damage if asteroid.hp < 0: for a in range(0, 60): self.sector.add_particle( ExplosionFireBall( starting_index = a/10, sector = self.sector, x = p.x, y = p.y, sector_position_x = p.sector_position_x, sector_position_y = p.sector_position_y, angle = randrange(0, 359), velocity = random() * randrange(1,3))) # self.sector.asteroids.remove(asteroid) asteroid_to_delete = index else: self.sector.add_particle( Fire( sector = self.sector, x = p.x, y = p.y, sector_position_x = p.sector_position_x, sector_position_y = p.sector_position_y)) # delete the bullet that hit self.sector.particles.remove(p) if asteroid_to_delete is not None: self.sector.asteroids.pop(asteroid_to_delete) def render_all(self): if self.player_ship.velocity > 0.0: self.starfield.scroll( self.player_ship.velocity_angle, self.player_ship.velocity ) self.starfield.draw() self.sector.update_particle_positions() self.sector.scroll_particles( self.player_ship.velocity_angle, self.player_ship.velocity ) self.sector.update_visibility(self.player_ship.sector_position_x, self.player_ship.sector_position_y) self.nebula.draw() for planet in self.sector.planets: planet.draw() for asteroid in self.sector.asteroids: asteroid.draw() self.check_for_collisions() for particle in self.sector.particles: particle.draw() self.player_ship.draw() if self.sector.selected_planet is not None or self.sector.selected_asteroid is not None: self.sector.update_selected_planet_distance(self.player_ship) if self.sector.selected_planet_distance() > (self.screen_height/2.0): self.player_ship.draw_target_arrow(self.sector.selected_planet_angle) # self.sector.draw_target_arrow(self.player_ship) self.buffer.blit(self.console) libtcod.console_blit(self.console, 0, 0, self.screen_width, self.screen_height, 0, 0, 0) if self.sector.selected_planet is not None or self.sector.selected_asteroid is not None: # Target window planet = self.sector.get_selected_planet() planet.draw_target_picture(self.targeting_buffer, 4, 2) self.targeting_buffer.blit(self.targeting_console) libtcod.console_print_frame(self.targeting_console, 0, 0, self.targeting_width, self.targeting_height, clear=False, flag=libtcod.BKGND_SET, fmt=0) name = textwrap.wrap(" Name: {0}".format(planet.name), width=self.targeting_width-4) libtcod.console_print_ex(self.targeting_console, 1, 16, libtcod.BKGND_SET, libtcod.LEFT, "\n ".join(name)+"\n" ) planet_class = planet.planet_class.title() if planet.star_class: planet_class += " ({0})".format(planet.star_class) extra_info = "" if planet.star_temp: extra_info = "\n Temp: {0} K\n".format(planet.star_temp) elif planet.planet_class == 'asteroid': extra_info = "\n HP: {0} \n".format(planet.hp) libtcod.console_print_ex(self.targeting_console, 1, 17+len(name), libtcod.BKGND_SET, libtcod.LEFT, ( " Class: {0}\n{1}\n" " Distance: {2}\n" ).format( planet_class, extra_info, int(self.sector.selected_planet_distance()), ) ) libtcod.console_blit(self.targeting_console, 0, 0, self.targeting_width, self.targeting_height, 0, 0, 0, 1.0, 0.25) # Ship Info libtcod.console_print_frame(self.ship_info_console, 0, 0, self.ship_info_width, self.ship_info_height, clear=True, flag=libtcod.BKGND_SET, fmt=0) libtcod.console_print_ex(self.ship_info_console, 1, 1, libtcod.BKGND_SET, libtcod.LEFT, ( " Heading: {0}\n" " Velocity: {1}\n" " VelAngle: {2}\n" "Particles: {3}\n" "Ship\nSeed: {4}\n" # "Nebula Position:\n" # "l:{4} r:{5}\n" # "t:{6} b:{7}\n" ).format( round(math.degrees(self.player_ship.heading),2), round(self.player_ship.velocity,2), round(math.degrees(self.player_ship.velocity_angle),2), len(self.sector.particles), hex(self.player_ship.ship_value) # self.nebula.left, self.nebula.right, self.nebula.top, self.nebula.bottom ).ljust(self.ship_info_width-2) ) libtcod.console_blit(self.ship_info_console, 0, 0, self.ship_info_width, self.ship_info_height, 0, self.screen_width-self.ship_info_width, self.screen_height-self.ship_info_height-self.message_height, 1.0, 0.25) # Bottom Messages if len(self.messages) > 0: libtcod.console_print_ex(self.message_console, 0, 0, libtcod.BKGND_SET, libtcod.LEFT, "\n".join([message.ljust(self.message_width) for message in self.messages]) ) libtcod.console_blit(self.message_console, 0, 0, self.message_width, self.message_height, 0, 0, self.screen_height-self.message_height, 1.0, 0.25) # Minimap self.sector.draw_minimap(self.minimap_buffer, self.minimap_width, self.minimap_height, self.player_ship) self.minimap_buffer.blit(self.minimap_console) libtcod.console_print_frame(self.minimap_console, 0, 0, self.minimap_width, self.minimap_height, clear=False, flag=libtcod.BKGND_SET, fmt=0) libtcod.console_print_ex(self.minimap_console, 1, self.minimap_height-1, libtcod.BKGND_SET, libtcod.LEFT, ("[ {0} {1} ]").format( int(self.player_ship.sector_position_x), int(self.player_ship.sector_position_y), ).center(self.minimap_width-2, chr(196)) ) libtcod.console_blit(self.minimap_console, 0, 0, self.minimap_width, self.minimap_height, 0, self.screen_width-self.minimap_width, 0, 1.0, 0.25) libtcod.console_flush() self.buffer.clear(self.sector.background[0], self.sector.background[1], self.sector.background[2]) def handle_keys(self): if self.key.vk == libtcod.KEY_UP: self.player_ship.throttle_open = self.key.pressed if self.key.vk == libtcod.KEY_DOWN: self.player_ship.reversing = self.key.pressed if self.key.vk == libtcod.KEY_LEFT: self.player_ship.turning_left = self.key.pressed if self.key.vk == libtcod.KEY_RIGHT: self.player_ship.turning_right = self.key.pressed if self.key.vk == libtcod.KEY_SPACE: self.player_ship.laser_firing = self.key.pressed if self.key.pressed and self.key.vk == libtcod.KEY_ENTER and self.key.lalt: libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen()) elif self.key.pressed and self.key.vk == libtcod.KEY_ESCAPE: return 1 #exit game elif self.key.pressed: key_character = chr(self.key.c) if key_character == 'l' and self.current_screen == 'flight': landed, message, planet_index = self.sector.land_at_closest_planet(self.player_ship) if message: self.add_message(message) if landed: self.landed_loop(planet_index) elif key_character == 'G': self.player_ship.ship_value = getrandbits(32) self.player_ship.load_ship_sprites() elif self.key.vk == libtcod.KEY_TAB: if self.current_screen == 'flight': self.galaxy_map_loop() else: return 1 # exit galaxy loop elif key_character == '\\' and self.current_screen == 'galaxy': self.galaxy.cycle_sector_target() elif key_character == 'm': if self.minimap_width == self.screen_height: self.set_minimap(20) elif self.minimap_width == 23: self.set_minimap(20 + (self.screen_height-20)/2) else: self.set_minimap(self.screen_height-3) elif key_character == 'p': self.sector.cycle_planet_target(self.player_ship) elif key_character == 'P': self.sector.target_nearest_planet(self.player_ship) elif key_character == 't': self.sector.cycle_target(self.player_ship) elif key_character == 'T': self.sector.target_nearest_asteroid(self.player_ship) elif key_character == 'j' and self.current_screen == 'flight': self.new_sector() elif key_character == 'S': libtcod.sys_save_screenshot() self.add_message("Saved screenshot") def clear_messages(self): self.messages.clear() def add_message(self, message): if len(self.messages) == self.message_height: self.messages.popleft() self.messages.append(message) def galaxy_map_loop(self): self.current_screen = 'galaxy' done = False while not done: libtcod.sys_check_for_event(libtcod.KEY_PRESSED|libtcod.KEY_RELEASED|libtcod.EVENT_MOUSE, self.key, self.mouse) libtcod.console_clear(self.galaxy_map_console) self.starfield.draw() self.nebula.draw() self.galaxy.draw(self.buffer) self.buffer.blit(self.console) libtcod.console_blit(self.console, 0, 0, self.screen_width, self.screen_height, 0, 0, 0) # Galaxy Map Border/Frame libtcod.console_print_frame(self.galaxy_map_console, 0, 0, self.screen_width, self.screen_height, clear=False, flag=libtcod.BKGND_SET, fmt=0) # Title in the center of the top border top_title = "[ Galaxy Map ]" libtcod.console_print_ex(self.galaxy_map_console, (self.screen_width/2) - (len(top_title)/2), 0, libtcod.BKGND_SET, libtcod.LEFT, top_title) # Title in the center of the bottom border bottom_title = "[ Seed: {0} ]".format( self.galaxy.seed ) libtcod.console_print_ex(self.galaxy_map_console, (self.screen_width/2) - (len(bottom_title)/2), self.screen_height-1, libtcod.BKGND_SET, libtcod.LEFT, bottom_title) # Extra info in upper right info = ("Current Sector: {0}\n" "Target Sector: {1}\n").format( self.galaxy.sectors[self.galaxy.current_sector].name, self.galaxy.sectors[ self.galaxy.sectors[self.galaxy.current_sector].neighbors[self.galaxy.targeted_sector_index] ].name ) libtcod.console_print_ex(self.galaxy_map_console, 1, 1, libtcod.BKGND_SET, libtcod.LEFT, info) libtcod.console_blit(self.galaxy_map_console, 0, 0, self.screen_width, self.screen_height, 0, 0, 0, 1.0, 0.25) libtcod.console_flush() self.buffer.clear(self.sector.background[0], self.sector.background[1], self.sector.background[2]) player_action = self.handle_keys() if player_action == 1: done = True self.current_screen = 'flight' def landed_loop(self, planet_index): self.current_screen = 'landed' done = False planet = self.sector.planets[planet_index] while not done: libtcod.sys_check_for_event(libtcod.KEY_PRESSED|libtcod.KEY_RELEASED|libtcod.EVENT_MOUSE, self.key, self.mouse) self.starfield.draw() self.nebula.draw() planet.render_detail() self.buffer.blit(self.console) libtcod.console_blit(self.console, 0, 0, self.screen_width, self.screen_height, 0, 0, 0) libtcod.console_print_frame(self.landing_console, 0, 0, self.landing_screen_width, self.landing_screen_height, clear=True, flag=libtcod.BKGND_SET, fmt=0) title = "[ Landed at {0} ]".format(planet.name) libtcod.console_print_ex(self.landing_console, (self.landing_screen_width/2) - (len(title)/2), 0, libtcod.BKGND_SET, libtcod.LEFT, title) libtcod.console_print_ex(self.landing_console, 2, 2, libtcod.BKGND_SET, libtcod.LEFT, "Class: {0}".format(planet.planet_class.title())) libtcod.console_print_ex(self.landing_console, 2, 3, libtcod.BKGND_SET, libtcod.LEFT, "Diameter: {0}".format(planet.width)) libtcod.console_print_ex(self.landing_console, 2, 4, libtcod.BKGND_SET, libtcod.LEFT, "Seed: {0}".format(planet.seed)) libtcod.console_blit(self.landing_console, 0, 0, self.landing_screen_width, self.landing_screen_height, 0, self.screen_width/2, 2, 1.0, 0.25) libtcod.console_flush() self.buffer.clear(self.sector.background[0], self.sector.background[1], self.sector.background[2]) player_action = self.handle_keys() if player_action == 1: self.add_message("Taking off from {0}".format(planet.name)) self.current_screen = 'flight' done = True def main_loop(self): while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event(libtcod.KEY_PRESSED|libtcod.KEY_RELEASED|libtcod.EVENT_MOUSE, self.key, self.mouse) self.render_all() player_action = self.handle_keys() if player_action == 1: break if self.player_ship.throttle_open: self.player_ship.apply_thrust() if self.player_ship.laser_firing: self.player_ship.fire_laser() if self.player_ship.reversing: self.player_ship.reverse_direction() elif self.player_ship.turning_left: self.player_ship.turn_left() elif self.player_ship.turning_right: self.player_ship.turn_right()