Mercurial > touhou
comparison eosd @ 373:6deab6ad8be8
Add the ability to save a replay.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sun, 05 Aug 2012 16:37:26 +0200 |
parents | 704bea2e4360 |
children | 8f2f3053906a |
comparison
equal
deleted
inserted
replaced
372:704bea2e4360 | 373:6deab6ad8be8 |
---|---|
25 from pytouhou.game.background import Background | 25 from pytouhou.game.background import Background |
26 from pytouhou.ui.gamerunner import GameRunner | 26 from pytouhou.ui.gamerunner import GameRunner |
27 from pytouhou.games.eosd import EoSDGame | 27 from pytouhou.games.eosd import EoSDGame |
28 from pytouhou.game.game import GameOver | 28 from pytouhou.game.game import GameOver |
29 from pytouhou.game.player import PlayerState | 29 from pytouhou.game.player import PlayerState |
30 from pytouhou.formats.t6rp import T6RP | 30 from pytouhou.formats.t6rp import T6RP, Level |
31 from pytouhou.utils.random import Random | 31 from pytouhou.utils.random import Random |
32 from pytouhou.vm.msgrunner import NextStage | 32 from pytouhou.vm.msgrunner import NextStage |
33 | 33 |
34 | 34 |
35 class EoSDGameBossRush(EoSDGame): | 35 class EoSDGameBossRush(EoSDGame): |
60 self.bullets = [bullet for bullet in self.bullets if bullet.frame > 1] | 60 self.bullets = [bullet for bullet in self.bullets if bullet.frame > 1] |
61 EoSDGame.cleanup(self) | 61 EoSDGame.cleanup(self) |
62 | 62 |
63 | 63 |
64 | 64 |
65 def main(path, data, stage_num, rank, character, replay, boss_rush, fps_limit, single_buffer, debug, fixed_pipeline): | 65 def main(path, data, stage_num, rank, character, replay, save_filename, |
66 boss_rush, fps_limit, single_buffer, debug, fixed_pipeline): | |
67 | |
66 resource_loader = Loader(path) | 68 resource_loader = Loader(path) |
67 | 69 |
68 try: | 70 try: |
69 resource_loader.scan_archives(data) | 71 resource_loader.scan_archives(data) |
70 except IOError: | 72 except IOError: |
87 with open(replay, 'rb') as file: | 89 with open(replay, 'rb') as file: |
88 replay = T6RP.read(file) | 90 replay = T6RP.read(file) |
89 rank = replay.rank | 91 rank = replay.rank |
90 character = replay.character | 92 character = replay.character |
91 | 93 |
94 save_keystates = None | |
95 if save_filename: | |
96 save_replay = T6RP() | |
97 save_replay.rank = rank | |
98 save_replay.character = character | |
99 | |
92 difficulty = 16 | 100 difficulty = 16 |
93 default_power = [0, 64, 128, 128, 128, 128, 0][stage_num - 1] | 101 default_power = [0, 64, 128, 128, 128, 128, 0][stage_num - 1] |
94 states = [PlayerState(character=character, power=default_power)] | 102 states = [PlayerState(character=character, power=default_power)] |
95 | 103 |
96 game_class = EoSDGameBossRush if boss_rush else EoSDGame | 104 game_class = EoSDGameBossRush if boss_rush else EoSDGame |
108 #TODO: see if the stored score is used or if it’s the one from the previous stage. | 116 #TODO: see if the stored score is used or if it’s the one from the previous stage. |
109 if stage_num != 1 and stage_num - 2 in replay.levels: | 117 if stage_num != 1 and stage_num - 2 in replay.levels: |
110 previous_level = replay.levels[stage_num - 1] | 118 previous_level = replay.levels[stage_num - 1] |
111 states[0].score = previous_level.score | 119 states[0].score = previous_level.score |
112 states[0].effective_score = previous_level.score | 120 states[0].effective_score = previous_level.score |
121 states[0].point_items = level.point_items | |
113 states[0].power = level.power | 122 states[0].power = level.power |
114 states[0].lives = level.lives | 123 states[0].lives = level.lives |
115 states[0].bombs = level.bombs | 124 states[0].bombs = level.bombs |
116 difficulty = level.difficulty | 125 difficulty = level.difficulty |
117 else: | 126 else: |
118 prng = None | 127 prng = Random() |
128 | |
129 if save_filename: | |
130 if not replay: | |
131 save_replay.levels[stage_num - 1] = level = Level() | |
132 level.score = states[0].score | |
133 level.random_seed = prng.seed | |
134 level.point_items = states[0].points | |
135 level.power = states[0].power | |
136 level.lives = states[0].lives | |
137 level.bombs = states[0].bombs | |
138 level.difficulty = difficulty | |
139 save_keystates = [] | |
119 | 140 |
120 # Load stage data | 141 # Load stage data |
121 stage = resource_loader.get_stage('stage%d.std' % stage_num) | 142 stage = resource_loader.get_stage('stage%d.std' % stage_num) |
122 | 143 |
123 game = game_class(resource_loader, states, stage_num, rank, difficulty, prng=prng, continues=continues) | 144 game = game_class(resource_loader, states, stage_num, rank, difficulty, prng=prng, continues=continues) |
124 | 145 |
125 background_anm_wrapper = resource_loader.get_anm_wrapper(('stg%dbg.anm' % stage_num,)) | 146 background_anm_wrapper = resource_loader.get_anm_wrapper(('stg%dbg.anm' % stage_num,)) |
126 background = Background(stage, background_anm_wrapper) | 147 background = Background(stage, background_anm_wrapper) |
127 | 148 |
128 # Main loop | 149 # Main loop |
129 runner.load_game(game, background, stage.bgms, replay) | 150 runner.load_game(game, background, stage.bgms, replay, save_keystates) |
130 try: | 151 try: |
131 runner.start() | 152 runner.start() |
132 break | 153 break |
133 except NextStage: | 154 except NextStage: |
134 game.music.pause() | 155 game.music.pause() |
137 stage_num += 1 | 158 stage_num += 1 |
138 states = [player.state.copy() for player in game.players] # if player.state.lives >= 0] | 159 states = [player.state.copy() for player in game.players] # if player.state.lives >= 0] |
139 except GameOver: | 160 except GameOver: |
140 print('Game over') | 161 print('Game over') |
141 break | 162 break |
163 finally: | |
164 if save_filename: | |
165 last_key = -1 | |
166 for time, key in enumerate(save_keystates): | |
167 if key != last_key: | |
168 level.keys.append((time, key, 0)) | |
169 last_key = key | |
170 | |
171 if save_filename: | |
172 with open(save_filename, 'wb+') as file: | |
173 save_replay.write(file) | |
142 | 174 |
143 | 175 |
144 pathsep = os.path.pathsep | 176 pathsep = os.path.pathsep |
145 default_data = (pathsep.join(('CM.DAT', 'th06*_CM.DAT', '*CM.DAT', '*cm.dat')), | 177 default_data = (pathsep.join(('CM.DAT', 'th06*_CM.DAT', '*CM.DAT', '*cm.dat')), |
146 pathsep.join(('ST.DAT', 'th6*ST.DAT', '*ST.DAT', '*st.dat')), | 178 pathsep.join(('ST.DAT', 'th6*ST.DAT', '*ST.DAT', '*st.dat')), |
155 parser.add_argument('-p', '--path', metavar='DIRECTORY', default='.', help='Game directory path.') | 187 parser.add_argument('-p', '--path', metavar='DIRECTORY', default='.', help='Game directory path.') |
156 parser.add_argument('-s', '--stage', metavar='STAGE', type=int, default=None, help='Stage, 1 to 7 (Extra).') | 188 parser.add_argument('-s', '--stage', metavar='STAGE', type=int, default=None, help='Stage, 1 to 7 (Extra).') |
157 parser.add_argument('-r', '--rank', metavar='RANK', type=int, default=0, help='Rank, from 0 (Easy, default) to 3 (Lunatic).') | 189 parser.add_argument('-r', '--rank', metavar='RANK', type=int, default=0, help='Rank, from 0 (Easy, default) to 3 (Lunatic).') |
158 parser.add_argument('-c', '--character', metavar='CHARACTER', type=int, default=0, help='Select the character to use, from 0 (ReimuA, default) to 3 (MarisaB).') | 190 parser.add_argument('-c', '--character', metavar='CHARACTER', type=int, default=0, help='Select the character to use, from 0 (ReimuA, default) to 3 (MarisaB).') |
159 parser.add_argument('--replay', metavar='REPLAY', help='Select a replay') | 191 parser.add_argument('--replay', metavar='REPLAY', help='Select a replay') |
192 parser.add_argument('--save-replay', metavar='REPLAY', help='Save the upcoming game into a replay file') | |
160 parser.add_argument('-b', '--boss-rush', action='store_true', help='Fight only bosses') | 193 parser.add_argument('-b', '--boss-rush', action='store_true', help='Fight only bosses') |
161 parser.add_argument('--single-buffer', action='store_true', help='Disable double buffering') | 194 parser.add_argument('--single-buffer', action='store_true', help='Disable double buffering') |
162 parser.add_argument('--fps-limit', metavar='FPS', default=60, type=int, help='Set fps limit') | 195 parser.add_argument('--fps-limit', metavar='FPS', default=60, type=int, help='Set fps limit') |
163 parser.add_argument('--debug', action='store_true', help='Set unlimited continues, and perhaps other debug features.') | 196 parser.add_argument('--debug', action='store_true', help='Set unlimited continues, and perhaps other debug features.') |
164 parser.add_argument('--fixed-pipeline', action='store_true', help='Use the fixed pipeline instead of the new programmable one.') | 197 parser.add_argument('--fixed-pipeline', action='store_true', help='Use the fixed pipeline instead of the new programmable one.') |
165 | 198 |
166 args = parser.parse_args() | 199 args = parser.parse_args() |
167 | 200 |
168 main(args.path, tuple(args.data), args.stage, args.rank, args.character, | 201 main(args.path, tuple(args.data), args.stage, args.rank, args.character, |
169 args.replay, args.boss_rush, args.fps_limit, args.single_buffer, | 202 args.replay, args.save_replay, args.boss_rush, args.fps_limit, |
170 args.debug, args.fixed_pipeline) | 203 args.single_buffer, args.debug, args.fixed_pipeline) |