Code edit (1 edits merged)
Please save this source code
User prompt
in buttonADrag fix the anchors because arms are rotating around their center
Code edit (1 edits merged)
Please save this source code
User prompt
add the log in degrees too
User prompt
log the angleRadians
User prompt
also restore the rotations on release
User prompt
during buttonA Drag, arms and hands should not rotate around their center, but around their fixation point on the trunk. To do so Update anchors of the arms during the buttonA Drag and restore them when released.
Code edit (2 edits merged)
Please save this source code
User prompt
during buttonA Drag, arms and hands should not rotate around their center, but around their fixation point on the trunk, update their anchors only during the buttonA Drag, to make the move realistic
User prompt
during buttonA Drag, arms and hands should not rotate around their center, but around their fixation point on the trunk, update their anchor to make the move realistic
User prompt
during buttonA Drag, arms and hands should not rotate around their center, but around their fixation point on the trunk like real human arms
User prompt
during buttonA Drag use Rotation for the arms and hands direction
User prompt
when buttonA is released, return to idle posture
User prompt
When buttonA is dragged, if player hasBall is false, switch to throwingPosture and then move the arms and the hands following buttonA movement
User prompt
limit the drag range of buttonA like the one of the joystick
User prompt
buttonA should be draggable as the joystick but independently
User prompt
make buttonA behave in a similar way as the joystick. Use a buttonADrag boolean
User prompt
make buttonA behave like the joystick
User prompt
make buttonA behave like the joystick (it will be used for ball throwing)
Code edit (2 edits merged)
Please save this source code
User prompt
tint the buttonA in orange
Code edit (1 edits merged)
Please save this source code
User prompt
tint the buttonA in red
User prompt
when buttonA pressed, if player hasBall is false, swich to throwingPosture for 1 sec
Code edit (1 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.speedY = -power;
		self.isShot = true;
	};
	self.update = function () {
		if (self.isShot) {
			self.y += self.speedY;
			self.speedY += self.gravity;
		}
	};
	self.reset = function () {
		self.x = 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.verticalDirection = 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: 0.5,
		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: 0.5,
		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.1; // Speed of transition
		if (!this.targetPosture) {
			return;
		}
		//this.x += (this.targetPosture.x - this.x) * speed;
		//this.y += (this.targetPosture.y - this.y) * speed;
		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.verticalDirection === 0;
		}
		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 () {
		if (self.targetPoint) {
			self.verticalDirection = self.targetPoint.y < self.y ? 1 : 0;
			var fixedSpeed = 10; // Fixed pixels per frame
			// Calculate direction vector
			var dx = self.targetPoint.x - self.x;
			var dy = self.targetPoint.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			var nx = dx / distance; // Normalized direction x
			var ny = dy / distance; // Normalized direction y
			// Move player by fixed speed in the direction of the targetPoint
			self.x += nx * fixedSpeed;
			self.y += ny * fixedSpeed;
			// Check if player is close enough to targetPoint to stop
			if (distance < fixedSpeed) {
				self.targetPoint = null; // Clear targetPoint when close enough
				self.verticalDirection = 0;
				// Alternate between dribblingPosture1 and dribblingPosture2 when player hasBall and is not moving
				if (self.hasBall && !self.targetPoint) {
					var currentTick = LK.ticks;
					self.setPosture(dribblingPosture1);
				} else {
					self.setPosture(idlePosture);
				}
			} else {
				// Alternate between runningUp1 and runningUp2 postures while moving
				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) {
				var currentTick = LK.ticks;
				self.setPosture(Math.abs(ball.y - self.y) > 150 ? dribblingPosture1 : dribblingPosture2);
			}
		}
	};
	self.setPosture = function (newPosture) {
		self.targetPosture = newPosture;
	};
	self.goToPoint = function (newPosition) {
		self.targetPoint = newPosition;
	};
});
/**** 
* Initialize Game
****/ 
// Player positions
var game = new LK.Game({
	backgroundColor: 0x87CEEB // Sky blue background
});
/**** 
* Game Code
****/ 
// Create and position buttonA
var buttonA = game.addChild(LK.getAsset('buttonA', {
	anchorX: 0.5,
	anchorY: 0.5,
	alpha: 0.75,
	x: 2048 - 300,
	// Positioned on the right with some margin
	y: 2732 - 250 // Positioned at the bottom with some margin
}));
// 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 = {
	x: 1024,
	y: 2000,
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 110,
		y: -20
	},
	rightHand: {
		x: 125,
		y: 30
	},
	leftArm: {
		x: -110,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: -90,
		y: 30
	},
	leftArm: {
		x: -90,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: -90,
		y: 50
	},
	leftArm: {
		x: -90,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: 105,
		y: 30
	},
	leftArm: {
		x: -90,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 80,
		y: -20
	},
	rightHand: {
		x: 95,
		y: 30
	},
	leftArm: {
		x: -80,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: -90,
		y: 30
	},
	leftArm: {
		x: -90,
		y: -20
	},
	leftHand: {
		x: 90,
		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 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
	},
	rightHand: {
		x: -95,
		y: 30
	},
	leftArm: {
		x: -80,
		y: -20
	},
	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 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,
		// Set the right hand at the top of the right arm
		y: -220 // Set the right hand at the top of the right arm
	},
	leftArm: {
		x: -100,
		y: -120
	},
	leftHand: {
		x: -100,
		// Set the left hand at the top of the left arm
		y: -220 // 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 = 2048 / 2; // Center X
player.y = 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 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 joystickDrag = false;
game.on('down', function (obj) {
	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;
	} else {
		// 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 outside joystick radius and not within buttonA radius, treat it as a target position
		if (distanceToButtonA > buttonA.width / 2) {
			player.goToPoint({
				x: pos.x,
				y: pos.y
			});
		}
	}
});
game.on('move', function (obj) {
	if (!joystickDrag) {
		return;
	}
	var pos = obj.event.getLocalPosition(game);
	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;
	// Update player target point based on joystick movement
	player.goToPoint({
		x: player.x + dx * 5,
		// Multiplier to increase sensitivity
		y: player.y + dy * 5
	});
});
game.on('up', function (obj) {
	if (!joystickDrag) {
		return;
	}
	joystickDrag = false;
	joystick.x = joystickBasePosition.x;
	joystick.y = joystickBasePosition.y;
});
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.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 (ball.currentPlayer.verticalDirection === 0) {
			ball.y = ball.currentPlayer.y + 150 + Math.sin(LK.ticks / 7) * 100; // Add dribble movement when moving down or idle
			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 / 7) * 50; // Add dribble movement when moving up
			game.addChild(ball.currentPlayer); // Ensure player is in front by re-adding it to the game
		}
	}
	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
	if (ball.y > 2732) {
		ball.reset();
	}
}); /**** 
* 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.speedY = -power;
		self.isShot = true;
	};
	self.update = function () {
		if (self.isShot) {
			self.y += self.speedY;
			self.speedY += self.gravity;
		}
	};
	self.reset = function () {
		self.x = 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.verticalDirection = 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: 0.5,
		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: 0.5,
		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.1; // Speed of transition
		if (!this.targetPosture) {
			return;
		}
		//this.x += (this.targetPosture.x - this.x) * speed;
		//this.y += (this.targetPosture.y - this.y) * speed;
		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.verticalDirection === 0;
		}
		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 () {
		if (self.targetPoint) {
			self.verticalDirection = self.targetPoint.y < self.y ? 1 : 0;
			var fixedSpeed = 10; // Fixed pixels per frame
			// Calculate direction vector
			var dx = self.targetPoint.x - self.x;
			var dy = self.targetPoint.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			var nx = dx / distance; // Normalized direction x
			var ny = dy / distance; // Normalized direction y
			// Move player by fixed speed in the direction of the targetPoint
			self.x += nx * fixedSpeed;
			self.y += ny * fixedSpeed;
			// Check if player is close enough to targetPoint to stop
			if (distance < fixedSpeed) {
				self.targetPoint = null; // Clear targetPoint when close enough
				self.verticalDirection = 0;
				// Alternate between dribblingPosture1 and dribblingPosture2 when player hasBall and is not moving
				if (self.hasBall && !self.targetPoint) {
					var currentTick = LK.ticks;
					self.setPosture(dribblingPosture1);
				} else {
					self.setPosture(idlePosture);
				}
			} else {
				// Alternate between runningUp1 and runningUp2 postures while moving
				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) {
				var currentTick = LK.ticks;
				self.setPosture(Math.abs(ball.y - self.y) > 150 ? dribblingPosture1 : dribblingPosture2);
			}
		}
	};
	self.setPosture = function (newPosture) {
		self.targetPosture = newPosture;
	};
	self.goToPoint = function (newPosition) {
		self.targetPoint = newPosition;
	};
});
/**** 
* Initialize Game
****/ 
// Player positions
var game = new LK.Game({
	backgroundColor: 0x87CEEB // Sky blue background
});
/**** 
* Game Code
****/ 
// Create and position buttonA
var buttonA = game.addChild(LK.getAsset('buttonA', {
	anchorX: 0.5,
	anchorY: 0.5,
	alpha: 0.75,
	x: 2048 - 300,
	// Positioned on the right with some margin
	y: 2732 - 250 // Positioned at the bottom with some margin
}));
// 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 = {
	x: 1024,
	y: 2000,
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 110,
		y: -20
	},
	rightHand: {
		x: 125,
		y: 30
	},
	leftArm: {
		x: -110,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: -90,
		y: 30
	},
	leftArm: {
		x: -90,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: -90,
		y: 50
	},
	leftArm: {
		x: -90,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: 105,
		y: 30
	},
	leftArm: {
		x: -90,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 80,
		y: -20
	},
	rightHand: {
		x: 95,
		y: 30
	},
	leftArm: {
		x: -80,
		y: -20
	},
	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 = {
	x: 1024,
	// Center X
	y: 2000,
	// Player Y position
	head: {
		x: 0,
		y: -160
	},
	eyes: {
		x: 0,
		y: -160
	},
	rightArm: {
		x: 90,
		y: -20
	},
	rightHand: {
		x: -90,
		y: 30
	},
	leftArm: {
		x: -90,
		y: -20
	},
	leftHand: {
		x: 90,
		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 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
	},
	rightHand: {
		x: -95,
		y: 30
	},
	leftArm: {
		x: -80,
		y: -20
	},
	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 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,
		// Set the right hand at the top of the right arm
		y: -220 // Set the right hand at the top of the right arm
	},
	leftArm: {
		x: -100,
		y: -120
	},
	leftHand: {
		x: -100,
		// Set the left hand at the top of the left arm
		y: -220 // 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 = 2048 / 2; // Center X
player.y = 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 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 joystickDrag = false;
game.on('down', function (obj) {
	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;
	} else {
		// 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 outside joystick radius and not within buttonA radius, treat it as a target position
		if (distanceToButtonA > buttonA.width / 2) {
			player.goToPoint({
				x: pos.x,
				y: pos.y
			});
		}
	}
});
game.on('move', function (obj) {
	if (!joystickDrag) {
		return;
	}
	var pos = obj.event.getLocalPosition(game);
	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;
	// Update player target point based on joystick movement
	player.goToPoint({
		x: player.x + dx * 5,
		// Multiplier to increase sensitivity
		y: player.y + dy * 5
	});
});
game.on('up', function (obj) {
	if (!joystickDrag) {
		return;
	}
	joystickDrag = false;
	joystick.x = joystickBasePosition.x;
	joystick.y = joystickBasePosition.y;
});
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.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 (ball.currentPlayer.verticalDirection === 0) {
			ball.y = ball.currentPlayer.y + 150 + Math.sin(LK.ticks / 7) * 100; // Add dribble movement when moving down or idle
			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 / 7) * 50; // Add dribble movement when moving up
			game.addChild(ball.currentPlayer); // Ensure player is in front by re-adding it to the game
		}
	}
	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
	if (ball.y > 2732) {
		ball.reset();
	}
});