def __init__(self): # ゲームの名前 self.name = "TEST" # ゲームの状態 self.state = State.START self.turn = Turn.EGO # ゲームの設定 # palette=[0x000000, 0x1D2B53, 0x7E2553, 0x008751, 0xAB5236, 0x5F574F, 0xC2C3C7, 0xFFF1E8, 0xFF004D, 0xFFA300, 0xFFEC27, 0x00E436, 0x29ADFF, 0x83769C, 0xFF77A8, 0xFFCCAA] pyxel.init(256, 256, caption=self.name, scale=2, fps=12) #, palette=palette) pyxel.load("my_resource.pyxres") pyxel.playm(0, loop=True) # SE pyxel.sound(10).set("A3", "N", "3", "F", 20) # 剣を振る pyxel.sound(11).set("F2RRF2RRF2RRF2RR", "N", "6", "F", 10) # 階段 pyxel.sound(12).set("C1", "N", "6", "F", 15) # 攻撃があたる pyxel.sound(13).set("A3", "T", "3", "F", 20) # 敵の攻撃 # 画面切り替え時間 self.change_view_timer = 13 # [frames] 1secくらいまつ self.change_turn_timer = 6 # [frames] self.exp_table = {} for lv in range(1, 100): self.exp_table[lv] = int(lv**2 * 1.5) + 4 # フロア self.floor = 0 # [F] # タイミング self.tick = 0 # 地図 self.map = Maze(96, 64) self.num_col_rooms = 3 self.num_row_rooms = 2 self.corrider_width = 1 self.map.create_map_dungeon(num_col_rooms=self.num_col_rooms, num_row_rooms=self.num_row_rooms, corrider_width=self.corrider_width, max_room_size_ratio=0.3, min_room_size_ratio=0.2) self.map.set_goal() # 見たことある場所 self.is_seen = np.zeros((self.map.h, self.map.w), dtype=bool) self.occupancy = np.zeros((self.map.h, self.map.w), dtype=bool) # キャラとかアイテムがある場所 # 自キャラの初期化, map.dataの16倍の位置 yx = self.map.get_free_space(num=1) self.ego = Man(yx[1], yx[0], 11, Direction.UP, hitpoints=50, max_hitpoints=50) self.occupancy[yx[0], yx[1]] = True # 敵キャラの配置 self.num_enemies = 4 # np.random.randint(2, 5) self.enemies = [] for _ in range(self.num_enemies): yx = self.map.get_free_space(num=1) enemy = Enemy(yx[1], yx[0], 14, Direction.UP, hitpoints=9, max_hitpoints=9) enemy.set_route(deque()) self.enemies.append(enemy) self.occupancy[yx[0], yx[1]] = True # 自分中心で描画可能な範囲だけを取り出しち地図と、その左右上下のマージン self.local_data, self.margins = self.map.get_local_data( self.ego.y, self.ego.x) # 画面上での自キャラの位置 # 基本は画面中央で、画面端のときだけ視覚中央からはずれる # TODO: 直接メンバを触っているので変すること self.ego.vx = self.margins[0] * 16 self.ego.vy = self.margins[2] * 16 for ene in self.enemies: ene.vx = self.ego.vx + (ene.x - self.ego.x) * 16 ene.vy = self.ego.vy + (ene.y - self.ego.y) * 16 # 実行 pyxel.run(self.update, self.draw)
def update(self): """ 状態を変更する関数。毎フレーム呼ばれる。 敵の行動は自分が行動した後に実行される """ if self.state == State.START: # 開始演出 if (pyxel.btn(pyxel.KEY_S)): self.state = State.MAIN if (pyxel.btn(pyxel.KEY_DOWN)): self.use_random_map = False if (pyxel.btn(pyxel.KEY_UP)): self.use_random_map = True elif self.state == State.MAIN: # ボタン操作受付 if (pyxel.btn(pyxel.KEY_Q)): self.state == State.MENU return # if (pyxel.btn(pyxel.KEY_Y)): # ボタン操作がなかったので動作 if self.turn == Turn.EGO: # 自キャラの操作うけつけ # 攻撃するか移動するか(道具をつかうかなど。) if not self.ego.moved: if (pyxel.btn(pyxel.KEY_W)): self.ego.moved = True self.ego.attacked = True attacked_cell = [self.ego.x, self.ego.y] if self.ego.d == Direction.UP: dx = 0 dy = -1 elif self.ego.d == Direction.RIGHT: dx = 1 dy = 0 elif self.ego.d == Direction.DOWN: dx = 0 dy = 1 elif self.ego.d == Direction.LEFT: dx = -1 dy = 0 attacked_cell[0] += dx attacked_cell[1] += dy if not self.ego.moved: self.move_target(self.ego) # 攻撃の結果を更新 if self.ego.attacked: for idx, enemy in enumerate(self.enemies): if enemy.x == attacked_cell[ 0] and enemy.y == attacked_cell[1]: # 敵の体力を減らす enemy.hitpoints -= int( self.ego.strength - enemy.defense / 2.0 ) if self.ego.strength - enemy.defense / 2.0 else 1 pyxel.play(3, [12]) # 攻撃があたる音 # 敵の体力が0以下なら、殺す if enemy.hitpoints <= 0: self.occupancy[enemy.y, enemy.x] = False # 殺す前に解放 enemy.kill() # TODO: リストからの削除をすること self.ego.exp += enemy.exp del self.enemies[idx] # TODO: デストラクでOCCを解放したい # レベルアップ判定 while self.ego.exp > self.exp_table[self.ego.lv + 1]: self.ego.level_up() # 音でもならす if self.ego.moved and self.ego.attacked: self.turn = Turn.WAIT elif self.ego.moved: self.turn = Turn.ENEMY if self.turn == Turn.ENEMY: # 敵キャラの行動 # TODO 順番にうごいてほしい for enemy in self.enemies: if enemy.hitpoints > 0: self.act_enemy(enemy) if enemy.attacked: pyxel.play(3, [12]) # 攻撃があたる音 self.ego.hitpoints -= int( enemy.strength - self.ego.defense / 2.0 ) if enemy.strength - self.ego.defense / 2.0 > 0 else 0 # enemy.attacked = False self.turn = Turn.EGO if self.turn == Turn.WAIT: self.change_turn_timer -= 1 if self.change_turn_timer == 0: self.turn = Turn.ENEMY self.change_turn_timer = 6 # 画面内に表示される分だけのローカル地図 self.local_data, self.margins = self.map.get_local_data( self.ego.y, self.ego.x) # 探索済みのフラグ更新 cx = int(self.ego.x) cy = int(self.ego.y) lsmx, rsmx, usmy, dsmy = self.margins for i in range(self.map.w): for j in range(self.map.h): if cx - lsmx < i < cx + rsmx and cy - usmy < j < cy + dsmy: self.is_seen[j, i] = True # 描画用時計 if pyxel.frame_count % 5 == 0: self.tick += 1 # ゴール判定 if self.map.data[cy, cx] == -1 and self.map.data[self.ego.py, self.ego.px] != -1: self.state = State.QUESTION # 死亡判定 if self.ego.hitpoints <= 0: self.state = State.END # updateの最後に自キャラの行動フラグをクリア self.ego.moved = False elif self.state == State.QUESTION: if (pyxel.btn(pyxel.KEY_Y)): self.state = State.CHANGE pyxel.play(3, [11]) # 階段をおりる音 elif (pyxel.btn(pyxel.KEY_N)): self.state = State.MAIN elif self.state == State.CHANGE: # 急に画面が切り替わらないように少しまつ if self.change_view_timer > 0: self.change_view_timer -= 1 return self.change_view_timer = 13 # 初期化 self.map.create_map_dungeon(num_col_rooms=self.num_col_rooms, num_row_rooms=self.num_row_rooms, corrider_width=self.corrider_width, max_room_size_ratio=0.8, min_room_size_ratio=0.2) self.map.set_goal() # 見たことある場所 self.is_seen = np.zeros((self.map.h, self.map.w), dtype=bool) self.occupancy = np.zeros((self.map.h, self.map.w), dtype=bool) # キャラとかアイテムがある場所 # 自キャラの初期化, map.dataの16倍の位置 yx = self.map.get_free_space(num=1) self.ego.update(yx[1], yx[0]) self.occupancy[yx[0], yx[1]] = True # 敵キャラの配置 self.enemies = [] self.num_enemies for _ in range(self.num_enemies): yx = self.map.get_free_space(num=1) self.occupancy[yx[0], yx[1]] = True enemy = Enemy(yx[1], yx[0], 14, Direction.UP) enemy.set_route(deque()) self.enemies.append(enemy) # 自分両中心で描画可能な範囲だけを取り出しち地図と、その左右上下のマージン self.local_data, self.margins = self.map.get_local_data( self.ego.y, self.ego.x) self.ego.vx = self.margins[0] * 16 self.ego.vy = self.margins[2] * 16 for ene in self.enemies: ene.vx = self.ego.vx + (ene.x - self.ego.x) * 16 ene.vy = self.ego.vy + (ene.y - self.ego.y) * 16 self.floor += 1 self.state = State.MAIN elif self.state == State.MENU: # 所有品のカーソル操作受付 pass elif self.state == State.END: pass