@UberGoober I liked the code so much that I made a few changes to your code. I hope you don’t mind. I rewrote the animation in a different way. I divided the model into two parts, the propeller and the fuselage, and then let the propeller rotation around the axis, in this way to achieve the helicopter flight animation.
https://youtu.be/3ak4peIaERQ
The code is below:
Copter = class()
function Copter:init(pos)
self.camera = scene.camera:get(craft.camera)
self.state = true
self.root = scene:entity()
self.root.position = pos or vec3(0,0,0)
self.topRoot = scene:entity()
self.topRoot.parent = self.root
self.topRoot.position = vec3(0,0,0)
self.top = scene:entity()
self.top.parent = self.topRoot
self.top.position = vec3(-8.5,-8.5,-12.5)
self.vm1 = self.top:add(craft.volume, 1,1,1)
self.vm1:load(asset.Propellers)
self.top.active = true
self.body = scene:entity()
self.body.parent = self.root
self.body.position = vec3(-8.5,-8.5,-12.5)
self.vm2 = self.body:add(craft.volume, 1,1,1)
self.vm2:load(asset.Airframe)
self.body.active = true
self.angle = 0
self.zoom = 1
self.y = 0
touches.addHandler(self, -1, false)
end
function Copter:update(dt)
self.topRoot.rotation = quat.eulerAngles(0, self.angle*100,0)
self.root.rotation = quat.eulerAngles(0,self.angle,0)
self.root.scale = vec3(self.zoom, self.zoom, self.zoom)
self.root.y = self.y
-- print(self.root.worldPosition)
local a = self.topRoot.worldPosition + vec3(0,0,-1)
local b = self.topRoot.worldPosition + vec3(0,0,1)
local c = self.topRoot.worldPosition + vec3(0,-1,0)
local d = self.topRoot.worldPosition + vec3(0,1,0)
scene.debug:line(a, b,color(16, 239, 5))
scene.debug:line(c, d,color(239, 19, 5))
end
function Copter:interact()
if not self.open then
self.open = true
tween(2.5, self, {angle = 61.8, zoom=1/2}, {easing=tween.easing.backOut,loop = tween.loop.once})
else
self.open = false
tween(2.5, self, {angle = 0, zoom=1}, {easing=tween.easing.backOut,loop = tween.loop.once})
end
local t1 = tween(0.5,self,{y=2})
local t2 = tween(0.5,self,{y=-1})
local t3 = tween(0.5,self,{y=1})
local t4 = tween(0.5,self,{y=-2})
local t5 = tween(0.5,self,{y=3})
tween.sequence(t1,t2,t3,t4,t5)
end
function Copter:touched(touch)
if touch.state == BEGAN then
self:interact()
-- Returning true will capture this touch and prevent other handlers from getting it
local origin, dir = self.camera:screenToRay(vec2(touch.x, touch.y))
-- print(self.root.worldPosition)
-- Do a raycast to check if touch is hitting the bulb
local hit = scene.physics:raycast(origin, dir, 300)
-- print(self.top.position)
if hit and hit.entity == self.body then
-- Turn up light intensity
-- self.light.intensity = 3
-- self.entity.material.diffuse = self.color
self.state = not self.state
print("Touch Began (Captured - "..touch.id..")",origin)
return true
end
elseif touch.state == ENDED and self.state then
-- Turn down intensity when touch ends
-- self.light.intensity = 0.2
-- self.entity.material.diffuse = self.color * 0.2
print("Touch Ended (Captured - "..touch.id..")")
end
end
function setup()
-- Create a new craft scene
scene = craft.scene()
scene.ambientColor = color(218, 158, 79)
scene.sky.active = false
-- Setup camera and lighting
scene.sun.rotation = quat.eulerAngles(125, 125, 0)
-- Helper class for interactive camera
myViewer = scene.camera:add(OrbitViewer, vec3( 0, 0, 0), 80, 1, 400)
myViewer.rx = 0
myViewer.ry = 0
myCopter1 = Copter(vec3(0,0,0))
myCopter2 = Copter(vec3(-30,0,60))
end
function update(dt)
scene:update(dt)
myCopter1:update()
myCopter2:update()
end
-- Called automatically by codea
function draw()
update(DeltaTime)
scene:draw()
sprite(asset.builtin.UI.Blue_Circle,CurrentTouch.x,CurrentTouch.y)
end