upskill
@upskill (学 高島)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

ゲームの関数の作り方を教えてほしい泣

Q&A

Closed

解決したいこと

Python始めたての初心者です。
ゲームを開発するうえで必要な機能を関数として作りたいので教えていただきたいです。

作りたい機能
エネルギーに応じて何の技が出せるかの関数を作りたい。

1、エネルギーチャージ +1
2、バリア エネルギー -1
3、小技  エネルギー -2
4、大技  エネルギー -3

自分のターンでエネルギー量に応じて出せる技の選択肢が決まるような関数を作りたいです。
敵(CPU)はエネルギーに応じて出せる技をランダムに出せるようにしたいと考えています。

自分で試したこと

とりあえず、じゃんけんゲームは作ってみました。しかし、じゃんけんゲームはエネルギーチャージが必要ないので、行き詰まっている状態です。少しでもわかる方がいらっしゃればご教授ください。

0

3Answer

一応作ってみました.最初に持っているHPやエネルギー(MP),勝敗判定のところは明確なルールがわからないので適当です.望まれている関数はselect_action()が該当します.参考になれば幸いです.

class Player:
    action = [
        ("MP-Charge", +1, 0),
        ("Barrier", -1, 0),
        ("Weak Attack", -2, 1),
        ("Strong Attack", -3, 2)
    ]
    def __init__(self, name: str, hp: int = 5, mp: int = 0):
        self.name: str = name
        self.hp: int = hp
        self.mp: int = mp
    
    def select_action(self):
        print(f"Choise Your Action Number:")
        for n, (act, cost, damage) in enumerate(self.action):
            # MPに応じて何の技が出せるかの判定,可能な技を表示
            if -cost <= self.mp:
                print(f"No.{n} is {act:13}: {cost:+} and Damage: {damage}")

        # MPに応じて何の技が出せるかの判定, 不可な選択であれば再選択
        self.act: int = int(input("> "))
        while 0 > self.act or self.act >= len(self.action) or -self.action[self.act][1] > self.mp:
            self.act = int(input("choise correct number > "))
    
    def take_action(self, other):
        self.mp += self.action[self.act][1]
        self.hp -= other.action[other.act][2]

    def __str__(self):
        return f"{self.name}, (HP, MP): ({self.hp}, {self.mp})"
    
    def __lt__(self, other):
        return self.hp < other.hp

    def __le__(self, other):
        return self.hp <= other.hp

    def __gt__(self, other):
        return self.hp > other.hp
    
    def __ge__(self, other):
        return self.hp >= other.hp

    def __eq__(self, other):
        return self.hp == other.hp

    def __ne__(self, other):
        return self.hp != other.hp

from random import randint

class CPU(Player):
    def __init__(self, name: str, hp: int = 5, mp: int = 0):
        super().__init__(name, hp, mp)
    
    def select_action(self):
        self.act = randint(0, len(self.action) - 1)
        # MPに応じて何の技が出せるかの判定, 不可な選択であれば再選択
        while -self.action[self.act][1] > self.mp:
            self.act = randint(0, len(self.action) - 1)
        return self.act

class Cheater(CPU):
    def __init__(self, name: str = "Cheater", hp: int = 100, mp: int = 100):
        super().__init__(name, hp, mp)

class GameMaster:
    def __init__(self, p1: Player, p2: Player = CPU("CPU")):
        self.turn = 1
        self.p1: Player = p1
        self.p2: Player = p2
    
    def loop(self):
        print(f"Turn {self.turn}: {self.p1} vs {self.p2}")
        self.p1.select_action()
        self.p2.select_action()
        self.p1.take_action(self.p2)
        self.p2.take_action(self.p1)

        if max(self.p1.hp, self.p2.hp) <= 0:
            print("Draw")
            return False
        
        if self.p1.hp <= 0 or self.p2.hp <= 0:
            print(f"Winner: {max(self.p1, self.p2)}")
            return False
        
        self.turn += 1
        return True

