2015-09-28 08:41:18 -05:00

157 lines
4.9 KiB
Python

#
# Code under the MIT license by Alexander Pruss
#
from mc import *
import mcpi.settings
import cmath
import time
import sys
ESCAPE = 256
if len(sys.argv) < 2:
SIZE = 640 if not mcpi.settings.isPE else 400
else:
SIZE = int(sys.argv[1])
if len(sys.argv) < 3:
formula = lambda z,c : z * z + c
else:
formula = eval('lambda z,c : '+sys.argv[2])
black = WOOL_BLACK
#palette = ( WOOL_WHITE, WOOL_ORANGE, WOOL_MAGENTA, WOOL_LIGHT_BLUE,
# WOOL_YELLOW, WOOL_LIME, WOOL_PINK, WOOL_GRAY, WOOL_LIGHT_GRAY,
# WOOL_CYAN, WOOL_PURPLE, WOOL_BLUE, WOOL_BROWN, WOOL_GREEN,
# WOOL_RED, 152 )
# palette generated by solving traveling salesman problems in RGB space
#palette = (WOOL_WHITE,WOOL_LIGHT_GRAY,WOOL_LIGHT_BLUE,WOOL_CYAN,WOOL_LIME,WOOL_YELLOW,WOOL_ORANGE,152,WOOL_RED,WOOL_BROWN,WOOL_GREEN,WOOL_GRAY,WOOL_BLUE,WOOL_PURPLE,WOOL_MAGENTA,WOOL_PINK)
palette = (WOOL_WHITE,HARDENED_CLAY_STAINED_WHITE,WOOL_PINK,WOOL_MAGENTA,WOOL_PURPLE,HARDENED_CLAY_STAINED_LIGHT_BLUE,HARDENED_CLAY_STAINED_CYAN,HARDENED_CLAY_STAINED_PURPLE,HARDENED_CLAY_STAINED_LIGHT_GRAY,HARDENED_CLAY_STAINED_MAGENTA,HARDENED_CLAY_STAINED_PINK,HARDENED_CLAY_STAINED_RED,WOOL_RED,REDSTONE_BLOCK,HARDENED_CLAY_STAINED_ORANGE,WOOL_ORANGE,HARDENED_CLAY_STAINED_YELLOW,WOOL_YELLOW,WOOL_LIME,HARDENED_CLAY_STAINED_LIME,HARDENED_CLAY_STAINED_GREEN,WOOL_GREEN,HARDENED_CLAY_STAINED_GRAY,WOOL_BROWN,HARDENED_CLAY_STAINED_BROWN,WOOL_GRAY,HARDENED_CLAY_STAINED_BLUE,WOOL_BLUE,WOOL_CYAN,WOOL_LIGHT_BLUE,WOOL_LIGHT_GRAY)
def escapeTime(c):
i = 0
z = c
try:
while abs(z) < 2 and i < ESCAPE:
i = i + 1
z = formula(z,c)
return i
except:
return -1
#
# we could of course just do for x in range(0,size): for y in range(0,size): yield(x,y)
# but it will make users happier if we start at the player
#
def loopGenerator(size, cenX, cenY):
yield (cenX, cenY)
for r in range(1,size):
# right line segment
if cenX+r < size:
y = cenY - r
if y < 0:
y = 0
while y < cenY + r and y < size:
yield (cenX+r, y)
y += 1
# top line segment
if cenY+r < size:
x = cenX + r
if x >= size:
x = size - 1
while cenX - r < x and 0 <= x:
yield (x, cenY+r)
x -= 1
# left line segment
if 0 <= cenX-r:
y = cenY + r
if y >= size:
y = size - 1
while cenY - r < y and 0 <= y:
yield (cenX-r, y)
y -= 1
# bottom line segment
if 0 <= cenY-r:
x = cenX - r
if x < 0:
x = 0
while x < cenX + r and x < size:
yield(x, cenY - r)
x += 1
def pollZoom():
global lastHitEvent
events = mc.events.pollBlockHits()
if len(events) == 0:
return lastHitEvent != None
lastHitEvent = events[-1]
return True
def toComplex(x,y):
return complex((x - centerMC.x) * scale + centerCx.real,
(y - centerMC.z) * scale + centerCx.imag)
def draw():
count = 0
for (x,y) in loopGenerator(SIZE, SIZE/2, SIZE/2):
mcX = x + centerMC.x - SIZE/2
mcY = y + centerMC.z - SIZE/2
c = toComplex(mcX, mcY)
esc = escapeTime(c)
if esc < 0:
block = AIR
elif esc < ESCAPE:
block = palette[esc % len(palette)]
else:
block = black
mc.setBlock(mcX, centerMC.y, mcY,block)
if count >= 1000:
if pollZoom():
break
else:
count = 0
else:
count += 1
def formatComplex(z):
return "%.2g+%.2gi" % (z.real,z.imag)
def getInfo():
return ( "Center: "+formatComplex(centerCx)+", range from "+
formatComplex(toComplex(centerMC.x - SIZE/2, centerMC.z - SIZE/2))+" to "+
formatComplex(toComplex(centerMC.x + SIZE/2 - 1, centerMC.z + SIZE/2 - 1)) )
mc = Minecraft()
centerMC = mc.player.getPos()
centerMC.ifloor()
adjustedPlayer = centerMC.clone()
adjustedPlayer.y += 1
centerCx = complex(0,0)
scale = 4. / SIZE
lastHitEvent = None
while True:
mc.player.setPos(adjustedPlayer)
mc.postToChat(getInfo())
draw()
mc.postToChat("Rendered")
while not pollZoom():
time.sleep(0.25)
if ( lastHitEvent.pos.y != centerMC.y or
lastHitEvent.pos.x < centerMC.x - SIZE / 2 or
lastHitEvent.pos.x >= centerMC.x + SIZE / 2 or
lastHitEvent.pos.z < centerMC.z - SIZE / 2 or
lastHitEvent.pos.z >= centerMC.z + SIZE / 2 ):
mc.postToChat("resetting")
centerCx = complex(0,0)
scale = 4. / SIZE
else:
mc.postToChat("zooming")
centerCx = toComplex(lastHitEvent.pos.x,lastHitEvent.pos.z)
scale /= 2
lastHitEvent = None