dberube4

Ptglet+Pymunk Drag&Drop

Sep 14th, 2013
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.72 KB | None | 0 0
  1. from pyglet.window import Window, key
  2. from pyglet.graphics import vertex_list
  3. from pyglet import app, gl, clock, text
  4.  
  5. import pymunk
  6. from pymunk import Vec2d
  7.  
  8. class StaticLine(object):
  9.     '''
  10.    An object that bind drawing and physics of a static line.
  11.    '''
  12.     def __init__(self, start, end, body, color=[0,0,0], friction=0.0):
  13.         '''
  14.        start(suple): A tuple of 2D vertex coordinate. Start point of the line.
  15.        end(tuple): A tuple of 2D vertex coordinate. End point of the line.
  16.        body(pymunk.Body): Pymunk body object
  17.        color(list): List of [red green blue] in bytes. Color of the vertices.
  18.        friction(float): Friction for the physic.
  19.        '''
  20.        
  21.         vertices = (start[0], start[1], end[0], end[1])
  22.         self.mesh = vertex_list(2, ('v2i', vertices),
  23.                                    ('c3B', color*2 ))
  24.         self.mesh_physic = pymunk.Segment(body, start, end, 0.0)
  25.         self.friction = friction
  26.        
  27.     def registerPhysicSpace(self, space):
  28.         space.add(self.mesh_physic)
  29.        
  30.     def draw(self):
  31.         self.mesh.draw(gl.GL_LINES)
  32.        
  33. class Box():
  34.     '''
  35.    An object that bind the physics and the drawing of a box.
  36.    Also add drags options
  37.    '''
  38.     def __init__(self,start,size,color=[0,0,0],friction=0.0,
  39.                  mass=None, life = -1):
  40.         '''
  41.        start(tuple): The coordinates of the top left vertex
  42.        size(tuple): The width and the height of the box
  43.        color(lits): A list of 3 BYTE. Color of the mesh vertices
  44.        friction(float): Friction of the object
  45.        mass(int): Mass of the object
  46.        life(int): Number of game tick the object should live (-1 for infinite)
  47.        '''
  48.        
  49.         #Calculate vertices position
  50.         x,y = start
  51.         w,h = size
  52.         v = (x,y, x+w,y, x+w,y+h, x,y+h)
  53.         self.mesh = vertex_list(4, ('v2f', v),
  54.                                    ('c3B', color*4 ))
  55.                                    
  56.         #Physical mesh
  57.         v = [(x,y), (x+w,y), (x+w,y+h)]
  58.         moment = pymunk.moment_for_box(mass, w, h)
  59.         self.body = pymunk.Body(mass, moment)
  60.         self.mesh_physic = pymunk.Poly.create_box(self.body, (w,h))
  61.         self.mesh_physic.friction = friction
  62.         self.body.position = x+w/2, y+h/2
  63.        
  64.         #Property
  65.         self.mesh_pos = x+w/2, y+h/2
  66.         self.width = size[0]
  67.         self.height = size[1]
  68.        
  69.     def draw(self):
  70.  
  71.         #Update vertices position
  72.         p = self.body.position
  73.         dt = p[0]-self.mesh_pos[0], p[1]-self.mesh_pos[1]
  74.         for i in range(4):
  75.             self.mesh.vertices[i*2] += dt[0]
  76.             self.mesh.vertices[i*2+1] += dt[1]
  77.        
  78.         self.mesh_pos = p[0],p[1]
  79.         self.mesh.draw(gl.GL_QUADS)
  80.        
  81.     def registerPhysicSpace(self, space):
  82.         space.add(self.body, self.mesh_physic)
  83.  
  84. class Game(Window):
  85.    
  86.     def __init__(self, **kwargs):
  87.         super(Game, self).__init__(**kwargs)
  88.        
  89.         self.space = pymunk.Space()
  90.         self.space.gravity = Vec2d(0.0, -900.0)
  91.        
  92.         #Static for non-moving physic object and dynamics for moving.
  93.         self.statics = []
  94.         self.dynamics = []
  95.        
  96.         self.initGame()
  97.         self.set_visible(True)
  98.        
  99.     def initGame(self):
  100.        
  101.         sqrt = lambda w,x,y,z: (w,z, y,z, y,x, w,x)
  102.         w, h = self.width, self.height
  103.        
  104.         #Properties to drag objects
  105.         self.dragged_object = None
  106.         self.drag_offset = (0,0)  
  107.         self.mouse_pos = (0,0)
  108.        
  109.         #A clock object to print the current fps on screen
  110.         self.fps_display = clock.ClockDisplay()
  111.        
  112.         #Create a square to fill the window background
  113.         vertices = sqrt(0,0, w,h)
  114.         white = [255, 255, 255]
  115.         self.background = vertex_list(4, ('v2i/static', vertices),
  116.                                          ('c3B/static', white*4 ))
  117.         #A label title
  118.         self.title = text.Label('DRAG & DROP!',
  119.                           font_name='Arial',
  120.                           font_size=36,color=(0,0,0,100),
  121.                           x=w//2, y=h-h//5,
  122.                           anchor_x='center', anchor_y='center')
  123.                                          
  124.         #Limits & other Lines
  125.         body = pymunk.Body()
  126.         l1 = StaticLine((2,2), (w-2,2), body)
  127.         l2 = StaticLine((2,2), (2,h-2), body)
  128.         l3 = StaticLine((w-2,2), (w-2,h-2), body)
  129.         l4 = StaticLine((2,h-2), (w-2,h-2), body)
  130.         l5 = StaticLine((50,h-190), (180,h-240), body)
  131.         l6 = StaticLine((350,h-200), (350,h-290), body)
  132.         l7 = StaticLine((430,h-200), (430,h-290), body)
  133.         l8 = StaticLine((350,h-290), (430,h-290), body)
  134.         self.statics = [l1,l2,l3,l4,l5,l6,l7,l8]
  135.         for obj in self.statics:
  136.             obj.registerPhysicSpace(self.space)
  137.        
  138.         #Dynamics objects
  139.         box1 = Box((350,100),(50,50), color=[0,70,255], mass=1)
  140.         box2 = Box((180,80),(30,30), color=[255,0,255], mass=1)
  141.         box3 = Box((230,140),(70,70), color=[255,70,0], mass=1)
  142.         self.dynamics = [box1, box2, box3]
  143.         for obj in self.dynamics:
  144.             obj.registerPhysicSpace(self.space)
  145.    
  146.     def update(self, dt):
  147.        
  148.         dt = 1.0/60.0
  149.         self.space.step(dt) #Physics steps        
  150.        
  151.         self.on_draw()
  152.    
  153.     def on_mouse_press(self, x, y, button, mod):
  154.        
  155.         self.mouse_pos = (x,y)        
  156.        
  157.         #Check if a dynamic object is in the clicked space:
  158.         for i in self.dynamics:
  159.             maxX = i.mesh.vertices[0]+ i.width
  160.             maxY = i.mesh.vertices[1]+ i.height
  161.  
  162.             if x >= i.mesh.vertices[0] and y >=i.mesh.vertices[1]:            
  163.                 if x <= maxX and y <= maxY:
  164.                     self.dragged_object = i
  165.            
  166.                     #Get where the cursor clicked on the object
  167.                     center = i.width//2, i.height//2
  168.                     of_x = -(x-maxX+center[0])
  169.                     of_y = -(y-maxY+center[1])
  170.                     print(of_y)
  171.                     self.drag_offset = of_x,of_y
  172.                    
  173.    
  174.     def on_mouse_release(self, x, y, button, mod):
  175.         self.mouse_pos = (x,y)
  176.         self.dragged_object = None
  177.    
  178.     def on_mouse_drag(self, x,y, dx,dy, buttons, mod):
  179.        
  180.         self.mouse_pos = (x,y)
  181.         if self.dragged_object:
  182.             body = self.dragged_object.body
  183.             body.position.x = self.mouse_pos[0]+self.drag_offset[0]
  184.             body.position.y = self.mouse_pos[1]+self.drag_offset[1]
  185.            
  186.             #Communicate the cursor velocity to the object
  187.             self.dragged_object.body.velocity += (dx*3, dy*3)
  188.            
  189.             if dx > -2 and dx <2:
  190.                 self.dragged_object.body.velocity.x = 0
  191.             if dy > -2 and dy <2:
  192.                 self.dragged_object.body.velocity.y = 0
  193.    
  194.     def on_draw(self):
  195.  
  196.         #Clean the elements previously drawn.
  197.         self.clear()        
  198.        
  199.         self.background.draw(gl.GL_QUADS)
  200.         self.title.draw()
  201.        
  202.         #Check the dragged object position
  203.         if self.dragged_object:
  204.             body = self.dragged_object.body
  205.             body.position.x = self.mouse_pos[0]+self.drag_offset[0]
  206.             body.position.y = self.mouse_pos[1]+self.drag_offset[1]
  207.        
  208.         for i in self.statics:
  209.             i.draw()
  210.        
  211.         for i in self.dynamics:
  212.             i.draw()
  213.            
  214.         self.fps_display.draw()
  215.        
  216. if __name__ == '__main__':
  217.     w = Game(caption="Drag&Drop Test", width=500, height=500, visible=False)
  218.     clock.schedule_interval(w.update, 1.0/60.0)
  219.     app.run()
Advertisement
Add Comment
Please, Sign In to add comment