Last active
August 3, 2024 15:30
-
-
Save MnkyArts/f6cc526d46868720ac9f66f045f64f68 to your computer and use it in GitHub Desktop.
alt:V Camerapath Helper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CameraPath { | |
waypoints: { position: alt.Vector3; rotation: alt.Vector3 }[]; | |
totalDuration: number; | |
camera: number | null; | |
startTime: number; | |
isActive: boolean; | |
constructor(waypoints, totalDuration) { | |
if (waypoints.length < 2) { | |
throw new Error("At least two waypoints are required"); | |
} | |
this.waypoints = waypoints; | |
this.totalDuration = totalDuration; | |
this.camera = null; | |
this.startTime = 0; | |
this.isActive = false; | |
} | |
start() { | |
if (this.isActive) { | |
return; | |
} | |
const start = this.waypoints[0]; | |
this.camera = native.createCamWithParams( | |
"DEFAULT_SCRIPTED_CAMERA", | |
start.position.x, | |
start.position.y, | |
start.position.z, | |
start.rotation.x, | |
start.rotation.y, | |
start.rotation.z, | |
90, // FOV | |
true, | |
0 | |
); | |
native.renderScriptCams(true, false, 0, true, false, 0); | |
this.startTime = Date.now(); | |
this.isActive = true; | |
this.update(); | |
} | |
update() { | |
if (!this.isActive) return; | |
const currentTime = Date.now(); | |
const elapsedTime = currentTime - this.startTime; | |
const progress = Math.min(elapsedTime / this.totalDuration, 1); | |
if (progress >= 1) { | |
this.stop(); | |
return; | |
} | |
const { position, rotation } = this.getInterpolatedState(progress); | |
native.setCamCoord(this.camera, position.x, position.y, position.z); | |
native.setCamRot(this.camera, rotation.x, rotation.y, rotation.z, 2); | |
alt.nextTick(() => this.update()); | |
} | |
getInterpolatedState(progress) { | |
const totalDistance = this.getTotalDistance(); | |
const targetDistance = totalDistance * progress; | |
let currentDistance = 0; | |
for (let i = 0; i < this.waypoints.length - 1; i++) { | |
const start = this.waypoints[i]; | |
const end = this.waypoints[i + 1]; | |
const segmentDistance = this.getDistance(start.position, end.position); | |
if (currentDistance + segmentDistance >= targetDistance) { | |
const segmentProgress = (targetDistance - currentDistance) / segmentDistance; | |
return { | |
position: this.interpolate(start.position, end.position, segmentProgress), | |
rotation: this.interpolateRotation(start.rotation, end.rotation, segmentProgress) | |
}; | |
} | |
currentDistance += segmentDistance; | |
} | |
const lastWaypoint = this.waypoints[this.waypoints.length - 1]; | |
return { position: lastWaypoint.position, rotation: lastWaypoint.rotation }; | |
} | |
getTotalDistance() { | |
let distance = 0; | |
for (let i = 0; i < this.waypoints.length - 1; i++) { | |
distance += this.getDistance(this.waypoints[i].position, this.waypoints[i + 1].position); | |
} | |
return distance; | |
} | |
getDistance(point1, point2) { | |
const dx = point2.x - point1.x; | |
const dy = point2.y - point1.y; | |
const dz = point2.z - point1.z; | |
return Math.sqrt(dx * dx + dy * dy + dz * dz); | |
} | |
interpolate(start, end, progress) { | |
return { | |
x: start.x + (end.x - start.x) * progress, | |
y: start.y + (end.y - start.y) * progress, | |
z: start.z + (end.z - start.z) * progress | |
}; | |
} | |
interpolateRotation(start, end, progress) { | |
return { | |
x: this.lerpAngle(start.x, end.x, progress), | |
y: this.lerpAngle(start.y, end.y, progress), | |
z: this.lerpAngle(start.z, end.z, progress) | |
}; | |
} | |
lerpAngle(a, b, t) { | |
const diff = b - a; | |
const adjusted = ((diff + 180) % 360) - 180; | |
return a + adjusted * t; | |
} | |
stop() { | |
if (this.camera !== null) { | |
native.destroyAllCams(true); | |
native.renderScriptCams(false, false, 0, true, false, 0); | |
this.camera = null; | |
} | |
this.isActive = false; | |
} | |
} | |
// Usage example | |
const waypoints = [ | |
{ | |
position: { x: -279.37506103515625, y: -4014.04833984375, z: 283.5936279296875 }, | |
rotation: { x: 0, y: 0, z: 0 } | |
}, | |
{ | |
position: { x: 0, y: 0, z: 500 }, | |
rotation: { x: -30, y: 0, z: 45 } | |
}, | |
{ | |
position: { x: 496.1072692871094, y: 5524.7744140625, z: 811.158203125 }, | |
rotation: { x: 15, y: 0, z: 180 } | |
} | |
]; | |
const totalDuration = 10000; // 10 seconds for the entire path | |
const cameraPath = new CameraPath(waypoints, totalDuration); | |
cameraPath.start(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment