premiere animation
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
<button (click)="setInteractionMode('animate')">Dessiner Vecteur</button>
|
||||
<button (click)="setVectorType('linear')">Vecteur Linéaire</button>
|
||||
<button (click)="setVectorType('curved')">Vecteur Courbé</button>
|
||||
<button (click)="toggleLoop()">Activer/Désactiver Boucle d'Animation</button>
|
||||
</div>
|
||||
|
||||
<!-- <canvas #canvas width="800" height="600"
|
||||
|
||||
@@ -16,6 +16,8 @@ interface Circle {
|
||||
controlPointY?: number | null; // Pour les vecteurs courbés
|
||||
isMoving: boolean;
|
||||
progress: number; // Paramètre de progression sur la courbe
|
||||
startX: number;
|
||||
startY: number;
|
||||
}
|
||||
|
||||
interface Rectangle {
|
||||
@@ -58,6 +60,11 @@ export class FootballFieldComponent {
|
||||
private prevAngle: number = 0;
|
||||
private isDrawingVector: boolean = false;
|
||||
|
||||
private endX: number = 0;
|
||||
private endY: number = 0;
|
||||
private isAnimating: boolean = false;
|
||||
private animationSpeed: number = 0.01;
|
||||
|
||||
public colors: string[] = ['#ff0000', '#00ff00',
|
||||
'#0000ff', '#ffff00',
|
||||
'#ff00ff', '#00ffff',
|
||||
@@ -66,9 +73,9 @@ export class FootballFieldComponent {
|
||||
public selectedColor: string = this.colors[0]; // Couleur sélectionné par défaut (rouge)
|
||||
// Options de forme
|
||||
public selectedShape: string = 'none'; // Par défaut, aucune forme
|
||||
public playerCount: number = 2; // Nombre de joueurs par défaut
|
||||
public plotCount: number = 1; // Nombre de plots par défaut
|
||||
public piquetCount: number = 1; // Nombre de plots par défaut
|
||||
public playerCount: number = 4; // Nombre de joueurs par défaut
|
||||
public plotCount: number = 2; // Nombre de plots par défaut
|
||||
public piquetCount: number = 2; // Nombre de plots par défaut
|
||||
public ballCount: number = 1; // Nombre de ballons par defaut
|
||||
public players: Circle[] = [];
|
||||
public plots: Circle[] = [];
|
||||
@@ -83,7 +90,12 @@ export class FootballFieldComponent {
|
||||
destinationX: null,
|
||||
destinationY: null,
|
||||
isMoving:false,
|
||||
progress: 0 };
|
||||
progress: 0,
|
||||
startX: 150,
|
||||
startY: 150 };
|
||||
public selectedPlayer: Circle | null = null;
|
||||
public isDrawingLine: boolean = false;
|
||||
public loopAnimation: boolean = true; // Pour répéter l'animation
|
||||
public debugInfo: string = ""; // Variable pour les informations de debogage
|
||||
public vectorType: 'linear' | 'curved' = 'linear'; // Type de vecteur sélectionné
|
||||
public interactionMode: 'move' | 'animate' = 'move'; // Mode d'interaction sélectionné
|
||||
@@ -169,47 +181,81 @@ export class FootballFieldComponent {
|
||||
this.drawPiquets();
|
||||
this.drawBall();
|
||||
this.updateDebugInfo();
|
||||
|
||||
// Dessiner la ligne si en mode dessin
|
||||
if (this.isDrawingLine && this.selectedPlayer) {
|
||||
console.log("[Draw Field] drawing vector");
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.startX, this.startY);
|
||||
ctx.lineTo(this.endX, this.endY);
|
||||
ctx.strokeStyle = '#FF0000';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
private animate() {
|
||||
this.updatePositions();
|
||||
//this.updatePositions();
|
||||
if (this.isAnimating && this.selectedPlayer) {
|
||||
this.updatePlayerPosition(this.selectedPlayer);
|
||||
}
|
||||
this.drawField();
|
||||
requestAnimationFrame(() => this.animate());
|
||||
}
|
||||
|
||||
private updatePositions() {
|
||||
// Mettre à jour les positions des joueurs
|
||||
this.players.forEach(player => {
|
||||
player.x += player.vx;
|
||||
player.y += player.vy;
|
||||
private updatePlayerPosition(player: Circle) {
|
||||
// Avancer le joueur sur la ligne avec un LERP (Linear Interpolation)
|
||||
player.progress += this.animationSpeed;
|
||||
|
||||
// Collision avec les bords
|
||||
if (player.x - player.radius < 0 || player.x + player.radius > this.canvas.nativeElement.width) {
|
||||
player.vx = -player.vx;
|
||||
if (player.progress >= 1) {
|
||||
if (this.loopAnimation) {
|
||||
player.progress = 0; // Répéter l'animation
|
||||
player.x = player.startX;
|
||||
player.y = player.startY;
|
||||
} else {
|
||||
this.isAnimating = false;
|
||||
this.selectedPlayer = null;
|
||||
}
|
||||
if (player.y - player.radius < 0 || player.y + player.radius > this.canvas.nativeElement.height) {
|
||||
player.vy = -player.vy;
|
||||
}
|
||||
});
|
||||
|
||||
// Si le ballon est attaché à un joueur, le suivre
|
||||
if (this.attachedPlayer) {
|
||||
this.updateBallPositionOnPlayer();
|
||||
} else {
|
||||
// Mise à jour de la position du ballon
|
||||
this.ball.x += this.ball.vx;
|
||||
this.ball.y += this.ball.vy;
|
||||
|
||||
// Collision avec les bords pour le ballon
|
||||
if (this.ball.x - this.ball.radius < 0 || this.ball.x + this.ball.radius > this.canvas.nativeElement.width) {
|
||||
this.ball.vx = -this.ball.vx;
|
||||
}
|
||||
if (this.ball.y - this.ball.radius < 0 || this.ball.y + this.ball.radius > this.canvas.nativeElement.height) {
|
||||
this.ball.vy = -this.ball.vy;
|
||||
}
|
||||
const t = player.progress;
|
||||
player.x = (1 - t) * player.startX + t * this.endX;
|
||||
player.y = (1 - t) * player.startY + t * this.endY;
|
||||
}
|
||||
}
|
||||
|
||||
// private updatePositions() {
|
||||
// // Mettre à jour les positions des joueurs
|
||||
// this.players.forEach(player => {
|
||||
// player.x += player.vx;
|
||||
// player.y += player.vy;
|
||||
//
|
||||
// // Collision avec les bords
|
||||
// if (player.x - player.radius < 0 || player.x + player.radius > this.canvas.nativeElement.width) {
|
||||
// player.vx = -player.vx;
|
||||
// }
|
||||
// if (player.y - player.radius < 0 || player.y + player.radius > this.canvas.nativeElement.height) {
|
||||
// player.vy = -player.vy;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // Si le ballon est attaché à un joueur, le suivre
|
||||
// if (this.attachedPlayer) {
|
||||
// this.updateBallPositionOnPlayer();
|
||||
// } else {
|
||||
// // Mise à jour de la position du ballon
|
||||
// this.ball.x += this.ball.vx;
|
||||
// this.ball.y += this.ball.vy;
|
||||
//
|
||||
// // Collision avec les bords pour le ballon
|
||||
// if (this.ball.x - this.ball.radius < 0 || this.ball.x + this.ball.radius > this.canvas.nativeElement.width) {
|
||||
// this.ball.vx = -this.ball.vx;
|
||||
// }
|
||||
// if (this.ball.y - this.ball.radius < 0 || this.ball.y + this.ball.radius > this.canvas.nativeElement.height) {
|
||||
// this.ball.vy = -this.ball.vy;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Mettre à jour debugInfo avec les positions des joueurs et du ballon
|
||||
private updateDebugInfo() {
|
||||
const playerPositions = this.players.map((player, index) => `Joueur ${index + 1}: (${player.x.toFixed(1)}, ${player.y.toFixed(1)})`).join(', ');
|
||||
@@ -234,7 +280,9 @@ export class FootballFieldComponent {
|
||||
destinationX: null,
|
||||
destinationY: null,
|
||||
isMoving:false,
|
||||
progress: 0 });
|
||||
progress: 0,
|
||||
startX: 150,
|
||||
startY: 150 });
|
||||
}
|
||||
this.drawField();
|
||||
}
|
||||
@@ -255,7 +303,9 @@ export class FootballFieldComponent {
|
||||
destinationX: null,
|
||||
destinationY: null,
|
||||
isMoving:false,
|
||||
progress: 0 });
|
||||
progress: 0,
|
||||
startX: 150,
|
||||
startY: 150 });
|
||||
}
|
||||
this.drawField();
|
||||
}
|
||||
@@ -390,7 +440,23 @@ export class FootballFieldComponent {
|
||||
const { x, y } = this.getMousePos(event);
|
||||
if (this.interactionMode === 'animate') {
|
||||
console.log("[Mouse Down] animate elements");
|
||||
this.startDrawingVector(x, y);
|
||||
//this.startDrawingVector(x, y);
|
||||
if (!this.selectedPlayer) {
|
||||
console.log("[Mouse Down|Animate] select player");
|
||||
this.selectPlayer(x, y);
|
||||
} else if (!this.isDrawingLine) {
|
||||
this.startX = this.selectedPlayer.x;
|
||||
this.startY = this.selectedPlayer.y;
|
||||
this.endX = x;
|
||||
this.endY = y;
|
||||
this.isDrawingLine = true;
|
||||
console.log("[Mouse Down|Animate] Draw line - Start:(",
|
||||
this.startX,",",
|
||||
this.startY,"), End:(",
|
||||
this.endX,",",
|
||||
this.endY,
|
||||
")");
|
||||
}
|
||||
} else if (this.interactionMode === 'move') {
|
||||
console.log("[Mouse Down] move elements");
|
||||
this.startDragging(x, y);
|
||||
@@ -400,7 +466,7 @@ export class FootballFieldComponent {
|
||||
onCanvasMouseMove(event: MouseEvent) {
|
||||
const { x, y } = this.getMousePos(event);
|
||||
if (this.interactionMode === 'animate') {
|
||||
console.log("[Mouse Move] animate elements");
|
||||
//console.log("[Mouse Move] animate elements");
|
||||
} else if (this.interactionMode === 'move') {
|
||||
this.drag(x, y);
|
||||
}
|
||||
@@ -410,7 +476,14 @@ export class FootballFieldComponent {
|
||||
const { x, y } = this.getMousePos(event);
|
||||
if (this.interactionMode === 'animate') {
|
||||
console.log("[Mouse Up] Stop animating elements");
|
||||
this.finishDrawingVector(x,y);
|
||||
//this.finishDrawingVector(x,y);
|
||||
if (this.isDrawingLine && this.selectedPlayer) {
|
||||
console.log("[Mouse Up|Animate] Stop drawing vector");
|
||||
this.endX = x;
|
||||
this.endY = y;
|
||||
this.isDrawingLine = false;
|
||||
this.startAnimation();
|
||||
}
|
||||
} else if (this.interactionMode === 'move') {
|
||||
console.log("[Mouse Up] Stop moving elements");
|
||||
this.stopDragging();
|
||||
@@ -593,6 +666,21 @@ export class FootballFieldComponent {
|
||||
// this.ball.y = player.y + Math.sin(angle) * (player.radius + this.ball.radius);
|
||||
// }
|
||||
|
||||
private selectPlayer(x: number, y: number) {
|
||||
this.selectedPlayer = this.getNearestPlayer(x, y);
|
||||
if (this.selectedPlayer) {
|
||||
this.selectedPlayer.startX = this.selectedPlayer.x; // Sauvegarder le point de départ
|
||||
this.selectedPlayer.startY = this.selectedPlayer.y;
|
||||
}
|
||||
}
|
||||
|
||||
private startAnimation() {
|
||||
if (this.selectedPlayer) {
|
||||
this.isAnimating = true;
|
||||
this.selectedPlayer.progress = 0; // Réinitialiser la progression
|
||||
}
|
||||
}
|
||||
|
||||
private getNearestPlayerToBall(): Circle | null {
|
||||
let nearestPlayer: Circle | null = null;
|
||||
let minDistance = this.magnetRadius;
|
||||
@@ -643,103 +731,103 @@ export class FootballFieldComponent {
|
||||
this.drawField();
|
||||
}
|
||||
|
||||
// Change la couleur sélectionnée
|
||||
setColor(color: string) {
|
||||
this.selectedColor = color;
|
||||
}
|
||||
// // Change la couleur sélectionnée
|
||||
// setColor(color: string) {
|
||||
// this.selectedColor = color;
|
||||
// }
|
||||
|
||||
// Commence a dessiner quand la souris est enfoncée
|
||||
startDrawing(event: MouseEvent) {
|
||||
this.drawing = true;
|
||||
const { x, y } = this.getMousePos(event);
|
||||
this.startX = x;
|
||||
this.startY = y;
|
||||
this.lastX = x;
|
||||
this.lastY = y;
|
||||
}
|
||||
// // Commence a dessiner quand la souris est enfoncée
|
||||
// startDrawing(event: MouseEvent) {
|
||||
// this.drawing = true;
|
||||
// const { x, y } = this.getMousePos(event);
|
||||
// this.startX = x;
|
||||
// this.startY = y;
|
||||
// this.lastX = x;
|
||||
// this.lastY = y;
|
||||
// }
|
||||
|
||||
private startDrawingVector(x:number, y:number) {
|
||||
this.startX = x;
|
||||
this.startY = y;
|
||||
this.isDrawingVector = true;
|
||||
}
|
||||
// private startDrawingVector(x:number, y:number) {
|
||||
// this.startX = x;
|
||||
// this.startY = y;
|
||||
// this.isDrawingVector = true;
|
||||
// }
|
||||
|
||||
private finishDrawingVector(endX: number, endY: number) {
|
||||
if (!this.isDrawingVector) return;
|
||||
this.isDrawingVector = false;
|
||||
// private finishDrawingVector(endX: number, endY: number) {
|
||||
// if (!this.isDrawingVector) return;
|
||||
// this.isDrawingVector = false;
|
||||
//
|
||||
// const nearestPlayer = this.getNearestPlayer(this.startX, this.startY);
|
||||
// if (nearestPlayer) {
|
||||
// nearestPlayer.destinationX = endX;
|
||||
// nearestPlayer.destinationY = endY;
|
||||
// nearestPlayer.isMoving = true;
|
||||
// nearestPlayer.progress = 0;
|
||||
//
|
||||
// if (this.vectorType === 'curved') {
|
||||
// nearestPlayer.controlPointX = (this.startX + endX) / 2 + 50;
|
||||
// nearestPlayer.controlPointY = (this.startY + endY) / 2 - 50;
|
||||
// } else {
|
||||
// nearestPlayer.controlPointX = null;
|
||||
// nearestPlayer.controlPointY = null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
const nearestPlayer = this.getNearestPlayer(this.startX, this.startY);
|
||||
if (nearestPlayer) {
|
||||
nearestPlayer.destinationX = endX;
|
||||
nearestPlayer.destinationY = endY;
|
||||
nearestPlayer.isMoving = true;
|
||||
nearestPlayer.progress = 0;
|
||||
|
||||
if (this.vectorType === 'curved') {
|
||||
nearestPlayer.controlPointX = (this.startX + endX) / 2 + 50;
|
||||
nearestPlayer.controlPointY = (this.startY + endY) / 2 - 50;
|
||||
} else {
|
||||
nearestPlayer.controlPointX = null;
|
||||
nearestPlayer.controlPointY = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dessiner en fonction de la forme sélectionnée
|
||||
draw(event: MouseEvent) {
|
||||
if (!this.drawing) return;
|
||||
|
||||
const { x, y } = this.getMousePos(event);
|
||||
const ctx = this.ctx;
|
||||
|
||||
// Effacer ce qui a été dessiné pendant le déplacement
|
||||
//this.drawField();
|
||||
|
||||
// Si aucune forme n'est sélectionnée, on dessine librement
|
||||
if (this.selectedShape === 'none') {
|
||||
ctx.strokeStyle = this.selectedColor;
|
||||
ctx.lineWidth = 5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.lastX, this.lastY);
|
||||
ctx.lineTo(x, y);
|
||||
ctx.stroke();
|
||||
} else {
|
||||
// Sauvegarder le contexte pour ne pas effacer le terrain
|
||||
ctx.save();
|
||||
ctx.strokeStyle = this.selectedColor;
|
||||
ctx.lineWidth = 5;
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
|
||||
switch (this.selectedShape) {
|
||||
case 'rectangle':
|
||||
ctx.strokeRect(this.startX, this.startY, x - this.startX, y - this.startY);
|
||||
break;
|
||||
case 'circle':
|
||||
const radius = Math.sqrt((x - this.startX) ** 2 + (y - this.startY) ** 2);
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.startX, this.startY, radius, 0, Math.PI * 2);
|
||||
ctx.stroke();
|
||||
break;
|
||||
case 'line':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.startX, this.startY);
|
||||
ctx.lineTo(x, y);
|
||||
ctx.stroke();
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
this.lastX = x;
|
||||
this.lastY = y;
|
||||
}
|
||||
// // Dessiner en fonction de la forme sélectionnée
|
||||
// draw(event: MouseEvent) {
|
||||
// if (!this.drawing) return;
|
||||
//
|
||||
// const { x, y } = this.getMousePos(event);
|
||||
// const ctx = this.ctx;
|
||||
//
|
||||
// // Effacer ce qui a été dessiné pendant le déplacement
|
||||
// //this.drawField();
|
||||
//
|
||||
// // Si aucune forme n'est sélectionnée, on dessine librement
|
||||
// if (this.selectedShape === 'none') {
|
||||
// ctx.strokeStyle = this.selectedColor;
|
||||
// ctx.lineWidth = 5;
|
||||
// ctx.beginPath();
|
||||
// ctx.moveTo(this.lastX, this.lastY);
|
||||
// ctx.lineTo(x, y);
|
||||
// ctx.stroke();
|
||||
// } else {
|
||||
// // Sauvegarder le contexte pour ne pas effacer le terrain
|
||||
// ctx.save();
|
||||
// ctx.strokeStyle = this.selectedColor;
|
||||
// ctx.lineWidth = 5;
|
||||
// ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
//
|
||||
// switch (this.selectedShape) {
|
||||
// case 'rectangle':
|
||||
// ctx.strokeRect(this.startX, this.startY, x - this.startX, y - this.startY);
|
||||
// break;
|
||||
// case 'circle':
|
||||
// const radius = Math.sqrt((x - this.startX) ** 2 + (y - this.startY) ** 2);
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.startX, this.startY, radius, 0, Math.PI * 2);
|
||||
// ctx.stroke();
|
||||
// break;
|
||||
// case 'line':
|
||||
// ctx.beginPath();
|
||||
// ctx.moveTo(this.startX, this.startY);
|
||||
// ctx.lineTo(x, y);
|
||||
// ctx.stroke();
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// ctx.restore();
|
||||
// }
|
||||
//
|
||||
// this.lastX = x;
|
||||
// this.lastY = y;
|
||||
// }
|
||||
|
||||
|
||||
// Arrête de dessiner quand la souris est relâchée
|
||||
stopDrawing() {
|
||||
this.drawing = false;
|
||||
}
|
||||
// stopDrawing() {
|
||||
// this.drawing = false;
|
||||
// }
|
||||
|
||||
// Obtient la position de la souris sur le canvas
|
||||
private getMousePos(event: MouseEvent) {
|
||||
@@ -763,11 +851,17 @@ export class FootballFieldComponent {
|
||||
// Méthode pour changer le mode d'interaction (déplacer ou dessiner un vecteur)
|
||||
setInteractionMode(mode: 'move' | 'animate') {
|
||||
this.interactionMode = mode;
|
||||
this.isDrawingVector = false;
|
||||
//this.isDrawingVector = false;
|
||||
//this.selectedPlayer = null; // Réinitialiser la sélection de joueur pour éviter tout déplacement involontaire
|
||||
}
|
||||
|
||||
// Méthode pour définir le type de vecteur (linéaire ou courbé)
|
||||
setVectorType(type: 'linear' | 'curved') {
|
||||
this.vectorType = type;
|
||||
}
|
||||
|
||||
// Méthode pour activer/désactiver la boucle de l'animation
|
||||
toggleLoop() {
|
||||
this.loopAnimation = !this.loopAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user