# HG changeset patch # User Thibaut Girka # Date 1317763922 -7200 # Node ID 5cf927cbd9c58fff9cdc0649322735df94379455 # Parent 4f46717390aa8c8119760639b2ebe79ab11fd201 Merge GameState into Game. TODO: Merge PlayerState into Player diff --git a/pytouhou/game/bullet.py b/pytouhou/game/bullet.py --- a/pytouhou/game/bullet.py +++ b/pytouhou/game/bullet.py @@ -21,8 +21,8 @@ from pytouhou.game.sprite import Sprite class Bullet(object): def __init__(self, pos, bullet_type, sprite_idx_offset, - angle, speed, attributes, flags, player, game_state): - self._game_state = game_state + angle, speed, attributes, flags, player, game): + self._game = game self._sprite = None self._anmrunner = None self._removed = False diff --git a/pytouhou/game/enemy.py b/pytouhou/game/enemy.py --- a/pytouhou/game/enemy.py +++ b/pytouhou/game/enemy.py @@ -22,8 +22,8 @@ from math import cos, sin, atan2, pi class Enemy(object): - def __init__(self, pos, life, _type, anm_wrapper, game_state, pop_enemy): - self._game_state = game_state + def __init__(self, pos, life, _type, anm_wrapper, game, pop_enemy): + self._game = game self._anm_wrapper = anm_wrapper self._sprite = None self._anmrunner = None @@ -86,7 +86,7 @@ class Enemy(object): (type_, type_idx, sprite_idx_offset, bullets_per_shot, number_of_shots, speed, speed2, launch_angle, angle, flags) = self.bullet_attributes - bullet_type = self._game_state.bullet_types[type_idx] + bullet_type = self._game.bullet_types[type_idx] ox, oy = self.bullet_launch_offset launch_pos = self.x + ox, self.y + oy @@ -107,8 +107,8 @@ class Enemy(object): if type_ != 75: launch_angle -= angle * (bullets_per_shot - 1) / 2. - bullets = self._game_state.bullets - nb_bullets_max = self._game_state.nb_bullets_max + bullets = self._game.bullets + nb_bullets_max = self._game.nb_bullets_max for shot_nb in range(number_of_shots): shot_speed = speed if shot_nb == 0 else speed + (speed2 - speed) * float(shot_nb) / float(number_of_shots) @@ -118,18 +118,18 @@ class Enemy(object): break if type_ == 75: # 102h.exe@0x4138cf - bullet_angle = self._game_state.prng.rand_double() * (launch_angle - angle) + angle + bullet_angle = self._game.prng.rand_double() * (launch_angle - angle) + angle if type_ in (74, 75): # 102h.exe@0x4138cf - shot_speed = self._game_state.prng.rand_double() * (speed - speed2) + speed2 + shot_speed = self._game.prng.rand_double() * (speed - speed2) + speed2 bullets.append(Bullet(launch_pos, bullet_type, sprite_idx_offset, bullet_angle, shot_speed, self.extended_bullet_attributes, - flags, player, self._game_state)) + flags, player, self._game)) bullet_angle += angle def select_player(self, players=None): - return (players or self._game_state.players)[0] #TODO + return (players or self._game.players)[0] #TODO def get_player_angle(self, player=None, pos=None): @@ -147,12 +147,12 @@ class Enemy(object): def set_pos(self, x, y, z): self.x, self.y = x, y self.interpolator = Interpolator((x, y)) - self.interpolator.set_interpolation_start(self._game_state.frame, (x, y)) + self.interpolator.set_interpolation_start(self._game.frame, (x, y)) def move_to(self, duration, x, y, z, formula): if not self.interpolator: - frame = self._game_state.frame + frame = self._game.frame self.interpolator = Interpolator((self.x, self.y), formula) self.interpolator.set_interpolation_start(frame, (self.x, self.y)) self.interpolator.set_interpolation_end(frame + duration - 1, (x, y)) @@ -163,7 +163,7 @@ class Enemy(object): def stop_in(self, duration, formula): if not self.speed_interpolator: - frame = self._game_state.frame + frame = self._game.frame self.speed_interpolator = Interpolator((self.speed,), formula) self.speed_interpolator.set_interpolation_start(frame, (self.speed,)) self.speed_interpolator.set_interpolation_end(frame + duration - 1, (0.,)) @@ -194,7 +194,7 @@ class Enemy(object): def update(self): x, y = self.x, self.y if self.interpolator: - self.interpolator.update(self._game_state.frame) + self.interpolator.update(self._game.frame) x, y = self.interpolator.values self.speed += self.acceleration #TODO: units? Execution order? @@ -202,7 +202,7 @@ class Enemy(object): if self.speed_interpolator: - self.speed_interpolator.update(self._game_state.frame) + self.speed_interpolator.update(self._game.frame) self.speed, = self.speed_interpolator.values diff --git a/pytouhou/game/game.py b/pytouhou/game/game.py --- a/pytouhou/game/game.py +++ b/pytouhou/game/game.py @@ -22,29 +22,34 @@ from pytouhou.game.enemy import Enemy from pytouhou.game.item import Item -class GameState(object): - __slots__ = ('resource_loader', 'bullets', 'items', 'players', 'rank', 'difficulty', 'frame', - 'stage', 'boss', 'prng', 'bullet_types', 'item_types', 'characters', 'nb_bullets_max') - def __init__(self, resource_loader, players, stage, rank, difficulty, - bullet_types, item_types, characters, nb_bullets_max): + +class Game(object): + def __init__(self, resource_loader, player_states, stage, rank, difficulty, + bullet_types, item_types, characters, nb_bullets_max=None): self.resource_loader = resource_loader + self.nb_bullets_max = nb_bullets_max self.bullet_types = bullet_types self.item_types = item_types self.characters = characters + self.players = [Player(player_state, characters[player_state.character]) for player_state in player_states] + self.enemies = [] self.bullets = [] self.items = [] - self.nb_bullets_max = nb_bullets_max self.stage = stage - self.players = players self.rank = rank self.difficulty = difficulty self.boss = None self.prng = Random() self.frame = 0 + self.enm_anm_wrapper = resource_loader.get_anm_wrapper2(('stg%denm.anm' % stage, + 'stg%denm2.anm' % stage)) + ecl = resource_loader.get_ecl('ecldata%d.ecl' % stage) + self.ecl_runner = ECLMainRunner(ecl, self.new_enemy, self) + def change_bullets_into_star_items(self): player = self.players[0] #TODO @@ -53,27 +58,8 @@ class GameState(object): self.bullets = [] - -class Game(object): - def __init__(self, resource_loader, player_states, stage, rank, difficulty, - bullet_types, item_types, characters, nb_bullets_max=None): - self.game_state = GameState(resource_loader, player_states, stage, - rank, difficulty, - bullet_types, item_types, characters, nb_bullets_max) - - self.players = [Player(player_state, characters[player_state.character]) for player_state in player_states] - self.enemies = [] - - self.bonuses = [] - - self.enm_anm_wrapper = resource_loader.get_anm_wrapper2(('stg%denm.anm' % stage, - 'stg%denm2.anm' % stage)) - ecl = resource_loader.get_ecl('ecldata%d.ecl' % stage) - self.ecl_runner = ECLMainRunner(ecl, self.new_enemy, self.game_state) - - def new_enemy(self, pos, life, instr_type, pop_enemy): - enemy = Enemy(pos, life, instr_type, self.enm_anm_wrapper, self.game_state, pop_enemy) + enemy = Enemy(pos, life, instr_type, self.enm_anm_wrapper, self, pop_enemy) self.enemies.append(enemy) return enemy @@ -101,10 +87,10 @@ class Game(object): for enemy in self.enemies: enemy.update() - for bullet in self.game_state.bullets: + for bullet in self.bullets: bullet.update() - for item in self.game_state.items: + for item in self.items: item.update() # 4. Check for collisions! @@ -114,7 +100,7 @@ class Game(object): phalf_size = player.hitbox_half_size px1, px2 = px - phalf_size, px + phalf_size py1, py2 = py - phalf_size, py + phalf_size - for bullet in self.game_state.bullets: + for bullet in self.bullets: half_size = bullet.hitbox_half_size bx, by = bullet.x, bullet.y bx1, bx2 = bx - half_size, bx + half_size @@ -130,7 +116,7 @@ class Game(object): # 5. Cleaning self.cleanup() - self.game_state.frame += 1 + self.frame += 1 def cleanup(self): @@ -145,9 +131,9 @@ class Game(object): # Filter out-of-scren bullets # TODO: was_visible thing - self.game_state.bullets = [bullet for bullet in self.game_state.bullets if bullet.is_visible(384, 448)] + self.bullets = [bullet for bullet in self.bullets if bullet.is_visible(384, 448)] # Disable boss mode if it is dead/it has timeout - if self.game_state.boss and self.game_state.boss._removed: - self.game_state.boss = None + if self.boss and self.boss._removed: + self.boss = None diff --git a/pytouhou/game/item.py b/pytouhou/game/item.py --- a/pytouhou/game/item.py +++ b/pytouhou/game/item.py @@ -17,8 +17,8 @@ from math import cos, sin, atan2, pi class Item(object): - def __init__(self, pos, item_type, angle, speed, player, game_state): - self._game_state = game_state + def __init__(self, pos, item_type, angle, speed, player, game): + self._game = game self._sprite = item_type.sprite self._removed = False self._item_type = item_type diff --git a/pytouhou/opengl/gamerenderer.pyx b/pytouhou/opengl/gamerenderer.pyx --- a/pytouhou/opengl/gamerenderer.pyx +++ b/pytouhou/opengl/gamerenderer.pyx @@ -151,8 +151,8 @@ cdef class GameRenderer: glDisable(GL_FOG) self.render_elements(game.enemies) self.render_elements(game.players) - self.render_elements(game.game_state.bullets) - self.render_elements(game.game_state.items) + self.render_elements(game.bullets) + self.render_elements(game.items) #TODO: display item indicators glEnable(GL_FOG) diff --git a/pytouhou/opengl/gamerunner.py b/pytouhou/opengl/gamerunner.py --- a/pytouhou/opengl/gamerunner.py +++ b/pytouhou/opengl/gamerunner.py @@ -86,7 +86,7 @@ class GameRunner(pyglet.window.Window, G def update(self): if self.background: - self.background.update(self.game.game_state.frame) + self.background.update(self.game.frame) if self.game: #TODO: allow user settings keystate = 0 diff --git a/pytouhou/vm/eclrunner.py b/pytouhou/vm/eclrunner.py --- a/pytouhou/vm/eclrunner.py +++ b/pytouhou/vm/eclrunner.py @@ -25,13 +25,13 @@ logger = get_logger(__name__) class ECLMainRunner(object): __metaclass__ = MetaRegistry - __slots__ = ('_ecl', '_new_enemy_func', '_game_state', 'processes', + __slots__ = ('_ecl', '_new_enemy_func', '_game', 'processes', 'instruction_pointer') - def __init__(self, ecl, new_enemy_func, game_state): + def __init__(self, ecl, new_enemy_func, game): self._ecl = ecl self._new_enemy_func = new_enemy_func - self._game_state = game_state + self._game = game self.processes = [] @@ -45,12 +45,12 @@ class ECLMainRunner(object): except IndexError: break - if frame > self._game_state.frame: + if frame > self._game.frame: break else: self.instruction_pointer += 1 - if frame == self._game_state.frame: + if frame == self._game.frame: try: callback = self._handlers[instr_type] except KeyError: @@ -65,13 +65,13 @@ class ECLMainRunner(object): def _pop_enemy(self, sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3): if instr_type & 4: if x < -990: #102h.exe@0x411820 - x = self._game_state.prng.rand_double() * 368 + x = self._game.prng.rand_double() * 368 if y < -990: #102h.exe@0x41184b - y = self._game_state.prng.rand_double() * 416 + y = self._game.prng.rand_double() * 416 if z < -990: #102h.exe@0x411881 - y = self._game_state.prng.rand_double() * 800 + y = self._game.prng.rand_double() * 800 enemy = self._new_enemy_func((x, y), life, instr_type, self._pop_enemy) - process = ECLRunner(self._ecl, sub, enemy, self._game_state) + process = ECLRunner(self._ecl, sub, enemy, self._game) self.processes.append(process) process.run_iteration() @@ -81,7 +81,7 @@ class ECLMainRunner(object): @instruction(4) @instruction(6) def pop_enemy(self, sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3): - if self._game_state.boss: + if self._game.boss: return self._pop_enemy(sub, instr_type, x, y, z, life, bonus_dropped, unknown2, unknown3) @@ -90,14 +90,14 @@ class ECLMainRunner(object): class ECLRunner(object): __metaclass__ = MetaRegistry - __slots__ = ('_ecl', '_enemy', '_game_state', 'variables', 'sub', 'frame', + __slots__ = ('_ecl', '_enemy', '_game', 'variables', 'sub', 'frame', 'instruction_pointer', 'comparison_reg', 'stack') - def __init__(self, ecl, sub, enemy, game_state): + def __init__(self, ecl, sub, enemy, game): # Things not supposed to change self._ecl = ecl self._enemy = enemy - self._game_state = game_state + self._game = game # Things supposed to change (and be put in the stack) self.variables = [0, 0, 0, 0, @@ -159,7 +159,7 @@ class ECLRunner(object): #TODO: skip bad ranks - if not rank_mask & (0x100 << self._game_state.rank): + if not rank_mask & (0x100 << self._game.rank): continue @@ -181,9 +181,9 @@ class ECLRunner(object): return self.variables[int(-10001-value)] elif -10025 <= value <= -10013: if value == -10013: - return self._game_state.rank + return self._game.rank elif value == -10014: - return self._game_state.difficulty + return self._game.difficulty elif value == -10015: return self._enemy.x elif value == -10016: @@ -203,7 +203,7 @@ class ECLRunner(object): elif value == -10024: return self._enemy.life elif value == -10025: - return self._enemy.select_player().character + return self._enemy.select_player().state.character #TODO raise NotImplementedError(value) #TODO else: return value @@ -274,19 +274,19 @@ class ECLRunner(object): def set_random_int(self, variable_id, maxval): """Set the specified variable to a random int in the [0, maxval) range. """ - self._setval(variable_id, int(self._getval(maxval) * self._game_state.prng.rand_double())) + self._setval(variable_id, int(self._getval(maxval) * self._game.prng.rand_double())) @instruction(8) def set_random_float(self, variable_id, maxval): """Set the specified variable to a random float in [0, maxval) range. """ - self._setval(variable_id, self._getval(maxval) * self._game_state.prng.rand_double()) + self._setval(variable_id, self._getval(maxval) * self._game.prng.rand_double()) @instruction(9) def set_random_float2(self, variable_id, amp, minval): - self._setval(variable_id, self._getval(minval) + self._getval(amp) * self._game_state.prng.rand_double()) + self._setval(variable_id, self._getval(minval) + self._getval(amp) * self._game.prng.rand_double()) @instruction(10) @@ -443,7 +443,7 @@ class ECLRunner(object): @instruction(49) def set_random_angle(self, min_angle, max_angle): - angle = self._game_state.prng.rand_double() * (max_angle - min_angle) + min_angle + angle = self._game.prng.rand_double() * (max_angle - min_angle) + min_angle self._enemy.angle = angle @@ -454,7 +454,7 @@ class ECLRunner(object): else: minx, miny, maxx, maxy = (0., 0., 0., 0.) - angle = self._game_state.prng.rand_double() * (max_angle - min_angle) + min_angle + angle = self._game.prng.rand_double() * (max_angle - min_angle) + min_angle sa, ca = sin(angle), cos(angle) distx = min(96.0, (maxx - minx) / 2.) @@ -635,7 +635,7 @@ class ECLRunner(object): @instruction(77) def set_bullet_interval_ex(self, value): self._enemy.bullet_launch_interval = value - self._enemy.bullet_launch_timer = int(self._game_state.prng.rand_double() * value) #TODO: check + self._enemy.bullet_launch_timer = int(self._game.prng.rand_double() * value) #TODO: check @instruction(78) @@ -660,7 +660,7 @@ class ECLRunner(object): @instruction(83) def change_bullets_into_star_items(self): - self._game_state.change_bullets_into_star_items() + self._game.change_bullets_into_star_items() @instruction(93) @@ -693,7 +693,7 @@ class ECLRunner(object): @instruction(101) def set_boss_mode(self, unknown): #TODO: unknown - self._game_state.boss = self._enemy + self._game.boss = self._enemy @instruction(103) @@ -787,14 +787,14 @@ class ECLRunner(object): def call_special_function(self, function, arg): if function == 0: # Cirno if arg == 0: - for bullet in self._game_state.bullets: + for bullet in self._game.bullets: bullet.speed = bullet.angle = 0. bullet.delta = (0., 0.) bullet.set_anim(sprite_idx_offset=15) #TODO: check else: - for bullet in self._game_state.bullets: + for bullet in self._game.bullets: bullet.speed = 2.0 #TODO - bullet.angle = self._game_state.prng.rand_double() * pi #TODO + bullet.angle = self._game.prng.rand_double() * pi #TODO bullet.delta = (cos(bullet.angle) * bullet.speed, sin(bullet.angle) * bullet.speed) else: logger.warn("Unimplemented special function %d!", function)