Layer 1

lundi 2 avril 2012

Module Box2D pour Python

Le jeu "Angry Birds" utilise le module Box2D en version 2.2.1.
C'est une librairie C++, open-source,  pour faciliter le développement des applications utilisant des objets 2D: interaction physique d'objet dans un monde dont vous choisissez la puissance gravitationnelle suivant les deux axes.
Cette librairie a été porté sous Python, en utilisant le mécanisme SWIG, et est aujourd'hui en version 2.0.2 béta.
Pour l'utiliser sous Python 2.7 il faut recompiler l'archive  en utilisant MinGW, compilateur C OpenSource et MSYS, shell gnu pour utiliser les scripts de compilation Linux. Ça fait peur comme ça ! Mais ça roule sans problème même sans connaissance Linux.

Direction le manuel de Box2D. (Attention ne pas prendre le manuel de la future version 2.1 !)

Test du module: " Jeu de balles rebondissantes "



Script 'Box2D_tests.py' - Python (v2.7/windows)

version améliorée avec possibilité d'ajouter des balles avec le clique droit de la souris




  1 #!/usr/bin/python
  2 # -*- coding: iso-8859-15 -*-
  3 '''
  4 Created on 22 fvr. 2012
  5 
  6 @author: damien
  7 '''
  8 import random
  9 import pygame
 10 from Box2D import *
 11 
 12 #Taille de l'écran
 13 size=[400,800]
 14 # Initialize the game engine
 15 pygame.init()
 16 screen=pygame.display.set_mode(size)
 17 pygame.display.set_caption("Balls Test")
 18 pygame.display.toggle_fullscreen()
 19  
 20 
 21 #Zone de calcul de Box2D & création de l'objet world
 22 worldAABB=b2AABB()
 23 worldAABB.lowerBound = (-10000.0, -10000.0)
 24 worldAABB.upperBound = ( 10000.0, 10000.0)
 25 gravity = (1.0, -10.0)
 26 #permet d'arrêter le calcul des coord. d'un body lorsqu'il est immobile
 27 doSleep = True
 28 world = b2World(worldAABB, gravity, doSleep)
 29 
 30 #définition de body/shape (implicitement static) définissant les 'parois'
 31 groundBodyDef = b2BodyDef()
 32 groundShapeDef = b2PolygonDef()
 33 
 34 #création de deux parois (horizontale penché et verticale par rapport au point body en bas à gauche = coord.(0,0)
 35 groundBodyDef.position = (0, 0)
 36 groundBody = world.CreateBody(groundBodyDef)
 37 groundShapeDef.setVertices( [ (-150, 0.0), (150, 0.0), (0.0, 10) ] )
 38 groundBody.CreateShape(groundShapeDef)
 39 groundShapeDef.SetAsBox(1, 400)
 40 groundBody.CreateShape(groundShapeDef)
 41 
 42 #création d'une paroi (horizontale penché type triangle) à partir du gauche/bas de l'écran
 43 groundBodyDef.position = (400, 0)
 44 groundBody = world.CreateBody(groundBodyDef)
 45 groundBody.CreateShape(groundShapeDef)
 46 groundShapeDef.setVertices( [ (-150, 0.0), (150, 0.0), (0.0, 10) ] )
 47 groundBody.CreateShape(groundShapeDef)
 48 
 49 #.setVertices( [ (-1.0, 0.0), (1.0, 0.0), (0.0, 2.0) ] )
 50 groundBodyDef.position = (210,size[1]/2-25)
 51 groundShapeDef.setVertices( [ (-100, 0.0), (100, 0.0), (0.0, 60) ] )
 52 groundBody = world.CreateBody(groundBodyDef)
 53 groundBody.CreateShape(groundShapeDef)
 54 
 55 nb_balls=10
 56 # Création des body balls
 57 for i in range(nb_balls):
 58     bodyDef= b2BodyDef()
 59     bodyDef.position = ((i+1)*400/(nb_balls+1), 800)
 60     body= world.CreateBody(bodyDef)
 61     shapeDef = b2CircleDef()
 62     shapeDef.radius=10
 63     shapeDef.density = 0.1*(1+random.random())
 64     shapeDef.friction = 0.3
 65     shapeDef.restitution=0.9
 66     body.CreateShape(shapeDef)
 67     body.SetMassFromShapes()
 68     body.userData=[int(random.random()*255),int(random.random()*255),int(random.random()*255)]
 69 # Gestion du temps de simulation: calcul de 60 coordonnées des body par secondes
 70 timeStep = 1.0 / 50.0
 71 velocityIterations = 10
 72 positionIterations = 8
 73 world.Step(timeStep, velocityIterations, positionIterations)
 74 
 75 
 76 
 77 
 78  
 79 # Define the colors we will use in RGB format
 80 black = [  0,  0,  0]
 81 white = [255,255,255]
 82 blue =  [  0,  0,255]
 83 green = [  0,255,  0]
 84 red =   [255,  0,  0]
 85  
 86 pi=3.141592653
 87  
 88 #Loop until the user clicks the close button.
 89 done=False;nbhigh=0
 90 clock = pygame.time.Clock()
 91 
 92 while done==False:
 93  
 94     # This limits the while loop to a max of 10 times per second.
 95     # Leave this out and we will use all CPU we can.
 96     clock.tick(500)
 97      
 98     for event in pygame.event.get(): # User did something
 99         if event.type == pygame.QUIT: # If user clicked close
