Raycast Help

In the game that I am making, I want to use raycast to find an object with a rigid body attached to it, but I don’t know what code to write if a rigid body is found, and if so, what to write next. Here’s the code that I have done so far:

– Fruit & Blobs

—function setup()
– Create a new craft scene
scene = craft.scene()
scene.physics.gravity = vec3(0, 0, 0)
day = readText(asset.builtin.Environments.Sunny)
env = craft.cubeTexture(json.decode(day))
scene.sky.material.envMap = env
cameraYPos = {x = 0, y = 0, z = 0}
playerXPos = 0
viewer.mode = FULLSCREEN

-- Create a new entity
local e = scene:entity()
body = e:add(craft.rigidbody)
e.model = craft.model(asset.builtin.Primitives.Capsule)
e.x = 0.15
e.y = 0
e.z = -2 
e.scale = vec3(1, 1, 1) / 8

scene.camera.z = -0.1

end

—function touched(touch)
if touch.state == MOVING then
scene.camera.eulerAngles = vec3(0, cameraYPos.y, 0)

    cameraYPos.y = cameraYPos.y + -1
    playerXPos = playerXPos + 1
end

if touch.state == BEGAN then
    scene.physics:raycast(vec3(0, 0, 0), vec3(0, 0, 5), 100)
end

end

—function update(dt)
– Update the scene (physics, transforms etc)
scene:update(dt)
end

– Called automatically by codea
—function draw()
update(DeltaTime)

-- Draw the scene
scene:draw()	

end

@Creator27 Heres a raycast example I have. Move the slider to move the raycast line across the circles.

viewer.mode=STANDARD
    

function setup()    
    parameter.integer("x",-300,WIDTH+300,-300)    
    nbr=15
    tab={}
    for z=1,nbr do
        p1=physics.body(CIRCLE,20)
        p1.type=STATIC
        p1.x=math.random(100,WIDTH-100)
        p1.y=math.random(HEIGHT/2,HEIGHT)
        table.insert(tab,p1)
    end
    stroke(255)
    strokeWidth(2)
    fill(255)
end

function draw()
    background(40, 40, 50)    
    for z=1,nbr do
        ellipse(tab[z].x,tab[z].y,40)
    end    
    line(WIDTH/2,0,x,1000)   
    size=0    
    ta=physics.raycastAll(vec2(WIDTH/2,0),vec2(x,1000))
    if ta~=nil then
        size=#ta
    end
    text("# crossed "..size,WIDTH/2,200)
end

@dave1707, thank you for that example. I did, however, forget to mention that it was a 3D Craft game, not like a 2d game. Is there any way to use raycasts properly in a 3D game, and bring back a result like in your example?

@Creator27 Look under Craft,Physics for ray cast. It gives you the parameters for 3D. Probably just like what I show for 2D, but for Craft 3D.

@dave1707, I don’t think it’s the parameters, as I copied a bit of your code and altered it a bit, but I still am baffled on what to do as I’m not the best at fixing problems. At the moment, here’s the code that I have written:

– Fruit & Blobs

—-function setup()
– Create a new craft scene
scene = craft.scene()
scene.physics.gravity = vec3(0, 0, 0)
day = readText(asset.builtin.Environments.Sunny)
env = craft.cubeTexture(json.decode(day))
scene.sky.material.envMap = env
cameraYPos = {x = 0, y = 0, z = 0}
playerXPos = 0
objectsFound = 0
parameter.integer(“x”,-300,WIDTH+300,-300)
viewer.mode = FULLSCREEN

—Create a new entity
local e = scene:entity()
body = e:add(craft.rigidbody)
e.model = craft.model(asset.builtin.Primitives.Capsule)
e.material = craft.material(asset.builtin.Materials.Specular)
e.x = 0
e.y = 0
e.z = -2 
e.scale = vec3(1, 1, 1) / 8

scene.camera.z = -0.1
scene.camera.eulerAngles = vec3(0, 180, 0)

end

—-function touched(touch)
if touch.state == MOVING then
scene.camera.eulerAngles = vec3(0, cameraYPos.y, 0)

    cameraYPos.y = cameraYPos.y + -1
    playerXPos = playerXPos + 1
end

if touch.state == BEGAN then
    ray = scene.physics:raycast(vec3(WIDTH/2,0,0),vec3(x,1000,0))
    if ray ~= nil then
        objectsFound = #ray
    end
end

end

—-function update(dt)
– Update the scene (physics, transforms etc)
scene:update(dt)
end

