Samarium
Thank you for your detailed answer. I very much appreciate this.
Unfortunately formula to calculate rotation did not work for me because I tested it for:
const targetPosition = { x: 475, y: 475 }
const oldPosition = { x: 500, y: 500 }
and it gave me 0
as degrees.
So I found new formula:
const rotate = function(currentPosition: PositionXY, targetPosition: PositionXY) {
const deltaX = targetPosition.x - currentPosition.x;
const deltaY = targetPosition.y - currentPosition.y;
// Use Math.atan2 to calculate the angle in radians
const radians = Math.atan2(deltaY, deltaX);
// Convert radians to degrees
const degrees = radians * (180 / Math.PI);
// Ensure the angle is in the range [0, 360)
const positiveDegrees = (degrees + 360) % 360;
return positiveDegrees;
}
and it returns 45
degrees for that example
I tested it and when I set angle to 45 then arrow is rotated correctly, but I can't get it working because I don't know how to get current and next position in this RpgSpriteHooks.
I tried with:
sprite.position as currentPosition
sprite.data.position as currentPosition
sprite.data.paramsChanged.position as targetPosition
sprite.data.prevParamsChanged.position
but result is very similar for every combination as on this video: https://imgur.com/a/7ZJ5wvA
I tried to add new param targetPosition
to AbstractObject
or RpgCommonPlayer
in my computeNextPosition
method
AbstractObject.prototype.computeNextPosition = async function(nextPosition: Vector2d, target: Vector2d): Promise<Vector2d> {
const pullDistance = target.distanceWith(nextPosition)
if (pullDistance <= this.speed) {
return nextPosition.set(target)
}
const pull = (target.copy().subtract(nextPosition)).multiply((1 / pullDistance))
const totalPush = new Vector2dZero()
let contenders = 0
await this.isCollided(nextPosition);
pull
.multiply(Math.max(1, 4 * contenders))
.add(totalPush)
.normalize()
nextPosition.add(pull.multiply(this.speed))
this.targetPosition = nextPosition.copy();
return nextPosition;
}
and I tried to add it here:
declare module "@rpgjs/server" {
export interface AbstractObject {
targetPosition?: Vector2d
movePlayerToPosition(position: Vector2d): Observable<Vector2d>
computeNextPosition(nextPosition: Vector2d, target: Vector2d): Promise<Vector2d>
changeDirectionByNextPosition(nextPosition: Vector2d): void
}
export interface RpgCommonPlayer {
targetPosition?: Vector2d
}
}
but I couldn't fetch it through Sprite on the client side.
Probably it's not synchronized in this way.
Do you have any idea how could I achieve that?
Thank you in advance.
Edit: I got formula that works pretty well
onChanges(sprite: RpgSprite, data, old) {
const rotate = function(currentPosition: PositionXY, targetPosition: PositionXY) {
const deltaX = targetPosition.x - currentPosition.x;
const deltaY = targetPosition.y - currentPosition.y;
// Use Math.atan2 to calculate the angle in radians
const radians = Math.atan2(deltaY, deltaX);
// Convert radians to degrees
const degrees = radians * (180 / Math.PI);
// Ensure the angle is in the range [0, 360)
const positiveDegrees = (degrees + 360) % 360;
return positiveDegrees;
}
if (sprite.data.name === 'arrow') {
if (old.paramsChanged?.position) {
const angle = rotate(data.position, old.paramsChanged?.position)
if (angle === 0) {
return;
}
console.log('angle', angle);
sprite.angle = angle
}
}
}
but unfortunatelly it is in onChanges
hook and I can't update angle
here
Check console in video: https://imgur.com/K9igTRa
These degrees are very accurate