首页 > 解决方案 > 通过拖动鼠标旋转对象pygame

问题描述

我想通过拖动鼠标使 3d 对象旋转

我发现的最接近的例子是来自https://sites.google.com/site/3dprogramminginpython/的例子

# matrix.py
import math


class Vector3D:
    def __init__(self, x=0.0, y=0.0, z=0.0):
        self.x = x
        self.y = y
        self.z = z

    def __str__(self):
        return '[%f, %f, %f]' % (self.x, self.y, self.z)

    def magnitude(self):
        return math.sqrt(self.x*self.x+self.y*self.y+self.z*self.z)

    def __add__(self, v):
        if isinstance(v, Vector3D):
            return Vector3D(self.x+v.x, self.y+v.y, self.z+v.z)
        else:
            raise Exception('*** Vector3D: error, add not with a vector! ***')

    def __sub__(self, v):
        if isinstance(v, Vector3D):
            return Vector3D(self.x-v.x, self.y-v.y, self.z-v.z)
        else:
            raise Exception('*** Vector3D: error, sub not with a vector! ***')

    def __neg__(self):
        return Vector3D(-self.x, -self.y, -self.z)
    
    def __mul__(self, val):
        if isinstance(val, int) or isinstance(val, float):
            return Vector3D(self.x*val, self.y*val, self.z*val)
        elif isinstance(val, Vector3D):
            return Vector3D(self.x*val.x, self.y*val.y, self.z*val.z)
        else:
            raise Exception('*** Vector3D: error, multiplication with not vector, int or float! ***')

    def __div__(self, val):
        if isinstance(val, int) or isinstance(val, float):
            if (val): 
                return Vector3D(self.x/val, self.y/val, self.z/val)
            else:
                raise Exception('*** Vector: error, divison with zero! ***')
        elif isinstance(val, Vector3D):
            if (val.x and val.y and val.z): 
                return Vector3D(self.x/val.x, self.y/val.y, self.z/val.z)
            else:
                raise Exception('*** Vector: error, divison with zero vector coord! ***')
        else:
            raise Exception('*** Vector: error, divison with not vector, int or float! ***')

        #   def __rmul__(self, other): #__mul__ is called in case of vector*int but in case of int*vector __rmul__ is called

    def normalize(self):
        mag = self.magnitude()
        if (mag > 0.0):
#           Vector3D.__mul__(self, 1/mag)
            self.x /= mag
            self.y /= mag
            self.z /= mag
        else:
            raise Exception('*** Vector: error, normalizing zero vector! ***')

    def dot(self, v): #dot product
        if isinstance(v, Vector3D):
            return self.x*v.x+self.y*v.y+self.z*v.z
        else:
            raise Exception('*** Vector: error, dot product not with a vector! ***')

    def cross(self, v): #cross product
        if isinstance(v, Vector3D):
            return Vector3D(self.y*v.z-self.z*v.y, self.z*v.x-self.x*v.z, self.x*v.y-self.y*v.x)
        else:
            raise Exception('*** Vector: error, cross product not with a vector! ***')


