/****
* Classes
****/
/**
* config {
* x : Number || 0,
* y : Number || 0,
* rotation : Number || 0,
* }
**/
var ConfigContainer = Container.expand(function (config) {
var self = Container.call(this);
config = config || {};
;
self.x = config.x || 0;
self.y = config.y || 0;
self.rotation = config.rotation || 0;
if (config.scale !== undefined || config.scaleX !== undefined || config.scaleY !== undefined) {
var scaleX = config.scaleX !== undefined ? config.scaleX : config.scale !== undefined ? config.scale : 1;
var scaleY = config.scaleY !== undefined ? config.scaleY : config.scale !== undefined ? config.scale : 1;
self.scale.set(scaleX, scaleY);
}
;
return self;
});
var Spawner = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var spawnFunction = config.spawnFunction;
var positionFunction = config.positionFunction;
var margin = config.margin;
;
self.update = function () {
while (self.x - frog.x < margin) {
self.x += positionFunction(self);
spawnFunction(self, self.x);
}
};
return self;
});
var ShiftContainer = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
config = config || {};
self.shift = config.shift !== undefined ? config.shift : 1.0;
;
return self;
});
var Pickup = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
config = config || {};
var collected = false;
var collectable = self.attachAsset('collectable', {
anchorX: 0.5,
anchorY: 0.5,
rotation: Math.random() * Math.PI * 2
});
self.collect = function () {
if (!collected) {
collected = true;
LK.getSound('pickupCaught').play();
gameInterface.increaseMultiplier();
self.destroy();
}
};
self.update = function () {
if (!collected && checkVacinity(self, frog) && collectable.intersects(frog.collision)) {
self.collect();
} else if (self.x < firewall.x) {
self.destroy();
}
};
return self;
});
var Lilypad = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
config = config || {};
;
var inert = config.inert !== undefined ? config.inert : false;
var active = config.active !== undefined ? config.active : true;
var destroying = false;
var pickup = undefined;
var stalk = self.attachAsset('stalk', {
anchorX: 0.5,
y: LILYPAD_STALK_OFFSET,
width: 15,
height: -(self.y + LILYPAD_STALK_OFFSET) * LILYPAD_HEIGHT_FACTOR,
rotation: LILYPAD_ANGLE * (1 - 2 * Math.random()),
tint: 0x90ee90 // light green
});
var lilypad = self.attachAsset('lilypad', {
anchorX: 0.5,
anchorY: 0.5
});
if (!inert && Math.random() < LILYPAD_PICKUP_CHANCE) {
pickup = pickupContainer.addChild(new Pickup({
x: self.x,
y: self.y - LILYPAD_PICKUP_OFFSET_MIN - LILYPAD_PICKUP_OFFSET_VAR * Math.random()
}));
}
;
self.launch = function () {
active = false;
destroying = true;
LK.getSound('frogBounce').play();
if (pickup) {
pickup.collect();
}
};
self.update = function () {
if (destroying) {
if (self.alpha <= 0) {
self.destroy();
}
self.alpha -= 0.1;
self.y += 10;
} else if (active && checkVacinity(self, frog) && lilypad.intersects(frog.collision)) {
frog.bounce();
self.launch();
}
if (self.x < firewall.x) {
self.destroy();
}
};
;
return self;
});
var Interface = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var score = 0;
var multiplier = 1.0;
var scoreText = self.addChild(new BorderedText('0', {
y: -75,
size: 1.5 * TEXT_DEFAULT_SIZE,
anchorX: 0.5
}));
var multiplierText = self.addChild(new BorderedText('1.0x', {
y: 0,
anchorX: 0.5,
anchorY: 0.5
}));
;
self.finalize = function () {
LK.setScore(Math.floor(score));
};
self.increaseDistance = function (distance) {
self.updateScore(score + distance * SCORE_PER_DISTANCE * multiplier);
};
self.updateScore = function (newScore) {
score = newScore;
scoreText.setText(Math.floor(score));
};
self.increaseMultiplier = function () {
self.updateMultiplier(multiplier + SCORE_PICKUP_MULTIPLER);
};
self.updateMultiplier = function (newMultiplier) {
multiplier = newMultiplier;
multiplierText.setText(newMultiplier.toFixed(1) + 'x');
};
;
return self;
});
var Hook = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
// Removed highlightContainer
var hook = self.attachAsset('hook', {
anchorX: 0.5,
anchorY: 0.5
});
var flipInterval = HOOK_FLIPTICKS_MIN + Math.floor(Math.random() * HOOK_FLIPTICKS_VAR);
var flipCounter = 0;
;
self.enabled = true;
self.disable = function () {
self.enabled = false;
var originalTint = hook.tint;
hook.tint = 0x222222; // Dark grey
var disableTicks = HOOK_OFFLINE;
var disableTimeout = LK.setTimeout(function () {
self.enabled = true;
hook.tint = originalTint;
}, 1000 * disableTicks / GAME_TICKS);
};
self.update = function () {
flipCounter++;
if (flipCounter >= flipInterval) {
hook.scale.x *= -1;
flipCounter = 0;
flipInterval = HOOK_FLIPTICKS_MIN + Math.floor(Math.random() * HOOK_FLIPTICKS_VAR);
}
if (self.x < firewall.x) {
if (self === frog.hookedObj) {
frog.release();
}
self.destroy();
}
};
;
return self;
});
var Highlight = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
self.addChild(new BorderedSymbol('highlight', {
anchorX: 0.5,
anchorY: 0.5,
weight: 4
}));
self.update = function () {
self.rotation += 0.01;
};
return self;
});
var Grass = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
config = config || {};
var grass = self.attachAsset(config.asset, {
anchorX: 0.5,
anchorY: 1.0,
scaleX: config.scale * (Math.random() < 0.5 ? 1 : -1),
scaleY: config.scale,
tint: 0x1a1a3f,
// Slight hue added to the dark tint
// 90% black
alpha: 0.75
});
self.update = function () {
if (self.x < firewall.x) {
self.destroy();
}
};
return self;
});
var FrogTongue = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
;
var tongueBody = self.attachAsset('shapeBox', {
anchorX: 0,
anchorY: 0.5,
height: 10,
width: config.length,
tint: 0xff69b4 // slightly darker pink
});
var tongueTip = self.attachAsset('shapeEllipse', {
anchorX: 0.5,
anchorY: 0.5,
height: 15,
width: 20,
x: config.length,
tint: 0xff69b4 // slightly darker pink
});
;
return self;
});
var Frog = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
;
var hooked = false;
self.sitting = true;
var velocityX = 0;
var velocityY = 0;
var velocityAngle = 0;
self.hookedObj = undefined;
var hookLength = 0;
var tangentialVelocity = 0;
var angularVelocity = 0;
var tongue = undefined;
var tongueContainer = self.addChild(new Container());
var frog = self.attachAsset('frog', {
anchorX: 0.5,
anchorY: 0.5
});
var collision = self.attachAsset('shapeEllipse', {
anchorX: 0.5,
anchorY: 0.5,
width: 75,
height: 75,
alpha: 0 // Hide the collision
});
;
var rangeIndicator = self.attachAsset('rangeIndicator', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1
});
self.collision = collision;
self.attach = function (hook) {
if (hook) {
hooked = true;
self.sitting = false;
self.hookedObj = hook;
var dx = self.x - self.hookedObj.x;
var dy = self.y - self.hookedObj.y;
hookLength = Math.max(PLAYER_TONGUE_RANGE_MIN, Math.sqrt(dx * dx + dy * dy));
velocityAngle = Math.atan2(dy, dx);
var direction = Math.atan2(velocityY, velocityX);
var magnitude = Math.sin(direction - velocityAngle) * PLAYER_ATTACH_MULTIPLIER;
angularVelocity = magnitude * Math.sqrt(velocityX * velocityX + velocityY * velocityY) / hookLength;
tongue = tongueContainer.addChild(new FrogTongue({
length: hookLength
}));
self.rotation = velocityAngle + Math.PI;
LK.getSound('frogTongue').play();
} else {
LK.getSound('noTarget').play();
}
};
self.release = function () {
if (tongue) {
tongue.destroy();
tongue = undefined;
}
if (hooked) {
self.hookedObj.disable();
self.hookedObj = undefined;
hooked = false;
// Convert tangential velocity into new vx and vy
velocityX = angularVelocity * hookLength * Math.cos(velocityAngle + MATH_HALF_PI) * PLAYER_RELEASE_MULTIPLIER;
velocityY = angularVelocity * hookLength * Math.sin(velocityAngle + MATH_HALF_PI) * PLAYER_RELEASE_MULTIPLIER - PLAYER_RELEASE_VY_BONUS;
hookLength = 0;
}
};
self.bounce = function () {
if (hooked) {
angularVelocity *= PLAYER_BOUNCE_FACTOR;
} else {
velocityY = -Math.abs(velocityY * PLAYER_BOUNCE_FACTOR);
}
};
self.update = function () {
if (!self.sitting) {
if (hooked) {
var hookAngle = Math.atan2(self.y - self.hookedObj.y, self.x - self.hookedObj.x);
var perpendicularAcceleration = PLAYER_GRAVITY * Math.sin(hookAngle + MATH_HALF_PI);
angularVelocity += perpendicularAcceleration / hookLength;
angularVelocity *= PLAYER_ANGULAR_DAMPENING;
velocityAngle += angularVelocity;
velocityX = self.hookedObj.x + hookLength * Math.cos(velocityAngle) - self.x;
velocityY = self.hookedObj.y + hookLength * Math.sin(velocityAngle) - self.y;
camera.shift(velocityX, velocityY);
self.rotation = Math.atan2(self.y - self.hookedObj.y, self.x - self.hookedObj.x) + Math.PI;
} else {
velocityY += PLAYER_GRAVITY;
self.rotation += angularVelocity * PLAYER_SPIN_MAGNITUDE;
camera.shift(velocityX, velocityY);
}
}
};
;
return self;
});
var Foreground = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
config = config || {};
var tint = config.tint !== undefined ? config.tint : 0xFFFFFF;
var coverage = config.coverage !== undefined ? config.coverage : 0;
var covered = 0;
var segmentWidth = 0;
var flipX = -1;
var scaleX = self.scale.x;
do {
var foregroundLeft = self.attachAsset('foreground', {
x: -covered / 2,
anchorX: Math.max(0, flipX),
anchorY: 1.0,
scaleX: flipX,
tint: tint
});
var foregroundRight = self.attachAsset('foreground', {
x: covered / 2,
anchorX: Math.max(0, flipX),
anchorY: 1.0,
scaleX: -flipX,
tint: tint
});
covered += segmentWidth || (segmentWidth = foregroundRight.width + foregroundLeft.width);
flipX *= -1;
} while (covered < coverage);
;
self.update = function () {
if (self.x <= -segmentWidth * scaleX) {
self.x += segmentWidth * scaleX;
}
if (self.x >= segmentWidth * scaleX) {
self.x -= segmentWidth * scaleX;
}
};
;
return self;
});
var Firewall = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var speed = FIREWALL_SPEED;
var columns = [];
var columnCount = config.columns || 0;
var firewallOverlay = self.attachAsset('shapeBox', {
anchorX: 1,
anchorY: 1,
width: 2 * GAME_WIDTH,
height: 2 * GAME_HEIGHT,
tint: 0x000000,
alpha: 0.85
});
var firewallBase = self.attachAsset('firewallBase', {
anchorX: 0.5,
anchorY: 1.0
});
columns.push(firewallBase);
for (var i = 0; i < columnCount; i++) {
var firewallColumn = LK.getAsset('firewallColumn', {});
var column = self.attachAsset('firewallColumn', {
anchorX: 0.5,
anchorY: 1.0,
y: -firewallBase.height * FIREWALL_OFFSET - i * firewallColumn.height * FIREWALL_OFFSET,
scaleX: Math.random() > 0.5 ? 1 : -1
});
columns.push(column);
}
self.update = function () {
var randomColumn = columns[Math.floor(Math.random() * columns.length)];
randomColumn.scale.x *= -1;
if (!frog.sitting) {
speed += FIREWALL_SPEED_INC;
self.x += speed;
if (self.x < frog.x - FIREWALL_DISTANCE_MAX) {
self.x = frog.x - FIREWALL_DISTANCE_MAX;
}
}
};
return self;
});
var Camera = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var distance = 0;
var distanceMax = 0;
var hookSpawnDist = self.zoom = 1;
self.shift = function (x, y) {
// Shift all nested instances attached to the camera
for (var i = 0; i < self.children.length; i++) {
var shiftContainer = self.children[i];
var shiftX = shiftContainer.shift * x;
for (var j = 0; j < shiftContainer.children.length; j++) {
var childInstance = shiftContainer.children[j];
childInstance.x -= shiftX;
}
}
// Manually adjust the frog's position
frog.x += x;
frog.y += y;
// Keep track of the scoring
distance += x;
if (distance > distanceMax) {
gameInterface.increaseDistance(distance - distanceMax);
distanceMax = distance;
}
};
self.update = function () {
self.zoom = Math.min(1, GAME_HEIGHT / (Math.abs(frog.y) * PLAYER_SCREEN_MARGIN));
self.scale.set(self.zoom);
moon.scale.set(1 - MOON_SCALING + MOON_SCALING * self.zoom);
};
});
/**
* config {
* x : Number || 0, // See: ConfigContainer
* y : Number || 0, // See: ConfigContainer
* rotation : Number || 0, // See: ConfigContainer
* anchorX : Number || 0,
* anchorY : Number || 1,
* size : Number || TEXT_DEFAULT_SIZE,
* weight : Number || TEXT_DEFAULT_WEIGHT,
* font : String || TEXT_DEFAULT_FONT,
* fill : String || TEXT_DEFAULT_FILL,
* border : String || TEXT_DEFAULT_BORDER,
* }
**/
var BorderedText = ConfigContainer.expand(function (text, config) {
var self = ConfigContainer.call(this, config);
config = config || {};
;
var anchorX = config.anchorX !== undefined ? config.anchorX : 0;
var anchorY = config.anchorY !== undefined ? config.anchorY : 1;
var size = config.size !== undefined ? config.size : TEXT_DEFAULT_SIZE;
var weight = config.weight !== undefined ? config.weight : TEXT_DEFAULT_WEIGHT;
var font = config.font !== undefined ? config.font : TEXT_DEFAULT_FONT;
var textFill = config.fill !== undefined ? config.fill : TEXT_DEFAULT_FILL;
var borderFill = config.border !== undefined ? config.border : TEXT_DEFAULT_BORDER;
var textAssets = [];
var mainAsset;
;
self.setText = setText;
self.setFill = setFill;
;
function setText(newText) {
for (var i = 0; i < textAssets.length; i++) {
textAssets[i].setText(newText);
}
}
function setFill(newFill) {
textFill = newFill;
mainAsset.fill = newFill;
}
function buildTextAssets(newText) {
for (var i = 0; i < TEXT_OFFSETS.length; i++) {
var main = i === TEXT_OFFSETS.length - 1;
var fill = main ? textFill : borderFill;
var textAsset = textAssets[i];
if (textAsset) {
textAsset.destroy();
}
textAsset = self.addChild(new Text2(newText, {
fill: fill,
font: font,
size: size
}));
textAsset.anchor = {
x: anchorX,
y: anchorY
}; // NOTE: Cannot be set in config
textAsset.x = TEXT_OFFSETS[i][0] * weight; // NOTE: Cannot be set in config
textAsset.y = TEXT_OFFSETS[i][1] * weight; // NOTE: Cannot be set in config
textAssets[i] = textAsset;
}
mainAsset = textAssets[TEXT_OFFSETS.length - 1];
}
;
buildTextAssets(text);
return self;
});
/**
* var config = {
* x : Number || 0, // See: ConfigContainer
* y : Number || 0, // See: ConfigContainer
* rotation : Number || 0, // See: ConfigContainer
* anchorX : Number || .5,
* anchorY : Number || .5,
* scale : Number || undefined,
* scaleX : Number || scale,
* scaleY : Number || scale,
* weight : Number || TEXT_DEFAULT_WEIGHT,
* width : Number || undefined, // Auto-calculated if left undefined and height is set
* height : Number || undefined, // Auto-calculated if left undefined and width is set
* tint : String || 0xFFFFFF, // Not tinted by default
* border : String || TEXT_DEFAULT_BORDER,
* }
**/
var BorderedSymbol = ConfigContainer.expand(function (symbol, config) {
var self = ConfigContainer.call(this, config);
config = config || {};
var width = config.width !== undefined ? config.width : undefined;
var height = config.height !== undefined ? config.height : undefined;
var scale = config.scale !== undefined ? config.scale : undefined;
var scaleX = config.scaleX !== undefined ? config.scaleX : scale;
var scaleY = config.scaleY !== undefined ? config.scaleX : scale;
var weight = config.weight !== undefined ? config.weight : TEXT_DEFAULT_WEIGHT;
var anchorX = config.anchorX !== undefined ? config.anchorX : .5;
var anchorY = config.anchorY !== undefined ? config.anchorY : .5;
var symbolTint = config.tint !== undefined ? config.tint : 0xFFFFFF;
var borderTint = config.border !== undefined ? config.border : TEXT_DEFAULT_BORDER;
var mainSymbol;
var symbolAssets = [];
;
self.setSymbol = buildSymbolAssets;
self.setTint = setTint;
;
function setTint(newTint) {
// NOTE: Tinting is currently broken (cannot use string)
// mainSymbol.tint = newTint;
// symbolConfig.tint = newTint
}
function buildSymbolAssets(newSymbol) {
for (var i = 0; i < TEXT_OFFSETS.length; i++) {
var main = i === TEXT_OFFSETS.length - 1;
var symbolAsset = symbolAssets[i];
if (symbolAsset) {
symbolAsset.destroy();
}
symbolAsset = self.attachAsset(newSymbol, {
// tint: main ? symbolTint : borderTint,
tint: main ? 0xFFFFFF : 0x000000,
// NOTE: Tinting is currently broken (cannot use string)
x: TEXT_OFFSETS[i][0] * weight,
y: TEXT_OFFSETS[i][1] * weight,
anchorX: anchorX,
anchorY: anchorY
});
if (width !== undefined && height === undefined) {
height = symbolAsset.height * (width / symbolAsset.width);
} else if (height !== undefined && width === undefined) {
width = symbolAsset.width * (height / symbolAsset.height);
}
symbolAsset.width = width;
symbolAsset.height = height;
if (scaleX !== undefined && scaleY !== undefined) {
symbolAsset.scale.set(scaleX, scaleY);
}
symbolAssets[i] = symbolAsset;
}
mainSymbol = symbolAssets[TEXT_OFFSETS.length - 1];
}
;
buildSymbolAssets(symbol);
return self;
});
/****
* Initialize Game
****/
//<Assets used in the game will automatically appear here>
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
;
//==============================================================================
// Global Constants & Settings
//==============================================================================
;
// Game Constants
var GAME_TICKS = 60;
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var GAME_VACINITY_DIST = 200;
;
// Math Constants / Pre-calculations
var MATH_4_PI = Math.PI * 4;
var MATH_2_PI = Math.PI * 2;
var MATH_HALF_PI = Math.PI / 2;
var MATH_HALF_ROOT_3 = Math.sqrt(3) / 2; // Required by: TEXT_OFFSETS, BorderedText, BorderedSymbol, BorderedShape, SymbolText
;
// Text Settings
var TEXT_OFFSETS = [[0, 1], [MATH_HALF_ROOT_3, 0.5], [MATH_HALF_ROOT_3, -0.5], [0, -1], [-MATH_HALF_ROOT_3, -0.5], [-MATH_HALF_ROOT_3, 0.5], [0, 0]]; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText
var TEXT_DEFAULT_WEIGHT = 8; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText
var TEXT_DEFAULT_BORDER = '#FFFFFF'; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText
var TEXT_DEFAULT_FILL = '#000000'; // Required by: BorderedText, SymbolText
var TEXT_DEFAULT_FONT = 'Consolas'; // Required by: BorderedText, SymbolText
var TEXT_DEFAULT_SIZE = 120; // Required by: BorderedText, SymbolText
;
// Firewall Settings
var FIREWALL_OFFSET = 0.7;
var FIREWALL_SPEED = 2;
var FIREWALL_SPEED_INC = 0.1 / GAME_TICKS;
var FIREWALL_START_X = -GAME_WIDTH / 2 - 500;
var FIREWALL_SOUND_COUNT = 4;
var FIREWALL_SOUND_DIVDIST = 1000;
var FIREWALL_DISTANCE_MAX = 3 * GAME_WIDTH;
;
// Lilypad Settings
var LILYPAD_ANGLE = 10 * Math.PI / 180;
var LILYPAD_HEIGHT_FACTOR = 1.025;
var LILYPAD_STALK_OFFSET = -5;
var LILYPAD_SPAWN_MARGIN = 2 * GAME_WIDTH;
var LILYPAD_SPAWN_X_MIN = 50;
var LILYPAD_SPAWN_X_VAR = 1450;
var LILYPAD_SPAWN_Y_MIN = -50;
var LILYPAD_SPAWN_Y_VAR = -300;
var LILYPAD_PICKUP_CHANCE = 0.25;
var LILYPAD_PICKUP_OFFSET_MIN = 50;
var LILYPAD_PICKUP_OFFSET_VAR = 100;
;
// Hook Settings
var HOOK_OFFLINE = 1 * GAME_TICKS;
var HOOK_SPAWN_MARGIN = 2 * GAME_WIDTH;
var HOOK_SPAWN_X_MIN = 500;
var HOOK_SPAWN_X_VAR = 1000;
var HOOK_SPAWN_Y_MIN = -700;
var HOOK_SPAWN_Y_VAR = -900;
var HOOK_DOUBLE_CHANCE = 0.1;
var HOOK_DOUBLE_SPREAD = 0.25;
var HOOK_FLIPTICKS_MIN = 20;
var HOOK_FLIPTICKS_VAR = 40;
var HOOK_SEARCH_OFFSET = 100;
;
// Player Settings
var PLAYER_START_X = -400;
var PLAYER_START_Y = -1300;
var PLAYER_GRAVITY = 0.5;
var PLAYER_SPIN_MAGNITUDE = -2.0;
var PLAYER_ANGULAR_DAMPENING = 0.9995;
var PLAYER_TONGUE_RANGE_MIN = 200;
var PLAYER_TONGUE_RANGE_MAX = 1000;
var PLAYER_ATTACH_MULTIPLIER = 1.12;
var PLAYER_RELEASE_MULTIPLIER = 1.12;
var PLAYER_RELEASE_VY_BONUS = 5;
var PLAYER_BOUNCE_FACTOR = -1.12;
var PLAYER_SCREEN_MARGIN = 1.25;
;
// Background Settings
var MOON_SCALING = 0.25;
var FOREGROUND_COVERAGE = 6 * GAME_WIDTH;
var FOREGROUND_OFFSET_X = 200;
var FOREGROUND_SCALE = 1.0;
var FOREGROUND_MOVEMENT = 25;
var FOREGROUND_SHIFT_FACTOR = 1.0;
var SHADOWGROUND_OFFSET_X = -50;
var SHADOWGROUND_OFFSET_Y = -200;
var SHADOWGROUND_SCALE = 0.65;
var SHADOWGROUND_SHIFT_FACTOR = 0.7;
var GRASS_ASSETS = ['grassTall', 'grassShort', 'grassAngled', 'grassShort', 'grassAngled'];
var GRASS_SPAWN_MARGIN = 2 * GAME_WIDTH;
var GRASS_SCALE_VAR = 0.15;
var GRASS_SPAWN_X_MIN = 10;
var GRASS_SPAWN_X_VAR = 990;
var GRASS_SPAWN_Y = 200;
var GRASS_SHIFT_FACTOR_1 = 1.25;
var GRASS_SHIFT_FACTOR_2 = 1.35;
;
// Scoring Settings
var SCORE_PER_DISTANCE = 0.01;
var SCORE_PICKUP_MULTIPLER = 0.1;
;
//==============================================================================
// Game Instances & Variables
//==============================================================================
;
var paused = true;
var gameOver = false;
var background = game.addChild(LK.getAsset('background', {
anchorX: 0.5,
anchorY: 1.0,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT
}));
var moon = game.addChild(LK.getAsset('moon', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT / 2 - 400
}));
var gameInterface = game.addChild(new Interface({
x: moon.x,
y: moon.y
}));
var camera = game.addChild(new Camera({
x: GAME_WIDTH / 2,
y: GAME_HEIGHT
}));
// Camera containers
camera.addChild(new ShiftContainer({
shift: SHADOWGROUND_SHIFT_FACTOR
})).addChild(new Foreground({
x: PLAYER_START_X + SHADOWGROUND_OFFSET_X,
y: SHADOWGROUND_OFFSET_Y,
tint: 0x111111,
coverage: FOREGROUND_COVERAGE,
scale: SHADOWGROUND_SCALE
}));
camera.addChild(new ShiftContainer({
shift: FOREGROUND_SHIFT_FACTOR
})).addChild(new Foreground({
x: PLAYER_START_X + FOREGROUND_OFFSET_X,
tint: 0x808080,
coverage: FOREGROUND_COVERAGE,
scale: FOREGROUND_SCALE
}));
var foregroundContainer = camera.addChild(new ShiftContainer());
var hookContainer = camera.addChild(new ShiftContainer());
var lilypadContainer = camera.addChild(new ShiftContainer());
var pickupContainer = camera.addChild(new ShiftContainer());
var forefrontContainer = camera.addChild(new ShiftContainer());
var grassContainer1 = camera.addChild(new ShiftContainer({
shift: GRASS_SHIFT_FACTOR_1
}));
var grassContainer2 = camera.addChild(new ShiftContainer({
shift: GRASS_SHIFT_FACTOR_2
}));
// Camera instances
var defaultPad = lilypadContainer.addChild(new Lilypad({
x: PLAYER_START_X,
y: PLAYER_START_Y,
active: false,
inert: true
}));
var frog = forefrontContainer.addChild(new Frog({
rotation: MATH_HALF_PI,
x: PLAYER_START_X,
y: PLAYER_START_Y
}));
var firewall = forefrontContainer.addChild(new Firewall({
x: FIREWALL_START_X,
columns: 10
}));
var targetHook = hookContainer.addChild(new Hook({
x: defaultPad.x + 400,
y: defaultPad.y + 200,
inert: true
}));
var highlight = targetHook.addChild(new Highlight());
// Decor lilypads
lilypadContainer.addChild(new Lilypad({
x: PLAYER_START_X - 50,
y: -500,
inert: true
}));
lilypadContainer.addChild(new Lilypad({
x: PLAYER_START_X + 100,
y: -300,
inert: true
}));
// Spawners
forefrontContainer.addChild(new Spawner({
x: PLAYER_START_X + 100,
spawnFunction: spawnLilypad,
positionFunction: positionLilypad,
margin: LILYPAD_SPAWN_MARGIN
}));
forefrontContainer.addChild(new Spawner({
x: targetHook.x,
spawnFunction: spawnHook,
positionFunction: positionHook,
margin: HOOK_SPAWN_MARGIN
}));
grassContainer1.addChild(new Spawner({
x: firewall.x,
spawnFunction: spawnGrass,
positionFunction: positionGrass,
margin: GRASS_SPAWN_MARGIN
}));
grassContainer2.addChild(new Spawner({
x: firewall.x,
spawnFunction: spawnGrass,
positionFunction: positionGrass,
margin: GRASS_SPAWN_MARGIN
}));
;
//==============================================================================
// Spawner functions
//==============================================================================
;
function spawnHook(self, x) {
if (Math.random() < HOOK_DOUBLE_CHANCE) {
hookContainer.addChild(new Hook({
x: x,
y: HOOK_SPAWN_Y_MIN + HOOK_SPAWN_Y_VAR * HOOK_DOUBLE_SPREAD * Math.random()
}));
hookContainer.addChild(new Hook({
x: x,
y: HOOK_SPAWN_Y_MIN + HOOK_SPAWN_Y_VAR - HOOK_SPAWN_Y_VAR * HOOK_DOUBLE_SPREAD * Math.random()
}));
} else {
hookContainer.addChild(new Hook({
x: x,
y: HOOK_SPAWN_Y_MIN + HOOK_SPAWN_Y_VAR * Math.random()
}));
}
}
function positionHook(self) {
return HOOK_SPAWN_X_MIN + HOOK_SPAWN_X_VAR * Math.random();
}
function spawnLilypad(self, x) {
lilypadContainer.addChild(new Lilypad({
x: x,
y: LILYPAD_SPAWN_Y_MIN + LILYPAD_SPAWN_Y_VAR * Math.random()
}));
}
function positionLilypad(self) {
return LILYPAD_SPAWN_X_MIN + LILYPAD_SPAWN_X_VAR * Math.random();
}
function spawnGrass(self, x) {
var assetId = Math.floor(Math.random() * GRASS_ASSETS.length);
var scale = 1 + GRASS_SCALE_VAR * (1 - 2 * Math.random());
self.parent.addChild(new Grass({
asset: GRASS_ASSETS[assetId],
scale: scale,
x: x,
y: GRASS_SPAWN_Y
}));
}
function positionGrass(self) {
return GRASS_SPAWN_X_MIN + GRASS_SPAWN_X_VAR * Math.random();
}
;
//==============================================================================
// Global helper functions
//==============================================================================
;
/**
* Quick-check to see if objects are in the same vacinity; compares x-values
* against the GAME_VACINITY_DIST.
**/
function checkVacinity(obj1, obj2) {
var dx = Math.abs(obj1.x - obj2.x);
return dx < GAME_VACINITY_DIST;
}
;
//==============================================================================
// Global events
//==============================================================================
;
game.up = frog.release;
game.down = function () {
frog.attach(targetHook);
if (paused) {
paused = false;
defaultPad.launch();
}
};
game.update = function () {
if (gameOver) {
frog.release();
gameInterface.finalize();
LK.showGameOver();
}
;
// Dynamically loop the fire crackling effect based on distance
if (LK.ticks % (GAME_TICKS * 1) === 0) {
var distance = frog.x - firewall.x;
var volume = Math.pow(1 + distance / FIREWALL_SOUND_DIVDIST, -1);
var index = Math.floor(volume * 5);
if (index) {
LK.getSound('fireCrackling' + index).play();
}
}
// Find the targetHook
var closestHook = undefined;
var maxDistanceSq = PLAYER_TONGUE_RANGE_MAX * PLAYER_TONGUE_RANGE_MAX;
// Forward checking
for (var i = 0; i < hookContainer.children.length; i++) {
var hook = hookContainer.children[i];
if (hook !== frog.hookedObj && hook.enabled) {
var dx = hook.x - frog.x;
if (dx >= HOOK_SEARCH_OFFSET) {
var dy = hook.y - frog.y;
var distanceSq = dx * dx + dy * dy;
if (distanceSq < maxDistanceSq) {
maxDistanceSq = distanceSq;
closestHook = hook;
}
}
}
}
// Backwards checcking
if (!closestHook) {
for (var i = 0; i < hookContainer.children.length; i++) {
var hook = hookContainer.children[i];
if (hook !== frog.hookedObj && hook.enabled) {
var dx = hook.x - frog.x;
if (dx < HOOK_SEARCH_OFFSET && dx > PLAYER_START_X - hook.width) {
var dy = hook.y - frog.y;
var distanceSq = dx * dx + dy * dy;
if (distanceSq < maxDistanceSq) {
maxDistanceSq = distanceSq;
closestHook = hook;
}
}
}
}
}
targetHook = closestHook;
if (targetHook) {
targetHook.addChild(highlight);
highlight.visible = true;
} else {
game.addChild(highlight);
highlight.visible = false;
}
// Loop the background music
if (LK.ticks % (GAME_TICKS * 10) === 0) {
LK.getSound('backgroundAmbient').play();
}
// Game over conditions
if (frog.y > 0 || frog.x < firewall.x) {
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('frogDeath').play();
gameOver = true;
}
};
fireCrackle
Sound effect
frogTongue
Sound effect
frogDeath
Sound effect
lilypadBounce
Sound effect
noTarget
Sound effect
backgroundAmbient
Sound effect
fireCrackling1
Sound effect
fireCrackling2
Sound effect
fireCrackling3
Sound effect
fireCrackling4
Sound effect
frogBounce
Sound effect
pickupCaught
Sound effect