Code edit (14 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: player1 is not defined' in or related to this line: 'if (!ball.currentPlayer) {' Line Number: 1294
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: currentPosture is not defined' in or related to this line: 'if (!player2.isThrowing) {' Line Number: 1354
Code edit (1 edits merged)
Please save this source code
Code edit (12 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'mesureFlag.x = targetPosition.x; // TEMP DEBUG' Line Number: 1329
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
in aiActing case MOVE_TO_THROW, move to a random courtPositions
Code edit (13 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of null (reading 'height')' in or related to this line: 'courtPositions.push({' Line Number: 670
User prompt
Add 9 points in courtPositions with values x: i * game.width / 4, y: courtTopY + i*3+j * court.height / 4, i and j going from 1 to 3
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of null (reading 'height')' in or related to this line: 'courtPositions.push({' Line Number: 670
User prompt
create a global array of objects, containing 9 positions: from x: 1*game.width / 4, y: courtTopY + 1* court.height / 4 to x: 3*game.width / 4, y: courtTopY + 3* court.height / 4
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
in if (self.isAI && self.moveToTarget && self.currentTargetPosition) , make the speed constant, not depending on distance
Code edit (1 edits merged)
Please save this source code
User prompt
in Player class , in updatePosition, implement case if (self.isAI && self.moveToTarget)
Code edit (6 edits merged)
Please save this source code
User prompt
instead of moving ai player in aiActing() case MOVE_TO_BALL, just set a target position. use Player's : self.currentTargetPosition = null; self.moveToTarget = false;
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
in aiActing, implement the case MOVE_TO_BALL
/**** * Classes ****/ /****************************************************************************************** */ /************************************** BALL ********************************************** */ /****************************************************************************************** */ // Ball class for the basketball var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('basketball', { anchorX: 0.5, anchorY: 0.5 }); self.followingSpeed = 1.0; // Increased speed when following target line self.fallingInitialSpeed = 20.0; // Increased speed when following target line self.speedY = 0; self.gravity = 0.5; self.isShot = false; self.isFollowTrajectory = false; self.isFalling = false; self.currentPlayer = null; // New property to track the current player holding the ball self.referenceX = null; self.fallingAngle = null; self.hasBumpedLeft = false; self.hasBumpedRight = false; self.collidedWithBumper = false; self.touchedBumper = null; self.initialXAmplitude = 75; // Amplitude of the sinusoidal movement self.initialXFrequency = 0.15; // Frequency of the sinusoidal movement self.Xamplitude = 0; self.XFrequency = 0; self.YAmplitude = 10; self.YFrequency = 0.05; self.refTicks = 0; self.shootBall = function () { console.log("Executing shootBall ", currentTrajectory); if (!currentTrajectory || currentTrajectory.length === 0) { console.log("No currentTrajectory"); return; } if (self.currentPlayer) { self.currentPlayer.hasBall = false; self.currentPlayer = null; } self.isFollowTrajectory = true; self.isShot = true; }; self.handleFollowing = function () { // Calculate progressive movement towards the next point in the trajectory var nextPoint = currentTrajectory[0]; var dx = nextPoint.x - self.x; var dy = nextPoint.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); //console.log("dx,dy=" + dx, dy, " distance =", distance); if (distance < 5) { //console.log("Close enough..."); // If close enough to the next point, move to the next point and remove it from the trajectory self.x = nextPoint.x; self.y = nextPoint.y; currentTrajectory.shift(); if (currentTrajectory.length === 0) { self.isFollowTrajectory = false; console.log("Trajectory end. Falling...", self.x, self.y, " / hoop :", basket.x, basket.y); // Pause for debug /* LK.setTimeout(function () { self.isFalling = true; }, 1000); */ self.isFalling = true; } } else { // Otherwise, move progressively towards the next point //console.log("following..."); //debugTxt.setText("following"); var speedX = dx * self.followingSpeed; var speedY = dy * self.followingSpeed; self.x += speedX; self.y += speedY; self.speedX = speedX * 0.5; // Store speedX self.speedY = speedY; // Store speedY self.lastSpeedX = speedX; // Store speedX self.lastSpeedY = speedY; // Store speedY } self.referenceX = null; }; self.handleFalling = function () { // Bullet Time effect //if (self.y < 350 && LK.ticks % 2 !== 0) { // return; // Simplify falling behavior // Apply gravity to speedY, increasing it over time to simulate acceleration with increasing factor // if (self.speedY != self.fallingInitialSpeed && self.fallingAngle == null) { // self.speedY = self.fallingInitialSpeed; // self.fallingAngle = 1; // TEMP DEBUG !!! // } self.gravity = 0.5; //self.y > courtTopBoundary ? 0.5 : 0.75; // Reset gravity to a constant value self.speedY += self.gravity; //console.log("handleFalling...", self.speedX, self.speedY, " bumping=" + self.collidedWithBumper); if (!self.collidedWithBumper && (self.intersects(basket.leftHoopBumper) || self.intersects(basket.rightHoopBumper))) { self.collidedWithBumper = true; self.touchedBumper = null; if (self.intersects(basket.leftHoopBumper)) { self.hasBumpedLeft = true; self.touchedBumper = basket.leftHoopBumper; //console.log("Bump left"); } else { self.hasBumpedRight = true; self.touchedBumper = basket.rightHoopBumper; //console.log("Bump right"); } var bumperX = basket.x + self.touchedBumper.x; var bumperY = basket.y + self.touchedBumper.y; var angleToBumper = Math.atan2(bumperY - self.y, bumperX - self.x); /* console.log("Init speed: " + Math.floor(self.speedX) + ", " + Math.floor(self.speedY)); console.log("Bump angle: " + angleToBumper + " => " + (angleToBumper * (180 / Math.PI)).toFixed(0) + "°"); console.log("Ball=" + Math.floor(self.x) + "," + Math.floor(self.y)); console.log("Bump=" + Math.floor(bumperX) + "," + Math.floor(bumperY)); */ // Calculate relative velocity components var relativeSpeedX = self.speedX * Math.cos(angleToBumper) + self.speedY * Math.sin(angleToBumper); var relativeSpeedY = self.speedX * Math.sin(angleToBumper) - self.speedY * Math.cos(angleToBumper); // Adjust speed based on impact relativeSpeedX *= -0.9; // Coefficient of restitution relativeSpeedY *= -0.5; // Reduced vertical rebound // Convert relative velocity components back to global coordinates self.speedX = relativeSpeedX * Math.cos(angleToBumper) - relativeSpeedY * Math.sin(angleToBumper); self.speedY = relativeSpeedX * Math.sin(angleToBumper) + relativeSpeedY * Math.cos(angleToBumper); // Apply dampening effect self.speedX *= 0.95; self.speedY *= 0.95; //console.log("Result speed: " + Math.floor(self.speedX) + ", " + Math.floor(self.speedY)); } else { // Ensure bumper is defined before accessing its properties if (self.collidedWithBumper && self.touchedBumper) { var bumperX = basket.x + self.touchedBumper.x; var bumperY = basket.y + self.touchedBumper.y; var distToBump = Math.sqrt(Math.pow(bumperX - self.x, 2) + Math.pow(bumperY - self.y, 2)); if (distToBump > 75) { //console.log("Stopped bumping. Dist=" + distToBump); self.collidedWithBumper = false; self.touchedBumper = null; } } } // Update the ball's position based on the current speedY and speedX self.x += self.speedX; self.y += self.speedY; // When ball is falling and reaches courtTopBoundary, make its x follow a sinusoidal curve if (self.y > courtTopBoundary) { if (self.referenceX == null) { self.fallingAngle = Math.PI / 4 + (self.lastSpeedX < 0 ? Math.PI / 2 : 0); self.referenceX = self.x; self.Xamplitude = self.initialXAmplitude; self.XFrequency = self.initialXFrequency; self.refTicks = LK.ticks; } self.Xamplitude *= 0.98; // Logarithmic decrease self.XFrequency -= 0.0001; if (self.Xamplitude > 1) { self.x = self.referenceX + (LK.ticks - self.refTicks) * 5 * Math.cos(self.fallingAngle) + self.Xamplitude * Math.abs(Math.sin(LK.ticks * self.XFrequency)); } } // Check boundaries and bounce if a border is reached if (self.y > courtBottomBoundary - self.height / 2) { self.y = courtBottomBoundary - self.height / 2; self.speedY *= -0.5; // Bounce back with reduced speed } if (self.x < courtLeftBoundary + self.width / 2) { self.x = courtLeftBoundary + self.width / 2; self.speedX *= -0.5; // Bounce back with reduced speed } else if (self.x > courtRightBoundary - self.width / 2) { self.x = courtRightBoundary - self.width / 2; self.speedX *= -0.5; // Bounce back with reduced speed } self.speedX *= 0.95; self.speedY *= 0.95; if (self.y > courtTopBoundary && Math.abs(self.speedX) < 1 && Math.abs(self.speedY) < 1) { // Adjust threshold for ending falling console.log("Too slow stop falling", self.speedY); self.isFalling = false; self.fallingAngle = null; self.hasBumpedLeft = false; self.hasBumpedRight = false; self.isShot = false; self.speedY = 0; self.speedX = 0; } }; self.update = function () { if (self.isShot) { if (self.isFollowTrajectory && currentTrajectory && currentTrajectory.length > 0) { self.handleFollowing(); } else if (self.isFalling) { self.handleFalling(); } else { debugTxt.setText("wait"); } } }; self.catched = function () { self.isFalling = false; self.fallingAngle = null; self.hasBumpedLeft = false; self.hasBumpedRight = false; self.collidedWithBumper = false; self.isShot = false; self.speedY = 0; self.speedX = 0; self.scoreCounted = false; }; self.reset = function () { self.x = 300; //1024; // Center X self.y = 2000; // Starting Y 500 -> 2565 self.isShot = false; self.speedY = 0; }; }); /****************************************************************************************** */ /************************************** BASKET ******************************************** */ /****************************************************************************************** */ // Basket class to group backboard, basketBallPost, and hoop var Basket = Container.expand(function () { var self = Container.call(this); self.x = 1024; self.y = 300; self.hoopX = 1024; self.hoopY = 270; self.hoopW = 182; self.hoppBumpW = 10; self.hoopLeftBumpX = 1024 - 182 / 2 + self.hoppBumpW / 2; self.hoopRightBumpX = 1024 + 182 / 2 - self.hoppBumpW / 2; // Create and attach basketBallPost asset self.basketBallPost = self.attachAsset('post', { anchorX: 0.5, anchorY: 1.0, x: 0, y: self.y + 150 // Base of the post aligns with the bottom of the Basket container }); // Create and attach backboard asset self.backboard = self.attachAsset('backBoard', { anchorX: 0.5, anchorY: 0.5, x: 0, y: self.y - 420 }); // Create and attach backboardInner part under backboard self.backboardInner = self.attachAsset('backBoardInner', { anchorX: 0.5, anchorY: 0.5, x: 0, y: self.y - 420 }); // Create and attach hoop asset self.hoop = self.attachAsset('hoop', { anchorX: 0.5, anchorY: 0.5, x: self.x - 1024, // Same as Basket y: self.y - 350 }); // Create and attach leftHoopBumper asset self.leftHoopBumper = self.attachAsset('hoopBumper', { anchorX: 0.5, anchorY: 0.5, x: self.hoopLeftBumpX - self.x, y: self.y - 350 }); // Create and attach rightHoopBumper asset self.rightHoopBumper = self.attachAsset('hoopBumper', { anchorX: 0.5, anchorY: 0.5, x: self.hoopRightBumpX - self.x, y: self.y - 350 }); }); /****************************************************************************************** */ /************************************** PLAYER ******************************************** */ /****************************************************************************************** */ var Player = Container.expand(function (isAI, tint) { var self = Container.call(this); self.isAI = isAI; // New property to indicate if the player is controlled by AI self.tint = tint; // Default tint color for player self.hasBall = false; // New property to indicate if the player has the ball self.currentPosture = ""; // New property to store the name of the current posture self.isChangingPosture = false; // 0 when idle or moving down, 1 when moving up self.nextPosture = null; self.isMovingUp = 0; // 0 when idle or moving down, 1 when moving up self.currentTargetPosition = null; self.moveToTarget = false; self.head = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 1, tint: self.tint }); self.eyes = self.attachAsset('eyes', { anchorX: 0.5, anchorY: 0.75, scaleX: 0.8, scaleY: 1, tint: 0xFFFFFF }); self.rightArm = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 1, scaleX: 0.5, scaleY: 1.5, tint: self.tint }); self.rightHand = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.75, scaleY: 0.5, tint: self.tint }); self.leftArm = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 1, scaleX: 0.5, scaleY: 1.5, tint: self.tint }); self.leftHand = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.75, scaleY: 0.5, tint: self.tint }); self.trunk = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 2.0, tint: self.tint }); self.rightLeg = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 2, tint: self.tint }); self.rightFoot = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.75, scaleY: 0.5, tint: self.tint }); self.leftLeg = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 2, tint: self.tint }); self.leftFoot = self.attachAsset('bodyPart', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.75, scaleY: 0.5, tint: self.tint }); self.updatePosture = function () { var speed = 0.2; //0.1; // Speed of transition if (!this.targetPosture) { return; } // Check if the target posture for hands and legs is reached //console.log("this.targetPosture: " + this.targetPosture.name + " : this.rightHand.x: " + this.rightHand.x, " this.targetPosture.rightHand.x: " + this.targetPosture.rightHand.x); var handsAndLegsReached = Math.abs(this.rightHand.x - this.targetPosture.rightHand.x) < 1 && Math.abs(this.rightHand.y - this.targetPosture.rightHand.y) < 1 && Math.abs(this.leftHand.x - this.targetPosture.leftHand.x) < 1 && Math.abs(this.leftHand.y - this.targetPosture.leftHand.y) < 1 && Math.abs(this.rightLeg.x - this.targetPosture.rightLeg.x) < 1 && Math.abs(this.rightLeg.y - this.targetPosture.rightLeg.y) < 1 && Math.abs(this.leftLeg.x - this.targetPosture.leftLeg.x) < 1 && Math.abs(this.leftLeg.y - this.targetPosture.leftLeg.y) < 1 && Math.abs(this.head.x - this.targetPosture.head.x) < 1 && Math.abs(this.head.y - this.targetPosture.head.y) < 1 && Math.abs(this.eyes.x - this.targetPosture.eyes.x) < 1 && Math.abs(this.eyes.y - this.targetPosture.eyes.y) < 1 && Math.abs(this.rightFoot.x - this.targetPosture.rightFoot.x) < 1 && Math.abs(this.rightFoot.y - this.targetPosture.rightFoot.y) < 1 && Math.abs(this.leftFoot.x - this.targetPosture.leftFoot.x) < 1 && Math.abs(this.leftFoot.y - this.targetPosture.leftFoot.y) < 1; if (handsAndLegsReached) { //console.log("handsAndLegsReached !"); // Update currentPosture to the name of the targetPosture when hands and legs posture is reached this.currentPosture = this.targetPosture.name; this.targetPosture = null; self.isChangingPosture = false; if (self.nextPosture) { self.setPosture(self.nextPosture); } return; } else { self.isChangingPosture = true; } if (this.targetPosture && this.targetPosture.head) { this.head.x += (this.targetPosture.head.x - this.head.x) * speed; } if (this.targetPosture && this.targetPosture.eyes) { this.eyes.x += (this.targetPosture.eyes.x - this.eyes.x) * speed; this.eyes.y += (this.targetPosture.eyes.y - this.eyes.y) * speed; self.updateEyes(); } this.head.y += (this.targetPosture.head.y - this.head.y) * speed; this.rightArm.x += (this.targetPosture.rightArm.x - this.rightArm.x) * speed; this.rightArm.y += (this.targetPosture.rightArm.y - this.rightArm.y) * speed; this.rightHand.x += (this.targetPosture.rightHand.x - this.rightHand.x) * speed; this.rightHand.y += (this.targetPosture.rightHand.y - this.rightHand.y) * speed; this.leftArm.x += (this.targetPosture.leftArm.x - this.leftArm.x) * speed; this.leftArm.y += (this.targetPosture.leftArm.y - this.leftArm.y) * speed; this.leftHand.x += (this.targetPosture.leftHand.x - this.leftHand.x) * speed; this.leftHand.y += (this.targetPosture.leftHand.y - this.leftHand.y) * speed; this.trunk.x += (this.targetPosture.trunk.x - this.trunk.x) * speed; this.trunk.y += (this.targetPosture.trunk.y - this.trunk.y) * speed; this.rightLeg.x += (this.targetPosture.rightLeg.x - this.rightLeg.x) * speed; this.rightLeg.y += (this.targetPosture.rightLeg.y - this.rightLeg.y) * speed; this.rightFoot.x += (this.targetPosture.rightFoot.x - this.rightFoot.x) * speed; this.rightFoot.y += (this.targetPosture.rightFoot.y - this.rightFoot.y) * speed; this.leftLeg.x += (this.targetPosture.leftLeg.x - this.leftLeg.x) * speed; this.leftLeg.y += (this.targetPosture.leftLeg.y - this.leftLeg.y) * speed; this.leftFoot.x += (this.targetPosture.leftFoot.x - this.leftFoot.x) * speed; this.leftFoot.y += (this.targetPosture.leftFoot.y - this.leftFoot.y) * speed; }; self.updatePosition = function () { self.isMoving = false; self.speedX = 0; self.speedY = 0; if (!self.isAI && joystickDrag && !isThrowingMode) { self.isMoving = true; var dx = joystick.x - joystickBasePosition.x; var dy = joystick.y - joystickBasePosition.y; self.speedX = dx * 0.15; // Adjust speed factor as needed self.speedY = dy * 0.15; // Adjust speed factor as needed } if (self.isAI && self.moveToTarget && self.currentTargetPosition) { var dx = self.currentTargetPosition.x - self.x; var dy = self.currentTargetPosition.y - self.y; self.speedX = dx > 50 ? 10 : dx < -50 ? -10 : 0; // Set constant speed regardless of distance self.speedY = dy > 50 ? 10 : dy < -50 ? -10 : 0; // Set constant speed regardless of distance // Check if the AI player has reached the target position within a certain threshold //console.log("dx,dy)", dx, dy, " => speedX,speedY", self.speedX, self.speedY); if (!self.speedX && !self.speedY) { console.warn("Reached target!"); self.moveToTarget = false; // Stop moving towards the target self.currentTargetPosition = null; // Clear the target position } } // Apply speed self.x += self.speedX; self.y += self.speedY; //debugTxt.setText("Player X: " + self.x.toFixed(2) + ", Y: " + self.y.toFixed(2)); //console.log("Player speedY: ", self.speedY); // Log player's vertical speed self.isMovingUp = self.speedY < 0 ? 1 : 0; self.updateEyes(); // Boundary checks if (self.x < courtLeftBoundary + self.width / 2) { self.x = courtLeftBoundary + self.width / 2; } else if (self.x > courtRightBoundary - self.width / 2) { self.x = courtRightBoundary - self.width / 2; } if (self.y < courtTopBoundary - 0) { self.y = courtTopBoundary - 0; } else if (self.y > courtBottomBoundary - 275) { self.y = courtBottomBoundary - 275; } // Posture updates based on movement if (self.isMoving) { var currentTick = LK.ticks; if (currentTick % 20 < 10) { self.setPosture(self.hasBall ? runningUpWithBall1 : runningUp1); } else { self.setPosture(self.hasBall ? runningUpWithBall2 : runningUp2); } } else { if (self.hasBall) { if (isThrowingMode) {} else { self.setPosture(Math.abs(ball.y - self.y) > 150 ? dribblingPosture1 : dribblingPosture2); } } else { //console.log("No ball => idle" + self.hasBall); self.setPosture(idlePosture); } } }; self.updateEyes = function () { self.eyes.visible = enableEye && !self.isMovingUp && (self.isAI || !isThrowingMode); }; self.setPosture = function (newPosture) { //console.log("Entering setPosture " + self.currentPosture + " => " + newPosture.name); if (self.isChangingPosture) { //console.log("Already changing"); // Store next posture for when target one is reached self.nextPosture = newPosture; return; } if (self.nextPosture) { // If a next posture is set, use it as target newPosture = self.nextPosture; self.nextPosture = null; } if (newPosture && self.currentPosture != newPosture.name) { self.targetPosture = newPosture; } else { //console.log("Already in posture"); } }; }); /****************************************************************************************** */ /************************************** TARGET LINE *************************************** */ /****************************************************************************************** */ // Class for the targeting line made of targetDots var TargetingLine = Container.expand(function () { var self = Container.call(this); self.dots = []; self.steps = 20; // Initialize 10 dots for the targeting line for (var i = 0; i < self.steps; i++) { var dot = self.attachAsset('targetDot', { anchorX: 0.5, anchorY: 0.5, visible: false // Initially not visible }); self.dots.push(dot); } // Method to update the targeting line self.updateLine = function (startX, startY, endX, endY) { // Controls only the dots positions, not their visibility if (this.isUpdating) { return; } this.isUpdating = true; // Calculate line direction and distance var dx = endX - startX; var dy = endY - startY; var distance = Math.sqrt(dx * dx + dy * dy); var parabolRatio = Math.min(Math.max(Math.abs(dy / 20), 10), 40); //console.log("dy: " + (dy + game.height * 0.25) + ", ParabolRatio: " + parabolRatio); var stepX = dx / self.steps; var stepY = dy / self.steps; // Update positions of existing dots along the line for (var i = 0; i < self.steps; i++) { if (self.dots[i]) { // Calculate offset to only go up var offset = -parabolRatio * i * Math.sin(Math.PI / self.steps * i); self.dots[i].x = startX + stepX * i; self.dots[i].y = startY + stepY * i + offset; } } this.isUpdating = false; // Store dots coordinates in currentTrajectory currentTrajectory = self.dots.map(function (dot) { return { x: dot.x, y: dot.y }; }); }; // Method to hide the targeting line self.showLine = function () { // Controls only the dots visibility, not their positions self.visible = true; self.dots.forEach(function (dot) { dot.visible = true; }); }; self.hideLine = function () { // Controls only the dots visibility, not their positions self.visible = false; self.dots.forEach(function (dot) { dot.visible = false; }); }; }); /**** * Initialize Game ****/ /******* Retro Basket ******** A retro basketball game. It's a one vs one basketball game. Ball is lanched in the middle. Players must run and catch it, then throw it in the hoop. *****************************/ var game = new LK.Game({ backgroundColor: 0x000000 // Sky blue background }); /**** * Game Code ****/ // Enumeration for AI states var AI_STATE = { IDLE: 'IDLE', MOVE_TO_BALL: 'MOVE_TO_BALL', MOVE_TO_BLOCK: 'MOVE_TO_BLOCK', BLOCKING: 'BLOCKING', MOVE_TO_THROW: 'MOVE_TO_THROW', THROWING: 'THROWING' }; // Enumeration for game states var GAME_STATE = { INIT: 'INIT', MENU: 'MENU', STARTING: 'STARTING', PLAYING: 'PLAYING', SCORE: 'SCORE' }; var gameState = GAME_STATE.INIT; var aiState = AI_STATE.IDLE; var isDebug = true; var player = null; var player2 = null; var ball = null; var basket = null; var court = null; var courtBackground = null; var startButton = null; var mesureFlag = null; var joystick = null; var debugTxt = null; var scoreTxt = null; var score = 0; var joystickBasePosition = null; var joystickDrag = false; var lastTouchDownTime = 0; // Timestamp of the last touch down event var touchTapThreshold = 200; // Milliseconds within which a touch is considered a tap var isTapGesture = false; // Flag to differentiate between tap and drag gestures var isThrowingMode = 0; // 0 = Move mode; 1 = Throw mode var targetingLine = null; var enableEye = true; var courtTopY = 750; var courtCenterY = 1500; // court asset height 2056/2+750 (top) = 1778 ~= 1700 | v2 : 2250/2+750 = 1875 var courtBottomY = 2240; var targetPointXOffsetDirection = 1; var targetPointYOffsetDirection = 1; var targetPointXOffset = 0; var targetPointYOffset = -50; // Offset above hoop for targetting var targetPointXOffsetIncrement = 5; // Increment or decrement offset by 10 var targetPointXOffsetBounds = 220; // Bounds for changing direction var targetPointYOffsetIncrement = 2; // Increment or decrement offset by 10 var targetPointYOffsetBounds = 100; // Bounds for changing direction var currentTrajectory = []; // Define court boundaries as global variables var courtTopBoundary = 750 - 230; var courtBottomBoundary = 2240; var courtLeftBoundary = 0; var courtRightBoundary = 2048; // Global array to store court positions var courtPositions = []; for (var i = 1; i <= 3; i++) { for (var j = 1; j <= 3; j++) { courtPositions.push({ x: i * game.width / 4, y: courtTopY + (i * 3 + j) * court.height / 4 }); } } // Moved courtPositions population to gameInitialize to ensure game object is initialized var distanceImprecisionMin = 1; var distanceImprecisionMax = 20; /****************************************************************************************** */ /************************************** POSTURES ****************************************** */ /****************************************************************************************** */ var idlePosture = { name: "idlePosture", x: 1024, y: 2000, head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 110, y: 50 }, rightHand: { x: 125, y: 30 }, leftArm: { x: -110, y: 50 }, leftHand: { x: -120, y: 30 }, trunk: { x: 0, y: 0 }, rightLeg: { x: 37.5, y: 150 }, rightFoot: { x: 50, y: 250 }, leftLeg: { x: -37.5, y: 150 }, leftFoot: { x: -50, y: 250 } }; var dribblingPosture1 = { name: "dribblingPosture1", x: 1024, // Center X y: 2000, // Player Y position head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 90, y: 50 // Adjusted from -20 to 50 }, rightHand: { x: -90, y: 30 }, leftArm: { x: -90, y: 50 // Adjusted from -20 to 50 }, leftHand: { x: 90, y: 30 }, trunk: { x: 0, y: 0 }, rightLeg: { x: 40, y: 150 }, rightFoot: { x: 50, y: 250 }, leftLeg: { x: -40, y: 150 }, leftFoot: { x: -50, y: 250 } }; var dribblingPosture2 = { name: "dribblingPosture2", x: 1024, // Center X y: 2000, // Player Y position head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 90, y: 50 // Adjusted from -20 to 50 }, rightHand: { x: -90, y: 50 }, leftArm: { x: -90, y: 50 // Adjusted from -20 to 50 }, leftHand: { x: 90, y: 50 }, trunk: { x: 0, y: 0 }, rightLeg: { x: 40, y: 150 }, rightFoot: { x: 50, y: 250 }, leftLeg: { x: -40, y: 150 }, leftFoot: { x: -50, y: 250 } }; var runningUp1 = { name: "runningUp1", x: 1024, // Center X y: 2000, // Player Y position head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 90, y: 50 // Adjusted from -20 to 50 by adding 70 }, rightHand: { x: 105, y: 30 }, leftArm: { x: -90, y: 50 }, leftHand: { x: -105, y: 30 }, trunk: { x: 0, y: 0 }, rightLeg: { x: 40, y: 100 }, rightFoot: { x: 50, y: 200 }, leftLeg: { x: -40, y: 150 }, leftFoot: { x: -50, y: 250 } }; var runningUp2 = { name: "runningUp2", x: 1024, // Center X y: 2000, // Player Y position head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 80, y: 50 // Adjusted from -20 to 50 by adding 70 }, rightHand: { x: 95, y: 30 }, leftArm: { x: -80, y: 50 }, leftHand: { x: -95, y: 30 }, trunk: { x: 0, y: 0 }, rightLeg: { x: 40, y: 150 }, rightFoot: { x: 50, y: 250 }, leftLeg: { x: -40, y: 100 }, leftFoot: { x: -50, y: 200 } }; var runningUpWithBall1 = { name: "runningUpWithBall1", x: 1024, // Center X y: 2000, // Player Y position head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 90, y: 20 // Adjusted from -20 to 50 by adding 70 }, rightHand: { x: -0, y: -20 }, leftArm: { x: -90, y: 20 }, leftHand: { x: 0, y: -20 }, trunk: { x: 0, y: 0 }, rightLeg: { x: 40, y: 100 }, rightFoot: { x: 50, y: 200 }, leftLeg: { x: -40, y: 150 }, leftFoot: { x: -50, y: 250 } }; var runningUpWithBall2 = { name: "runningUpWithBall2", x: 1024, // Center X y: 2000, // Player Y position head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 80, y: -20 // Adjusted from -90 to -20 by adding 70 }, rightHand: { x: 5, y: 15 }, leftArm: { x: -80, y: -20 }, leftHand: { x: 5, y: 15 }, trunk: { x: 0, y: 0 }, rightLeg: { x: 40, y: 150 }, rightFoot: { x: 50, y: 250 }, leftLeg: { x: -40, y: 100 }, leftFoot: { x: -50, y: 200 } }; var throwingPosture = { name: "throwingPosture", x: 1024, y: 2000, head: { x: 0, y: -160 }, eyes: { x: 0, y: -160 }, rightArm: { x: 100, y: -120 }, rightHand: { x: 100, y: -250 // Set the right hand at the top of the right arm }, leftArm: { x: -100, y: -120 }, leftHand: { x: -100, y: -250 // Set the left hand at the top of the left arm }, trunk: { x: 0, y: 0 }, rightLeg: { x: 37.5, y: 150 }, rightFoot: { x: 50, y: 250 }, leftLeg: { x: -37.5, y: 150 }, leftFoot: { x: -50, y: 250 } }; /****************************************************************************************** */ /*********************************** UTILITY FUNCTIONS ************************************ */ /****************************************************************************************** */ function isPointInEllipse(x, y) { console.log("isPointInEllipse:", x, y); // Coordonnées du centre de l'ellipse var x0 = 1024; // Centre du canvas var y0 = 1170; // Centre du canvas var rX = 720; var rY = 600; var dX = Math.abs(x - x0); var dY = Math.abs(y - y0); var d = Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2)); // Calcul de l'angle polaire du point par rapport au centre de l'ellipse var angle = Math.atan2(y - y0, x - x0); if (angle < 0) { angle += 2 * Math.PI; // Convertit l'angle en radians positifs } var factor = Math.abs(Math.cos(angle)); // factor will be 1 at 0, PI/2, PI, 3*PI/2 and smaller near PI/4 and 3*PI/4 var xt = x0 + rX * Math.cos(angle) / Math.sqrt(1 / factor); var yt = y0 + rY * Math.sin(angle); var radiusAtAngle = Math.sqrt(Math.pow(xt - x0, 2) + Math.pow(yt - y0, 2)); /* mesureFlag.x = x0; mesureFlag.y = y0; mesureFlag.rotation = angle; mesureFlag.width = d; console.log("Angle : ", angle, "Radius : ", radiusAtAngle, "Dist : ", d, " => inside ", d <= radiusAtAngle); drawElipse(x0, y0, rX, rY); */ return d <= radiusAtAngle; } function drawElipse(x0, y0, rX, rY) { for (var angle = 0; angle < 2 * Math.PI; angle += 0.1) { var factor = Math.abs(Math.cos(angle)); // factor will be 1 at 0, PI/2, PI, 3*PI/2 and smaller near PI/4 and 3*PI/4 var xt = x0 + rX * Math.cos(angle) / Math.sqrt(1 / factor); var yt = y0 + rY * Math.sin(angle); // / Math.sqrt(factor * 1.0); var dot = game.addChild(LK.getAsset('targetDot', { anchorX: 0.5, anchorY: 0.5, x: xt, y: yt, visible: true })); } } /****************************************************************************************** */ /*********************************** INPUT HANDLERS *************************************** */ /****************************************************************************************** */ function onDownPlaying(obj) { lastTouchDownTime = Date.now(); // Capture the current timestamp when touch starts var pos = obj.event.getLocalPosition(game); // Calculate distance between click and joystick center var distance = Math.sqrt(Math.pow(pos.x - joystick.x, 2) + Math.pow(pos.y - joystick.y, 2)); // If click is within joystick radius, start dragging if (distance <= joystick.width / 2) { joystickDrag = true; } } function onMovePlaying(obj) { var pos = obj.event.getLocalPosition(game); if (joystickDrag) { var dx = pos.x - joystickBasePosition.x; var dy = pos.y - joystickBasePosition.y; var distance = Math.sqrt(dx * dx + dy * dy); var maxDistance = joystick.width / 4; // Max distance joystick can move from center if (distance > maxDistance) { var angle = Math.atan2(dy, dx); dx = Math.cos(angle) * maxDistance; dy = Math.sin(angle) * maxDistance; } joystick.x = joystickBasePosition.x + dx; joystick.y = joystickBasePosition.y + dy; if (isThrowingMode) { //console.log("Using joysting in throwing mode..."); var armRotationFactor = 0.05; // Factor to control the rotation sensitivity var armRotation = Math.max(-Math.PI / 1.8, Math.min(Math.PI / 1.8, dx * armRotationFactor)); // Clamp rotation between -100 and 100 degrees converted to radians // Log armRotation in degrees //console.log("Arm rotation: " + (armRotation * (180 / Math.PI)).toFixed(2) + " degrees"); player.rightArm.rotation = armRotation; player.leftArm.rotation = armRotation; // Calculate the top position of the arms and move hands to follow the arms' movement var rightArmTopX = player.rightArm.x + Math.cos(player.rightArm.rotation - Math.PI / 2) * (player.rightArm.height + player.rightHand.height / 1.5); var rightArmTopY = player.rightArm.y + Math.sin(player.rightArm.rotation - Math.PI / 2) * (player.rightArm.height + player.rightHand.height / 1.5); var leftArmTopX = player.leftArm.x + Math.cos(player.leftArm.rotation - Math.PI / 2) * (player.leftArm.height + player.rightHand.height / 1.5); var leftArmTopY = player.leftArm.y + Math.sin(player.leftArm.rotation - Math.PI / 2) * (player.leftArm.height + player.rightHand.height / 1.5); //console.log("rightArmTopX: " + rightArmTopX.toFixed(2) + " y " + rightArmTopY.toFixed(2)); player.rightHand.x = rightArmTopX; player.rightHand.y = rightArmTopY; player.leftHand.x = leftArmTopX; player.leftHand.y = leftArmTopY; } else { //console.log("Using joysting in moving mode..."); } } } function onUpPlaying(obj) { var touchDuration = Date.now() - lastTouchDownTime; // Calculate the duration of the touch isTapGesture = touchDuration <= touchTapThreshold; // Determine if the gesture is a tap based on the duration if (isTapGesture && player.hasBall) { if (isThrowingMode == 1) { var targetPointX = basket.hoop.x; var targetPointY = basket.hoop.y; ball.shootBall(targetPointX, targetPointY); player.hasBall = false; } isThrowingMode = 1 - isThrowingMode; // Toggle isThrowingMode between 0 and 1 console.log("isThrowingMode: " + isThrowingMode); // Log the current joystick mode // Correctly toggle the joystick asset based on isThrowingMode if (isThrowingMode == 1) { joystick.attachAsset('buttonA', { anchorX: 0.5, anchorY: 0.5 }); player.setPosture(throwingPosture); console.log("=> show targeting line"); // Log the current joystick mode LK.setTimeout(function () { targetingLine.showLine(); }, 250); } else { player.rightArm.rotation = 0; player.leftArm.rotation = 0; joystick.attachAsset('joystick', { anchorX: 0.5, anchorY: 0.5 }); targetingLine.hideLine(); // Hide targeting line } joystickDrag = false; } else if (joystickDrag) { joystickDrag = false; joystick.x = joystickBasePosition.x; joystick.y = joystickBasePosition.y; } } game.on('down', function (obj) { switch (gameState) { case GAME_STATE.MENU: // Handle menu logic here break; case GAME_STATE.STARTING: // Handle game starting logic here break; case GAME_STATE.PLAYING: onDownPlaying(obj); break; case GAME_STATE.SCORE: // Handle score display logic here break; } }); game.on('move', function (obj) { switch (gameState) { case GAME_STATE.MENU: // Handle menu logic here break; case GAME_STATE.STARTING: // Handle game starting logic here break; case GAME_STATE.PLAYING: onMovePlaying(obj); break; case GAME_STATE.SCORE: // Handle score display logic here break; } }); game.on('up', function (obj) { switch (gameState) { case GAME_STATE.MENU: // Handle menu logic here break; case GAME_STATE.STARTING: // Handle game starting logic here break; case GAME_STATE.PLAYING: onUpPlaying(obj); break; case GAME_STATE.SCORE: // Handle score display logic here break; } }); // Test postures /* var idle = true; var changePostureTimer = LK.setInterval(function () { if (idle) { player.setPosture(runningUp1); idle = false; } else { player.setPosture(runningUp2); idle = true; } }, 1000); */ /****************************************************************************************** */ /************************************* AI FUNCTIONS **************************************** */ /****************************************************************************************** */ function aiThinking() { if (LK.ticks % 60 !== 0) { return; } var initState = aiState; // Determine AI state based on the ball's situation if (!ball.currentPlayer) { // If the ball is not currently hold, move towards the ball aiState = AI_STATE.MOVE_TO_BALL; } else if (ball.currentPlayer === player2) { // If the ball is being shot and the AI is the current player, prepare to throw aiState = AI_STATE.MOVE_TO_THROW; } else if (ball.currentPlayer && ball.currentPlayer !== player2) { // If the ball is being shot and the AI is not the current player, attempt to block aiState = AI_STATE.MOVE_TO_BLOCK; } // Log the current AI state for debugging purposes console.log("aiThinking... State: " + initState + " -> " + aiState); } function aiActing() { if (LK.ticks % 10 !== 0) { return; } console.log("aiActing... State: " + aiState); switch (aiState) { case AI_STATE.MOVE_TO_BALL: if (!player2.currentTargetPosition) { player2.currentTargetPosition = { x: ball.x, y: ball.y }; player2.moveToTarget = true; } else { console.log("Already have target..."); } break; case AI_STATE.MOVE_TO_THROW: break; case AI_STATE.MOVE_TO_BLOCK: break; default: // IDLE break; } } /****************************************************************************************** */ /************************************* GAME STATES **************************************** */ /****************************************************************************************** */ function gameInitialize() { courtBackground = game.addChild(LK.getAsset('courtBackground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: courtCenterY })); court = game.addChild(LK.getAsset('Court', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: courtCenterY, scaleX: 1.08, scaleY: 0.90, tint: 0xb27747 })); basket = game.addChild(new Basket()); startButton = game.addChild(LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, visible: false, interactive: false })); mesureFlag = game.addChild(LK.getAsset('mesureFlag', { anchorX: 0, anchorY: 0.5, x: 3 * game.width / 4, y: courtTopY + 3 * court.height / 4, width: 20, rotation: 2 * Math.PI / 2, visible: isDebug })); debugTxt = new Text2("Court Top: " + (court.y - court.height / 2), { size: 50, fill: "#ffffff" }); debugTxt.visible = isDebug; debugTxt.x = 20; debugTxt.y = 20; LK.gui.topLeft.addChild(debugTxt); gameInitStateMenu(); } function gameSwitchNextState() { console.log("gameSwitchNextState...from", gameState); switch (gameState) { case GAME_STATE.MENU: gameCleanStateMenu(); gameInitStateStarting(); break; case GAME_STATE.STARTING: gameCleanStateStarting(); gameInitStatePlaying(); break; case GAME_STATE.PLAYING: break; case GAME_STATE.SCORE: // Handle score display logic here break; default: // INIT gameInitStateMenu(); break; } } function gameInitStateMenu() { console.log("gameInitStateMenu..."); gameState = GAME_STATE.MENU; startButton.visible = true; startButton.interactive = true; // Add event listener to startButton to switch game state on press startButton.on('down', function () { var originalWidth = startButton.width; var originalHeight = startButton.height; var shrinkWidth = originalWidth * 0.6; var shrinkHeight = originalHeight * 0.6; var enlargeWidth = originalWidth * 20; var enlargeHeight = originalHeight * 20; var animationSteps = 100; var currentStep = 0; startButton.alpha = 1; var animationInterval = LK.setInterval(function () { if (currentStep < animationSteps / 5) { // Shrink startButton.width -= (originalWidth - shrinkWidth) / (animationSteps / 5); startButton.height -= (originalHeight - shrinkHeight) / (animationSteps / 5); } else if (currentStep < animationSteps) { // Enlarge startButton.width += (enlargeWidth - originalWidth) / (animationSteps / 5); startButton.height += (enlargeHeight - originalHeight) / (animationSteps / 5); startButton.alpha -= 0.01; } else { // Reset to original size and clear interval startButton.width = originalWidth; startButton.height = originalHeight; LK.clearInterval(animationInterval); gameSwitchNextState(); } currentStep++; }, 5); }); debugTxt.setText("MENU"); } function gameCleanStateMenu() { console.log("gameCleanStateMenu..."); startButton.visible = false; startButton.interactive = false; debugTxt.setText("MENU => STARTING"); } function gameInitStateStarting() { console.log("gameInitStateStarting..."); gameState = GAME_STATE.STARTING; debugTxt.setText("STARTING"); // Create and position the joystick joystick = game.addChild(LK.getAsset('joystick', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75, x: 2048 / 2, y: 2732 - 300 })); player = game.addChild(new Player(false, 0x0000FF)); player.x = 800; //2048 / 2; // Center X player.y = 2000; //2732 / 2; // Center Y player.setPosture(idlePosture); player2 = game.addChild(new Player(true, 0xFF0000)); // Instantiate player2 as AI with red tint player2.x = 1248; // Position player2 slightly to the right of player1 player2.y = 2000; // Same Y position as player1 player2.setPosture(idlePosture); ball = game.addChild(new Ball()); ball.reset(); scoreTxt = new Text2(score.toString(), { size: 150, fill: "#ffffff" }); scoreTxt.x = -180; scoreTxt.y = -10; LK.gui.topRight.addChild(scoreTxt); joystickBasePosition = { x: joystick.x, y: joystick.y }; targetingLine = new TargetingLine(); game.addChild(targetingLine); LK.setTimeout(gameSwitchNextState, 1000); } function gameCleanStateStarting() { console.log("gameCleanStateStarting..."); debugTxt.setText("STARTING => PLAYING"); } function gameInitStatePlaying() { console.log("gameInitStatePlaying..."); gameState = GAME_STATE.PLAYING; debugTxt.setText("PLAYING"); } function gamePlaying() { ball.update(); // Check if player's trunk intersects with the ball if (!ball.currentPlayer) { if (player.trunk.intersects(ball) || player.rightLeg.intersects(ball) || player.leftLeg.intersects(ball)) { ball.currentPlayer = player; // Assign the player to the ball's currentPlayer property ball.catched(); player.hasBall = true; // Assign the player to the ball's currentPlayer property } if (player2.trunk.intersects(ball) || player2.rightLeg.intersects(ball) || player2.leftLeg.intersects(ball)) { ball.currentPlayer = player2; // Assign the player to the ball's currentPlayer property ball.catched(); player2.hasBall = true; // Assign the player to the ball's currentPlayer property } } // Make the ball follow the currentPlayer's position with dribble movement if (ball.currentPlayer && !ball.isFollowTrajectory) { ball.x = ball.currentPlayer.x; if (isThrowingMode == 1) { // Dynamically make the ball follow the player's hands position in throwing mode // Calculate the middle position between the two hands var middleHandX = (ball.currentPlayer.rightHand.x + ball.currentPlayer.leftHand.x) / 2 + ball.currentPlayer.x; var middleHandY = (ball.currentPlayer.rightHand.y + ball.currentPlayer.leftHand.y) / 2 + ball.currentPlayer.y; ball.x = middleHandX; ball.y = middleHandY; //Update the targeting line from the ball to the hoop var distanceToHoop = Math.sqrt(Math.pow(basket.x - ball.currentPlayer.x, 2) + Math.pow(basket.y - ball.currentPlayer.y, 2)); // Calculate distanceImprecisionRatio based on distanceToHoop, clamped between 0.5 and 2 var distanceImprecisionRatio = Math.min(Math.max(distanceToHoop / 600, distanceImprecisionMin), distanceImprecisionMax); targetPointXOffset += targetPointXOffsetDirection * targetPointXOffsetIncrement * distanceImprecisionRatio; // Increment or decrement offset if (targetPointXOffset >= targetPointXOffsetBounds || targetPointXOffset <= -targetPointXOffsetBounds) { targetPointXOffsetDirection *= -1; // Change direction } targetPointYOffset += targetPointYOffsetDirection * targetPointYOffsetIncrement * distanceImprecisionRatio; // Increment or decrement offset if (targetPointYOffset >= targetPointYOffsetBounds || targetPointYOffset <= -targetPointYOffsetBounds) { targetPointYOffsetDirection *= -1; } var targetPointX = basket.x + targetPointXOffset + (middleHandX - ball.currentPlayer.x); var targetPointY = basket.y + targetPointYOffset + (middleHandY - ball.currentPlayer.y + 200); targetingLine.updateLine(ball.x, ball.y, targetPointX, targetPointY); // This line is removed to rely on updateLine method for visibility control game.addChild(ball.currentPlayer); // Ensure player is in front by re-adding it to the game } else if (ball.currentPlayer.isMovingUp === 0) { targetingLine.hideLine(); ball.y = ball.currentPlayer.y + 150 + Math.sin(LK.ticks / (ball.currentPlayer.isMoving ? 4 : 7)) * 100; game.addChild(ball); // Ensure ball is in front by re-adding it to the game } else { targetingLine.hideLine(); ball.y = ball.currentPlayer.y - 120 + Math.sin(LK.ticks / (ball.currentPlayer.isMoving ? 4 : 7)) * 50; game.addChild(ball.currentPlayer); // Ensure player is in front by re-adding it to the game } } player.updatePosture(); player.updatePosition(); player2.updatePosture(); player2.updatePosition(); // Re-add joystick to ensure it appears above other elements game.addChild(joystick); // Check if ball intersects with hoop and is moving downwards // Check if ball is passing between the hoop bumpers and moving downwards if (ball.y - ball.height / 2 < basket.hoopY && ball.speedY > 0 && ball.x > basket.hoopLeftBumpX && ball.x < basket.hoopRightBumpX && !ball.scoreCounted) { ball.aboveHoop = true; } else if (ball.aboveHoop && ball.y > basket.hoopY && ball.y < basket.hoopY + ball.height && ball.speedY > 0 && ball.x > basket.hoopLeftBumpX && ball.x < basket.hoopRightBumpX && !ball.scoreCounted) { var refX = player.x; var refY = player.y; refX += player.x > 1024 ? player.leftFoot.x : player.rightFoot.x; refY += player.x > 1024 ? player.leftFoot.y : player.rightFoot.y; console.log("isPointInEllipse:", isPointInEllipse(refX, refY)); var pointsScored = 2; // Default to 2 points if (refY <= 1170) { // Top rectangle area if (refX <= 300 || refX >= 1740) { pointsScored = 3; // Award 3 points for shots from the sides within the specified Y range } } else { // Elipse area pointsScored = isPointInEllipse(refX, refY) ? 2 : 3; } console.log(refX, refY, "=> " + Math.floor(Math.sqrt(Math.pow(refX - 1024, 2) + Math.pow(refY - 1200, 2))) + " => " + pointsScored + "pts"); score += pointsScored; scoreTxt.setText(score.toString()); ball.scoreCounted = true; // Mark score as counted to prevent multiple increments ball.aboveHoop = false; // Reset aboveHoop flag after scoring } // Reset ball if it goes off-screen // Check Y boundaries for the ball if (!ball.isFollowTrajectory && !ball.isFalling) { // when isFollowTrajectory might pass the top of screen if (ball.y < 0 + ball.height / 2) { ball.y = 0 + ball.height / 2; ball.speedY *= -0.5; // Bounce back with reduced speed } if (ball.y > courtBottomBoundary - ball.height / 2) { ball.y = courtBottomBoundary - ball.height / 2; ball.speedY *= -0.5; // Bounce back with reduced speed } } aiThinking(); aiActing(); } LK.on('tick', function () { switch (gameState) { case GAME_STATE.MENU: // Handle menu logic here break; case GAME_STATE.STARTING: // Handle game starting logic here break; case GAME_STATE.PLAYING: gamePlaying(); break; case GAME_STATE.SCORE: // Handle score display logic here break; } }); gameInitialize();
===================================================================
--- original.js
+++ change.js
@@ -640,8 +640,16 @@
var courtLeftBoundary = 0;
var courtRightBoundary = 2048;
// Global array to store court positions
var courtPositions = [];
+for (var i = 1; i <= 3; i++) {
+ for (var j = 1; j <= 3; j++) {
+ courtPositions.push({
+ x: i * game.width / 4,
+ y: courtTopY + (i * 3 + j) * court.height / 4
+ });
+ }
+}
// Moved courtPositions population to gameInitialize to ensure game object is initialized
var distanceImprecisionMin = 1;
var distanceImprecisionMax = 20;
/****************************************************************************************** */