forked from Pavel/labygui
209 lines
5.5 KiB
Python
209 lines
5.5 KiB
Python
from math import sin, cos, pi, asin
|
|
from tkinter import *
|
|
|
|
laby_w, laby_h = 20, 12
|
|
|
|
wl = [676499, 819210, 704161, 828804, 911396, 1010837, 772540, 600182, 526017, 803480, 756064, 701196, 1756736, 1376344, 1158834, 1315990, 1102792, 1323847, 1497194, 1810708, 1327018, 1094903, 1349813]
|
|
|
|
zint = 2
|
|
zx, zy = 50, 50
|
|
screen_w, screen_h = laby_w * zx + zint, laby_h * zy + zint
|
|
|
|
master = Tk()
|
|
master.resizable(0, 0)
|
|
|
|
index = 0
|
|
path = [(0.0, 0.5)]
|
|
|
|
def escape(event):
|
|
global master
|
|
master.quit()
|
|
|
|
def add(event):
|
|
global path, index
|
|
if len(path) < 24:
|
|
index += 1
|
|
path.append((0.0, 0.5))
|
|
aller_selon(path)
|
|
|
|
def remove(event):
|
|
global path, index
|
|
if len(path) > 1:
|
|
path = path[:-1]
|
|
if index > len(path) - 1:
|
|
index = len(path) - 1
|
|
aller_selon(path)
|
|
|
|
def next(event):
|
|
global path, index
|
|
if index < len(path) - 1:
|
|
index += 1
|
|
aller_selon(path)
|
|
|
|
def previous(event):
|
|
global path, index
|
|
if index > 0:
|
|
index -= 1
|
|
aller_selon(path)
|
|
|
|
def left(event, step):
|
|
global path, index
|
|
path[index] = (round(path[index][0] + step, 2), path[index][1])
|
|
aller_selon(path)
|
|
|
|
def right(event, step):
|
|
global path, index
|
|
path[index] = (round(path[index][0] - step, 2), path[index][1])
|
|
aller_selon(path)
|
|
|
|
def up(event):
|
|
global path, index
|
|
path[index] = (path[index][0], round(path[index][1] + 0.1, 1))
|
|
aller_selon(path)
|
|
|
|
def down(event):
|
|
global path, index
|
|
if path[index][1] > 0:
|
|
path[index] = (path[index][0], round(path[index][1] - 0.1, 1))
|
|
aller_selon(path)
|
|
|
|
def print_code(event):
|
|
global path
|
|
print('')
|
|
print('path = %s' % path)
|
|
print('')
|
|
print('def chemin():')
|
|
for i in range(len(path)):
|
|
print(' a_gauche(%s)' % path[i][0])
|
|
print(' avancer(%s)' % path[i][1])
|
|
print('')
|
|
|
|
master.bind('<Escape>', escape)
|
|
master.bind('<Return>', add)
|
|
master.bind('<BackSpace>', remove)
|
|
master.bind('<Control-Left>', previous)
|
|
master.bind('<Control-Right>', next)
|
|
master.bind('<Left>', lambda e: left(e, 0.1))
|
|
master.bind('<Right>', lambda e: right(e, 0.1))
|
|
master.bind('<Shift-Left>', lambda e: left(e, 0.01))
|
|
master.bind('<Shift-Right>', lambda e: right(e, 0.01))
|
|
master.bind('<Up>', up)
|
|
master.bind('<Down>', down)
|
|
master.bind('p', print_code)
|
|
master.bind('P', print_code)
|
|
|
|
canvas = Canvas(master, width = screen_w, height = screen_h + 68, bg = 'white')
|
|
canvas.pack()
|
|
|
|
def clean_screen():
|
|
global canvas
|
|
canvas.delete('all')
|
|
|
|
def draw_rect(x, y, w, h, color):
|
|
global canvas
|
|
x += 1
|
|
y += 1
|
|
canvas.create_rectangle(x, y, x + w, y + h, fill = color, outline = '')
|
|
|
|
def draw_line(x1, y1, x2, y2, color):
|
|
global canvas
|
|
canvas.create_line(x1 + 1, y1 + 1, x2 + 1, y2 + 1, fill = color, width = 2.0)
|
|
|
|
def draw_help():
|
|
global canvas
|
|
help = 'change angle: [Shift+]Left/Right, change length: Up/Down, add/remove element: Enter/BackSpace, previous/next element: Ctrl+Left/Right, print code: P, exit: Esc'
|
|
canvas.create_text(4, screen_h + 36, anchor = NW, text = help, fill = 'black')
|
|
|
|
def draw_path():
|
|
global canvas, path
|
|
for i in range(len(path)):
|
|
if i == index:
|
|
color = 'red'
|
|
else:
|
|
color = 'blue'
|
|
if i < 12:
|
|
y = 0
|
|
else:
|
|
y = 16
|
|
canvas.create_text(4 + (i % 12) * 80, screen_h + 4 + y, anchor = NW, text = '(%5.2f, %3.1f)' % path[i], fill = color)
|
|
|
|
def draw_score(score):
|
|
global canvas
|
|
canvas.create_text(4, screen_h + 52, anchor = NW, text = f'score: {score}, state[7]: {state[7]}, state[6]: {state[6]}', fill = 'black')
|
|
|
|
def fix_angle(a):
|
|
return a * 2 * asin(1) / pi
|
|
|
|
def cout(x):
|
|
n, c = 5, 1
|
|
x = round(abs(x) * 10**n)
|
|
if x:
|
|
c = max(n + 1 - len(str(x)), 0)
|
|
while n and not (x % 10):
|
|
x = x // 10
|
|
n -= 1
|
|
c += not n
|
|
return 1 + len(str(x)) + c
|
|
|
|
def tourner(a):
|
|
global state
|
|
state[7] += a
|
|
state[5] += 5 + cout(a)
|
|
state[2] -= a
|
|
|
|
def avancer(l, color):
|
|
global state
|
|
t = fix_angle(state[2])
|
|
dx, dy = cos(t), sin(t)
|
|
state[7] += l
|
|
state[5] += 8 + cout(l)
|
|
while(l > 0):
|
|
state[3:5] = state[0:2]
|
|
x, y = state[0] + dx/4, state[1] + dy/4
|
|
ix, iy = int(x) - (x < 0), int(y) - (y < 0)
|
|
drx, dry = ix - int(state[3]), iy - int(state[4])
|
|
vw = lambda y, x: wl[y] & 2**x
|
|
hw = lambda y, x: wl[y + laby_h] & 2**x
|
|
tx = drx and (ix < 0 or ix >= laby_w or vw(iy - dry, laby_w - 2 - min(ix, ix - drx)))
|
|
ty = dry and (iy < 0 or iy >= laby_h or hw(min(iy, iy - dry), laby_w - 1 - (ix - drx)))
|
|
t = dx <= 0 or int(x) < laby_w - 1 or int(y) < laby_h - 1
|
|
if t and tx or ty or (drx and dry and (t and tx or ty)) or (drx and dry and (t and vw(iy, laby_w - 2 - min(ix, ix - drx)) or hw(min(iy, iy - dry), laby_w - 1 - ix))):
|
|
state[5] += 15
|
|
return
|
|
l -= .25
|
|
state[6] += (state[6] < 200)
|
|
state[0:2] = (x, y)
|
|
draw_line(state[3] * zx, state[4] * zy, state[0] * zx, state[1] * zy, color)
|
|
|
|
def aller_selon(path):
|
|
global state
|
|
state = [0, .5, 0, 0, .5, 0, 0, 0]
|
|
clean_screen()
|
|
for i in range(2):
|
|
draw_rect(0, i * laby_h * zy, laby_w * zx + zint, zint, 'black')
|
|
draw_rect(i * laby_w * zx, (not i) * zy, zint, (laby_h - 1) * zy, 'black')
|
|
for y in range(2 * laby_h - 1):
|
|
for z in range(laby_w - (y < laby_h)):
|
|
if wl[y] & 2**z:
|
|
x = laby_w - 1 - z
|
|
if y < laby_h:
|
|
draw_rect(x * zx, y * zy, zint, zy + zint, 'black')
|
|
else:
|
|
pass
|
|
draw_rect(x * zx, (y - laby_h + 1) * zy, zx + zint, zint, 'black')
|
|
for i in range(len(path)):
|
|
tourner(path[i][0])
|
|
if i == index:
|
|
color = 'red'
|
|
else:
|
|
color = 'blue'
|
|
avancer(path[i][1], color)
|
|
state[5] += sin(fix_angle(state[7])) - state[6] // 2
|
|
draw_help()
|
|
draw_path()
|
|
draw_score(state[5])
|
|
|
|
aller_selon(path)
|
|
|
|
master.mainloop()
|