I made a 3D Car in Defold. very interesting!

I think it will be a very good and interesting 3D example for Defold

16 Likes

Nice! Would you be willing to share the code? I’m really interested in seeing how you built it. :slightly_smiling_face:

1 Like

This is the script that control the red car. :grinning_face:

function init(self)
	msg.post(".", "acquire_input_focus")
	msg.post("@render:", "use_camera_projection")
	msg.post("camera", "acquire_camera_focus")

	-- 汽车运动参数(你可以根据你的3D世界比例调整这些数值)
	self.speed = 0              -- 当前速度
	self.max_speed = 10         -- 最大前进速度
	self.reverse_speed = 5      -- 最大倒车速度
	self.acceleration = 15      -- 加速度
	self.friction = 8           -- 摩擦力(松开按键时自动减速的力度)
	self.turn_speed = 120       -- 转向速度(度/秒)

	-- 记录按键状态
	self.actions = {
		forward = false,
		backward = false,
		left = false,
		right = false
	}
end

function update(self, dt)
	-- 1. 计算输入方向
	local input_y = (self.actions.forward and 1 or 0) - (self.actions.backward and 1 or 0)
	local input_x = (self.actions.left and 1 or 0) - (self.actions.right and 1 or 0)

	-- 2. 处理转向 (A 和 D)
	-- 只有在汽车有速度时才允许转向(更符合真实物理,如果需要原地打转可以去掉 speed ~= 0 的判断)
	if input_x ~= 0 and math.abs(self.speed) > 0.1 then
		-- 如果是在倒车,反转方向盘的逻辑
		local dir = self.speed > 0 and 1 or -1

		-- 获取当前Y轴旋转并修改
		local current_rot_y = go.get(".", "euler.y")
		current_rot_y = current_rot_y + input_x * self.turn_speed * dt * dir
		go.set(".", "euler.y", current_rot_y)
	end

	-- 3. 处理油门与刹车 (W 和 S)
	if input_y ~= 0 then
		-- 加速
		self.speed = self.speed + input_y * self.acceleration * dt
	else
		-- 松开按键时摩擦力减速
		if self.speed > 0 then
			self.speed = math.max(0, self.speed - self.friction * dt)
		elseif self.speed < 0 then
			self.speed = math.min(0, self.speed + self.friction * dt)
		end
	end

	-- 限制最大速度
	self.speed = math.max(-self.reverse_speed, math.min(self.max_speed, self.speed))

	-- 4. 根据当前朝向移动汽车
	if self.speed ~= 0 then
		local pos = go.get_position()
		local rot = go.get_rotation()

		-- 计算汽车的"正前方"向量。
		-- 注意:Defold 3D的标准正前方通常是 -Z 轴 (0, 0, -1)。
		-- 如果你的3D车模型导进来是横着的,可以改成 (1, 0, 0) 或 (-1, 0, 0)。
		local forward_vector = vmath.rotate(rot, vmath.vector3(0, 0, -1))

		-- 更新位置
		pos = pos + forward_vector * self.speed * dt
		go.set_position(pos)
	end
end

function on_input(self, action_id, action)
	-- 监听我们之前在 input_binding 中设置的动作
	if action_id == hash("forward") then
		self.actions.forward = not action.released
	elseif action_id == hash("backward") then
		self.actions.backward = not action.released
	elseif action_id == hash("left") then
		self.actions.left = not action.released
	elseif action_id == hash("right") then
		self.actions.right = not action.released
	end
end
3 Likes