Advertisement
FaDaQ

Pymunk and PyGame - Physics Balls

Jul 5th, 2022
755
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 18.13 KB | None | 0 0
  1. import pygame as pg
  2. import pymunk.pygame_util
  3. from pygame.locals import *
  4. from random import uniform, randrange
  5. from sys import exit as sysExit
  6. import gameSettings
  7.  
  8. pymunk.pygame_util.positive_y_is_up = False
  9.  
  10. WIDTH, HEIGHT = 1280, 720
  11. FPS = 60
  12.  
  13. # объявление всего необходимого
  14. pg.init()
  15.  
  16. settings = gameSettings.parseSettings()
  17.  
  18. display = pg.display.set_mode((WIDTH, HEIGHT), pg.RESIZABLE)
  19. pg.display.set_caption("Мячики с физикой на PyGame + Pymunk")
  20. clock = pg.time.Clock()
  21. draw_option = pymunk.pygame_util.DrawOptions(display)
  22.  
  23. space = pymunk.Space()
  24. space.gravity = 0, 2000
  25.  
  26. """ объекты """
  27. # платформы
  28. segment_shape = pymunk.Segment(space.static_body, (0, HEIGHT + 35), (WIDTH + 10000, HEIGHT + 35), 50)
  29. segment_shape.elasticity = 0.5
  30. segment_shape.friction = 0.5
  31. space.add(segment_shape)
  32.  
  33. verifyLimitCreation = False
  34. temp = []
  35.  
  36.  
  37. def createWindowLimits(create):
  38.     global temp
  39.     global verifyLimitCreation
  40.     if create:
  41.         temp = []
  42.         verifyLimitCreation = True
  43.         segment_shape = pymunk.Segment(space.static_body, (-35, 0), (-35, pg.display.get_window_size()[1]), 50)
  44.         segment_shape.elasticity = 0.5
  45.         segment_shape.friction = 0.5
  46.         temp.append(segment_shape)
  47.  
  48.         segment_shape = pymunk.Segment(space.static_body, (pg.display.get_window_size()[0] + 35, 0),
  49.                                        (pg.display.get_window_size()[0] + 35, pg.display.get_window_size()[1]), 50)
  50.         segment_shape.elasticity = 0.5
  51.         segment_shape.friction = 0.5
  52.         temp.append(segment_shape)
  53.  
  54.         segment_shape = pymunk.Segment(space.static_body, (0, 0 - 35), (pg.display.get_window_size()[0], 0 - 35), 50)
  55.         segment_shape.elasticity = 0.5
  56.         segment_shape.friction = 0.5
  57.         temp.append(segment_shape)
  58.         for i in temp:
  59.             space.add(i)
  60.     else:
  61.         for i in temp:
  62.             space.remove(i)
  63.         verifyLimitCreation = False
  64.  
  65.  
  66. # создать мячик
  67. ball_arr = []
  68. ball_size = settings[0]
  69. ballSize_font = pg.font.SysFont('serif', 18)
  70. ballSize_fontRender = ballSize_font.render(f"Размер мячиков: {ball_size}(↑ or ↓)", True, (0, 0, 0))
  71. placePos_ballSizeFont = ballSize_fontRender.get_rect(topleft=(5, 18))
  72.  
  73. ball_elasticity = settings[1]
  74. ballElasticity_font = pg.font.SysFont('serif', 18)
  75. ballElasticity_fontRender = ballElasticity_font.render(f"Упругость мячиков: {ball_elasticity}(F1 or F2)", True,
  76.                                                        (0, 0, 0))
  77. placePos_ballElasticityFont = ballElasticity_fontRender.get_rect(topleft=(5, 36))
  78.  
  79. ball_friction = settings[2]
  80. ballFriction_font = pg.font.SysFont('serif', 18)
  81. ballFriction_fontRender = ballFriction_font.render(f"Трение мячиков: {ball_friction}(F3 or F4)", True, (0, 0, 0))
  82. placePos_ballFrictionFont = ballFriction_fontRender.get_rect(topleft=(5, 54))
  83.  
  84. ball_mass = settings[3]
  85. ballMass_font = pg.font.SysFont('serif', 18)
  86. ballMass_fontRender = ballMass_font.render(f"Масса мячиков: {ball_mass}(F5 or F6)", True, (0, 0, 0))
  87. placePos_ballMassFont = ballMass_fontRender.get_rect(topleft=(5, 72))
  88.  
  89.  
  90. def createBall(mass, radius, position, elasticity, friction, color):
  91.     ball_mass, ball_radius = mass, radius
  92.     ball_moment = pymunk.moment_for_circle(ball_mass, 0, ball_radius)
  93.     ball_body = pymunk.Body(ball_mass, ball_moment)
  94.     ball_body.position = position
  95.     ball_shape = pymunk.Circle(ball_body, ball_radius)
  96.     ball_shape.elasticity = elasticity
  97.     ball_shape.friction = friction
  98.     ball_shape.color = color
  99.     space.add(ball_body, ball_shape)
  100.     ball_arr.append(ball_body)
  101.     ball_arr.append(ball_shape)
  102.  
  103.  
  104. # статическая линия для рисования платформ
  105. painter_line_arr = []
  106. # painter_line_arrTemp - нужен для запоминания удалённых объектов для их возвращения на сцену
  107. painter_line_arrTemp = []
  108. painter_line_size = 10
  109. painter_line_font = pg.font.SysFont('serif', 18)
  110. painter_line_fontRender = painter_line_font.render(f"Размер кисти препятствий: {painter_line_size}(→ or ←)", True,
  111.                                                    (0, 0, 0))
  112. placePos_painter_ballFont = painter_line_fontRender.get_rect(topleft=(5, 0))
  113.  
  114. # вот тут вот я РАНЬШЕ не понимал, в чём проблема и как заставить это работать(сейчас это работает)
  115. lastMousePos = None
  116. mousePressed = False
  117.  
  118.  
  119. def createPainterLine(radius, singleClickVerify):
  120.     if singleClickVerify == False:
  121.         segment_shape = pymunk.Segment(space.static_body, lastMousePos,
  122.                                        (pg.mouse.get_pos()[0], pg.mouse.get_pos()[1]), radius)
  123.         segment_shape.elasticity = 0.4
  124.         segment_shape.friction = 0.5
  125.         space.add(segment_shape)
  126.         painter_line_arr.append(segment_shape)
  127.     else:
  128.         segment_shape = pymunk.Segment(space.static_body, lastMousePos,
  129.                                        (pg.mouse.get_pos()[0] + 1, pg.mouse.get_pos()[1] + 1), radius)
  130.         segment_shape.elasticity = 0.4
  131.         segment_shape.friction = 0.5
  132.         space.add(segment_shape)
  133.         painter_line_arr.append(segment_shape)
  134.  
  135.  
  136. def deletePainterLine():
  137.     for i in range(0, len(painter_line_arr)):
  138.         space.remove(painter_line_arr[i])
  139.     painter_line_arr.clear()
  140.  
  141.  
  142. def deleteBalls():
  143.     for i in range(0, len(ball_arr)):
  144.         space.remove(ball_arr[i])
  145.     ball_arr.clear()
  146.  
  147.  
  148. def deleteRectangles():
  149.     for i in range(0, len(rectangle_arr)):
  150.         space.remove(rectangle_arr[i])
  151.     rectangle_arr.clear()
  152.  
  153.  
  154. # надпись с FPS
  155. fps_font = pg.font.SysFont('serif', 18)
  156. fps_fontRender = fps_font.render(f"FPS = {round(clock.get_fps(), 2)}", True, (0, 0, 0))
  157. display_rect = display.get_rect()
  158. placePos_fps_font = painter_line_fontRender.get_rect(topright=(pg.display.get_window_size()[0] + 220, 0))
  159.  
  160. # создать прямоугольник
  161. rectangle_arr = []
  162. rectangle_mass = settings[4]
  163. rectangle_width = settings[5]
  164. rectangle_height = settings[6]
  165. rectangle_elasticity = settings[7]
  166. rectangle_friction = settings[8]
  167.  
  168. rect_font = pg.font.SysFont('serif', 18)
  169. rectWidth_fontRender = rect_font.render(f"Ширина прям-ов: {rectangle_width}(F7 or F8)", True, (0, 0, 0))
  170. placePos_rectWidthFont = rectWidth_fontRender.get_rect(topleft=(320, 0))
  171.  
  172. rectHeight_fontRender = rect_font.render(f"Высота прям-ов: {rectangle_height}(F9 or F10)", True, (0, 0, 0))
  173. placePos_rectHeightFont = ballSize_fontRender.get_rect(topleft=(320, 18))
  174.  
  175. rectMass_fontRender = rect_font.render(f"Масса прям-ов: {rectangle_mass}(F11 or F12)", True, (0, 0, 0))
  176. placePos_rectMassFont = ballSize_fontRender.get_rect(topleft=(320, 36))
  177.  
  178. rectElasticity_fontRender = rect_font.render(f"Упругость прям-ов: {rectangle_elasticity}(1 or 2)", True, (0, 0, 0))
  179. placePos_rectElasticityFont = rectElasticity_fontRender.get_rect(topleft=(320, 54))
  180.  
  181. rectFriction_fontRender = rect_font.render(f"Трение прям-ов: {rectangle_friction}(3 or 4)", True, (0, 0, 0))
  182. placePos_rectFrictionFont = rectElasticity_fontRender.get_rect(topleft=(320, 72))
  183.  
  184.  
  185. def CreateRectangle(rectangle_mass, pos, rectangle_height, rectangle_width, rectangle_elasticity, rectangle_friction):
  186.     square_mass, square_size = rectangle_mass, (rectangle_width, rectangle_height)
  187.     square_moment = pymunk.moment_for_box(square_mass, square_size)
  188.     square_body = pymunk.Body(square_mass, square_moment)
  189.     square_body.position = pos
  190.     square_shape = pymunk.Poly.create_box(square_body, square_size)
  191.     square_shape.elasticity = rectangle_elasticity
  192.     square_shape.friction = rectangle_friction
  193.     square_shape.color = [randrange(256) for i in range(4)]
  194.     rectangle_arr.append(square_shape)
  195.     space.add(square_body, square_shape)
  196.  
  197.  
  198. # надпись гравитации
  199. gravity = True
  200. gravity_font = pg.font.SysFont('serif', 18)
  201. gravity_fontRender = rect_font.render(f"Гравитация: {gravity}(G)", True, (0, 0, 0))
  202. placePos_GravityFont = gravity_fontRender.get_rect(topright=(pg.display.get_window_size()[0] - 5, 18))
  203.  
  204. while True:
  205.     settings = gameSettings.parseSettings()
  206.     display.fill((0, 160, 90))
  207.  
  208.     mouseKeys = pg.mouse.get_pressed()
  209.     keyboardKeys = pg.key.get_pressed()
  210.  
  211.     for event in pg.event.get():
  212.         if event.type == pg.QUIT:
  213.             sysExit()
  214.         elif event.type == pg.MOUSEBUTTONUP:
  215.             mousePressed = False
  216.             f1pressed = False
  217.         elif event.type == pg.MOUSEBUTTONDOWN:
  218.             if event.button == 1:
  219.                 createBall(ball_mass, ball_size, pg.mouse.get_pos(), ball_elasticity, ball_friction,
  220.                            [uniform(0, 255) for i in range(4)])
  221.             elif event.button == 3:
  222.                 singleClickVerify = True
  223.                 lastMousePos = pg.mouse.get_pos()
  224.                 createPainterLine(painter_line_size, singleClickVerify)
  225.                 mousePressed = True
  226.             elif event.button == 2:
  227.                 deletePainterLine()
  228.                 deleteBalls()
  229.                 deleteRectangles()
  230.         elif event.type == pg.MOUSEMOTION:
  231.             if mousePressed:
  232.                 singleClickVerify = False
  233.                 createPainterLine(painter_line_size, singleClickVerify)
  234.                 lastMousePos = pg.mouse.get_pos()
  235.         elif event.type == pg.WINDOWSIZECHANGED:
  236.             placePos_GravityFont = gravity_fontRender.get_rect(topright=(pg.display.get_window_size()[0] - 5, 18))
  237.             placePos_fps_font = painter_line_fontRender.get_rect(topright=(pg.display.get_window_size()[0] + 220, 0))
  238.             space.remove(segment_shape)
  239.             segment_shape = pymunk.Segment(space.static_body, (1, pg.display.get_window_size()[1] + 35),
  240.                                            (pg.display.get_window_size()[0], pg.display.get_window_size()[1] + 35), 50)
  241.             segment_shape.elasticity = 0.5
  242.             segment_shape.friction = 0.5
  243.             space.add(segment_shape)
  244.  
  245.             if verifyLimitCreation:
  246.                 for i in temp:
  247.                     space.remove(i)
  248.                 createWindowLimits(True)
  249.         elif event.type == pg.KEYDOWN:
  250.             if event.key == pg.K_RIGHT:
  251.  
  252.                 painter_line_size += 1
  253.                 painter_line_fontRender = painter_line_font.render(
  254.                     f"Размер кисти препятствий: {painter_line_size}(→ or ←)", True,
  255.                     (0, 0, 0))
  256.  
  257.             elif event.key == K_LEFT:
  258.                 painter_line_size -= 1
  259.                 painter_line_fontRender = painter_line_font.render(
  260.                     f"Размер кисти препятствий: {painter_line_size}(→ or ←)", True,
  261.                     (0, 0, 0))
  262.  
  263.             elif event.key == K_UP:
  264.                 gameSettings.changeFileParameters(1, ball_size=True)
  265.             elif event.key == K_DOWN:
  266.                 gameSettings.changeFileParameters(1, action=False, ball_size=True)
  267.             elif event.key == K_F1:
  268.                 gameSettings.changeFileParameters(0.1, ball_elasticity=True)
  269.             elif event.key == K_F2:
  270.                 if settings[1] > 0:
  271.                     gameSettings.changeFileParameters(0.1, action=False, ball_elasticity=True)
  272.                 else:
  273.                     pass
  274.  
  275.             elif event.key == K_F5:
  276.                 gameSettings.changeFileParameters(0.1, ball_mass=True)
  277.  
  278.             elif event.key == K_F6:
  279.                 temp_mass = ball_mass
  280.                 if settings[3] > 0.1:
  281.                     gameSettings.changeFileParameters(0.1, action=False, ball_mass=True)
  282.                 else:
  283.                     pass
  284.             elif event.key == K_F3:
  285.                 gameSettings.changeFileParameters(0.1, ball_friction=True)
  286.  
  287.             elif event.key == K_F4:
  288.                 gameSettings.changeFileParameters(0.1, ball_friction=True, action=False)
  289.  
  290.             elif event.key == K_F7:
  291.                 gameSettings.changeFileParameters(1, rectangle_width=True)
  292.             elif event.key == K_F8:
  293.                 gameSettings.changeFileParameters(1, action=False, rectangle_width=True)
  294.             elif event.key == K_F9:
  295.                 gameSettings.changeFileParameters(1, rectangle_height=True)
  296.             elif event.key == K_F10:
  297.                 gameSettings.changeFileParameters(1, action=False, rectangle_height=True)
  298.             elif event.key == K_F11:
  299.                 gameSettings.changeFileParameters(0.1, rectangle_mass=True)
  300.             elif event.key == K_F12:
  301.                 gameSettings.changeFileParameters(0.1, action=False, rectangle_mass=True)
  302.             elif event.key == K_1:
  303.                 gameSettings.changeFileParameters(0.1, rectangle_elasticity=True)
  304.             elif event.key == K_2:
  305.                 if settings[7] > 0.1:
  306.                     gameSettings.changeFileParameters(0.1, action=False, rectangle_elasticity=True)
  307.                 else:
  308.                     pass
  309.                 gameSettings.changeFileParameters(0.1, action=False, rectangle_elasticity=True)
  310.             elif event.key == K_3:
  311.                 gameSettings.changeFileParameters(0.1, rectangle_friction=True)
  312.             elif event.key == K_4:
  313.                 if settings[8] > 0.1:
  314.                     gameSettings.changeFileParameters(0.1, action=False, rectangle_friction=True)
  315.                 else:
  316.                     pass
  317.                 gameSettings.changeFileParameters(0.1, action=False, rectangle_friction=True)
  318.             elif event.key == K_l:
  319.                 if not verifyLimitCreation:
  320.                     createWindowLimits(True)
  321.                 else:
  322.                     createWindowLimits(False)
  323.             elif event.key == K_r:
  324.                 CreateRectangle(rectangle_mass, pg.mouse.get_pos(), rectangle_height, rectangle_width,
  325.                                 rectangle_elasticity,
  326.                                 rectangle_friction)
  327.             elif event.key == K_g:
  328.                 if gravity:
  329.                     space.gravity = 0, 0
  330.                     gravity = False
  331.                     gravity_fontRender = rect_font.render(f"Гравитация: {gravity}(G)", True, (0, 0, 0))
  332.                 else:
  333.                     space.gravity = 0, 2000
  334.                     gravity = True
  335.                     gravity_fontRender = rect_font.render(f"Гравитация: {gravity}(G)", True, (0, 0, 0))
  336.  
  337.     if mouseKeys[0] and keyboardKeys[K_LSHIFT]:
  338.         createBall(ball_mass, ball_size, pg.mouse.get_pos(), ball_elasticity, ball_friction,
  339.                    [uniform(0, 255) for i in range(4)])
  340.  
  341.     elif keyboardKeys[K_r] and keyboardKeys[K_LSHIFT]:
  342.         pass
  343.     if keyboardKeys[K_LCTRL] and keyboardKeys[K_z] and not keyboardKeys[K_LSHIFT]:
  344.         try:
  345.             space.remove(painter_line_arr[-1])
  346.             painter_line_arrTemp.append(painter_line_arr[-1])
  347.             painter_line_arr.pop(-1)
  348.         except IndexError:
  349.             painter_line_arrTemp.clear()
  350.             pass
  351.     if keyboardKeys[K_LCTRL] and keyboardKeys[K_z] and keyboardKeys[K_LSHIFT]:
  352.         try:
  353.             space.add(painter_line_arrTemp[-1])
  354.             painter_line_arr.append(painter_line_arrTemp[-1])
  355.             painter_line_arrTemp.pop(-1)
  356.         except:
  357.             pass
  358.     space.step(1 / FPS)
  359.     space.debug_draw(draw_option)
  360.  
  361.     display.blit(rectWidth_fontRender, placePos_rectWidthFont)
  362.     display.blit(rectHeight_fontRender, placePos_rectHeightFont)
  363.     display.blit(rectMass_fontRender, placePos_rectMassFont)
  364.     display.blit(rectElasticity_fontRender, placePos_rectElasticityFont)
  365.     display.blit(rectFriction_fontRender, placePos_rectFrictionFont)
  366.  
  367.     display.blit(painter_line_fontRender, placePos_painter_ballFont)
  368.     display.blit(ballSize_fontRender, placePos_ballSizeFont)
  369.     display.blit(ballElasticity_fontRender, placePos_ballElasticityFont)
  370.     display.blit(ballMass_fontRender, placePos_ballMassFont)
  371.     display.blit(ballFriction_fontRender, placePos_ballFrictionFont)
  372.  
  373.     display.blit(fps_fontRender, placePos_fps_font)
  374.     display.blit(gravity_fontRender, placePos_GravityFont)
  375.  
  376.     # мячики
  377.     ball_size = settings[0]
  378.     ball_elasticity = settings[1]
  379.     ball_friction = settings[2]
  380.     ball_mass = settings[3]
  381.  
  382.     ballSize_fontRender = ballSize_font.render(f"Размер мячиков: {ball_size}(↑ or ↓)", True, (0, 0, 0))
  383.     ballElasticity_fontRender = ballElasticity_font.render(f"Упругость мячиков: {ball_elasticity}(F1 or F2)",
  384.                                                            True, (0, 0, 0))
  385.     ballFriction_fontRender = ballFriction_font.render(f"Трение мячиков: {ball_friction}(F3 or F4)", True,
  386.                                                        (0, 0, 0))
  387.     ballMass_fontRender = ballMass_font.render(f"Масса мячиков: {ball_mass}(F5 or F6)", True,
  388.                                                (0, 0, 0))
  389.  
  390.     # прямоугольники
  391.     rectangle_mass = settings[4]
  392.     rectangle_width = settings[5]
  393.     rectangle_height = settings[6]
  394.     rectangle_elasticity = settings[7]
  395.     rectangle_friction = settings[8]
  396.  
  397.     rectWidth_fontRender = rect_font.render(f"Ширина прям-ов: {rectangle_width}(F7 or F8)", True,
  398.                                             (0, 0, 0))
  399.     rectHeight_fontRender = rect_font.render(f"Высота прям-ов: {rectangle_height}(F9 or F10)", True,
  400.                                              (0, 0, 0))
  401.     rectMass_fontRender = rect_font.render(f"Масса прям-ов: {rectangle_mass}(F11 or F12)", True,
  402.                                            (0, 0, 0))
  403.     rectElasticity_fontRender = rect_font.render(f"Упругость прям-ов: {rectangle_elasticity}(1 or 2)", True,
  404.                                                  (0, 0, 0))
  405.  
  406.     rectFriction_fontRender = rect_font.render(f"Трение прям-ов: {rectangle_friction}(3 or 4)", True, (0, 0, 0))
  407.  
  408.     pg.display.flip()
  409.     clock.tick(FPS)
  410.  
  411.     fps_fontRender = fps_font.render(f"FPS: {round(clock.get_fps(), 2)}", True, (0, 0, 0))
  412.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement