学习python编程,在新东方少儿编程官网的自由创作平台做的一些作品。
可以在线运行,效果如下(在新页面中打开链接):
代码如下(用到平台自定义的xdf库):
import math
class Vector3:
def __init__(self, x = 0.0, y = 0.0, z = 0.0, w = 1.0):
self.x = x
self.y = y
self.z = z
self.w = w
def setV(self, v):
self.x = v.x
self.y = v.y
self.z = v.z
def copy(self):
return Vector3(self.x, self.y, self.z)
def length(self):
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
def sqrLength(self):
return self.x * self.x + self.y * self.y + self.z * self.z
def normalize(self):
inv = 1 / self.length()
return Vector3(self.x * inv, self.y * inv, self.z * inv)
def cross(self, v):
return Vector3(-self.x * v.y + self.y * v.z, self.z * v.x - self.x * v.z, -self.y * v.x + self.x * v.y)
def __pow__(self, v):
return Vector3(-self.x * v.y + self.y * v.z, self.z * v.x - self.x * v.z, -self.y * v.x + self.x * v.y)
def __neg__(self): #重载-(负)
return Vector3(-self.x, -self.y, -self.z)
def __pos__(self): #重载+(正)
return Vector3(self.x, self.y, self.z)
def __abs__(self): #重载abs()
return Vector3(abs(self.x), abs(self.y), abs(self.z))
def __add__(self, v): #重载+
return Vector3(self.x + v.x, self.y + v.y, self.z + v.z)
def __sub__(self, v): #重载-
return Vector3(self.x - v.x, self.y - v.y, self.z - v.z)
def __mul__(self, v): #重载*
if type(v)==type(self):
return self.x * v.x + self.y * v.y + self.z * v.z
return Vector3(self.x * v, self.y * v, self.z * v)
def __div__(self, v): # 重载/
if type(v)==type(self):
pass
invf = 1 / v
return Vector3(self.x * invf, self.y * invf, self.z * invf)
def __iadd__(self, v): #重载+=
self.x += v.x
self.y += v.y
self.z += v.z
return self
def __isub__(self, v): #重载-=
self.x -= v.x
self.y -= v.y
self.z -= v.z
return self
def __imul__(self, v): #重载*=
if type(v)==type(self):
return self.x * v.x + self.y * v.y + self.z * v.z
self.x *= v
self.y *= v
self.z *= v
return self
def __idiv__(self, v): # 重载/
if type(v)==type(self):
pass
invf = 1 / v
self.x *= invf
self.y *= invf
self.z *= invf
return self
def __str__(self):
return "({},{},{},{})".format(self.x, self.y, self.z, self.w)
pass
Vector3.zero = Vector3()
class Matrix:
def __init__(self):
self.m = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
]
def setRotation(self, a, b, c):
cosa = math.cos(a)
sina = math.sin(a)
cosb = math.cos(b)
sinb = math.sin(b)
cosc = math.cos(c)
sinc = math.sin(c)
m = self.m
m[0][0] = cosb * cosc
m[0][1] = sina * sinb * cosc - sinc * cosa
m[0][2] = sinb * cosa * cosc + sina * sinc
m[1][0] = cosb * sinc
m[1][1] = cosa * cosc + sina * sinb * sinc
m[1][2] = -sina * cosc + sinc * sinb * cosa
m[2][0] = -sinb
m[2][1] = sina * cosb
m[2][2] = cosa * cosb
def setRotationV(self, v):
self.setRotation(v.x, v.y, v.z)
def setTranslate(self, tx = 0.0, ty = 0.0, tz = 0.0):
m = self.m
m[0][3] = tx
m[1][3] = ty
m[2][3] = tz
def setTranslateV(self, v):
self.setTranslate(v.x, v.y, v.z)
def __mul__(self, v):
m = self.m
if type(v)==type(self):
vm = v.m
mt = Matrix()
m0 = mt.m
for i in range(4):
for j in range(4):
m0[i][j] = 0
for k in range(4):
m0[i][j] += m[i][k] * vm[k][j]
return mt
return Vector3(
m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
)
def ang2rad(ang):
return math.pi * ang / 180
def rad2ang(rad):
return 180 * rad / math.pi
class Camera:
def __init__(self, p, dr, fov, w, h):
self.p = p
self.dr = dr
self.w = w
self.h = h
self.n = (h / 2) / math.tan(ang2rad(fov/2))
self.m = Matrix()
self.m.setRotation(math.pi/4, 0, 0)
def mapV(self, v):
p = self.p
dr = self.dr
w = self.w
h = self.h
n = self.n
#
p0 = v - p
d = p0 * dr
d0 = p0.length()
# n / d = t / d0
t = d0 * n / d
p1 = p0.normalize()
p2 = p + p1 * t
#
p3 = p + dr
p4 = self.m * p2
return Vector3(p4.x + 768 / 2, p4.y + 1024 / 2)
from xdf import *
ground = stamp("ground001@001j")
SQRT2_2 = 0.7071067811865475
camera = Camera(Vector3(0, 3, 3), Vector3(0, -SQRT2_2, -SQRT2_2), 45, 768, 464)
class Cube:
def __init__(self):
psA = [
Vector3(0, -0.3359375, 0),
Vector3(-0.234375,0.3125, 0),
Vector3(0.234375,0.3125, 0),
Vector3(-0.1640625,0.1171875, 0),
Vector3(0.1640625,0.1171875, 0)
]
lindA = [
[0, 1],
[0, 2],
[3, 4]
]
psB = [
Vector3(-0.1484375,-0.234375, 1.0),
Vector3(0.1484375,-0.1171875, 1.0),
Vector3(-0.1484375,0.234375, 1.0),
Vector3(0.1484375,0.1171875, 1.0),
Vector3(-0.1484375,0, 1.0)
]
lindB = [
[0, 1],
[0, 2],
[1, 4],
[2, 3],
[3, 4]
]
psC = [
Vector3(-0.5,-0.265625,0.1953125 + 0.5),
Vector3(-0.5,-0.265625,-0.1953125 + 0.5),
Vector3(-0.5,0.265625,-0.1953125 + 0.5),
Vector3(-0.5,0.265625,0.1953125 + 0.5),
]
lindC = [
[0, 1],
[1, 2],
[2, 3]
]
psD = [
Vector3(0.5,-0.265625,0.1953125 + 0.5),
Vector3(0.5,0.265625,0.1953125 + 0.5),
Vector3(0.5,0,-0.1953125 + 0.5),
]
lindD = [
[0, 1],
[1, 2],
[2, 0]
]
psE = [
Vector3(-0.109375,0.5,-0.265625 + 0.5),
Vector3(-0.109375,0.5,0.265625 + 0.5),
Vector3(0.15625,0.5,-0.265625 + 0.5),
Vector3(-0.109375,0.5,0 + 0.5),
Vector3(0.15625,0.5,0 + 0.5),
Vector3(0.15625,0.5,0.265625 + 0.5)
]
lindE = [
[0, 1],
[0, 2],
[3, 4],
[1, 5]
]
psF = [
Vector3(-0.109375,-0.5,-0.265625 + 0.5),
Vector3(-0.109375,-0.5,0.265625 + 0.5),
Vector3(0.15625,-0.5,-0.265625 + 0.5),
Vector3(-0.109375,-0.5,0 + 0.5),
Vector3(0.15625,-0.5,0 + 0.5)
]
lindF = [
[0, 1],
[0, 2],
[3, 4]
]
self.arr = [
[psA, lindA]
#,[psB, lindB]
#,[psC, lindC]
#,[psD, lindD]
#,[psE, lindE]
#,[psF, lindF]
]
#
self.ps0 = [
Vector3(-0.5, -0.5, 0),
Vector3(0.5, -0.5, 0),
Vector3(0.5, 0.5, 0),
Vector3(-0.5, 0.5, 0),
Vector3(-0.5, -0.5, 1),
Vector3(0.5, -0.5, 1),
Vector3(0.5, 0.5, 1),
Vector3(-0.5, 0.5, 1)
]
self.linds = [[0, 1],[1, 2],[2, 3],[3, 0],
[4, 5],[5, 6],[6, 7],[7, 4],
[0, 4],[1, 5],[2, 6],[3, 7]
]
#
for a in self.arr:
n = len(self.ps0)
ps = a[0]
inds = a[1]
for b in inds:
b[0] += n
b[1] += n
self.ps0.extend(ps)
self.linds.extend(inds)
#
self.ps = [Vector3() for v in self.ps0]
self.ps2 = [Vector3() for v in self.ps]
self.lines = [line(0, 0, 1, 0) for l in self.linds]
self.pos = Vector3()
self.reset()
def reset(self):
for i in range(len(self.ps0)):
self.ps[i].setV(self.ps0[i])
self.pos.setV(Vector3.zero)
def isEqual(self, p0, p1, th):
return (p0 - p1).sqrLength() < th
def success(self):
th = 0.1 * 0.1
if self.isEqual(self.pos, Vector3.zero, th):
for i in range(len(self.ps0)):
if not self.isEqual(self.ps[i], self.ps0[i], th):
return False
return True
return False
def update(self):
for i in range(len(self.ps)):
self.ps2[i] = camera.mapV(self.ps[i])
for i in range(len(self.linds)):
ps = self.linds[i]
li = self.lines[i]
p0 = self.ps2[ps[0]]
p1 = self.ps2[ps[1]]
dx = p1.x - p0.x
dy = p1.y - p0.y
sz = math.sqrt(dx * dx + dy * dy)
rot = math.atan2(dy, dx)
li.move(p0.x, p0.y)
li.rotate(rad2ang(rot) + 90)
li.size(sz)
class Turn:
def __init__(self, cube):
self.angV = Vector3()
self.transV = Vector3()
self.cube = cube
self.isAnim = False
self.N = 20
self.n = 0
def reset(self):
self.isAnim = False
def anim(self, angV, transV, im = False):
if self.isAnim:
return
tp = self.cube.pos + transV * 2
if tp.x > 1.5 or tp.x < -1.5 or tp.y > 1.5 or tp.y < -1.5:
return
self.isAnim = True
self.n = 0
self.angV = angV / self.N
self.transV = self.cube.pos + transV
self.cube.pos += transV * 2
if im:
self.angV = angV
self.update()
self.isAnim = False
def update(self):
if not self.isAnim:
return
angV = self.angV
transV = self.transV
ps = self.cube.ps
#
m = Matrix()
m0 = Matrix()
m0.setTranslateV(-transV)
m1 = Matrix()
m1.setRotation(angV.x, angV.y, angV.z)
m2 = Matrix()
m2.setTranslateV(transV)
m = m2 * m1 * m0
for v in ps:
v.setV(m*v)
self.n += 1
if self.n >= self.N:
self.isAnim = False
chekSuccess()
isOver = False
cube = Cube()
turn = Turn(cube)
overTf = text("成功了", 768/2, 100, 100, "red", "center")
def chekSuccess():
global isOver
if cube.success():
isOver = True
overTf.show()
pass
def loop():
turn.update()
cube.update()
pass
def reset():
global isOver
isOver = False
cube.reset()
turn.reset()
overTf.hide()
aa = [
[[turnLeft, turnUp, turnRight, turnDown],
[turnLeft, turnDown, turnRight, turnUp],
[turnRight, turnDown, turnLeft, turnUp],
[turnRight, turnUp, turnLeft, turnDown]],
[[turnUp, turnLeft, turnDown, turnRight],
[turnUp, turnRight, turnDown, turnLeft],
[turnDown, turnLeft, turnUp, turnRight],
[turnDown, turnRight, turnUp, turnLeft]]
][random(2)-1]
while cube.success():
bb = []
for i in range(10):
a = aa[random(len(aa)) - 1]
bb.append(a)
for a in bb:
for b in a:
b(True)
def turnLeft(im = False):
turn.anim(Vector3(0, -math.pi / 2, 0), Vector3(-0.5, 0, 0), im)
def turnRight(im = False):
turn.anim(Vector3(0, math.pi / 2, 0), Vector3(0.5, 0, 0), im)
def turnUp(im = False):
turn.anim(Vector3(math.pi / 2, 0, 0), Vector3(0, -0.5, 0), im)
def turnDown(im = False):
turn.anim(Vector3(-math.pi / 2, 0, 0), Vector3(0, 0.5, 0), im)
def keyup(code, key):
global isOver
if turn.isAnim:
return
if isOver:
if code == 32:
reset()
return
if code == 37:
turnLeft()
elif code == 38:
turnUp()
elif code == 39:
turnRight()
elif code == 40:
turnDown()
pass
def tap():
global isOver
if isOver:
reset()
pass
reset()
btn = text("重新开始", 0, 50, 50)
btn.tap = reset
class MyKeyBoard:
def __init__(self, x, y, w):
hw = w / 2
hhw = w * 0.75
self.arr = [
box(x, y - w, w, w, "white", "red"),
text("↑", x + hw, y - w + hhw, w, "center", "red"),
box(x, y, w, w, "white", "red"),
text("↓", x + hw, y + hhw, w, "center", "red"),
box(x - w, y, w, w, "white", "red"),
text("←", x - hw, y + hhw, w, "center", "red"),
box(x + w, y, w, w, "white", "red"),
text("→", x + w + hw, y + hhw, w, "center", "red"),
]
self.arr[0].tap=self.clickUp
self.arr[2].tap=self.clickDown
self.arr[4].tap=self.clickLeft
self.arr[6].tap=self.clickRight
delay(self.loop, 100)
def loop(self):
for i in range(len(self.arr)):
self.arr[i].front()
delay(self.loop, 100)
def onKeydown(self, keyCode, key):
try:
keyup(keyCode, key)
except e:
pass
def clickUp(self):
self.onKeydown(38, "ArrowLeft")
def clickDown(self):
self.onKeydown(40, "ArrowDown")
def clickLeft(self):
self.onKeydown(37, "ArrowLeft")
def clickRight(self):
self.onKeydown(39, "ArrowRight")
MyKeyBoard(768-200, 1024-100, 100)
也可以下载代码,本地python环境运行(用pygame封装了xdf库)。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。