/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.isActive = false;
self.hasHitTarget = false;
self.update = function () {
if (self.isActive && !self.hasHitTarget) {
self.y -= self.speed;
// Check if arrow is off screen
if (self.y < -100) {
self.isActive = false;
}
// Check collision with targets
for (var i = 0; i < targets.length; i++) {
var target = targets[i];
if (self.intersects(target) && !self.hasHitTarget) {
self.hasHitTarget = true;
self.isActive = false;
// Score point
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('Score: ' + LK.getScore());
// Play hit sound
LK.getSound('hit').play();
// Visual feedback
LK.effects.flashObject(target, 0xFFFF00, 500);
break;
}
}
}
};
self.shoot = function (startX, startY, power) {
self.x = startX;
self.y = startY;
self.speed = 5 + power * 15; // Speed based on power (5-20)
self.isActive = true;
self.hasHitTarget = false;
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var targetGraphics = self.attachAsset('targetBoard', {
anchorX: 0.5,
anchorY: 0.5
});
var middleGraphics = self.attachAsset('targetMiddle', {
anchorX: 0.5,
anchorY: 0.5
});
var centerGraphics = self.attachAsset('targetCenter', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game variables
var arrows = [];
var targets = [];
var arrowCount = 10;
var isCharging = false;
var chargeStartTime = 0;
var currentChargePower = 0;
var maxChargeDuration = 10000; // 10 seconds for max charge
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var arrowCountTxt = new Text2('Arrows: 10', {
size: 60,
fill: 0xFFFFFF
});
arrowCountTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(arrowCountTxt);
// Background setup
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
background.x = 0;
background.y = 0;
// Bow setup
var bow = game.addChild(LK.getAsset('bow', {
anchorX: 0.5,
anchorY: 1.0
}));
bow.x = 1024; // Center horizontally
bow.y = 2732 - 100; // Near bottom of screen
// Charge meter setup
var chargeMeterBG = game.addChild(LK.getAsset('chargeMeter', {
anchorX: 0.5,
anchorY: 0.5
}));
chargeMeterBG.x = 1024;
chargeMeterBG.y = 2732 - 300;
var chargeBar = game.addChild(LK.getAsset('chargeBar', {
anchorX: 0,
anchorY: 0.5
}));
chargeBar.x = chargeMeterBG.x - 200;
chargeBar.y = chargeMeterBG.y;
chargeBar.scaleX = 0;
// Create targets at different positions
function createTargets() {
var targetPositions = [{
x: 500,
y: 800
}, {
x: 1024,
y: 600
}, {
x: 1548,
y: 900
}, {
x: 700,
y: 400
}, {
x: 1300,
y: 700
}];
for (var i = 0; i < targetPositions.length; i++) {
var target = new Target();
target.x = targetPositions[i].x;
target.y = targetPositions[i].y;
targets.push(target);
game.addChild(target);
}
}
createTargets();
// Add movement to targets
function moveTargets() {
for (var i = 0; i < targets.length; i++) {
var target = targets[i];
moveTarget(target);
}
}
// Move individual target continuously
function moveTarget(target) {
// Generate random direction and distance
var direction = Math.random() < 0.5 ? -1 : 1; // Random left or right
var distance = 200 + Math.random() * 300; // Random distance between 200-500
var newX = target.x + direction * distance;
// Keep targets within screen bounds
newX = Math.max(150, Math.min(1898, newX));
// Create tween for smooth movement
tween(target, {
x: newX
}, {
duration: 2000 + Math.random() * 3000,
// Random duration 2-5 seconds
easing: tween.easeInOut,
onFinish: function onFinish() {
// Immediately start next movement without delay
moveTarget(target);
}
});
}
// Start target movement
LK.setTimeout(moveTargets, 1000);
// Dragging variables
var isDraggingBow = false;
var dragOffsetX = 0;
var dragOffsetY = 0;
// Touch/mouse handlers
game.down = function (x, y, obj) {
// Check if touch is on bow for dragging
var bowBounds = bow.getBounds();
if (x >= bowBounds.x && x <= bowBounds.x + bowBounds.width && y >= bowBounds.y && y <= bowBounds.y + bowBounds.height) {
isDraggingBow = true;
dragOffsetX = x - bow.x;
dragOffsetY = y - bow.y;
} else if (arrowCount > 0 && !isCharging && !isDraggingBow) {
// Only start charging if not dragging bow
isCharging = true;
chargeStartTime = LK.ticks;
currentChargePower = 0;
}
};
game.move = function (x, y, obj) {
if (isDraggingBow) {
bow.x = x - dragOffsetX;
// Keep bow within horizontal screen bounds only
bow.x = Math.max(250, Math.min(1798, bow.x)); // Keep bow within horizontal bounds
// Update charge meter position to follow bow horizontally only
chargeMeterBG.x = bow.x;
chargeBar.x = chargeMeterBG.x - 200;
}
};
game.up = function (x, y, obj) {
if (isDraggingBow) {
isDraggingBow = false;
} else if (isCharging && arrowCount > 0) {
isCharging = false;
// Create and shoot arrow
var arrow = new Arrow();
arrow.shoot(bow.x, bow.y - 200, currentChargePower);
arrows.push(arrow);
game.addChild(arrow);
// Play shoot sound
LK.getSound('shoot').play();
// Decrease arrow count
arrowCount--;
arrowCountTxt.setText('Arrows: ' + arrowCount);
// Reset charge
currentChargePower = 0;
chargeBar.scaleX = 0;
// Check if game is over
if (arrowCount <= 0) {
LK.setTimeout(function () {
if (LK.getScore() >= 25) {
// 5 targets * 5 points = 25 for perfect score
LK.showYouWin();
} else {
LK.showGameOver();
}
}, 2000);
}
}
};
game.update = function () {
// Update charge meter
if (isCharging) {
var chargeDuration = (LK.ticks - chargeStartTime) * (1000 / 60); // Convert ticks to milliseconds
currentChargePower = Math.min(chargeDuration / maxChargeDuration, 1.0);
chargeBar.scaleX = currentChargePower * 40; // Scale to fit meter width
// Change color based on charge level
if (currentChargePower < 0.33) {
chargeBar.tint = 0x00FF00; // Green
} else if (currentChargePower < 0.66) {
chargeBar.tint = 0xFFFF00; // Yellow
} else {
chargeBar.tint = 0xFF0000; // Red
}
}
// Clean up inactive arrows
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
if (!arrow.isActive && (arrow.y < -100 || arrow.hasHitTarget)) {
arrow.destroy();
arrows.splice(i, 1);
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.isActive = false;
self.hasHitTarget = false;
self.update = function () {
if (self.isActive && !self.hasHitTarget) {
self.y -= self.speed;
// Check if arrow is off screen
if (self.y < -100) {
self.isActive = false;
}
// Check collision with targets
for (var i = 0; i < targets.length; i++) {
var target = targets[i];
if (self.intersects(target) && !self.hasHitTarget) {
self.hasHitTarget = true;
self.isActive = false;
// Score point
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('Score: ' + LK.getScore());
// Play hit sound
LK.getSound('hit').play();
// Visual feedback
LK.effects.flashObject(target, 0xFFFF00, 500);
break;
}
}
}
};
self.shoot = function (startX, startY, power) {
self.x = startX;
self.y = startY;
self.speed = 5 + power * 15; // Speed based on power (5-20)
self.isActive = true;
self.hasHitTarget = false;
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var targetGraphics = self.attachAsset('targetBoard', {
anchorX: 0.5,
anchorY: 0.5
});
var middleGraphics = self.attachAsset('targetMiddle', {
anchorX: 0.5,
anchorY: 0.5
});
var centerGraphics = self.attachAsset('targetCenter', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Game variables
var arrows = [];
var targets = [];
var arrowCount = 10;
var isCharging = false;
var chargeStartTime = 0;
var currentChargePower = 0;
var maxChargeDuration = 10000; // 10 seconds for max charge
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var arrowCountTxt = new Text2('Arrows: 10', {
size: 60,
fill: 0xFFFFFF
});
arrowCountTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(arrowCountTxt);
// Background setup
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
background.x = 0;
background.y = 0;
// Bow setup
var bow = game.addChild(LK.getAsset('bow', {
anchorX: 0.5,
anchorY: 1.0
}));
bow.x = 1024; // Center horizontally
bow.y = 2732 - 100; // Near bottom of screen
// Charge meter setup
var chargeMeterBG = game.addChild(LK.getAsset('chargeMeter', {
anchorX: 0.5,
anchorY: 0.5
}));
chargeMeterBG.x = 1024;
chargeMeterBG.y = 2732 - 300;
var chargeBar = game.addChild(LK.getAsset('chargeBar', {
anchorX: 0,
anchorY: 0.5
}));
chargeBar.x = chargeMeterBG.x - 200;
chargeBar.y = chargeMeterBG.y;
chargeBar.scaleX = 0;
// Create targets at different positions
function createTargets() {
var targetPositions = [{
x: 500,
y: 800
}, {
x: 1024,
y: 600
}, {
x: 1548,
y: 900
}, {
x: 700,
y: 400
}, {
x: 1300,
y: 700
}];
for (var i = 0; i < targetPositions.length; i++) {
var target = new Target();
target.x = targetPositions[i].x;
target.y = targetPositions[i].y;
targets.push(target);
game.addChild(target);
}
}
createTargets();
// Add movement to targets
function moveTargets() {
for (var i = 0; i < targets.length; i++) {
var target = targets[i];
moveTarget(target);
}
}
// Move individual target continuously
function moveTarget(target) {
// Generate random direction and distance
var direction = Math.random() < 0.5 ? -1 : 1; // Random left or right
var distance = 200 + Math.random() * 300; // Random distance between 200-500
var newX = target.x + direction * distance;
// Keep targets within screen bounds
newX = Math.max(150, Math.min(1898, newX));
// Create tween for smooth movement
tween(target, {
x: newX
}, {
duration: 2000 + Math.random() * 3000,
// Random duration 2-5 seconds
easing: tween.easeInOut,
onFinish: function onFinish() {
// Immediately start next movement without delay
moveTarget(target);
}
});
}
// Start target movement
LK.setTimeout(moveTargets, 1000);
// Dragging variables
var isDraggingBow = false;
var dragOffsetX = 0;
var dragOffsetY = 0;
// Touch/mouse handlers
game.down = function (x, y, obj) {
// Check if touch is on bow for dragging
var bowBounds = bow.getBounds();
if (x >= bowBounds.x && x <= bowBounds.x + bowBounds.width && y >= bowBounds.y && y <= bowBounds.y + bowBounds.height) {
isDraggingBow = true;
dragOffsetX = x - bow.x;
dragOffsetY = y - bow.y;
} else if (arrowCount > 0 && !isCharging && !isDraggingBow) {
// Only start charging if not dragging bow
isCharging = true;
chargeStartTime = LK.ticks;
currentChargePower = 0;
}
};
game.move = function (x, y, obj) {
if (isDraggingBow) {
bow.x = x - dragOffsetX;
// Keep bow within horizontal screen bounds only
bow.x = Math.max(250, Math.min(1798, bow.x)); // Keep bow within horizontal bounds
// Update charge meter position to follow bow horizontally only
chargeMeterBG.x = bow.x;
chargeBar.x = chargeMeterBG.x - 200;
}
};
game.up = function (x, y, obj) {
if (isDraggingBow) {
isDraggingBow = false;
} else if (isCharging && arrowCount > 0) {
isCharging = false;
// Create and shoot arrow
var arrow = new Arrow();
arrow.shoot(bow.x, bow.y - 200, currentChargePower);
arrows.push(arrow);
game.addChild(arrow);
// Play shoot sound
LK.getSound('shoot').play();
// Decrease arrow count
arrowCount--;
arrowCountTxt.setText('Arrows: ' + arrowCount);
// Reset charge
currentChargePower = 0;
chargeBar.scaleX = 0;
// Check if game is over
if (arrowCount <= 0) {
LK.setTimeout(function () {
if (LK.getScore() >= 25) {
// 5 targets * 5 points = 25 for perfect score
LK.showYouWin();
} else {
LK.showGameOver();
}
}, 2000);
}
}
};
game.update = function () {
// Update charge meter
if (isCharging) {
var chargeDuration = (LK.ticks - chargeStartTime) * (1000 / 60); // Convert ticks to milliseconds
currentChargePower = Math.min(chargeDuration / maxChargeDuration, 1.0);
chargeBar.scaleX = currentChargePower * 40; // Scale to fit meter width
// Change color based on charge level
if (currentChargePower < 0.33) {
chargeBar.tint = 0x00FF00; // Green
} else if (currentChargePower < 0.66) {
chargeBar.tint = 0xFFFF00; // Yellow
} else {
chargeBar.tint = 0xFF0000; // Red
}
}
// Clean up inactive arrows
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
if (!arrow.isActive && (arrow.y < -100 || arrow.hasHitTarget)) {
arrow.destroy();
arrows.splice(i, 1);
}
}
};