#The layout of the matrix (row- or column-major) matters only when the user reads from or writes to the matrix (indexing). For example in the multiplication function we know that the first components of the Matrix-vectors need to be multiplied by the vector. The memory-layout is not important
class Matrix:
    ''' Column-major order '''

    def __init__(self, rows, cols, createidentity=True):# (2,2) creates a 2*2 Matrix
        if rows < 2 or cols < 2:
            raise Exception('*** Matrix: error, getitem((row, col)), row, col problem! ***')
        self.rows = rows
        self.cols = cols
        self.m = [[0.0]*rows for x in xrange(cols)]

        #If quadratic matrix then create identity one
        if self.isQuadratic() and createidentity:
            for i in range(self.rows):
                self.m[i][i] = 1.0

    def __str__(self):
        s = ''
        for row in self.m:
            s += '%s\n' % row

        return s

    def isQuadratic(self):
        return self.rows == self.cols

    def copy(self):
        r = Matrix(self.rows, self.cols, False)
        for i in range(self.rows):
            for j in range(self.cols):
                r.m[i][j] = self.m[i][j]
        return r

    def __getitem__(self, (row, col)):
        ''' The value at (row, col) 
        For example, to get the element at 1,3 say
                m[(1,2)]'''
        if self.rows > row and self.cols > col:
            return self.m[row][col]
        else:
            raise Exception('*** Matrix: error, getitem((row, col)), row, col problem! ***')

    def __setitem__(self, (row, col), val):
        ''' Sets the value at (row, col) 
        For example, to set the value of element at 1,3 say
                m[(1,2)] = 3 '''

        if self.rows > row and self.cols > col:
            self.m[row][col] = val
        else:
            raise Exception('*** Matrix: error, setitem((row, col), val), row, col problem! ***')

    def rowsNum(self):
        return len(self.m)

    def colsNum(self):
        return len(self.m[0])

    def getRow(self, i):
        if i < self.rows:
            return self.m[i]
        else:
            raise Exception('*** Matrix: error, row(i), i > number of rows! ***')

    def getCol(self, j):
        if j < self.cols:
            return [row[j] for row in self.m] #(returns array of the vector)
        else:
            raise Exception('*** Matrix: error, col(j), j > columns! ***')

#   def setColumn(self, j, v):
#       if j < self.cols:
#           self.m[0][j] = v.x
#           self.m[1][j] = v.y
#           self.m[2][j] = v.z
#       else:
#           raise Exception('*** Matrix: error, setColumn(j, v), j > columns! ***')

    def __add__(self, right):
        if self.rows == right.rows and self.cols == right.cols:
            r = Matrix(self.rows, self.cols, False)
            for i in range(self.rows):
                for j in range(self.cols):
                    r.m[i][j] = self.m[i][j]+right.m[i][j]
            return r
        else:
            raise Exception('*** Matrix: error, add() matrices are not of the same type ***')

    def __sub__(self, right):
        if self.rows == right.rows and self.cols == right.cols:
            r = Matrix(self.rows, self.cols, False)
            for i in range(self.rows):
                for j in range(self.cols):
                    r.m[i][j] = self.m[i][j]-right.m[i][j]
            return r
        else:
            raise Exception('*** Matrix: error, sub() matrices are not of the same type ***')

    def __mul__(self, right):
        if isinstance(right, Matrix):
            if self.cols == right.rows:
                r = Matrix(self.rows, right.cols, False)
                for i in range(self.rows):
                    for j in range(right.cols):
                        for k in range(self.cols):
                            r.m[i][j] += self.m[i][k]*right.m[k][j]
                return r
            else:
                raise Exception('*** Matrix: error, matrix multiplication with incompatible matrix! ***')
        elif isinstance(right, Vector3D): #Translation: the last column of the matrix. Remains unchanged due to the the fourth coord of the vector (1).
#           if self.cols == 4:
            r = Vector3D()
            addx = addy = addz = 0.0
            if self.rows == self.cols == 4:
                addx = self.m[0][3]
                addy = self.m[1][3]
                addz = self.m[2][3]
            r.x = self.m[0][0]*right.x+self.m[0][1]*right.y+self.m[0][2]*right.z+addx
            r.y = self.m[1][0]*right.x+self.m[1][1]*right.y+self.m[1][2]*right.z+addy
            r.z = self.m[2][0]*right.x+self.m[2][1]*right.y+self.m[2][2]*right.z+addz

            #In 3D game programming we use homogenous coordinates instead of cartesian ones in case of Vectors in order to be able to use them with a 4*4 Matrix. The 4th coord (w) is not included in the Vector-class but gets computed on the fly
            if self.rows == self.cols == 4:
                w = self.m[3][0]*right.x+self.m[3][1]*right.y+self.m[3][2]*right.z+self.m[3][3]
                if (w != 1 and w != 0):
                    r.x = r.x/w;
                    r.y = r.y/w;
                    r.z = r.z/w;
            return r
