Advertisement
Guest User

Untitled

a guest
Dec 19th, 2014
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.42 KB | None | 0 0
  1. {
  2. "metadata": {
  3. "name": "",
  4. "signature": "sha256:cdd6cae9156d67533a7648ec148e62141e5c2f5838b6c107108fd2575c4568a9"
  5. },
  6. "nbformat": 3,
  7. "nbformat_minor": 0,
  8. "worksheets": [
  9. {
  10. "cells": [
  11. {
  12. "cell_type": "heading",
  13. "level": 1,
  14. "metadata": {},
  15. "source": [
  16. "[Volver al \u00edndice](localhost:8888/newtbooks/indexp.ipynb \"Volver al \u00edndice\") <hr>"
  17. ]
  18. },
  19. {
  20. "cell_type": "heading",
  21. "level": 2,
  22. "metadata": {},
  23. "source": [
  24. "Motor f\u00edsico"
  25. ]
  26. },
  27. {
  28. "cell_type": "markdown",
  29. "metadata": {},
  30. "source": [
  31. "El motor f\u00edsico constituye la primera parte del archivo ***apple.py***, en la que se definar\u00e1n aquella clases responsables de dirigir la f\u00edsica del juego. La segunda parte, hace referencia a las caracter\u00edsticas propias del m\u00f3vil (manzana) y del lanzador (tirachinas), a la cual se podr\u00e1 acceder m\u00e1s adelante."
  32. ]
  33. },
  34. {
  35. "cell_type": "markdown",
  36. "metadata": {},
  37. "source": [
  38. "El esquema general de esta parte del documento queda de la siguiente manera:\n",
  39. "* **Funci\u00f3n collide_relative_widgets**: Interviene en el comportamiento de la colisi\u00f3n de dos widgets. Utilizado en la colisi\u00f3n entre manzana y objetivo.\n",
  40. "* **Clase PhysicsEngine**: Motor f\u00edsico principal. Contiene el comportamiento ideal.\n",
  41. "* **Clase LinearFrictionPhysicsEngine**: Hereda de PhysicsEngine. Contiene la informaci\u00f3n necesaria para el comportamiento con rozamiento lineal.\n",
  42. "* **Clase PhysicsAdapter**: Adapta la informaci\u00f3n gr\u00e1fica a partir de la informaci\u00f3n proporcionada por el motor f\u00edsico."
  43. ]
  44. },
  45. {
  46. "cell_type": "markdown",
  47. "metadata": {},
  48. "source": [
  49. "La librer\u00eda math nos proporcionar\u00e1 aquellas herramientas num\u00e9ricas necesarias para realizar los c\u00e1lculos f\u00edsicos."
  50. ]
  51. },
  52. {
  53. "cell_type": "code",
  54. "collapsed": false,
  55. "input": [
  56. "from math import sqrt, cos, sin, pi, exp"
  57. ],
  58. "language": "python",
  59. "metadata": {},
  60. "outputs": [],
  61. "prompt_number": 2
  62. },
  63. {
  64. "cell_type": "markdown",
  65. "metadata": {},
  66. "source": [
  67. "A continuaci\u00f3n importamos una s\u00e9rie de m\u00f3dulos pertenecientes a la librer\u00eda kivy, cuya utilidad quedar\u00e1 reflejada posteriormente. Sin embargo, podriamos introducir su uso en el programa como:\n",
  68. "\n",
  69. "* **Animation**: Control del cambio de opacidad de las manzanas.\n",
  70. "* **Clock**: Control de los int\u00e9rvalos delta de tiempo, lo que implica actualizaci\u00f3n de las variables din\u00e1micas de la manzana.\n",
  71. "* **RelativeLayout**: Herramientas \n",
  72. "* **Vector**: Control de las variables f\u00edsicas mediante vectores."
  73. ]
  74. },
  75. {
  76. "cell_type": "code",
  77. "collapsed": false,
  78. "input": [
  79. "from kivy.animation import Animation\n",
  80. "from kivy.clock import Clock\n",
  81. "from kivy.uix.relativelayout import RelativeLayout\n",
  82. "from kivy.vector import Vector"
  83. ],
  84. "language": "python",
  85. "metadata": {},
  86. "outputs": []
  87. },
  88. {
  89. "cell_type": "markdown",
  90. "metadata": {},
  91. "source": [
  92. "Finalmente importamos las herramientas definidas en ***common.py***, explicadas anteriormente."
  93. ]
  94. },
  95. {
  96. "cell_type": "code",
  97. "collapsed": false,
  98. "input": [
  99. "from common import config, FixedSizeImage, make_sized_image, LineWidget, LinePointsWidget"
  100. ],
  101. "language": "python",
  102. "metadata": {},
  103. "outputs": []
  104. },
  105. {
  106. "cell_type": "markdown",
  107. "metadata": {},
  108. "source": [
  109. " "
  110. ]
  111. },
  112. {
  113. "cell_type": "markdown",
  114. "metadata": {},
  115. "source": [
  116. "Tras importar lo necesario, pasaremos a definir la primera funci\u00f3n, **collide_relative_widgets**. El prop\u00f3sito principal de esta funci\u00f3n es "
  117. ]
  118. },
  119. {
  120. "cell_type": "code",
  121. "collapsed": false,
  122. "input": [
  123. "def collide_relative_widgets(w1, w2):\n",
  124. " w1x, w1y = w1.to_window(w1.x, w1.y)\n",
  125. " w2x, w2y = w2.to_window(w2.x, w2.y)\n",
  126. "\n",
  127. " if w1x + w1.width < w2x:\n",
  128. " return None\n",
  129. " if w1x > w2x + w2.width:\n",
  130. " return None\n",
  131. " if w1x + w1.height < w2y:\n",
  132. " return None\n",
  133. " if w1y > w2y + w2.height:\n",
  134. " return None\n",
  135. "\n",
  136. " left_right = 0\n",
  137. " if w1x < w2x:\n",
  138. " left_right = -1\n",
  139. " elif w1x + w1.width > w2x + w2.width:\n",
  140. " left_right = 1\n",
  141. "\n",
  142. " top_bottom = 0\n",
  143. " if w1y < w2y:\n",
  144. " top_bottom = -1\n",
  145. " elif w1y + w1.height > w2y + w2.height:\n",
  146. " top_bottom = 1\n",
  147. "\n",
  148. " return (left_right, top_bottom)"
  149. ],
  150. "language": "python",
  151. "metadata": {},
  152. "outputs": []
  153. },
  154. {
  155. "cell_type": "markdown",
  156. "metadata": {},
  157. "source": [
  158. "Pasamos a continuaci\u00f3n a definir la clase principal, **PhysicsEngine**, que funcionar\u00e1 como motor f\u00edsico principal del juego. Para ello llamamos inicialmente a @config para obtener los datos ofrecidos por el usuario en **settings.ini**, ofreci\u00e9ndole al programa los valores por omisi\u00f3n en el caso de que esta informaci\u00f3n no se encuentre en el archivo. Las variables presentes son explicadas con mayor detenimiento en el apartado **Configuraci\u00f3n** del \u00edndice."
  159. ]
  160. },
  161. {
  162. "cell_type": "code",
  163. "collapsed": false,
  164. "input": [
  165. "@config(\n",
  166. " mass = 1,\n",
  167. " k = 80,\n",
  168. " g = 500,\n",
  169. " damping_factor_facing = 0.1,\n",
  170. " damping_factor_side = 0.3\n",
  171. ")"
  172. ],
  173. "language": "python",
  174. "metadata": {},
  175. "outputs": []
  176. },
  177. {
  178. "cell_type": "markdown",
  179. "metadata": {},
  180. "source": [
  181. " "
  182. ]
  183. },
  184. {
  185. "cell_type": "markdown",
  186. "metadata": {},
  187. "source": [
  188. "Pasando a la definici\u00f3n directa de la clase, encontramos inicialmente el m\u00e9todo __init__, el cual inicializa la clase tomando los valores indicados en la configuraci\u00f3n mediante el m\u00e9todo copy_config(), que proporciona\u00a0@config.\n",
  189. "\n",
  190. "Seguidamente encontramos aquellos m\u00e9todos que realizan los c\u00f3mputos del movimiento arm\u00f3nico simple explicados en el apartado **Conceptos f\u00edsicos** del \u00edndice. Esta encapsulaci\u00f3n tiene el car\u00e1cter de favorecer la claredad del c\u00f3digo y devolver la posici\u00f3n y velocidad del m\u00f3vil en cada instante.\n",
  191. "\n",
  192. "Los c\u00e1lculos generales del el\u00e1stico se reunen en el m\u00e9todo compute_launch, que toma como par\u00e1metros la posici\u00f3n de equilibrio del el\u00e1stico (balance), la posici\u00f3n desde la que se ha agarrado a la manzana (grab) y la posici\u00f3n desde la que se ha soltado esta (release).\n",
  193. "\n",
  194. "Aprovechamos los m\u00e9todos definidos para calcular el tiempo que dura el movimiento arm\u00f3nico, la posici\u00f3n en la que se encontrar\u00e1 la manzana al separarse del el\u00e1stico (y por tanto iniciar el movimiento parab\u00f3lico), y la velocidad a la que sale esta del el\u00e1stico (que tomar\u00e1 el papel de velocidad inicial en el tiro parab\u00f3lico).\n",
  195. "\n",
  196. "Tras el movimiento el\u00e1stico pasamos a desarrollar los m\u00e9todos encargados del c\u00e1lculo de la posici\u00f3n y la velocidad en el movimiento parab\u00f3lico ideal en funci\u00f3n del tiempo. Esta encapsulaci\u00f3n nos permetir\u00e1 a\u00f1adir posteriormente una clase encargada de controlar el movimiento con rozamiento lineal sustituyendo peque\u00f1as porciones de c\u00f3digo por las ecuaciones correspondientes. Los m\u00e9todos permiten pasar como argumentos los valores iniciales de la posici\u00f3n y la velocidad, o en el caso de no hacerlo, coge por defecto los valores finales del movimiento el\u00e1stico."
  197. ]
  198. },
  199. {
  200. "cell_type": "code",
  201. "collapsed": false,
  202. "input": [
  203. "class PhysicsEngine:\n",
  204. " def __init__(self):\n",
  205. " self.copy_config()\n",
  206. "\n",
  207. " def compute_launch(self, balance, grab, release):\n",
  208. " self.balance = balance\n",
  209. "\n",
  210. " self.d = grab - release # vector: release point ---> grab point\n",
  211. " self.mu = sqrt(self.k/self.mass)\n",
  212. "\n",
  213. " self.slinky_end_time = self.compute_slinky_end_time()\n",
  214. " self.slinky_end_pos = self.slinky(self.slinky_end_time)\n",
  215. " self.slinky_end_velocity = self.slinky_velocity(self.slinky_end_time)\n",
  216. "\n",
  217. " def compute_slinky_end_time(self):\n",
  218. " return pi/(2*self.mu)\n",
  219. "\n",
  220. " def slinky(self, t):\n",
  221. " balance, d, mu = self.balance, self.d, self.mu\n",
  222. " return balance - d * cos(mu*t)\n",
  223. "\n",
  224. " def slinky_velocity(self, t):\n",
  225. " d, mu = self.d, self.mu\n",
  226. " return d * mu * sin(mu*t)\n",
  227. "\n",
  228. " def parabolic(self, t, p0=None, v0=None):\n",
  229. " p0 = p0 or self.slinky_end_pos\n",
  230. " v0 = v0 or self.slinky_end_velocity\n",
  231. "\n",
  232. " x = p0.x + v0.x*t\n",
  233. " y = p0.y + v0.y*t - self.g*t*t/2\n",
  234. "\n",
  235. " return (x,y)\n",
  236. "\n",
  237. " def parabolic_velocity(self, t, v0):\n",
  238. " v0x, v0y = v0 or self.slinky_end_velocity\n",
  239. "\n",
  240. " return Vector(v0x, v0y - self.g*t)\n",
  241. "\n",
  242. " def collision_bounce_velocity(self, t, v0, collision):\n",
  243. " v = self.parabolic_velocity(t, v0)\n",
  244. "\n",
  245. " for i in [1,0]:\n",
  246. " if collision[i]*v[i] < 0:\n",
  247. " v[i] *= -self.damping_factor_facing\n",
  248. " v[1-i] *= self.damping_factor_side\n",
  249. " break\n",
  250. " else:\n",
  251. " v *= self.damping_factor_side\n",
  252. "\n",
  253. " return v"
  254. ],
  255. "language": "python",
  256. "metadata": {},
  257. "outputs": []
  258. },
  259. {
  260. "cell_type": "markdown",
  261. "metadata": {},
  262. "source": [
  263. " "
  264. ]
  265. },
  266. {
  267. "cell_type": "markdown",
  268. "metadata": {},
  269. "source": [
  270. "A continuaci\u00f3n encontramos la clase encargada de dirigir el movimiento parab\u00f3lico con fricci\u00f3n. Esta hereda del motor principal, **PhysicsEngine**, cargando su constructor junto a los valores ofrecidos en @config. La encapsulaci\u00f3n ofrecida en el padre permite que esta clase pueda ser definida como una modificaci\u00f3n del contenido de los m\u00e9todos que calculan la posici\u00f3n y la velocidad, aplicando en este caso las expresiones deducidad en el apartado **F\u00edsica** del \u00edndice."
  271. ]
  272. },
  273. {
  274. "cell_type": "code",
  275. "collapsed": false,
  276. "input": [
  277. "@config(b = 0.03)\n",
  278. "class LinearFrictionPhysicsEngine(PhysicsEngine):\n",
  279. " def __init__(self):\n",
  280. " PhysicsEngine.__init__(self)\n",
  281. " self.copy_config()\n",
  282. "\n",
  283. " def parabolic(self, t, p0=None, v0=None):\n",
  284. " p0 = p0 or self.slinky_end_pos\n",
  285. " v0 = v0 or self.slinky_end_velocity\n",
  286. "\n",
  287. " g, b = self.g, self.b\n",
  288. "\n",
  289. " x = p0.x + v0.x/b * (1-exp(-b*t))\n",
  290. " y = p0.y - g/b * t + 1/b * (g/b + v0.y)*(1-exp(-b*t))\n",
  291. "\n",
  292. " return (x,y)\n",
  293. "\n",
  294. " def parabolic_velocity(self, t, v0):\n",
  295. " v0x, v0y = v0 or self.slinky_end_velocity\n",
  296. " g, b = self.g, self.b\n",
  297. "\n",
  298. " vx = v0.x * exp(-b*t)\n",
  299. " vy = (g/b + v0.y) * exp(-b*t) - g/b\n",
  300. " return Vector(vx, vy)"
  301. ],
  302. "language": "python",
  303. "metadata": {},
  304. "outputs": []
  305. },
  306. {
  307. "cell_type": "code",
  308. "collapsed": false,
  309. "input": [],
  310. "language": "python",
  311. "metadata": {},
  312. "outputs": []
  313. }
  314. ],
  315. "metadata": {}
  316. }
  317. ]
  318. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement