How to make a biliard

I want to make this biliard for my roblox game. And i have no idea how it is calculating that after hit movement.

this

anyone can explain?

1 Like

Why would it calculate anything? Roblox physics already does that for you when you set part collision on.

i mean that after hit trajectory of the ball, the white line i mean.

Then you’ll have to look into Raycasting

Which topic exactly do i read in reaycast because i only know that you can shoot raycast from a point to a direction and it gets you the object it hits.

Read about trigonometry, you’ll need cos/sin to calculate the direction given the angles. Then you use this direction alongside the position of the white ball to raycast.

Explanation

  1. Use Spherecast to determine the ball hit by the cue ball

  2. If there was a hit:

    • Using the spherecast’s RaycastResult’s Position property, compute the unit vector describing hit direction (from the cue ball’s expected hit position to the ball)
    • Using the spherecast’s RaycastResult’s Normal property, compute the unit vector of the ball’s velocity (i.e. it’s collision response), e.g. …
      local function reflectVector(direction, normal)
      	local d = -2*normal:Dot(direction)
      	return d*normal + direction
      end
      
    • The direction from the cue ball to the hit position will be the cue ball’s trajectory, and the reflected vector will describe the collision response (the trajectory after the ball has been hit)

Example

How to use this example
  1. Insert a ball into workspace called CueBall as Parts with a size of Vector3.new(1, 1, 1) and a Shape of Enum.PartType.Ball
  2. Insert a few different balls into workspace and group them into a model called Balls (as above, should be 1x1x1 of a Ball shape)
  3. Copy the source code below into a Script and insert it into ServerScriptService
  4. Press F8 or the “Run” button to demo
  5. Rotate the CueBall instance to see the results
Source code
-- reflect a Vector3 off the normal of the given plane
local function reflectVector(direction, normal)
	local d = -2*normal:Dot(direction)
	return d*normal + direction
end


-- constants
local BALL_RADIUS = 0.5                      -- radius of the ball

local MAX_CUE_TRAJECTORY_LENGTH = 50         -- should be calculated from power
local MAX_RESPONSE_TRAJECTORY_LENGTH = 20    -- same here


-- parts relating to the game
local cueBall = workspace.CueBall
local otherBalls = workspace.Balls:GetChildren()


-- some demo parts to show the trajectory lines
local cueBallTrajectoryLine = Instance.new('Part')
cueBallTrajectoryLine.Size = Vector3.one*0.1
cueBallTrajectoryLine.Anchored = true
cueBallTrajectoryLine.CanCollide = false
cueBallTrajectoryLine.Parent = workspace

local responseTrajectoryLine = Instance.new('Part')
responseTrajectoryLine.Transparency = 1
responseTrajectoryLine.Size = Vector3.new(0.1, 0.1, MAX_RESPONSE_TRAJECTORY_LENGTH)
responseTrajectoryLine.Anchored = true
responseTrajectoryLine.CanCollide = false
responseTrajectoryLine.Parent = workspace


-- only look at intersections for balls
--
--    Note: your implementation would probably want to look at intersections
--          for the edges of the table too
--
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Include
params.FilterDescendantsInstances = otherBalls


-- example demo
game:GetService('RunService').Heartbeat:Connect(function ()
	local cueBallOrigin = cueBall.CFrame
	local targetDirection = cueBallOrigin.LookVector
	
	local cueBallRadiusOffset = targetDirection*BALL_RADIUS
	
	local result = workspace:Spherecast(cueBallOrigin.Position, BALL_RADIUS, targetDirection*MAX_CUE_TRAJECTORY_LENGTH, params)
	if result and result.Instance then
		local hitBall = result.Instance
		local hitBallPosition = hitBall.Position

		local hitNormal = result.Normal
		local hitDistance = result.Distance
		local hitPosition = result.Position
		local hitDirection = (hitPosition - hitBallPosition).Unit

		local responseDirection = reflectVector(hitDirection, hitNormal)
		responseTrajectoryLine.CFrame = CFrame.new(hitBallPosition, hitBallPosition + responseDirection) + responseDirection*MAX_RESPONSE_TRAJECTORY_LENGTH*0.5
		responseTrajectoryLine.Transparency = 0.5

		cueBallTrajectoryLine.Size = Vector3.new(0.1, 0.1, hitDistance)
		cueBallTrajectoryLine.CFrame = cueBallOrigin + cueBallRadiusOffset + targetDirection*hitDistance*0.5
	else
		responseTrajectoryLine.Transparency = 1

		cueBallTrajectoryLine.Size = Vector3.new(0.1, 0.1, MAX_CUE_TRAJECTORY_LENGTH)
		cueBallTrajectoryLine.CFrame = cueBallOrigin + cueBallRadiusOffset + targetDirection*MAX_CUE_TRAJECTORY_LENGTH*0.5
	end
	
end)

This looks great. One more thing if you can add, the line for the other ball changes its size according to how strong it’s been hit. How can i add this?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.