#           else:
#               raise Exception('*** Matrix: error, matrix multiplication with incompatible vector! ***')
        elif isinstance(right, int) or isinstance(right, float):
            r = Matrix(self.rows, self.cols, False)
            for i in range(self.rows):
                for j in range(self.cols):
                    r.m[i][j] = self.m[i][j]*right
            return r
        else:
            raise Exception('*** Matrix: error, matrix multiply with not matrix, vector or int or float! ***')

    def __div__(self, right):
        if isinstance(right, int) or isinstance(right, float):
            r = Matrix(self.rows, self.cols, False)
            for i in range(self.rows):
                for j in range(self.cols):
                    r.m[i][j] = self.m[i][j]/right
            return r
        else:
            raise Exception('*** Matrix: error, matrix division with not int or float! ***')

    def transpose(self):
        t = Matrix(self.cols, self.rows, False)
        for j in range(self.cols):
            for i in range(self.rows):
                t.m[j][i] = self.m[i][j]

        return t

#For Quadratic Matrices:
#isSymetric(): A=Atransposed
#isNormal(): Atransposed*A = A*Atransposed

    def det(self):#Only for quadratic matrices
        if not self.isQuadratic():
            raise Exception('*** Matrix: error, determinant of non-quadratic matrix! ***')
        if self.rows == 2:
            return self.m[0][0]*self.m[1][1]-self.m[0][1]*self.m[1][0]

        return self.expandByMinorsOnRow(0)

    def expandByMinorsOnRow(self, row):#used by det()
        assert(row < self.rows)
        d = 0
        for col in xrange(self.cols):
            d += (-1)**(row+col)*self.m[row][col]*self.minor(row, col).det()

        return d

    def expandByMinorsOnCol(self, col):#used by det()
        assert(col < self.cols)
        d = 0
        for row in xrange(self.rows):
            d += (-1)**(row+col)*self.m[row][col]*self.minor(row, col).det()

        return d

    def minor(self, i, j): #used by det()
        ''' A minor of the matrix. Return the minor given by 
            striking out row i and column j of the matrix '''

        if i < 0 or i >= self.rows:
            raise Exception('*** Matrix: error, Determinant-row value is out of range! ***')
        if j < 0 or j >= self.cols:
            raise Exception('*** Matrix: error, Determinant-col value is out of range! ***')
        mat = Matrix(self.rows-1, self.cols-1)
        #Loop through the matrix, skipping over the row and column specified
        #by i and j
        minor_row = minor_col = 0
        for self_row in xrange(self.rows):
            if not self_row == i: #skip row i
                for self_col in xrange(self.cols):
                    if not self_col == j: #Skip column j
                        mat.m[minor_row][minor_col] = self.m[self_row][self_col]
                        minor_col += 1

                minor_col = 0
                minor_row += 1

        return mat

    def invert(self): 
        if not self.isQuadratic():
            raise Exception('*** Matrix: error, determinant of non-quadratic matrix! ***')
        else:
            N = self.cols
            mat = Matrix(N, N)
            mo = self.copy()
            for column in range(N):
                # Swap row in case our pivot point is not working
                if (mo.m[column][column] == 0):
                    big = column
                    for row in range(N):
                        if (math.fabs(mo.m[row][column]) > math.fabs(mo.m[big][column])):
                            big = row
                    # Print this is a singular matrix, return identity ?
                    if (big == column):
                        print("Singular matrix\n") #To stderr
                    # Swap rows                               
                    else: 
                        for j in range(N):
                            mo.m[column][j], mo.m[big][j] = mo.m[big][j], mo.m[column][j]
                            mat.m[column][j], mat.m[big][j] = mat.m[big][j], mat.m[column][j] 

                #Set each row in the column to 0  
                for row in range(N):
                    if (row != column):
                        coeff = mo.m[row][column]/mo.m[column][column]
                        if (coeff != 0):
                            for j in range(N):
                                mo.m[row][j] -= coeff*mo.m[column][j]
                                mat.m[row][j] -= coeff*mat.m[column][j]

                            #Set the element to 0 for safety
                            mo.m[row][column] = 0

            # Set each element of the diagonal to 1
            for row in range(N):
                for column in range(N):
                    mat.m[row][column] /= mo.m[row][row]

            return mat


