Hallo!
Heute werde ich detailliert beschreiben, wie ich das Spiel in der Kommandozeile gemacht habe und wie gut es geworden ist.
Woher kommt die Idee?
Ich war inspiriert von der Idee, auf den ersten Blick etwas Einfaches zu tun, das aber gleichzeitig entwicklungsinteressant ist. Mir kam die Idee, ein Spiel in der Konsole zu erstellen. Es ist interessant für die Entwicklung, und es wird interessant sein, es auch von außen zu betrachten, wie dieses Spiel.
Spiel-Engine
Beginnen wir also damit, wie das Spiel an der Wurzel organisiert ist und wie es funktioniert.
Zuerst habe ich beschlossen, wie die Spielwelt auf der Konsole angezeigt werden soll. Ich erkannte, dass wir zum Anzeigen von Spielobjekten eine Liste benötigen, in der andere Listen gespeichert sind, in denen Zeichen gespeichert sind, die anschließend in einer Schleife auf dem Spielfeld angezeigt werden
for.
Mit diesem Code:
for line_words in OUTPUT_IMAGE:
for word in line_words:
print(word, end="")
print("\n", end="")
Hier zeichnen wir alle Zeichen aus der Liste und gehen zu einer neuen Zeile, um die nächste Liste von Zeichen zu zeichnen.
So sieht die Variable aus, in der die Symbollisten gespeichert sind:
Hier erhalten wir sofort eine Entscheidung darüber, wie Objekte in X und Y angezeigt werden sollen. Jetzt können wir Folgendes angeben:
X - ein Symbol in der Liste
Y - eine Liste, die X enthält
Zeichnen Sie also ein Symbol auf das Feld ... Wir werden dies beim Zeichnen von Spielobjekten verwenden.
Wir können versuchen, einen "Ball" auf das Spielfeld zu ziehen, indem wir X und Y durch den Buchstaben "O" ersetzen.
Schreiben Sie dazu den folgenden Code:
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="")
Und so haben wir ein Objekt auf unser Spielfeld gezeichnet. Die X- und Y-Koordinaten sind zwar nicht klassisch. Erstens geben wir zuerst Y an, dann X, was nicht ganz den Klassikern entspricht, und zweitens sollte die Y-Koordinate zunehmen, um das Objekt anzuheben, in unserem Fall sollte es im Gegenteil abnehmen.
Grafik von X und Y im Spiel:
Diese Funktion muss auch später berücksichtigt werden, wenn wir Kollisionen von Objekten in der Konsole durchführen.
Jetzt können wir versuchen, unser Objekt über das Spielfeld zu bewegen, d. H. Bewegung schaffen.
Wir müssen die Konsole löschen, um das alte Bild des Spielfelds zu löschen.
Wir werden dies mit dem Befehl tun:
os.system("cls||clear")
Außerdem müssen wir die Variable überschreiben
OUTPUT_IMAGE, um alle zuvor auf dem Spielfeld gezeichneten Objekte zu löschen.
Wir werden das alles auch tun müssen
while True.
Fügen wir der
while TrueFunktion hinzu time.sleep(1), um die FPS zu begrenzen.
Und so wurde der Code vor unseren Augen gezeichnet:
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 = [
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
]
Jetzt haben wir die Möglichkeit, Objekte über das Feld zu verteilen.
Diese Objekte sind zwar zu primitiv, und wir müssten lernen, wie man komplexe Objekte wie Spieler, Häuser, Lebensmittel ...
zeichnet. Um ein komplexes Objekt zu zeichnen, müssen wir verstehen und herausfinden, wie man ein Objekt zeichnet, indem
wir nur einmal sein X und Y angeben. Dazu benötigen wir eine Funktion, die ein Bild (Symbole) akzeptiert, X, Y;
Lass uns das machen:
def SetImage(image: str, x: int, y: int):
pass
Jetzt müssen wir es implementieren. Dazu müssen Sie entscheiden, wie ein Bild gezeichnet werden soll, das sich entlang der X- und Y-Achse erstreckt. Ich habe Folgendes gefunden:
Zeichnen Sie ein Objekt, indem Sie es in Symbole unterteilen, und fügen Sie die Y-Achse hinzu, sobald das Zeichen "\ n" gefunden wird.
Die Y-Achse ist, wie gesagt, falsch. umgekehrt, also fügen wir es hinzu, um das Objekt abzusenken.
Ein Beispiel für ein Bild, das nach meinem Prinzip gezeichnet wurde:
image = " O\n'|'\n |"#
Beschreiben wir dies nun in unserer Funktion:
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
Fügen wir hinzu
try: except(), um Fehler zu vermeiden, wenn das Objekt X und Y zu klein oder zu groß hat.
x_startDies ist das X, von dem aus wir mit dem Zeichnen beginnen müssen, wenn wir Y erhöhen (mit dem
Zeichen "\ n"). Jetzt können wir unsere Funktion verwenden, X und Y hineinlegen und das Bild, das gezeichnet werden muss:
der Code
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 = [
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
]
Und das haben wir:
Genau wie der Ball, den wir gezogen haben, kann er entlang der X- und Y-Achse bewegt werden.
der Code
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 = [
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
]
Und jetzt bewegt sich der Spieler bereits auf der Karte.
Hier haben wir schon viel gemacht, es gibt bereits einen Spieler, es gibt bereits eine Karte, und es scheint, dass es bereits möglich ist, ein Spiel zu machen, aber nein. Wir brauchen eine Funktion zur Berechnung von Kollisionen von Objekten, denn was für ein Spiel ist das ohne Objektinteraktionen? Also lasst uns anfangen.
Zuerst müssen wir eine Funktion erstellen, um den Breitengrad und die Höhe eines Objekts zu ermitteln und seine Hitbox zu berechnen.
Also habe ich beschlossen, die Funktion gemäß der folgenden Logik zu
erstellen : X - die Hitbox des Objekts in X-Breite, dies ist die größte Anzahl von Zeichen zwischen den Zeichen "\ n" im Bild
Y - die Hitbox in Y ist die Anzahl der Zeichen "\ n" im Bild
Nach dieser Logik ist es nicht schwierig Erstellen Sie eine Funktion, die ein Bild aufnimmt, alle Zeichen zwischen "\ n" zählt und die größte Anzahl von Zeichen daraus auswählt - der Breitengrad wird erhalten.
Und wenn Sie die Zeichen "\ n" zählen, wie ich bereits geschrieben habe, erhalten Sie die Höhe.
Die Funktion stellte sich wie folgt heraus:
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}
Warum ist ValueError außer hier?
.
Zeichnen wir also unseren Player und berechnen seine Breite und Länge.
Code mit Zeichnen und Berechnen von Breite und Höhe
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()
Hurra! Wir haben eine Funktion zur Berechnung von Breite und Höhe. Jetzt müssen wir eine Funktion zur Berechnung der Hitbox und der Kollisionen von Objekten erstellen.
Denken wir daran, dass unser Koordinatensystem kein klassisches ist. Leider können wir die klassische Funktion nicht verwenden, sondern müssen unsere eigene erstellen. Zu diesem Zweck habe ich 2 Quadrate auf dem Diagramm gezeichnet, die kollidieren, und aus diesem Bild können Sie eine Bedingung für die Berechnung der Kollision
erstellen . Zum besseren Verständnis habe ich Trefferfelder gezeichnet, d. H. Quadrate:
Logik in Worten
x — X
y — Y
h —
w —
x2 — X
y2 — Y
h2 —
w2 —
:
X, Y,
:
X
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
Y
X, Y,
y — x, h — w.
:
x x2 - w2 + w x - w x2 + w2 - w
x2 x - w + w2 x2 - w2 x + w - w2
X
Logic in Code
, :
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 .
Ich habe zusätzlich einen Würfel auf unser Spielfeld gezogen, damit der Spieler jemanden hat, dem er sich stellen muss.
Und ich habe versucht, wie die Kollisionsberechnungsfunktion funktioniert.
Hier ist ein Spieler, der einen Würfel berührt:
Aber keine Berührung:
Kontaktcode
/ :
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()
Jetzt haben wir alle Startfunktionen für das Spiel, tatsächlich habe ich mein Spiel basierend darauf geschrieben.
Ein Spiel
Die Idee des Spiels ist folgende:
Es gibt einen Spieler, um ihn herum erscheint Essen, das er sammeln muss, um nicht zu sterben. Das Spiel hat auch Funktionen: Lebensmittel aufnehmen, in das Inventar aufnehmen, aus dem Inventar essen, einen Gegenstand aus dem Inventar auf den
Boden legen. Ich habe zunächst eine Spielschleife in drei Zeilen erstellt. Es ist ganz einfach
While True:
from time import sleep
while True:
sleep(0.1)
Dann hielt ich es für notwendig, eine Klasse zu erstellen, in der alle Funktionen zukünftiger Objekte gespeichert werden. Daher habe ich eine main.py-Datei und einen lib-Ordner erstellt, in die ich die lib.py-Datei gelegt habe, in der sich die Spielklasse befand. JENE. Die Spieledateien sahen folgendermaßen aus:
+----game
| + --
| | -- main.py
| \ --lib
| +--lib.py -> class Game()
| \
|
+---
In Zukunft habe ich hauptsächlich mit der Game () -Klasse gearbeitet, in main.py habe ich es einfach genannt, Startobjekte erstellt und das Spiel gestartet.
In der Spielklasse habe ich eine run () -Funktion erstellt, die die Spielschleife startet. Mit der Funktion draw_all () werden auch alle früheren Objekte gelöscht, neue gezeichnet und auf dem Spielfeld gedruckt.
Und so sah die Klasse aus:
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)
Ich fügte hinzu , alle grundlegenden Funktionen des Typs
set_image(), size_object(), is_clash(), und alle diejenigen , die Spiel - Engine sind, und die ich oben beschrieben habe.
Sie machte eine neue Funktion
create_object()und eine Variable self.OBJECTS, eine Funktion create_object()I - Objekte erstellen kann, dauert es die Parameter img, name, x, y, up, rigid, data.
img- Objektbild - Objektname
name(Haus, Gras, Bewohner, Nahrung usw.)
x- X-Objekt
y- Y-Objekt
up- Wenn dieser Parameter True ist, wird das Objekt über den Spieler gezogen, andernfalls überlappt der Spieler es
rigid- Härte kann der Spieler nicht Gehen Sie durch dieses Objekt (noch nicht implementiert)
data- persönliche Daten des Objekts, seine persönlichen Eigenschaften
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}
)
Zu dieser Zeit habe ich bereits einen Spieler, ein Haus, Gras und einen Dorfbewohner hinzugefügt.
Und ich habe beschlossen, denselben Parameter im Objekt zu
upverwenden, ihn im Objekt zu verwenden Home, d. H. so dass das Haus den Spieler bedeckt. Zu diesem Zweck habe ich die Funktion CheckAll () erstellt. Eine for-Schleife durchlief alle Objekte und zeichnete sie auf das ausgehende Bild, d. H. Verwenden Sie die Funktion SetImage (x: int, y: int, img: str) und geben Sie das X und Y des Objekts sowie ein Bild an.
So zeichnete er Objekte, die der Spieler selbst schließen konnte. Im selben Zyklus habe ich eine Liste deklariert.
up_of_payer_objectsWenn das Objekt up = True hatte, habe ich es der Liste hinzugefügt, ohne es auf dem Feld zu zeichnen. Danach habe ich den Spieler selbst gezeichnet und erst dann habe ich die for-Schleife über die Objekte in up_of_payer_objects durchlaufen und sie gezeichnet, sodass sie sich über dem Spieler befanden.
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"])
Dann fing ich an, den Player zu bewegen. Dafür habe ich es als separates Objekt erstellt, das nicht in der Liste enthalten ist
self.OBJECTS, sondern in einer Variablen gespeichert ist self.PLAYER.
Alle seine Parameter entsprechend der Art
X, Y, img, ITP Sie können es mit Schlüsseln erhalten, mit anderen Worten, es ist ein Wörterbuch (dikt). Mit einem solchen Spieler und Objekten war es bereits möglich zu arbeiten, sich zu bewegen, Kollisionen zu berechnen. Ich begann mit einem Umzug.
Ich habe mit dem Erstellen von Bewegungen begonnen, indem ich die Funktion CheckKeysObjects () erstellt habe, die für die Verfolgung von Tastenanschlägen verantwortlich ist und die ich ganz am Anfang in der Funktion CheckAll () aufrufe
def CheckAll(self):
self.CheckKeysObjects()
....
Um Tastenanschläge zu verfolgen, habe ich die Tastaturbibliothek und 4 Variablen verwendet: Und alles hat sich als einfach herausgestellt. Wir verfolgen die Tasten und wenn sie gedrückt werden, erstellen wir eine Variable . Ganz am Anfang der Funktion deklarieren wir alle Variablen in , um alle vergangenen Ergebnisse zurückzusetzen, sonst stoppt der Player nicht.
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
Danach
CheckAll()überprüfe ich in der Funktion alle für die Bewegung verantwortlichen Variablen und finde heraus, wohin sich der Spieler bewegt.
Wenn welche vorhanden ist
True, finden Sie heraus, welche und bewegen Sie das Objekt in die entgegengesetzte Richtung.
Der resultierende Bewegungscode
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
Ja, wir bewegen Objekte in die entgegengesetzte Richtung, um die Illusion von Bewegung zu erzeugen. Wenn der Spieler nach rechts geht, werden alle Objekte der Umgebung nach links verschoben.
Dann fügte ich weitere Umweltgegenstände hinzu und fing an, Nahrung zu laichen. Das Ziel des Spielers ist es, Nahrung zu sammeln, um nicht zu sterben.
Für den Countdown der Food-Spawn-Zeit habe ich eine einfache
time.sleep()und eine Bibliothek threadingverwendet, um zwei Funktionen gleichzeitig auszuführen: Food-Spawn und die Hauptspielschleife. Die Nahrungsbrutfunktion SpawnEat()ist nur eine Funktion, die beim Start an zufälligen Stellen Nahrung erzeugt und eine Funktion für jede Nahrungseinheit aufruft CreateObject().
Nachdem ich die Food-Spawn-Funktion aktiviert hatte, machte ich den Player variabel
self.PLAYER["hungry"], das ist sein Hunger, ganz am Anfang sind es 100 Einheiten. Ich werde ihn verringern, wenn der Spieler geht und Energie verbraucht (wie Energie, die nicht im Spiel ist) oder erhöhen, wenn der Spieler etwas gegessen hat.
Ich habe auch eine Funktion erstellt
MinimizeHungry(), die alle 5 Sekunden aufgerufen wird und dem Spieler nur 2 Einheiten Hunger nimmt. Ich tat dies, damit sich der Spieler bewegen und nicht still stehen musste.
Schließlich wird
Eat()diese Funktion in einer Funktion in einem von der Spielschleife getrennten Thread aufgerufen. Sie prüft, ob zu viel Essen auf der Karte ist, wenn das Essen mehr als 10 Einheiten umfasst. Es ruft die Funktion NICHT auf, SpawnEat()wenn weniger als 10 Einheiten vorhanden sind. ruft dann an SpawnEat().
So stellte sich heraus:
Essen ()
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()
Funktion
Start()zum Starten der Hauptschleife:
Start ()
def Start(self):
while True:
self.CheckAll()
self.DrawAll()
sleep(0.01)
Und eine Funktion
run(), die das gesamte Spiel startet.
Lauf ()
def run(self):
proc1 = threading.Thread(target=self.Start)
proc1.start()
proc2 = threading.Thread(target=self.Eat)
proc2.start()
Den Prozess des Essens selbst habe ich einfach in die Funktion
CheckAll()und umgesetzt CheckKeysObjects(). F CheckKeysObjects()Ich habe überprüft, ob der Player die Taste gedrückt hat E. Wenn gedrückt, geben Sie die Variable self.PRESS_Eein True.
In der Schleife
CheckAll()überprüfte ich, ob das aktuelle Objekt in der Schleife forLebensmittel war, ob das Lebensmittel nicht überprüfte, ob der Spieler damit kollidierte, ob es kollidierte, überprüfte die Variable self.PRESS_Eund ob es Truedann einfach das Objekt löschte und den Hunger erhöhte, d.h. variabel self.PLAYER["hungry"].
So ist es im Code
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
Ich werde im Voraus sagen, dass ich all dies neu schreiben muss, wenn ich das Inventar mache
Inventar erstellen
Es ist also schwierig, eine Bestandsaufnahme durchzuführen.
Die Schwierigkeit besteht darin, dass alle Objekte angezeigt, der Verlauf gespeichert, gelöscht und Objekte auf dem Boden platziert werden müssen.
Ich begann damit, dem Player einen neuen Schlüssel hinzuzufügen. Es
self.PLAYER["inventory"]wurden 4 Zellen dort gespeichert, wie folgt:
"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"},
}
Sind nur Zellennummern.
status- Dieser Schlüssel speichert den Wert, ob die Eizelle leer ist oder nicht. Wenn leer, dann "Leerzeichen", wenn es einen Artikel gibt, dann wird der Name des Artikels dort gespeichert.
name- speichert den Namen des Gegenstands, er wird verwendet, wenn der Spieler den Gegenstand legt.
minimize_image- Dies ist ein kleines Bild des Gegenstands, der im Inventar des Spielers angezeigt wird.
Nachdem ich bei uns neue Überprüfungen durchgeführt habe , wird es auf den Boden geworfen
CheckKeysObjects(), wenn Sie auf das XObjekt klicken. Wenn Sie auf die Schaltfläche klicken, wird die EFunktion aufgerufen self.UseEat(), die wir nun analysieren.
Also die Funktion
self.UseEat()ist ein Durchgang durch alle Zellen des Inventars auf der Suche nach Nahrung. Wenn Nahrung gefunden wird, wird sie aus dem Inventar entfernt und 10 Einheiten werden dem Hunger hinzugefügt. Um einen Artikel aus dem Inventar zu entfernen, habe ich eine Funktion erstellt, self.DestroyItem()in der der Zellenindex bereitgestellt wird und die gesamte Zelle standardmäßig und ohne irgendetwas leer wird.
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))
Als nächstes wird ein Objekt auf den Boden geworfen.
Es gibt jedoch nichts Kompliziertes. Wenn Sie auf die
Xaufgerufene Funktion klicken self.QuitItem(), durchläuft die for-Schleife alle Zellen des Inventars. Wenn der Schlüssel ["status"]nicht gleich ist "space", löschen wir diese Zelle mit der zuvor betrachteten Funktion self.DestroyItem()und erstellen ein Objekt basierend auf dem, was sich in der Zelle X und befand Y stellt den Spieler so, als hätte er ihn neben sich geworfen.
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
Und doch viele Dinge, die ich nicht gesagt habe, wie ich es getan habe, T.K. Sie waren nicht der Hauptteil des Spiels, wenn auch interessant. Zum Beispiel Nachrichten über die Möglichkeit, einen Gegenstand abzuholen oder nicht (wenn das Inventar voll ist), dass ich eine Laufanimation hinzugefügt habe, dass ich eine separate Bibliothek mit Bildern erstellt habe und andere Dinge.
Das ist alles?
Nein, ich werde dem Spiel ein neuronales Netzwerk hinzufügen, indem ich eine Bibliothek verwende, die ich in Python geschrieben habe.
Ich werde die Interaktion des Spielers mit NPCs herstellen, die mit einem neuronalen Netzwerk ausgestattet sind, einer
kleinen, aber einer Art Handlung und auch einigen Vorräten für den Spieler wie Rüstung, Essen. Gegenstände, die Fähigkeit, Blöcke einzubauen.
Probieren Sie das Spiel aus
Es kann kostenlos von meinem GitHub heruntergeladen werden, Sie benötigen nur Python3 zum Ausführen und die Tastaturbibliothek . Sie müssen die Datei ausführen
main.py.
Ein Spiel