Code edit (1 edits merged)
Please save this source code
User prompt
log shootBall
User prompt
implement the shootBall function
User prompt
Please fix the bug: 'TypeError: ball.throwBall is not a function' in or related to this line: 'ball.throwBall(targetPointX, targetPointY);' Line Number: 928
Code edit (12 edits merged)
Please save this source code
User prompt
when Tap Gesture is made in throwing mode, lauch the ball with the same sinosoidal trajectory as used for targetline
Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 1002
User prompt
call if (!player.isChangingPosture) { targetingLine.updateLine(ball.x, ball.y, hoop.x, hoop.y); } only after a timeout of 300
User prompt
call targetingLine.updateLine(ball.x, ball.y, hoop.x, hoop.y); only when player isChangingPosture == false;
Code edit (1 edits merged)
Please save this source code
User prompt
When switching to thowingMode Ensure player is in front in by re-adding it
User prompt
Ensure player is in front in thowingMode by re-adding it
Code edit (2 edits merged)
Please save this source code
User prompt
before handsAndLegsReached log this.rightHand.x and this.targetPosture.rightHand.x
Code edit (8 edits merged)
Please save this source code
User prompt
in handsAndLegsReached, check that all body parts arrived
Code edit (1 edits merged)
Please save this source code
Code edit (4 edits merged)
Please save this source code
User prompt
console log distance and parabolRatio
User prompt
Make parabolRatio depend on distance. And clamp it between 60 and 120
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Update the offset to draw only half of it
Code edit (2 edits merged)
Please save this source code
/**** 
* Classes
****/ 
// Assets will be automatically created based on usage in the code.
// 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.speedY = 0;
	self.gravity = 0.5;
	self.isShot = false;
	self.currentPlayer = null; // New property to track the current player holding the ball
	self.shoot = function (power, angle) {
		self.speedX = Math.cos(angle) * power;
		self.speedY = Math.sin(angle) * -power; // Negate Y to move up
		self.isShot = true;
	};
	self.update = function () {
		if (self.isShot) {
			self.x += self.speedX;
			self.y += self.speedY;
			// Removed gravity effect for isometric view
			// Boundary checks
			if (self.x < courtLeftBoundary + self.width / 2) {
				self.x = courtLeftBoundary + self.width / 2;
				self.speedX *= -0.5; // Bounce back with reduced speed
			}
			if (self.x > courtRightBoundary - self.width / 2) {
				self.x = courtRightBoundary - self.width / 2;
				self.speedX *= -0.5; // Bounce back with reduced speed
			}
		}
	};
	self.reset = function () {
		self.x = 300; //1024; // Center X
		self.y = 2000; // Starting Y
		self.isShot = false;
		self.speedY = 0;
	};
});
// Hoop class for the basketball hoop
var Hoop = Container.expand(function () {
	var self = Container.call(this);
	var hoopGraphics = self.attachAsset('hoop', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.setPosition = function () {
		self.x = 1024; // Center X
		self.y = 200; // Hoop Y position
	};
});
// Player class for the player
var Player = Container.expand(function () {
	var self = Container.call(this);
	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.isMovingUp = 0; // 0 when idle or moving down, 1 when moving up
	self.head = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.8,
		scaleY: 1
	});
	self.eyes = self.attachAsset('eyes', {
		anchorX: 0.5,
		anchorY: 0.75,
		scaleX: 0.8,
		scaleY: 1
	});
	self.rightArm = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 1,
		scaleX: 0.5,
		scaleY: 1.5
	});
	self.rightHand = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.75,
		scaleY: 0.5
	});
	self.leftArm = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 1,
		scaleX: 0.5,
		scaleY: 1.5
	});
	self.leftHand = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.75,
		scaleY: 0.5
	});
	self.trunk = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 2.0
	});
	self.rightLeg = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.5,
		scaleY: 2
	});
	self.rightFoot = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.75,
		scaleY: 0.5
	});
	self.leftLeg = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.5,
		scaleY: 2
	});
	self.leftFoot = self.attachAsset('bodyPart', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.75,
		scaleY: 0.5
	});
	self.updatePosture = function () {
		var speed = 0.2; //0.1; // Speed of transition
		if (!this.targetPosture) {
			return;
		}
		//this.x += (this.targetPosture.x - this.x) * speed;
		//this.y += (this.targetPosture.y - this.y) * speed;
		// Check if the target posture for hands and legs is reached
		console.log("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 (this.targetPosture && 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;
			return;
		}
		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;
			this.eyes.visible = enableEye && this.isMovingUp === 1;
		}
		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 (joystickDrag) {
			if (isThrowingMode) {} else {
				self.isMoving = true;
				var dx = joystick.x - joystickBasePosition.x;
				var dy = joystick.y - joystickBasePosition.y;
				self.speedX = dx * 0.1; // Adjust speed factor as needed
				self.speedY = dy * 0.1; // Adjust speed factor as needed
			}
		}
		// Apply speed
		self.x += self.speedX;
		self.y += self.speedY;
		//console.log("Player speedY: ", self.speedY); // Log player's vertical speed
		self.isMovingUp = self.speedY < 0 ? 1 : 0;
		self.eyes.visible = enableEye && (this.isMovingUp === 0 || isThrowingMode);
		// 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 + self.height / 2) {
			self.y = courtTopBoundary + self.height / 2;
		} else if (self.y > courtBottomBoundary - 500 - self.height / 2) {
			self.y = courtBottomBoundary - 500 - self.height / 2;
		}
		// 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.setPosture = function (newPosture) {
		console.log("Entering setPosture " + self.currentPosture + " => " + newPosture.name);
		if (self.currentPosture != newPosture.name) {
			self.targetPosture = newPosture;
		} else {
			console.log("Already in posture");
		}
	};
	// self.goToPoint = function (newPosition) {
	// 	self.targetPoint = newPosition;
	// };
});
// Class for the targeting line made of targetDots
var TargetingLine = Container.expand(function () {
	var self = Container.call(this);
	self.dots = [];
	self.steps = 20;
	//self.visible = false; // Initially not visible
	// 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) {
		if (this.isUpdating) {
			return;
		}
		this.isUpdating = true;
		// Hide dots
		for (var i = 0; i < self.steps; i++) {
			if (self.dots[i]) {
				self.dots[i].visible = false;
			}
		}
		// 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;
				self.dots[i].visible = true;
			}
		}
		// Hide remaining dots if any
		/*for (var i = steps; i < 10; i++) {
			if (self.dots[i]) {
				self.dots[i].visible = false;
			}
		}*/
		this.isUpdating = false;
	};
	// Method to hide the targeting line
	self.showLine = function () {
		self.visible = true;
		self.dots.forEach(function (dot) {
			dot.visible = true;
		});
	};
	self.hideLine = function () {
		self.visible = false;
		self.dots.forEach(function (dot) {
			dot.visible = false;
		});
	};
});
/**** 
* Initialize Game
****/ 
// Player positions
var game = new LK.Game({
	backgroundColor: 0x87CEEB // Sky blue background
});
/**** 
* Game Code
****/ 
// Define court boundaries as global variables
var courtTopBoundary = 0;
var courtBottomBoundary = 2732;
var courtLeftBoundary = 0;
var courtRightBoundary = 2048;
// Removed simulateAnchorY1 function and its usage
var buttonA = game.addChild(LK.getAsset('buttonA', {
	anchorX: 0.5,
	anchorY: 0.5,
	alpha: 0.85,
	x: 2048 - 300,
	y: 2732 - 250,
	visible: false
}));
// Create and position the joystick
var joystick = game.addChild(LK.getAsset('joystick', {
	anchorX: 0.5,
	anchorY: 0.5,
	alpha: 0.75,
	x: 300,
	// Positioned on the left with some margin
	// Center X
	y: 2732 - 250 // Positioned at the bottom with some margin
}));
/******* 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 oppoent hoop.
*****************************/
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,
	// Center X
	y: 2000,
	// Player Y position
	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
	}
};
var player = game.addChild(new Player());
player.x = 200; //2048 / 2; // Center X
player.y = 2000; //2732 / 2; // Center Y
player.setPosture(idlePosture);
var ball = game.addChild(new Ball());
ball.reset();
var hoop = game.addChild(new Hoop());
hoop.setPosition();
var score = 0;
var debugTxt = new Text2("Debug Info", {
	size: 50,
	fill: "#ffffff"
});
debugTxt.x = 20;
debugTxt.y = 20;
LK.gui.topLeft.addChild(debugTxt);
var scoreTxt = new Text2("0" + score.toString(), {
	size: 150,
	fill: "#ffffff"
});
scoreTxt.x = -180;
scoreTxt.y = -10;
var enableEye = true;
LK.gui.topRight.addChild(scoreTxt);
var joystickBasePosition = {
	x: joystick.x,
	y: joystick.y
};
var buttonABasePosition = {
	x: buttonA.x,
	y: buttonA.y
};
var joystickDrag = false;
var buttonADrag = 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 = new TargetingLine();
game.addChild(targetingLine);
game.on('down', function (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));
	// Calculate distance between click and buttonA center
	var distanceToButtonA = Math.sqrt(Math.pow(pos.x - buttonA.x, 2) + Math.pow(pos.y - buttonA.y, 2));
	// If click is within joystick radius, start dragging
	if (distance <= joystick.width / 2) {
		joystickDrag = true;
	} else if (distanceToButtonA <= buttonA.width / 2) {
		// buttonADrag = true; Disabled interaction with buttonA
	}
});
game.on('move', function (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...");
			// Calculate arm rotation based on buttonA movement
			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...");
			// Update player target point based on joystick movement
			// player.goToPoint({
			// 	x: player.x + dx * 5,
			// 	y: player.y + dy * 5
			// });
		}
	} else if (buttonADrag) {
		if (!player.hasBall) {
			player.setPosture(throwingPosture);
		}
		var dxButtonA = pos.x - (2048 - 300);
		var dyButtonA = pos.y - (2732 - 250);
		var distanceButtonA = Math.sqrt(dxButtonA * dxButtonA + dyButtonA * dyButtonA);
		var maxDistanceButtonA = buttonA.width / 4; // Max distance buttonA can move from center
		if (distanceButtonA > maxDistanceButtonA) {
			var angleButtonA = Math.atan2(dyButtonA, dxButtonA);
			dxButtonA = Math.cos(angleButtonA) * maxDistanceButtonA;
			dyButtonA = Math.sin(angleButtonA) * maxDistanceButtonA;
		}
		buttonA.x = 2048 - 300 + dxButtonA;
		buttonA.y = 2732 - 250 + dyButtonA;
		if (player.currentPosture != "throwingPosture") {
			return;
		}
		// Calculate arm rotation based on buttonA movement
		var armRotationFactor = 0.05; // Factor to control the rotation sensitivity
		var armRotation = Math.max(-Math.PI / 1.8, Math.min(Math.PI / 1.8, dxButtonA * 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;
	}
});
game.on('up', function (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) {
		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
			targetingLine.showLine();
		} 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;
	}
	if (buttonADrag) {
		buttonADrag = false;
		// If the player has the ball, throw it in the direction selected
		if (player.hasBall) {
			var throwPower = 20; // Adjust throw power as needed
			var dx = buttonA.x - buttonABasePosition.x;
			var dy = -(buttonA.y - buttonABasePosition.y); // Invert Y-axis for correct angle calculation
			var throwAngle = Math.atan2(dy, dx);
			console.log("Throw angle in degrees: " + (throwAngle * (180 / Math.PI)).toFixed(2)); // Log throwAngle in degrees
			ball.shoot(throwPower, throwAngle);
			player.hasBall = false; // Player no longer has the ball
			ball.currentPlayer = null; // Clear the ball's currentPlayer property
		} else {
			// Restore hands to normal positions after dragging buttonA
			player.rightArm.rotation = 0;
			player.leftArm.rotation = 0;
			// Return player to idle posture
			player.setPosture(idlePosture);
		}
		// Reset buttonA to its original position
		buttonA.x = 2048 - 300;
		buttonA.y = 2732 - 250;
	}
});
var idle = true;
// Test postures
/*
var changePostureTimer = LK.setInterval(function () {
	if (idle) {
		player.setPosture(runningUp1);
		idle = false;
	} else {
		player.setPosture(runningUp2);
		idle = true;
	}
}, 1000);
*/
LK.on('tick', function () {
	ball.update();
	// Check if player's trunk intersects with the ball
	if (!player.hasBall && player.trunk.intersects(ball)) {
		ball.currentPlayer = player; // Assign the player to the ball's currentPlayer property
		player.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.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;
			// Create and update the targeting line from the ball to the hoop
			targetingLine.updateLine(ball.x, ball.y, hoop.x, hoop.y);
			// This line is removed to rely on updateLine method for visibility control
		} else if (ball.currentPlayer.isMovingUp === 0) {
			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 {
			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
		}
	}
	if (!buttonADrag || player.currentPosture != "throwingPosture") {
		player.updatePosture();
		player.updatePosition();
	}
	// Re-add joystick to ensure it appears above other elements
	game.addChild(joystick);
	// Check if ball intersects with hoop and is moving downwards
	if (ball.intersects(hoop) && ball.speedY > 0) {
		score += 1;
		scoreTxt.setText(score.toString());
		ball.reset();
	}
	// Reset ball if it goes off-screen
	// Check Y boundaries for the ball
	if (ball.y < courtTopBoundary + ball.height / 2) {
		ball.y = courtTopBoundary + 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
	}
}); ===================================================================
--- original.js
+++ change.js
@@ -132,10 +132,11 @@
 		}
 		//this.x += (this.targetPosture.x - this.x) * speed;
 		//this.y += (this.targetPosture.y - this.y) * speed;
 		// Check if the target posture for hands and legs is reached
+		console.log("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) {
+		if (this.targetPosture && 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;