demo16.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. program demo16;
  2. // RU: В этом файле конфигурации содержится "опция" USE_CHIPMUNK_STATIC для статической компиляции с Chipmunk
  3. // EN: This file contains "option" USE_CHIPMUNK_STATIC for static compilation with Chipmunk
  4. {$I zglCustomConfig.cfg}
  5. {$I zgl_config.cfg}
  6. uses
  7. {$IFDEF UNIX}
  8. cthreads,
  9. {$ENDIF}
  10. zglChipmunk,
  11. {$IFDEF USE_ZENGL_STATIC}
  12. zgl_screen,
  13. zgl_window,
  14. zgl_timers,
  15. zgl_keyboard,
  16. zgl_mouse,
  17. zgl_textures,
  18. zgl_textures_png,
  19. zgl_render_2d,
  20. zgl_font,
  21. zgl_text,
  22. zgl_primitives_2d,
  23. zgl_math_2d,
  24. zgl_types,
  25. zgl_utils
  26. {$ELSE}
  27. zglHeader
  28. {$ENDIF}
  29. ;
  30. var
  31. dirRes : UTF8String {$IFNDEF MACOSX} = '../data/' {$ENDIF};
  32. fntMain : Byte;
  33. space : PcpSpace;
  34. bCount : Integer;
  35. Bodies : array of PcpBody;
  36. Shapes : array of PcpShape;
  37. TimePhisics: Byte;
  38. // RU: Добавить объект "шар"
  39. // x, y - координаты центра
  40. // mass - масса
  41. // r - радиус
  42. // e - коэффициент эластичности
  43. // u - коэффициент трения
  44. //
  45. // EN: Add new object "ball"
  46. // x, y - coordinates
  47. // mass - mass
  48. // r - radius
  49. // e - coefficient of restitution. (elasticity)
  50. // u - coefficient of friction
  51. procedure cpAddBall(x, y, r, mass, e, u : cpFloat);
  52. begin
  53. INC(bCount);
  54. SetLength(Bodies, bCount);
  55. SetLength(Shapes, bCount);
  56. Bodies[bCount - 1] := cpBodyNew(mass, cpMomentForCircle(mass, 0, r, cpvzero));
  57. Bodies[bCount - 1]^.p := cpv(x, y);
  58. cpSpaceAddBody(space, Bodies[bCount - 1]);
  59. Shapes[bCount - 1] := cpCircleShapeNew(Bodies[bCount - 1], r, cpvzero);
  60. Shapes[bCount - 1]^.e := e;
  61. Shapes[bCount - 1]^.u := u;
  62. cpSpaceAddShape( space, Shapes[ bCount - 1 ] );
  63. end;
  64. // RU: Добавить объект "коробка"
  65. // Схож с процедурой cpAddBall по аргументам
  66. // x, y - координаты центра
  67. // w, h - ширина и высота
  68. //
  69. // EN: Add bew object "box"
  70. // Arguments are similar to arguments of procedure cpAddBall
  71. // x, y - coordinates of center
  72. // w, h - width and height
  73. procedure cpAddBox(x, y, w, h, mass, e, u : cpFloat);
  74. var
  75. points : array[0..3] of cpVect;
  76. f : cpFloat;
  77. begin
  78. INC(bCount);
  79. SetLength(Bodies, bCount);
  80. SetLength(Shapes, bCount);
  81. points[0].x := - w / 2;
  82. points[0].y := - h / 2;
  83. points[1].x := - w / 2;
  84. points[1].y := h / 2;
  85. points[2].x := w / 2;
  86. points[2].y := h / 2;
  87. points[3].x := w / 2;
  88. points[3].y := - h / 2;
  89. f := cpMomentForPoly(mass, 4, @points[0], cpvzero);
  90. Bodies[bCount - 1] := cpBodyNew(mass, f);
  91. Bodies[bCount - 1]^.p := cpv(x + w / 2, y + h / 2);
  92. cpSpaceAddBody(space, Bodies[bCount - 1]);
  93. Shapes[bCount - 1] := cpPolyShapeNew(Bodies[bCount - 1], 4, @points[0], cpvzero);
  94. Shapes[bCount - 1]^.e := e;
  95. Shapes[bCount - 1]^.u := u;
  96. cpSpaceAddShape(space, Shapes[bCount - 1]);
  97. end;
  98. procedure Init;
  99. var
  100. staticBody : PcpBody;
  101. ground : PcpShape;
  102. e, u : cpFloat;
  103. begin
  104. fntMain := font_LoadFromFile(dirRes + 'font.zfi');
  105. setFontTextScale(15, fntMain);
  106. cpInitChipmunk();
  107. // RU: Создаем новый "мир".
  108. // EN: Create new world.
  109. space := cpSpaceNew();
  110. // RU: Задаем количество итераций обработки(рекомендуется 10).
  111. // EN: Set count of iterations of processing(recommended is 10).
  112. space^.iterations := 10;
  113. space^.elasticIterations := 10;
  114. // RU: Задаем силу гравитации.
  115. // EN: Set the gravity.
  116. space^.gravity := cpv(1, 100);
  117. // RU: Задаем коэффициент "затухания" движения объектов.
  118. // EN: Set the damping for moving of objects.
  119. space^.damping := 0.99;
  120. e := 1;
  121. u := 0.9;
  122. // RU: Создадим статичное "тело".
  123. // EN: Create a static "body".
  124. staticBody := cpBodyNew(INFINITY, INFINITY);
  125. // RU: Добавим три отрезка для ограничения мира. Первый параметр - указатель на созданное тело, два последующих - координаты точек отрезка, последний - толщина отрезка.
  126. // EN: Add three segments for restriction of world. First parameter - pointer of created body, next two - coordinates of segment points, the last one - width of segment.
  127. ground := cpSegmentShapeNew(staticBody, cpv(5, 0), cpv(5, 590), 1);
  128. ground^.e := e;
  129. ground^.u := u;
  130. cpSpaceAddStaticShape(space, ground );
  131. ground := cpSegmentShapeNew(staticBody, cpv(795, 0), cpv(795, 590), 1);
  132. ground^.e := e;
  133. ground^.u := u;
  134. cpSpaceAddStaticShape(space, ground);
  135. ground := cpSegmentShapeNew(staticBody, cpv(0, 590), cpv(800, 590), 1);
  136. ground^.e := e;
  137. ground^.u := u;
  138. cpSpaceAddStaticShape(space, ground);
  139. // RU: Добавим треугольник.
  140. // EN: Add the triangle.
  141. staticBody := cpBodyNew(INFINITY, INFINITY);
  142. ground := cpSegmentShapeNew(staticBody, cpv(400, 300), cpv(200, 350), 1);
  143. ground^.e := e;
  144. ground^.u := u;
  145. cpSpaceAddStaticShape(space, ground);
  146. ground := cpSegmentShapeNew(staticBody, cpv(200, 350), cpv(700, 350), 1);
  147. ground^.e := e;
  148. ground^.u := u;
  149. cpSpaceAddStaticShape(space, ground);
  150. ground := cpSegmentShapeNew(staticBody, cpv(700, 350), cpv(400, 300), 1);
  151. ground^.e := e;
  152. ground^.u := u;
  153. cpSpaceAddStaticShape(space, ground);
  154. end;
  155. procedure Draw;
  156. begin
  157. batch2d_Begin();
  158. // RU: Рендерим объекты указанного "мира". Второй аргумент функции отвечает за показ точек соприкосновения.
  159. // EN: Render objects for specified "world". Second argument responsible for rendering of collision points.
  160. cpDrawSpace(space, TRUE);
  161. text_Draw(fntMain, 10, 5, 'FPS: ' + u_IntToStr(zgl_Get(RENDER_FPS)));
  162. text_Draw(fntMain, 10, 25, 'Use your mouse: Left Click - box, Right Click - ball');
  163. batch2d_End();
  164. end;
  165. procedure KeyMouseEvent;
  166. begin
  167. // два варианта работы с мышью, статический и динамический
  168. if (mouseAction[M_BLEFT].state and is_down) > 0 Then
  169. cpAddBox(mouseX - 10, mouseY - 10, 48, 32, 1, 0.5, 0.5);
  170. if mouseBClick(M_BRIGHT) Then
  171. cpAddBall(mouseX, mouseY, 16, 2, 0.5, 0.1);
  172. end;
  173. procedure Phisics;
  174. begin
  175. cpSpaceStep(space, 1 / zgl_Get(RENDER_FPS));
  176. end;
  177. procedure Quit;
  178. begin
  179. // RU: Очистка объектов и "мира".
  180. // EN: Free objects and "world".
  181. cpSpaceFreeChildren(space);
  182. cpSpaceFree(space);
  183. end;
  184. Begin
  185. randomize();
  186. {$IFNDEF USE_ZENGL_STATIC}
  187. if not zglLoad( libZenGL ) Then exit;
  188. {$ENDIF}
  189. {$IFNDEF USE_CHIPMUNK_STATIC}
  190. if not cpLoad( libChipmunk ) Then exit;
  191. {$ENDIF}
  192. TimePhisics := timer_Add(@Phisics, 16, t_Start);
  193. zgl_Reg(SYS_EVENTS, @KeyMouseEvent);
  194. zgl_Reg(SYS_LOAD, @Init);
  195. zgl_Reg(SYS_DRAW, @Draw);
  196. zgl_Reg(SYS_EXIT, @Quit);
  197. wnd_SetCaption(utf8_Copy('16 - Physics Simple'));
  198. zgl_Init();
  199. End.