Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- | Orbit (Interactive Celestial Body Simulator Program) Complete Release v1.3.5 [5/24/2024], written by 1m1m0 & several AI models | --
- local t = true -- Do not touch
- local f = false -- Do not touch
- local screenW = display.contentWidth -- Do not touch
- local screenH = display.contentHeight -- Do not touch
- -- (Quick Settings/Variables) --
- -- { Most configurations are syncronized with Polygons! }
- local scale = math.random(0.6, 1.2) -- Factor to propotionally resize objects, size and mass included
- local trailLifeTime = 1 -- How long a trail will last (seconds)
- local trailSize = 0.25 -- How wide trails will be proportional to their parent circle's radius
- local trailOpaqueness = 0.5 -- How see-through trails will be
- local trailGradient = 0 -- Determines if trails fade out or not
- local numRandomShapes = math.random(2, 100) -- Amount of circles can randomly spawn
- local circleMass = math.random(1, 12) -- Mass of circles while being randomized
- local polygonMass = math.random(1, 12) -- Mass of polygons while being randomized
- local radiusMax = 30 -- Maximum random radius of circles while being randomized
- local radiusMin = 30 -- Minimum random radius of circles while being randomized
- local polygonSides = math.random(3, 6) -- Side count of a polygon between a triangle to a circle [EXPERIMENTAL]
- local circleFriction = math.random(0.0, 1.0) -- Friction for circles
- local polygonFriction = math.random(0.0, 1.0) -- Friction for polygons
- local gravityStrength = 9.81 -- Dictates the gravitational strength (not forces) of the simulation
- local throwAmplifier = 0.075 -- Factor in which how fast an object will be after throwing or flicking it
- local velocityRate = 5 -- Time (seconds) to calculate the velocity of the circle while thrown (pix/s)
- local dampingAmplifier = 0.25 -- Factor to simulate drag or air resistance (set to 0 for cosmic simulations)
- local randomCirclesBounce = math.random(0.0, 0.5) -- Elasticity of the Randomized Circles
- local randomPolygonsBounce = math.random(0.0, 0.5) -- Elasticity of the Randomized Polygons
- local wrapBuffer = 0.5 -- Time in seconds to ensure the circle is fully off-screen to wrap around the screen
- local startingXpos = screenW/2 -- Center of screen (Applies to Polygons and Circles)
- local startingYpos = screenH/2
- local musicVolume = 0.3 -- Volume of background music
- -- Color Configs --
- local red = math.random() -- Amount of red for random circles/polygons
- local green = math.random() -- Amount of green for random circles/polygons
- local blue = math.random() -- Amount of blue for random circles/polygons
- -- (Togglables) --
- local toggleMusic = t -- Toggle to turn background music on or off, music is chosen from the creator's favorite playlist :)
- local toggleDebugMode = f -- Toggle to view the simulation in debugging mode, usually to monitor the physics of polygons and circles [Master Switch]
- local toggleMonochrome = t -- Toggle to generate random shapes with the same random color (Applies to random circles/polygons) [Master Switch]
- local toggleCircles = t -- Toggle the generation of circles [Master Switch]
- local togglePolygons = f -- Toggle the generation of polygons (Will have the same configurations to Random Circles!) [Master Switch]
- local toggleWalls = t -- Toggle to have bounderies to the simulation
- local toggleTopWall = t -- Toggle to add or remove the top wall
- local toggleRightWall = f -- Toggle to add or remove the right wall
- local toggleBottomWall = t -- Toggle to add or remove the bottom wall
- local toggleLeftWall = f -- Toggle to add or remove the left wall
- local toggleBodyWrap = t -- Toggle teleporting objects across the screen when crossing the walls
- local toggleStartingCircle = t -- Toggle to spawn a starting circle
- local toggleCustomCircles = f -- Toggle to spawn more starting circles which can be changed in 'local customCircles = 4'
- local toggleRandomCircles = t -- Toggle randomized circles
- local toggleStartingPolygon = t -- Same concept as toggleStartingCircle
- local toggleCustomPolygons = f -- Same concept as toggleCustomCircles
- local toggleRandomPolygons = t -- Same concept as toggleRandomCircles
- local toggleTrails = f -- Toggle trails on/off (Greatly affect performance)
- local toggleForces = t -- Toggle gravitational forces on the circles
- local toggleReversedForces = f -- Toggle negative gravity or repelling forces
- local toggleGravity = f -- Toggle gravity of the simulation
- -- (Starting Circle quick settings) --
- local customCircles = 1 -- Number of custom starting circles to spawn
- local startingCircleBounce = 0.25 -- Elasticity of the circle
- local startingCircleFriction = 0.5 -- Friction of the circle
- local startingCircleRadius = 50 -- Size of circle
- local startingCircleMass = 500 -- Mass of circle
- local startingColorR = 255 -- Red value (Maximum 255)
- local startingColorG = 255 -- Green value (Maximum 255)
- local startingColorB = 255 -- Blue value (Maximum 255)
- -- (Starting Polygon quick settings) --
- local customPolygons = 1 -- Number of custom starting polygons to spawn
- local startingPolygonSides = math.random(3, 6) -- Number of sides for the starting polygon
- local startingPolygonBounce = 0.3 -- Elasticity of the polygon
- local startingPolygonFriction = 0.5 -- Friction of the polygon
- local startingPolygonRadius = 80 -- Size of polygon
- local startingPolygonMass = 400 -- Mass of polygon
- local startingPolygonColorR = 255 -- Red value (Maximum 255)
- local startingPolygonColorG = 255 -- Green value (Maximum 255)
- local startingPolygonColorB = 255 -- Blue value (Maximum 255)
- ----> | Main Program | <----
- -- Initialize physics
- local physics = require("physics")
- physics.start()
- if toggleGravity then
- physics.setGravity(0, gravityStrength)
- else
- physics.setGravity(0, 0) -- Set gravity to 0 if toggleGravity is false
- end
- if toggleDebugMode then
- physics.setDrawMode("hybrid")
- else if toggleDebugMode == f then
- physics.setDrawMode("normal")
- end
- end
- local spheres = {} -- Table to keep track of spheres
- -- [[ Starting Circle with fixed size & mass for experimentations
- local function createCircle(x, y, radius, mass, r, g, b)
- local circle = display.newCircle(x, y, radius)
- -- Prevent color errors
- if startingColorR <= 0 or startingColorR >= 255 then
- startingColorR = 1
- elseif startingColorG <= 0 or startingColorG >= 255 then
- startingColorG = 1
- elseif startingColorB <= 0 or startingColorB >= 255 then
- startingColorB = 1
- end
- circle:setFillColor(startingColorR, startingColorG, startingColorB)
- physics.addBody(circle, {radius=radius, density=mass/(math.pi*radius*radius), bounce=startingCircleBounce, friction=startingCircleFriction})
- circle.mass = mass
- table.insert(spheres, circle)
- -- Combined function with improved throwing and double-click locking mechanism
- function circle:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- self.movementHistory = {}
- -- Stop the sphere's movement (only if not locked)
- if not self.isLocked then
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- end
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging (only if not locked)
- if not self.isLocked then
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- -- Record movement history
- table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
- -- Clean up old movement history
- local currentTime = system.getTimer()
- local cutOffTime = currentTime - (velocityRate*1000)
- for i, record in ipairs(self.movementHistory) do
- if record.time < cutOffTime then
- table.remove(self.movementHistory, i)
- end
- end
- end
- elseif event.phase == "ended" or event.phase == "cancelled" then
- if not self.isLocked then -- Don't apply a throw if locked
- -- Released
- local endTime = system.getTimer()
- local distance = 0
- local throwForce = 0
- local timeDiff = 0
- if #self.movementHistory >= 2 then
- local lastRecord = self.movementHistory[#self.movementHistory]
- local prevRecord = self.movementHistory[#self.movementHistory - 1]
- distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
- timeDiff = lastRecord.time - prevRecord.time
- throwForce = distance * throwAmplifier / timeDiff
- -- Apply decay to the throw force to simulate energy loss
- throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
- local vx = (event.x - self.markX) * throwForce
- local vy = (event.y - self.markY) * throwForce
- self:applyLinearImpulse(vx, vy, self.x, self.y)
- end
- end
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- elseif event.phase == "ended" and not self.isFocus then
- -- Detect double click
- if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
- -- Double click detected within 300 milliseconds
- self.isLocked = not self.isLocked
- self.body:setType(self.isLocked and "static" or "dynamic")
- self.lastClickTime = nil
- else
- -- Single click, start timer
- self.lastClickTime = system.getTimer()
- end
- end
- return true
- end
- circle:addEventListener("touch", circle)
- return circle
- end
- --]]
- -- Function to spawn multiple starting circles
- local function spawnStartingCircles()
- if customCircles <= 0 then -- Prevents negative starting circles
- customCircles = 1
- end
- if startingCircleRadius <= 0 then -- Prevents negative radius
- startingCircleRadius = 25
- end
- for i = 1, (customCircles) do
- local xPosition = math.random(startingCircleRadius, display.actualContentWidth - startingCircleRadius)
- local yPosition = math.random(startingCircleRadius, display.actualContentHeight - startingCircleRadius)
- createCircle(xPosition, yPosition, startingCircleRadius, startingCircleMass)
- end
- end
- -- Function to create a polygon with a specified number of sides
- local function createStartingPolygon(x, y, radius, mass, sides, r, g, b)
- sides = polygonSides
- -- Calculate the vertices of the polygon
- local vertices = {}
- for i = 1, sides do
- local angle = ((i - 1) / sides) * (2 * math.pi)
- vertices[#vertices + 1] = radius * math.cos(angle)
- vertices[#vertices + 1] = radius * math.sin(angle)
- end
- -- Create the polygon
- local polygon = display.newPolygon(x, y, vertices)
- -- Prevent color errors
- if startingPolygonColorR <= 0 or startingPolygonColorR >= 255 then
- startingPolygonColorR = 1
- elseif startingPolygonColorG <= 0 or startingPolygonColorG >= 255 then
- startingPolygonColorG = 1
- elseif startingPolygonColorB <= 0 or startingPolygonColorB >= 255 then
- startingPolygonColorB = 1
- end
- polygon:setFillColor(startingPolygonColorR, startingPolygonColorG, startingPolygonColorB)
- physics.addBody(polygon, {shape=vertices, density=mass/(radius*radius*sides), bounce=startingPolygonBounce, friction=startingPolygonFriction})
- polygon.mass = mass
- table.insert(spheres, polygon)
- -- Touch event handling
- function polygon:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- self.movementHistory = {}
- -- Stop the polygon's movement (only if not locked)
- if not self.isLocked then
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- end
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging (only if not locked)
- if not self.isLocked then
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- -- Record movement history
- table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
- -- Clean up old movement history
- local currentTime = system.getTimer()
- local cutOffTime = currentTime - (velocityRate*1000)
- for i, record in ipairs(self.movementHistory) do
- if record.time < cutOffTime then
- table.remove(self.movementHistory, i)
- end
- end
- end
- elseif event.phase == "ended" or event.phase == "cancelled" then
- if not self.isLocked then -- Don't apply a throw if locked
- -- Released
- local endTime = system.getTimer()
- local distance = 0
- local throwForce = 0
- local timeDiff = 0
- if #self.movementHistory >= 2 then
- local lastRecord = self.movementHistory[#self.movementHistory]
- local prevRecord = self.movementHistory[#self.movementHistory - 1]
- distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
- timeDiff = lastRecord.time - prevRecord.time
- throwForce = distance * throwAmplifier / timeDiff
- -- Apply decay to the throw force to simulate energy loss
- throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
- local vx = (event.x - self.markX) * throwForce
- local vy = (event.y - self.markY) * throwForce
- self:applyLinearImpulse(vx, vy, self.x, self.y)
- end
- end
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- elseif event.phase == "ended" and not self.isFocus then
- -- Detect double click
- if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
- -- Double click detected within 300 milliseconds
- self.isLocked = not self.isLocked
- self.body:setType(self.isLocked and "static" or "dynamic")
- self.lastClickTime = nil
- else
- -- Single click, start timer
- self.lastClickTime = system.getTimer()
- end
- end
- return true
- end
- polygon:addEventListener("touch", polygon)
- return polygon
- end
- -- Function to create a polygon with a specified number of sides
- local function createPolygon(x, y, radius, mass, sides, r, g, b)
- sides = polygonSides
- -- Calculate the vertices of the polygon
- local vertices = {}
- for i = 1, sides do
- local angle = ((i - 1) / sides) * (2 * math.pi)
- vertices[#vertices + 1] = radius * math.cos(angle)
- vertices[#vertices + 1] = radius * math.sin(angle)
- end
- -- Create the polygon
- local polygon = display.newPolygon(x, y, vertices)
- -- Color components
- if toggleMonochrome then
- red = red
- green = green
- blue = blue
- else
- red = math.random()
- green = math.random()
- blue = math.random()
- end
- polygon:setFillColor(red, green, blue)
- physics.addBody(polygon, {shape=vertices, density=mass/(radius*radius*sides), bounce=randomPolygonsBounce, friction=polygonFriction})
- polygon.mass = mass
- table.insert(spheres, polygon)
- -- Touch event handling
- function polygon:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- self.movementHistory = {}
- -- Stop the polygon's movement (only if not locked)
- if not self.isLocked then
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- end
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging (only if not locked)
- if not self.isLocked then
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- -- Record movement history
- table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
- -- Clean up old movement history
- local currentTime = system.getTimer()
- local cutOffTime = currentTime - (velocityRate*1000)
- for i, record in ipairs(self.movementHistory) do
- if record.time < cutOffTime then
- table.remove(self.movementHistory, i)
- end
- end
- end
- elseif event.phase == "ended" or event.phase == "cancelled" then
- if not self.isLocked then -- Don't apply a throw if locked
- -- Released
- local endTime = system.getTimer()
- local distance = 0
- local throwForce = 0
- local timeDiff = 0
- if #self.movementHistory >= 2 then
- local lastRecord = self.movementHistory[#self.movementHistory]
- local prevRecord = self.movementHistory[#self.movementHistory - 1]
- distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
- timeDiff = lastRecord.time - prevRecord.time
- throwForce = distance * throwAmplifier / timeDiff
- -- Apply decay to the throw force to simulate energy loss
- throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
- local vx = (event.x - self.markX) * throwForce
- local vy = (event.y - self.markY) * throwForce
- self:applyLinearImpulse(vx, vy, self.x, self.y)
- end
- end
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- elseif event.phase == "ended" and not self.isFocus then
- -- Detect double click
- if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
- -- Double click detected within 300 milliseconds
- self.isLocked = not self.isLocked
- self.body:setType(self.isLocked and "static" or "dynamic")
- self.lastClickTime = nil
- else
- -- Single click, start timer
- self.lastClickTime = system.getTimer()
- end
- end
- return true
- end
- polygon:addEventListener("touch", polygon)
- -- Trail effect for polygons
- if toggleTrails then
- local trailGroup = display.newGroup()
- function polygon:enterFrame(event)
- -- Create a new set of vertices scaled by trailSize for the trail
- local scaledVertices = {}
- for i = 1, #vertices, 2 do
- local vx = vertices[i] * trailSize
- local vy = vertices[i + 1] * trailSize
- table.insert(scaledVertices, vx)
- table.insert(scaledVertices, vy)
- end
- -- Create a new polygon trail with the scaled vertices
- local trail = display.newPolygon(trailGroup, self.x, self.y, scaledVertices)
- -- Use the polygon's current fill color for the trail
- trail:setFillColor(self.fill.r, self.fill.g, self.fill.b, trailOpaqueness)
- transition.to(trail, {time=(trailLifeTime*1000), alpha=trailGradient, onComplete=function() display.remove(trail) end})
- end
- Runtime:addEventListener("enterFrame", polygon)
- end
- return polygon
- end
- -- Function to spawn multiple starting polygons
- local function spawnStartingPolygons()
- if customPolygons <= 0 then -- Prevents negative starting polygons
- customPolygons = 1
- end
- if startingPolygonRadius <= 0 then -- Prevents negative radius
- startingPolygonRadius = 25
- end
- for i = 1, (customPolygons) do
- local xPosition = math.random(startingPolygonRadius, display.actualContentWidth - startingPolygonRadius)
- local yPosition = math.random(startingPolygonRadius, display.actualContentHeight - startingPolygonRadius)
- createStartingPolygon(xPosition, yPosition, startingPolygonRadius, startingPolygonMass, startingPolygonSides, startingPolygonColorR, startingPolygonColorG, startingPolygonColorB)
- end
- end
- -- Function to create a new sphere with a random color and trail
- local function createSphere(x, y, radius, mass)
- -- Color components
- if toggleMonochrome then
- red = red
- green = green
- blue = blue
- else
- red = math.random()
- green = math.random()
- blue = math.random()
- end
- local sphere = display.newCircle(x, y, radius)
- sphere:setFillColor(red, green, blue) -- Set the random color
- physics.addBody(sphere, {radius=radius, density=mass/(math.pi*radius*radius), bounce=randomCirclesBounce, friction=circleFriction})
- sphere.mass = mass
- table.insert(spheres, sphere)
- -- Trail effect for spheres
- if toggleTrails then
- local trailGroup = display.newGroup()
- function sphere:enterFrame(event)
- local trail = display.newCircle(trailGroup, self.x, self.y, radius * trailSize)
- -- Use the sphere's current fill color for the trail
- trail:setFillColor(self.fill.r, self.fill.g, self.fill.b, trailOpaqueness)
- transition.to(trail, {time=(trailLifeTime*1000), alpha=trailGradient, onComplete=function() display.remove(trail) end})
- end
- Runtime:addEventListener("enterFrame", sphere)
- end
- -- Combined function with improved throwing and double-click locking mechanism
- function sphere:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- self.movementHistory = {}
- -- Stop the sphere's movement (only if not locked)
- if not self.isLocked then
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- end
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging (only if not locked)
- if not self.isLocked then
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- -- Record movement history
- table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
- -- Clean up old movement history
- local currentTime = system.getTimer()
- local cutOffTime = currentTime - (velocityRate*1000)
- for i, record in ipairs(self.movementHistory) do
- if record.time < cutOffTime then
- table.remove(self.movementHistory, i)
- end
- end
- end
- elseif event.phase == "ended" or event.phase == "cancelled" then
- if not self.isLocked then -- Don't apply a throw if locked
- -- Released
- local endTime = system.getTimer()
- local distance = 0
- local throwForce = 0
- local timeDiff = 0
- if #self.movementHistory >= 2 then
- local lastRecord = self.movementHistory[#self.movementHistory]
- local prevRecord = self.movementHistory[#self.movementHistory - 1]
- distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
- timeDiff = lastRecord.time - prevRecord.time
- throwForce = distance * throwAmplifier / timeDiff
- -- Apply decay to the throw force to simulate energy loss
- throwForce = throwForce * math.exp(-timeDiff * dampingAmplifier)
- local vx = (event.x - self.markX) * throwForce
- local vy = (event.y - self.markY) * throwForce
- self:applyLinearImpulse(vx, vy, self.x, self.y)
- end
- end
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- elseif event.phase == "ended" and not self.isFocus then
- -- Detect double click
- if self.lastClickTime and (system.getTimer() - self.lastClickTime) < 300 then
- -- Double click detected within 300 milliseconds
- self.isLocked = not self.isLocked
- self.body:setType(self.isLocked and "static" or "dynamic")
- self.lastClickTime = nil
- else
- -- Single click, start timer
- self.lastClickTime = system.getTimer()
- end
- end
- return true
- end
- sphere:addEventListener("touch", sphere)
- return sphere
- end
- -- Function to update gravitational forces
- local function updateGravity()
- for i = 1, #spheres do
- for j = i+1, #spheres do
- local sphere1 = spheres[i]
- local sphere2 = spheres[j]
- local dx = sphere2.x - sphere1.x
- local dy = sphere2.y - sphere1.y
- local distance = math.sqrt(dx*dx + dy*dy)
- local forceMagnitude = (sphere1.mass * sphere2.mass) / (distance * distance)
- -- Normalize the direction
- local forceX = (dx / distance) * forceMagnitude
- local forceY = (dy / distance) * forceMagnitude
- -- Reverse the force if toggleRepel is true
- if toggleReversedForces then
- forceX = -forceX
- forceY = -forceY
- end
- -- Apply the force
- sphere1:applyForce(forceX, forceY, sphere1.x, sphere1.y)
- sphere2:applyForce(-forceX, -forceY, sphere2.x, sphere2.y)
- end
- end
- end
- -- Create screen boundaries that fit any screen size
- local function createWalls()
- if toggleLeftWall then
- local leftWall = display.newRect(display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight + (display.actualContentHeight/2))
- physics.addBody(leftWall, "static")
- end
- if toggleRightWall then
- local rightWall = display.newRect(display.actualContentWidth + display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight + (display.actualContentHeight/2))
- physics.addBody(rightWall, "static")
- end
- if toggleTopWall then
- local topWall = display.newRect(display.contentCenterX, display.screenOriginY, display.actualContentWidth + (display.actualContentWidth/2), 1)
- physics.addBody(topWall, "static")
- end
- if toggleBottomWall then
- local bottomWall = display.newRect(display.contentCenterX, display.actualContentHeight + display.screenOriginY, display.actualContentWidth + (display.actualContentWidth/2), 1)
- physics.addBody(bottomWall, "static")
- end
- end
- -- Function to create a Portal-like wrap-around effect
- local function wrapAroundScreen(object)
- local buffer = object.width * wrapBuffer -- Buffer to ensure the circle is fully off-screen before wrapping
- local leftBoundary = display.screenOriginX
- local rightBoundary = display.actualContentWidth + display.screenOriginX
- local topBoundary = display.screenOriginY
- local bottomBoundary = display.actualContentHeight + display.screenOriginY
- -- Check if any part of the object is beyond the screen boundary
- if object.x - buffer > rightBoundary then
- object.x = leftBoundary - buffer + (object.x - buffer - rightBoundary)
- elseif object.x + buffer < leftBoundary then
- object.x = rightBoundary + buffer - (leftBoundary - (object.x + buffer))
- end
- if object.y - buffer > bottomBoundary then
- object.y = topBoundary - buffer + (object.y - buffer - bottomBoundary)
- elseif object.y + buffer < topBoundary then
- object.y = bottomBoundary + buffer - (topBoundary - (object.y + buffer))
- end
- end
- -- Modify the enterFrame event to include the Portal-like wrap-around logic
- local function onEnterFrame(event)
- for _, sphere in ipairs(spheres) do
- wrapAroundScreen(sphere)
- end
- --[[
- updateGravity() -- Keep the original gravity update logic if needed
- --]]
- end
- -- Function to generate a random number of circles with random properties
- local function generateRandomCircles()
- local numCircles = numRandomShapes -- Random number of circles
- for i = 1, numCircles do
- local radius = ((math.random(radiusMin, radiusMax))*scale) -- Random radius
- local mass = ((radius * circleMass)*scale) -- Mass proportional to radius, adjust as needed
- local x = math.random(radius, display.actualContentWidth - radius) -- Random x position, ensuring circle stays on screen
- local y = math.random(radius, display.actualContentHeight - radius) -- Random y position, ensuring circle stays on screen
- createSphere(x, y, radius, mass)
- end
- end
- -- Function to generate a random number of polygons with random properties
- local function generateRandomPolygons()
- local numPolygons = numRandomShapes -- Random number of polygons
- for i = 1, numPolygons do
- local radius = ((math.random(radiusMin, radiusMax))*scale) -- Random radius
- local mass = ((radius * polygonMass)*scale) -- Mass proportional to radius, adjust as needed
- local x = math.random(radius, display.actualContentWidth - radius) -- Random x position, ensuring polygon stays on screen
- local y = math.random(radius, display.actualContentHeight - radius) -- Random y position, ensuring polygon stays on screen
- createPolygon(x, y, radius, mass)
- end
- end
- -- Togglable Functions
- -- Create walls
- if toggleWalls then
- createWalls() -- Disable for portal-like wrapping
- end
- -- Call the function to generate random circles
- if toggleRandomCircles and toggleCircles then
- generateRandomCircles()
- end
- -- Create starting circle
- if toggleStartingCircle and toggleCircles then
- createCircle(startingXpos, startingYpos, startingCircleRadius, startingCircleMass)
- end
- -- Call the function to spawn the starting circles
- if toggleCustomCircles and toggleCircles then
- spawnStartingCircles()
- end
- -- Call the function to generate random polygons
- if toggleRandomPolygons and togglePolygons then
- generateRandomPolygons()
- end
- -- Create starting polygon
- if toggleStartingPolygon and togglePolygons then
- createStartingPolygon(startingXpos, startingYpos, startingPolygonRadius, startingPolygonMass)
- end
- -- Call the function to spawn the starting polygons
- if toggleCustomPolygons and togglePolygons then
- spawnStartingPolygons(startingXpos, startingYpos, startingPolygonRadius, startingPolygonMass)
- end
- -- Update gravity every frame
- if toggleForces then
- Runtime:addEventListener("enterFrame", updateGravity)
- end
- -- [[ Object wrapping (Infinite space)
- if toggleBodyWrap then
- Runtime:addEventListener("enterFrame", onEnterFrame)
- end
- ----< | End of Main Program | >----
- ----> | Music Player | <----
- local function bgMusic()
- local audioFiles = {
- "Miami.mp3",
- "Light_Flow.mp3",
- "Here_You_Go.mp3",
- }
- -- Function to play a random audio file
- local function playRandomAudio()
- math.randomseed(os.time())
- -- Choose a random audio file
- local randomIndex = math.random(#audioFiles)
- local randomAudioFile = audioFiles[randomIndex]
- -- Load and play the audio file
- local sound = audio.loadSound(randomAudioFile)
- audio.setVolume(musicVolume) -- Ensure the volume is set to maximum
- audio.play(sound)
- end
- playRandomAudio()
- end
- if toggleMusic then
- bgMusic()
- end
- ----< | End of Music Player | >----
- -- ( PATCHNOTES & VERSION INFO ) --
- print(" ")
- print("Orbit Beta v1.3.5 May 24 2024 (Polygon) Edition has initialized. Updates are available on the Pastbin: https://pastebin.com/qixBZPLH")
- print(" ")
- print("[ Patchnote 1.3.5 ]")
- print("|- Added a debug mode for shapes")
- print("|- Fixed randomCirclesBounce")
- print("|- Universalized startingXpos and Ypos for starting circles and polygons")
- print("|- Fixed randomCirclesBounce")
- print("|- Fixed objects teleporting to the roof when one of the walls are disabled")
- print("|- Added some background music :)")
- print("|- If you want the music files, download them here:")
- print(" Miami (Tom Fox) - https://drive.google.com/file/d/1atp9hoW1aWF5nUQKcnv7xIzkK6n4MCWF/view?usp=sharing")
- print(" Light Flow (Tom Fox) - https://drive.google.com/file/d/1atp9hoW1aWF5nUQKcnv7xIzkK6n4MCWF/view?usp=sharing")
- print(" Here You Go (Tom Fox) - https://drive.google.com/file/d/1mx7Bpa7Jw_o0ZZqcYkFniZarE2kYcAt5/view?usp=sharing")
- print(" ")
- 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. ]")
Advertisement
Comments
-
Comment was deleted
-
- new version:
- -- Initialize physics
- local physics = require("physics")
- physics.start()
- physics.setGravity(0, 0) -- Set gravity to 0
- -- Core Variables
- local screenW = display.contentWidth
- local screenH = display.contentHeight
- scale = math.random(1.25, 1.50) -- Factor to propotionally resize objects, size and mass included
- throwAmplifier = 0.075 -- Factor in which how fast an object will be after throwing or flicking it
- dampingAmplifier = 0.25 -- Factor to simulate drag or air resistance (set to 0 for cosmic simulations)
- -- Table to keep track of spheres
- local spheres = {}
- -- [[ Starting Circle with fixed size & mass for experimentations
- local function createCircle(x, y, radius, mass)
- local circle = display.newCircle(x, y, radius)
- physics.addBody(circle, {radius=radius, density=mass/(math.pi*radius*radius), bounce=0.5})
- circle.mass = mass
- table.insert(spheres, circle)
- -- Make spheres draggable
- function sphere:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- self.movementHistory = {} -- Array to store past positions and times
- -- Stop the sphere's movement
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- -- Record movement history
- table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
- -- Clean up old movement history
- local currentTime = system.getTimer()
- local cutOffTime = currentTime - 1000
- for i, record in ipairs(self.movementHistory) do
- if record.time < cutOffTime then
- table.remove(self.movementHistory, i)
- end
- end
- elseif event.phase == "ended" or event.phase == "cancelled" then
- -- Released
- local endTime = system.getTimer()
- local distance = 0
- local throwForce = 0
- -- Calculate distance based on movement history
- if #self.movementHistory >= 2 then
- local lastRecord = self.movementHistory[#self.movementHistory]
- local prevRecord = self.movementHistory[#self.movementHistory - 1]
- distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
- throwForce = distance * throwAmplifier / (endTime - prevRecord.time)
- end
- local vx = (event.x - self.markX) * throwForce * dampingAmplifier
- local vy = (event.y - self.markY) * throwForce * dampingAmplifier
- -- Apply linear impulse
- self:applyLinearImpulse(vx, vy, self.x, self.y)
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- end
- return true
- end
- circle:addEventListener("touch", circle)
- return circle
- end
- --]]
- -- Function to create a new sphere with a random color and trail
- local function createSphere(x, y, radius, mass)
- -- Random color components
- local r = math.random()
- local g = math.random()
- local b = math.random()
- local sphere = display.newCircle(x, y, radius)
- sphere:setFillColor(r, g, b) -- Set the random color
- physics.addBody(sphere, {radius=radius, density=mass/(math.pi*radius*radius), bounce=math.random(0.0, 0.5)})
- sphere.mass = mass
- table.insert(spheres, sphere)
- -- [[ Trail effect
- local trailGroup = display.newGroup()
- function sphere:enterFrame(event)
- local trail = display.newCircle(trailGroup, self.x, self.y, radius * 0.3)
- trail:setFillColor(r, g, b, 0.5) -- Slightly transparent version of the sphere's color
- transition.to(trail, {time=500, alpha=0, onComplete=function() display.remove(trail) end})
- end
- --]]
- Runtime:addEventListener("enterFrame", sphere)
- -- Make spheres draggable
- function sphere:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- self.movementHistory = {} -- Array to store past positions and times
- -- Stop the sphere's movement
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- -- Record movement history
- table.insert(self.movementHistory, {time = system.getTimer(), x = event.x, y = event.y})
- -- Clean up old movement history
- local currentTime = system.getTimer()
- local cutOffTime = currentTime - 1000
- for i, record in ipairs(self.movementHistory) do
- if record.time < cutOffTime then
- table.remove(self.movementHistory, i)
- end
- end
- elseif event.phase == "ended" or event.phase == "cancelled" then
- -- Released
- local endTime = system.getTimer()
- local distance = 0
- local throwForce = 0
- -- Calculate distance based on movement history
- if #self.movementHistory >= 2 then
- local lastRecord = self.movementHistory[#self.movementHistory]
- local prevRecord = self.movementHistory[#self.movementHistory - 1]
- distance = math.sqrt((lastRecord.x - prevRecord.x) ^ 2 + (lastRecord.y - prevRecord.y) ^ 2)
- throwForce = distance * throwAmplifier / (endTime - prevRecord.time)
- end
- local vx = (event.x - self.markX) * throwForce * dampingAmplifier
- local vy = (event.y - self.markY) * throwForce * dampingAmplifier
- -- Apply linear impulse
- self:applyLinearImpulse(vx, vy, self.x, self.y)
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- end
- return true
- end
- sphere:addEventListener("touch", sphere)
- return sphere
- end
- -- [[ Function to update gravitational forces
- local function updateGravity()
- for i = 1, #spheres do
- for j = i+1, #spheres do
- local sphere1 = spheres[i]
- local sphere2 = spheres[j]
- local dx = sphere2.x - sphere1.x
- local dy = sphere2.y - sphere1.y
- local distance = math.sqrt(dx*dx + dy*dy)
- local force = (sphere1.mass * sphere2.mass) / (distance * distance)
- local forceX = force * (dx / distance)
- local forceY = force * (dy / distance)
- sphere1:applyForce(forceX, forceY, sphere1.x, sphere1.y)
- sphere2:applyForce(-forceX, -forceY, sphere2.x, sphere2.y)
- end
- end
- end
- --]]
- -- Create screen boundaries that fit any screen size
- local function createWalls()
- local leftWall = display.newRect(display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
- local rightWall = display.newRect(display.actualContentWidth + display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
- local topWall = display.newRect(display.contentCenterX, display.screenOriginY, display.actualContentWidth, 1)
- local bottomWall = display.newRect(display.contentCenterX, display.actualContentHeight + display.screenOriginY, display.actualContentWidth, 1)
- physics.addBody(leftWall, "static")
- physics.addBody(rightWall, "static")
- physics.addBody(topWall, "static")
- physics.addBody(bottomWall, "static")
- end
- -- Function to generate a random number of circles with random properties
- local function generateRandomCircles()
- local numCircles = math.random(2, 12) -- Random number of circles between 2 and 10
- for i = 1, numCircles do
- local radius = (math.random(math.random(8, 13), math.random(15, 25)))*scale -- Random radius between 5 and 20
- local mass = (radius * math.random(1, 12))*scale -- Mass proportional to radius, adjust as needed
- local x = math.random(radius, screenW - radius) -- Random x position, ensuring circle stays on screen
- local y = math.random(radius, screenH - radius) -- Random y position, ensuring circle stays on screen
- createSphere(x, y, radius, mass)
- end
- end
- -- Call the function to generate random circles
- generateRandomCircles()
- -- Create walls
- createWalls()
- -- Create starting circle
- --createCircle(160, 240, 25, 25)
- -- Update gravity every frame
- Runtime:addEventListener("enterFrame", updateGravity)
-
- PREVIOUS VERSION OF ORBIT:
- -- Initialize physics
- local physics = require("physics")
- physics.start()
- physics.setGravity(0, 0) -- Set gravity to 0
- -- Core Variables
- local screenW = display.contentWidth
- local screenH = display.contentHeight
- scale = 0.75 -- Factor to propotionally resize objects, size and mass included
- -- Table to keep track of spheres
- local spheres = {}
- -- [[ Starting Circle with fixed size & mass for experimentations
- local function createCircle(x, y, radius, mass)
- local circle = display.newCircle(x, y, radius)
- physics.addBody(circle, {radius=radius, density=mass/(math.pi*radius*radius), bounce=0.5})
- circle.mass = mass
- table.insert(spheres, circle)
- -- Make spheres draggable and stop their movement while dragging
- function circle:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- -- Stop the sphere's movement
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- elseif event.phase == "ended" or event.phase == "cancelled" then
- -- Released
- local endTime = system.getTimer()
- local timePassed = endTime - self.startTime
- local vx = (event.x - self.markX) / timePassed
- local vy = (event.y - self.markY) / timePassed
- -- Apply the linear impulse based on the calculated velocity
- self:applyLinearImpulse(vx * 0.1, vy * 0.1, self.x, self.y)
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- end
- return true
- end
- circle:addEventListener("touch", circle)
- return circle
- end
- --]]
- -- Function to create a new sphere with a random color and trail
- local function createSphere(x, y, radius, mass)
- -- Random color components
- local r = math.random()
- local g = math.random()
- local b = math.random()
- local sphere = display.newCircle(x, y, radius)
- sphere:setFillColor(r, g, b) -- Set the random color
- physics.addBody(sphere, {radius=radius, density=mass/(math.pi*radius*radius), bounce=math.random(0.0, 0.65)})
- sphere.mass = mass
- table.insert(spheres, sphere)
- --[[ Trail effect
- local trailGroup = display.newGroup()
- function sphere:enterFrame(event)
- local trail = display.newCircle(trailGroup, self.x, self.y, radius * 0.3)
- trail:setFillColor(r, g, b, 0.5) -- Slightly transparent version of the sphere's color
- transition.to(trail, {time=500, alpha=0, onComplete=function() display.remove(trail) end})
- end
- --]]
- Runtime:addEventListener("enterFrame", sphere)
- -- Make spheres draggable and stop their movement while dragging
- function sphere:touch(event)
- if event.phase == "began" then
- -- Initial touch
- display.getCurrentStage():setFocus(self, event.id)
- self.isFocus = true
- self.markX = self.x
- self.markY = self.y
- self.startTime = system.getTimer()
- -- Stop the sphere's movement
- self:setLinearVelocity(0, 0)
- self.angularVelocity = 0
- elseif self.isFocus then
- if event.phase == "moved" then
- -- Dragging
- self.x = event.x - event.xStart + self.markX
- self.y = event.y - event.yStart + self.markY
- elseif event.phase == "ended" or event.phase == "cancelled" then
- -- Released
- local endTime = system.getTimer()
- local timePassed = endTime - self.startTime
- local vx = (event.x - self.markX) / timePassed
- local vy = (event.y - self.markY) / timePassed
- -- Apply the linear impulse based on the calculated velocity
- self:applyLinearImpulse(vx * 0.1, vy * 0.1, self.x, self.y)
- display.getCurrentStage():setFocus(self, nil)
- self.isFocus = false
- end
- end
- return true
- end
- sphere:addEventListener("touch", sphere)
- return sphere
- end
- -- [[ Function to update gravitational forces
- local function updateGravity()
- for i = 1, #spheres do
- for j = i+1, #spheres do
- local sphere1 = spheres[i]
- local sphere2 = spheres[j]
- local dx = sphere2.x - sphere1.x
- local dy = sphere2.y - sphere1.y
- local distance = math.sqrt(dx*dx + dy*dy)
- local force = (sphere1.mass * sphere2.mass) / (distance * distance)
- local forceX = force * (dx / distance)
- local forceY = force * (dy / distance)
- sphere1:applyForce(forceX, forceY, sphere1.x, sphere1.y)
- sphere2:applyForce(-forceX, -forceY, sphere2.x, sphere2.y)
- end
- end
- end
- --]]
- -- Create screen boundaries that fit any screen size
- local function createWalls()
- local leftWall = display.newRect(display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
- local rightWall = display.newRect(display.actualContentWidth + display.screenOriginX, display.contentCenterY, 1, display.actualContentHeight)
- local topWall = display.newRect(display.contentCenterX, display.screenOriginY, display.actualContentWidth, 1)
- local bottomWall = display.newRect(display.contentCenterX, display.actualContentHeight + display.screenOriginY, display.actualContentWidth, 1)
- physics.addBody(leftWall, "static")
- physics.addBody(rightWall, "static")
- physics.addBody(topWall, "static")
- physics.addBody(bottomWall, "static")
- end
- -- Function to generate a random number of circles with random properties
- local function generateRandomCircles()
- local numCircles = math.random(2, 12) -- Random number of circles between 2 and 10
- for i = 1, numCircles do
- local radius = (math.random(math.random(8, 13), math.random(15, 25)))*scale -- Random radius between 5 and 20
- local mass = (radius * math.random(1, 12))*scale -- Mass proportional to radius, adjust as needed
- local x = math.random(radius, screenW - radius) -- Random x position, ensuring circle stays on screen
- local y = math.random(radius, screenH - radius) -- Random y position, ensuring circle stays on screen
- createSphere(x, y, radius, mass)
- end
- end
- -- Call the function to generate random circles
- generateRandomCircles()
- -- Create walls
- createWalls()
- -- Create starting circle
- --createCircle(160, 240, 25, 25)
- -- Update gravity every frame
- Runtime:addEventListener("enterFrame", updateGravity)
Add Comment
Please, Sign In to add comment
Advertisement