-
{{ i + 1 }}
diff --git a/src/app/football-field/football-field.component.ts b/src/app/football-field/football-field.component.ts
index c4d52fe..f4609e0 100644
--- a/src/app/football-field/football-field.component.ts
+++ b/src/app/football-field/football-field.component.ts
@@ -13,19 +13,19 @@ interface TimelineStep {
duration: number; // Temps d'animation (en secondes ou ticks)
}
+interface Rectangle {
+ x: number; // Position X du centre du rectangle de l'élément
+ y: number; // Position Y du centre du rectangle de l'élément
+ width: number; // longueur de l'élément
+ height: number; // largeur de l'élément
+}
+
interface Circle {
id: number; // Identifiant unique de l'élément
x: number; // Position X du centre du cercle de l'élément
y: number; // Position Y du centre du cercle de l'élément
- number: number;
radius: number; // Rayon du cercle de l'élément
isDragging: boolean;
- vx: number; // vitesse en X
- vy: number; // vitesse en Y
- destinationX: number | null;
- destinationY: number | null;
- controlPointX?: number | null; // Pour les vecteurs courbés
- controlPointY?: number | null; // Pour les vecteurs courbés
isMoving: boolean;
progress: number; // Paramètre de progression sur la courbe
startX: number;
@@ -34,12 +34,46 @@ interface Circle {
currentStepIndex: number; // Suivre l'étape actuelle dans la timeline
}
-interface Rectangle {
- x: number;
- y: number;
- width: number;
- height: number;
- isDragging: boolean;
+interface Circle2 {
+ x: number; // Position X du centre du cercle de l'élément
+ y: number; // Position Y du centre du cercle de l'élément
+ radius: number; // Rayon du cercle de l'élément
+}
+
+interface Piquet {
+ id: number; // Identifiant unique de l'élément
+ design: Rectangle; // Design du piquet
+ isDragging: boolean; // Flag de déplacement du piquet
+}
+
+interface Plot {
+ id: number; // Identifiant unique de l'élément
+ design: Circle2; // Design du plot
+ isDragging: boolean; // Flag de déplacement du plot
+}
+
+interface Ball {
+ id: number; // Identifiant unique de l'élément
+ design: Circle2; // Design du ballon
+ isDragging: boolean; // Flag de déplacement du ballon
+ isMoving: boolean; // Flag d'animation du ballon
+ progress: number; // Paramètre de progression sur la courbe
+ steps: TimelineStep[]; // Stockage des étapes d'animation
+ currentStepIndex: number; // Suivre l'étape actuelle dans la timeline
+ attachToPlayer: Circle | null; // Le joueur auquel le ballon est attaché
+}
+
+interface Player {
+ id: number; // Identifiant unique de l'élément
+ design: Circle2; // Design du Joueur
+ isDragging: boolean; // Flag de déplacement du joueur
+ isMoving: boolean; // Flag d'animation du joueur
+ progress: number; // Paramètre de progression sur la courbe
+ hasBall: boolean; // Indique si le joueur a le ballon
+ startX: number;
+ startY: number;
+ steps: TimelineStep[]; // Stockage des étapes d'animation
+ currentStepIndex: number; // Suivre l'étape actuelle dans la timeline
}
@Component({
@@ -61,10 +95,7 @@ export class FootballFieldComponent {
private startX = 0;
private startY = 0;
private draggingPlayer: Circle | null = null;
- private draggingBall: Circle | null = null;
- //private draggingPlot: Circle | null = null;
- //private draggingPiquet: Rectangle | null = null;
- private draggingElement: any = null;
+ private draggingElement: any = null; // Element (plot, piquet) en cours de déplacement sur le terrain
private attachedPlayer: Circle | null = null;
private magnetRadius: number = 35; // Distance à laquelle le ballon s'attache au joueur
//private attachedToPlayer: boolean = false; // indique si le ballon est attache a un joueur
@@ -94,31 +125,34 @@ export class FootballFieldComponent {
public playerCount: number = 8; // 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[] = [];
- public piquets: Rectangle[] = [];
- public ball: Circle = { id: 0,
+ public plots: Plot[] = [];
+ public piquets: Piquet[] = [];
+ /*public ball: Circle = { id: 0,
x:400,
- y:300,
- number:1,
+ y:300,
radius:10,
- isDragging:false,
- vx:0,
- vy:0,
- destinationX: null,
- destinationY: null,
+ isDragging:false,
isMoving:false,
progress: 0,
startX: 150,
startY: 150,
- timeline: null,
- currentStepIndex: 0 };
+ timeline: [],
+ currentStepIndex: 0 };*/
+ public ball: Ball = { id: 0,
+ design: { x:400, y:300,
+ radius:10,
+ },
+ isDragging:false,
+ isMoving:false,
+ progress: 0,
+ steps: [],
+ currentStepIndex: 0,
+ attachToPlayer: null };
public selectedPlayer: Circle | null = null;
public isDrawingLine: boolean = false;
public loopAnimation: boolean = false; // 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é
public isTimelineDragging: boolean = false;
@@ -344,7 +378,7 @@ export class FootballFieldComponent {
const playerPositions = this.players.map((player, index) =>
`Joueur ${index + 1}: (${player.x.toFixed(1)}, ${player.y.toFixed(1)})`
).join(', ');
- const ballPosition = `Ballon: (${this.ball.x.toFixed(1)}, ${this.ball.y.toFixed(1)})`;
+ const ballPosition = `Ballon: (${this.ball.design.x.toFixed(1)}, ${this.ball.design.y.toFixed(1)})`;
this.debugInfo = `${playerPositions}, ${ballPosition}`;
}
@@ -357,20 +391,15 @@ export class FootballFieldComponent {
const x = i * (2 * radius) + radius;
const y = radius;
this.players.push({ id: i + 1,
- x,
- y,
- number: i + 1,
- radius,
- isDragging: false,
- vx:0, vy:0,
- destinationX: null,
- destinationY: null,
- isMoving:false,
- progress: 0,
- startX: 0,
- startY: 0,
- timeline: [],
- currentStepIndex: 0 });
+ x, y,
+ radius,
+ isDragging: false,
+ isMoving:false,
+ progress: 0,
+ startX: 0,
+ startY: 0,
+ timeline: [],
+ currentStepIndex: 0 });
}
this.drawField();
}
@@ -383,20 +412,10 @@ export class FootballFieldComponent {
const x = (this.canvas.nativeElement.width - radius) - (i) * (2 * radius);
const y = radius;
this.plots.push({ id: i + 1,
- x,
- y,
- number: i + 1,
- radius,
- isDragging: false,
- vx: 0, vy: 0,
- destinationX: null,
- destinationY: null,
- isMoving:false,
- progress: 0,
- startX: 0,
- startY: 0,
- timeline: null,
- currentStepIndex: 0 });
+ design: {
+ x, y,
+ radius },
+ isDragging: false });
}
this.drawField();
}
@@ -409,7 +428,9 @@ export class FootballFieldComponent {
const height = 100;
const x = (i * width);
const y = (this.canvas.nativeElement.height - height);
- this.piquets.push({ x, y, width, height, isDragging: false });
+ this.piquets.push({ id: i+1,
+ design: {x, y, width, height},
+ isDragging: false });
}
this.drawField();
}
@@ -437,14 +458,14 @@ export class FootballFieldComponent {
// Dessiner les cercles representant les plots
private drawPlots() {
- this.plots.forEach(circle => {
- this.drawPlot(circle);
+ this.plots.forEach(plot => {
+ this.drawPlot(plot);
});
}
private drawPiquets() {
- this.piquets.forEach(rectangle => {
- this.drawPiquet(rectangle);
+ this.piquets.forEach(piquet => {
+ this.drawPiquet(piquet);
});
}
@@ -454,7 +475,7 @@ export class FootballFieldComponent {
// Dessiner le cercle
ctx.beginPath();
- ctx.arc(this.ball.x, this.ball.y, this.ball.radius, 0, Math.PI * 2);
+ ctx.arc(this.ball.design.x, this.ball.design.y, this.ball.design.radius, 0, Math.PI * 2);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.strokeStyle = '#000000';
@@ -463,12 +484,12 @@ export class FootballFieldComponent {
}
// Dessiner un plot
- private drawPlot(circle: Circle) {
+ private drawPlot(plot: Plot) {
const ctx = this.ctx;
// Dessiner le cercle
ctx.beginPath();
- ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
+ ctx.arc(plot.design.x, plot.design.y, plot.design.radius, 0, Math.PI * 2);
ctx.fillStyle = '#ffa500';
ctx.fill();
ctx.strokeStyle = '#ff4500';
@@ -477,14 +498,14 @@ export class FootballFieldComponent {
}
// Dessiner un piquet
- private drawPiquet(rectangle: Rectangle) {
+ private drawPiquet(piquet: Piquet) {
const ctx = this.ctx;
ctx.beginPath();
ctx.fillStyle = '#ff0000';
- ctx.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+ ctx.fillRect(piquet.design.x, piquet.design.y, piquet.design.width, piquet.design.height);
ctx.strokeStyle = '#000000';
- ctx.strokeRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+ ctx.strokeRect(piquet.design.x, piquet.design.y, piquet.design.width, piquet.design.height);
}
// Dessiner un joueur avec un numér
@@ -504,7 +525,7 @@ export class FootballFieldComponent {
ctx.font = 'bold 12px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
- ctx.fillText(circle.number.toString(), circle.x, circle.y);
+ ctx.fillText(circle.id.toString(), circle.x, circle.y);
}
onCanvasMouseDown(event: MouseEvent) {
@@ -579,7 +600,7 @@ export class FootballFieldComponent {
duration: 1000 // Durée d'animation arbitraire, peut être ajustée
});
console.log("timeline:", this.selectedPlayer.timeline);
- this.selectedPlayer.currentStepIndex = 0; // Réinitialiser au début de la timeline
+ //this.selectedPlayer.currentStepIndex = 0; // Réinitialiser au début de la timeline
this.startAnimation();
}
} else if (this.interactionMode === 'move') {
@@ -601,23 +622,24 @@ export class FootballFieldComponent {
// Commencer a déplacer un élément du canvas
startDragging(x:number, y:number) {
- if (this.isInsideCircle(this.ball, x, y)) {
+ if (this.isInsideCircle(this.ball.design, x, y)) {
console.log("inside ball");
this.ball.isDragging = true;
this.attachedPlayer = null; // Libérer le ballon lors du clic
- this.offsetX = x - this.ball.x;
- this.offsetY = y - this.ball.y;
+ this.offsetX = x - this.ball.design.x;
+ this.offsetY = y - this.ball.design.y;
return;
}
- this.draggingElement = this.plots.find(plot => this.isInsideCircle(plot, x, y)) ||
- this.piquets.find(piquet => this.isInsideRectangle(piquet, x, y)) ||
- (this.isInsideCircle(this.ball, x, y) ? this.ball : null);
+ this.draggingElement = this.plots.find(plot => this.isInsideCircle(plot.design, x, y)) ||
+ this.piquets.find(piquet => this.isInsideRectangle(piquet.design, x, y)) ||
+ (this.isInsideCircle(this.ball.design, x, y) ? this.ball : null);
if (this.draggingElement) {
this.draggingElement.isDragging = true;
- this.offsetX = x - this.draggingElement.x;
- this.offsetY = y - this.draggingElement.y;
+ this.offsetX = x - this.draggingElement.design.x;
+ this.offsetY = y - this.draggingElement.design.y;
+ console.log("inside element:", this.draggingElement);
}
this.draggingPlayer = this.players.find(player => {
@@ -635,8 +657,8 @@ export class FootballFieldComponent {
drag(x:number, y:number) {
if (this.ball.isDragging) {
console.log("dragging ball");
- this.ball.x = x - this.offsetX;
- this.ball.y = y - this.offsetY;
+ this.ball.design.x = x - this.offsetX;
+ this.ball.design.y = y - this.offsetY;
this.drawField();
return;
}
@@ -648,7 +670,7 @@ export class FootballFieldComponent {
// Attacher le ballon si un joueur se rapproche suffisamment
const nearestPlayer = this.getNearestPlayerToBall();
- if (nearestPlayer && this.getDistance(this.ball, nearestPlayer) < this.magnetRadius) {
+ if (nearestPlayer && this.getDistance(this.ball.design, nearestPlayer) < this.magnetRadius) {
this.attachedPlayer = nearestPlayer;
this.updateBallPositionOnPlayer();
}
@@ -664,8 +686,8 @@ export class FootballFieldComponent {
if (this.draggingElement && this.draggingElement.isDragging) {
console.log("dragging element");
- this.draggingElement.x = x - this.offsetX;
- this.draggingElement.y = y - this.offsetY;
+ this.draggingElement.design.x = x - this.offsetX;
+ this.draggingElement.design.y = y - this.offsetY;
this.drawField();
return;
}
@@ -692,49 +714,12 @@ export class FootballFieldComponent {
}
}
- private moveAlongLine(player: Circle) {
- const dx = player.destinationX! - player.x;
- const dy = player.destinationY! - player.y;
- const distance = Math.sqrt(dx * dx + dy * dy);
-
- if (distance < 1) {
- player.x = player.destinationX!;
- player.y = player.destinationY!;
- player.isMoving = false;
- } else {
- player.vx = (dx / distance) * 2;
- player.vy = (dy / distance) * 2;
- player.x += player.vx;
- player.y += player.vy;
- }
- }
-
- private moveAlongCurve(player: Circle) {
- player.progress += 0.01;
- if (player.progress >= 1) {
- player.x = player.destinationX!;
- player.y = player.destinationY!;
- player.isMoving = false;
- player.progress = 0;
- } else {
- const t = player.progress;
- const x = (1 - t) * (1 - t) * player.x +
- 2 * (1 - t) * t * player.controlPointX! +
- t * t * player.destinationX!;
- const y = (1 - t) * (1 - t) * player.y +
- 2 * (1 - t) * t * player.controlPointY! +
- t * t * player.destinationY!;
- player.x = x;
- player.y = y;
- }
- }
-
private updateBallPositionOnPlayer() {
const player = this.attachedPlayer;
if (!player) return;
- const dx = this.ball.x - player.x;
- const dy = this.ball.y - player.y;
+ const dx = this.ball.design.x - player.x;
+ const dy = this.ball.design.y - player.y;
let angle = 0;
if (this.test) {
angle = Math.atan2(dy, dx);
@@ -744,25 +729,10 @@ export class FootballFieldComponent {
angle = this.prevAngle;
}
- this.ball.x = player.x + (player.radius + this.ball.radius) * Math.cos(angle);
- this.ball.y = player.y + (player.radius + this.ball.radius) * Math.sin(angle);
+ this.ball.design.x = player.x + (player.radius + this.ball.design.radius) * Math.cos(angle);
+ this.ball.design.y = player.y + (player.radius + this.ball.design.radius) * Math.sin(angle);
}
- // Calculer la nouvelle position du ballon a la tangente du joueur
-// private updateBallPositionOnTangent() {
-// const player = this.draggingPlayer;
-// if (!player) return;
-//
-// const dx = this.ball.x - player.x;
-// const dy = this.ball.y - player.y;
-// const distance = Math.sqrt(dx * dy + dy * dy); // Distance entre le joueur et le ballon
-// const angle = Math.atan2(dy, dx); // Calculer l'angle entre le joueur et le ballon
-//
-// // Positionner le ballon a la tangente du joueur
-// this.ball.x = player.x + Math.cos(angle) * (player.radius + this.ball.radius);
-// 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) {
@@ -783,7 +753,7 @@ export class FootballFieldComponent {
let minDistance = this.magnetRadius;
this.players.forEach(player => {
- const distance = this.getDistance(this.ball, player);
+ const distance = this.getDistance(this.ball.design, player);
if (distance < minDistance) {
minDistance = distance;
nearestPlayer = player;
@@ -807,12 +777,12 @@ export class FootballFieldComponent {
return nearestPlayer;
}
- private getDistance(circle1: Circle, circle2: Circle): number {
+ private getDistance(circle1: Circle2, circle2: Circle2): number {
return Math.sqrt((circle1.x - circle2.x) ** 2 + (circle1.y - circle2.y) ** 2);
}
// Vérifier si la souris et a l'intérieur d'un cercle
- private isInsideCircle(circle: Circle, x: number, y: number) {
+ private isInsideCircle(circle: Circle2, x: number, y: number) {
const distance = Math.sqrt((x - circle.x) ** 2 + (y - circle.y) ** 2);
return distance <= circle.radius;
}
@@ -828,104 +798,6 @@ export class FootballFieldComponent {
this.drawField();
}
-// // 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;
-// }
-
-// 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;
-//
-// 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;
-// }
-
-
- // Arrête de dessiner quand la souris est relâchée
-// stopDrawing() {
-// this.drawing = false;
-// }
-
// Obtient la position de la souris sur le canvas
private getMousePos(event: MouseEvent) {
const rect = this.canvas.nativeElement.getBoundingClientRect();
@@ -952,11 +824,6 @@ export class FootballFieldComponent {
//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;