Halo!
Hari ini saya akan menjelaskan secara rinci bagaimana saya membuat game di baris perintah, dan seberapa bagus hasilnya.
Dari mana ide itu berasal?
Sekilas saya terinspirasi oleh gagasan melakukan sesuatu yang sederhana, tetapi pada saat yang sama menarik dalam hal pengembangan. Saya mendapat ide untuk membuat game di konsol, menarik dari segi pengembangan, dan akan menarik untuk dilihat bahkan dari luar, seperti game ini .
Mesin game
Jadi, mari kita mulai dengan bagaimana game ini disusun di root, dan apa ide kerjanya.
Pertama, saya memutuskan bagaimana dunia game akan ditampilkan di konsol. Saya menyadari bahwa untuk menampilkan objek game, kami memerlukan daftar yang menyimpan daftar lain yang menyimpan karakter, yang kemudian ditampilkan di lapangan bermain dalam satu lingkaran
for.
Dengan kode ini:
for line_words in OUTPUT_IMAGE:
for word in line_words:
print(word, end="")
print("\n", end="")
Di sini kami menggambar semua karakter dari daftar, dan pergi ke baris baru untuk menggambar daftar karakter berikutnya.
Ini adalah bagaimana variabel yang menyimpan daftar simbol terlihat seperti:
Di sini kita segera mendapatkan keputusan tentang cara menampilkan objek dengan X dan Y, sekarang kita dapat menentukan:
X - simbol dalam daftar
Y - daftar yang berisi X
Jadi, gambarlah simbol di lapangan ... Kami akan menggunakan ini saat menggambar objek game.
Kita bisa mencoba menggambar "bola" di lapangan, menggantikan huruf "O" untuk X dan Y.
Untuk melakukan ini, tulis kode berikut:
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="")
Jadi, kami telah menggambar sebuah objek di lapangan permainan kami. Benar, koordinat X dan Y bukanlah klasik. Pertama, kami menunjukkan Y pertama, kemudian X, yang tidak sesuai dengan klasik, dan kedua, koordinat Y harus meningkat untuk menaikkan objek, dalam kasus kami, sebaliknya, itu harus berkurang.
Grafik X dan Y di dalam game:
Fitur ini nantinya juga harus diperhitungkan ketika kita melakukan tabrakan pada objek di konsol.
Sekarang kita dapat mencoba untuk memindahkan objek kita melintasi lapangan permainan, mis. menciptakan gerakan.
Kita perlu membersihkan konsol untuk menghapus gambar lama dari lapangan permainan tersebut.
Kami akan melakukan ini dengan perintah:
os.system("cls||clear")
Juga, kita perlu mengganti variabel
OUTPUT_IMAGEuntuk menghapus semua objek yang sebelumnya digambar di lapangan.
Kami juga harus memasukkan semua ini
while True.
Mari tambahkan
while Truefungsi time.sleep(1)untuk membatasi FPS.
Jadi, kode itu ditarik di depan mata kita:
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 = [
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
]
Sekarang kami memiliki kemampuan untuk mendistribusikan objek ke seluruh bidang.
Benar, objek-objek ini terlalu primitif, dan kita harus belajar cara menggambar objek kompleks seperti pemain, rumah, makanan ...
Untuk menggambar objek yang kompleks, kita perlu memahami dan mencari cara menggambar objek dengan menentukan hanya sekali X dan Y.
Untuk ini kita perlu fungsi yang menerima gambar (simbol), X, Y;
Mari kita lakukan:
def SetImage(image: str, x: int, y: int):
pass
Sekarang kita perlu menerapkannya. Untuk melakukan ini, Anda perlu memutuskan cara menggambar gambar yang membentang di sepanjang sumbu X dan Y, saya menemukan ini:
menggambar objek dengan membaginya menjadi simbol, dan segera setelah karakter "\ n" ditemukan, tambahkan sumbu
Y. Sumbu Y, seperti yang kami katakan, salah, terbalik, jadi kami menambahkannya untuk menurunkan objek.
Contoh gambar yang digambar menurut prinsip saya:
image = " O\n'|'\n |"#
Sekarang mari kita gambarkan ini dalam fungsi kita:
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
Mari tambahkan
try: except()untuk menghindari kesalahan jika objek memiliki X dan Y terlalu kecil atau terlalu besar.
x_startIni adalah X, dari mana kita perlu mulai menggambar saat menambah Y (dengan karakter "\ n")
Sekarang kita bisa menggunakan fungsi kita, jatuhkan X dan Y ke dalamnya, dan gambar yang perlu digambar:
Kode
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 = [
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
]
Dan inilah yang kami dapatkan:
seperti bola yang kami tarik, bola dapat dipindahkan di sepanjang sumbu X dan Y.
Kode
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 = [
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
[".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".",],
]
Dan sekarang, pemain sudah bergerak di sekitar peta.
Di sini kami sudah melakukan banyak hal, sudah ada pemain, sudah ada peta, dan sepertinya sudah memungkinkan untuk membuat game, tetapi tidak. Kita membutuhkan fungsi untuk menghitung tabrakan objek, karena jenis permainan apa itu tanpa interaksi objek? Jadi mari kita mulai.
Pertama, kita perlu membuat fungsi untuk mendapatkan latitude dan height suatu objek untuk menghitung hitboxnya.
Jadi, saya memutuskan untuk membuat fungsi sesuai dengan logika berikut:
X - hitbox objek dalam lebar X, ini adalah jumlah karakter terbesar di antara karakter "\ n" di gambar
Y - hitbox di Y adalah jumlah karakter "\ n" di gambar
Dengan logika ini, tidak sulit buat fungsi yang mengambil gambar, menghitung semua karakter antara "\ n" untuk itu, dan memilih jumlah karakter terbesar dari ini - garis lintang diperoleh.
Dan jika Anda menghitung karakter "\ n", seperti yang sudah saya tulis, Anda mendapatkan tingginya.
Fungsinya ternyata seperti ini:
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}
Mengapa ValueError kecuali di sini?
.
Jadi mari menggambar pemain kita, dan menghitung lebar dan panjangnya.
kode dengan menggambar dan menghitung lintang dan tinggi
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()
Hore! kita memiliki fungsi untuk menghitung latitude dan height, sekarang kita harus membuat fungsi untuk menghitung hitbox dan tabrakan objek.
Ingatlah bahwa sistem koordinat kita bukanlah sistem klasik, jadi, sayangnya, kita tidak dapat menggunakan fungsi klasik, kita harus membuatnya sendiri. Untuk melakukan ini, saya menggambar 2 kotak pada grafik yang bertabrakan, dan dari gambar ini Anda bisa mendapatkan kondisi untuk menghitung tabrakan.
Untuk memudahkan pemahaman, saya menggambar kotak hit, yaitu kotak:
Logika dalam kata-kata
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
Logika dalam kode
, :
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 .
Saya juga menggambar kubus di lapangan bermain kami sehingga pemain memiliki seseorang untuk dihadapi.
Dan saya mencoba cara kerja fungsi kalkulasi tabrakan.
Berikut adalah pemain menyentuh kubus:
Tapi tidak menyentuh:
Kode kontak
/ :
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()
Sekarang kami memiliki semua fungsi awal untuk gim, sebenarnya, saya menulis gim saya berdasarkan mereka.
Permainan
Ide dari permainan ini adalah:
Ada seorang pemain, makanan muncul di sekitarnya, yang dipaksa untuk dikumpulkan agar tidak mati. Gim ini juga memiliki fungsi: mengambil makanan, memasukkannya ke dalam inventaris Anda, memakannya dari inventaris Anda, meletakkan item dari inventaris Anda di lantai.
Saya mulai dengan membuat loop game dalam 3 baris, sederhana
While True:
from time import sleep
while True:
sleep(0.1)
Kemudian saya menganggap perlu untuk membuat kelas di mana semua fungsi objek masa depan akan disimpan. Oleh karena itu, saya membuat file main.py dan folder lib, tempat saya meletakkan file lib.py di mana kelas game itu berada. MEREKA. file game terlihat seperti ini:
+----game
| + --
| | -- main.py
| \ --lib
| +--lib.py -> class Game()
| \
|
+---
Di masa depan, saya bekerja terutama dengan kelas Game (), di main.py saya hanya menyebutnya, membuat objek awal, dan meluncurkan game.
Di kelas game, saya membuat fungsi run () yang memulai loop game. Saya juga membuat fungsi draw_all (), itu menghapus semua objek masa lalu, menggambar yang baru, dan mencetak ke lapangan bermain.
Dan seperti inilah tampilan kelasnya:
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)
Saya menambahkan semua fungsi dasar dari jenis
set_image(), size_object(), is_clash(), dan semua orang yang mesin permainan, dan yang saya telah dijelaskan di atas.
Membuat fungsi baru
create_object()dan variabel self.OBJECTS, fungsi create_object()saya gunakan untuk membuat objek, dibutuhkan parameter img, name, x, y, up, rigid, data.
img- gambar objek -
namenama objek (rumah, rumput, penghuni, makanan, dll.)
x- objek X - objek
yY
up- jika parameter ini benar, maka objek akan ditarik ke atas pemain, jika tidak pemain tumpang tindih
rigid- kekerasan, pemain tidak bisa melalui objek ini (belum diimplementasikan)
data- data pribadi objek, karakteristik pribadinya
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}
)
Saat itu, saya sudah menambahkan pemain, rumah, rumput, dan penduduk desa.
Dan saya memutuskan untuk menggunakan parameter yang sama di objek
up, menggunakannya di objek Home, mis. sehingga rumah menutupi pemain. Untuk melakukan ini, saya membuat fungsi CheckAll (), loop for melewati semua objek, dan menggambarnya pada gambar keluar, mis. gunakan fungsi SetImage (x: int, y: int, img: str), memasok X dan Y objek, dan sebuah gambar.
Karena itu, dia menggambar objek yang bisa ditutup sendiri oleh pemain. Dalam siklus yang sama, saya mendeklarasikan list
up_of_payer_objects, dan jika objek telah up = True, maka saya menambahkannya ke daftar tanpa menggambarnya di lapangan. Setelah itu saya menggambar pemain itu sendiri, dan baru kemudian saya melalui loop for atas objek di up_of_payer_objects, menggambarnya, sehingga mereka berada di atas pemain.
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"])
Kemudian saya mulai memindahkan pemain. Untuk ini, saya membuatnya sebagai objek terpisah, yang tidak ada dalam daftar
self.OBJECTS, tetapi disimpan dalam variabel self.PLAYER.
Semua parameter sesuai dengan jenis
X, Y, img, ITP Anda bisa mendapatkannya dengan menggunakan tombol, dengan kata lain ini adalah kamus (dikt). Dengan pemain dan objek seperti itu, sudah mungkin untuk bekerja, bergerak, menghitung tabrakan. Saya mulai dengan bergerak.
Saya mulai membuat gerakan dengan melakukan fungsi CheckKeysObjects (), yang bertanggung jawab untuk melacak penekanan tombol, dan yang saya panggil dalam fungsi CheckAll () di awal
def CheckAll(self):
self.CheckKeysObjects()
....
Untuk melacak penekanan tombol, saya menggunakan perpustakaan keyboard , dan 4 variabel: Dan semuanya ternyata sederhana, kami melacak tombolnya, dan jika ditekan , kami membuat variabel . Di awal fungsi, kami mendeklarasikan semua variabel di , untuk menyetel ulang semua hasil sebelumnya, jika tidak, pemain tidak akan berhenti.
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
Setelah itu, di fungsinya, saya
CheckAll()memeriksa semua variabel yang bertanggung jawab atas gerakan, mencari tahu kemana pemain itu bergerak.
Jika ada yang masuk
True, cari tahu yang mana, dan pindahkan benda ke arah yang berlawanan.
Kode gerakan yang dihasilkan
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
Ya, kami memindahkan objek ke arah yang berlawanan untuk menciptakan ilusi gerakan. Jika pemain pergi ke kanan, maka semua item lingkungan bergeser ke kiri.
Kemudian saya menambahkan lebih banyak item lingkungan, dan mulai memijah makanan, tujuan pemain adalah mengumpulkan makanan agar tidak mati.
Untuk menghitung mundur waktu pemijahan makanan, saya menggunakan yang sederhana
time.sleep()dan perpustakaan threading- untuk menjalankan 2 fungsi pada saat yang sama, pemijahan makanan dan putaran permainan utama. Fungsi pemijahan makanan SpawnEat()hanyalah fungsi yang, ketika diluncurkan, menghasilkan makanan di tempat acak, memanggil fungsi untuk setiap unit makanan CreateObject().
Juga, setelah saya membuat fungsi pemijahan makanan, saya membuat variabel untuk pemain
self.PLAYER["hungry"], ini adalah rasa laparnya, pada awalnya sama dengan 100 unit, saya akan menguranginya jika pemain berjalan dan menghabiskan energi (seperti energi, tidak ada dalam permainan) atau meningkatkannya jika pemain makan sesuatu.
Saya juga membuat sebuah fungsi
MinimizeHungry(), itu dipanggil setiap 5 detik, dan hanya membutuhkan 2 unit kelaparan dari pemain. Saya melakukan ini agar pemain harus bergerak, dan tidak diam.
Terakhir, dalam sebuah fungsi
Eat(), fungsi ini dipanggil di thread terpisah dari game loop. Dia memeriksa apakah ada terlalu banyak makanan di peta jika ada lebih dari 10 unit makanan. itu TIDAK memanggil fungsi SpawnEat()jika kurang dari 10 unit. lalu menelepon SpawnEat().
Begini hasilnya:
Makan ()
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()
Fungsi
Start()untuk memulai loop utama:
Mulailah ()
def Start(self):
while True:
self.CheckAll()
self.DrawAll()
sleep(0.01)
Dan fungsi
run()yang meluncurkan seluruh game.
Lari ()
def run(self):
proc1 = threading.Thread(target=self.Start)
proc1.start()
proc2 = threading.Thread(target=self.Eat)
proc2.start()
Proses makannya sendiri, saya terapkan secara sederhana pada fungsi
CheckAll()dan CheckKeysObjects(). Q CheckKeysObjects()Saya memeriksa untuk melihat apakah pemain menekan tombol E. Jika ditekan, kemudian menempatkan variabel self.PRESS_Edi True.
Dalam loop
CheckAll(), saya memeriksa apakah objek saat ini dalam loop adalah formakanan, jika makanan kemudian memeriksa apakah pemain bertabrakan dengannya, jika bertabrakan, kemudian memeriksa variabelnya self.PRESS_E, dan jika itu Truehanya menghapus objek dan meningkatkan rasa lapar, mis. variabel self.PLAYER["hungry"].
Beginilah caranya di dalam kode
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
Saya akan katakan sebelumnya, saya perlu menulis ulang semua ini ketika saya melakukan inventarisasi
Membuat inventaris
Jadi, sulit, kita perlu membuat inventaris.
Kesulitannya adalah bahwa semua objek perlu ditampilkan, disimpan sejarah, dihapus, objek ditempatkan di lantai.
Saya mulai dengan menambahkan kunci baru ke pemain, yaitu
self.PLAYER["inventory"], 4 sel disimpan di sana, seperti ini:
"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"},
}
Apakah hanya nomor sel.
status- kunci ini menyimpan nilai apakah sel telur kosong atau tidak. Jika kosong maka "spasi", jika ada item, maka nama item tersebut disimpan di sana.
name- menyimpan nama item, itu akan digunakan saat pemain meletakkan item tersebut.
minimize_image- ini adalah gambar kecil dari item yang ditampilkan di inventaris pemain.
Setelah, saya membuat cek baru di milik kami
CheckKeysObjects(), ketika Anda mengklik Xitem, itu akan melemparkannya ke tanah, dan juga ketika Anda mengklik tombol, Efungsi akan dipanggil self.UseEat(), yang sekarang akan kita analisis.
Jadi fungsinya
self.UseEat()adalah jalan melalui semua sel dari persediaan, untuk mencari makanan, dan jika makanan ditemukan, maka itu dikeluarkan dari persediaan, dan 10 unit ditambahkan ke kelaparan. Untuk menghapus item dari inventaris, saya membuat fungsi self.DestroyItem()di mana indeks sel disediakan, dan seluruh sel menjadi kosong secara default dan tanpa apa pun.
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))
Selanjutnya adalah fungsi melempar benda ke tanah.
Namun, tidak ada yang rumit, ketika Anda mengklik
Xfungsi yang disebut self.QuitItem(), loop for melewati semua sel inventaris, dan jika kuncinya ["status"]tidak sama "space", maka kami menghapus sel ini menggunakan fungsi yang sebelumnya dianggap self.DestroyItem(), dan membuat objek berdasarkan apa yang ada di dalam sel, X dan Y menempatkan pemain seolah-olah dia telah melemparkannya ke sampingnya.
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
Namun semua, banyak hal yang tidak saya katakan bagaimana saya melakukannya, T.K. mereka bukan bagian utama dari permainan, meskipun menarik. Misalnya pesan tentang kemungkinan mengambil barang atau tidak (saat persediaan penuh), saya menambahkan animasi jalan kaki, membuat perpustakaan gambar tersendiri, dan lain-lain.
Itu saja?
Tidak, saya akan menambahkan jaringan saraf ke dalam game, menggunakan perpustakaan yang saya tulis dengan Python,
saya akan membuat interaksi pemain dengan NPC yang dilengkapi dengan jaringan saraf, sebuah
plot kecil, tetapi semacam, dan juga beberapa persediaan untuk pemain, seperti baju besi, makanan. item, kemampuan untuk membangun balok.
Coba permainannya
Anda dapat dengan bebas mendownloadnya dari GitHub saya, Anda hanya perlu Python3 untuk menjalankannya, dan pustaka keyboard . Anda perlu menjalankan file tersebut
main.py.
Permainan