https://www.roblox.com/games/4519631442/Bloxy-Roads#!/game-instances
Hours of critical thinking and trial and error.
https://www.roblox.com/games/4519631442/Bloxy-Roads#!/game-instances
Hours of critical thinking and trial and error.
I played a round of it and I can say that’s really amazing.
Nice to see even AI’S could be racing with players.
Gives me some Mario Kart vibes playing this.
Keep up the great work.
Mario kart with destruction physics
Here’s the script so far if you guys want to check it out. I’m giving it for free for those who might be struggling with AI cars or whatnot <3
local CurrentNode = nil
local NodeIndex = 0
local Nodes = {}
function GetNodes(Map)
local FakeNodes = Map:FindFirstChild("AIPath"):GetChildren()
-- you have the table.
-- you want to get the names of the table.
-- convert the names to numbers
-- find the one
local num = 0
repeat wait()
num = num + 1
for i,v in pairs(FakeNodes) do
if tonumber(v.Name) == num and (not table.find(Nodes, v)) then
table.insert(Nodes, v)
-- print(num, v.Name)
-- print(#Nodes, #FakeNodes)
end
end
until #Nodes == #FakeNodes
--print(#Nodes)
end
repeat wait() until script.Parent.Humanoid.SeatPart
local Car = script.Parent.Humanoid.SeatPart.Parent
--print("I'm driving this car "..Car.Name)
repeat wait() until game.ServerScriptService["Car Stiff"].Map.Value ~= nil
--print("wow")
-- add a coroutine while loop for constantly checking the surroundings for crash logic avoiding.
-- if the car is stuck and it cannot go left or right or to the front then it reverses towards the last node.
-- steering too.
local char = script.Parent
GetNodes(game.ServerScriptService["Car Stiff"].Map.Value)
local path = game.ServerScriptService["Car Stiff"].Map.Value:FindFirstChild("AIPath", true)
--print(#Nodes)
--print("okay let's go!")
function Throttle(num)
if Car.VehicleSeat.Throttle == num then return end
Car.VehicleSeat.Throttle = num
end
function Steer(num)
if Car.VehicleSeat.Steer == num then return end
Car.VehicleSeat.Steer = num
end
if NodeIndex == 0 then
NodeIndex = NodeIndex + 1
end
local evade = false
coroutine.wrap(function() -- avoidance logic
while script.Parent.Humanoid.SeatPart do
wait(.5)
local rayOrigin = Car.VehicleSeat.Position + Car.VehicleSeat.CFrame.LookVector
local rayDirection = Car.VehicleSeat.CFrame.LookVector * 30
-- Build a "RaycastParams" object and cast the ray
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {char.Head.Parent, Car }
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if raycastResult and (raycastResult.Instance.Size.Magnitude < 40 and (raycastResult.Instance.Name ~= "Landscape" or raycastResult.Instance.Name ~= "Road" )) then
--print("There's an obstacle in front of me")
local rrayOrigin = Car.VehicleSeat.Position + Car.VehicleSeat.CFrame.LookVector
local rrayDirection = CFrame.fromAxisAngle(Vector3.new(0,1,0), math.rad(20)) * Car.VehicleSeat.CFrame.LookVector *30
-- Build a "RaycastParams" object and cast the ray
local rraycastParams = RaycastParams.new()
rraycastParams.FilterDescendantsInstances = {char.Head.Parent, Car }
rraycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local rraycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if rraycastResult and (rraycastResult.Instance.Size.Magnitude < 40 and (rraycastResult.Instance.Name ~= "Landscape" or rraycastResult.Instance.Name ~= "Road" )) then
-- print("I can't turn to the right so i'll check the left")
else
evade = true
Steer(-1)
wait(1)
evade = false
end
local lrayOrigin = Car.VehicleSeat.Position + Car.VehicleSeat.CFrame.LookVector
local lrayDirection = CFrame.fromAxisAngle(Vector3.new(0,1,0), math.rad(-20)) * Car.VehicleSeat.CFrame.LookVector * 30
-- Build a "RaycastParams" object and cast the ray
local lraycastParams = RaycastParams.new()
lraycastParams.FilterDescendantsInstances = {char.Head.Parent, Car }
lraycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local lraycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if lraycastResult and (lraycastResult.Instance.Size.Magnitude < 40 and (lraycastResult.Instance.Name ~= "Landscape" or lraycastResult.Instance.Name ~= "Road" )) then
-- print("I can't turn to the left so i'll check to the right")
evade = true
Throttle(-1)
Steer(0)
wait(1.5)
evade = false
else
evade = true
Steer(1)
wait(1)
evade = false
end
end
end
end)()
CurrentNode = path:FindFirstChild("1")
local cframe = nil
local OffCourse = false
local OldNode = nil
coroutine.wrap(function()
repeat wait() until cframe
while true do
OldNode = CurrentNode
wait(1)
repeat wait(.5) until Car.VehicleSeat.Velocity.Magnitude < 10 or OffCourse == true
local stuck = false
for i = 1,30 do
wait(.1)
if i < 30 and Car.VehicleSeat.Velocity.Magnitude > 10 then
stuck = false
break
end
if i == 30 then
stuck = true
end
end
if (CurrentNode == OldNode and script.Parent.Head.Velocity.Magnitude < 5 and evade == false and stuck == true) or OffCourse == true then
evade = true
Throttle(-1)
Steer(0)
wait(math.random(1,3))
NodeIndex = NodeIndex
local count = 0
repeat
if Car.VehicleSeat.CFrame:ToObjectSpace(CurrentNode.CFrame).X > 0 then
Steer(-1)
-- print("I'm reversing to the left")
elseif Car.VehicleSeat.CFrame:ToObjectSpace(CurrentNode.CFrame).X <= 0 then
Steer(1)
-- print("I'm reversing to the right")
end
wait()
count = count + 1
if Car.VehicleSeat.Velocity.Magnitude > 40 then
Throttle(1)
elseif Car.VehicleSeat.Velocity.Magnitude < 40 then
Throttle(-1)
end
if count > 1300 and CurrentNode == OldNode then
-- print("time to look for previous node")
NodeIndex = NodeIndex - 1
CurrentNode = FindNextNearestNode(NodeIndex)
break
end
until Car.VehicleSeat.CFrame:ToObjectSpace(CurrentNode.CFrame).Z < 0
-- print("ALRIGHT LET'S GO!!!!")
OffCourse = false
NodeIndex = NodeIndex + 1
CurrentNode = FindNextNearestNode(NodeIndex)
evade = false
stuck = false
--print("I suck at racing")
end
end
end)()
local checkifoffcourse = false
local topspeed = 180 + (6) * (Car.Level.Value ) - 1
local ImustDecideWhichPathToTake = false
local Followingstraightpath = true
local Factor = 10
local Exp = nil
for i,v in pairs(Car:GetDescendants()) do
if v:IsA("HingeConstraint") and v.ActuatorType == Enum.ActuatorType.Servo and v.ServoMaxTorque > 10000 then
Steer(1)
Exp = v
break
end
end
--print(math.abs(Exp.TargetAngle).." is the target angle of this car")
local Coo = 0
repeat
Coo = Coo + 1
wait(.1)
until Exp or Coo > math.random(10,40)
if Exp then
Factor = math.abs(Exp.TargetAngle)
elseif Exp == nil then
Factor = 18
end
Steer(0)
local SpeedNecessary = 0
local truespeednec = 0
local Check = {}
function FindNextNearestNode(index)
local Node = nil
local NearestDist = 100000
for i, d in pairs(Nodes) do
if (Car.VehicleSeat.Position - d.Position).Magnitude < NearestDist and tonumber(d.Name) == index then
Node = d
NearestDist = (Car.VehicleSeat.Position - d.Position).Magnitude
end
end
if Node == nil then
Node = path:FindFirstChild("1")
NodeIndex = 1
end
NearestDist = nil
return Node
end
local PredictedPath = nil
local CarSpeed = nil
while script.Parent.Humanoid.Health > 0 and script.Parent.Humanoid.SeatPart and script.Parent:FindFirstChild("Head") do
game:GetService("RunService").Heartbeat:Wait()
print(Car.Name.. " is trying to reach "..CurrentNode.Name .." which is ".. (CurrentNode.Position - Car.VehicleSeat.Position).Magnitude .." studs away")
if CurrentNode == nil then
CurrentNode = path:FindFirstChild("1")
end
local Val = CurrentNode.CFrame + Vector3.new(math.random(-20,20),0,math.random(-20,20))
Throttle(1)
-- print(NodeIndex)
SpeedNecessary = ((CurrentNode.Position - FindNextNearestNode(NodeIndex+1).Position ).Magnitude )/(( 20 / Factor))
repeat wait(.025)-- game:GetService("RunService").Heartbeat:Wait()
if evade == false then
cframe = Car.VehicleSeat.CFrame:ToObjectSpace(Val)
--print(CurrentNode.Name.." is the target")
--print(Car.VehicleSeat.AssemblyAngularVelocity.Magnitude)
PredictedPath = (Car.VehicleSeat.CFrame + Car.VehicleSeat.Velocity):ToObjectSpace(Val)
-- print(cframe.X.." car is steering "..Car.VehicleSeat.Steer)
if cframe.X + (Car.VehicleSeat.Velocity.X * 0.25) > (45 ) then
coroutine.wrap(function()
if Car.VehicleSeat.Steer == 1 then return end
Steer(1)
-- print("steer to the right now!")
repeat game:GetService("RunService").Heartbeat:Wait() Steer(1) until Car.VehicleSeat.CFrame:ToObjectSpace(Val).X + (Car.VehicleSeat.Velocity.X * 0.1) <30
-- print("I'm aligned to the right")
Steer(0)
end)()
elseif cframe.X + (Car.VehicleSeat.Velocity.X * 0.25) < -(45 ) then
-- print("Node is to left of player!")
coroutine.wrap(function()
if Car.VehicleSeat.Steer == -1 then return end
Steer(-1)
-- print("Steer to the left")
repeat game:GetService("RunService").Heartbeat:Wait() Steer(-1) until Car.VehicleSeat.CFrame:ToObjectSpace(Val).X + (Car.VehicleSeat.Velocity.X * 0.1) >-30
-- print("I'm aligned to the left")
Steer(0)
end)()
elseif cframe.X > -45 and cframe.X < 45 and Car.VehicleSeat.Brakes.Value == false then
Steer(0)
if Car.VehicleSeat.Throttle ~= 1 then
Throttle(1)
end
end
-- print(value.." is what we'll go for")
if SpeedNecessary == 0 then
SpeedNecessary = topspeed
end
CarSpeed = Car.VehicleSeat.Velocity.Magnitude
--print(SpeedNecessary , CarSpeed .." reaching for "..value.." node")
truespeednec = SpeedNecessary
if SpeedNecessary > topspeed * 2 then
SpeedNecessary = topspeed * 2
end
if OffCourse == false and (Car.VehicleSeat.CFrame):ToObjectSpace(FindNextNearestNode(NodeIndex).CFrame).Z > 0 and (Car.VehicleSeat.Velocity.Magnitude < 10) and checkifoffcourse == false and (Car.VehicleSeat.CFrame):ToObjectSpace(FindNextNearestNode(NodeIndex + 1).CFrame).Z > 0 then
-- print("Am I going off course?")
checkifoffcourse = true
Throttle(0)
coroutine.wrap(function()
wait(3)
if checkifoffcourse == true and (Car.VehicleSeat.CFrame):ToObjectSpace(FindNextNearestNode(NodeIndex).CFrame).Z > 0 and (Car.VehicleSeat.Velocity.Magnitude < 10) and (Car.VehicleSeat.CFrame):ToObjectSpace(FindNextNearestNode(NodeIndex + 1).CFrame).Z > 0 then
OffCourse = true
print("Looks like im going off course")
end
checkifoffcourse = false
end)()
end
-- print("car is off course: "..tostring(OffCourse))
-- print(Car.Name.." should go to speed: "..SpeedNecessary)
if OffCourse == false then
if CarSpeed < SpeedNecessary *1.75 then
--print(CarSpeed.." is speed of "..Car.Name)
Throttle(1)
Car.VehicleSeat.Brakes.Value = false
elseif CarSpeed > SpeedNecessary * 2 then
Throttle(0)
coroutine.wrap(function()
if Car.VehicleSeat.Brakes.Value == false then
Car.VehicleSeat.Brakes.Value = true
repeat wait() until CarSpeed < SpeedNecessary * 1.25
end
end)()
Car.VehicleSeat.Boost.Value = false
elseif CarSpeed < SpeedNecessary * 2 and CarSpeed > SpeedNecessary * 1.75 then
Throttle(0)
Car.VehicleSeat.Boost.Value = false
end
if (Car.VehicleSeat.Position - CurrentNode.Position).Magnitude > topspeed * 0.5 then
Car.VehicleSeat.Boost.Value = true
elseif (Car.VehicleSeat.Position - CurrentNode.Position).Magnitude < topspeed * 0.5 then
Car.VehicleSeat.Boost.Value = false
end
end
if math.abs(Car.VehicleSeat.AssemblyAngularVelocity.Y) > 2.4 then
--Car.VehicleSeat.Brakes.Value = true
print("Steering too fast")
repeat wait() Steer(0) until math.abs(Car.VehicleSeat.AssemblyAngularVelocity.Y) < 2
-- Car.VehicleSeat.Brakes.Value = false
end
end
-- print(Car.Name.." tries reaching: ".. CurrentNode.Name, math.abs(cframe.X), math.abs(cframe.Z))
--print((Val.Position - Car.VehicleSeat.Position).Magnitude)
until Car.VehicleSeat.CFrame:ToObjectSpace(Val).Z > math.random(-20,5) and (Val.Position - Car.VehicleSeat.Position).Magnitude < 200
NodeIndex = NodeIndex + 1
-- if there aren't other of those same node values it means
CurrentNode = FindNextNearestNode(NodeIndex)
print("I'm now moving to "..CurrentNode.Name.." yay")
end
i wish my math brain is yours
Here… All you need to do when making AI is to define the environment.
Define where it is and where it should be.
Define what it has to do with what it already knows.
If it doesn’t know something, teach it. Lol but still it’s really hard you’d need to work in cooperation with others.
Honestly the brainstorming part is the hard part.