User prompt
Make the player shoot auto when the dog is following the animal
User prompt
Make the ammo inf
Code edit (1 edits merged)
Please save this source code
User prompt
Add Diffrent seasons and diffrent dogs with diffrent ablities every season change ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Make The Player not able to go in the ponds
User prompt
Create Small Ponds in the map and add Ducks in to the ponds Make Sure the dogs go slower in the pond ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add More Sounds
User prompt
Modify dog to only follow one animal at a time by setting single target priority ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
while the animal is running form the dog it cannot turn invis
User prompt
Make the dog go after the animal untill it is shot ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove the stamina bar and replace it with an ammo
User prompt
Make the dog walk animation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make Sure the dog follows the animal to the player to shoot easier ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make The Dog follow footprints and find the animal ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Animals go slower than the dog
User prompt
After the dog stops barking make it come backt to the player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the animals invis after some time that dog sees them ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove The animal hiding under trees
User prompt
Make the dog go after the animals ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make The Footprints Almost invis to the player and make it so you cant shoot trough trees
User prompt
Make the animals hide under trees and bushes after beeing Seen By The Dog
User prompt
Make the animals invis untill the dog sees them,Make The Dog Follow animal footprints ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make an hunting dog ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make More Maps
User prompt
Shop Does not oppen
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Animal = Container.expand(function (animalType) {
var self = Container.call(this);
self.animalType = animalType || 'deer';
self.graphics = self.attachAsset(self.animalType, {
anchorX: 0.5,
anchorY: 0.5
});
// Animal properties
self.health = 100;
self.alertLevel = 0;
self.speed = 0.5 + Math.random() * 1.5;
self.direction = Math.random() * Math.PI * 2;
self.isAlive = true;
self.detectionRadius = 150 + Math.random() * 100;
self.lastX = self.x;
self.lastY = self.y;
// Visibility properties for dog tracking system
self.isDiscoveredByDog = false;
self.graphics.visible = false; // Start invisible
self.visibilityTimer = 0; // Timer for how long animal has been visible
self.maxVisibilityTime = 300; // 5 seconds at 60fps before going invisible
self.isFadingOut = false; // Flag to prevent multiple fade animations
// Movement timer
self.moveTimer = 0;
self.moveChangeInterval = 60 + Math.random() * 120;
self.update = function () {
if (!self.isAlive) {
return;
}
// Random movement behavior
self.moveTimer++;
if (self.moveTimer >= self.moveChangeInterval) {
self.direction += (Math.random() - 0.5) * 0.5;
self.moveTimer = 0;
self.moveChangeInterval = 60 + Math.random() * 120;
}
// Move animal
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Keep within bounds
if (self.x < 50) {
self.x = 50;
self.direction = Math.random() * Math.PI * 2;
}
if (self.x > 1998) {
self.x = 1998;
self.direction = Math.random() * Math.PI * 2;
}
if (self.y < 50) {
self.y = 50;
self.direction = Math.random() * Math.PI * 2;
}
if (self.y > 2682) {
self.y = 2682;
self.direction = Math.random() * Math.PI * 2;
}
// Dog and player detection behavior
var distanceToDog = Math.sqrt(Math.pow(self.x - huntingDog.x, 2) + Math.pow(self.y - huntingDog.y, 2));
var distanceToPlayer = Math.sqrt(Math.pow(self.x - hunter.x, 2) + Math.pow(self.y - hunter.y, 2));
// If discovered by dog, flee from dog
if (self.isDiscoveredByDog && distanceToDog < 300) {
// Flee from dog
var fleeFromDogAngle = Math.atan2(self.y - huntingDog.y, self.x - huntingDog.x);
self.direction = fleeFromDogAngle;
self.speed = Math.min(4, self.speed + 0.15);
self.graphics.alpha = 1.0;
} else if (distanceToPlayer < self.detectionRadius) {
// Normal player detection behavior
self.alertLevel = Math.min(100, self.alertLevel + 2);
// Flee from player
var fleeAngle = Math.atan2(self.y - hunter.y, self.x - hunter.x);
self.direction = fleeAngle;
self.speed = Math.min(4, self.speed + 0.1);
self.graphics.alpha = 1.0; // Fully visible when fleeing from player
} else {
self.alertLevel = Math.max(0, self.alertLevel - 1);
self.speed = Math.max(1, self.speed - 0.05);
self.graphics.alpha = 1.0; // Fully visible when calm
}
// Handle visibility timer - make animal invisible after being seen for some time
// But don't turn invisible if being chased by the dog
var isBeingChased = distanceToDog < 300 && self.isDiscoveredByDog;
if (self.isDiscoveredByDog && self.graphics.visible && !isBeingChased) {
self.visibilityTimer++;
// Start fading out when timer reaches max visibility time
if (self.visibilityTimer >= self.maxVisibilityTime && !self.isFadingOut) {
self.isFadingOut = true;
// Use tween to fade out the animal
tween(self.graphics, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
self.graphics.visible = false;
self.isDiscoveredByDog = false;
self.visibilityTimer = 0;
self.isFadingOut = false;
self.graphics.alpha = 1.0; // Reset alpha for next discovery
}
});
}
} else if (isBeingChased) {
// Reset visibility timer while being chased to prevent fading
self.visibilityTimer = 0;
self.isFadingOut = false;
// Stop any ongoing fade animation
tween.stop(self.graphics, {
alpha: true
});
self.graphics.alpha = 1.0;
}
// Create footprints occasionally - more frequent when fleeing
var footprintChance = 0.02;
if (self.alertLevel > 50 || self.isDiscoveredByDog) {
footprintChance = 0.08; // More footprints when scared or being chased
}
if (Math.random() < footprintChance) {
createFootprint(self.x, self.y);
}
// Play rustling sound when animal is moving and alert
if (self.alertLevel > 30 && Math.random() < 0.01) {
LK.getSound('rustle').play();
}
};
return self;
});
var Duck = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('duck', {
anchorX: 0.5,
anchorY: 0.5
});
// Duck properties
self.health = 100;
self.speed = 1.0;
self.direction = Math.random() * Math.PI * 2;
self.isAlive = true;
self.swimRadius = 80; // How far from pond center duck will swim
self.pondX = 0; // Will be set when duck is assigned to pond
self.pondY = 0;
self.isDiscoveredByDog = false;
self.graphics.visible = false;
self.visibilityTimer = 0;
self.maxVisibilityTime = 400;
self.isFadingOut = false;
self.moveTimer = 0;
self.moveChangeInterval = 90 + Math.random() * 60;
self.update = function () {
if (!self.isAlive) {
return;
}
// Duck swimming behavior - stay near pond center
self.moveTimer++;
if (self.moveTimer >= self.moveChangeInterval) {
// Change direction occasionally
self.direction += (Math.random() - 0.5) * 0.8;
self.moveTimer = 0;
self.moveChangeInterval = 90 + Math.random() * 60;
}
// Move duck
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Keep duck within pond area
var distanceFromPondCenter = Math.sqrt(Math.pow(self.x - self.pondX, 2) + Math.pow(self.y - self.pondY, 2));
if (distanceFromPondCenter > self.swimRadius) {
// Turn back toward pond center
var angleToPondCenter = Math.atan2(self.pondY - self.y, self.pondX - self.x);
self.direction = angleToPondCenter + (Math.random() - 0.5) * 0.5;
// Move back toward center
self.x += Math.cos(angleToPondCenter) * 2;
self.y += Math.sin(angleToPondCenter) * 2;
}
// Dog and player detection behavior
var distanceToDog = Math.sqrt(Math.pow(self.x - huntingDog.x, 2) + Math.pow(self.y - huntingDog.y, 2));
var distanceToPlayer = Math.sqrt(Math.pow(self.x - hunter.x, 2) + Math.pow(self.y - hunter.y, 2));
// If discovered by dog, stay more visible and swim faster
if (self.isDiscoveredByDog && distanceToDog < 200) {
self.speed = Math.min(2, self.speed + 0.1);
self.graphics.alpha = 1.0;
} else if (distanceToPlayer < 120) {
// Player detection - swim away from player
var fleeAngle = Math.atan2(self.y - hunter.y, self.x - hunter.x);
self.direction = fleeAngle;
self.speed = Math.min(2.5, self.speed + 0.1);
self.graphics.alpha = 1.0;
} else {
self.speed = Math.max(1, self.speed - 0.05);
self.graphics.alpha = 1.0;
}
// Handle visibility like other animals
var isBeingChased = distanceToDog < 200 && self.isDiscoveredByDog;
if (self.isDiscoveredByDog && self.graphics.visible && !isBeingChased) {
self.visibilityTimer++;
if (self.visibilityTimer >= self.maxVisibilityTime && !self.isFadingOut) {
self.isFadingOut = true;
tween(self.graphics, {
alpha: 0
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.graphics.visible = false;
self.isDiscoveredByDog = false;
self.visibilityTimer = 0;
self.isFadingOut = false;
self.graphics.alpha = 1.0;
}
});
}
} else if (isBeingChased) {
self.visibilityTimer = 0;
self.isFadingOut = false;
tween.stop(self.graphics, {
alpha: true
});
self.graphics.alpha = 1.0;
}
// Create splash effects occasionally
if (Math.random() < 0.01) {
// Create small ripple effect (using footprint as placeholder)
createFootprint(self.x + (Math.random() - 0.5) * 20, self.y + (Math.random() - 0.5) * 20);
}
};
return self;
});
var Footprint = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('footprint', {
anchorX: 0.5,
anchorY: 0.5
});
self.graphics.alpha = 0.1;
self.lifetime = 600; // 10 seconds at 60fps
self.update = function () {
self.lifetime--;
self.graphics.alpha = self.lifetime / 600 * 0.1;
if (self.lifetime <= 0) {
self.destroy();
for (var i = footprints.length - 1; i >= 0; i--) {
if (footprints[i] === self) {
footprints.splice(i, 1);
break;
}
}
}
};
return self;
});
// Game variables
var Hunter = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('hunter', {
anchorX: 0.5,
anchorY: 0.5
});
self.rifle = self.addChild(LK.getAsset('rifle', {
anchorX: 0,
anchorY: 0.5
}));
self.rifle.x = 30;
self.rifle.y = 0;
// Hunter stats
self.ammo = 30;
self.maxAmmo = 30;
self.hunger = 100;
self.accuracy = 50;
self.stealth = 50;
self.tracking = 50;
self.isMoving = false;
self.lastMoveTime = 0;
return self;
});
var HuntingDog = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('dog', {
anchorX: 0.5,
anchorY: 0.5
});
// Dog properties - will be updated based on breed
self.energy = 100;
self.maxEnergy = 100;
self.loyalty = 80;
self.tracking = 60;
self.speed = 2.5;
self.followDistance = 80;
self.detectionRadius = 200;
self.breed = 'Retriever';
self.specialAbility = 'tracking';
self.isFollowing = true;
self.targetAnimal = null;
self.alertCooldown = 0;
self.wasChasing = false; // Track if dog was previously chasing
self.persistentTarget = null; // Animal that dog will pursue until shot
self.lastKnownTargetX = 0; // Last known position of target
self.lastKnownTargetY = 0;
// Movement properties
self.targetX = 0;
self.targetY = 0;
self.lastX = self.x;
self.lastY = self.y;
// Walking animation properties
self.isWalking = false;
self.walkAnimationOffset = 0;
self.walkAnimationSpeed = 0.2;
self.update = function () {
if (self.energy <= 0) {
return;
}
// Single target priority system - only chase one animal at a time
var targetAnimal = null;
var targetDistance = Infinity;
// First priority: continue chasing persistent target if it exists and is alive
if (self.persistentTarget && self.persistentTarget.isAlive && self.persistentTarget.isDiscoveredByDog) {
var persistentDistance = Math.sqrt(Math.pow(self.x - self.persistentTarget.x, 2) + Math.pow(self.y - self.persistentTarget.y, 2));
if (persistentDistance < 400) {
// Extended chase range
targetAnimal = self.persistentTarget;
targetDistance = persistentDistance;
} else {
// Clear persistent target if too far away
self.persistentTarget = null;
}
}
// Second priority: if no persistent target, find closest discovered animal
if (!targetAnimal) {
var allAnimals = animals.concat(ducks);
for (var a = 0; a < allAnimals.length; a++) {
var animal = allAnimals[a];
if (!animal.isAlive || !animal.isDiscoveredByDog) {
continue;
}
var animalDistance = Math.sqrt(Math.pow(self.x - animal.x, 2) + Math.pow(self.y - animal.y, 2));
if (animalDistance < 250 && animalDistance < targetDistance) {
targetAnimal = animal;
targetDistance = animalDistance;
// Set as new persistent target
self.persistentTarget = animal;
}
}
}
// Use single target for all chase logic
var closestAnimal = targetAnimal;
var closestAnimalDistance = targetDistance;
// Chase behavior - prioritize chasing animals over following hunter
// Expanded detection range for persistent chasing
if (closestAnimal && closestAnimalDistance < 400) {
// Increased range from 250 to 400
// Set chasing flag
self.wasChasing = true;
// Stop any existing return tween
tween.stop(self, {
x: true,
y: true
});
// Strategic herding behavior to drive animal toward player
var animalToHunterAngle = Math.atan2(hunter.y - closestAnimal.y, hunter.x - closestAnimal.x);
var dogToAnimalAngle = Math.atan2(closestAnimal.y - self.y, closestAnimal.x - self.x);
var animalToHunterDistance = Math.sqrt(Math.pow(closestAnimal.x - hunter.x, 2) + Math.pow(closestAnimal.y - hunter.y, 2));
// Position dog on the opposite side of animal from hunter to herd it toward player
var herdingAngle = animalToHunterAngle + Math.PI; // Opposite direction from hunter
var optimalDistance = 80; // Distance to maintain from animal while herding
// Calculate where dog should be to herd animal toward hunter
var targetHerdX = closestAnimal.x + Math.cos(herdingAngle) * optimalDistance;
var targetHerdY = closestAnimal.y + Math.sin(herdingAngle) * optimalDistance;
// Move toward herding position
var moveToHerdAngle = Math.atan2(targetHerdY - self.y, targetHerdX - self.x);
var distanceToHerdPosition = Math.sqrt(Math.pow(targetHerdX - self.x, 2) + Math.pow(targetHerdY - self.y, 2));
// If dog is far from optimal herding position, move toward it
if (distanceToHerdPosition > 30) {
// Check if dog is in pond and reduce speed
var dogHerdSpeed = self.speed * 1.5;
for (var p = 0; p < ponds.length; p++) {
var pond = ponds[p];
var distanceToPond = Math.sqrt(Math.pow(self.x - pond.x, 2) + Math.pow(self.y - pond.y, 2));
if (distanceToPond < 100) {
// Dog is in or near pond
dogHerdSpeed *= 0.4; // Reduce speed significantly in water
break;
}
}
self.x += Math.cos(moveToHerdAngle) * dogHerdSpeed;
self.y += Math.sin(moveToHerdAngle) * dogHerdSpeed;
} else {
// If in good herding position, apply pressure to drive animal toward hunter
var pressureAngle = Math.atan2(closestAnimal.y - self.y, closestAnimal.x - self.x);
// Check if dog is in pond and reduce speed
var dogChaseSpeed = self.speed * 1.0;
for (var p = 0; p < ponds.length; p++) {
var pond = ponds[p];
var distanceToPond = Math.sqrt(Math.pow(self.x - pond.x, 2) + Math.pow(self.y - pond.y, 2));
if (distanceToPond < 100) {
// Dog is in or near pond
dogChaseSpeed *= 0.4; // Reduce speed significantly in water
break;
}
}
self.x += Math.cos(pressureAngle) * dogChaseSpeed;
self.y += Math.sin(pressureAngle) * dogChaseSpeed;
}
// Point towards the animal being herded
self.graphics.rotation = dogToAnimalAngle;
// Bark more frequently when herding toward player (closer to hunter)
var barkFrequency = animalToHunterDistance < 200 ? 45 : 60; // More frequent barking
if (LK.ticks % barkFrequency === 0) {
LK.getSound('bark').play();
}
// Consume more energy while chasing
if (LK.ticks % 20 === 0) {
// Reduced energy consumption frequency from 15 to 20
self.energy = Math.max(0, self.energy - 0.3); // Reduced energy drain from 0.5 to 0.3
}
// Flash the dog to show it's in chase mode - green flash when successfully herding toward player
if (LK.ticks % 30 === 0) {
var flashColor = animalToHunterDistance < 150 ? 0x44FF44 : 0xFF4444; // Green when close to hunter, red otherwise
LK.effects.flashObject(self, flashColor, 150);
}
}
// If no animals are in immediate chase range, search for persistent target within larger radius
else if (!closestAnimal && self.persistentTarget && self.persistentTarget.isAlive) {
var searchDistance = Math.sqrt(Math.pow(self.x - self.persistentTarget.x, 2) + Math.pow(self.y - self.persistentTarget.y, 2));
if (searchDistance < 600) {
// Large search radius for persistent tracking
// Move directly toward the persistent target
var directAngle = Math.atan2(self.persistentTarget.y - self.y, self.persistentTarget.x - self.x);
// Check if dog is in pond and reduce speed
var dogPursuitSpeed = self.speed * 1.2;
for (var p = 0; p < ponds.length; p++) {
var pond = ponds[p];
var distanceToPond = Math.sqrt(Math.pow(self.x - pond.x, 2) + Math.pow(self.y - pond.y, 2));
if (distanceToPond < 100) {
// Dog is in or near pond
dogPursuitSpeed *= 0.4; // Reduce speed significantly in water
break;
}
}
self.x += Math.cos(directAngle) * dogPursuitSpeed;
self.y += Math.sin(directAngle) * dogPursuitSpeed;
self.graphics.rotation = directAngle;
self.wasChasing = true;
// Bark occasionally to signal pursuit
if (LK.ticks % 90 === 0) {
LK.getSound('bark').play();
}
// Flash to show active pursuit
if (LK.ticks % 60 === 0) {
LK.effects.flashObject(self, 0xFFAA00, 100); // Orange flash for long-distance pursuit
}
} else {
// Clear persistent target if too far away
self.persistentTarget = null;
}
} else if (self.isFollowing) {
// Follow footprints or hunter when not chasing
var distanceToHunter = Math.sqrt(Math.pow(self.x - hunter.x, 2) + Math.pow(self.y - hunter.y, 2));
// If dog was chasing but now stopped, smoothly return to player using tween
if (self.wasChasing && !closestAnimal) {
self.wasChasing = false;
// Use tween to smoothly move dog back to hunter
tween(self, {
x: hunter.x + self.followDistance * 0.6,
y: hunter.y + self.followDistance * 0.4
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Dog has returned to player
LK.effects.flashObject(self, 0x00FF00, 300);
}
});
return; // Skip normal movement while tweening back
}
// Check for nearby footprints to follow and find hidden animals
var nearestFootprint = null;
var nearestFootprintDistance = Infinity;
var footprintTrail = []; // Store footprints for trail following
for (var f = 0; f < footprints.length; f++) {
var footprint = footprints[f];
var footprintDistance = Math.sqrt(Math.pow(self.x - footprint.x, 2) + Math.pow(self.y - footprint.y, 2));
if (footprintDistance < 150) {
footprintTrail.push({
footprint: footprint,
distance: footprintDistance
});
}
if (footprintDistance < nearestFootprintDistance) {
nearestFootprint = footprint;
nearestFootprintDistance = footprintDistance;
}
}
// Sort footprint trail by distance for better pathfinding
footprintTrail.sort(function (a, b) {
return a.distance - b.distance;
});
// Follow footprints if found, otherwise follow hunter
if (nearestFootprint && nearestFootprintDistance < 80) {
// Move towards footprint
var angle = Math.atan2(nearestFootprint.y - self.y, nearestFootprint.x - self.x);
// Check if dog is in pond and reduce speed
var dogSpeed = self.speed * 0.9;
for (var p = 0; p < ponds.length; p++) {
var pond = ponds[p];
var distanceToPond = Math.sqrt(Math.pow(self.x - pond.x, 2) + Math.pow(self.y - pond.y, 2));
if (distanceToPond < 100) {
// Dog is in or near pond
dogSpeed *= 0.4; // Reduce speed significantly in water
break;
}
}
self.x += Math.cos(angle) * dogSpeed;
self.y += Math.sin(angle) * dogSpeed;
// Flash footprint when following it
if (LK.ticks % 60 === 0) {
LK.effects.flashObject(nearestFootprint, 0xFFFF00, 200);
}
// When close to footprint, search for nearby hidden animals
if (nearestFootprintDistance < 30) {
for (var a = 0; a < animals.length; a++) {
var animal = animals[a];
if (!animal.isAlive || animal.isDiscoveredByDog) {
continue;
}
var animalToFootprintDistance = Math.sqrt(Math.pow(animal.x - nearestFootprint.x, 2) + Math.pow(animal.y - nearestFootprint.y, 2));
var animalToDogDistance = Math.sqrt(Math.pow(animal.x - self.x, 2) + Math.pow(animal.y - self.y, 2));
// If animal is near this footprint and dog is close, discover it
if (animalToFootprintDistance < 100 && animalToDogDistance < self.detectionRadius * 1.2) {
animal.isDiscoveredByDog = true;
animal.graphics.visible = true;
animal.visibilityTimer = 0;
animal.isFadingOut = false;
animal.graphics.alpha = 1.0;
// Special effect for footprint-based discovery
LK.effects.flashObject(animal, 0x00FFFF, 1000); // Cyan flash for trail discovery
LK.effects.flashObject(nearestFootprint, 0x00FFFF, 500);
// Play bark sound for discovery
if (LK.ticks % 30 === 0) {
LK.getSound('bark').play();
}
// Point dog towards discovered animal
var discoveryAngle = Math.atan2(animal.y - self.y, animal.x - self.x);
self.graphics.rotation = discoveryAngle;
break;
}
}
}
// Consume energy while tracking
if (LK.ticks % 25 === 0) {
self.energy = Math.max(0, self.energy - 0.2);
}
} else if (distanceToHunter > self.followDistance) {
// Move towards hunter
var angle = Math.atan2(hunter.y - self.y, hunter.x - self.x);
// Check if dog is in pond and reduce speed
var dogFollowSpeed = self.speed;
for (var p = 0; p < ponds.length; p++) {
var pond = ponds[p];
var distanceToPond = Math.sqrt(Math.pow(self.x - pond.x, 2) + Math.pow(self.y - pond.y, 2));
if (distanceToPond < 100) {
// Dog is in or near pond
dogFollowSpeed *= 0.4; // Reduce speed significantly in water
break;
}
}
self.x += Math.cos(angle) * dogFollowSpeed;
self.y += Math.sin(angle) * dogFollowSpeed;
// Consume energy while moving
if (LK.ticks % 20 === 0) {
self.energy = Math.max(0, self.energy - 0.3);
}
}
}
// Apply breed-specific abilities
var detectionBonus = 1.0;
var speedBonus = 1.0;
var energyDrain = 1.0;
if (self.specialAbility === 'sight') {
// Pointer - better long distance detection
detectionBonus = 1.3;
} else if (self.specialAbility === 'stealth') {
// Setter - animals don't flee as quickly
speedBonus = 1.1;
} else if (self.specialAbility === 'endurance') {
// Husky - less energy drain
energyDrain = 0.7;
} else if (self.specialAbility === 'tracking') {
// Retriever - better footprint following
detectionBonus = 1.1;
}
// Scan for animals and ducks and make them visible when detected
self.alertCooldown = Math.max(0, self.alertCooldown - 1);
var allAnimals = animals.concat(ducks);
for (var i = 0; i < allAnimals.length; i++) {
var animal = allAnimals[i];
if (!animal.isAlive) {
continue;
}
var distance = Math.sqrt(Math.pow(self.x - animal.x, 2) + Math.pow(self.y - animal.y, 2));
// Make animal visible if dog detects it (with breed bonus)
var effectiveDetectionRadius = self.detectionRadius * detectionBonus;
if (distance < effectiveDetectionRadius && !animal.isDiscoveredByDog) {
animal.isDiscoveredByDog = true;
animal.graphics.visible = true;
animal.visibilityTimer = 0; // Reset visibility timer
animal.isFadingOut = false; // Reset fading flag
animal.graphics.alpha = 1.0; // Ensure full visibility
// Set as persistent target only if dog doesn't have one, prioritizing closer animals
if (!self.persistentTarget || !self.persistentTarget.isAlive) {
self.persistentTarget = animal;
// Flash the animal when first discovered and set as target
LK.effects.flashObject(animal, 0x00FF00, 800);
} else {
// Check if this animal is closer than current persistent target
var currentTargetDistance = Math.sqrt(Math.pow(self.x - self.persistentTarget.x, 2) + Math.pow(self.y - self.persistentTarget.y, 2));
if (distance < currentTargetDistance) {
// Switch to closer target
self.persistentTarget = animal;
// Flash the new priority target
LK.effects.flashObject(animal, 0x00FF00, 800);
} else {
// Flash discovered but not prioritized animal differently
LK.effects.flashObject(animal, 0xFFFF00, 400);
}
}
}
// Update last known position of persistent target
if (self.persistentTarget && self.persistentTarget.isAlive) {
self.lastKnownTargetX = self.persistentTarget.x;
self.lastKnownTargetY = self.persistentTarget.y;
}
}
// Alert to closest animal
if (self.alertCooldown === 0) {
var closestAnimal = null;
var closestDistance = Infinity;
var allAnimals = animals.concat(ducks);
for (var i = 0; i < allAnimals.length; i++) {
var animal = allAnimals[i];
if (!animal.isAlive || !animal.isDiscoveredByDog) {
continue;
}
var distance = Math.sqrt(Math.pow(self.x - animal.x, 2) + Math.pow(self.y - animal.y, 2));
if (distance < self.detectionRadius && distance < closestDistance) {
closestAnimal = animal;
closestDistance = distance;
}
}
if (closestAnimal && closestAnimal !== self.targetAnimal) {
self.targetAnimal = closestAnimal;
self.alertToAnimal();
self.alertCooldown = 180; // 3 seconds cooldown
}
}
// Regenerate energy when not moving much
var movement = Math.sqrt(Math.pow(self.x - self.lastX, 2) + Math.pow(self.y - self.lastY, 2));
if (movement < 1 && self.energy < 100) {
self.energy += 0.15;
}
// Dog whines when energy is very low
if (self.energy < 20 && LK.ticks % 180 === 0) {
LK.getSound('dog_whine').play();
}
// Walking animation logic
var currentlyWalking = movement > 0.5; // Dog is walking if movement is significant
// Start walking animation when movement begins
if (!self.isWalking && currentlyWalking) {
self.isWalking = true;
self.startWalkAnimation();
}
// Stop walking animation when movement stops
else if (self.isWalking && !currentlyWalking) {
self.isWalking = false;
self.stopWalkAnimation();
}
self.lastX = self.x;
self.lastY = self.y;
};
self.alertToAnimal = function () {
// Visual alert - flash the dog
LK.effects.flashObject(self, 0xFFFF00, 500);
// Point towards the animal
if (self.targetAnimal) {
var angle = Math.atan2(self.targetAnimal.y - self.y, self.targetAnimal.x - self.x);
self.graphics.rotation = angle;
// Play bark sound
LK.getSound('bark').play();
// Create tracking bonus for player - larger bonus if found via footprints
var trackingBonus = 5;
// Check if there are recent footprints nearby (indicating trail-based discovery)
for (var f = 0; f < footprints.length; f++) {
var footprint = footprints[f];
var footprintToAnimalDistance = Math.sqrt(Math.pow(self.targetAnimal.x - footprint.x, 2) + Math.pow(self.targetAnimal.y - footprint.y, 2));
if (footprintToAnimalDistance < 80) {
trackingBonus = 10; // Double bonus for footprint-based discovery
break;
}
}
hunter.tracking = Math.min(100, hunter.tracking + trackingBonus);
}
};
self.rest = function () {
// Dog rests and recovers energy faster
self.energy = Math.min(100, self.energy + 2);
};
self.startWalkAnimation = function () {
// Create a continuous bobbing animation while walking
self.walkAnimationLoop();
};
self.stopWalkAnimation = function () {
// Stop the walking animation and return to normal position
tween.stop(self.graphics, {
y: true,
scaleY: true
});
tween(self.graphics, {
y: 0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
};
self.walkAnimationLoop = function () {
if (!self.isWalking) {
return;
} // Stop if no longer walking
// Create bobbing motion with slight scale changes to simulate walking
tween(self.graphics, {
y: -3,
scaleY: 0.95
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.isWalking) {
// Bounce back down
tween(self.graphics, {
y: 0,
scaleY: 1.05
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue the loop if still walking
if (self.isWalking) {
self.walkAnimationLoop();
}
}
});
}
}
});
};
self.switchBreed = function (breedData) {
self.breed = breedData.name;
self.speed = breedData.speed;
self.detectionRadius = breedData.detection;
self.maxEnergy = breedData.energy;
self.energy = Math.min(self.energy, self.maxEnergy);
self.specialAbility = breedData.specialAbility;
// Apply breed color tint
self.graphics.tint = breedData.color;
// Flash effect for breed change
LK.effects.flashObject(self, 0x00FF00, 1000);
};
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
// Shop background panel
self.background = self.addChild(LK.getAsset('shop_panel', {
anchorX: 0.5,
anchorY: 0.5
}));
self.background.scaleX = 1.2;
self.background.scaleY = 1.5;
// Shop title
self.title = self.addChild(new Text2('HUNTING SHOP', {
size: 32,
fill: 0xFFFFFF
}));
self.title.anchor.set(0.5, 0);
self.title.y = -450;
// Close button
self.closeButton = self.addChild(LK.getAsset('buy_button', {
anchorX: 0.5,
anchorY: 0.5
}));
self.closeButton.y = 420;
self.closeButton.tint = 0xFF4444;
self.closeText = self.addChild(new Text2('CLOSE', {
size: 18,
fill: 0xFFFFFF
}));
self.closeText.anchor.set(0.5, 0.5);
self.closeText.y = 420;
// Shop items
self.items = [];
self.itemsContainer = self.addChild(new Container());
self.itemsContainer.y = -350;
self.open = function () {
self.isOpen = true;
self.visible = true;
self.setupItems();
// Bring shop to front
if (self.parent) {
self.parent.removeChild(self);
self.parent.addChild(self);
}
};
self.close = function () {
self.isOpen = false;
self.visible = false;
};
self.setupItems = function () {
// Clear existing items
for (var i = 0; i < self.items.length; i++) {
if (self.items[i].parent) {
self.items[i].destroy();
}
}
self.items = [];
// Add shop items
var yOffset = 0;
for (var i = 0; i < shopItemsData.length; i++) {
var item = self.itemsContainer.addChild(new ShopItem(shopItemsData[i]));
item.y = yOffset;
item.x = -200; // Center the items
self.items.push(item);
yOffset += 100;
}
};
self.down = function (x, y, obj) {
if (!self.isOpen) {
return;
}
// Check close button
if (x >= -60 && x <= 60 && y >= 400 && y <= 440) {
LK.getSound('button_click').play();
self.close();
}
};
// Initially hidden
self.visible = false;
return self;
});
var ShopItem = Container.expand(function (itemData) {
var self = Container.call(this);
self.itemData = itemData;
self.name = itemData.name;
self.price = itemData.price;
self.description = itemData.description;
self.type = itemData.type;
self.effect = itemData.effect;
// Create item display
self.panel = self.addChild(LK.getAsset('shop_panel', {
anchorX: 0,
anchorY: 0
}));
self.panel.scaleX = 0.8;
self.panel.scaleY = 0.3;
// Item name
self.nameText = self.addChild(new Text2(self.name, {
size: 24,
fill: 0xFFFFFF
}));
self.nameText.anchor.set(0, 0);
self.nameText.x = 10;
self.nameText.y = 10;
// Item price
self.priceText = self.addChild(new Text2('$' + self.price, {
size: 20,
fill: 0xFFD700
}));
self.priceText.anchor.set(0, 0);
self.priceText.x = 10;
self.priceText.y = 35;
// Description
self.descText = self.addChild(new Text2(self.description, {
size: 16,
fill: 0xCCCCCC
}));
self.descText.anchor.set(0, 0);
self.descText.x = 10;
self.descText.y = 60;
// Buy button
self.buyButton = self.addChild(LK.getAsset('buy_button', {
anchorX: 0,
anchorY: 0
}));
self.buyButton.x = 250;
self.buyButton.y = 30;
self.buyText = self.addChild(new Text2('BUY', {
size: 18,
fill: 0xFFFFFF
}));
self.buyText.anchor.set(0.5, 0.5);
self.buyText.x = 310;
self.buyText.y = 50;
self.down = function (x, y, obj) {
// Check if click is on buy button
if (x >= 250 && x <= 370 && y >= 30 && y <= 70) {
LK.getSound('button_click').play();
if (playerCoins >= self.price) {
playerCoins -= self.price;
applyItemEffect(self);
coinText.setText('Coins: ' + playerCoins);
// Visual feedback
LK.effects.flashObject(self.buyButton, 0x00FF00, 300);
LK.getSound('coin_pickup').play();
} else {
// Not enough coins
LK.effects.flashObject(self.buyButton, 0xFF0000, 300);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F4F2F // Dark forest green
});
/****
* Game Code
****/
// Sounds
// UI elements
// Environment
// Animals
// Hunter and equipment
// Game variables
var hunter;
var huntingDog;
var animals = [];
var trees = [];
var footprints = [];
var ponds = [];
var ducks = [];
var gameScore = 0;
var dayTime = 0; // 0-1440 (24 hours in minutes)
var isAiming = false;
// Shop system variables
var playerCoins = 100; // Starting coins
var shop;
var shopButton;
var coinText;
// Map system variables
var currentMap = 0; // 0=Forest, 1=Desert, 2=Arctic
var mapButton;
var mapText;
// Season system variables
var currentSeason = storage.currentSeason || 0; // 0=Spring, 1=Summer, 2=Autumn, 3=Winter
var seasonDuration = 3600; // 60 seconds per season at 60fps
var seasonTimer = storage.seasonTimer || 0;
var seasonButton;
var seasonText;
// Dog breed data for different seasons
var dogBreeds = [{
name: 'Retriever',
season: 'Spring',
speed: 2.5,
detection: 200,
energy: 100,
specialAbility: 'tracking',
color: 0xD2691E
}, {
name: 'Pointer',
season: 'Summer',
speed: 3.0,
detection: 250,
energy: 120,
specialAbility: 'sight',
color: 0xFFD700
}, {
name: 'Setter',
season: 'Autumn',
speed: 2.8,
detection: 180,
energy: 110,
specialAbility: 'stealth',
color: 0x8B4513
}, {
name: 'Husky',
season: 'Winter',
speed: 2.2,
detection: 220,
energy: 140,
specialAbility: 'endurance',
color: 0x708090
}];
var seasons = [{
name: 'Spring',
backgroundColor: 0x228B22,
visibility: 1.0,
animalSpawnRate: 1.2,
weatherEffect: 'rain'
}, {
name: 'Summer',
backgroundColor: 0x32CD32,
visibility: 0.8,
animalSpawnRate: 0.8,
weatherEffect: 'heat'
}, {
name: 'Autumn',
backgroundColor: 0xD2691E,
visibility: 0.9,
animalSpawnRate: 1.1,
weatherEffect: 'wind'
}, {
name: 'Winter',
backgroundColor: 0xF0F8FF,
visibility: 0.6,
animalSpawnRate: 0.7,
weatherEffect: 'snow'
}];
var maps = [{
name: 'Forest',
backgroundColor: 0x2F4F2F,
animals: ['deer', 'rabbit', 'boar', 'wolf'],
treeCount: 30,
bushCount: 50,
animalCount: 15,
pondCount: 3,
duckCount: 6,
visibility: 1.0
}, {
name: 'Desert',
backgroundColor: 0x8B7355,
animals: ['rabbit', 'boar'],
treeCount: 5,
bushCount: 20,
animalCount: 8,
pondCount: 1,
duckCount: 2,
visibility: 0.7
}, {
name: 'Arctic',
backgroundColor: 0xE6F3FF,
animals: ['deer', 'wolf'],
treeCount: 15,
bushCount: 10,
animalCount: 6,
pondCount: 2,
duckCount: 4,
visibility: 0.5
}];
// Shop items data
var shopItemsData = [{
name: 'Better Rifle',
price: 150,
description: 'Increases accuracy by 20%',
type: 'weapon',
effect: 'accuracy'
}, {
name: 'Camouflage Gear',
price: 100,
description: 'Improves stealth by 25%',
type: 'equipment',
effect: 'stealth'
}, {
name: 'Tracking Boots',
price: 80,
description: 'Better tracking skills +15%',
type: 'equipment',
effect: 'tracking'
}, {
name: 'Energy Drink',
price: 50,
description: 'Restores stamina to full',
type: 'consumable',
effect: 'stamina'
}, {
name: 'Ammo Pack',
price: 40,
description: 'Restores ammo to full',
type: 'consumable',
effect: 'ammo'
}, {
name: 'Food Rations',
price: 30,
description: 'Restores hunger to full',
type: 'consumable',
effect: 'hunger'
}];
// UI elements
var ammoBar, hungerBar, scoreText, timeText;
// Initialize hunter
hunter = game.addChild(new Hunter());
hunter.x = 1024;
hunter.y = 1366;
// Initialize hunting dog
huntingDog = game.addChild(new HuntingDog());
huntingDog.x = hunter.x + 50;
huntingDog.y = hunter.y + 30;
// Set initial dog breed based on current season
var initialBreed = dogBreeds[currentSeason];
huntingDog.switchBreed(initialBreed);
// Initialize first map
createMapEnvironment(maps[currentMap]);
// Create UI
var ammoBar = LK.getAsset('ammo_bar', {
anchorX: 0,
anchorY: 0
});
LK.gui.topLeft.addChild(ammoBar);
ammoBar.x = 120;
ammoBar.y = 20;
// Ammo label
var ammoText = new Text2('Ammo', {
size: 16,
fill: 0xFFFFFF
});
ammoText.anchor.set(0, 0);
LK.gui.topLeft.addChild(ammoText);
ammoText.x = 120;
ammoText.y = 5;
hungerBar = LK.getAsset('hunger_bar', {
anchorX: 0,
anchorY: 0
});
LK.gui.topLeft.addChild(hungerBar);
hungerBar.x = 120;
hungerBar.y = 50;
// Dog energy bar
var dogEnergyBar = LK.getAsset('stamina_bar', {
anchorX: 0,
anchorY: 0
});
LK.gui.topLeft.addChild(dogEnergyBar);
dogEnergyBar.x = 120;
dogEnergyBar.y = 80;
dogEnergyBar.tint = 0xFFD700; // Golden color for dog
// Dog energy label
var dogEnergyText = new Text2('Dog Energy', {
size: 16,
fill: 0xFFFFFF
});
dogEnergyText.anchor.set(0, 0);
LK.gui.topLeft.addChild(dogEnergyText);
dogEnergyText.x = 120;
dogEnergyText.y = 105;
scoreText = new Text2('Score: 0', {
size: 40,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -200;
scoreText.y = 20;
timeText = new Text2('Dawn', {
size: 35,
fill: 0xFFD700
});
timeText.anchor.set(0.5, 0);
LK.gui.top.addChild(timeText);
timeText.y = 20;
// Coin display
coinText = new Text2('Coins: ' + playerCoins, {
size: 40,
fill: 0xFFD700
});
coinText.anchor.set(1, 0);
LK.gui.topRight.addChild(coinText);
coinText.x = -10;
coinText.y = 60;
// Shop button
shopButton = LK.getAsset('shop_button', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomRight.addChild(shopButton);
shopButton.x = -100;
shopButton.y = -50;
var shopButtonText = new Text2('SHOP', {
size: 24,
fill: 0xFFFFFF
});
shopButtonText.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(shopButtonText);
shopButtonText.x = -100;
shopButtonText.y = -50;
// Initialize shop
shop = game.addChild(new Shop());
shop.x = 1024;
shop.y = 1366;
shop.visible = false;
// Map button
mapButton = LK.getAsset('shop_button', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(mapButton);
mapButton.x = 100;
mapButton.y = -50;
mapText = new Text2('MAP: ' + maps[currentMap].name, {
size: 20,
fill: 0xFFFFFF
});
mapText.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(mapText);
mapText.x = 100;
mapText.y = -50;
// Season button
seasonButton = LK.getAsset('shop_button', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(seasonButton);
seasonButton.x = 100;
seasonButton.y = -120;
seasonText = new Text2('SEASON: ' + seasons[currentSeason].name, {
size: 18,
fill: 0xFFFFFF
});
seasonText.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(seasonText);
seasonText.x = 100;
seasonText.y = -120;
// Create footprint function
function createFootprint(x, y) {
var footprint = game.addChild(new Footprint());
footprint.x = x;
footprint.y = y;
footprints.push(footprint);
}
// Function to switch seasons
function switchToSeason(seasonIndex) {
currentSeason = seasonIndex;
var seasonData = seasons[currentSeason];
var breedData = dogBreeds[currentSeason];
// Update background color to season theme
var mapData = maps[currentMap];
var seasonColor = seasonData.backgroundColor;
game.setBackgroundColor(seasonColor);
// Switch dog breed
if (huntingDog) {
huntingDog.switchBreed(breedData);
}
// Update UI
seasonText.setText('SEASON: ' + seasonData.name);
// Save to storage
storage.currentSeason = currentSeason;
storage.seasonTimer = 0;
seasonTimer = 0;
// Visual effects for season change
LK.effects.flashScreen(seasonColor, 1500);
}
// Function to switch maps
function switchToMap(mapIndex) {
currentMap = mapIndex;
var mapData = maps[currentMap];
// Apply current season's background color
var seasonData = seasons[currentSeason];
game.setBackgroundColor(seasonData.backgroundColor);
// Clear existing environment
for (var i = trees.length - 1; i >= 0; i--) {
if (trees[i].parent) {
trees[i].destroy();
}
}
trees = [];
// Clear existing animals
for (var i = animals.length - 1; i >= 0; i--) {
if (animals[i].parent) {
animals[i].destroy();
}
}
animals = [];
// Clear footprints
for (var i = footprints.length - 1; i >= 0; i--) {
if (footprints[i].parent) {
footprints[i].destroy();
}
}
footprints = [];
// Clear existing ponds
for (var i = ponds.length - 1; i >= 0; i--) {
if (ponds[i].parent) {
ponds[i].destroy();
}
}
ponds = [];
// Clear existing ducks
for (var i = ducks.length - 1; i >= 0; i--) {
if (ducks[i].parent) {
ducks[i].destroy();
}
}
ducks = [];
// Create new environment
createMapEnvironment(mapData);
// Update UI
mapText.setText('MAP: ' + mapData.name);
// Reset hunter position
hunter.x = 1024;
hunter.y = 1366;
// Reset dog position near hunter
if (huntingDog) {
huntingDog.x = hunter.x + 50;
huntingDog.y = hunter.y + 30;
huntingDog.energy = 100;
huntingDog.targetAnimal = null;
}
}
// Function to create environment for current map
function createMapEnvironment(mapData) {
// Create trees
for (var i = 0; i < mapData.treeCount; i++) {
var tree = game.addChild(LK.getAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
}));
tree.x = Math.random() * 1948 + 50;
tree.y = Math.random() * 2582 + 100;
// Apply map-specific tinting
if (currentMap === 1) {
// Desert
tree.tint = 0xD2B48C; // Sandy brown
} else if (currentMap === 2) {
// Arctic
tree.tint = 0xC0C0C0; // Silver/white
}
trees.push(tree);
}
// Add bushes
for (var i = 0; i < mapData.bushCount; i++) {
var bush = game.addChild(LK.getAsset('bush', {
anchorX: 0.5,
anchorY: 0.5
}));
bush.x = Math.random() * 1948 + 50;
bush.y = Math.random() * 2582 + 100;
// Apply map-specific tinting
if (currentMap === 1) {
// Desert
bush.tint = 0xDAA520; // Golden rod
} else if (currentMap === 2) {
// Arctic
bush.tint = 0xF0F8FF; // Alice blue
}
}
// Spawn animals for this map
for (var i = 0; i < mapData.animalCount; i++) {
var animalType = mapData.animals[Math.floor(Math.random() * mapData.animals.length)];
var animal = game.addChild(new Animal(animalType));
animal.x = Math.random() * 1848 + 100;
animal.y = Math.random() * 2482 + 100;
// Reset visibility for new map
animal.isDiscoveredByDog = false;
animal.graphics.visible = false;
animal.graphics.alpha = 1.0; // Reset transparency
animal.visibilityTimer = 0; // Reset visibility timer
animal.isFadingOut = false; // Reset fading flag
animals.push(animal);
}
// Create ponds
for (var i = 0; i < mapData.pondCount; i++) {
var pond = game.addChild(LK.getAsset('pond', {
anchorX: 0.5,
anchorY: 0.5
}));
pond.x = Math.random() * 1648 + 200; // Keep ponds away from edges
pond.y = Math.random() * 2382 + 200;
// Apply map-specific tinting
if (currentMap === 1) {
// Desert - more muddy water
pond.tint = 0x8FBC8F;
} else if (currentMap === 2) {
// Arctic - icy water
pond.tint = 0xAFEEEE;
}
ponds.push(pond);
}
// Spawn ducks in ponds
var ducksPerPond = Math.floor(mapData.duckCount / mapData.pondCount);
var extraDucks = mapData.duckCount % mapData.pondCount;
for (var i = 0; i < mapData.pondCount; i++) {
var pond = ponds[i];
var ducksForThisPond = ducksPerPond + (i < extraDucks ? 1 : 0);
for (var j = 0; j < ducksForThisPond; j++) {
var duck = game.addChild(new Duck());
// Position duck near pond center with some randomness
duck.x = pond.x + (Math.random() - 0.5) * 60;
duck.y = pond.y + (Math.random() - 0.5) * 60;
duck.pondX = pond.x;
duck.pondY = pond.y;
// Start ducks as invisible until dog finds them
duck.isDiscoveredByDog = false;
duck.graphics.visible = false;
duck.graphics.alpha = 1.0;
duck.visibilityTimer = 0;
duck.isFadingOut = false;
ducks.push(duck);
}
}
}
// Shop item effects function
function applyItemEffect(shopItem) {
var effect = shopItem.effect;
var type = shopItem.type;
if (type === 'consumable') {
if (effect === 'ammo') {
hunter.ammo = hunter.maxAmmo;
LK.getSound('reload').play();
} else if (effect === 'hunger') {
hunter.hunger = 100;
}
} else if (type === 'equipment' || type === 'weapon') {
if (effect === 'accuracy') {
hunter.accuracy = Math.min(100, hunter.accuracy + 20);
} else if (effect === 'stealth') {
hunter.stealth = Math.min(100, hunter.stealth + 25);
} else if (effect === 'tracking') {
hunter.tracking = Math.min(100, hunter.tracking + 15);
}
}
}
// Function to award coins for hunting
function awardCoins(animalType) {
var coinReward = 5;
if (animalType === 'deer') {
coinReward = 10;
} else if (animalType === 'boar') {
coinReward = 15;
} else if (animalType === 'wolf') {
coinReward = 25;
} else if (animalType === 'duck') {
coinReward = 12;
}
playerCoins += coinReward;
coinText.setText('Coins: ' + playerCoins);
// Create coin visual effect
var coinEffect = game.addChild(LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
}));
coinEffect.x = hunter.x;
coinEffect.y = hunter.y - 50;
// Animate coin moving up and fading
tween(coinEffect, {
y: coinEffect.y - 100,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
if (coinEffect.parent) {
coinEffect.destroy();
}
}
});
}
// Shooting function
function shootAtTarget(targetX, targetY) {
if (hunter.ammo <= 0) {
return;
}
hunter.ammo -= 1;
LK.getSound('gunshot').play();
// Check if shot is blocked by trees
var shotBlocked = false;
for (var t = 0; t < trees.length; t++) {
var tree = trees[t];
// Calculate if the shot line intersects with the tree
var dx = targetX - hunter.x;
var dy = targetY - hunter.y;
var shotLength = Math.sqrt(dx * dx + dy * dy);
// Normalize the shot direction
var shotDirX = dx / shotLength;
var shotDirY = dy / shotLength;
// Check multiple points along the shot path
for (var step = 0; step < shotLength; step += 10) {
var checkX = hunter.x + shotDirX * step;
var checkY = hunter.y + shotDirY * step;
var treeDistance = Math.sqrt(Math.pow(checkX - tree.x, 2) + Math.pow(checkY - tree.y, 2));
if (treeDistance < 50) {
// Tree collision radius
shotBlocked = true;
break;
}
}
if (shotBlocked) {
break;
}
}
// If shot is blocked, don't check for animal hits
if (shotBlocked) {
return;
}
// Check if we hit any animals or ducks
var allTargets = animals.concat(ducks);
for (var i = allTargets.length - 1; i >= 0; i--) {
var animal = allTargets[i];
var distance = Math.sqrt(Math.pow(animal.x - targetX, 2) + Math.pow(animal.y - targetY, 2));
if (distance < 60) {
// Hit!
animal.isAlive = false;
animal.graphics.alpha = 0.5;
LK.getSound('animal_hurt').play();
// Clear dog's persistent target if this animal was being chased
if (huntingDog && huntingDog.persistentTarget === animal) {
huntingDog.persistentTarget = null;
huntingDog.wasChasing = false;
// Flash dog to show successful hunt completion
LK.effects.flashObject(huntingDog, 0x00FF00, 500);
}
// Award points based on animal type
var points = 10;
if (animal.animalType === 'deer') {
points = 20;
} else if (animal.animalType === 'boar') {
points = 30;
} else if (animal.animalType === 'wolf') {
points = 50;
} else {
points = 15;
} // Duck points
gameScore += points;
LK.setScore(gameScore);
scoreText.setText('Score: ' + gameScore);
// Award coins
if (animal.animalType) {
awardCoins(animal.animalType);
} else {
awardCoins('duck'); // For ducks
}
// Flash effect
LK.effects.flashObject(animal, 0xff0000, 500);
// Remove animal after delay
LK.setTimeout(function () {
if (animal.parent) {
animal.destroy();
// Remove from appropriate array
if (animal.animalType) {
for (var j = animals.length - 1; j >= 0; j--) {
if (animals[j] === animal) {
animals.splice(j, 1);
break;
}
}
} else {
for (var j = ducks.length - 1; j >= 0; j--) {
if (ducks[j] === animal) {
ducks.splice(j, 1);
break;
}
}
}
}
}, 1000);
break;
}
}
}
// Movement handling
var targetX = hunter.x;
var targetY = hunter.y;
var isMovingToTarget = false;
function handleMove(x, y, obj) {
targetX = x;
targetY = y;
isMovingToTarget = true;
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Convert to GUI coordinates for shop button check - with null check
if (obj && obj.parent && obj.position) {
var guiPos = LK.gui.bottomRight.toLocal(obj.parent.toGlobal(obj.position));
// Check if shop button was clicked
if (guiPos.x >= -175 && guiPos.x <= -25 && guiPos.y >= -75 && guiPos.y <= -25) {
console.log("Shop button clicked!");
LK.getSound('button_click').play();
if (!shop.isOpen) {
shop.open();
console.log("Shop opened, visible:", shop.visible);
}
return;
}
// Check if map button was clicked
var mapGuiPos = LK.gui.bottomLeft.toLocal(obj.parent.toGlobal(obj.position));
if (mapGuiPos.x >= 25 && mapGuiPos.x <= 175 && mapGuiPos.y >= -75 && mapGuiPos.y <= -25) {
console.log("Map button clicked!");
LK.getSound('button_click').play();
currentMap = (currentMap + 1) % maps.length;
switchToMap(currentMap);
LK.effects.flashObject(mapButton, 0x00FF00, 300);
return;
}
// Check if season button was clicked
if (mapGuiPos.x >= 25 && mapGuiPos.x <= 175 && mapGuiPos.y >= -145 && mapGuiPos.y <= -95) {
console.log("Season button clicked!");
LK.getSound('button_click').play();
currentSeason = (currentSeason + 1) % seasons.length;
switchToSeason(currentSeason);
LK.effects.flashObject(seasonButton, 0x00FF00, 300);
return;
}
}
// Check if clicking on the dog to give it rest command
var dogDistance = Math.sqrt(Math.pow(huntingDog.x - x, 2) + Math.pow(huntingDog.y - y, 2));
if (dogDistance < 60) {
huntingDog.rest();
LK.effects.flashObject(huntingDog, 0x00FF00, 300);
return;
}
if (isAiming) {
shootAtTarget(x, y);
isAiming = false;
} else {
isAiming = true;
LK.setTimeout(function () {
isAiming = false;
}, 2000);
}
};
// Main game update loop
game.update = function () {
// Update season progression
seasonTimer++;
storage.seasonTimer = seasonTimer;
// Automatic season change every seasonDuration ticks
if (seasonTimer >= seasonDuration) {
var nextSeason = (currentSeason + 1) % seasons.length;
switchToSeason(nextSeason);
}
// Update day/night cycle
dayTime += 0.5; // 0.5 minutes per frame at 60fps = 48 minutes real time for full day
if (dayTime >= 1440) {
dayTime = 0;
}
// Update time display
var hour = Math.floor(dayTime / 60);
var timeOfDay = '';
if (hour >= 5 && hour < 12) {
timeOfDay = 'Morning';
} else if (hour >= 12 && hour < 18) {
timeOfDay = 'Afternoon';
} else if (hour >= 18 && hour < 21) {
timeOfDay = 'Evening';
} else {
timeOfDay = 'Night';
}
timeText.setText(timeOfDay + ' (' + hour + ':' + Math.floor(dayTime % 60).toString().padStart(2, '0') + ')');
// Move hunter towards target
if (isMovingToTarget) {
var dx = targetX - hunter.x;
var dy = targetY - hunter.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var moveSpeed = 3;
var newX = hunter.x + dx / distance * moveSpeed;
var newY = hunter.y + dy / distance * moveSpeed;
// Check if new position would be inside any pond
var canMove = true;
for (var p = 0; p < ponds.length; p++) {
var pond = ponds[p];
var distanceToPond = Math.sqrt(Math.pow(newX - pond.x, 2) + Math.pow(newY - pond.y, 2));
if (distanceToPond < 100) {
// Pond collision radius
canMove = false;
break;
}
}
// Only move if not colliding with pond
if (canMove) {
hunter.x = newX;
hunter.y = newY;
// Consume hunger while moving
if (LK.ticks % 10 === 0) {
hunter.hunger = Math.max(0, hunter.hunger - 0.1);
}
// Play footstep sound occasionally
if (LK.ticks % 30 === 0) {
LK.getSound('footstep').play();
}
} else {
// Stop moving if hitting pond
isMovingToTarget = false;
}
} else {
isMovingToTarget = false;
}
}
// Update UI bars
ammoBar.scaleX = hunter.ammo / hunter.maxAmmo;
hungerBar.scaleX = hunter.hunger / 100;
dogEnergyBar.scaleX = huntingDog.energy / 100;
// Update hunting dog
if (huntingDog) {
huntingDog.update();
}
// Update animals
for (var i = 0; i < animals.length; i++) {
animals[i].update();
}
// Update ducks
for (var i = 0; i < ducks.length; i++) {
ducks[i].update();
}
// Update footprints
for (var i = 0; i < footprints.length; i++) {
footprints[i].update();
}
// Spawn new animals occasionally (affected by season)
var mapData = maps[currentMap];
var seasonData = seasons[currentSeason];
var adjustedAnimalCount = Math.floor(mapData.animalCount * seasonData.animalSpawnRate);
var spawnRate = Math.floor(600 / seasonData.animalSpawnRate);
if (animals.length < adjustedAnimalCount && LK.ticks % spawnRate === 0) {
var animalType = mapData.animals[Math.floor(Math.random() * mapData.animals.length)];
var animal = game.addChild(new Animal(animalType));
animal.x = Math.random() * 1848 + 100;
animal.y = Math.random() * 2482 + 100;
// Start new animals as invisible until dog finds them
animal.isDiscoveredByDog = false;
animal.graphics.visible = false;
animal.graphics.alpha = 1.0; // Reset transparency
animal.visibilityTimer = 0; // Reset visibility timer
animal.isFadingOut = false; // Reset fading flag
animals.push(animal);
}
// Spawn new ducks occasionally
if (ducks.length < mapData.duckCount && LK.ticks % 800 === 0) {
if (ponds.length > 0) {
var randomPond = ponds[Math.floor(Math.random() * ponds.length)];
var duck = game.addChild(new Duck());
duck.x = randomPond.x + (Math.random() - 0.5) * 60;
duck.y = randomPond.y + (Math.random() - 0.5) * 60;
duck.pondX = randomPond.x;
duck.pondY = randomPond.y;
// Start new ducks as invisible until dog finds them
duck.isDiscoveredByDog = false;
duck.graphics.visible = false;
duck.graphics.alpha = 1.0;
duck.visibilityTimer = 0;
duck.isFadingOut = false;
ducks.push(duck);
}
}
// Game over condition - if hunter runs out of hunger
if (hunter.hunger <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -32,9 +32,11 @@
// Movement timer
self.moveTimer = 0;
self.moveChangeInterval = 60 + Math.random() * 120;
self.update = function () {
- if (!self.isAlive) return;
+ if (!self.isAlive) {
+ return;
+ }
// Random movement behavior
self.moveTimer++;
if (self.moveTimer >= self.moveChangeInterval) {
self.direction += (Math.random() - 0.5) * 0.5;
@@ -153,9 +155,11 @@
self.isFadingOut = false;
self.moveTimer = 0;
self.moveChangeInterval = 90 + Math.random() * 60;
self.update = function () {
- if (!self.isAlive) return;
+ if (!self.isAlive) {
+ return;
+ }
// Duck swimming behavior - stay near pond center
self.moveTimer++;
if (self.moveTimer >= self.moveChangeInterval) {
// Change direction occasionally
@@ -308,9 +312,11 @@
self.isWalking = false;
self.walkAnimationOffset = 0;
self.walkAnimationSpeed = 0.2;
self.update = function () {
- if (self.energy <= 0) return;
+ if (self.energy <= 0) {
+ return;
+ }
// Single target priority system - only chase one animal at a time
var targetAnimal = null;
var targetDistance = Infinity;
// First priority: continue chasing persistent target if it exists and is alive
@@ -329,9 +335,11 @@
if (!targetAnimal) {
var allAnimals = animals.concat(ducks);
for (var a = 0; a < allAnimals.length; a++) {
var animal = allAnimals[a];
- if (!animal.isAlive || !animal.isDiscoveredByDog) continue;
+ if (!animal.isAlive || !animal.isDiscoveredByDog) {
+ continue;
+ }
var animalDistance = Math.sqrt(Math.pow(self.x - animal.x, 2) + Math.pow(self.y - animal.y, 2));
if (animalDistance < 250 && animalDistance < targetDistance) {
targetAnimal = animal;
targetDistance = animalDistance;
@@ -517,9 +525,11 @@
// When close to footprint, search for nearby hidden animals
if (nearestFootprintDistance < 30) {
for (var a = 0; a < animals.length; a++) {
var animal = animals[a];
- if (!animal.isAlive || animal.isDiscoveredByDog) continue;
+ if (!animal.isAlive || animal.isDiscoveredByDog) {
+ continue;
+ }
var animalToFootprintDistance = Math.sqrt(Math.pow(animal.x - nearestFootprint.x, 2) + Math.pow(animal.y - nearestFootprint.y, 2));
var animalToDogDistance = Math.sqrt(Math.pow(animal.x - self.x, 2) + Math.pow(animal.y - self.y, 2));
// If animal is near this footprint and dog is close, discover it
if (animalToFootprintDistance < 100 && animalToDogDistance < self.detectionRadius * 1.2) {
@@ -589,9 +599,11 @@
self.alertCooldown = Math.max(0, self.alertCooldown - 1);
var allAnimals = animals.concat(ducks);
for (var i = 0; i < allAnimals.length; i++) {
var animal = allAnimals[i];
- if (!animal.isAlive) continue;
+ if (!animal.isAlive) {
+ continue;
+ }
var distance = Math.sqrt(Math.pow(self.x - animal.x, 2) + Math.pow(self.y - animal.y, 2));
// Make animal visible if dog detects it (with breed bonus)
var effectiveDetectionRadius = self.detectionRadius * detectionBonus;
if (distance < effectiveDetectionRadius && !animal.isDiscoveredByDog) {
@@ -631,9 +643,11 @@
var closestDistance = Infinity;
var allAnimals = animals.concat(ducks);
for (var i = 0; i < allAnimals.length; i++) {
var animal = allAnimals[i];
- if (!animal.isAlive || !animal.isDiscoveredByDog) continue;
+ if (!animal.isAlive || !animal.isDiscoveredByDog) {
+ continue;
+ }
var distance = Math.sqrt(Math.pow(self.x - animal.x, 2) + Math.pow(self.y - animal.y, 2));
if (distance < self.detectionRadius && distance < closestDistance) {
closestAnimal = animal;
closestDistance = distance;
@@ -714,9 +728,11 @@
easing: tween.easeOut
});
};
self.walkAnimationLoop = function () {
- if (!self.isWalking) return; // Stop if no longer walking
+ if (!self.isWalking) {
+ return;
+ } // Stop if no longer walking
// Create bobbing motion with slight scale changes to simulate walking
tween(self.graphics, {
y: -3,
scaleY: 0.95
@@ -823,9 +839,11 @@
yOffset += 100;
}
};
self.down = function (x, y, obj) {
- if (!self.isOpen) return;
+ if (!self.isOpen) {
+ return;
+ }
// Check close button
if (x >= -60 && x <= 60 && y >= 400 && y <= 440) {
LK.getSound('button_click').play();
self.close();
@@ -1412,9 +1430,17 @@
}
// Function to award coins for hunting
function awardCoins(animalType) {
var coinReward = 5;
- if (animalType === 'deer') coinReward = 10;else if (animalType === 'boar') coinReward = 15;else if (animalType === 'wolf') coinReward = 25;else if (animalType === 'duck') coinReward = 12;
+ if (animalType === 'deer') {
+ coinReward = 10;
+ } else if (animalType === 'boar') {
+ coinReward = 15;
+ } else if (animalType === 'wolf') {
+ coinReward = 25;
+ } else if (animalType === 'duck') {
+ coinReward = 12;
+ }
playerCoins += coinReward;
coinText.setText('Coins: ' + playerCoins);
// Create coin visual effect
var coinEffect = game.addChild(LK.getAsset('coin', {
@@ -1437,9 +1463,11 @@
});
}
// Shooting function
function shootAtTarget(targetX, targetY) {
- if (hunter.ammo <= 0) return;
+ if (hunter.ammo <= 0) {
+ return;
+ }
hunter.ammo -= 1;
LK.getSound('gunshot').play();
// Check if shot is blocked by trees
var shotBlocked = false;
@@ -1462,9 +1490,11 @@
shotBlocked = true;
break;
}
}
- if (shotBlocked) break;
+ if (shotBlocked) {
+ break;
+ }
}
// If shot is blocked, don't check for animal hits
if (shotBlocked) {
return;
@@ -1487,9 +1517,17 @@
LK.effects.flashObject(huntingDog, 0x00FF00, 500);
}
// Award points based on animal type
var points = 10;
- if (animal.animalType === 'deer') points = 20;else if (animal.animalType === 'boar') points = 30;else if (animal.animalType === 'wolf') points = 50;else points = 15; // Duck points
+ if (animal.animalType === 'deer') {
+ points = 20;
+ } else if (animal.animalType === 'boar') {
+ points = 30;
+ } else if (animal.animalType === 'wolf') {
+ points = 50;
+ } else {
+ points = 15;
+ } // Duck points
gameScore += points;
LK.setScore(gameScore);
scoreText.setText('Score: ' + gameScore);
// Award coins
@@ -1598,13 +1636,23 @@
switchToSeason(nextSeason);
}
// Update day/night cycle
dayTime += 0.5; // 0.5 minutes per frame at 60fps = 48 minutes real time for full day
- if (dayTime >= 1440) dayTime = 0;
+ if (dayTime >= 1440) {
+ dayTime = 0;
+ }
// Update time display
var hour = Math.floor(dayTime / 60);
var timeOfDay = '';
- if (hour >= 5 && hour < 12) timeOfDay = 'Morning';else if (hour >= 12 && hour < 18) timeOfDay = 'Afternoon';else if (hour >= 18 && hour < 21) timeOfDay = 'Evening';else timeOfDay = 'Night';
+ if (hour >= 5 && hour < 12) {
+ timeOfDay = 'Morning';
+ } else if (hour >= 12 && hour < 18) {
+ timeOfDay = 'Afternoon';
+ } else if (hour >= 18 && hour < 21) {
+ timeOfDay = 'Evening';
+ } else {
+ timeOfDay = 'Night';
+ }
timeText.setText(timeOfDay + ' (' + hour + ':' + Math.floor(dayTime % 60).toString().padStart(2, '0') + ')');
// Move hunter towards target
if (isMovingToTarget) {
var dx = targetX - hunter.x;
Wild Boar. In-Game asset. 2d. High contrast. No shadows
Bush. In-Game asset. 2d. High contrast. No shadows
Tree. In-Game asset. 2d. High contrast. No shadows
Deer. In-Game asset. 2d. High contrast. No shadows
Hunter. In-Game asset. 2d. High contrast. No shadows
Rifle. In-Game asset. 2d. High contrast. No shadows
Wolf. In-Game asset. 2d. High contrast. No shadows
Rabbit. High contrast. No shadows
Coin. In-Game asset. 2d. High contrast. No shadows
Animal Footprint. High contrast. No shadows
Shop Button. In-Game asset. 2d. High contrast. No shadows
Duck Flying. In-Game asset. 2d. No shadows