if __name__ == "__main__":
    m1 = Matrix(3, 3)
    m1[(0,0)] = 1
    m1[(0,1)] = 6
    m1[(0,2)] = 8
    m1[(1,0)] = 2
    m1[(1,1)] = 5
    m1[(1,2)] = 7
    m1[(2,0)] = 3
    m1[(2,1)] = 4
    m1[(2,2)] = 9
    m2 = Matrix(3, 3)
    m2[(0,0)] = 5
    m2[(0,1)] = 8
    m2[(0,2)] = 1
    m2[(1,0)] = 6
    m2[(1,1)] = 1
    m2[(1,2)] = 4
    m2[(2,0)] = 3
    m2[(2,1)] = 2
    m2[(2,2)] = 7

    m = m1*m2
    print str(m)

# tut1.py
import math
from Tkinter import *
import matrix



class Simulation:
    ''' Coordiante-system: Right-handed, Matrices are column-major ones '''

    WIDTH = 640.0
    HEIGHT = 640.0

    RATE = 3
    SPEED = 2

    def __init__(self):
        self.root = Tk()
        self.root.resizable(False, False)
        self.root.title('3D')
        left = (self.root.winfo_screenwidth() - Simulation.WIDTH) / 2
        top = (self.root.winfo_screenheight() - Simulation.HEIGHT) / 2
        self.root.geometry('%dx%d+%d+%d' % (Simulation.WIDTH, Simulation.HEIGHT, left, top))
        self.graph = Canvas(self.root, width=Simulation.WIDTH, height=Simulation.HEIGHT, background='black')
        self.graph.pack()

        #The vectors of the Coordinate System (CS)
        self.cs = [
            matrix.Vector3D(0.0, 0.0, 0.0), #Origin
            matrix.Vector3D(0.5, 0.0, 0.0), #X
            matrix.Vector3D(0.0, 0.5, 0.0), #Y
            matrix.Vector3D(0.0 ,0.0, 0.5), #Z
            ]

        #Let these be in World-coordinates (worldview-matrix already applied)
        #In right-handed, counter-clockwise order
        self.cube = [
            matrix.Vector3D(-0.5,0.5,-0.5),
            matrix.Vector3D(0.5,0.5,-0.5),
            matrix.Vector3D(0.5,-0.5,-0.5),
            matrix.Vector3D(-0.5,-0.5,-0.5),
            matrix.Vector3D(-0.5,0.5,0.5),
            matrix.Vector3D(0.5,0.5,0.5),
            matrix.Vector3D(0.5,-0.5,0.5),
            matrix.Vector3D(-0.5,-0.5,0.5)
            ]

        self.dotx = matrix.Vector3D(-0.5, 0.0, 0.0)
        self.doty = matrix.Vector3D(0.0, -0.5, 0.0)
        self.dotz = matrix.Vector3D(0.0, 0.0, -0.5)


        # Define the vertices that compose each of the 6 faces. These numbers are
        # indices to the vertices list defined above.
        self.cubefaces = [(0,1,2,3),(1,5,6,2),(5,4,7,6),(4,0,3,7),(0,4,5,1),(3,2,6,7)] 

        self.ang = [0.0, 0.0, 0.0] # phi(x), theta(y), psi(z)
        self.trans = [0.0, 0.0, 0.0] # translation (x, y, z) (e.g. if want to move the Camera to (0, 0, 2) then (0, 0, -2) need to be entered)

        #The matrices (Scale, Shear, Rotate, Translate) apply to the View/Camera

        #The Scale Matrix
        self.Scale = matrix.Matrix(4, 4)
        Scalex = 1.0
        Scaley = 1.0
        Scalez = 1.0
        self.Scale[(0,0)] = Scalex
        self.Scale[(1,1)] = Scaley
        self.Scale[(2,2)] = Scalez

        #The Shear Matrix
        self.Shearxy = matrix.Matrix(4, 4)
        self.Shearxy[(0,2)] = 0.0
        self.Shearxy[(1,2)] = 0.0
        self.Shearxz = matrix.Matrix(4, 4)
        self.Shearxz[(0,1)] = 0.0
        self.Shearxz[(2,1)] = 0.0
        self.Shearyz = matrix.Matrix(4, 4)
        self.Shearyz[(1,0)] = 0.0
        self.Shearyz[(2,0)] = 0.0
        self.Shear = self.Shearxy*self.Shearxz*self.Shearyz

        #The Rotation Matrices
        self.Rotx = matrix.Matrix(4,4)
        self.Roty = matrix.Matrix(4,4)
        self.Rotz = matrix.Matrix(4,4)

        #The Translation Matrix (will contain xoffset, yoffset, zoffset)
        self.Tr = matrix.Matrix(4, 4)   

        #The Projection Matrix
        self.Proj = matrix.Matrix(4, 4) 
        #foc controls how much of the screen is viewed
        fov = 90.0 #between 30 and 90 ?
        zfar = 100.0
        znear = 0.1
        S = 1/(math.tan(math.radians(fov/2)))
