Code edit (20 edits merged)
Please save this source code
User prompt
use Detritus class in road generateBackground, for that create a clone of attachAssetRadial that take an object insteade of an asset name but does the same thing
User prompt
use Detritus class in road generateBackground
User prompt
add a class for detritus
User prompt
Clone current system used to spanw Trees to spawn detritus
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
log variables before the line if (!jumpAction && jumpStep >= PLAYER_JUMP_STEP_MIN || jumpStep >= PLAYER_JUMP_STEP_MAX)
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (5 edits merged)
Please save this source code
User prompt
add an asset for the background
Code edit (14 edits merged)
Please save this source code
User prompt
in Sun class, animate the alpha of each circle alternatively
User prompt
Please fix the bug: 'Uncaught ReferenceError: rotation0 is not defined' in or related to this line: 'parent.attachAsset(asset, {' Line Number: 119
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
add a starfield in the background
Code edit (1 edits merged)
Please save this source code
Remix started
Copy The Road Runner
/****
* 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 Sun = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
for (var i = 0; i < 10; i++) {
self.attachAsset('circle', {
width: 500 + 200 * i,
height: 500 + 200 * i,
color: 0xFFFF00,
alpha: 0.1,
anchorX: 0.5,
anchorY: 0.5
});
}
var sunAsset = self.attachAsset('sun', {
anchorX: 0.5075,
anchorY: 0.5,
alpha: 0.75
});
;
self.update = update;
;
function update() {
if (LK.ticks % 30 == 0) {
sunAsset.scale.x *= -1;
}
}
});
var RoadSegment = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var background = self.addChild(new Container());
self.attachAsset('roadSegment', {
anchorX: 1,
anchorY: 1
});
self.attachAsset('roadSegment', {
anchorX: 1,
anchorY: 1,
scaleX: 0.95,
scaleY: 0.95,
tint: 0x555555
});
if (config.index % 3 === 0) {
attachAssetRadial(self, 'square', {
offset: 200,
width: 100,
height: 10,
anchorR: 0.5,
anchorX: 0.5,
anchorY: 0.5
});
}
;
self.update = update;
self.regenerate = regenerate;
self.fadeout = false;
self.distance = config.distance;
self.step = config.step;
self.stepChance = config.stepChance;
self.previous = config.previous;
;
function attachAssetRadial(parent, asset, obj) {
var offsetTotal = ROAD_SEGMENT_HEIGHT - (obj.offset || 10);
var rotation = -(1 - obj.anchorR) * ROAD_SEGMENT_ANGLE;
parent.attachAsset(asset, {
x: Math.sin(rotation) * offsetTotal,
y: Math.cos(rotation) * -offsetTotal,
width: obj.width,
height: obj.height,
anchorX: obj.anchorX,
anchorY: obj.anchorY,
scaleX: obj.scaleX || 1,
scaleY: obj.scaleY || 1,
rotation: (obj.rotation || 0) + rotation
});
}
function generateBackground() {
console.log(self.distance);
background.removeChildren();
var plantCount = Math.floor(Math.random() * (ROAD_GEN_PLANT_MAX + 1));
if (self.distance === SCORE_TOTAL_DISTANCE) {
attachAssetRadial(background, 'flag', {
anchorR: 0.5,
anchorX: 0.1,
anchorY: 1
});
} else {
if (Math.random() < ROAD_GEN_TREE_CHANCE) {
var treeIndex = Math.floor(Math.random() * ROAD_GEN_TREE_ASSETS);
var scale = 0.9 + 0.2 * Math.random();
attachAssetRadial(background, 'tree' + treeIndex, {
anchorR: 0.4 + 0.2 * Math.random(),
anchorX: 0.5,
anchorY: 1,
scaleX: scale,
scaleY: scale
});
}
for (var i = 0; i < plantCount; i++) {
var plantIndex = Math.floor(Math.random() * ROAD_GEN_PLANT_ASSETS);
var scale = 0.9 + 0.2 * Math.random();
attachAssetRadial(background, 'plant' + plantIndex, {
anchorR: 0.1 + 0.8 * Math.random(),
anchorX: 0.5,
anchorY: 1,
scaleX: Math.random() < 0.5 ? -scale : scale,
scaleY: scale
});
}
}
if (Math.random() < ROAD_GEN_CLOUD_CHANCE) {
var cloudIndex = Math.floor(Math.random() * ROAD_GEN_CLOUD_ASSETS);
var scale = 1.0 + 1.5 * Math.random();
attachAssetRadial(background, 'cloud' + cloudIndex, {
offset: -800,
anchorR: -1.0 + 2.0 * Math.random(),
anchorX: 0.5,
anchorY: 0.5,
scaleX: scale,
scaleY: scale
});
}
}
function regenerate(incrementDistance) {
if (incrementDistance) {
self.distance += SCORE_SEGMENT_DISTANCE * ROAD_SEGMENT_COUNT;
}
var stepping = self.distance <= SCORE_TOTAL_DISTANCE;
var stepChance = self.previous.stepChance;
var stepUp = stepping && (self.previous.step < ROAD_STEP_COUNT ? Math.random() < self.stepChance : false);
var stepDown = stepping && (self.previous.step > 0 ? Math.random() < self.stepChance : false);
if (stepUp || stepDown) {
if (stepUp && stepDown) {
if (Math.random() < 0.5) {
stepDown = false;
} else {
stepUp = false;
}
}
self.step = self.previous.step + (stepUp ? 1 : -1);
self.stepChance = ROAD_STEP_CHANCE_BASE;
} else {
self.step = self.previous.step;
self.stepChance = self.previous.stepChance + ROAD_STEP_CHANCE_INCREMENT;
}
generateBackground();
self.fadeout = false;
rescale();
}
function update() {
if (self.fadeout && self.alpha > 0) {
if ((self.alpha -= ROAD_SEGMENT_FADEOUT) < 0) {
self.alpha = 0;
}
} else if (!self.fadeout && self.alpha < 1) {
if ((self.alpha += ROAD_SEGMENT_FADEOUT) > 1) {
self.alpha = 1;
}
}
}
function rescale() {
var newScale = (ROAD_STEP_HEIGHT_BASE + self.step * ROAD_STEP_HEIGHT_INCREMENT) / ROAD_SEGMENT_HEIGHT; // TEMP
self.scale.set(newScale);
}
;
rescale();
});
var Road = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var segments = [];
for (var i = 0; i < ROAD_SEGMENT_COUNT; i++) {
var segment = segments[i] = self.addChild(new RoadSegment({
index: i,
previous: i > 0 ? segments[i - 1] : undefined,
rotation: i * ROAD_SEGMENT_ANGLE,
distance: (i - 1) * SCORE_SEGMENT_DISTANCE,
stepChance: ROAD_STEP_CHANCE_BASE,
step: ROAD_STEP_DEFAULT
}));
if (i === ROAD_SEGMENT_COUNT - 1) {
segments[0].previous = segment;
}
if (i >= ROAD_FREE_RUN_COUNT) {
segment.regenerate();
}
self.attachAsset('roadSegment', {
anchorX: 1,
anchorY: 1,
scaleX: 0.27,
scaleY: 0.27,
rotation: i * ROAD_SEGMENT_ANGLE
});
}
self.attachAsset('circle', {
width: 500,
height: 500,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x222222
});
self.attachAsset('circle', {
width: 490,
height: 490,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x87CEEB
});
var destroyIndex = -1;
var regenerateIndex = -1;
;
self.rotate = rotate;
self.getIndex = getIndex;
self.getNode = getNode;
self.getNodeDist = getNodeDist;
;
function rotate(speed) {
self.rotation -= speed;
var newDestroyIndex = getIndex(ROAD_SEGMENT_DESTROY);
var newRegenerateIndex = getIndex(20); // TEMP
if (newDestroyIndex >= 0 && newDestroyIndex !== destroyIndex && !segments[newDestroyIndex].fadeout) {
destroyIndex = newDestroyIndex;
segments[destroyIndex].fadeout = true;
}
if (newRegenerateIndex >= 0 && newRegenerateIndex !== regenerateIndex && segments[newRegenerateIndex].fadeout) {
regenerateIndex = newRegenerateIndex;
segments[regenerateIndex].regenerate(true);
}
}
function getIndex(shift) {
return Math.floor(-self.rotation / MATH_2_PI * ROAD_SEGMENT_COUNT + (shift || 0) + 1) % ROAD_SEGMENT_COUNT;
}
function getNode(shift) {
return segments[getIndex(shift)];
}
function getNodeDist() {
return ROAD_SEGMENT_ANGLE - -self.rotation % ROAD_SEGMENT_ANGLE;
}
});
var PlayerBody = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
// Animation settings
var animation = animationStand;
var alpha = 0;
var blendAnimation = undefined;
var blendDecrement = 0;
var blendAlpha = 0;
var afterTint = 0xAAAAAA;
// Body settings
var bodyOffsetY = config.y || 0;
var pelvisOffsetX = -10;
var armUpperAngle = -3 * MATH_EIGHTH_PI;
var armUpperOffsetX = 15;
var armUpperOffsetY = 30;
var armLowerAngle = -MATH_QUARTER_PI;
var armLowerOffsetY = 90;
var legUpperAngle = 3 * MATH_EIGHTH_PI;
var legUpperOffsetX = 10;
var legLowerOffsetY = 135;
var footOffsetY = 100;
// Create and attach body parts
var armUpperRight = self.addChild(new ConfigContainer({
y: armUpperOffsetY
}));
var legUpperRight = self.addChild(new ConfigContainer({
x: pelvisOffsetX + legUpperOffsetX
}));
var torso = self.attachAsset('torso', {
anchorX: 0.5
});
var head = self.attachAsset('head', {
anchorX: 0.15,
anchorY: 0.95
});
var pelvis = self.attachAsset('pelvis', {
x: pelvisOffsetX,
y: torso.height,
anchorX: 0.5,
anchorY: 0.2,
tint: afterTint
});
var legUpperLeft = self.addChild(new ConfigContainer({
x: pelvisOffsetX - legUpperOffsetX
}));
var armUpperLeft = self.addChild(new ConfigContainer({
y: armUpperOffsetY
}));
// Arm extensions
armUpperRight.attachAsset('upperArm', {
rotation: armUpperAngle,
anchorX: 0.85,
anchorY: 0.25,
tint: afterTint
});
armUpperLeft.attachAsset('upperArm', {
rotation: armUpperAngle,
anchorX: 0.85,
anchorY: 0.25
});
var armLowerRight = armUpperRight.attachAsset('lowerArm', {
y: armLowerOffsetY,
rotation: armLowerAngle,
anchorX: 0.95,
anchorY: 0.05,
tint: afterTint
});
var armLowerLeft = armUpperLeft.attachAsset('lowerArm', {
y: armLowerOffsetY,
rotation: armLowerAngle,
anchorX: 0.95,
anchorY: 0.05
});
// Leg extensions
legUpperRight.attachAsset('upperLeg', {
rotation: legUpperAngle,
anchorY: 0.1,
tint: afterTint
});
legUpperLeft.attachAsset('upperLeg', {
rotation: legUpperAngle,
anchorY: 0.1
});
var legLowerRight = legUpperRight.attachAsset('lowerLeg', {
y: legLowerOffsetY,
anchorX: 0.65,
tint: afterTint
});
var legLowerLeft = legUpperLeft.attachAsset('lowerLeg', {
y: legLowerOffsetY,
anchorX: 0.65
});
var footRight = legLowerRight.attachAsset('foot', {
y: footOffsetY,
anchorX: 0.2,
anchorY: 0.05,
tint: afterTint
});
var footLeft = legLowerLeft.attachAsset('foot', {
y: footOffsetY,
anchorX: 0.2,
anchorY: 0.05
});
// Additional positioning
armUpperLeft.x = -torso.width / 2 + armUpperOffsetX;
armUpperRight.x = torso.width / 2 - armUpperOffsetX;
legUpperLeft.y = torso.height + pelvis.height / 3;
legUpperRight.y = torso.height + pelvis.height / 3;
;
self.animate = animate;
self.pushAnimation = pushAnimation;
;
function animate(increment) {
alpha = (alpha + increment) % 1;
if (blendAlpha > 0) {
if ((blendAlpha -= blendDecrement) <= 0) {
blendAlpha = 0;
blendAnimation = undefined;
}
}
var pose = animation(alpha);
var blendPose = blendAnimation && blendAnimation(alpha);
self.y = animateProperty(pose, blendPose, blendAlpha, 'BODY_OFFSET', bodyOffsetY);
head.rotation = animateProperty(pose, blendPose, blendAlpha, 'HEAD_ROTATION');
armUpperRight.rotation = animateProperty(pose, blendPose, blendAlpha, 'ARM_UPPER_RIGHT_ROTATION');
armUpperLeft.rotation = animateProperty(pose, blendPose, blendAlpha, 'ARM_UPPER_LEFT_ROTATION');
armLowerRight.rotation = animateProperty(pose, blendPose, blendAlpha, 'ARM_LOWER_RIGHT_ROTATION', armLowerAngle);
armLowerLeft.rotation = animateProperty(pose, blendPose, blendAlpha, 'ARM_LOWER_LEFT_ROTATION', armLowerAngle);
legUpperRight.rotation = animateProperty(pose, blendPose, blendAlpha, 'LEG_UPPER_RIGHT_ROTATION');
legUpperLeft.rotation = animateProperty(pose, blendPose, blendAlpha, 'LEG_UPPER_LEFT_ROTATION');
legLowerRight.rotation = animateProperty(pose, blendPose, blendAlpha, 'LEG_LOWER_RIGHT_ROTATION');
legLowerLeft.rotation = animateProperty(pose, blendPose, blendAlpha, 'LEG_LOWER_LEFT_ROTATION');
footRight.rotation = animateProperty(pose, blendPose, blendAlpha, 'FOOT_RIGHT_ROTATION');
footLeft.rotation = animateProperty(pose, blendPose, blendAlpha, 'FOOT_LEFT_ROTATION');
}
function pushAnimation(newAnimation, newBlendDecrement) {
blendDecrement = newBlendDecrement;
if (newAnimation !== animation) {
blendAnimation = animation;
animation = newAnimation;
blendAlpha = 1;
}
}
;
animate(0);
});
var Player = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var speedFactor = PLAYER_SPEED_FACTOR_BASE;
var stopped = false;
var falling = false;
var jumping = false; // If the player is currently jumping (and immune to gravity)
var jumpAction = false; // Tracks tap releases
var jumpStep = 0; // Tracks min/max jump heights
var aerialSpeed = 0; // Actual vertical/air speed
var baseY = config.y;
var step = ROAD_STEP_DEFAULT;
var nodeDistance = 0;
var nodeTicks = 0;
var nodeMulti = 0;
var body = self.addChild(new PlayerBody({
y: -370
}));
;
self.update = update;
self.jumpStart = jumpStart;
self.jumpEnd = jumpEnd;
self.jumping = false;
;
function update() {
var nextNode = road.getNode(1);
var currentNode = nextNode.previous;
// Update horizontal movement
var outputSpeed = PLAYER_SPEED_BASE * speedFactor;
var distance = road.getNodeDist();
// Check for collision
if (stopped && nextNode.step <= step) {
stopped = false;
} else if (nextNode.step > step && outputSpeed > distance) {
road.rotate(distance - PLAYER_SPACING);
speedFactor = PLAYER_SPEED_FACTOR_BASE;
stopped = true;
if (currentNode.step <= step) {
body.pushAnimation(animationStand, PLAYER_POSE_TRANSITION);
}
}
if (!stopped) {
road.rotate(outputSpeed);
if (!gameOver) {
if (speedFactor < PLAYER_SPEED_FACTOR_MAX) {
if ((speedFactor += PLAYER_SPEED_FACTOR_INCREMENT) >= PLAYER_SPEED_FACTOR_MAX) {
speedFactor = PLAYER_SPEED_FACTOR_MAX;
}
}
} else {
if (speedFactor > 0) {
if ((speedFactor -= PLAYER_SPEED_DECREMENT) <= 0) {
speedFactor = 0;
}
}
}
}
// TOOD: Get new node if applicable
// Update vertical movement
if (jumping) {
jumpStep += aerialSpeed;
if (!jumpAction && jumpStep >= PLAYER_JUMP_STEP_MIN || jumpStep >= PLAYER_JUMP_STEP_MAX) {
falling = true;
jumping = false;
jumpAction = false;
jumpStep = 0;
}
} else if (falling) {
aerialSpeed -= PLAYER_GRAVITY;
} else if (step > currentNode.step) {
falling = true;
body.pushAnimation(animationJump, PLAYER_POSE_TRANSITION);
}
step += aerialSpeed;
if (falling && step <= currentNode.step) {
step = currentNode.step;
falling = false;
aerialSpeed = 0;
body.pushAnimation(stopped ? animationStand : animationRun, PLAYER_POSE_TRANSITION);
}
// Score calculations
if (!gameOver && currentNode.distance > nodeDistance) {
adjustScore(nodeMulti / nodeTicks);
currentNode.distance = nodeDistance;
nodeMulti = 0;
nodeTicks = 0;
}
nodeMulti += stopped ? SCORE_STOPPED_FACTOR : speedFactor;
nodeTicks++;
// Adjustments
var stepHeight = ROAD_STEP_HEIGHT_BASE + step * ROAD_STEP_HEIGHT_INCREMENT; // TODO: Better scaling
self.y = baseY - stepHeight; // TODO: Better scaling
self.scale.set(PLAYER_SCALE_BASE * stepHeight / ROAD_SEGMENT_HEIGHT); // TODO: Better scaling
body.animate(PLAYER_ANIMATION_SPEED_BASE * speedFactor);
multiplierText.setText((stopped ? SCORE_STOPPED_FACTOR : speedFactor).toFixed(1) + 'x');
}
function jumpStart() {
if (!gameOver && !jumping && !falling) {
jumping = true;
jumpAction = true;
aerialSpeed = PLAYER_JUMP_STEP_INCREMENT;
body.pushAnimation(animationJump, PLAYER_POSE_TRANSITION);
}
}
function jumpEnd() {
jumpAction = false;
}
function adjustScore(averageMulti) {
var points = Math.floor(averageMulti * SCORE_SEGMENT_POINTS);
score = Math.max(0, score + points);
scoreText.setText(String(score).padStart(6, '0'));
distanceText.setText((distanceRemaining -= SCORE_SEGMENT_DISTANCE) + 'm');
incrementText.setText((points === SCORE_MAX_POINTS ? '[MAX!] +' : '+') + points);
if (distanceRemaining <= 0) {
body.pushAnimation(animationStand, PLAYER_SPEED_DECREMENT / speedFactor);
callGameOver();
}
}
;
body.pushAnimation(animationRun, PLAYER_POSE_TRANSITION);
});
/**
* 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;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue color
});
/****
* Game Code
****/
;
//==============================================================================
// Global Constants & Settings
//==============================================================================
;
// 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_THIRD_PI = Math.PI / 3;
var MATH_QUARTER_PI = Math.PI / 4;
var MATH_FIFTH_PI = Math.PI / 5;
var MATH_SIXTH_PI = Math.PI / 5;
var MATH_EIGHTH_PI = Math.PI / 8;
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 = 4; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText
var TEXT_DEFAULT_BORDER = '#000000'; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText
var TEXT_DEFAULT_FILL = '#FFFFFF'; // Required by: BorderedText, SymbolText
var TEXT_DEFAULT_FONT = 'Courier'; // Required by: BorderedText, SymbolText
var TEXT_DEFAULT_SIZE = 80; // Required by: BorderedText, SymbolText
;
// Game Constants
var GAME_TICKS = 60;
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
;
// Road Constants
var ROAD_SEGMENT_DISTANCE = 1.0;
var ROAD_SEGMENT_POINTS = 100;
var ROAD_SEGMENT_COUNT = 30;
var ROAD_SEGMENT_ANGLE = MATH_2_PI / ROAD_SEGMENT_COUNT;
var ROAD_SEGMENT_HEIGHT = 1000;
var ROAD_SEGMENT_DESTROY = -2;
var ROAD_SEGMENT_FADEOUT = 0.015;
var ROAD_FREE_RUN_COUNT = 5;
var ROAD_STEP_COUNT = 5;
var ROAD_STEP_DEFAULT = 2;
var ROAD_STEP_HEIGHT_BASE = 400;
var ROAD_STEP_HEIGHT_INCREMENT = 80;
var ROAD_STEP_CHANCE_BASE = 0.1;
var ROAD_STEP_CHANCE_INCREMENT = 0.05;
var ROAD_GEN_PLANT_ASSETS = 3;
var ROAD_GEN_PLANT_MAX = 3;
var ROAD_GEN_TREE_ASSETS = 4;
var ROAD_GEN_TREE_CHANCE = 0.1;
var ROAD_GEN_CLOUD_ASSETS = 4;
var ROAD_GEN_CLOUD_CHANCE = 0.2;
;
// Player Constants
var PLAYER_SPACING = ROAD_SEGMENT_ANGLE / 8; // 1/8 of a segment
var PLAYER_POSE_TRANSITION = 0.1;
var PLAYER_GRAVITY = 0.02;
var PLAYER_JUMP_STEP_MIN = 1.0;
var PLAYER_JUMP_STEP_MAX = 2.0;
var PLAYER_JUMP_STEP_INCREMENT = 0.15;
var PLAYER_ANIMATION_SPEED_BASE = 0.02;
var PLAYER_SCALE_BASE = 0.5;
var PLAYER_SPEED_BASE = MATH_2_PI / (GAME_TICKS * 10); // 10s to complete a revolution
var PLAYER_SPEED_FACTOR_BASE = 1.0;
var PLAYER_SPEED_FACTOR_MAX = 1.5;
var PLAYER_SPEED_FACTOR_INCREMENT = 0.001;
var PLAYER_SPEED_DECREMENT = 0.01;
;
// Scoring Constants
var SCORE_TOTAL_DISTANCE = 500;
var SCORE_SEGMENT_DISTANCE = 1;
var SCORE_SEGMENT_POINTS = 100;
var SCORE_STOPPED_FACTOR = -0.2;
var SCORE_MAX_POINTS = SCORE_SEGMENT_POINTS * PLAYER_SPEED_FACTOR_MAX;
//==============================================================================
// Game Instances & Variables
//==============================================================================
;
// Variables
var score = 0;
var winningTime = 0;
var gameOver = false;
var distanceRemaining = SCORE_TOTAL_DISTANCE;
;
// Instances
var sun = game.addChild(new Sun({
x: GAME_WIDTH / 2,
y: 50
}));
var road = game.addChild(new Road({
x: GAME_WIDTH / 2,
y: GAME_HEIGHT - GAME_WIDTH / 2
}));
var player = game.addChild(new Player({
x: road.x,
y: road.y,
scale: 0.5
}));
var distanceText = game.addChild(new BorderedText(distanceRemaining + 'm', {
x: road.x,
y: road.y - TEXT_DEFAULT_SIZE,
anchorX: 0.5,
anchorY: 1
}));
var scoreText = game.addChild(new BorderedText('000000', {
x: road.x,
y: road.y,
size: TEXT_DEFAULT_SIZE * 1.5,
anchorX: 0.5,
anchorY: 0.5
}));
var multiplierText = game.addChild(new BorderedText('1.0x', {
x: road.x,
y: road.y + TEXT_DEFAULT_SIZE,
anchorX: 0.5,
anchorY: 0
}));
var incrementText = game.addChild(new BorderedText('', {
x: road.x - 300,
y: road.y,
anchorX: 1,
anchorY: 0.5
}));
var winningText = game.addChild(new BorderedText('', {
x: GAME_WIDTH / 2,
y: 500,
anchorX: 0.5,
anchorY: 0.5,
size: 2 * TEXT_DEFAULT_SIZE
}));
;
//==============================================================================
// Global events
//==============================================================================
;
game.down = player.jumpStart;
game.up = player.jumpEnd;
;
//==============================================================================
// Global functions
//==============================================================================
;
// Helpers
function callGameOver() {
gameOver = true;
winningTime = LK.ticks;
LK.setScore(score);
winningText.setText('Congratulations!');
// Check if winningTime is set and show game over screen after 60 ticks
game.update = function () {
if (winningTime && LK.ticks >= winningTime + 120) {
LK.showGameOver();
}
};
}
;
// Animations & handlers
function animateProperty(animationPose, blendPose, blendAlpha, key, baseValue) {
var animationPoseValue = (animationPose || {})[key] || 0;
var blendPoseValue = (blendPose || {})[key] || 0;
return (baseValue || 0) + animationPoseValue * (1 - blendAlpha) + blendPoseValue * blendAlpha;
}
function animationRun(alpha) {
// Animation constants
var armUpperAngle = MATH_FIFTH_PI;
var armLowerAngle = -5 * MATH_EIGHTH_PI;
var legLowerAngle = MATH_EIGHTH_PI;
// Sinusoidals
var rightSinusoidal = Math.cos(MATH_2_PI * (alpha + 0.5));
var leftSinusoidal = Math.cos(MATH_2_PI * alpha);
var doubleSinusoidal = Math.cos(MATH_4_PI * alpha);
// Animation calculations
var armUpperRightSwing = -rightSinusoidal * MATH_QUARTER_PI;
var armUpperLeftSwing = -leftSinusoidal * MATH_QUARTER_PI;
var legUpperRightSwing = rightSinusoidal * MATH_THIRD_PI;
var legUpperLeftSwing = leftSinusoidal * MATH_THIRD_PI;
return {
BODY_OFFSET: doubleSinusoidal * 10,
HEAD_ROTATION: (1 + doubleSinusoidal) * Math.PI / 32,
ARM_UPPER_RIGHT_ROTATION: armUpperAngle + armUpperRightSwing,
ARM_UPPER_LEFT_ROTATION: armUpperAngle + armUpperLeftSwing,
ARM_LOWER_RIGHT_ROTATION: armLowerAngle + armUpperRightSwing / 2,
ARM_LOWER_LEFT_ROTATION: armLowerAngle + armUpperLeftSwing / 2,
LEG_UPPER_RIGHT_ROTATION: legUpperRightSwing,
LEG_UPPER_LEFT_ROTATION: legUpperLeftSwing,
LEG_LOWER_RIGHT_ROTATION: legLowerAngle + (alpha > 0.5 ? MATH_THIRD_PI + (1 - Math.abs(rightSinusoidal)) * MATH_SIXTH_PI : Math.abs(-legUpperRightSwing)),
LEG_LOWER_LEFT_ROTATION: legLowerAngle + (alpha <= 0.5 ? MATH_THIRD_PI + (1 - Math.abs(leftSinusoidal)) * MATH_SIXTH_PI : Math.abs(-legUpperLeftSwing)),
FOOT_RIGHT_ROTATION: Math.max(0, legUpperRightSwing * 2 / 3) - legLowerAngle,
FOOT_LEFT_ROTATION: Math.max(0, legUpperLeftSwing * 2 / 3) - legLowerAngle
};
}
function animationJump(alpha) {
var sinusoidal = Math.cos(MATH_2_PI * alpha);
return animationRun(0.35 + sinusoidal * 0.02);
}
function animationStand(alpha) {
var sinusoidal = Math.cos(MATH_2_PI * alpha);
var offsetAngle = Math.PI / 16;
var sharedAngle = (2 + sinusoidal) * Math.PI / 64;
return {
BODY_OFFSET: sinusoidal * 5,
ARM_UPPER_RIGHT_ROTATION: 0.5 * offsetAngle,
ARM_UPPER_LEFT_ROTATION: 3 * offsetAngle,
ARM_LOWER_RIGHT_ROTATION: -4 * offsetAngle,
ARM_LOWER_LEFT_ROTATION: -4 * offsetAngle,
LEG_UPPER_RIGHT_ROTATION: 1.5 * offsetAngle - sharedAngle,
LEG_UPPER_LEFT_ROTATION: -1.5 * offsetAngle - sharedAngle,
LEG_LOWER_RIGHT_ROTATION: 2 * sharedAngle,
LEG_LOWER_LEFT_ROTATION: 2 * sharedAngle,
FOOT_RIGHT_ROTATION: -sharedAngle - 1.5 * offsetAngle,
FOOT_LEFT_ROTATION: -sharedAngle + 1.5 * offsetAngle
};
}
white
circle sliced into many pieces, flat image. 2d, white background, shadowless.
pixel art of a tall, tree. game asset, 2d, white background, shadowless.
pixel art cloud. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
dark space.
flying lava bubble. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
a bonus crystal ball with the recycle symbol. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
top view A green round start button empty in the center like a ring.