document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. --# Main
  2. -- Bouncing Demos by Ignatz
  3.  
  4. --These demos show how to bounce a ball round the screen, from very simple to using the physics engine
  5. --You can use them as templates for your own projects
  6. --Just run this, and press the buttons at upper left to see the various demos
  7. --Simple = Demo_1
  8. --Friction = Demo_2
  9. --Physics = Demo_3
  10. --Physics rotation = Demo_4
  11.  
  12. --How to use the demos in your own projects
  13. --Each demo tab is completely self contained, but is set up as a class to make managing all of them easier.
  14. --To change any of them from a class to a main program, copy the code from the tab you want, into an
  15. --empty project and remove the first line saying Bounce_X =class()
  16. --remove the class prefixes in front of all the function names, so everywhere you (say) see
  17. --Bounce_2:somefunction(), change it to somefunction()
  18. --However, if you do want to use the demos in a class the way they are, you should probably prefix all
  19. --the variables with self. so they aren't global variables.
  20.  
  21. --The code below manages all the demos and isn't part of them.
  22.  
  23. function setup()
  24. choices={"Simple","Friction","Physics","Physics Rotation"}
  25. classes={Bounce_1(),Bounce_2(),Bounce_3(),Bounce_4()}
  26. callbacks={bounce1}
  27. for i=1,#choices do
  28. parameter.action(choices[i],function(n) Select(n) end)
  29. end
  30. currSel=""
  31. Select("Simple")
  32. end
  33.  
  34. function draw()
  35. b:draw()
  36. end
  37.  
  38. --this function changes between demos, setting up the new choice
  39. function Select(btn)
  40. if string.find(currSel,"Physics")~=nil then b:cleanup() end
  41. --setup new choice
  42. for i=1,#choices do
  43. if btn==choices[i] then
  44. b=classes[i]
  45. b:setup()
  46. currSel=btn
  47. return
  48. end
  49. end
  50. end
  51.  
  52. --this function only applies to demos which use physics
  53. --it tells the demo which objects collided
  54. function collide(contact)
  55. b:collide(contact)
  56. end
  57. --# Bounce_1
  58. Bounce_1=class()
  59. --[[
  60. A simple bouncing object
  61.  
  62. The code below makes a red ball and/or an image bounce around the walls endlessly.
  63. It isn't difficult to do, as long as you change direction when you get close to a wall
  64.  
  65. You will see an image and a red ball bouncing together when you run this. They have
  66. been included to show you how to do both types. Just delete the one you don't want
  67. (the code is all marked to help you).
  68. --]]
  69.  
  70. function Bounce_1:setup()
  71. x=200 --starting x
  72. y=250 --starting y
  73.  
  74. dx=3 --the amount x changes
  75. dy=2 --the amount y changes
  76.  
  77. --if you want to draw a ball, use this ---------
  78. d=60 --diameter of ball
  79.  
  80. --if you prefer to use an image, use this instead--------
  81. --change the image by pressing on the name in brackets (try to pick a roughly circular one)
  82. img=readImage("Tyrian Remastered:Mine Spiked Huge")
  83. d=(img.width+img.height)/2 --use average of width and height as diameter
  84.  
  85. output.clear()
  86. print("This is a simple bouncing demo")
  87. print("a ball and an image bounce forever")
  88. print("These are the two main things you will use for bouncing")
  89. print("They bounce together just to keep the code very simple for you to follow")
  90. end
  91.  
  92. function Bounce_1:draw()
  93. --update x and y positions
  94. x=x+dx
  95. y=y+dy
  96. --set up screen and color
  97. background(200,200,200,255)
  98.  
  99. --this chunk draws the ball --
  100. pushStyle() --see comment at very bottom
  101. fill(255,0,0,255)
  102. ellipse(x,y,d)
  103. popStyle()
  104. -------------------------------
  105.  
  106. --this chunk draws an image ---
  107. sprite(img,x,y)
  108. -------------------------------
  109.  
  110. --change direction if we hit a wall
  111. r=d/2 --how close the centre of the ball can get to a wall before bouncing
  112. if x>WIDTH-r or x<r then dx=-dx end --reverse x direction if we hit left or right wall
  113. if y>HEIGHT-r or y<r then dy=-dy end --reverse y direction if we hit top or bottom wall
  114. end
  115.  
  116. -- pushStyle and popStyle --
  117. -- in some programming, we plonk an object on the screen, then start setting colour etc
  118. -- However, because Codea is refreshing the screen 60 times a second, nothing on the screen is permanent,
  119. -- and everything is just a drawing.
  120. -- Actually, it's more like real life. If you paint, you select a brush and mix a palette, and then you
  121. -- paint on the canvas. No matter what you paint, your brush size and your colours will stay the same
  122. -- until you change them.
  123. -- Codea works like this too. You set the colour, brush size, whatever, then you draw on the screen. Those
  124. -- settings will stay there for the next thing you draw.
  125. -- Which can make a mess! So Codea provides pushStyle, which stores current settings safely, and popStyle,
  126. -- whch brings them back when you're done messing around, so you don't mess things up for anything else
  127. -- you're drawing. So whenever changing colours, styles, etc, wrap your changes between pushStyle and
  128. -- popStyle.
  129.  
  130.  
  131.  
  132.  
  133. --# Bounce_2
  134. Bounce_2=class()
  135. --[[
  136. A simple bouncing object that slows down
  137.  
  138. The code below makes a red ball and/or an image bounce around the walls, slowing down with friction and
  139. the effect of impacts.
  140.  
  141. Bouncing isn't difficult to do, as long as you change direction when you get close to a wall. Friction
  142. and impacts require trial and error to get them looking realistic, and you can get your object stuck in
  143. a wall if you aren't careful. If objects collide it starts getting hard.
  144.  
  145. You will see an image and a red ball bouncing together when you run this. Just delete the
  146. one you don't want (the code is all marked to help you).
  147. --]]
  148.  
  149. function Bounce_2:setup()
  150. x=200 --starting x
  151. y=250 --starting y
  152.  
  153. dx=3 --the amount x changes
  154. dy=2 --the amount y changes
  155.  
  156. impact=0.9 --speed is multiplied by this on impact
  157. friction=0.999 --speed is multiplied by this on each draw
  158. stop=2 --stop if speed is below this level, so it doesn't go on forever getting tinier
  159.  
  160. --if you want to draw a ball, use this ---------
  161. d=60 --diameter of ball
  162.  
  163. --if you prefer to use an image, use this instead--------
  164. --change the image by pressing on the name in brackets (try to pick a roughly circular one)
  165. img=readImage("Tyrian Remastered:Mine Spiked Huge")
  166. d=(img.width+img.height)/2 --use average of width and height as diameter
  167.  
  168. output.clear()
  169. print("The ball and image slow down and stop, due to impacts and friction. At this stage, we are managing all of this ourselves.")
  170. end
  171.  
  172. function Bounce_2:draw()
  173. --update x and y positions and speed
  174. dx=dx*friction
  175. dy=dy*friction
  176. if math.abs(dx)+math.abs(dy)<stop then dx=0 dy=0 end
  177. x=x+dx
  178. y=y+dy
  179. --set up screen and color
  180. background(200,200,200,255)
  181.  
  182. --this chunk draws the ball --
  183. pushStyle() --see comment at foot of Bounce_1
  184. fill(255,0,0,255)
  185. ellipse(x,y,d)
  186. popStyle()
  187. -------------------------------
  188.  
  189. --this chunk draws an image ---
  190. sprite(img,x,y)
  191. -------------------------------
  192.  
  193. --change direction if we hit a wall
  194. r=d/2 --how close the centre of the ball can get to a wall before bouncing
  195. --check for impact, if so, adjust speed for impact and reverse direction
  196. if x>WIDTH-r or x<r then dx=-dx*impact dy=dy*impact end --reverse x direction if we hit left or right wall
  197. if y>HEIGHT-r or y<r then dx=dx*impact dy=-dy*impact end --reverse y direction if we hit top or bottom wall
  198. end
  199. --# Bounce_3
  200. Bounce_3=class()
  201. --[[
  202. Bouncing with physics
  203.  
  204. The code below makes a red ball and an image bounce around the walls, using the Codea physics engine.
  205. Some of the code is adapted from an example by Dalorbi.
  206. --]]
  207.  
  208. function Bounce_3:setup()
  209. --create objects
  210. --we'll create a table of them simply to make it easy to destroy them later (see cleanup function at bottom)
  211. --They are unlike circles and images, which only exist if you draw them - instead, physics objects stay
  212. --alive until you actually destroy them, and they will interact with other physics objects
  213. --The added problem is they are invisible, so if you leave any lying around without something
  214. --visible attached, you're likely to collide with them
  215. bodies={}
  216. --first the ball
  217. ball_diam=60 --diameter of ball
  218. --now create the physics object that behaves like a real ball, it will tell us where to draw our ball
  219. --think of it as a GPS navigator that guides us
  220. p_ball = physics.body(CIRCLE,ball_diam/2) --physics bodies use radius not diameter
  221. p_ball.x = math.random(60,250) -- choose a random position between 30 and the screen width minus 30
  222. p_ball.y = math.random(60,250) -- same for the y position
  223. p_ball.gravityScale = 0 -- no gravity - if there was, the ball would fall to the bottom of screen
  224. p_ball.restitution = 1 -- this circle is bouncy
  225. p_ball.friction = 0.1 -- the amount of friction to be applied to the circle
  226. p_ball.linearVelocity = vec2(math.random(400),math.random(400)) --velocity (pixels per second = 60 redraws)
  227. p_ball.info="ball" --so when collisions occur, we can figure out which object was involved
  228. table.insert(bodies,p_ball) --keep track of body so we can destroy it later if we want
  229.  
  230. --now much the same for the image
  231. img=readImage("Tyrian Remastered:Mine Spiked Huge")
  232. img_diam=(img.width+img.height)/2 --use average of width and height as diameter
  233. --create the physics object
  234. p_img = physics.body(CIRCLE,img_diam/2) --physics bodies use radius not diameter
  235. p_img.x = math.random(60,250) -- choose a random position
  236. p_img.y = math.random(60,250) -- same for the y position
  237. p_img.gravityScale = 0 -- no gravity
  238. p_img.restitution = 0.8 -- this image is not so bouncy
  239. p_img.friction = 0.4 -- the amount of friction to be applied to the image
  240. p_img.linearVelocity = vec2(math.random(400),math.random(400)) -- velocity
  241. p_img.info="mine" --so when collisions occur, we can figure out which object was involved
  242. table.insert(bodies,p_img) --keep track of body so we can destroy it later if we want
  243.  
  244. --finally the walls
  245. Bounce_3:CreateWalls()
  246.  
  247. output.clear()
  248. print("The physics engine handles friction, bouncing and collisions")
  249. end
  250.  
  251. --create the walls - physics objects can only bounce off each other
  252. --the first four parameters are the starting x,y and ending x,y
  253. --the fifth parameter is restitution, or bounciness, from 0=no bounce to 1=very bouncy
  254. function Bounce_3:CreateWalls()
  255. leftWall = Bounce_3:CreateWall(1,1,1,HEIGHT-1,1.0)
  256. rightWall = Bounce_3:CreateWall(WIDTH-1,0,WIDTH-1,HEIGHT-1,0.9)
  257. bottomWall = Bounce_3:CreateWall(1,1,WIDTH-1,1,0.2)
  258. topWall = Bounce_3:CreateWall(1,HEIGHT-1,WIDTH-1,HEIGHT-1,0.7)
  259. end
  260. --this function creates one wall (actually just a line)
  261. function Bounce_3:CreateWall(x,y,x1,y1,r)
  262. local w = physics.body(EDGE,vec2(x,y),vec2(x1,y1)) -- vec2
  263. w.restitution=r --see comment above
  264. table.insert(bodies,w) --keep track of body so we can destroy it later if we want
  265. return w
  266. end
  267.  
  268. function Bounce_3:draw()
  269. background(200,200,200,255)
  270.  
  271. --draw the ball --
  272. pushStyle() --see comment at foot of Bounce_1
  273. fill(255,0,0,255)
  274. ellipse(p_ball.x,p_ball.y,ball_diam)
  275. popStyle()
  276. -------------------------------
  277.  
  278. --draw image ---
  279. sprite(img,p_img.x,p_img.y)
  280. -------------------------------
  281.  
  282. end
  283.  
  284. --the function to be called when two physics bodies collide
  285. --we are told which bodies (including walls etc) have collided
  286. --contactA and contactB are the two bodies
  287. function Bounce_3:collide(contact)
  288. if contact.state == BEGAN then
  289. if contact.bodyA.info=="ball" or contact.bodyB.info=="ball" then sound(SOUND_JUMP, 50) end
  290. if contact.bodyA.info=="mine" or contact.bodyB.info=="mine" then sound(SOUND_EXPLODE, 50) end
  291. end
  292. end
  293.  
  294. --destroy all bodies when we are done, we have to keep track of the, ourselves, hence the table
  295. function Bounce_3:cleanup()
  296. for i,bb in ipairs(bodies) do
  297. bb:destroy()
  298. end
  299. end
  300.  
  301. --# Bounce_4
  302. Bounce_4=class()
  303.  
  304. --[[
  305. Bouncing - and rotating - with physics
  306.  
  307. The code below makes a red rectangle and an image bounce around the walls, using the Codea physics engine.
  308. Both of them rotate as they bounce.
  309.  
  310.  
  311. --]]
  312.  
  313. function Bounce_4:setup()
  314. --create objects
  315. --we'll create a table of them simply to make it easy to destroy them later (see cleanup function at bottom)
  316. --They are unlike circles and images, which only exist if you draw them - instead, physics objects stay
  317. --alive until you actually destroy them, and they will interact with other physics objects
  318. --The added problem is they are invisible, so if you leave any lying around without something
  319. --visible attached, you're likely to collide with them
  320. bodies={}
  321. --first the rectangle
  322. rect_width=100 --size of rectangle
  323. rect_height=50
  324. --now create the physics object that behaves like a real block, it will tell us where to draw our rectangle
  325. --think of it as a GPS navigator that guides us
  326. p_rect = physics.body(POLYGON,
  327. vec2(-rect_width / 2, -rect_height / 2),
  328. vec2(-rect_width / 2, rect_height / 2),
  329. vec2(rect_width / 2, rect_height / 2),
  330. vec2(rect_width / 2, -rect_height / 2)
  331. )
  332. p_rect.x = math.random(60,250) -- choose a random position between 30 and the screen width minus 30
  333. p_rect.y = math.random(60,250) -- same for the y position
  334. p_rect.angle=math.random(0,360) -- and rotation
  335. p_rect.gravityScale = 0 -- no gravity - if there was, the ball would fall to the bottom of screen
  336. p_rect.restitution = 1 -- this circle is bouncy
  337. p_rect.friction = 0.1 -- the amount of friction to be applied to the circle
  338. p_rect.linearVelocity = vec2(100+math.random(400),100+math.random(400)) --velocity (pixels per second = 60 redraws)
  339. table.insert(bodies,p_rect)
  340. --p_rect.linearDamping = 0.2
  341. --p_rect.angularDamping = 0.2
  342.  
  343. p_rect.info="rect" --so when collisions occur, we can figure out which object was involved
  344.  
  345. --now much the same for the image
  346. img=readImage("Tyrian Remastered:Mine Spiked Huge")
  347. img_diam=(img.width+img.height)/2 --use average of width and height as diameter
  348. --create the physics object
  349. p_img = physics.body(CIRCLE,img_diam/2) --physics bodies use radius not diameter
  350. p_img.x = math.random(60,250) -- choose a random position
  351. p_img.y = math.random(60,250) -- same for the y position
  352. p_img.angle=math.random(0,360)
  353. p_img.gravityScale = 0 -- no gravity
  354. p_img.restitution = 0.8 -- this image is not so bouncy
  355. p_img.friction = 0.4 -- the amount of friction to be applied to the image
  356. p_img.linearVelocity = vec2(math.random(400),math.random(400)) -- velocity
  357. p_img.info="mine" --so when collisions occur, we can figure out which object was involved
  358. table.insert(bodies,p_img)
  359. --p_img.linearDamping = 0.9
  360. --p_img.angularDamping = 0.9
  361.  
  362. --finally the walls
  363. Bounce_4:CreateWalls()
  364.  
  365. output.clear()
  366. print("Watch how the rectangle and")
  367. print("image rotate as they bounce")
  368. end
  369.  
  370. --create the walls - physics objects can only bounce off each other
  371. --the first four parameters are the starting x,y and ending x,y
  372. --the fifth parameter is restitution, or bounciness, from 0=no bounce to 1=very bouncy
  373. function Bounce_4:CreateWalls()
  374. leftWall = Bounce_3:CreateWall(1,1,1,HEIGHT-1,1.0)
  375. rightWall = Bounce_3:CreateWall(WIDTH-1,0,WIDTH-1,HEIGHT-1,0.9)
  376. bottomWall = Bounce_3:CreateWall(1,1,WIDTH-1,1,0.2)
  377. topWall = Bounce_3:CreateWall(1,HEIGHT-1,WIDTH-1,HEIGHT-1,0.7)
  378. end
  379. --this function creates one wall (actually just a line)
  380. function Bounce_4:CreateWall(x,y,x1,y1,r)
  381. local w = physics.body(EDGE,vec2(x,y),vec2(x1,y1)) -- vec2
  382. w.restitution=r --see comment above
  383. table.insert(bodies,w) --keep track of body so we can destroy it later if we want
  384. return w
  385. end
  386.  
  387. function Bounce_4:draw()
  388. background(200,200,200,255)
  389.  
  390. --draw the rectangle --
  391. pushStyle() --see comment at foot of Bounce_1
  392. fill(255,0,0,255)
  393. --see explanation of next few lines at bottom below
  394. pushMatrix()
  395. translate(p_rect.x, p_rect.y)
  396. rotate(p_rect.angle)
  397. rect(-rect_width / 2, -rect_height / 2, rect_width, rect_height)
  398. popMatrix()
  399. popStyle()
  400. -------------------------------
  401.  
  402. --draw image ---
  403. --see explanation of next few lines at bottom below
  404. pushMatrix()
  405. translate(p_img.x, p_img.y)
  406. rotate(p_img.angle)
  407. sprite(img,0,0)
  408. popMatrix()
  409. -------------------------------
  410.  
  411. end
  412.  
  413. --the function to be called when two physics bodies collide
  414. --we are told which bodies (including walls etc) have collided
  415. --contactA and contactB are the two bodies
  416. function Bounce_4:collide(contact)
  417. if contact.state == BEGAN then
  418. if contact.bodyA.info=="rect" or contact.bodyB.info=="rect" then sound(SOUND_JUMP, 50) end
  419. if contact.bodyA.info=="mine" or contact.bodyB.info=="mine" then sound(SOUND_EXPLODE, 50) end
  420. end
  421. end
  422.  
  423. function Bounce_4:cleanup()
  424. for i,bb in ipairs(bodies) do
  425. bb:destroy()
  426. end
  427. end
  428.  
  429. --Drawing rotating physics objects
  430. --Suppose you had to draw a little shape all over a piece of paper, at different angles
  431. --The hard way is to keep the paper as is, and start having to lean all oer the place to draw sideways over
  432. --her, and upside down over there
  433. --The sensible approach is to swivel and move the paper so that you can draw each shape the right way up,
  434. --right in front of you. And Codea finds that the best way, too. Let's look at an example from above.
  435. --[[
  436. pushMatrix() --before we go swivelling the paper, let's remember how it was, so we can put it back later
  437. translate(x, y) -- move the place we want draw under our pen, so that the point x,y is now treated as 0,0
  438. -- this means if you now draw at 40,30, Codea will actually draw at x+40,y+30
  439. rotate(p_rect.angle) --rotate our whole screen by whatever angle our physics object is at
  440. -- this is like turning your paper round so you can draw the image the right way up
  441. rect(-rect_width / 2, -rect_height / 2, rect_width, rect_height) --draw our rectangle
  442. --note it is drawn the right way up, but Codea has the screen at an angle, so the final
  443. --result will be an angled rectangle
  444. --note also the centre of the rectangle is at 0,0, because we've moved to the exact
  445. --spot where we want to draw it. So the first two parameters x and y are set to a
  446. --point half of the width to the left, and half of the height below.
  447. popMatrix() --put everything back the way it was
  448. --]]
');