– Called automatically by codea
function draw()
update(DeltaTime)

-- Draw the scene
scene:draw()	
text("Found: "..objectsFound, WIDTH/2, 200)

end

@Creator27 I’m having trouble getting the ray cast to work in Craft. Once I figure it out I’ll post an example.

@Creator27 I got 3D ray cast working. Here’s the example. The one sphere is located at 30,20,10, so move the x,y,z sliders near those values and when the line intersects the sphere, it will show the x,y,z values. Try increasing the size of the second sphere from 2 to a larger value and see different intersect points.

viewer.mode=STANDARD

function setup()
    parameter.integer("x",0,40)
    parameter.integer("y",0,40)
    parameter.integer("z",0,40)
    fill(255)
    assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")        
    scene = craft.scene()
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(158, 202, 223, 255)
    skyMaterial.horizon=color(98, 166, 114, 255)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 300, 0, 1000)
    createSphere(vec3(0,0,0),1)
    createSphere(vec3(30,20,10),2)
end

function draw()
    update(DeltaTime)
    scene:draw()
    tab=scene.physics:raycast(vec3(0,0,0),vec3(x,y,z),100)
    if tab~=nil then
        text("x= "..tab.point.x//1,WIDTH/2,HEIGHT-100)
        text("y= "..tab.point.y//1,WIDTH/2,HEIGHT-120)
        text("z= "..tab.point.z//1,WIDTH/2,HEIGHT-140)
    end
    scene.debug:line(vec3(0,0,0),vec3(x,y,z)*20,color(255))  
end

function update(dt)
    scene:update(dt)
end

function createSphere(p,size)
    sphere1=scene:entity()
    s1=sphere1:add(craft.rigidbody,STATIC)
    sphere1.position=vec3(p.x,p.y,p.z)
    sphere1:add(craft.shape.sphere,size)
    sphere1.model = craft.model.icosphere(size,2)
    sphere1.material = craft.material(asset.builtin.Materials.Specular)
    sphere1.material.diffuse=color(255,0,0)
end

@dave1707, I have succeeded in making a raycast, but when I copied the code into my project, the text didn’t show up when the raycast hit the sphere. Here’s the code that I’ve done so far:

-- Laser Game

function setup()
    -- Create a new craft scene
    scene = craft.scene()
    day = readText(asset.builtin.Environments.Sunny)
    env = craft.cubeTexture(json.decode(day))
    scene.sky.material.envMap = env
    startRayCast = false
    parameter.integer("rotation", -10, 10, 0)

    -- Create a new entity
    local e = scene:entity()
    body = e:add(craft.rigidbody, STATIC)
    e.model = craft.model(asset.builtin.Primitives.Sphere)
    e.y = 1
    e.z = 1
    e.scale = vec3(1,1,1) / 8
    
    scene.camera.x = 1
    scene.camera.z = -4
end

-- Called automatically by codea 
function draw()
    update(DeltaTime)
    
    -- Draw the scene
    scene:draw()	
    
    
    
    
    
    ray2 = scene.physics:raycast(vec3(0, rotation, 0), vec3(1000, 1000, 1000))
    if ray2 ~= nil then
        print("Object found!")
    end
    scene.debug:line(vec3(0, rotation, 0), vec3(0, 0, 3), color(255))
end

- -function update(dt)
    -- Update the scene (physics, transforms etc)
    scene:update(dt)
end

- -function touched(touch) 
    if touch.state == MOVING and touch.deltaY > 0 then
        rotation = rotation + 0.01
    end
    
    if touch.state == MOVING and touch.deltaY < 0 then
        rotation = rotation - 0.01
    end
    
    
end

If you can find any problems as to why it isn’t working, please let me know.
Thank you :slight_smile:

See the builtin documentation for the raycast parameters. It looks like you’re changing where the raycast starts and the direction is always vec3(1000,1000,1000). So you’re not changing the direction of the raycast.

@dave1707, I’m not exactly sure what you mean. I don’t really know how to change the direction of the raycast. Are you able to possibly make another example on what you mean?

Thanks :slight_smile:

@Creator27 Look at my example above. My ray cast starts at vec3(0,0,0) and the direction is vec3(x,y,z) for a distance of 100. So the ray cast is just a direction starting at 0,0,0 and passing through points x,y,z for a distance of 100.

@dave1707, I have tried to do as you said, but I’ve still had no luck. Is there anyway for you to somehow format my code that I’ve showed you so that it works?