#1st version (Perspective Projection)
        self.Proj[(0,0)] = S
        self.Proj[(1,1)] = S
        self.Proj[(2,2)] = -zfar/(zfar-znear)
        self.Proj[(3,2)] = -1.0
        self.Proj[(2,3)] = -(zfar*znear)/(zfar-znear)
#       self.Proj[(3,3)] = 0.0 #this should be zero acc. to the docs but it doesn't work

#2nd version (Simple Projection)
#       self.Proj[(2,3)] = -1.0
#       self.Proj[(3,3)] = 0.0

#3rd version (Perspective Projection) (Dr HS Fortuna Playstation)
#       A = Simulation.WIDTH/Simulation.HEIGHT
#       self.Proj[(0,0)] = S/A
#       self.Proj[(1,1)] = S
#       self.Proj[(2,2)] = (zfar+znear)/(zfar-znear)
#       self.Proj[(3,2)] = -1.0
#       self.Proj[(2,3)] = -2*(zfar*znear)/(zfar-znear)
#       self.Proj[(3,3)] = 0.0

#4th version (Perspective Projection) (OpenGL)
#       A = Simulation.WIDTH/Simulation.HEIGHT
#       self.Proj[(0,0)] = S/A
#       self.Proj[(1,1)] = S
#       self.Proj[(2,2)] = (zfar+znear)/(znear-zfar)
#       self.Proj[(3,2)] = -1.0
#       self.Proj[(2,3)] = 2*(zfar*znear)/(znear-zfar)
#       self.Proj[(3,3)] = 0.0


        self.lctrl_pressed = False

        self.root.bind("<B1-Motion>", self.dragcallback)
        self.root.bind("<ButtonRelease-1>", self.releasecallback)
        self.root.bind("<Key>", self.keycallback)
        self.root.bind("<KeyRelease>", self.keyreleasecallback)

        self.cnt = Simulation.RATE
        self.prevmouseX = 0.0
        self.prevmouseY = 0.0

        self.update()
        mainloop()

    def toScreenCoords(self, pv):
#       print str(pv)
        #Projection will project to [-1; 1] so the points need to be scaled on screen
        px = min(((pv.x+1)*0.5*Simulation.WIDTH), Simulation.WIDTH-1)
        #Reflect the Y-coordinate because the screen it goes downwards
        py = min(((1-(pv.y+1)*0.5)*Simulation.HEIGHT), Simulation.HEIGHT-1)

        return matrix.Vector3D(int(px), int(py), 1)

        #Screen matrix
