/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boat = Container.expand(function () {
var self = Container.call(this);
var boatGraphics = self.attachAsset('boat', {
anchorX: 0.5,
anchorY: 0.5
});
self.floatSpeed = 1;
self.update = function () {
self.x += self.floatSpeed;
if (self.x > 2048 + 40) {
self.x = -40;
}
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.driftSpeed = 0.5;
self.update = function () {
self.x += self.driftSpeed;
if (self.x > 2048 + 60) {
self.x = -60;
}
};
return self;
});
var TrackPiece = Container.expand(function () {
var self = Container.call(this);
var trackGraphics = self.attachAsset('track', {
anchorX: 0.5,
anchorY: 0.5
});
self.isPlaced = false;
return self;
});
var Train = Container.expand(function () {
var self = Container.call(this);
var trainGraphics = self.attachAsset('train', {
anchorX: 0.5,
anchorY: 0.5
});
self.isMoving = false;
self.speed = 3;
self.targetX = 0;
self.targetY = 0;
self.currentTrackIndex = 0;
self.down = function (x, y, obj) {
if (!self.isMoving && trackPieces.length > 0) {
self.isMoving = true;
self.currentTrackIndex = 0;
self.moveToNextTrack();
}
};
self.moveToNextTrack = function () {
if (self.currentTrackIndex < trackPieces.length) {
var track = trackPieces[self.currentTrackIndex];
self.targetX = track.x;
self.targetY = track.y;
} else {
// Reached the end
self.isMoving = false;
if (self.targetX >= station.x - 50 && self.targetX <= station.x + 50) {
// Reached station
LK.effects.flashObject(station, 0x00FF00, 1000);
LK.setScore(LK.getScore() + 10);
scoreText.setText('Score: ' + LK.getScore());
}
}
};
self.update = function () {
if (self.isMoving && trackPieces.length > 0) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.currentTrackIndex++;
self.moveToNextTrack();
}
}
};
return self;
});
var Whistle = Container.expand(function () {
var self = Container.call(this);
var whistleGraphics = self.attachAsset('whistle', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
LK.getSound('choo').play();
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200
});
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var trackPieces = [];
var clouds = [];
var boats = [];
var isBuilding = true;
var tutorialStep = 0;
// Create scenery
var river = game.addChild(LK.getAsset('river', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 1800
}));
var tunnel = game.addChild(LK.getAsset('tunnel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200
}));
var station = game.addChild(LK.getAsset('station', {
anchorX: 0.5,
anchorY: 0.5,
x: 1700,
y: 2400
}));
// Create clouds
for (var i = 0; i < 5; i++) {
var cloud = game.addChild(new Cloud());
cloud.x = Math.random() * 2048;
cloud.y = 200 + Math.random() * 300;
cloud.driftSpeed = 0.2 + Math.random() * 0.8;
clouds.push(cloud);
}
// Create boats
for (var j = 0; j < 3; j++) {
var boat = game.addChild(new Boat());
boat.x = Math.random() * 2048;
boat.y = 1850;
boat.floatSpeed = 0.5 + Math.random() * 1;
boats.push(boat);
}
// Create train
var train = game.addChild(new Train());
train.x = 200;
train.y = 2200;
// Create whistle button
var whistle = game.addChild(new Whistle());
whistle.x = 150;
whistle.y = 150;
// Create UI
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var instructionText = new Text2('Tap to place tracks!', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 80;
LK.gui.top.addChild(instructionText);
var modeText = new Text2('Building Mode', {
size: 40,
fill: 0xFFFF00
});
modeText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(modeText);
// Game event handlers
game.down = function (x, y, obj) {
if (isBuilding) {
// Place track piece
var newTrack = game.addChild(new TrackPiece());
newTrack.x = x;
newTrack.y = y;
newTrack.isPlaced = true;
trackPieces.push(newTrack);
LK.getSound('place').play();
// Update instruction based on progress
if (trackPieces.length === 1) {
instructionText.setText('Great! Keep building your track!');
} else if (trackPieces.length === 5) {
instructionText.setText('Tap the train to start its journey!');
} else if (trackPieces.length === 10) {
instructionText.setText('Build toward the blue station!');
}
// Check if player has built enough track
if (trackPieces.length >= 3) {
modeText.setText('Tap train to start journey!');
}
}
};
// Main game loop
game.update = function () {
// Update train movement
if (train.isMoving) {
// Check if train reached station
var distanceToStation = Math.sqrt(Math.pow(train.x - station.x, 2) + Math.pow(train.y - station.y, 2));
if (distanceToStation < 100) {
train.isMoving = false;
LK.effects.flashScreen(0x00FF00, 500);
LK.setScore(LK.getScore() + 50);
scoreText.setText('Score: ' + LK.getScore());
instructionText.setText('Train reached station! Tap to build new track!');
// Reset for new round
LK.setTimeout(function () {
// Clear old tracks
for (var i = trackPieces.length - 1; i >= 0; i--) {
trackPieces[i].destroy();
}
trackPieces = [];
// Reset train position
train.x = 200;
train.y = 2200;
train.isMoving = false;
train.currentTrackIndex = 0;
instructionText.setText('Build a new track!');
modeText.setText('Building Mode');
isBuilding = true;
}, 2000);
}
}
// Animate whistle button
whistle.y = 150 + Math.sin(LK.ticks * 0.1) * 5;
// Update score display
if (LK.ticks % 60 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText('Score: ' + LK.getScore());
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boat = Container.expand(function () {
var self = Container.call(this);
var boatGraphics = self.attachAsset('boat', {
anchorX: 0.5,
anchorY: 0.5
});
self.floatSpeed = 1;
self.update = function () {
self.x += self.floatSpeed;
if (self.x > 2048 + 40) {
self.x = -40;
}
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.driftSpeed = 0.5;
self.update = function () {
self.x += self.driftSpeed;
if (self.x > 2048 + 60) {
self.x = -60;
}
};
return self;
});
var TrackPiece = Container.expand(function () {
var self = Container.call(this);
var trackGraphics = self.attachAsset('track', {
anchorX: 0.5,
anchorY: 0.5
});
self.isPlaced = false;
return self;
});
var Train = Container.expand(function () {
var self = Container.call(this);
var trainGraphics = self.attachAsset('train', {
anchorX: 0.5,
anchorY: 0.5
});
self.isMoving = false;
self.speed = 3;
self.targetX = 0;
self.targetY = 0;
self.currentTrackIndex = 0;
self.down = function (x, y, obj) {
if (!self.isMoving && trackPieces.length > 0) {
self.isMoving = true;
self.currentTrackIndex = 0;
self.moveToNextTrack();
}
};
self.moveToNextTrack = function () {
if (self.currentTrackIndex < trackPieces.length) {
var track = trackPieces[self.currentTrackIndex];
self.targetX = track.x;
self.targetY = track.y;
} else {
// Reached the end
self.isMoving = false;
if (self.targetX >= station.x - 50 && self.targetX <= station.x + 50) {
// Reached station
LK.effects.flashObject(station, 0x00FF00, 1000);
LK.setScore(LK.getScore() + 10);
scoreText.setText('Score: ' + LK.getScore());
}
}
};
self.update = function () {
if (self.isMoving && trackPieces.length > 0) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.currentTrackIndex++;
self.moveToNextTrack();
}
}
};
return self;
});
var Whistle = Container.expand(function () {
var self = Container.call(this);
var whistleGraphics = self.attachAsset('whistle', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
LK.getSound('choo').play();
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200
});
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var trackPieces = [];
var clouds = [];
var boats = [];
var isBuilding = true;
var tutorialStep = 0;
// Create scenery
var river = game.addChild(LK.getAsset('river', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 1800
}));
var tunnel = game.addChild(LK.getAsset('tunnel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200
}));
var station = game.addChild(LK.getAsset('station', {
anchorX: 0.5,
anchorY: 0.5,
x: 1700,
y: 2400
}));
// Create clouds
for (var i = 0; i < 5; i++) {
var cloud = game.addChild(new Cloud());
cloud.x = Math.random() * 2048;
cloud.y = 200 + Math.random() * 300;
cloud.driftSpeed = 0.2 + Math.random() * 0.8;
clouds.push(cloud);
}
// Create boats
for (var j = 0; j < 3; j++) {
var boat = game.addChild(new Boat());
boat.x = Math.random() * 2048;
boat.y = 1850;
boat.floatSpeed = 0.5 + Math.random() * 1;
boats.push(boat);
}
// Create train
var train = game.addChild(new Train());
train.x = 200;
train.y = 2200;
// Create whistle button
var whistle = game.addChild(new Whistle());
whistle.x = 150;
whistle.y = 150;
// Create UI
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var instructionText = new Text2('Tap to place tracks!', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 80;
LK.gui.top.addChild(instructionText);
var modeText = new Text2('Building Mode', {
size: 40,
fill: 0xFFFF00
});
modeText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(modeText);
// Game event handlers
game.down = function (x, y, obj) {
if (isBuilding) {
// Place track piece
var newTrack = game.addChild(new TrackPiece());
newTrack.x = x;
newTrack.y = y;
newTrack.isPlaced = true;
trackPieces.push(newTrack);
LK.getSound('place').play();
// Update instruction based on progress
if (trackPieces.length === 1) {
instructionText.setText('Great! Keep building your track!');
} else if (trackPieces.length === 5) {
instructionText.setText('Tap the train to start its journey!');
} else if (trackPieces.length === 10) {
instructionText.setText('Build toward the blue station!');
}
// Check if player has built enough track
if (trackPieces.length >= 3) {
modeText.setText('Tap train to start journey!');
}
}
};
// Main game loop
game.update = function () {
// Update train movement
if (train.isMoving) {
// Check if train reached station
var distanceToStation = Math.sqrt(Math.pow(train.x - station.x, 2) + Math.pow(train.y - station.y, 2));
if (distanceToStation < 100) {
train.isMoving = false;
LK.effects.flashScreen(0x00FF00, 500);
LK.setScore(LK.getScore() + 50);
scoreText.setText('Score: ' + LK.getScore());
instructionText.setText('Train reached station! Tap to build new track!');
// Reset for new round
LK.setTimeout(function () {
// Clear old tracks
for (var i = trackPieces.length - 1; i >= 0; i--) {
trackPieces[i].destroy();
}
trackPieces = [];
// Reset train position
train.x = 200;
train.y = 2200;
train.isMoving = false;
train.currentTrackIndex = 0;
instructionText.setText('Build a new track!');
modeText.setText('Building Mode');
isBuilding = true;
}, 2000);
}
}
// Animate whistle button
whistle.y = 150 + Math.sin(LK.ticks * 0.1) * 5;
// Update score display
if (LK.ticks % 60 === 0) {
LK.setScore(LK.getScore() + 1);
scoreText.setText('Score: ' + LK.getScore());
}
};