通常のWindowsコンソールで私が作った本格的なゲーム

こんにちは!



今日は、コマンドラインでゲームをどのように作成したか、そしてどのようにうまくいったかについて詳しく説明します。



アイデアはどこから来たのですか?



私は一見簡単なことをするというアイデアに触発されましたが、同時に開発の面でも興味深いものです。コンソールでゲームを作るという発想が思い浮かびましたが、開発的には面白く、このゲームのように外から見ても面白くなります



ゲームエンジン



それで、ゲームがルートでどのように編成されているか、そしてその仕事の考え方は何であるかから始めましょう。



まず、ゲームの世界をコンソールにどのように表示するかを決めました。ゲームオブジェクトを表示するには、シンボルを含む他のリストを格納するリストが必要であることに気付きました。これらのリストは、後でループで競技場に表示されますfor



このコードで:



for line_words in OUTPUT_IMAGE:
       for word in line_words:
           print(word, end="")
       print("\n", end="")


ここでは、リストからすべての文字を描画し、新しい行に移動して次の文字のリストを描画します。



シンボルのリストを格納する変数は次のようになります。



画像



ここで、オブジェクトをXとYで表示する方法をすぐに決定し、次のように指定できます。X-



リスト内のシンボル

Y-Xを含むリスト

したがって、フィールドにシンボルを描画します。 ..。これは、ゲームオブジェクトを描画するときに使用します。



XとYを「O」の文字に置き換えて、フィールドに「ボール」を描くことを試みることができます。



これを行うには、次のコードを記述します。



import os
OUTPUT_IMAGE = [
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        ]

OUTPUT_IMAGE[4][6] = "O"
os.system("cls||clear")
for line_words in OUTPUT_IMAGE:
       for word in line_words:
           print(word, end="")
       print("\n", end="")



画像



そして、私たちは自分たちの競技場にオブジェクトを描きました。確かに、X座標とY座標は古典的ではありません。まず、最初にYを示し、次にXを示しますが、これは古典に完全には一致していません。次に、オブジェクトを上げるためにY座標を増やす必要があります。この場合、逆に、Y座標を減らす必要があります。



ゲーム内のXとYのグラフ:



画像



この機能は、後でコンソールでオブジェクトの衝突を行うときにも考慮する必要があります。



これで、オブジェクトを競技場全体に移動してみることができます。動きを作成します。



競技場の古い写真を消去するには、コンソールをクリアする必要があります。

次のコマンドでこれを行います。



os.system("cls||clear")


また、OUTPUT_IMAGE以前に競技場に描かれたすべてのオブジェクトをクリアするには、変数をオーバーライドする必要があります



また、これらすべてをに入れる必要がありますwhile TrueFPSを制限するために関数



追加しましょう そのため、コードは目の前に描かれました。while Truetime.sleep(1)







from time import sleep
from os import system
OUTPUT_IMAGE = [
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
        ]

x = 0
y = 0
while True:
      sleep(1)
      system("cls||clear")
      OUTPUT_IMAGE[y][x] = "O"
      for line_words in OUTPUT_IMAGE:
             for word in line_words:
                 print(word, end="")
             print("\n", end="")
      y += 1
      x += 1
      OUTPUT_IMAGE = [
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            ]


画像



これで、フィールド全体にオブジェクトを分散することができます。



確かに、これらのオブジェクトは原始的すぎて、プレーヤー、家、食べ物などの複雑なオブジェクトを描画する方法を学ぶ



必要があります...複雑なオブジェクトを描画するには、XとYを1回だけ指定して、オブジェクトを描画する方法を理解して理解する必要があります。



これには、画像(記号)、X、Yを受け入れる関数。



これをやろう:



def SetImage(image: str, x: int, y: int):
    pass


次に、それを実装する必要があります。これを行うには、X軸とY軸に沿って伸びる画像を描画する方法を決定する必要があります。私はこれを思いつきまし

た。オブジェクトをシンボルに分割して描画し、「\ n」文字が見つかったらすぐに、Y軸を追加します。