#       SC = matrix.Matrix(4, 4)
#       SC[(0,0)] = Simulation.WIDTH/2
#       SC[(1,1)] = -Simulation.HEIGHT/2
#       SC[(0,3)] = Simulation.WIDTH/2
#       SC[(1,3)] = Simulation.HEIGHT/2

#       return SC*pv

    def update(self):
        # Main simulation loop.
        self.graph.delete(ALL)

        self.Rotx[(1,1)] = math.cos(math.radians(self.ang[0]))
        self.Rotx[(1,2)] = -math.sin(math.radians(self.ang[0]))
        self.Rotx[(2,1)] = math.sin(math.radians(self.ang[0]))
        self.Rotx[(2,2)] = math.cos(math.radians(self.ang[0]))

        self.Roty[(0,0)] = math.cos(math.radians(self.ang[1]))
        self.Roty[(0,2)] = math.sin(math.radians(self.ang[1]))
        self.Roty[(2,0)] = -math.sin(math.radians(self.ang[1]))
        self.Roty[(2,2)] = math.cos(math.radians(self.ang[1]))

        self.Rotz[(0,0)] = math.cos(math.radians(self.ang[2]))
        self.Rotz[(0,1)] = -math.sin(math.radians(self.ang[2]))
        self.Rotz[(1,0)] = math.sin(math.radians(self.ang[2]))
        self.Rotz[(1,1)] = math.cos(math.radians(self.ang[2]))

        #The Rotation matrix
        self.Rot = self.Rotx*self.Roty*self.Rotz

        self.Tr[(0,3)] = self.trans[0]
        self.Tr[(1,3)] = self.trans[1]
        self.Tr[(2,3)] = self.trans[2]

        #The Transformation matrix
        self.Tsf = self.Scale*self.Shear*self.Rot*self.Tr

        inviewingvolume = False

        #First draw the lines of the CS
        tvs = [] #transformed vectors
        for v in self.cs:
            r = self.Tsf*v
            ps = self.Proj*r
            tvs.append(self.toScreenCoords(ps))

            #if only one vertex is in the screen (x[-1,1], y[-1,1], z[-1,1]) then we draw the whole CS 
            if (-1.0 <= ps.x <= 1.0) and (-1.0 <= ps.y <= 1.0) and (-1.0 <= ps.z <= 1.0):
                inviewingvolume = True

        if inviewingvolume:
            self.graph.create_line(tvs[0].x, tvs[0].y, tvs[1].x, tvs[1].y, fill='red') 
            self.graph.create_line(tvs[0].x, tvs[0].y, tvs[2].x, tvs[2].y, fill='green') 
            self.graph.create_line(tvs[0].x, tvs[0].y, tvs[3].x, tvs[3].y, fill='blue') 
        #End of drawing of the lines of the CS

        inviewingvolume = False

        #Cube
        for i in range(len(self.cubefaces)):
            inviewingvolume = False
            poly = [] #transformed polygon
            for j in range(len(self.cubefaces[0])):
                v = self.cube[self.cubefaces[i][j]]

                # Scale, Shear, Rotate the vertex around X axis, then around Y axis, and finally around Z axis and Translate.
                r = self.Tsf*v

                # Transform the point from 3D to 2D
                ps = self.Proj*r

                # Put the screenpoint in the list of transformed vertices
                p = self.toScreenCoords(ps)
                x = int(p.x)
                y = int(p.y)
                poly.append((x, y))

                #if only one vertex is in the screen (x[-1,1], y[-1,1], z[-1,1]) then draw the whole polygon
                if (-1.0 <= ps.x <= 1.0) and (-1.0 <= ps.y <= 1.0) and (-1.0 <= ps.z <= 1.0):
                    inviewingvolume = True

            if inviewingvolume:
                for k in range(len(poly)-1):
                    self.graph.create_line(poly[k][0], poly[k][1], poly[k+1][0], poly[k+1][1], fill='white') 

                self.graph.create_line(poly[len(poly)-1][0], poly[len(poly)-1][1], poly[0][0], poly[0][1], fill='white') 

        inviewingvolume = False

        #Dotx
        r = self.Tsf*self.dotx
        ps = self.Proj*r
        if (-1.0 <= ps.x <= 1.0) and (-1.0 <= ps.y <= 1.0) and (-1.0 <= ps.z <= 1.0):
            inviewingvolume = True

        if inviewingvolume:
            p = self.toScreenCoords(ps)
            x, y = int(p.x), int(p.y)
            self.graph.create_rectangle(x, y, x+10, y+10, fill="red")

        inviewingvolume = False

        #Doty
        r = self.Tsf*self.doty
        ps = self.Proj*r
        if (-1.0 <= ps.x <= 1.0) and (-1.0 <= ps.y <= 1.0) and (-1.0 <= ps.z <= 1.0):
            inviewingvolume = True

        if inviewingvolume:
            p = self.toScreenCoords(ps)
            x, y = int(p.x), int(p.y)
            self.graph.create_rectangle(x, y, x+10, y+10, fill="green")

        inviewingvolume = False

        #Dotz
        r = self.Tsf*self.dotz
        ps = self.Proj*r
        if (-1.0 <= ps.x <= 1.0) and (-1.0 <= ps.y <= 1.0) and (-1.0 <= ps.z <= 1.0):
            inviewingvolume = True

        if inviewingvolume:
            p = self.toScreenCoords(ps)
            x, y = int(p.x), int(p.y)
            self.graph.create_rectangle(x, y, x+10, y+10, fill="blue")


    def dragcallback(self, event):
