tutorial2.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/usr/bin/env python
  2. # http://pyode.sourceforge.net/tutorials/tutorial2.html
  3. # pyODE example 2: Connecting bodies with joints
  4. # modified by Gideon Klompje (removed literals and using
  5. # 'ode.Mass.setSphereTotal' instead of 'ode.Mass.setSphere')
  6. import ode
  7. import pygame
  8. from pygame.locals import QUIT, KEYDOWN
  9. # Constants
  10. WINDOW_RESOLUTION = (640, 480)
  11. DRAW_SCALE = WINDOW_RESOLUTION[0] / 5
  12. """Factor to multiply physical coordinates by to obtain screen size in pixels"""
  13. DRAW_OFFSET = (WINDOW_RESOLUTION[0] / 2, 50)
  14. """Screen coordinates (in pixels) that map to the physical origin (0, 0, 0)"""
  15. BACKGROUND_COLOR = (255, 255, 255)
  16. GRAVITY = (0, -9.81, 0)
  17. SPHERE1_POSITION = (1, 0, 0)
  18. SPHERE1_MASS = 1
  19. SPHERE1_RADIUS = 0.15
  20. SPHERE1_COLOR = (55, 0, 200)
  21. SPHERE2_POSITION = (2, 0, 0)
  22. SPHERE2_MASS = 1
  23. SPHERE2_RADIUS = 0.15
  24. SPHERE2_COLOR = (55, 0, 200)
  25. JOINT1_ANCHOR = (0, 0, 0)
  26. JOINT1_COLOR = (200, 0, 55)
  27. JOINT1_WIDTH = 2
  28. """Width of the line (in pixels) representing the joint"""
  29. JOINT2_ANCHOR = SPHERE1_POSITION
  30. JOINT2_COLOR = (200, 0, 55)
  31. JOINT2_WIDTH = 2
  32. """Width of the line (in pixels) representing the joint"""
  33. TIME_STEP = 0.04
  34. # Utility functions
  35. def coord(x, y, integer=False):
  36. """
  37. Convert world coordinates to pixel coordinates. Setting 'integer' to
  38. True will return integer coordinates.
  39. """
  40. xs = (DRAW_OFFSET[0] + DRAW_SCALE*x)
  41. ys = (DRAW_OFFSET[1] - DRAW_SCALE*y)
  42. if integer:
  43. return int(round(xs)), int(round(ys))
  44. else:
  45. return xs, ys
  46. # Initialize pygame
  47. pygame.init()
  48. # Open a display
  49. screen = pygame.display.set_mode(WINDOW_RESOLUTION)
  50. # Create a world object
  51. world = ode.World()
  52. world.setGravity(GRAVITY)
  53. # Create two bodies
  54. body1 = ode.Body(world)
  55. M = ode.Mass()
  56. M.setSphereTotal(SPHERE1_MASS, SPHERE1_RADIUS)
  57. body1.setMass(M)
  58. body1.setPosition(SPHERE1_POSITION)
  59. body2 = ode.Body(world)
  60. M = ode.Mass()
  61. M.setSphereTotal(SPHERE2_MASS, SPHERE2_RADIUS)
  62. body2.setMass(M)
  63. body2.setPosition(SPHERE2_POSITION)
  64. # Connect body1 with the static environment
  65. j1 = ode.BallJoint(world)
  66. j1.attach(body1, ode.environment)
  67. j1.setAnchor(JOINT1_ANCHOR)
  68. # Connect body2 with body1
  69. j2 = ode.BallJoint(world)
  70. j2.attach(body1, body2)
  71. j2.setAnchor(JOINT2_ANCHOR)
  72. # Simulation loop...
  73. if __name__ == "__main__":
  74. fps = 1.0 / TIME_STEP
  75. clk = pygame.time.Clock()
  76. sph1_rad = int(DRAW_SCALE * SPHERE1_RADIUS)
  77. sph2_rad = int(DRAW_SCALE * SPHERE2_RADIUS)
  78. loopFlag = True
  79. while loopFlag:
  80. for e in pygame.event.get():
  81. if e.type==QUIT:
  82. loopFlag=False
  83. if e.type==KEYDOWN:
  84. loopFlag=False
  85. # Clear the screen
  86. screen.fill(BACKGROUND_COLOR)
  87. # Draw the two bodies and the lines representing the joints
  88. x1, y1, z1 = body1.getPosition()
  89. x2, y2, z2 = body2.getPosition()
  90. xj1, yj1, zj1 = j1.getAnchor()
  91. xj2, yj2, zj2 = j2.getAnchor()
  92. pygame.draw.line(screen, JOINT1_COLOR, coord(xj1, yj1), coord(x1, y1), JOINT1_WIDTH)
  93. pygame.draw.line(screen, JOINT2_COLOR, coord(xj2, yj2), coord(x2, y2), JOINT2_WIDTH)
  94. pygame.draw.circle(screen, SPHERE1_COLOR, coord(x1, y1, integer=True), sph1_rad, 0)
  95. pygame.draw.circle(screen, SPHERE2_COLOR, coord(x2, y2, integer=True), sph2_rad, 0)
  96. pygame.display.flip()
  97. # Next simulation step
  98. world.step(TIME_STEP)
  99. # Try to keep the specified framerate
  100. clk.tick(fps)