在文章的开始,我打算先感谢一下这位大佬 —— 张*睿
一、沙盒游戏初识
玩过游戏的朋友估计不会陌生 —— 什么是“沙盒游戏”? 本篇文章将带领您从“零”开始学习如何编写一个沙盒游戏(终端显示).
首先,我提供一个来自百度的结果显示 :
“沙盒游戏(Sandbox Games)是由沙盘游戏演变而来,自成一种游戏类型,由一个或多个地图区域构成,往往包含多种游戏要素,包括角色扮演,动作、射击、驾驶等等。能够改变或影响甚至创造世界是沙盒游戏的特点。创造是该类型游戏的核心玩法,利用游戏中提供的物件制造出玩家自己独创的东西。” —— 百度百科
从上面的结果,我们大致可以看出沙盒游戏的特性,也就是 —— 自由性、创造性
自由性,也就是玩家在玩这个游戏的时候可以按照自己的想法,几乎为所欲为地在游戏地图中做自己想做的.
创造性,也就是玩家可以自己身临其境作为造物主来创造物体.
比较有影响力的沙盒游戏有:
1、我的世界/Minecraft(2009年Mojang AB公司出品游戏)(3维游戏)
2、泰拉瑞亚/Terraria (Relogic出品) (2维游戏)
这篇文章讲的是终端沙盒,因此2维游戏便更简便的可以编写.
二、游戏编写准备
本项目的编写我使用了通俗易懂的大众化语言——Python.版本控制为Python3.6以上.
特别注意:本项目的部分代码放在不同的计算机操作系统可能会有不一样的效果
这一节就先简单带过
三、前置工作
就我个人而言,我会先去用一张纸画出沙盒游戏的功能(我认为这是一个很好的习惯.这样一来我们在编写的时候就会有头绪,有条不紊;并且这也可以帮我们稳住好奇心)
首先,我先编写了一些前置的功能类,方便我后面进行一些功能的操作.(注:这些代码是从我的gitee项目上搬迁过来的,有一些版权并不属于我,但是我已经按照相应作品的许可证进行版权申明了)
import time
import sys
import os
import random
import re
import termios
import enum
from typing import Any, Iterable, Optional, Union
class ColorConsole(enum.Enum):
"""
枚举类 枚举终端的颜色
"""
Black = 0
White = 1
Cyan = 2
Blue = 3
Green = 4
Yellow = 5
Red = 6
class ColorPixel:
def __init__(self):
self.color_pixel = None
def SetColor(self, _r : int, _g : int, _b : int):
self.color_pixel = f"\033[48;2;{_r};{_g};{_b}m"
def GetColor(self, txt):
return f"{self.color_pixel}{txt}\033[0m"
class Press:
def getch(self):
fd = sys.stdin.fileno()
old_setting = termios.tcgetattr(fd)
new_setting = termios.tcgetattr(fd)
new_setting[3] = new_setting[3] & ~termios.ECHO & ~ termios.ICANON
try:
termios.tcsetattr(fd, termios.TCSADRAIN, new_setting)
get = sys.stdin.read(1)
if get:
return get
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_setting)
class Printf:
def __init__(self):
self.ls = []
def printf(self,words):
for i in range(len(words)):
print(words[i],end="",flush = True)
time.sleep(0.03)
self.ls.append(words[i])
print()
def lists(self):
print(self.ls)
# @staticmethod
def clean(self):
print("\033c",end="",flush = True)
# Copyright (c) 2023 Qian
class Composite: #复合组件总类
def unary_choose(self,choose_list): #一元选择器
n2 = 1 #建立一个初始量
answer = "" #建立一个问答字符串
while answer != "y":
printf.clean()
n1 = 1
print("选择:")
for i in choose_list:
if n1 == n2:
print(f" \033[32m{str(n1)}.{i}\033[m")
else:
print(f" {str(n1)}.{i}")
n1+=1
print("请输入:(w/s上下,y选中)")
answer = press_.getch()
if answer == "s":
if n2 != len(choose_list):
n2 += 1
else:
n2 = 1
if answer == "w":
if n2 != 1:
n2 -= 1
else:
n2 = len(choose_list)
printf.clean()
return n2
color_pixel = ColorPixel()
press_ = Press()
printf = Printf()
_composite = Composite()
# Copyright [C] 2023 LinLin 用于伪装成numpy库的类
class amap:
def __init__(self, l):
self.l=list(l)
def __str__(self):
return str(list(self.l))
def __add__(self, other):
if type(other)==amap:
d=map(lambda x,y:x+y,self.l,other.l)
else:
d=map(lambda x:x+other,self.l)
return amap(d)
def __sub__(self, other):
if type(other)==amap:
d=map(lambda x,y:x-y,self.l,other.l)
else:
d=map(lambda x:other,self.l)
return amap(d)
def __mul__(self, other):
if type(other)==amap:
d=map(lambda x,y:x*y,self.l,other.l)
else:
d=map(lambda x:x*other,self.l)
return amap(d)
def __truediv__(self, other):
if type(other)==amap:
d=map(lambda x,y:x/y,self.l,other.l)
else:
d=map(lambda x:x/other,self.l)
return amap(d)
def __mod__(self, other):
if type(other)==amap:
d=map(lambda x,y:x%y,self.l,other.l)
else:
d=map(lambda x:x%other,self.l)
return amap(d)
def __pow__(self, other):
if type(other)==amap:
d=map(lambda x,y:x**y,self.l,other.l)
else:
d=map(lambda x:x**other,self.l)
return amap(d)
def __floordiv__(self, other):
if type(other) == amap:
d=map(lambda x ,y :x // y, self.l, other.l)
else:
d=map(lambda x:x//other,self.l)
return amap(d)
def __setitem__(self, index, ro):
self.l = list(self.l)
eif.l[index] = ro
def __getitem__(self, index):
return list(self.l)[index]
def __len__(self):
return len(list(self.l))
def __cmp__(self, other):
return list(self.l)==list(other)
class Figure:
"""图像类 用于展示矩形、"""
def square(self, _x : int, _y : int, _item):
return [[_item for i in range(_x)]for j in range(_y)]
def output(self, _list):
for i in range(len(_list)):
for j in range(len(_list[i])):
print(_list[i][j], end = "")
print()
def exchage(self, _list, value):
for i in range(len(_list)):
for j in range(len(_list[i])):
_list[i][j] = value
return _list
def change(self, _x : int, _y : int, _list, value):
_list[x-1][y-1] = value
def add(self, _x1 : int, _x2 : int, _y1 : int, _y2 : int, _list, value):
_list[_x1 : _x2][_y1 : _y2] = value
def image(self, _color):
pass
_figure = Figure()
介绍一下以上的功能类:
1、ColorConsole类原本是我的WYUL中的一个类,用于完成更加复杂的检测枚举(此处感谢鱼翔浅底先生,为我提供了思路)
2、ColorPixel类其实是一个近乎烂尾的功能类,也是我的HPUL中一个小玩意儿,但是由于开发的时候思路错误,因此我对它十分厌恶.
3、Press类,基础操作,用于无堵塞操作.网上有许多这些类型的,因此原创性不高
4、Printf类,用于一些基本的终端操作,如逐字输出、清空终端
...
7、Figure类,用于操作矩阵,这个类尚未完善,但是目前的功能基本够用了.
这一篇文章不长,所以暂时告一段落.下期我会继续详细讲解一下沙盒游戏的编写.
各位如果感兴趣的话可以赞赏一下,或者点赞、收藏本专栏.