学习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库)。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。