前述のように、Y軸は正しくありません。逆になっているので、オブジェクトを下げるために追加します。



私の原則に従って描かれた画像の例:



image = " O\n'|'\n |"#


それでは、これを関数で説明しましょう。



def SetImage(x: int, y: int, image: str):
  x_start = x
  x = x
  y = y
  for word in image:
      if word == "\n":
          x = x_start
          y += 1
      else:
          x += 1
          try:
            OUTPUT_IMAGE[y][x] = word
          except IndexError:
              break


try: except()オブジェクトのXとYが小さすぎるか大きすぎる場合のエラーを回避するために、 追加してみましょう



x_startこれはXであり、Yを増やすときに描画を開始する必要があります(「\ n」



文字を使用。これで、関数を使用して、XとYをその中にドロップし、描画する必要のある画像を作成できます。



コード
from time import sleep
from os import system
OUTPUT_IMAGE = [
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      ]

def SetImage(x: int, y: int, image: str):
  x_start = x
  x = x
  y = y
  for word in image:
      if word == "\n":
          x = x_start
          y += 1
      else:
          x += 1
          try:
            OUTPUT_IMAGE[y][x] = word
          except IndexError:
              break
while True:
      sleep(1)
      system("cls||clear")
      SetImage(x=3,y=4,image=" O\n'|'\n |")
      for line_words in OUTPUT_IMAGE:
             for word in line_words:
                 print(word, end="")
             print("\n", end="")
      OUTPUT_IMAGE = [
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            ]




そして、これが私たちが得たものです。私たちが



画像



描いたボールと同じように、X軸とY軸に沿って移動することができます。



コード
from time import sleep
from os import system
OUTPUT_IMAGE = [
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      ]
px = 0
py = 0
def SetImage(x: int, y: int, image: str):
  x_start = x
  x = x
  y = y
  for word in image:
      if word == "\n":
          x = x_start
          y += 1
      else:
          x += 1
          try:
            OUTPUT_IMAGE[y][x] = word
          except IndexError:
              break
while True:
      sleep(1)
      system("cls||clear")
      SetImage(x=px,y=py,image=" O\n'|'\n |")
      for line_words in OUTPUT_IMAGE:
             for word in line_words:
                 print(word, end="")
             print("\n", end="")
      px += 1
      py += 1
      OUTPUT_IMAGE = [
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            ]




画像



そして今、プレイヤーはすでにマップを動き回っています。



ここでは、すでに多くのことを行っており、プレーヤーも、マップもあり、ゲームを作成することはすでに可能であるように見えますが、そうではありません。オブジェクトの相互作用がないのはどのようなゲームなので、オブジェクトの衝突を計算するための関数が必要です。それでは始めましょう。



まず、ヒットボックスを計算するために、オブジェクトの緯度と高さを取得する関数を作成する必要があります。



そこで、次のロジックに従って関数を作成することにしました



。X-X幅のオブジェクトのヒットボックス、これは画像

Yの文字「\ n」間の最大文字数です-Yのヒットボックスは画像の文字「\ n」の数です



このロジックでは難しくありません写真を撮り、「\ n」の間のすべての文字を数え、そこから最大数の文字を選択する関数を作成します。緯度が取得されます。

そして、私がすでに書いたように、文字「\ n」を数えると、高さがわかります。



関数は次のようになりました。



def GetSizeObject(img: str):
    w = 0
    weights = []
    h = [word for word in img if word == "\n"]

    for word in img:
      if word == "\n":
          weights.append(w)
          w = 0
      else:
          w += 1
      try:
          return {"w": max(weights), "h":len(h)}
      except ValueError:
            return {"w": 0, "h":0}



ここ以外でValueErrorが発生するのはなぜですか?
.



それでは、プレーヤーを描画して、その幅と長さを計算しましょう。



緯度と高さを描画および計算するコード
from time import sleep
from os import system
OUTPUT_IMAGE = [
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      ]
px = 3
py = 3
def SetImage(x: int, y: int, image: str):
    global OUTPUT_IMAGE      
    x_start = x
    x = x
    y = y
    for word in image:
        if word == "\n":
            x = x_start
            y += 1
        else:
            x += 1
            try:
              OUTPUT_IMAGE[y][x] = word
            except IndexError:
                break

def GetSizeObject(img: str):
    w = 0
    weights = []
    h = [word for word in img if word == "\n"]
    h.append(1)

    for word in img:
        if word == "\n":
            weights.append(w)
            w = 0
        else:
            w += 1
    try:
        return {"w": max(weights), "h":len(h)}
    except ValueError:
        return {"w": 0, "h":0}

player_image = " O\n'|'\n |"
def draw():
      global OUTPUT_IMAGE
      sleep(1)
      system("cls||clear")
      for line_words in OUTPUT_IMAGE:
             for word in line_words:
                 print(word, end="")
             print("\n", end="")
      OUTPUT_IMAGE = [
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            ]
while True:
    SetImage(x=px,y=py,image=player_image)
    print(GetSizeObject(img=player_image))
    draw()





やったー!緯度と高さを計算する関数があります。次に、ヒットボックスとオブジェクトの衝突を計算する関数を作成する必要があります。



私たちの座標系は古典的なものではないので、残念ながら、古典的な関数を使用することはできません。独自に作成する必要があります。これを行うために、衝突するグラフに2つの正方形を描画しました。この図から、衝突が計算される条件を考え出すことができます。



わかりやすくするために、ヒットボックスを描画しました。四角:



画像



言葉での論理




x — X

y — Y

h —

w —

x2 — X

y2 — Y

h2 —

w2 —



:





y y2 - h2 + h y - h y2 + h2 - h



y2 y - h + h2 y2 - h2 y + h - h2

2 ?
2 , - / .



Y



X, Y, yx, hw.



:



x x2 - w2 + w x - w x2 + w2 - w







x2 x - w + w2 x2 - w2 x + w - w2



X



コード内のロジック
, :



def IsClash(x: int, y: int, h: int, w: int,x2: int, y2: int, h2: int, w2: int):
    if (y >= y2 - h2 + h and y - h <= y2 + h2 - h) or (y2 >= y - h + h2 and y2 - h2 <= y + h - h2):
        if (x >= x2 - w2 + w and x - w <= x2 + w2 - w) or (x2 >= x - w + w2 and x2 - w2 <= x + w - w2):
            return True

    return False


True , False .



プレイヤーが誰かと向き合うことができるように、私は競技場に追加のキューブを描きました。



そして、衝突計算機能のしくみを試してみました。



キューブに触れているプレーヤーは次のとおりです。



画像



ただし、触れていない:



画像



連絡先コード
/ :



from time import sleep
from os import system
OUTPUT_IMAGE = [
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
      ]

def SetImage(x: int, y: int, image: str):
    global OUTPUT_IMAGE      
    x_start = x
    x = x
    y = y
    for word in image:
        if word == "\n":
            x = x_start
            y += 1
        else:
            x += 1
            try:
              OUTPUT_IMAGE[y][x] = word
            except IndexError:
                break

def GetSizeObject(img: str):
    w = 0
    weights = []
    h = [word for word in img if word == "\n"]
    h.append(1)

    for word in img:
        if word == "\n":
            weights.append(w)
            w = 0
        else:
            w += 1
    try:
        return {"w": max(weights), "h":len(h)}
    except ValueError:
        return {"w": 0, "h":0}

def IsClash(x: int, y: int, h: int, w: int,x2: int, y2: int, h2: int, w2: int):
    if (y >= y2 - h2 + h and y - h <= y2 + h2 - h) or (y2 >= y - h + h2 and y2 - h2 <= y + h - h2):
        if (x >= x2 - w2 + w and x - w <= x2 + w2 - w) or (x2 >= x - w + w2 and x2 - w2 <= x + w - w2):
            return True

    return False

player_image = " O\n'|'\n |"
cube_image = "____\n|  |\n----"
cx = 5#
cy = 4  #          
px = 10  #
py = 3#
def draw():
      global OUTPUT_IMAGE
      sleep(1)
      system("cls||clear")
      for line_words in OUTPUT_IMAGE:
             for word in line_words:
                 print(word, end="")
             print("\n", end="")
      OUTPUT_IMAGE = [
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
            ]
while True:
    SetImage(x=px,y=py,image=player_image)
    SetImage(x=cx,y=cy,image=cube_image)
    print("is clash: ",IsClash(
      x=px,
      x2=cx,
      y=py,
      y2=cy,
      h=GetSizeObject(img=player_image)["h"],
      h2=GetSizeObject(img=cube_image)["h"],
      w=GetSizeObject(img=player_image)["w"],
      w2=GetSizeObject(img=cube_image)["w"],
      ))
    draw()





これでゲームの開始機能がすべて揃いました。実際、私はそれらに基づいてゲームを作成しました。



ゲーム



ゲームのアイデアは次のとおりです:



プレーヤーがいて、食べ物が彼の周りに現れ、彼は死なないようにそれを集めることを余儀なくされています。ゲームには機能もあります:食べ物を拾い、それをあなたの在庫に入れ、あなたの在庫からそれを食べ、あなたの在庫からアイテムを



床に置きます.3行でゲームループを作ることから始めました、それは簡単While Trueです:



from time import sleep
while True:
    sleep(0.1)


次に、将来のオブジェクトのすべての機能が格納されるクラスを作成する必要があると考えました。そのため、main.pyファイルとlibフォルダーを作成し、その中にゲームクラスが含まれるlib.pyファイルを配置しました。これら。ゲームファイルは次のようになりました。



+----game
|    + -- 
|    | -- main.py
|    \ --lib
|         +--lib.py -> class Game()
|         \
|
+---


将来的には、主にGame()クラスで作業し、main.pyでそれを呼び出し、開始オブジェクトを作成し、ゲームを開始しました。



ゲームクラスでは、ゲームループを開始するrun()関数を作成しました。また、draw_all()関数を作成し、過去のすべてのオブジェクトを消去し、新しいオブジェクトを描画して、プレイフィールドに出力します。



そして、これはクラスがどのように見えたかです:



from time import sleep


class Game():
    def __init__(self):
        self.OUTPUT_IMAGE = []  #   

    def draw_all(self):
        for line_words in self.OUTPUT_IMAGE:
            for word in line_words:
                print(word, end="")
            print("\n", end="")

    def run(self):
        while True:
            self.draw_all()
            sleep(0.1)



私はタイプのすべての基本的な機能を追加したset_image() size_object()is_clash()、およびゲームエンジンですすべての人々 、そしてその私が上記しています。



新機能メイドcreate_object()、変数self.OBJECTS、関数create_object()、私はオブジェクトを作成するために使用し、それはパラメータを取りimgnamexyuprigiddata



img-オブジェクト画像-オブジェクト

name名(家、草、住民、食べ物など)

x-Xオブジェクト

y-Yオブジェクト

up-このパラメータがTrueの場合、オブジェクトはプレーヤーの上に描画されます。それ以外の場合、プレーヤーはそれをオーバーラップします

rigid-硬度、プレーヤーはできませんこのオブジェクトを通過します(まだ実装されていません)

data-オブジェクトの個人データ、その個人的な特徴



create_object()
:



def CreateObject(self,x: int, y: int, img: str, name: str = None, up: bool = False, rigid: bool = False, data: dict = {}):
    size_object = self.GetSizeObject(img=img)
    self.OBJECTS.append(
        {"name": name,
         "x": x,
         "y": y,
         "up": up,
         "rigid": rigid,
         "h":size_object["h"],
         "w":size_object["w"],
         "id":uuid4().hex,
         "data":data,
         "img": img}
    )




その時、私はすでにプレーヤー、家、草、そして村人を追加しました。



そして、オブジェクトup同じパラメータを使用することにしましたHome。つまり、オブジェクトで使用します。家がプレーヤーを覆うように。これを行うために、CheckAll()関数を作成し、forループがすべてのオブジェクトを通過し、それらを送信画像に描画しました。 SetImage(x:int、y:int、img:str)関数を使用して、オブジェクトのXとY、および画像を指定します。



したがって、彼はプレイヤーが自分自身を閉じることができるオブジェクトを描きました。同じサイクルで、リストを宣言しup_of_payer_objects、オブジェクトのup = Trueの場合、フィールドに描画せずにリストに追加しました。その後、私は自分でプレーヤーを描きました。それから、up_of_payer_objects内のオブジェクトのforループを通過して描画しました。したがって、それらはプレーヤーの上にありました。



def CheckAll(self):
    up_of_payer_objects = []
    for object_now in range(len(self.OBJECTS)):
        if object_now["up"]:
            up_of_payer_objects.append(object_now)
            continue
        self.SetImage(x=object_now["x"],y=object_now["y"],image=object_now["img"])


それから私はプレーヤーを動かし始めました。このために、リストにはないがself.OBJECTS変数に格納されている別のオブジェクトとして作成しましたself.PLAYER



すべてのそのパラメータの種類に応じてXYimg、ITPキーを使用して取得できます。つまり、辞書(dict)です。そのようなプレーヤーとオブジェクトを使用すると、衝突の作業、移動、計算がすでに可能でした。私は引っ越しから始めました。

キーストロークの追跡を担当し、最初にCheckAll()関数で呼び出すCheckKeysObjects()関数を作成することから、モーションの作成を開始しました。



def CheckAll(self):
    self.CheckKeysObjects()
    ....


キーストロークを追跡するために、キーボードライブラリと4つの変数を使用しました すべてが単純であることが判明し、キーを追跡し、キーが押された場合は変数を作成します 関数の最初に、過去のすべての結果をリセットするため、のすべての変数を宣言します。そうしないと、プレーヤーは停止しません。



self.WALK_LEFT_PLAYER

self.WALK_RIGHT_PLAYER

self.WALK_UP_PLAYER

self.WALK_DOWN_PLAYER



dself.WALK_RIGHT_PLAYERTrue



False



CheckKeysObjects()
def CheckKeysObjects(self):
    #    False,    
    self.WALK_LEFT_PLAYER = False
    self.WALK_RIGHT_PLAYER = False
    self.WALK_UP_PLAYER = False
    self.WALK_DOWN_PLAYER = False
    #    
    if keyboard.is_pressed("a"):
        self.WALK_LEFT_PLAYER = True
    elif keyboard.is_pressed("d"):
        self.WALK_RIGHT_PLAYER = True
    if keyboard.is_pressed("w"):
        self.WALK_UP_PLAYER = True
    elif keyboard.is_pressed("s"):
        self.WALK_DOWN_PLAYER = True




その後、関数でCheckAll()、動きの原因となるすべての変数チェックし、プレーヤーがどこに動いているかを調べます。



中にあるものがある場合は、どれをTrue見つけて、オブジェクトを反対方向に移動します。



結果の移動コード
def CheckAll(self):
    self.CheckKeysObjects()  # check moves
    up_of_payer_objects = []
    for object_now in range(len(self.OBJECTS)):
        self.PLAYER["img"] = self.PLAYER["image_normal"]
        if self.WALK_LEFT_PLAYER:
            self.OBJECTS[object_now]["x"] += 1

        elif self.WALK_RIGHT_PLAYER:
            self.OBJECTS[object_now]["x"] -= 1


        if self.WALK_UP_PLAYER:

            self.OBJECTS[object_now]["y"] += 1
        elif self.WALK_DOWN_PLAYER:

            self.OBJECTS[object_now]["y"] -= 1




はい、動きの錯覚を作り出すために、オブジェクトを反対方向に動かします。プレイヤーが右に行くと、環境のすべてのオブジェクトが左にシフトします。



それから環境アイテムを追加して、食べ物を産み始めました。プレイヤーの目標は、死なないように食べ物を集めることです。



フードスポーン時間のカウントダウンには、シンプルなtime.sleep()ものとライブラリを使用してthreading、フードスポーンとメインゲームループの2つの機能を同時に実行しました。フードスポーン機能SpawnEat()は、起動時にランダムな場所で食べ物を生成し、食べ物の単位ごとに関数を呼び出す関数ですCreateObject()



また、フードスポーン機能を作ったら、プレイヤー用の変数を作りましたself.PLAYER["hungry"]、これは彼の空腹です。最初は100ユニットに相当します。プレーヤーが歩いてエネルギーを消費する場合(エネルギーなど、ゲーム内にない場合)は減少し、プレーヤーが何かを食べた場合は増加します。



私も関数を作りましたMinimizeHungry()、それは5秒ごとに呼び出され、それはプレイヤーから2ユニットの空腹を取ります。これは、プレイヤーが静止せずに移動する必要があるようにするためです。



最後に、関数ではEat()、この関数はゲームループとは別のスレッドで呼び出されます。彼女は、食べ物が10単位を超えている場合、マップ上に食べ物が多すぎるかどうかを確認します。SpawnEat()10ユニット未満の場合、関数は呼び出されません次にを呼び出しますSpawnEat()



結果は次のとおりです。



食べる()
def Eat(self):
    while True:
        sleep(4)
        if len([i for i in self.OBJECTS if i["name"] == "meat"]) < 10:
            self.SpawnEat()
        sleep(1)
        self.MinimizeHungry()




Start()メインループを開始する 関数



開始()
def Start(self):
    while True:  
        self.CheckAll()
        self.DrawAll()
        sleep(0.01)




そして、run()ゲーム全体を起動する機能



実行()
def run(self):
    proc1 = threading.Thread(target=self.Start)
    proc1.start()
    proc2 = threading.Thread(target=self.Eat)
    proc2.start()




自分自身を食べるプロセス、私は関数CheckAll()とで簡単に実装しましたCheckKeysObjects()QCheckKeysObjects()プレーヤーがボタンを押したかどうかを確認しましたE押された場合は、変数をself.PRESS_E入れますTrue



ループCheckAll()では、ループ内の現在のオブジェクトがfor食べ物であるかどうか、食べ物がプレーヤーが衝突したかどうか、衝突したかどうか、変数をチェックしたself.PRESS_Eかどうか、Trueそして単にオブジェクトを削除して空腹感が増したかどうかを確認しました変数self.PLAYER["hungry"]



これがコードの内容です
for object_now in range(len(self.OBJECTS)):
    ....
    if self.OBJECTS[object_now]["name"] == "meat":
        items_objects.append(object_now)
        is_clash = self.IsClash(
            x=self.OBJECTS[object_now]["x"],
            y=self.OBJECTS[object_now]["y"],
            h=self.OBJECTS[object_now]["h"],
            w=self.OBJECTS[object_now]["w"],
            x2=self.PLAYER["x"],
            y2=self.PLAYER["y"],
            h2=self.PLAYER["h"],
            w2=self.PLAYER["w"],
        )

        if is_clash:
            if self.PRESS_E:
                try:
                    self.PLAYER["hungry"] += self.HUNGRUY_ADD
                    del self.OBJECTS[object_now]
                    break

                except IndexError:
                    pass




事前に言いますが、インベントリを作成するときは、これをすべて書き直す必要があります


在庫を作る



ですから、難しいので、在庫を作る必要があります。



難しいのは、すべてのオブジェクトを表示し、履歴を保存し、削除し、床にオブジェクトを配置する必要があることです。



プレーヤーに新しいキーを追加することから始めました。次のようにself.PLAYER["inventory"]、4つのセルがそこに保存されます。



"inventory":{
    "0":{"status":"space","name":"#0", "minimize_image":"#0"},
    "1":{"status":"space","name":"#1", "minimize_image":"#1"},
    "2":{"status":"space","name":"#2", "minimize_image":"#2"},
    "3":{"status":"space","name":"#3", "minimize_image":"#3"},
}


単なるセル番号です。



status-このキーはそれ自体に値を格納します。卵のセルは空かどうかです。空の場合は「スペース」、アイテムがある場合はアイテムの名前がそこに保存されます。



name-アイテムの名前を格納します。プレーヤーがアイテムを置くときに使用されます。



minimize_image-これは、プレーヤーのインベントリに表示されるアイテムの小さな写真です。



その後、新しいチェックを行いCheckKeysObjects()ました。Xアイテムをクリックすると地面に投げられ、ボタンをクリックEすると関数が呼び出されself.UseEat()ます。これを分析します。



だから関数self.UseEat()は、食品を探して在庫のすべてのセルを通過する通路です。食品が見つかった場合は、在庫から削除され、10ユニットが空腹に追加されます。インベントリからアイテムを削除するためにself.DestroyItem()、セルインデックスが提供される関数を作成しました。デフォルトでは、セル全体が空になり、何も表示されません。



self.DestroyItem()
def DestroyItem(self,index_item: str):
    item = self.PLAYER["inventory"][index_item]
    self.PLAYER["inventory"][index_item] = self.PLAYER["default_inventory_item"](index_item)
    self.PLAYER["inventory_must_update"] = True
    return item




self.CheckKeysObjects()
def CheckKeysObjects(self):
    self.WALK_LEFT_PLAYER = False
    self.WALK_RIGHT_PLAYER = False
    self.WALK_UP_PLAYER = False
    self.WALK_DOWN_PLAYER = False
    if key("a"):
        self.WALK_LEFT_PLAYER = True
    elif key("d"):
        self.WALK_RIGHT_PLAYER = True
    if key("w"):
        self.WALK_UP_PLAYER = True
    elif key("s"):
        self.WALK_DOWN_PLAYER = True
    if key("f"):
        self.KEY_F = True
    else:
        self.KEY_F= False
    if key("e"):
        self.UseEat()




self.UseEat()
def UseEat(self):
    for inventory_item in range(len(self.PLAYER["inventory"])):
        if self.PLAYER["inventory"][str(inventory_item)]["name"] == "meat":
            if self.PLAYER["hungry"] + self.ADD_HUNGRY_COUNT < 100.0:
                self.PLAYER["hungry"] += self.ADD_HUNGRY_COUNT
                self.DestroyItem(index_item=str(inventory_item))




次は、物を地面に投げる機能です。



ただし、複雑なことは何もありません。X関数をクリックするself.QuitItem()、forループがインベントリのすべてのセルを通過し、キーが["status"]等しくない場合"space"は、以前に検討した関数を使用してこのセルを削除self.DestroyItem()し、セルの内容に基づいてオブジェクトを作成します。XとYは、あたかも彼を隣に投げたかのようにプレーヤーを置きます。



self.Quititem()
def QuitItem(self):
    for inventory_item in range(len(self.PLAYER["inventory"])):
        if self.PLAYER["inventory"][str(inventory_item)]["status"] != "space":
            self.CreateObject(
                img=self.PLAYER["inventory"][str(inventory_item)]["img"],
                x=self.PLAYER["x"],
                y=self.PLAYER["y"],
                name=self.PLAYER["inventory"][str(inventory_item)]["name"],
                data=self.PLAYER["inventory"][str(inventory_item)]["data"],
            )
            self.DestroyItem(index_item=str(inventory_item))
            break




それでもなお、私がどのようにしたかを言わなかった多くのこと、T.K。興味深いものの、それらはゲームの主要部分ではありませんでした。たとえば、アイテムを拾う可能性があるかどうか(在庫がいっぱいの場合)、ウォーキングアニメーションを追加したこと、写真の別のライブラリを作成したことなどに関するメッセージ。



それで全部です?



いいえ、Pythonで作成したライブラリを使用して、ゲームにニューラルネットワークを追加します。ニューラルネットワークを

備えたNPCとのプレーヤーの相互作用、

小さいながらもある種のプロット、および鎧、食べ物などのプレーヤー用の消耗品を作成します。アイテム、ブロックを組み込む機能。



ゲームを試す



それは私のGitHubから自由にダウンロードでき、実行するのに必要なのはPython3とキーボードライブラリだけです。ファイルを実行する必要がありますmain.py



ゲーム



All Articles