前言
这次我们尝试在mc中绘制一个时钟,能按照外界的时间进行移动。
主要使用的是我的世界的python api:mcpi,以及minecraftstuff包(主要是绘制一些形状)。
如果对这些有问题,请看这里。
实现
先贴一下代码:
"""draw line and circle by minercraftstuff"""
import mcpi.minecraft as minecraft
import mcpi.block as block
import minecraftstuff
import time
import datetime
import math
mc = minecraft.Minecraft.create()
# 创建MinecraftDrawing对象
mcdrawing = minecraftstuff.MinecraftDrawing(mc)
pos = mc.player.getTilePos()
pos.y += 25
CLOCK_RADIUS = 20
HOUR_HAND_LENGTH = 10
MIN_HAND_LENGTH = 18
SEC_HAND_LENGTH = 20
mcdrawing.drawCircle(pos.x,pos.y,pos.z,CLOCK_RADIUS,block.DIAMOND_BLOCK.id)
def findPointOnCircle(cx,cy,radius,angle):
x = cx+math.sin(math.radians(angle))*radius
y = cy+math.cos(math.radians(angle))*radius
x = int(round(x,0))
y = int(round(y,0))
return (x,y)
while True:
# get the time
timeNow = datetime.datetime.now()
hours = timeNow.hour
# one circle has only 12 hours
hours = hours-12 if hours>=12 else hours
minutes = timeNow.minute
seconds = timeNow.second
# make out the hour point
# get the °
hourHandAngle = 30*hours
hourHandx,hourHandy = findPointOnCircle(pos.x,pos.y,HOUR_HAND_LENGTH,hourHandAngle)
mcdrawing.drawLine(pos.x,pos.y,pos.z,hourHandx,hourHandy,pos.z,block.DIRT.id)
# make out the minute point
minhandAngle = 6*minutes
minhandx,minhandy = findPointOnCircle(pos.x,pos.y,MIN_HAND_LENGTH,minhandAngle)
mcdrawing.drawLine(pos.x,pos.y,pos.z-1,minhandx,minhandy,pos.z-1,block.WOOD_PLANKS.id)
# make the second point
secHandAngle = 6*seconds
sechandx,sechandy = findPointOnCircle(pos.x,pos.y,SEC_HAND_LENGTH,secHandAngle)
mcdrawing.drawLine(pos.x,pos.y,pos.z+1,sechandx,sechandy,pos.z+1,block.STONE.id)
time.sleep(1)
# clear the old points
mcdrawing.drawLine(pos.x,pos.y,pos.z,hourHandx,hourHandy,pos.z,block.AIR.id)
mcdrawing.drawLine(pos.x,pos.y,pos.z-1,minhandx,minhandy,pos.z-1,block.AIR.id)
mcdrawing.drawLine(pos.x,pos.y,pos.z+1,sechandx,sechandy,pos.z+1,block.AIR.id)
初始设置
首先还是最重要的mc和mcdrawing实例的创建。
然后我们将地点设置到了玩家的上方,然后是一些时钟的基本数据,比如指针长度和圆的半径。
mc = minecraft.Minecraft.create()
# 创建MinecraftDrawing对象
mcdrawing = minecraftstuff.MinecraftDrawing(mc)
pos = mc.player.getTilePos()
pos.y += 25
CLOCK_RADIUS = 20
HOUR_HAND_LENGTH = 10
MIN_HAND_LENGTH = 18
SEC_HAND_LENGTH = 20
然后,需要绘制一个圆:
# 参数:x、y、z圆心,圆的半径以及方块的类型
mcdrawing.drawCircle(pos.x,pos.y,pos.z,CLOCK_RADIUS,block.DIAMOND_BLOCK.id)
mcdrawing就是我们之前创建的实例,内部有绘制直线、圆、球体、多边形等多种方法。
时钟工作
我们先想一下时钟的工作原理(想明白了的当我没说)
首先是时针,一圈12个h,所以按照时间,每一个小时代表30°。
分针也是相同的道理,60min转一圈,一分钟6°,秒针同理。
但是,这只是最基本的,其实在时针或者分针还有一点很重要,就是会按照当前的时间进行一个小的移动(比如3.30,时针其实是在34之间的)。不过这里我们就不考虑了。
游戏循环:
while True:
# get the time
timeNow = datetime.datetime.now()
hours = timeNow.hour
# one circle has only 12 hours
hours = hours-12 if hours>=12 else hours
minutes = timeNow.minute
seconds = timeNow.second
根据我们得到的时分秒,就能计算出角度,先给一个通过角度计算指针终点位置的函数:
def findPointOnCircle(cx,cy,radius,angle):
x = cx+math.sin(math.radians(angle))*radius
y = cy+math.cos(math.radians(angle))*radius
x = int(round(x,0))
y = int(round(y,0))
return (x,y)
因为我们的时钟是在xoy平面上的,所以输入(x,y)为时钟的中心,然后输入指针的长度和当前指针的角度。
对于时针:
# make out the hour point
# get the °
hourHandAngle = 30*hours
hourHandx,hourHandy = findPointOnCircle(pos.x,pos.y,HOUR_HAND_LENGTH,hourHandAngle)
mcdrawing.drawLine(pos.x,pos.y,pos.z,hourHandx,hourHandy,pos.z,block.DIRT.id)
剩下的两个指针也类似操作,但是注意在z轴上错开一格,防止几个指针粘在一起。
然后就是程序需要挂起1s,然后删除创建的指针(绘制air方块)。