if __name__ == "__main__":
    gm = GameMaster(Player("upskill"))
    while gm.loop():
        pass

    gm = GameMaster(Player("PondVillege"), Cheater())
    while gm.loop():
        pass

コメントは後日追記します.

エネルギーに応じて何の技が出せるか

を判定する際には,以下の比較を行いました.

MPに応じてcostのかかる技が出せるかどうか
-cost <= self.mp

この条件を満たせば技が出せるので,画面に表示を行うようにしました.

しかし,あくまで表示しただけで技を機能として保持しているので,不可能な技の指定を受け取らないように,その逆の条件を使うことも必要でした.こちらに関しては要求とは逆の判定文でわかりづらくてすいません.

技に対してMPが不足していたらTrueになる
 -self.action[self.act][1] > self.mp

先ほどの判定文とは比較演算子が逆のものになっただけです.質問で書かれていたような値の持ち方であれば,存在するMPとの比較のため正負反転の必要がありましたので,いずれにしろ上のような比較文になります.個人的には書く数字が増えて微妙な気持ちになりますが,移項して下のように書くのも良いと思います.今あるMPを消費1して負になったらダメって式ですね.

同上
0 > self.mp + self.action[self.act][1]

Cheaterクラスは1コストで100ダメージ出るように変えても面白そうですね.

  1. MPへ加算する値を保持しているのでこの書き方になります.負の値を加算する,すなわちMPを消費するというちょっとわかりづらい状態です.

2Like

@upskill さん

提案

提案になってしまい申し訳ありません。

実装の前に、まずはお勉強の次のステップとしてPythonの「クラス」というものを学ぶのはいかがでしょうか?

こういったところで、基礎を学べると思います。

例えば?

「エネルギーをチャージして、エネルギー量に応じてキャラクターは技を繰り出す」「自身と敵という概念があり、エネルギーを使うということは共通項目」といった実装を行うときに「クラス」を用いると素直に実装できるかなと(個人的に)思います。

例えばHumanクラスがあり、クラス変数にはenergyが定義されている。クラスメソッドにcherge()barrier()attack()メソッドがあり、これらを使えるかどうかは、クラス変数energyの大きさで決まる。みたいな実装を行えます。

と言われても、よくわからないと思いますが、クラスは避けては通れない道だと思うので、勉強してみてほしいです。

たとえばこんな感じ?

class Human:
  def __init__(self):
    self.energy = 0

  def charge(self):
    self.energy += 1

  def barrier(self):
    if self.energy >= 1:
      self.energy -= 1
      # バリアの具体的な処理
    else:
      # 失敗処理や選択できない旨など

  def attack(self):
    if self.energy >= 2:
      self.energy -= 2
      # 小技の具体的な処理
    else:
      # 失敗処理や選択できない旨など

  def special(self):
    if self.energy >= 3:
      self.energy -= 3
      # 大技の具体的な処理
    else:
      # 失敗処理や選択できない旨など

# クラスインスタンスの使い方 ざっくり
character = Human()
character.charge() # エネルギーチャージ

すごく適当な実装なので、このまま動くわけではありませんが、クラスを勉強していくとこういったものを身に着けていきます。

お詫び

「関数の実装を教えてください」というものだったので、質問の本質的な回答になっていないため申し訳ありません。

じゃんけんゲームの次のステップとして、「エネルギーを使ったバトル」を実装したい。

その前段階の準備として、「クラス」を身に着けてみてはいかがでしょうかという提案になります。

雑多の文章を失礼いたしました。

2Like

PondVillege様や RoaaaA様と同じく、
デザインパターンの「状態クラス」で実装されるとバグ混入が減らせるかと思いました.

やや情報は少ないですが、「状態クラス」のライブラリに該当する
Python の transitions パッケージは秀逸です.

0Like

Your answer might help someone💌