Advertisement
1m1m0

Orbit 1.3.5 [Polygonal]

Mar 11th, 2024 (edited)
237
0
Never
3
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 34.89 KB | Software | 0 0
  1. -- | Orbit (Interactive Celestial Body Simulator Program) Complete Release v1.3.5 [5/24/2024], written by 1m1m0 & several AI models | --
  2.  
  3. local t = true -- Do not touch
  4. local f = false -- Do not touch
  5. local screenW = display.contentWidth -- Do not touch
  6. local screenH = display.contentHeight -- Do not touch
  7. -- (Quick Settings/Variables) --
  8. -- { Most configurations are syncronized with Polygons! }
  9. local scale = math.random(0.6, 1.2) -- Factor to propotionally resize objects, size and mass included
  10. local trailLifeTime = 1 -- How long a trail will last (seconds)
  11. local trailSize = 0.25 -- How wide trails will be proportional to their parent circle's radius
  12. local trailOpaqueness = 0.5 -- How see-through trails will be
  13. local trailGradient = 0 -- Determines if trails fade out or not
  14. local numRandomShapes = math.random(2, 100) -- Amount of circles can randomly spawn
  15. local circleMass = math.random(1, 12) -- Mass of circles while being randomized
  16. local polygonMass = math.random(1, 12) -- Mass of polygons while being randomized
  17. local radiusMax = 30 -- Maximum random radius of circles while being randomized
  18. local radiusMin = 30 -- Minimum random radius of circles while being randomized
  19. local polygonSides = math.random(3, 6) -- Side count of a polygon between a triangle to a circle [EXPERIMENTAL]
  20. local circleFriction = math.random(0.0, 1.0) -- Friction for circles
  21. local polygonFriction = math.random(0.0, 1.0) -- Friction for polygons
  22. local gravityStrength = 9.81 -- Dictates the gravitational strength (not forces) of the simulation
  23. local throwAmplifier = 0.075 -- Factor in which how fast an object will be after throwing or flicking it
  24. local velocityRate = 5 -- Time (seconds) to calculate the velocity of the circle while thrown (pix/s)
  25. local dampingAmplifier = 0.25 -- Factor to simulate drag or air resistance (set to 0 for cosmic simulations)
  26. local randomCirclesBounce = math.random(0.0, 0.5) -- Elasticity of the Randomized Circles
  27. local randomPolygonsBounce = math.random(0.0, 0.5) -- Elasticity of the Randomized Polygons
  28. local wrapBuffer = 0.5 -- Time in seconds to ensure the circle is fully off-screen to wrap around the screen
  29. local startingXpos = screenW/2 -- Center of screen (Applies to Polygons and Circles)
  30. local startingYpos = screenH/2
  31. local musicVolume = 0.3 -- Volume of background music
  32. -- Color Configs --
  33. local red = math.random() -- Amount of red for random circles/polygons
  34. local green = math.random() -- Amount of green for random circles/polygons
  35. local blue = math.random() -- Amount of blue for random circles/polygons
  36. -- (Togglables) --
  37. local toggleMusic = t -- Toggle to turn background music on or off, music is chosen from the creator's favorite playlist :)
  38. local toggleDebugMode = f -- Toggle to view the simulation in debugging mode, usually to monitor the physics of polygons and circles [Master Switch]
  39. local toggleMonochrome = t -- Toggle to generate random shapes with the same random color (Applies to random circles/polygons) [Master Switch]
  40. local toggleCircles = t -- Toggle the generation of circles [Master Switch]
  41. local togglePolygons = f -- Toggle the generation of polygons (Will have the same configurations to Random Circles!) [Master Switch]
  42. local toggleWalls = t -- Toggle to have bounderies to the simulation
  43. local toggleTopWall = t -- Toggle to add or remove the top wall
  44. local toggleRightWall = f -- Toggle to add or remove the right wall
  45. local toggleBottomWall = t -- Toggle to add or remove the bottom wall
  46. local toggleLeftWall = f -- Toggle to add or remove the left wall
  47. local toggleBodyWrap = t -- Toggle teleporting objects across the screen when crossing the walls
  48. local toggleStartingCircle = t -- Toggle to spawn a starting circle
  49. local toggleCustomCircles = f -- Toggle to spawn more starting circles which can be changed in 'local customCircles = 4'
  50. local toggleRandomCircles = t -- Toggle randomized circles
  51. local toggleStartingPolygon = t -- Same concept as toggleStartingCircle
  52. local toggleCustomPolygons = f -- Same concept as toggleCustomCircles
  53. local toggleRandomPolygons = t -- Same concept as toggleRandomCircles
  54. local toggleTrails = f -- Toggle trails on/off (Greatly affect performance)
  55. local toggleForces = t -- Toggle gravitational forces on the circles
  56. local toggleReversedForces = f -- Toggle negative gravity or repelling forces
  57. local toggleGravity = f -- Toggle gravity of the simulation
  58. -- (Starting Circle quick settings) --
  59. local customCircles = 1 -- Number of custom starting circles to spawn
  60. local startingCircleBounce = 0.25 -- Elasticity of the circle
  61. local startingCircleFriction = 0.5 -- Friction of the circle
  62. local startingCircleRadius = 50 -- Size of circle
  63. local startingCircleMass = 500 -- Mass of circle
  64. local startingColorR = 255 -- Red value (Maximum 255)
  65. local startingColorG = 255 -- Green value (Maximum 255)
  66. local startingColorB = 255 -- Blue value (Maximum 255)
  67. -- (Starting Polygon quick settings) --
  68. local customPolygons = 1 -- Number of custom starting polygons to spawn
  69. local startingPolygonSides = math.random(3, 6) -- Number of sides for the starting polygon
  70. local startingPolygonBounce = 0.3 -- Elasticity of the polygon
  71. local startingPolygonFriction = 0.5 -- Friction of the polygon
  72. local startingPolygonRadius = 80 -- Size of polygon
  73. local startingPolygonMass = 400 -- Mass of polygon
  74. local startingPolygonColorR = 255 -- Red value (Maximum 255)
  75. local startingPolygonColorG = 255 -- Green value (Maximum 255)
  76. local startingPolygonColorB = 255 -- Blue value (Maximum 255)
  77.  
  78.     ----> | Main Program | <----
  79.  
  80. -- Initialize physics
  81. local physics = require("physics")
  82. physics.start()
  83. if toggleGravity then
  84.     physics.setGravity(0, gravityStrength)
  85. else
  86.     physics.setGravity(0, 0) -- Set gravity to 0 if toggleGravity is false
  87. end
  88. if toggleDebugMode then
  89.     physics.setDrawMode("hybrid")
  90. else if toggleDebugMode == f then
  91.     physics.setDrawMode("normal")
  92. end
  93. end
  94.  
  95. local spheres = {} -- Table to keep track of spheres
  96.  
  97. -- [[ Starting Circle with fixed size & mass for experimentations
  98. local function createCircle(x, y, radius, mass, r, g, b)
  99.     local circle = display.newCircle(x, y, radius)
  100.     -- Prevent color errors
  101.     if startingColorR <= 0 or startingColorR >= 255 then
  102.         startingColorR = 1
  103.     elseif startingColorG <= 0 or startingColorG >= 255 then
  104.         startingColorG = 1
  105.     elseif startingColorB <= 0 or startingColorB >= 255 then
  106.         startingColorB = 1
  107.     end
  108.     circle:setFillColor(startingColorR, startingColorG, startingColorB)
  109.     physics.addBody(circle, {radius=radius, density=mass/(math.pi*radius*radius), bounce=startingCircleBounce, friction=startingCircleFriction})
  110.     circle.mass = mass
  111.     table.insert(spheres, circle)
  112.  
  113.     -- Combined function with improved throwing and double-click locking mechanism
  114.     function circle:touch(event)
  115.         if event.phase == "began" then
  116.             -- Initial touch
  117.             display.getCurrentStage():setFocus(self, event.id)
  118.             self.isFocus = true
  119.             self.markX = self.x
  120.             self.markY = self.y
  121.             self.startTime = system.getTimer()
  122.             self.movementHistory = {}
  123.             -- Stop the sphere's movement (only if not locked)
  124.             if not self.isLocked then
  125.                 self:setLinearVelocity(0, 0)
  126.                 self.angularVelocity = 0
  127.             end
  128.         elseif self.isFocus then
  129.             if event.phase == "moved" then
  130.                 -- Dragging (only if not locked)
  131.                 if not self.isLocked then
  132.                     self.x = event.x - event.xStart + self.markX
  133.                     self.y = event.y - event.yStart + self.markY
  134.                     -- Record movement history
  135.                     table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
  136.                     -- Clean up old movement history
  137.                     local currentTime = system.getTimer()
  138.                     local cutOffTime = currentTime - (velocityRate*1000)
  139.                     for i, record in ipairs(self.movementHistory) do
  140.                         if record.time < cutOffTime then
  141.                             table.remove(self.movementHistory, i)
  142.                         end
  143.                     end
  144.                 end
  145.             elseif event.phase == "ended" or event.phase == "cancelled" then
  146.                 if not self.isLocked then  -- Don't apply a throw if locked
  147.                     -- Released
  148.                     local endTime = system.getTimer()
  149.                     local distance = 0
  150.                     local throwForce = 0
  151.                     local timeDiff = 0
  152.                     if #self.movementHistory >= 2 then
  153.                         local lastRecord = self.movementHistory[#self.movementHistory]
  154.                         local prevRecord = self.movementHistory[#self.movementHistory - 1]
  155.                         distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
  156.                         timeDiff = lastRecord.time - prevRecord.time
  157.                         throwForce = distance * throwAmplifier / timeDiff
  158.                         -- Apply decay to the throw force to simulate energy loss
  159.                         throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
  160.                         local vx = (event.x - self.markX) * throwForce
  161.                         local vy = (event.y - self.markY) * throwForce
  162.                         self:applyLinearImpulse(vx, vy, self.x, self.y)
  163.                     end
  164.                 end
  165.                 display.getCurrentStage():setFocus(self, nil)
  166.                 self.isFocus = false
  167.             end
  168.         elseif event.phase == "ended" and not self.isFocus then
  169.             -- Detect double click
  170.             if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
  171.                 -- Double click detected within 300 milliseconds
  172.                 self.isLocked = not self.isLocked
  173.                 self.body:setType(self.isLocked and "static" or "dynamic")
  174.                 self.lastClickTime = nil
  175.             else
  176.                 -- Single click, start timer
  177.                 self.lastClickTime = system.getTimer()
  178.             end
  179.         end
  180.         return true
  181.     end
  182.    
  183.     circle:addEventListener("touch", circle)
  184.     return circle
  185. end
  186. --]]
  187. -- Function to spawn multiple starting circles
  188. local function spawnStartingCircles()
  189.     if customCircles <= 0 then -- Prevents negative starting circles
  190.         customCircles = 1
  191.     end
  192.     if startingCircleRadius <= 0 then -- Prevents negative radius
  193.         startingCircleRadius = 25
  194.     end
  195.     for i = 1, (customCircles) do
  196.         local xPosition = math.random(startingCircleRadius, display.actualContentWidth - startingCircleRadius)
  197.         local yPosition = math.random(startingCircleRadius, display.actualContentHeight - startingCircleRadius)
  198.         createCircle(xPosition, yPosition, startingCircleRadius, startingCircleMass)
  199.     end
  200. end
  201.  
  202. -- Function to create a polygon with a specified number of sides
  203. local function createStartingPolygon(x, y, radius, mass, sides, r, g, b)
  204.     sides = polygonSides
  205.     -- Calculate the vertices of the polygon
  206.     local vertices = {}
  207.     for i = 1, sides do
  208.         local angle = ((i - 1) / sides) * (2 * math.pi)
  209.         vertices[#vertices + 1] = radius * math.cos(angle)
  210.         vertices[#vertices + 1] = radius * math.sin(angle)
  211.     end
  212.     -- Create the polygon
  213.     local polygon = display.newPolygon(x, y, vertices)
  214.     -- Prevent color errors
  215.     if startingPolygonColorR <= 0 or startingPolygonColorR >= 255 then
  216.         startingPolygonColorR = 1
  217.     elseif startingPolygonColorG <= 0 or startingPolygonColorG >= 255 then
  218.         startingPolygonColorG = 1
  219.     elseif startingPolygonColorB <= 0 or startingPolygonColorB >= 255 then
  220.         startingPolygonColorB = 1
  221.     end
  222.     polygon:setFillColor(startingPolygonColorR, startingPolygonColorG, startingPolygonColorB)
  223.     physics.addBody(polygon, {shape=vertices, density=mass/(radius*radius*sides), bounce=startingPolygonBounce, friction=startingPolygonFriction})
  224.     polygon.mass = mass
  225.     table.insert(spheres, polygon)
  226.  
  227.     -- Touch event handling
  228.     function polygon:touch(event)
  229.         if event.phase == "began" then
  230.             -- Initial touch
  231.             display.getCurrentStage():setFocus(self, event.id)
  232.             self.isFocus = true
  233.             self.markX = self.x
  234.             self.markY = self.y
  235.             self.startTime = system.getTimer()
  236.             self.movementHistory = {}
  237.             -- Stop the polygon's movement (only if not locked)
  238.             if not self.isLocked then
  239.                 self:setLinearVelocity(0, 0)
  240.                 self.angularVelocity = 0
  241.             end
  242.         elseif self.isFocus then
  243.             if event.phase == "moved" then
  244.                 -- Dragging (only if not locked)
  245.                 if not self.isLocked then
  246.                     self.x = event.x - event.xStart + self.markX
  247.                     self.y = event.y - event.yStart + self.markY
  248.                     -- Record movement history
  249.                     table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
  250.                     -- Clean up old movement history
  251.                     local currentTime = system.getTimer()
  252.                     local cutOffTime = currentTime - (velocityRate*1000)
  253.                     for i, record in ipairs(self.movementHistory) do
  254.                         if record.time < cutOffTime then
  255.                             table.remove(self.movementHistory, i)
  256.                         end
  257.                     end
  258.                 end
  259.             elseif event.phase == "ended" or event.phase == "cancelled" then
  260.                 if not self.isLocked then  -- Don't apply a throw if locked
  261.                     -- Released
  262.                     local endTime = system.getTimer()
  263.                     local distance = 0
  264.                     local throwForce = 0
  265.                     local timeDiff = 0
  266.                     if #self.movementHistory >= 2 then
  267.                         local lastRecord = self.movementHistory[#self.movementHistory]
  268.                         local prevRecord = self.movementHistory[#self.movementHistory - 1]
  269.                         distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
  270.                         timeDiff = lastRecord.time - prevRecord.time
  271.                         throwForce = distance * throwAmplifier / timeDiff
  272.                         -- Apply decay to the throw force to simulate energy loss
  273.                         throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
  274.                         local vx = (event.x - self.markX) * throwForce
  275.                         local vy = (event.y - self.markY) * throwForce
  276.                         self:applyLinearImpulse(vx, vy, self.x, self.y)
  277.                     end
  278.                 end
  279.                 display.getCurrentStage():setFocus(self, nil)
  280.                 self.isFocus = false
  281.             end
  282.         elseif event.phase == "ended" and not self.isFocus then
  283.             -- Detect double click
  284.             if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
  285.                 -- Double click detected within 300 milliseconds
  286.                 self.isLocked = not self.isLocked
  287.                 self.body:setType(self.isLocked and "static" or "dynamic")
  288.                 self.lastClickTime = nil
  289.             else
  290.                 -- Single click, start timer
  291.                 self.lastClickTime = system.getTimer()
  292.             end
  293.         end
  294.         return true
  295.     end
  296.  
  297.     polygon:addEventListener("touch", polygon)
  298.     return polygon
  299. end
  300. -- Function to create a polygon with a specified number of sides
  301. local function createPolygon(x, y, radius, mass, sides, r, g, b)
  302.     sides = polygonSides
  303.  
  304.     -- Calculate the vertices of the polygon
  305.     local vertices = {}
  306.     for i = 1, sides do
  307.         local angle = ((i - 1) / sides) * (2 * math.pi)
  308.         vertices[#vertices + 1] = radius * math.cos(angle)
  309.         vertices[#vertices + 1] = radius * math.sin(angle)
  310.     end
  311.  
  312.     -- Create the polygon
  313.     local polygon = display.newPolygon(x, y, vertices)
  314.     -- Color components
  315.     if toggleMonochrome then
  316.         red = red
  317.         green = green
  318.         blue = blue
  319.     else
  320.         red = math.random()
  321.         green = math.random()
  322.         blue = math.random()
  323.     end
  324.    
  325.     polygon:setFillColor(red, green, blue)
  326.     physics.addBody(polygon, {shape=vertices, density=mass/(radius*radius*sides), bounce=randomPolygonsBounce, friction=polygonFriction})
  327.     polygon.mass = mass
  328.     table.insert(spheres, polygon)
  329.  
  330.     -- Touch event handling
  331.     function polygon:touch(event)
  332.         if event.phase == "began" then
  333.             -- Initial touch
  334.             display.getCurrentStage():setFocus(self, event.id)
  335.             self.isFocus = true
  336.             self.markX = self.x
  337.             self.markY = self.y
  338.             self.startTime = system.getTimer()
  339.             self.movementHistory = {}
  340.             -- Stop the polygon's movement (only if not locked)
  341.             if not self.isLocked then
  342.                 self:setLinearVelocity(0, 0)
  343.                 self.angularVelocity = 0
  344.             end
  345.         elseif self.isFocus then
  346.             if event.phase == "moved" then
  347.                 -- Dragging (only if not locked)
  348.                 if not self.isLocked then
  349.                     self.x = event.x - event.xStart + self.markX
  350.                     self.y = event.y - event.yStart + self.markY
  351.                     -- Record movement history
  352.                     table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
  353.                     -- Clean up old movement history
  354.                     local currentTime = system.getTimer()
  355.                     local cutOffTime = currentTime - (velocityRate*1000)
  356.                     for i, record in ipairs(self.movementHistory) do
  357.                         if record.time < cutOffTime then
  358.                             table.remove(self.movementHistory, i)
  359.                         end
  360.                     end
  361.                 end
  362.             elseif event.phase == "ended" or event.phase == "cancelled" then
  363.                 if not self.isLocked then  -- Don't apply a throw if locked
  364.                     -- Released
  365.                     local endTime = system.getTimer()
  366.                     local distance = 0
  367.                     local throwForce = 0
  368.                     local timeDiff = 0
  369.                     if #self.movementHistory >= 2 then
  370.                         local lastRecord = self.movementHistory[#self.movementHistory]
  371.                         local prevRecord = self.movementHistory[#self.movementHistory - 1]
  372.                         distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
  373.                         timeDiff = lastRecord.time - prevRecord.time
  374.                         throwForce = distance * throwAmplifier / timeDiff
  375.                         -- Apply decay to the throw force to simulate energy loss
  376.                         throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
  377.                         local vx = (event.x - self.markX) * throwForce
  378.                         local vy = (event.y - self.markY) * throwForce
  379.                         self:applyLinearImpulse(vx, vy, self.x, self.y)
  380.                     end
  381.                 end
  382.                 display.getCurrentStage():setFocus(self, nil)
  383.                 self.isFocus = false
  384.             end
  385.         elseif event.phase == "ended" and not self.isFocus then
  386.             -- Detect double click
  387.             if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
  388.                 -- Double click detected within 300 milliseconds
  389.                 self.isLocked = not self.isLocked
  390.                 self.body:setType(self.isLocked and "static" or "dynamic")
  391.                 self.lastClickTime = nil
  392.             else
  393.                 -- Single click, start timer
  394.                 self.lastClickTime = system.getTimer()
  395.             end
  396.         end
  397.         return true
  398.     end
  399.  
  400.     polygon:addEventListener("touch", polygon)
  401.  
  402.     -- Trail effect for polygons
  403.     if toggleTrails then
  404.         local trailGroup = display.newGroup()
  405.  
  406.         function polygon:enterFrame(event)
  407.             -- Create a new set of vertices scaled by trailSize for the trail
  408.             local scaledVertices = {}
  409.             for i = 1, #vertices, 2 do
  410.                 local vx = vertices[i] * trailSize
  411.                 local vy = vertices[i + 1] * trailSize
  412.                 table.insert(scaledVertices, vx)
  413.                 table.insert(scaledVertices, vy)
  414.             end
  415.  
  416.             -- Create a new polygon trail with the scaled vertices
  417.             local trail = display.newPolygon(trailGroup, self.x, self.y, scaledVertices)
  418.             -- Use the polygon's current fill color for the trail
  419.             trail:setFillColor(self.fill.r, self.fill.g, self.fill.b, trailOpaqueness)
  420.             transition.to(trail, {time=(trailLifeTime*1000), alpha=trailGradient, onComplete=function() display.remove(trail) end})
  421.         end
  422.  
  423.         Runtime:addEventListener("enterFrame", polygon)
  424.     end
  425.  
  426.     return polygon
  427. end
  428. -- Function to spawn multiple starting polygons
  429. local function spawnStartingPolygons()
  430.     if customPolygons <= 0 then -- Prevents negative starting polygons
  431.         customPolygons = 1
  432.     end
  433.     if startingPolygonRadius <= 0 then -- Prevents negative radius
  434.         startingPolygonRadius = 25
  435.     end
  436.     for i = 1, (customPolygons) do
  437.         local xPosition = math.random(startingPolygonRadius, display.actualContentWidth - startingPolygonRadius)
  438.         local yPosition = math.random(startingPolygonRadius, display.actualContentHeight - startingPolygonRadius)
  439.         createStartingPolygon(xPosition, yPosition, startingPolygonRadius, startingPolygonMass, startingPolygonSides, startingPolygonColorR, startingPolygonColorG, startingPolygonColorB)
  440.     end
  441. end
  442. -- Function to create a new sphere with a random color and trail
  443. local function createSphere(x, y, radius, mass)
  444.     -- Color components
  445.     if toggleMonochrome then
  446.         red = red
  447.         green = green
  448.         blue = blue
  449.     else
  450.         red = math.random()
  451.         green = math.random()
  452.         blue = math.random()
  453.     end
  454.  
  455.     local sphere = display.newCircle(x, y, radius)
  456.     sphere:setFillColor(red, green, blue) -- Set the random color
  457.     physics.addBody(sphere, {radius=radius, density=mass/(math.pi*radius*radius), bounce=randomCirclesBounce, friction=circleFriction})
  458.     sphere.mass = mass
  459.     table.insert(spheres, sphere)
  460.  
  461.     -- Trail effect for spheres
  462.     if toggleTrails then
  463.         local trailGroup = display.newGroup()
  464.  
  465.         function sphere:enterFrame(event)
  466.             local trail = display.newCircle(trailGroup, self.x, self.y, radius * trailSize)
  467.             -- Use the sphere's current fill color for the trail
  468.             trail:setFillColor(self.fill.r, self.fill.g, self.fill.b, trailOpaqueness)
  469.             transition.to(trail, {time=(trailLifeTime*1000), alpha=trailGradient, onComplete=function() display.remove(trail) end})
  470.         end
  471.  
  472.         Runtime:addEventListener("enterFrame", sphere)
  473.     end
  474.  
  475.     -- Combined function with improved throwing and double-click locking mechanism
  476.     function sphere:touch(event)
  477.         if event.phase == "began" then
  478.             -- Initial touch
  479.             display.getCurrentStage():setFocus(self, event.id)
  480.             self.isFocus = true
  481.             self.markX = self.x
  482.             self.markY = self.y
  483.             self.startTime = system.getTimer()
  484.             self.movementHistory = {}
  485.             -- Stop the sphere's movement (only if not locked)
  486.             if not self.isLocked then
  487.                 self:setLinearVelocity(0, 0)
  488.                 self.angularVelocity = 0
  489.             end
  490.         elseif self.isFocus then
  491.             if event.phase == "moved" then
  492.                 -- Dragging (only if not locked)
  493.                 if not self.isLocked then
  494.                     self.x = event.x - event.xStart + self.markX
  495.                     self.y = event.y - event.yStart + self.markY
  496.                     -- Record movement history
  497.                     table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
  498.                     -- Clean up old movement history
  499.                     local currentTime = system.getTimer()
  500.                     local cutOffTime = currentTime - (velocityRate*1000)
  501.                     for i, record in ipairs(self.movementHistory) do
  502.                         if record.time < cutOffTime then
  503.                             table.remove(self.movementHistory, i)
  504.                         end
  505.                     end
  506.                 end
  507.             elseif event.phase == "ended" or event.phase == "cancelled" then
  508.                 if not self.isLocked then  -- Don't apply a throw if locked
  509.                     -- Released
  510.                     local endTime = system.getTimer()
  511.                     local distance = 0
  512.                     local throwForce = 0
  513.                     local timeDiff = 0
  514.                     if #self.movementHistory >= 2 then
  515.                         local lastRecord = self.movementHistory[#self.movementHistory]
  516.                         local prevRecord = self.movementHistory[#self.movementHistory - 1]
  517.                         distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
  518.                         timeDiff = lastRecord.time - prevRecord.time
  519.                         throwForce = distance * throwAmplifier / timeDiff
  520.                         -- Apply decay to the throw force to simulate energy loss
  521.                         throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
  522.                         local vx = (event.x - self.markX) * throwForce
  523.                         local vy = (event.y - self.markY) * throwForce
  524.                         self:applyLinearImpulse(vx, vy, self.x, self.y)
  525.                     end
  526.                 end
  527.                 display.getCurrentStage():setFocus(self, nil)
  528.                 self.isFocus = false
  529.             end
  530.         elseif event.phase == "ended" and not self.isFocus then
  531.             -- Detect double click
  532.             if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
  533.                 -- Double click detected within 300 milliseconds
  534.                 self.isLocked = not self.isLocked
  535.                 self.body:setType(self.isLocked and "static" or "dynamic")
  536.                 self.lastClickTime = nil
  537.             else
  538.                 -- Single click, start timer
  539.                 self.lastClickTime = system.getTimer()
  540.             end
  541.         end
  542.         return true
  543.     end
  544.  
  545.     sphere:addEventListener("touch", sphere)
  546.     return sphere
  547. end
  548.  
  549. -- Function to update gravitational forces
  550. local function updateGravity()
  551.     for i = 1, #spheres do
  552.         for j = i+1, #spheres do
  553.             local sphere1 = spheres[i]
  554.             local sphere2 = spheres[j]
  555.             local dx = sphere2.x - sphere1.x
  556.             local dy = sphere2.y - sphere1.y
  557.             local distance = math.sqrt(dx*dx + dy*dy)
  558.             local forceMagnitude = (sphere1.mass * sphere2.mass) / (distance * distance)
  559.            
  560.             -- Normalize the direction
  561.             local forceX = (dx / distance) * forceMagnitude
  562.             local forceY = (dy / distance) * forceMagnitude
  563.            
  564.             -- Reverse the force if toggleRepel is true
  565.             if toggleReversedForces then
  566.                 forceX = -forceX
  567.                 forceY = -forceY
  568.             end
  569.            
  570.             -- Apply the force
  571.             sphere1:applyForce(forceX, forceY, sphere1.x, sphere1.y)
  572.             sphere2:applyForce(-forceX, -forceY, sphere2.x, sphere2.y)
  573.         end
  574.     end
  575. end
  576.  
  577. -- Create screen boundaries that fit any screen size
  578. local function createWalls()
  579.     if toggleLeftWall then
  580.         local leftWall = display.newRect(display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight + (display.actualContentHeight/2))
  581.         physics.addBody(leftWall, "static")
  582.     end
  583.     if toggleRightWall then
  584.         local rightWall = display.newRect(display.actualContentWidth + display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight + (display.actualContentHeight/2))
  585.         physics.addBody(rightWall, "static")
  586.     end
  587.     if toggleTopWall then
  588.         local topWall = display.newRect(display.contentCenterX, display.screenOriginY, display.actualContentWidth + (display.actualContentWidth/2), 1)
  589.         physics.addBody(topWall, "static")
  590.     end
  591.     if toggleBottomWall then
  592.         local bottomWall = display.newRect(display.contentCenterX, display.actualContentHeight + display.screenOriginY, display.actualContentWidth + (display.actualContentWidth/2), 1)
  593.         physics.addBody(bottomWall, "static")
  594.     end
  595. end
  596.  
  597. -- Function to create a Portal-like wrap-around effect
  598. local function wrapAroundScreen(object)
  599.     local buffer = object.width * wrapBuffer -- Buffer to ensure the circle is fully off-screen before wrapping
  600.     local leftBoundary = display.screenOriginX
  601.     local rightBoundary = display.actualContentWidth + display.screenOriginX
  602.     local topBoundary = display.screenOriginY
  603.     local bottomBoundary = display.actualContentHeight + display.screenOriginY
  604.  
  605.     -- Check if any part of the object is beyond the screen boundary
  606.     if object.x - buffer > rightBoundary then
  607.         object.x = leftBoundary - buffer + (object.x - buffer - rightBoundary)
  608.     elseif object.x + buffer < leftBoundary then
  609.         object.x = rightBoundary + buffer - (leftBoundary - (object.x + buffer))
  610.     end
  611.     if object.y - buffer > bottomBoundary then
  612.         object.y = topBoundary - buffer + (object.y - buffer - bottomBoundary)
  613.     elseif object.y + buffer < topBoundary then
  614.         object.y = bottomBoundary + buffer - (topBoundary - (object.y + buffer))
  615.     end
  616. end
  617.  
  618. -- Modify the enterFrame event to include the Portal-like wrap-around logic
  619. local function onEnterFrame(event)
  620.     for _, sphere in ipairs(spheres) do
  621.         wrapAroundScreen(sphere)
  622.     end
  623.     --[[
  624.     updateGravity() -- Keep the original gravity update logic if needed
  625.     --]]
  626. end
  627.  
  628. -- Function to generate a random number of circles with random properties
  629. local function generateRandomCircles()
  630.     local numCircles = numRandomShapes -- Random number of circles
  631.     for i = 1, numCircles do
  632.         local radius = ((math.random(radiusMin, radiusMax))*scale) -- Random radius
  633.         local mass = ((radius * circleMass)*scale) -- Mass proportional to radius, adjust as needed
  634.         local x = math.random(radius, display.actualContentWidth - radius) -- Random x position, ensuring circle stays on screen
  635.         local y = math.random(radius, display.actualContentHeight - radius) -- Random y position, ensuring circle stays on screen
  636.         createSphere(x, y, radius, mass)
  637.     end
  638. end
  639.  
  640. -- Function to generate a random number of polygons with random properties
  641. local function generateRandomPolygons()
  642.     local numPolygons = numRandomShapes -- Random number of polygons
  643.     for i = 1, numPolygons do
  644.         local radius = ((math.random(radiusMin, radiusMax))*scale) -- Random radius
  645.         local mass = ((radius * polygonMass)*scale) -- Mass proportional to radius, adjust as needed
  646.         local x = math.random(radius, display.actualContentWidth - radius) -- Random x position, ensuring polygon stays on screen
  647.         local y = math.random(radius, display.actualContentHeight - radius) -- Random y position, ensuring polygon stays on screen
  648.         createPolygon(x, y, radius, mass)
  649.     end
  650. end
  651.  
  652. -- Togglable Functions
  653. -- Create walls
  654. if toggleWalls then
  655.     createWalls() -- Disable for portal-like wrapping
  656. end
  657. -- Call the function to generate random circles
  658. if toggleRandomCircles and toggleCircles then
  659.     generateRandomCircles()
  660. end
  661. -- Create starting circle
  662. if toggleStartingCircle and toggleCircles then
  663.     createCircle(startingXpos, startingYpos, startingCircleRadius, startingCircleMass)
  664. end
  665. -- Call the function to spawn the starting circles
  666. if toggleCustomCircles and toggleCircles then
  667.     spawnStartingCircles()
  668. end
  669. -- Call the function to generate random polygons
  670. if toggleRandomPolygons and togglePolygons then
  671.     generateRandomPolygons()
  672. end
  673. -- Create starting polygon
  674. if toggleStartingPolygon and togglePolygons then
  675.     createStartingPolygon(startingXpos, startingYpos, startingPolygonRadius, startingPolygonMass)
  676. end
  677. -- Call the function to spawn the starting polygons
  678. if toggleCustomPolygons and togglePolygons then
  679.     spawnStartingPolygons(startingXpos, startingYpos, startingPolygonRadius, startingPolygonMass)
  680. end
  681. -- Update gravity every frame
  682. if toggleForces then
  683.     Runtime:addEventListener("enterFrame", updateGravity)
  684. end
  685. -- [[ Object wrapping (Infinite space)
  686. if toggleBodyWrap then
  687.     Runtime:addEventListener("enterFrame", onEnterFrame)
  688. end
  689.  
  690.     ----< | End of Main Program | >----
  691.  
  692.     ----> | Music Player | <----
  693.  
  694. local function bgMusic()
  695.    
  696.     local audioFiles = {
  697.         "Miami.mp3",
  698.         "Light_Flow.mp3",
  699.         "Here_You_Go.mp3",
  700.     }
  701.            
  702.     -- Function to play a random audio file
  703.     local function playRandomAudio()
  704.         math.randomseed(os.time())
  705.            
  706.         -- Choose a random audio file
  707.         local randomIndex = math.random(#audioFiles)
  708.         local randomAudioFile = audioFiles[randomIndex]
  709.            
  710.         -- Load and play the audio file
  711.         local sound = audio.loadSound(randomAudioFile)
  712.         audio.setVolume(musicVolume) -- Ensure the volume is set to maximum
  713.         audio.play(sound)
  714.     end
  715.    
  716.     playRandomAudio()
  717. end
  718. if toggleMusic then
  719.     bgMusic()
  720. end
  721.  
  722.     ----< | End of Music Player | >----
  723.  
  724. -- ( PATCHNOTES & VERSION INFO ) --
  725. print(" ")
  726. print("Orbit Beta v1.3.5 May 24 2024 (Polygon) Edition has initialized. Updates are available on the Pastbin: https://pastebin.com/qixBZPLH")
  727. print(" ")
  728. print("[ Patchnote 1.3.5 ]")
  729. print("|- Added a debug mode for shapes")
  730. print("|- Fixed randomCirclesBounce")
  731. print("|- Universalized startingXpos and Ypos for starting circles and polygons")
  732. print("|- Fixed randomCirclesBounce")
  733. print("|- Fixed objects teleporting to the roof when one of the walls are disabled")
  734. print("|- Added some background music :)")
  735. print("|- If you want the music files, download them here:")
  736. print("   Miami (Tom Fox) - https://drive.google.com/file/d/1atp9hoW1aWF5nUQKcnv7xIzkK6n4MCWF/view?usp=sharing")
  737. print("   Light Flow (Tom Fox) - https://drive.google.com/file/d/1atp9hoW1aWF5nUQKcnv7xIzkK6n4MCWF/view?usp=sharing")
  738. print("   Here You Go (Tom Fox) - https://drive.google.com/file/d/1mx7Bpa7Jw_o0ZZqcYkFniZarE2kYcAt5/view?usp=sharing")
  739. print(" ")
  740. print("[ This code primarily uses Lua and runs on Solar2D or Corona Simulator 2024. This program is not yet an application and is still in prototype stages. Updates will occasionally be made with additional features and debugging. ]")
  741.  
Advertisement
Comments
  • 1m1m0
    324 days
    Comment was deleted
  • 1m1m0
    324 days
    # Lua 9.43 KB | 0 0
    1. new version:
    2.  
    3. -- Initialize physics
    4. local physics = require("physics")
    5. physics.start()
    6. physics.setGravity(0, 0) -- Set gravity to 0
    7.  
    8. -- Core Variables
    9. local screenW = display.contentWidth
    10. local screenH = display.contentHeight
    11.  
    12. scale = math.random(1.25, 1.50) -- Factor to propotionally resize objects, size and mass included
    13. throwAmplifier = 0.075 -- Factor in which how fast an object will be after throwing or flicking it
    14. dampingAmplifier = 0.25 -- Factor to simulate drag or air resistance (set to 0 for cosmic simulations)
    15.  
    16.  
    17. -- Table to keep track of spheres
    18. local spheres = {}
    19.  
    20. -- [[ Starting Circle with fixed size & mass for experimentations
    21. local function createCircle(x, y, radius, mass)
    22.     local circle = display.newCircle(x, y, radius)
    23.     physics.addBody(circle, {radius=radius, density=mass/(math.pi*radius*radius), bounce=0.5})
    24.     circle.mass = mass
    25.     table.insert(spheres, circle)
    26.  
    27.     -- Make spheres draggable
    28.     function sphere:touch(event)
    29.         if event.phase == "began" then
    30.             -- Initial touch
    31.             display.getCurrentStage():setFocus(self, event.id)
    32.             self.isFocus = true
    33.             self.markX = self.x
    34.             self.markY = self.y
    35.             self.startTime = system.getTimer()
    36.  
    37.             self.movementHistory = {} -- Array to store past positions and times
    38.  
    39.             -- Stop the sphere's movement
    40.             self:setLinearVelocity(0, 0)
    41.             self.angularVelocity = 0
    42.         elseif self.isFocus then
    43.             if event.phase == "moved" then
    44.                 -- Dragging
    45.                 self.x = event.x - event.xStart + self.markX
    46.                 self.y = event.y - event.yStart + self.markY
    47.  
    48.                 -- Record movement history
    49.                 table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
    50.  
    51.                 -- Clean up old movement history
    52.                 local currentTime = system.getTimer()
    53.                 local cutOffTime = currentTime - 1000
    54.                 for i, record in ipairs(self.movementHistory) do
    55.                     if record.time < cutOffTime then
    56.                         table.remove(self.movementHistory, i)
    57.                     end
    58.                 end
    59.  
    60.             elseif event.phase == "ended" or event.phase == "cancelled" then
    61.                 -- Released
    62.                 local endTime = system.getTimer()
    63.                 local distance = 0
    64.                 local throwForce = 0
    65.  
    66.                 -- Calculate distance based on movement history
    67.                 if #self.movementHistory >= 2 then
    68.                     local lastRecord = self.movementHistory[#self.movementHistory]
    69.                     local prevRecord = self.movementHistory[#self.movementHistory - 1]
    70.  
    71.                     distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
    72.                     throwForce = distance * throwAmplifier / (endTime - prevRecord.time)
    73.                 end
    74.  
    75.                 local vx = (event.x - self.markX) * throwForce * dampingAmplifier
    76.                 local vy = (event.y - self.markY) * throwForce * dampingAmplifier
    77.  
    78.                 -- Apply linear impulse
    79.                 self:applyLinearImpulse(vx, vy, self.x, self.y)
    80.  
    81.                 display.getCurrentStage():setFocus(self, nil)
    82.                 self.isFocus = false
    83.             end
    84.         end
    85.         return true
    86.     end
    87.  
    88.     circle:addEventListener("touch", circle)
    89.     return circle
    90. end
    91. --]]
    92. -- Function to create a new sphere with a random color and trail
    93. local function createSphere(x, y, radius, mass)
    94.     -- Random color components
    95.     local r = math.random()
    96.     local g = math.random()
    97.     local b = math.random()
    98.  
    99.     local sphere = display.newCircle(x, y, radius)
    100.     sphere:setFillColor(r, g, b) -- Set the random color
    101.     physics.addBody(sphere, {radius=radius, density=mass/(math.pi*radius*radius), bounce=math.random(0.0, 0.5)})
    102.     sphere.mass = mass
    103.     table.insert(spheres, sphere)
    104.  
    105.     -- [[ Trail effect
    106.     local trailGroup = display.newGroup()
    107.  
    108.     function sphere:enterFrame(event)
    109.         local trail = display.newCircle(trailGroup, self.x, self.y, radius * 0.3)
    110.         trail:setFillColor(r, g, b, 0.5) -- Slightly transparent version of the sphere's color
    111.         transition.to(trail, {time=500, alpha=0, onComplete=function() display.remove(trail) end})
    112.     end
    113.     --]]
    114.     Runtime:addEventListener("enterFrame", sphere)
    115.  
    116.     -- Make spheres draggable
    117.     function sphere:touch(event)
    118.         if event.phase == "began" then
    119.             -- Initial touch
    120.             display.getCurrentStage():setFocus(self, event.id)
    121.             self.isFocus = true
    122.             self.markX = self.x
    123.             self.markY = self.y
    124.             self.startTime = system.getTimer()
    125.  
    126.             self.movementHistory = {} -- Array to store past positions and times
    127.  
    128.             -- Stop the sphere's movement
    129.             self:setLinearVelocity(0, 0)
    130.             self.angularVelocity = 0
    131.         elseif self.isFocus then
    132.             if event.phase == "moved" then
    133.                 -- Dragging
    134.                 self.x = event.x - event.xStart + self.markX
    135.                 self.y = event.y - event.yStart + self.markY
    136.  
    137.                 -- Record movement history
    138.                 table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
    139.  
    140.                 -- Clean up old movement history
    141.                 local currentTime = system.getTimer()
    142.                 local cutOffTime = currentTime - 1000
    143.                 for i, record in ipairs(self.movementHistory) do
    144.                     if record.time < cutOffTime then
    145.                         table.remove(self.movementHistory, i)
    146.                     end
    147.                 end
    148.  
    149.             elseif event.phase == "ended" or event.phase == "cancelled" then
    150.                 -- Released
    151.                 local endTime = system.getTimer()
    152.                 local distance = 0
    153.                 local throwForce = 0
    154.  
    155.                 -- Calculate distance based on movement history
    156.                 if #self.movementHistory >= 2 then
    157.                     local lastRecord = self.movementHistory[#self.movementHistory]
    158.                     local prevRecord = self.movementHistory[#self.movementHistory - 1]
    159.  
    160.                     distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
    161.                     throwForce = distance * throwAmplifier / (endTime - prevRecord.time)
    162.                 end
    163.  
    164.                 local vx = (event.x - self.markX) * throwForce * dampingAmplifier
    165.                 local vy = (event.y - self.markY) * throwForce * dampingAmplifier
    166.  
    167.                 -- Apply linear impulse
    168.                 self:applyLinearImpulse(vx, vy, self.x, self.y)
    169.  
    170.                 display.getCurrentStage():setFocus(self, nil)
    171.                 self.isFocus = false
    172.             end
    173.         end
    174.         return true
    175.     end
    176.  
    177.     sphere:addEventListener("touch", sphere)
    178.     return sphere
    179. end
    180.  
    181. -- [[ Function to update gravitational forces
    182. local function updateGravity()
    183.     for i = 1, #spheres do
    184.         for j = i+1, #spheres do
    185.             local sphere1 = spheres[i]
    186.             local sphere2 = spheres[j]
    187.             local dx = sphere2.x - sphere1.x
    188.             local dy = sphere2.y - sphere1.y
    189.             local distance = math.sqrt(dx*dx + dy*dy)
    190.             local force = (sphere1.mass * sphere2.mass) / (distance * distance)
    191.             local forceX = force * (dx / distance)
    192.             local forceY = force * (dy / distance)
    193.  
    194.             sphere1:applyForce(forceX, forceY, sphere1.x, sphere1.y)
    195.             sphere2:applyForce(-forceX, -forceY, sphere2.x, sphere2.y)
    196.         end
    197.     end
    198. end
    199. --]]
    200. -- Create screen boundaries that fit any screen size
    201. local function createWalls()
    202.     local leftWall = display.newRect(display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
    203.     local rightWall = display.newRect(display.actualContentWidth + display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
    204.     local topWall = display.newRect(display.contentCenterX, display.screenOriginY, display.actualContentWidth, 1)
    205.     local bottomWall = display.newRect(display.contentCenterX, display.actualContentHeight + display.screenOriginY, display.actualContentWidth, 1)
    206.  
    207.     physics.addBody(leftWall, "static")
    208.     physics.addBody(rightWall, "static")
    209.     physics.addBody(topWall, "static")
    210.     physics.addBody(bottomWall, "static")
    211. end
    212.  
    213. -- Function to generate a random number of circles with random properties
    214. local function generateRandomCircles()
    215.     local numCircles = math.random(2, 12) -- Random number of circles between 2 and 10
    216.     for i = 1, numCircles do
    217.         local radius = (math.random(math.random(8, 13), math.random(15, 25)))*scale -- Random radius between 5 and 20
    218.         local mass = (radius * math.random(1, 12))*scale -- Mass proportional to radius, adjust as needed
    219.         local x = math.random(radius, screenW - radius) -- Random x position, ensuring circle stays on screen
    220.         local y = math.random(radius, screenH - radius) -- Random y position, ensuring circle stays on screen
    221.         createSphere(x, y, radius, mass)
    222.     end
    223. end
    224.  
    225. -- Call the function to generate random circles
    226. generateRandomCircles()
    227.  
    228. -- Create walls
    229. createWalls()
    230.  
    231. -- Create starting circle
    232. --createCircle(160, 240, 25, 25)
    233.  
    234. -- Update gravity every frame
    235. Runtime:addEventListener("enterFrame", updateGravity)
  • 1m1m0
    324 days
    # Lua 7.05 KB | 0 0
    1. PREVIOUS VERSION OF ORBIT:
    2.  
    3. -- Initialize physics
    4. local physics = require("physics")
    5. physics.start()
    6. physics.setGravity(0, 0) -- Set gravity to 0
    7.  
    8. -- Core Variables
    9. local screenW = display.contentWidth
    10. local screenH = display.contentHeight
    11.  
    12. scale = 0.75 -- Factor to propotionally resize objects, size and mass included
    13.  
    14. -- Table to keep track of spheres
    15. local spheres = {}
    16.  
    17. -- [[ Starting Circle with fixed size & mass for experimentations
    18. local function createCircle(x, y, radius, mass)
    19.     local circle = display.newCircle(x, y, radius)
    20.     physics.addBody(circle, {radius=radius, density=mass/(math.pi*radius*radius), bounce=0.5})
    21.     circle.mass = mass
    22.     table.insert(spheres, circle)
    23.  
    24.     -- Make spheres draggable and stop their movement while dragging
    25.     function circle:touch(event)
    26.         if event.phase == "began" then
    27.             -- Initial touch
    28.             display.getCurrentStage():setFocus(self, event.id)
    29.             self.isFocus = true
    30.             self.markX = self.x
    31.             self.markY = self.y
    32.             self.startTime = system.getTimer()
    33.             -- Stop the sphere's movement
    34.             self:setLinearVelocity(0, 0)
    35.             self.angularVelocity = 0
    36.         elseif self.isFocus then
    37.             if event.phase == "moved" then
    38.                 -- Dragging
    39.                 self.x = event.x - event.xStart + self.markX
    40.                 self.y = event.y - event.yStart + self.markY
    41.             elseif event.phase == "ended" or event.phase == "cancelled" then
    42.                 -- Released
    43.                 local endTime = system.getTimer()
    44.                 local timePassed = endTime - self.startTime
    45.                 local vx = (event.x - self.markX) / timePassed
    46.                 local vy = (event.y - self.markY) / timePassed
    47.                 -- Apply the linear impulse based on the calculated velocity
    48.                 self:applyLinearImpulse(vx * 0.1, vy * 0.1, self.x, self.y)
    49.                
    50.                 display.getCurrentStage():setFocus(self, nil)
    51.                 self.isFocus = false
    52.             end
    53.         end
    54.         return true
    55.     end
    56.  
    57.  
    58.     circle:addEventListener("touch", circle)
    59.     return circle
    60. end
    61. --]]
    62. -- Function to create a new sphere with a random color and trail
    63. local function createSphere(x, y, radius, mass)
    64.     -- Random color components
    65.     local r = math.random()
    66.     local g = math.random()
    67.     local b = math.random()
    68.  
    69.     local sphere = display.newCircle(x, y, radius)
    70.     sphere:setFillColor(r, g, b) -- Set the random color
    71.     physics.addBody(sphere, {radius=radius, density=mass/(math.pi*radius*radius), bounce=math.random(0.0, 0.65)})
    72.     sphere.mass = mass
    73.     table.insert(spheres, sphere)
    74.  
    75.     --[[ Trail effect
    76.     local trailGroup = display.newGroup()
    77.  
    78.     function sphere:enterFrame(event)
    79.         local trail = display.newCircle(trailGroup, self.x, self.y, radius * 0.3)
    80.         trail:setFillColor(r, g, b, 0.5) -- Slightly transparent version of the sphere's color
    81.         transition.to(trail, {time=500, alpha=0, onComplete=function() display.remove(trail) end})
    82.     end
    83.     --]]
    84.     Runtime:addEventListener("enterFrame", sphere)
    85.  
    86.     -- Make spheres draggable and stop their movement while dragging
    87.     function sphere:touch(event)
    88.         if event.phase == "began" then
    89.             -- Initial touch
    90.             display.getCurrentStage():setFocus(self, event.id)
    91.             self.isFocus = true
    92.             self.markX = self.x
    93.             self.markY = self.y
    94.             self.startTime = system.getTimer()
    95.             -- Stop the sphere's movement
    96.             self:setLinearVelocity(0, 0)
    97.             self.angularVelocity = 0
    98.         elseif self.isFocus then
    99.             if event.phase == "moved" then
    100.                 -- Dragging
    101.                 self.x = event.x - event.xStart + self.markX
    102.                 self.y = event.y - event.yStart + self.markY
    103.             elseif event.phase == "ended" or event.phase == "cancelled" then
    104.                 -- Released
    105.                 local endTime = system.getTimer()
    106.                 local timePassed = endTime - self.startTime
    107.                 local vx = (event.x - self.markX) / timePassed
    108.                 local vy = (event.y - self.markY) / timePassed
    109.                 -- Apply the linear impulse based on the calculated velocity
    110.                 self:applyLinearImpulse(vx * 0.1, vy * 0.1, self.x, self.y)
    111.                
    112.                 display.getCurrentStage():setFocus(self, nil)
    113.                 self.isFocus = false
    114.             end
    115.         end
    116.         return true
    117.     end
    118.  
    119.     sphere:addEventListener("touch", sphere)
    120.     return sphere
    121. end
    122.  
    123. -- [[ Function to update gravitational forces
    124. local function updateGravity()
    125.     for i = 1, #spheres do
    126.         for j = i+1, #spheres do
    127.             local sphere1 = spheres[i]
    128.             local sphere2 = spheres[j]
    129.             local dx = sphere2.x - sphere1.x
    130.             local dy = sphere2.y - sphere1.y
    131.             local distance = math.sqrt(dx*dx + dy*dy)
    132.             local force = (sphere1.mass * sphere2.mass) / (distance * distance)
    133.             local forceX = force * (dx / distance)
    134.             local forceY = force * (dy / distance)
    135.            
    136.             sphere1:applyForce(forceX, forceY, sphere1.x, sphere1.y)
    137.             sphere2:applyForce(-forceX, -forceY, sphere2.x, sphere2.y)
    138.         end
    139.     end
    140. end
    141. --]]
    142. -- Create screen boundaries that fit any screen size
    143. local function createWalls()
    144.     local leftWall = display.newRect(display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
    145.     local rightWall = display.newRect(display.actualContentWidth + display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
    146.     local topWall = display.newRect(display.contentCenterX, display.screenOriginY, display.actualContentWidth, 1)
    147.     local bottomWall = display.newRect(display.contentCenterX, display.actualContentHeight + display.screenOriginY, display.actualContentWidth, 1)
    148.    
    149.     physics.addBody(leftWall, "static")
    150.     physics.addBody(rightWall, "static")
    151.     physics.addBody(topWall, "static")
    152.     physics.addBody(bottomWall, "static")
    153. end
    154.  
    155. -- Function to generate a random number of circles with random properties
    156. local function generateRandomCircles()
    157.     local numCircles = math.random(2, 12) -- Random number of circles between 2 and 10
    158.     for i = 1, numCircles do
    159.         local radius = (math.random(math.random(8, 13), math.random(15, 25)))*scale -- Random radius between 5 and 20
    160.         local mass = (radius * math.random(1, 12))*scale -- Mass proportional to radius, adjust as needed
    161.         local x = math.random(radius, screenW - radius) -- Random x position, ensuring circle stays on screen
    162.         local y = math.random(radius, screenH - radius) -- Random y position, ensuring circle stays on screen
    163.         createSphere(x, y, radius, mass)
    164.     end
    165. end
    166.  
    167. -- Call the function to generate random circles
    168. generateRandomCircles()
    169.  
    170. -- Create walls
    171. createWalls()
    172.  
    173. -- Create starting circle
    174. --createCircle(160, 240, 25, 25)
    175.  
    176. -- Update gravity every frame
    177. Runtime:addEventListener("enterFrame", updateGravity)
Add Comment
Please, Sign In to add comment
Advertisement