100             done=True # Flag that we are done so we exit this loop
101         if event.type == pygame.MOUSEBUTTONDOWN:
102             bodyDef= b2BodyDef()
103             x,y=pygame.mouse.get_pos()
104             bodyDef.position = (x,800-y)
105             body= world.CreateBody(bodyDef)
106             shapeDef = b2CircleDef()
107             shapeDef.radius=10
108             shapeDef.density = 0.1*(1+random.random())
109             shapeDef.friction = 0.3
110             shapeDef.restitution=0.9
111             body.CreateShape(shapeDef)
112             body.SetMassFromShapes()
113             body.userData=[int(random.random()*255),int(random.random()*255),int(random.random()*255)]
114  
115 
116     screen.fill(black)
117     world.Step(timeStep, velocityIterations, positionIterations)
118     nb=0
119     for balls in world:
120         if balls.IsDynamic() :
121             if int(balls.position[1])<-1000:world.DestroyBody(balls)
122             nb+=1
123             try:
124                 pygame.draw.circle(screen, balls.userData,[int(balls.position[0]),800-int(balls.position[1])],10,5)
125             except:
126                 pass
127         if balls.IsStatic() :
128             for shape in balls.shapeList: # iterates over body.shapeList
129                 try:
130                     shape_coords=[[int(balls.position[0])+sx,800-int(balls.position[1])-sy] for sx,sy in shape.vertices]
131                     pygame.draw.lines(screen, white, True, shape_coords, 5)
132                 except:
133                     pass
134                 
135     # Select the font to use. Default font, 25 pt size.
136     font = pygame.font.Font(None, 25)
137     # Render the text. "True" means anti-aliased text. 
138     # Black is the color. This creates an image of the 
139     # letters, but does not put it on the screen
140     text = font.render("{:^10}".format(str(nb)+" Balles"),True,green)
141     # Put the image of the text on the screen at 250x250
142     screen.blit(text, [size[0]/2-2*8,size[1]/2])
143     
144     if nbhigh<nb : nbhigh=nb
145     text = font.render(("{:^10}".format('HighScore='+str(nbhigh))),True,red)
146     screen.blit(text, [2,2])
147   
148  
149     # Go ahead and update the screen with what we've drawn.
150     # This MUST happen after all the other drawing commands.
151     pygame.display.flip()
152  
153 # Be IDLE friendly
154 pygame.quit ()

1 commentaire: