So I have been working on a system that has basically a ball that bounces off the wall, its working great but for some reason even when you make it go at an angle it just goes back in the same angle opposite and then back in opposite of that angle (and basically just goes back and forth forever) even tho it should have some variations and change angles like go from right to left to more right if that makes sense
Getting the normal would be hard but you could just use some basic maths to find it out, like if the ball’s position is on the right side of the gui you can just see if the X difference between the GUI and the ball is greater than zero and the same goes for left. Same goes for up and down but with Y axis.
Its going out here and its not glitching its just thinking that its following the rules
local PhysicsFrame = script.Parent
local Ball = PhysicsFrame:WaitForChild("Ball")
local Walls = PhysicsFrame:WaitForChild("Walls"):GetChildren()
local SPEED = 500
local velocity = Vector2.new(5, 1).Unit * SPEED
local RunService = game:GetService("RunService")
local function getAbsolutePosition(guiObject)
if guiObject then
return guiObject.AbsolutePosition, guiObject.AbsoluteSize
else
return Vector2.new(0, 0), Vector2.new(0, 0)
end
end
local function checkCollision(ballPos, ballSize, wallPos, wallSize)
return ballPos.X < wallPos.X + wallSize.X and
ballPos.X + ballSize.X > wallPos.X and
ballPos.Y < wallPos.Y + wallSize.Y and
ballPos.Y + ballSize.Y > wallPos.Y
end
local function reflectVelocity(wallName)
if wallName == "LeftWall" or wallName == "RightWall" then
velocity = Vector2.new(-velocity.X, velocity.Y)
elseif wallName == "TopWall" or wallName == "BottomWall" then
velocity = Vector2.new(velocity.X, -velocity.Y)
end
end
local function updatePhysics()
local deltaTime = RunService.RenderStepped:Wait()
local newPosition = Ball.Position + UDim2.new(
velocity.X * deltaTime / PhysicsFrame.AbsoluteSize.X,
0,
velocity.Y * deltaTime / PhysicsFrame.AbsoluteSize.Y,
0
)
local ballPos, ballSize = getAbsolutePosition(Ball)
local newBallPos = Vector2.new(
newPosition.X.Scale * PhysicsFrame.AbsoluteSize.X,
newPosition.Y.Scale * PhysicsFrame.AbsoluteSize.Y
)
for _, wall in pairs(Walls) do
local wallPos, wallSize = getAbsolutePosition(wall)
if checkCollision(newBallPos, ballSize, wallPos, wallSize) then
reflectVelocity(wall.Name)
break
end
end
newPosition = UDim2.new(
math.clamp(newPosition.X.Scale, 0, 1 - Ball.Size.X.Scale),
0,
math.clamp(newPosition.Y.Scale, 0, 1 - Ball.Size.Y.Scale),
0
)
Ball.Position = newPosition
end
RunService.RenderStepped:Connect(updatePhysics)
local function CheckCollissions(Gui1:GuiObject,Gui2:GuiObject)
local Gui1_TopLeft,Gui2_TopLeft = Gui1.AbsolutePosition,Gui2.AbsolutePosition
local Gui1_BottomRight,Gui2_BottomRight = Gui1_TopLeft + Gui1.AbsoluteSize,Gui2_TopLeft + Gui2.AbsoluteSize
return Gui1_BottomRight.X > Gui2_TopLeft.X and Gui1_BottomRight.Y > Gui2_TopLeft.Y and Gui1_TopLeft.Y < Gui2_BottomRight.Y and Gui1_TopLeft.X < Gui2_BottomRight.X
end
Here is mine, it’s correct.
Maybe. But just try out my version to see if it works.
That’s because of your bouncing code part, The ball simply doesn’t get enough time to get out of collission to continue it’s path. I think a neat fix to this would be just blacklist said wall until the projectile collides again. Something like:
local blackLists = {}
local function reflectVelocity(wallName)
if table.find(blackLists,wallName) then return end
table.clear(blackLists)
table.insert(blackLists,wallName)
if wallName == "LeftWall" or wallName == "RightWall" then
velocity = Vector2.new(-velocity.X, velocity.Y)
elseif wallName == "TopWall" or wallName == "BottomWall" then
velocity = Vector2.new(velocity.X, -velocity.Y)
end
end