Attach camera to entity / follow entity

Hello,
I’ve made some searches but I can’t find an easy way to just make my camera follow an entity (player car or train for example)
The doc is unclear about all camera methods for newbies …

I did attach a camera to an entity with this code

c = train.loco:add(craft.camera, 45, 0.1, 1000, false)

But I don’t know how to adjust camera position to put it above the 3D model and adjust its orientation

C.position.y = 50 Doesn’t seem to work

@threads I don’t know if this will help. I’m not adding the camera like you show above, but I’m moving the camera around the Craft scene. See the code in the link below.

https://codea.io/talk/discussion/8932/starter-game-22#latest

@threads I haven’t been able to change the camera position on an entity, but maybe you can create a second entity attached to the first and just above it and attach the camera to the second entity. I haven’t tried it yet myself.

@threads I took one of my projects and modified it to attach a camera to one of the objects. Tap the attach parameter to attach or release the camera. I still haven’t been able to alter the camera position relative to the object.

PS. Added code to allow the attached camera to be rotated using the parameter sliders.

function setup()
    opac=.3
    parameter.action("attach",attach)
    parameter.integer("angX",0,360,0)
    parameter.integer("angY",0,360,0)
    parameter.integer("angZ",0,360,0)
    size=.2
    fill(255)
    scene = craft.scene()
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(0, 62, 255, 255)
    skyMaterial.horizon=color(99, 255, 0, 255)
    scene.sun.rotation=quat.eulerAngles(20,45,-30)
    createObjects()
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 30, 0, 200)
    v.rx=30
    v.ry=30
end

function attach()
    if not aa then
        aa=scene:entity()
        s1=aa:add(craft.rigidbody,DYNAMIC)
        s1.linearVelocity=vec3(2,2,2)
        s1.restitution=1
        s1.friction=0
        aa.position=vec3(0,0,0)
        aa:add(craft.shape.sphere,size)
        aa.model = craft.model.icosphere(size,2)
        aa.material = craft.material("Materials:Specular")
        aa.material.diffuse=color(255)        
        c=aa:add(craft.camera, 120, 0, 10, false)
    else
        c=nil
        aa:destroy()
        aa=nil
    end
end

function createObjects()
    for z=1,100 do
        a=scene:entity()
        s1=a:add(craft.rigidbody,DYNAMIC)
        s1.linearVelocity=vec3(2,2,2)
        s1.restitution=1
        s1.friction=0
        a.position=vec3(0,0,0)
        a:add(craft.shape.sphere,size)
        a.model = craft.model.icosphere(size,2)
        a.material = craft.material("Materials:Specular")
        a.material.diffuse=color(255,0,0)
    end    

    wall1=createWall(1,vec3(-5,0,0),vec3(.1,10,10),vec3(.1,10,10),"Blocks:Error")
    wall2=createWall(1,vec3(5,0,0),vec3(.1,10,10),vec3(.1,10,10),"Blocks:Dirt Sand")    
    wall3=createWall(1,vec3(0,-5,0),vec3(10,.1,10),vec3(10,.1,10),"Blocks:Cotton Blue")    
    wall4=createWall(1,vec3(0,0,5),vec3(10,10,.1),vec3(10,10,.1),"Blocks:Cactus Side")    
    wall5=createWall(1,vec3(0,0,-5),vec3(10,10,.1),vec3(10,10,.1),"Blocks:Brick Red")
    wall6=createWall(1,vec3(0,5,0),vec3(10,.1,10),vec3(10,.1,10),"Blocks:Brick Grey")
end

function createWall(rest,pos,a,mod,map)
    local ww=scene:entity()
    local w=ww:add(craft.rigidbody,STATIC)
    w.restitution=rest
    ww.position=pos
    ww:add(craft.shape.box,a)
    ww.model = craft.model.cube(mod)
    ww.material = craft.material("Materials:Standard")
    ww.material.map = readImage(map)
    ww.material.blendMode = NORMAL
    return ww
end

function draw()
    update(DeltaTime)
    scene:draw()    
    text("Move the slider to change opacity",WIDTH/2,HEIGHT-50)
    text("Drag your finger on the screen to rotate the cube",WIDTH/2,HEIGHT-100)
end

function update(dt)
    scene:update(dt)
    wall1.material.opacity=opac
    wall2.material.opacity=opac
    wall3.material.opacity=opac
    wall4.material.opacity=opac
    wall5.material.opacity=opac
    wall6.material.opacity=opac
    if c then
        c.entity.eulerAngles=vec3(angX,angY,angZ)
    end
end

Thanks a lot for your time and answer @dave1707

Yes, i managed to attach the camera to an entity (I was confused before, the camera is a component, not an entity) but I didn’t find a way to move it relatively from the entity itself, so I ended up moving my camera independently in my update/draw function

@threads Here’s an example of attaching the camera to an entity and move everything around the scene.

PS. I modified the code to use the tilt of the iPad to change the direction traveled.

displayMode(FULLSCREEN)

function setup()
    bx,bz=500,500   -- initial block position
    vel=.2          -- velocity
    dir=45
    
    scene = craft.scene()
       
    ground=scene:entity()
    ground.model = craft.model.cube(vec3(10000,1,10000))
    ground.position=vec3(0,-10,0)
    ground.material = craft.material("Materials:Standard")
    ground.material.map = readImage("Surfaces:Desert Cliff Normal")
    ground.material.offsetRepeat=vec4(0,0,50,50)
    
    block = scene:entity()
    block.model = craft.model.cube(vec3(4,.5,2))
    block.material = craft.material("Materials:Standard")
    block.material.map = readImage("Blocks:Trunk White Top")
    block.position=vec3(gx,0,gp)

    cam = scene:entity()
    cam.model = craft.model.cube(vec3(.2,.2,.2))
    cam.material = craft.material("Materials:Specular")
    cam.material.map = readImage("Blocks:Brick Grey")
    cam.position=vec3(0,6,6)
    
    cam.parent=block    -- attach camera to block
    c=cam:add(craft.camera, 120, .1, 1000, false) -- set camera values
    c.entity.eulerAngles=vec3(0,180,0)  -- set camera pointing direction
end

function update(dt)
    scene:update(dt)
    block.eulerAngles = vec3(0,dir,0)
    bx=bx-vel*math.sin(math.rad(dir))   -- calculate x value
    bz=bz-vel*math.cos(math.rad(dir))   -- calculate z value
    block.position=vec3(bx,0,bz)        -- update block x,z position   
    c.entity.eulerAngles=vec3(0,180,-Gravity.x*50)  -- set camera pointing direction
end

function draw()
    update(DeltaTime)
    scene:draw()	
    dir=dir-Gravity.x*3
end

Haha awesome @dave1707 ! Thank you !!

Edit : this should be a tutorial or a default project ! (Minus the cube attached to the cam entity, which is not necessary, and would make the code even shorter)