Python阶段学习之文字版MineCraft
最近在学习Python,读了《Learn Python3 the Hard Way》一大半,正好要求自己写一个游戏,就想起写一个文字版的MineCraft了。一开始写的很简单,就是一个很小的用input输入操作,得到随机物品,每种物品分数不同,最后全部挖光或者有某种结束机制,看得分论输赢。作为简单演练基本语法还可以,不过要说像minecraft还差很多了,所以做了一次大改动。
代码介绍:
主要是Engine、地图Map、玩家Player、物品goods(工厂类)、定位方向direction类,最右侧记录logs类。
按照面向对象的思想写的,后面可以轻松扩展,有兴趣可以下下代码自己加点东西玩一玩。
代码在Windows上编写,按照powershell全屏时的大小显示,在linux上简单添加文件解释器一行,调整一下显示大小和getch部分修改即可。
难点:
- 表达未知和物品:地图每个点都是一个对象,未知不显示,有各种物品和“空”,“空”也不显示,工厂类实现。
- 人的视野:随挖动、移动而显示物品,物品基类中增加exposed属性,操作后修改;
- 友好显示:分成三栏,分别是player、map、logs,每次获取一行,文字隔行显示。
缺点:
主要还是在于显示。
效果图如下:
主程序
.
# minecraft.py
# -*- coding = utf-8
# little minecraft game
import time
from minecraft_map import Map
from minecraft_player import Player
from minecraft_goods import scores
from minecraft_common import printmid
from minecraft_common import front_size
from minecraft_common import back_size
from minecraft_log import Logs
#from minecraft_common import fill_line
#windows
from msvcrt import getch
#linux
#import os
#import sys
#import tty, termios
def elect_act():
#return input("选择操作:前进(w), 后退(s), 左转(a),右转(d),挖(空格),退出(quit)>")
print("选择操作:前进(w), 后退(s), 左转(a),右转(d),挖(空格),退出(quit)>")
#windows
chr = str(getch(), encoding = "utf-8")
#getch() 得到的是byte 而不是str, 需要转化
#print(chr)
return chr
'''
#使用终端的设置,在c中也使用tty.setraw
fd = sys.stdin.fileno()
tty.setraw(fd)
ch = sys.stdin.read(1)
'''
class Engine(object):
def __init__(self):
print("""
===================================
|| ||
|| 欢迎来到文字版MineCraft! ||
|| 尽情的挖矿吧 ! ||
|| ||
||-------------------------------||
|| 最后得分结果为胜负 ||
||-------------------------------||
|| 作者: HHAHAA ||
|| 尝鲜版:20190221 ||
|| 初改版:20190301 ||
|| 二改版:20190302 ||
===================================
""")
time.sleep(1)
self.create_map(50)
print("\n生成地图中...")
time.sleep(1)
self.create_player()
print("\n创建玩家中...")
time.sleep(1)
self.create_logs()
print("\n小伙子,小菇凉,开始闯荡吧!")
time.sleep(1)
def create_map(self, size):
self.map = Map(size)
def create_player(self):
self.player = Player()
self.player.born(self.map)
self.map.expose_around(self.player.pos_x, self.player.pos_y)
self.map.set_empty(self.player.pos_x, self.player.pos_y)
def create_logs(self):
self.logs = Logs()
def play(self):
res = 0
while res != -1:
self.printscreen()
#print(f"当前分数: {scores(self.player.pocket)}")
#self.map.print_map_now(self.player.pos_x,
# self.player.pos_y, self.player.head)
act = elect_act()
words = ""
if act == "w": #前进
words = self.player.forward(self.map)
#由于空的地方比较多,前进也需要扩大视野
self.map.expose_view_by_move(self.player.pos_x,
self.player.pos_y, self.player.head)
elif act == "s": #后退
words = self.player.backward(self.map)
elif act == "a": #左转
words = self.player.turn_left()
self.map.expose_view_by_move(self.player.pos_x,
self.player.pos_y, self.player.head)
elif act == "d": #右转
words = self.player.turn_right()
self.map.expose_view_by_move(self.player.pos_x,
self.player.pos_y, self.player.head)
elif act == " ": #挖
words = self.player.dig(self.map)
self.logs.push(words)
#print("dig")
pos = self.player.get_dig_pos()
self.map.set_empty(pos.x, pos.y)
sentence = self.map.expose_view_by_dig(self.player.pos_x,
self.player.pos_y, self.player.head)
#print("after dig")
if sentence != "":
#print(f"sentence is not empty{sentence}")
res = -1
self.logs.push(sentence)
self.logs.push("游戏结束...")
self.printscreen()
exit(1)
else:
continue
elif act == "q":
self.logs.push("游戏结束...")
self.printscreen()
exit(1)
else:
continue
self.logs.push(words)
def printscreen(self):
out_buf = ""
#print(f"\n\n{'-'*(front_size + 2*self.map.x + 3 + back_size )}")
out_buf = f"\n\n{'-'*(front_size + 2*self.map.x + 3 + back_size )}"
for i in range(self.map.x):
player_line = self.player.getline(i)
map_line = self.map.get_line( i, self.player.pos_x,
self.player.pos_y, self.player.head)
#log_line = " "*(back_size - 1) + "|"
log_line = self.logs.get_line(i)
#print(player_line + map_line + log_line)
line = player_line + map_line + log_line
out_buf += "\n" + line
out_buf += "\n" + f"{'-'*(front_size + 2*self.map.x + 3 + back_size )}"
print(out_buf)
#print(f"{'-'*(front_size + 2*self.map.x + 3 + back_size )}")
engine = Engine()
engine.play()
#printmid(f"此次得分:{scores(engine.player.pocket)}")
common部分
# minecraft_common.py
# -*- coding: utf-8
# minecraft common class etc.
#common part
front_size = 8*6 #front
back_size = 59
tab = " "*front_size #目前tab为8个空格
def printmid(words):
print(f"{tab}" + words)
def fill_line(sentence, size):
sentence_occu = 0
for word in sentence:
if len( bytes(word, 'utf-8')) != 1:
sentence_occu += 2
else:
sentence_occu += 1
#print(sentence_occu)
return sentence + " "*(size - sentence_occu)
def fill_line_back(words, size):
return words + " "*size
class pair(object):
def __init__(self, x, y):
self.x = x
self.y = y
class pos(object):
def __init__(self, x