def Init_Storms(): # This is rather slow. global storm_graphics storm_graphics = particle.Make_Particle_Effect(particle.Storm_Particle) global storm_sound storm_sound = sound.Persisting_Sound("stormdmg", "stormbeeps")
def Init_Aliens(): global alien_firing_sound alien_firing_sound = sound.Persisting_Sound("clicker")
def Main_Loop(screen, clock, xxx_todo_changeme, restore_pos, challenge): # Initialisation of screen things. (width, height) = xxx_todo_changeme menu_margin = height screen.fill((0, 0, 0)) # screen is black during init pygame.display.flip() tutor.Off() draw_obj.Flush_Draw_Obj_Cache() # in case of resize # Grid setup (w, h) = GRID_SIZE assert w == h Set_Grid_Size(height / h) # Windows.. game_screen_rect = Rect(0, 0, menu_margin, height) game_screen_surf = screen.subsurface(game_screen_rect) menu_area = screen.subsurface( Rect(menu_margin, 0, width - menu_margin, height)) menu_width = width - menu_margin # Constraint on resolution applied here: assert menu_width >= 100 def Sc(v): # Original values were for 800x600 - scale that # for whatever the user's screen res happens to be. return (v * height) / 600 margin = Sc(10) x1 = menu_margin + margin menu_width1 = menu_width - (margin * 2) picture = resource.Load_Image("headersm.jpg") picture_rect = picture.get_rect().inflate(10, 10) picture_rect.center = (x1 + (menu_width1 / 2), 0) picture_rect.top = margin picture_surf = screen.subsurface(picture_rect) stats_rect = Rect(x1, picture_rect.bottom + margin, menu_width1, Sc(120)) stats_surf = screen.subsurface(stats_rect) global_stats_rect = Rect(x1, stats_rect.bottom + margin, menu_width1, Sc(110)) global_stats_surf = screen.subsurface(global_stats_rect) controls_rect = Rect(x1, global_stats_rect.bottom + margin, menu_width1, height - (margin + global_stats_rect.bottom + margin)) controls_surf = screen.subsurface(controls_rect) def Special_Refresh(): extra.Tile_Texture( screen, "rivets.jpg", Rect(menu_margin, 0, menu_width, screen.get_rect().height)) edge = Rect(menu_margin, -10, menu_width + 10, screen.get_rect().height + 10) for r in [stats_rect, global_stats_rect, edge]: extra.Line_Edging(screen, r, False) r = picture.get_rect() r.center = picture_surf.get_rect().center extra.Line_Edging(picture_surf, r, False) picture_surf.blit(picture, r.topleft) Special_Refresh() stats_surf.fill((0, 0, 0)) FRAME_RATE = 35 alarm_sound = sound.Persisting_Sound("emergency") teaching = (challenge == MENU_TUTORIAL) # Game data holder g = Game_Data() g.version = startup.Get_Game_Version() g.sysinfo = extra.Get_System_Info() # Steam network initialisation g.net = Network(teaching) DIFFICULTY.Set(MENU_INTERMEDIATE) # Establish equilibrium with initial network. for i in range(300): g.net.Steam_Think() if (g.net.hub.Get_Pressure() >= PRESSURE_GOOD): if (DEBUG): print(i, 'steps required for equilibrium') break assert g.net.hub.Get_Pressure() >= PRESSURE_GOOD # UI setup ui = User_Interface(g.net, (width, height)) inputs = [(controls_rect, ui.Control_Mouse_Down, ui.Control_Mouse_Move), (game_screen_rect, ui.Game_Mouse_Down, ui.Game_Mouse_Move)] exit_options = [(MENU_MENU, "Exit to Main Menu", []), (MENU_QUIT, "Exit to " + extra.Get_OS(), [K_F10])] save_available = [(MENU_SAVE, "Save Game", []), (MENU_LOAD, "Restore Game", []), (None, None, [])] if (challenge == MENU_TUTORIAL): save_available = [] in_game_menu = menu.Menu([(None, None, []), (MENU_MUTE, "Toggle Sound", []), (None, None, [])] + save_available + [(MENU_HIDE, "Return to Game", [K_ESCAPE])] + exit_options) current_menu = in_game_menu flash = True loop_running = True quit = False stats_review = False in_game_menu.Select(None) mail.Initialise() rt_then = time.time() fps_count = 0 fps_time = rt_then autosave_timer = 0 if (restore_pos == None): DIFFICULTY.Set(challenge) # Game variables g.season = SEASON_START g.season_ends = 0 g.season_effect = 0 g.season_fx = Quiet_Season(g.net) g.work_units_used = 0 g.challenge = challenge g.difficulty_level = 1.0 g.work_timer = 0.1 g.game_ends_at = None g.game_running = True g.game_time = gametime.Game_Time() g.historian = [] g.historian_time = 0 g.win = False g.warning_given = False g.wu_integral = 0 mail.Set_Day(g.game_time.Get_Day()) def Summary(g): lev = dict() lev[MENU_TUTORIAL] = "a Tutorial" lev[MENU_BEGINNER] = "a Beginner" lev[MENU_INTERMEDIATE] = "an Intermediate" lev[MENU_EXPERT] = "an Expert" lev[MENU_PEACEFUL] = "a Peaceful" assert g.challenge != None assert g.challenge in lev New_Mail("You are playing " + lev[g.challenge] + " game.") New_Mail("Win the game by upgrading your city to tech level %u." % DIFFICULTY.CITY_MAX_TECH_LEVEL) # Almost ready to start... but are we starting # from a savegame? def Restore(g, cmd): (g2, result) = save_game.Load(g, cmd) if (result == None): g = g2 ui.net = g.net mail.Initialise() mail.Set_Day(g.game_time.Get_Day()) assert g.challenge != None DIFFICULTY.Set(g.challenge) New_Mail( f"Game restored. It is currently {g.season_fx.name} season.") else: New_Mail(result) return g if (restore_pos != None): g.challenge = MENU_INTERMEDIATE g = Restore(g, restore_pos) assert g.challenge != None Summary(g) if (g.challenge == MENU_TUTORIAL): tutor.On((menu_margin * 40) / 100) cur_time = g.game_time.time() # Main loop while (loop_running): if (g.game_running): flash = not flash menu_inhibit = ui.Is_Menu_Open() or not g.game_running # Insert delay... # Hmm, I'm not sure if I know what this does. clock.tick(FRAME_RATE) rt_now = time.time() rt_frame_length = rt_now - rt_then rt_then = rt_now fps_count += 1 if (fps_count > 100): if (DEBUG): print( f"{math.floor(float(fps_count) / (rt_now - fps_time))} fps" ) fps_time = rt_now fps_count = 0 if (not menu_inhibit): if (not tutor.Frozen()): g.game_time.Advance(rt_frame_length) draw_obj.Next_Frame() # Flashing lights on the various items cur_time = g.game_time.time() mail.Set_Day(g.game_time.Get_Day()) ui.Draw_Game(game_screen_surf, g.season_fx) # if ( flash ): # ui.Draw_Selection(picture_surf) if (g.challenge == MENU_TUTORIAL): until_next = [] elif (g.challenge == MENU_PEACEFUL): until_next = [((128, 128, 128), 12, "Peaceful mode")] else: until_next = [( (128, 128, 128), 12, f"{math.floor((g.season_ends - cur_time) + 1)} days until next season)" )] ui.Draw_Stats(stats_surf, [((128, 0, 128), 18, f"Day {g.game_time.Get_Day()}"), ((128, 128, 0), 18, g.season_fx.name + " season")] + until_next + g.season_fx.Get_Extra_Info()) ui.Draw_Controls(controls_surf) if (menu_inhibit): current_menu.Draw(screen) alarm_sound.Set(0.0) stats_back = (0, 0, 0) supply = g.net.hub.Get_Steam_Supply() demand = g.net.hub.Get_Steam_Demand() if (g.net.hub.Get_Pressure() < PRESSURE_DANGER): # You'll lose the game if you stay in this zone # for longer than a timeout. Also, an # alarm will sound. if (g.game_ends_at == None): sound.FX("steamcrit") g.warning_given = True New_Mail("Danger! The City needs more steam!", (255, 0, 0)) g.game_ends_at = cur_time + DIFFICULTY.GRACE_TIME New_Mail( f"Game will end on Day {g.game_ends_at} unless supplies are increased.", (255, 0, 0)) if (flash): demand_colour = (255, 0, 0) if (not menu_inhibit): alarm_sound.Set(0.6) else: demand_colour = (128, 0, 0) stats_back = (100, 0, 0) elif (g.net.hub.Get_Pressure() < PRESSURE_WARNING): g.game_ends_at = None if (flash): demand_colour = (255, 100, 0) if (not menu_inhibit): alarm_sound.Set(0.3) else: demand_colour = (128, 50, 0) stats_back = (50, 25, 0) else: if (g.warning_given): sound.FX("steamres") g.warning_given = False if (g.net.hub.Get_Pressure() < PRESSURE_OK): demand_colour = (128, 128, 0) else: demand_colour = (0, 128, 0) g.game_ends_at = None alarm_sound.Set(0.0) avw = g.net.hub.Get_Avail_Work_Units() wu_unused = avw - g.work_units_used if (not menu_inhibit): global_stats_surf.fill(stats_back) stats.Draw_Stats_Window( global_stats_surf, [(CITY_COLOUR, 18, "Steam Pressure"), (CITY_COLOUR, 18, "Supply : Demand"), (demand_colour, 24, f"{round(supply, 1)} : {round(demand, 1)}"), (None, None, g.net.hub.Get_Pressure_Meter()), (CITY_COLOUR, 0, ""), (CITY_COLOUR, 12, f"{wu_unused} of {avw} work units available"), (None, None, (wu_unused, (255, 0, 255), avw, (0, 0, 0)))]) if (g.challenge == MENU_TUTORIAL): tutor.Draw(screen, g) pygame.display.flip() if (not menu_inhibit): g.season_fx.Per_Frame(rt_frame_length) ui.Frame_Advance(rt_frame_length) # Timing effects if (g.work_timer <= cur_time): # Fixed periodic effects g.work_timer = cur_time + 0.1 g.wu_integral += wu_unused g.work_units_used = g.net.Work_Pulse( g.net.hub.Get_Avail_Work_Units()) g.net.Steam_Think() g.net.Expire_Popups() tutor.Examine_Game(g) if (g.season_effect <= cur_time): # Seasonal periodic effects g.season_effect = cur_time + g.season_fx.Get_Period() g.season_fx.Per_Period() if (((not tutor.Permit_Season_Change()) and (g.season == SEASON_QUIET)) or (g.challenge == MENU_PEACEFUL)): g.season_ends = cur_time + 2 if (g.season_ends <= cur_time): # Season change if (g.season == SEASON_START): g.season = SEASON_QUIET g.season_fx = Quiet_Season(g.net) elif ((g.season == SEASON_QUIET) or (g.season == SEASON_STORM)): g.season = SEASON_ALIEN g.season_fx = Alien_Season(g.net, g.difficulty_level) sound.FX("aliensappr") elif (g.season == SEASON_ALIEN): g.season = SEASON_QUAKE g.season_fx = Quake_Season(g.net, g.difficulty_level) if (not tutor.Active()): # hack... sound.FX("quakewarn") elif (g.season == SEASON_QUAKE): g.season = SEASON_STORM g.season_fx = Storm_Season(g.net, g.difficulty_level) g.difficulty_level *= 1.2 # 20% harder.. sound.FX("stormwarn") else: assert False g.season_ends = cur_time + LENGTH_OF_SEASON g.season_effect = cur_time + (g.season_fx.Get_Period() / 2) if (g.challenge != MENU_PEACEFUL): New_Mail(f"The {g.season_fx.name} season has started.", (200, 200, 200)) just_ended = False if ((g.game_ends_at != None) and (g.game_ends_at <= cur_time) and (g.game_running)): # Game over - you lose g.game_running = False New_Mail("The City ran out of steam.", (255, 0, 0)) New_Mail("Game Over!", (255, 255, 0)) sound.FX("krankor") just_ended = True elif ((g.net.hub.tech_level >= DIFFICULTY.CITY_MAX_TECH_LEVEL) and (g.game_running)): # Game over - you win! g.game_running = False g.win = True New_Mail("The City is now fully upgraded!", (255, 255, 255)) New_Mail("You have won the game!", (255, 255, 255)) sound.FX("applause") just_ended = True if (just_ended): current_menu = in_game_menu = menu.Menu( [(None, None, []), (MENU_REVIEW, "Review Statistics", [])] + exit_options) in_game_menu.Select(None) # Events e = pygame.event.poll() while (e.type != NOEVENT): if e.type == QUIT: loop_running = False quit = True elif e.type == MOUSEBUTTONDOWN or e.type == MOUSEMOTION: if e.type == MOUSEBUTTONDOWN and e.button != 1: if not menu_inhibit: ui.Right_Mouse_Down() elif not menu_inhibit: for rect, click, move in inputs: if rect.collidepoint(e.pos): (x, y) = e.pos x -= rect.left y -= rect.top if e.type == MOUSEMOTION: move((x, y)) else: click((x, y)) elif menu_inhibit: if e.type == MOUSEMOTION: current_menu.Mouse_Move(e.pos) else: current_menu.Mouse_Down(e.pos) elif e.type == KEYDOWN: if not menu_inhibit: ui.Key_Press(e.key) elif menu_inhibit: current_menu.Key_Press(e.key) if DEBUG: # Cheats. if e.key == K_F10: New_Mail("Cheat used: Advanced to next season.") g.season_ends = 0 elif e.key == K_F9: New_Mail("Cheat used: Screen filled with white.") screen.fill((255, 255, 255)) elif e.key == K_F8: # Lose the game cheat # Heh, worst cheat ever. New_Mail("Cheat used: Game ended.") g.game_ends_at = cur_time e = pygame.event.poll() # Any commands from the menu? if menu_inhibit: cmd = current_menu.Get_Command() current_menu.Select(None) # consume command if current_menu == in_game_menu: # It's the normal menu. if cmd == MENU_QUIT: loop_running = False quit = True ui.Reset() # makes menu disappear elif cmd == MENU_MENU: loop_running = False ui.Reset() elif cmd == MENU_SAVE: if (g.game_running): # Switch to alternate menu current_menu = save_menu.Save_Menu(True) elif cmd == MENU_LOAD: current_menu = save_menu.Save_Menu(False) elif cmd == MENU_MUTE: config.cfg.mute = not config.cfg.mute ui.Reset() elif cmd == MENU_REVIEW: loop_running = False stats_review = True ui.Reset() elif cmd != None: # Default option - back to game if (not g.game_running): New_Mail("Sorry - the game has finished") ui.Reset() else: # It's another menu! That means it's the save menu. if cmd != None and cmd >= 0: if not current_menu.Is_Saving(): g = Restore(g, cmd) else: label = f"Day {math.floor(g.game_time.Get_Day())} - {g.season_fx.name} season - {time.asctime()}" g.net.Make_Ready_For_Save() result = save_game.Save(g, cmd, label) if result == None: New_Mail("Game saved.") else: New_Mail(result) if cmd != None: # Back to game. Special_Refresh() current_menu = in_game_menu ui.Reset() if autosave_timer <= cur_time and g.game_running and DEBUG and not menu_inhibit: # Autosave is slow, so it's really a debugging feature. save_game.Save(g, 11, "Autosave") autosave_timer = cur_time + 60 if (g.historian_time <= cur_time) and (g.game_running) and (not menu_inhibit): g.historian.append(review.Analyse_Network(g)) g.historian_time = cur_time + 4 tutor.Off() # About to exit. Blackout. screen.fill((0, 0, 0)) if (stats_review): review.Review(screen, (width, height), g, g.historian) return quit
def Init_Quakes(): global quake_sound quake_sound = sound.Persisting_Sound("earthquake")
for r in [stats_rect, global_stats_rect, edge]: extra.Line_Edging(screen, r, False) r = picture.get_rect() r.center = picture_surf.get_rect().center extra.Line_Edging(picture_surf, r, False) picture_surf.blit(picture, r.topleft) Special_Refresh() stats_surf.fill((0, 0, 0)) FRAME_RATE = 35 alarm_sound = sound.Persisting_Sound("emergency") teaching = (challenge == MENU_TUTORIAL) # Game data holder g = Game_Data() g.version = startup.Get_Game_Version() g.sysinfo = extra.Get_System_Info() # Steam network initialisation g.net = Network(teaching) DIFFICULTY.Set(MENU_INTERMEDIATE) # Establish equilibrium with initial network. for i in xrange(300):
def Main_Loop(restore_pos): global game # Initialisation of screen things. (width, height) = screen.Update_Resolution() menu_margin = height screen.surface.fill(BLACK) pygame.display.flip() tutor.Off() draw_obj.Flush_Draw_Obj_Cache() # in case of resize # Grid setup (w, h) = GRID_SIZE assert w == h Set_Grid_Size(height / h) # Right-hand side windows are removed game_screen_rect = Rect(SCROLL_MARGIN, SCROLL_MARGIN, width - (SCROLL_MARGIN * 2), height - (SCROLL_MARGIN * 2)) game_screen_surf = screen.surface.subsurface(game_screen_rect) menu_button_rect = Rect(0, 0, SCROLL_MARGIN * 3, SCROLL_MARGIN * 3) alarm_sound = sound.Persisting_Sound("emergency") # UI setup ui = User_Interface(game.net, (width, height), game.bg_number) exit_options = [(MENU_MENU, "Exit to Main Menu", []), (MENU_QUIT, "Exit to " + extra.Get_OS(), [K_F10])] save_available = [(MENU_SAVE, "Save Game", []), (MENU_LOAD, "Restore Game", []), (None, None, [])] if (game.challenge == MENU_TUTORIAL): save_available = [] in_game_menu = menu.Menu([(None, None, []), (MENU_MUTE, "Toggle Sound", []), (None, None, [])] + save_available + [(MENU_HIDE, "Return to Game", [K_ESCAPE])] + exit_options) current_menu = in_game_menu flash = True quit_state = MENU_LOOP_RUN in_game_menu.Select(None) mail.Initialise() autosave_timer = 0 DIFFICULTY.Set(game.challenge) def Summary(): lev = dict() lev[MENU_TUTORIAL] = "a Tutorial" lev[MENU_BEGINNER] = "a Beginner" lev[MENU_INTERMEDIATE] = "an Intermediate" lev[MENU_EXPERT] = "an Expert" assert game.challenge != None assert lev.has_key(game.challenge) New_Mail("You are playing " + lev[game.challenge] + " game.") # Almost ready to start... but are we starting # from a savegame? def Restore(cmd): global game (g2, result) = save_game.Load(game, cmd) if (result == None): game = g2 ui.net = game.net mail.Initialise() assert game.challenge != None DIFFICULTY.Set(game.challenge) New_Mail("Game restored. It is the " + game.season_fx.name + " season.") else: New_Mail(result) if (restore_pos != None): game.challenge = MENU_INTERMEDIATE Restore(restore_pos) assert game.challenge != None Summary() if (game.challenge == MENU_TUTORIAL): tutor.On((menu_margin * 40) / 100) # In Game - Main loop while (quit_state == MENU_LOOP_RUN): if (game.game_running): flash = not flash draw_obj.Next_Frame() # Flashing lights on the various items ui.Draw_Game(game_screen_surf, game.season_fx) pygame.draw.rect(screen.surface, CYAN, menu_button_rect) game.season_fx.Per_Frame(1) ui.Frame_Advance() game.net.Compute() pygame.display.flip() screen.clock.tick(FRAME_RATE) # Events e = screen.Get_Event(False) while (e.type != NOEVENT): if e.type == QUIT: quit_state = MENU_QUIT break elif e.type == VIDEORESIZE: quit_state = MENU_RESIZE_EVENT elif ((e.type == MOUSEBUTTONDOWN) and (e.button == BUTTON_LEFT)): # Left mouse down (x, y) = e.pos if menu_button_rect.collidepoint(e.pos): # on menu button quit_state = MENU_MENU elif game_screen_rect.collidepoint(e.pos): # on game window ui.Game_Mouse_Down( (x - game_screen_rect.left, y - game_screen_rect.top)) else: # on scrollbar pass elif (e.type == MOUSEMOTION): (x, y) = e.pos ui.Game_Mouse_Move( (x - game_screen_rect.left, y - game_screen_rect.top)) elif ((e.type == MOUSEBUTTONUP) and (e.button == BUTTON_LEFT)): (x, y) = e.pos ui.Game_Mouse_Up( (x - game_screen_rect.left, y - game_screen_rect.top)) elif e.type == KEYDOWN: ui.Key_Press(e.key) elif ((e.type == MOUSEBUTTONDOWN) and (e.button != BUTTON_LEFT)): ui.Right_Mouse_Down() e = screen.Get_Event(False) tutor.Off() alarm_sound.Set(0.0) if quit_state != MENU_MENU: return quit_state # In Game - Menu quit_state = MENU_LOOP_RUN while quit_state == MENU_LOOP_RUN: current_menu.Draw(screen.surface) pygame.display.flip() screen.clock.tick(FRAME_RATE) # Events e = screen.Get_Event(True) while (e.type != NOEVENT): if e.type == QUIT: quit_state = MENU_QUIT break elif e.type == VIDEORESIZE: quit_state = MENU_RESIZE_EVENT elif ((e.type == MOUSEBUTTONDOWN) and (e.button == BUTTON_LEFT)): current_menu.Mouse_Down(e.pos) elif e.type == MOUSEMOTION: current_menu.Mouse_Move(e.pos) elif e.type == KEYDOWN: current_menu.Key_Press(e.key) e = screen.Get_Event(False) cmd = current_menu.Get_Command() current_menu.Select(None) # consume command if (current_menu == in_game_menu): # It's the normal menu. if (cmd == MENU_QUIT): quit_state = MENU_QUIT ui.Reset() # makes menu disappear elif (cmd == MENU_MENU): quit_state = MENU_MENU ui.Reset() elif (cmd == MENU_SAVE): if (game.game_running): # Switch to alternate menu current_menu = save_menu.Save_Menu(True) elif (cmd == MENU_LOAD): current_menu = save_menu.Save_Menu(False) elif (cmd == MENU_REVIEW): quit_state = MENU_REVIEW ui.Reset() elif (cmd != None): # Default option - back to game if (not game.game_running): New_Mail("Sorry - the game has finished") ui.Reset() else: # It's another menu! That means it's the save menu. if ((cmd != None) and (cmd >= 0)): if (not current_menu.Is_Saving()): Restore(cmd) else: label = "%s season - %s" % (game.season_fx.name, time.asctime()) game.net.Make_Ready_For_Save() result = save_game.Save(game, cmd, label) if (result == None): New_Mail("Game saved.") else: New_Mail(result) if (cmd != None): # Back to game. Special_Refresh() current_menu = in_game_menu ui.Reset() return quit_state