Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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