#       It's also possible to use the angle calculated from the mousepos-change from the center of the screen:
#       dx = event.x - Simulation.WIDTH/2
#       dy = event.y - Simulation.HEIGHT/2
#       ang = math.degrees(math.atan2(dy, dx))

#       if ang < 0.0:
#           ang += 360.0
        self.cnt -= 1
        if self.cnt == 0:
            self.cnt = Simulation.RATE
            diffX = event.x-self.prevmouseX
            diffY = event.y-self.prevmouseY

            if not self.lctrl_pressed:
                self.ang[0] += diffY*Simulation.SPEED
                self.ang[1] += diffX*Simulation.SPEED

                if self.ang[0] >= 360.0:
                    self.ang[0] -= 360.0
                if self.ang[0] < 0.0:
                    self.ang[0] += 360.0
                if self.ang[1] >= 360.0:
                    self.ang[1] -= 360.0
                if self.ang[1] < 0.0:
                    self.ang[1] += 360.0

            else:
                self.ang[2] += diffX*Simulation.SPEED
                if self.ang[2] >= 360.0:
                    self.ang[2] -= 360.0
                if self.ang[2] < 0.0:
                    self.ang[2] += 360.0

            self.update()

        self.prevmouseX = event.x
        self.prevmouseY = event.y


    def releasecallback(self, event):
        self.cnt = Simulation.RATE
        self.prevmouseX = 0.0
        self.prevmouseY = 0.0


    def keycallback(self, event):
#       print event.char
#       print event.keycode
#       print event.keysym
        if event.keysym == "Control_L":
            self.lctrl_pressed = True


    def keyreleasecallback(self, event):
        if event.keysym == "Control_L":
            self.lctrl_pressed = False


if __name__ == "__main__":
    Simulation()

上面的示例使用 tkinter 和 python2,在这种情况下,我想使用 python3、pygame 和 opengl 进行进一步的开发。您可以通过运行 tut1.py 来尝试

我一直在摆弄鼠标事件,但我仍然无法得到它。有人可以给我建议吗?

标签: pythonpython-3.xopengl3dpygame

解决方案


推荐阅读