User prompt
Arregla todos los errores
User prompt
Arregla todos los errores
User prompt
Haz que se puedan ver los botones de girar y el botón de arrancar
User prompt
Añade un poco más de obstáculos
User prompt
Elimina las paredes en todo el centro de la pantalla
User prompt
Añade un límite de 3 vidas al jugador, que pierda una vida cada vez que choque con un obstáculo
User prompt
Haz que las paredes estén al borde de los escenarios
User prompt
Repara todos los errores
User prompt
Haz que cada pared de cada pista esté sincronizada con su respectiva imagen
User prompt
Añade 3 pistas diferentes con diferentes fondos
User prompt
Agrega una animación para el fondo del menú ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Agrégale una foto al fondo del menú
User prompt
Ahora agrégale multijugador
User prompt
Please fix the bug: 'Uncaught TypeError: Failed to execute 'attachShader' on 'WebGLRenderingContext': parameter 2 is not of type 'WebGLShader'.' in or related to this line: 'if (gameState === 'racing' && player) {' Line Number: 522
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 444
Code edit (1 edits merged)
Please save this source code
User prompt
Freddy's Racing Championship
Initial prompt
I would like to create a multiplayer and storymode game in the style of Mario Kart for Android, a racing game set in the animations of the 80s with 6 characters: a bear named Freddy, a blue rabbit named Bonnie, a yellow chicken named Chica, a red fox named Foxy, an animatronic endoskeleton named Endo and another yellow bear named Golden Freddy (Golden Freddy and Endo are difficult characters to unlock). That each player can create their own nickname and can enter their Google Play account, that the game has the following achievements: make a race in the shortest possible time, win 5 races with Foxy, win 5 races with Freddy, win 5 races with Endo or Golden Freddy, unlock Endo and unlock Golden Freddy. That there are 3 race tracks: first track: Candy Kingdom: a pink race track themed around candy and sweets, second track: Family Dinner: a track themed around Fredbear's Family Dinner pizzeria and third track: Funtime!: a race track themed around the Fnaf sister location animatronics that each race track has its obstacles: such as an animatronic endoskeleton, broken Freddy heads, wrenches, and knives.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function (text, callback) {
var self = Container.call(this);
self.callback = callback;
var bg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2(text, {
size: 40,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.down = function () {
LK.getSound('select').play();
if (self.callback) {
self.callback();
}
};
return self;
});
var Character = Container.expand(function (characterType) {
var self = Container.call(this);
self.characterType = characterType || 'freddy';
self.speed = 0;
self.maxSpeed = 8;
self.acceleration = 0.3;
self.deceleration = 0.2;
self.turnSpeed = 0.1;
self.direction = 0;
self.isUnlocked = true;
// Set unlock status
if (self.characterType === 'endo') {
self.isUnlocked = storage.endoUnlocked || false;
} else if (self.characterType === 'golden_freddy') {
self.isUnlocked = storage.goldenFreddyUnlocked || false;
}
var sprite = self.attachAsset(self.characterType, {
anchorX: 0.5,
anchorY: 0.5
});
self.moveForward = function () {
if (self.speed < self.maxSpeed) {
self.speed += self.acceleration;
}
};
self.moveBackward = function () {
if (self.speed > -self.maxSpeed * 0.5) {
self.speed -= self.acceleration;
}
};
self.turnLeft = function () {
self.direction -= self.turnSpeed;
sprite.rotation = self.direction;
};
self.turnRight = function () {
self.direction += self.turnSpeed;
sprite.rotation = self.direction;
};
self.applyDeceleration = function () {
if (self.speed > 0) {
self.speed -= self.deceleration;
if (self.speed < 0) self.speed = 0;
} else if (self.speed < 0) {
self.speed += self.deceleration;
if (self.speed > 0) self.speed = 0;
}
};
self.update = function () {
// Move based on current speed and direction
self.x += Math.sin(self.direction) * self.speed;
self.y -= Math.cos(self.direction) * self.speed;
// Keep within track bounds - adjust based on selected track
var minX = 100;
var maxX = 1948;
if (selectedTrack === 1) {
// Forest track - dynamic bounds based on Y position
var ySection = Math.floor(self.y / 200);
if (ySection >= 0 && ySection <= 12) {
var forestBounds = [{
minX: 100,
maxX: 1948
}, {
minX: 100,
maxX: 1948
}, {
minX: 100,
maxX: 1948
}, {
minX: 100,
maxX: 1948
}, {
minX: 300,
maxX: 1748
}, {
minX: 400,
maxX: 1648
}, {
minX: 350,
maxX: 1698
}, {
minX: 250,
maxX: 1798
}, {
minX: 150,
maxX: 1898
}, {
minX: 100,
maxX: 1948
}, {
minX: 150,
maxX: 1898
}, {
minX: 200,
maxX: 1848
}, {
minX: 250,
maxX: 1798
}];
if (forestBounds[ySection]) {
minX = forestBounds[ySection].minX;
maxX = forestBounds[ySection].maxX;
}
}
} else if (selectedTrack === 2) {
// Desert track - canyon bounds
var ySection = Math.floor(self.y / 200);
if (ySection >= 0 && ySection <= 12) {
var desertBounds = [{
minX: 300,
maxX: 1748
}, {
minX: 250,
maxX: 1798
}, {
minX: 200,
maxX: 1848
}, {
minX: 150,
maxX: 1898
}, {
minX: 100,
maxX: 1948
}, {
minX: 150,
maxX: 1898
}, {
minX: 200,
maxX: 1848
}, {
minX: 300,
maxX: 1748
}, {
minX: 400,
maxX: 1648
}, {
minX: 500,
maxX: 1548
}, {
minX: 400,
maxX: 1648
}, {
minX: 300,
maxX: 1748
}, {
minX: 200,
maxX: 1848
}];
if (desertBounds[ySection]) {
minX = desertBounds[ySection].minX;
maxX = desertBounds[ySection].maxX;
}
}
} else if (selectedTrack === 3) {
// Night track - city bounds
var ySection = Math.floor(self.y / 200);
if (ySection >= 0 && ySection <= 12) {
var nightBounds = [{
minX: 150,
maxX: 1898
}, {
minX: 200,
maxX: 1848
}, {
minX: 350,
maxX: 1698
}, {
minX: 500,
maxX: 1548
}, {
minX: 400,
maxX: 1648
}, {
minX: 250,
maxX: 1798
}, {
minX: 150,
maxX: 1898
}, {
minX: 100,
maxX: 1948
}, {
minX: 200,
maxX: 1848
}, {
minX: 350,
maxX: 1698
}, {
minX: 450,
maxX: 1598
}, {
minX: 300,
maxX: 1748
}, {
minX: 150,
maxX: 1898
}];
if (nightBounds[ySection]) {
minX = nightBounds[ySection].minX;
maxX = nightBounds[ySection].maxX;
}
}
}
if (self.x < minX) self.x = minX;
if (self.x > maxX) self.x = maxX;
if (self.y < 100) self.y = 100;
if (self.y > 2632) self.y = 2632;
};
return self;
});
var CharacterCard = Container.expand(function (characterType) {
var self = Container.call(this);
self.characterType = characterType;
var bg = self.attachAsset('character_card', {
anchorX: 0.5,
anchorY: 0.5
});
var character = new Character(characterType);
character.x = 0;
character.y = -50;
self.addChild(character);
var nameText = new Text2(characterType.toUpperCase(), {
size: 24,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = 80;
self.addChild(nameText);
// Show locked status
if (!character.isUnlocked) {
bg.tint = 0x666666;
var lockText = new Text2("LOCKED", {
size: 20,
fill: 0xFF0000
});
lockText.anchor.set(0.5, 0.5);
lockText.y = 100;
self.addChild(lockText);
}
self.down = function () {
if (character.isUnlocked) {
LK.getSound('select').play();
selectedCharacter = self.characterType;
// Just select character, don't start race yet
}
};
return self;
});
var Obstacle = Container.expand(function (obstacleType, x, y) {
var self = Container.call(this);
self.obstacleType = obstacleType || 'endoskeleton';
self.x = x || 0;
self.y = y || 0;
var sprite = self.attachAsset(self.obstacleType, {
anchorX: 0.5,
anchorY: 0.5
});
// Add some rotation for visual variety
sprite.rotation = Math.random() * Math.PI * 2;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Character sprites
// Track elements
// Obstacles
// UI elements
// Sounds
var gameState = 'menu'; // 'menu', 'character_select', 'racing', 'results', 'multiplayer_lobby', 'multiplayer_racing'
var selectedCharacter = 'freddy';
var selectedTrack = 1;
var player = null;
var otherPlayers = [];
var obstacles = [];
var lapTime = 0;
var startTime = 0;
var bestTime = storage.bestTime || 999999;
var raceDistance = 0;
var totalRaceDistance = 3000;
var isMultiplayer = false;
var playerNickname = storage.playerNickname || "Player";
var multiplayerRoom = null;
var playersFinished = [];
var playerLives = 3;
// Initialize storage defaults
if (storage.gamesPlayed === undefined) storage.gamesPlayed = 0;
if (storage.wins === undefined) storage.wins = 0;
if (storage.endoUnlocked === undefined) storage.endoUnlocked = false;
if (storage.goldenFreddyUnlocked === undefined) storage.goldenFreddyUnlocked = false;
// UI Elements
var titleText = new Text2("FREDDY'S RACING\nCHAMPIONSHIP", {
size: 80,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
var timeText = new Text2("", {
size: 60,
fill: 0xFFFFFF
});
timeText.anchor.set(0.5, 0);
LK.gui.top.addChild(timeText);
var speedText = new Text2("", {
size: 40,
fill: 0x00FF00
});
speedText.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(speedText);
var progressText = new Text2("", {
size: 40,
fill: 0xFFFF00
});
progressText.anchor.set(1, 0);
LK.gui.bottomRight.addChild(progressText);
var livesText = new Text2("", {
size: 40,
fill: 0xFF0000
});
livesText.anchor.set(0, 1);
LK.gui.bottomLeft.addChild(livesText);
function showMenu() {
gameState = 'menu';
game.removeChildren();
// Add background image
var menuBg = LK.getAsset('menu_background', {
anchorX: 0.5,
anchorY: 0.5
});
menuBg.x = 1024;
menuBg.y = 1366;
game.addChild(menuBg);
// Add pulsing animation to background
tween(menuBg, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(menuBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Restart the animation loop
if (gameState === 'menu') {
tween(menuBg, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 3000,
easing: tween.easeInOut,
onFinish: arguments.callee.caller
});
}
}
});
}
});
// Add subtle rotation animation
tween(menuBg, {
rotation: 0.02
}, {
duration: 4000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(menuBg, {
rotation: -0.02
}, {
duration: 4000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (gameState === 'menu') {
tween(menuBg, {
rotation: 0.02
}, {
duration: 4000,
easing: tween.easeInOut,
onFinish: arguments.callee.caller
});
}
}
});
}
});
game.addChild(titleText);
// Add floating animation to title
tween(titleText, {
y: 380
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
y: 420
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (gameState === 'menu') {
tween(titleText, {
y: 380
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: arguments.callee.caller
});
}
}
});
}
});
// Add color tinting animation to title
tween(titleText, {
tint: 0xFFFF00
}, {
duration: 2500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
tint: 0xFFD700
}, {
duration: 2500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (gameState === 'menu') {
tween(titleText, {
tint: 0xFFFF00
}, {
duration: 2500,
easing: tween.easeInOut,
onFinish: arguments.callee.caller
});
}
}
});
}
});
var singlePlayerButton = new Button("SINGLE PLAYER", function () {
isMultiplayer = false;
showCharacterSelect();
});
singlePlayerButton.x = 1024;
singlePlayerButton.y = 700;
game.addChild(singlePlayerButton);
var multiplayerButton = new Button("MULTIPLAYER", function () {
isMultiplayer = true;
showMultiplayerLobby();
});
multiplayerButton.x = 1024;
multiplayerButton.y = 820;
game.addChild(multiplayerButton);
var statsButton = new Button("STATS", function () {
showStats();
});
statsButton.x = 1024;
statsButton.y = 940;
game.addChild(statsButton);
// Show best time
if (bestTime < 999999) {
var bestTimeText = new Text2("Best Time: " + (bestTime / 1000).toFixed(2) + "s", {
size: 40,
fill: 0x00FF00
});
bestTimeText.anchor.set(0.5, 0.5);
bestTimeText.x = 1024;
bestTimeText.y = 1200;
game.addChild(bestTimeText);
}
}
function showCharacterSelect() {
gameState = 'character_select';
game.removeChildren();
var selectText = new Text2("SELECT CHARACTER", {
size: 60,
fill: 0xFFD700
});
selectText.anchor.set(0.5, 0.5);
selectText.x = 1024;
selectText.y = 300;
game.addChild(selectText);
var characters = ['freddy', 'bonnie', 'chica', 'foxy', 'endo', 'golden_freddy'];
var startX = 300;
var spacing = 300;
for (var i = 0; i < characters.length; i++) {
var card = new CharacterCard(characters[i]);
card.x = startX + i % 3 * spacing;
card.y = 600 + Math.floor(i / 3) * 400;
game.addChild(card);
}
var nextButton = new Button("NEXT: SELECT TRACK", function () {
showTrackSelect();
});
nextButton.x = 1024;
nextButton.y = 1400;
game.addChild(nextButton);
var backButton = new Button("BACK", function () {
showMenu();
});
backButton.x = 200;
backButton.y = 200;
game.addChild(backButton);
}
function showTrackSelect() {
gameState = 'track_select';
game.removeChildren();
var selectText = new Text2("SELECT TRACK", {
size: 60,
fill: 0xFFD700
});
selectText.anchor.set(0.5, 0.5);
selectText.x = 1024;
selectText.y = 300;
game.addChild(selectText);
// Track 1 - Forest Track
var track1Bg = LK.getAsset('track_background_1', {
anchorX: 0.5,
anchorY: 0.5
});
track1Bg.x = 512;
track1Bg.y = 700;
track1Bg.scaleX = 0.4;
track1Bg.scaleY = 0.4;
game.addChild(track1Bg);
var track1Button = new Button("FOREST TRACK", function () {
selectedTrack = 1;
if (isMultiplayer) {
if (multiplayer && multiplayer.sendData) {
multiplayer.sendData({
type: 'characterSelected',
character: selectedCharacter,
nickname: playerNickname,
track: selectedTrack
});
}
startMultiplayerRace();
} else {
startRace();
}
});
track1Button.x = 512;
track1Button.y = 950;
game.addChild(track1Button);
var track1Text = new Text2("FOREST", {
size: 30,
fill: 0xFFFFFF
});
track1Text.anchor.set(0.5, 0.5);
track1Text.x = 512;
track1Text.y = 500;
game.addChild(track1Text);
// Track 2 - Desert Track
var track2Bg = LK.getAsset('track_background_2', {
anchorX: 0.5,
anchorY: 0.5
});
track2Bg.x = 1024;
track2Bg.y = 700;
track2Bg.scaleX = 0.4;
track2Bg.scaleY = 0.4;
game.addChild(track2Bg);
var track2Button = new Button("DESERT TRACK", function () {
selectedTrack = 2;
if (isMultiplayer) {
if (multiplayer && multiplayer.sendData) {
multiplayer.sendData({
type: 'characterSelected',
character: selectedCharacter,
nickname: playerNickname,
track: selectedTrack
});
}
startMultiplayerRace();
} else {
startRace();
}
});
track2Button.x = 1024;
track2Button.y = 950;
game.addChild(track2Button);
var track2Text = new Text2("DESERT", {
size: 30,
fill: 0xFFFFFF
});
track2Text.anchor.set(0.5, 0.5);
track2Text.x = 1024;
track2Text.y = 500;
game.addChild(track2Text);
// Track 3 - Night Track
var track3Bg = LK.getAsset('track_background_3', {
anchorX: 0.5,
anchorY: 0.5
});
track3Bg.x = 1536;
track3Bg.y = 700;
track3Bg.scaleX = 0.4;
track3Bg.scaleY = 0.4;
game.addChild(track3Bg);
var track3Button = new Button("NIGHT TRACK", function () {
selectedTrack = 3;
if (isMultiplayer) {
if (multiplayer && multiplayer.sendData) {
multiplayer.sendData({
type: 'characterSelected',
character: selectedCharacter,
nickname: playerNickname,
track: selectedTrack
});
}
startMultiplayerRace();
} else {
startRace();
}
});
track3Button.x = 1536;
track3Button.y = 950;
game.addChild(track3Button);
var track3Text = new Text2("NIGHT", {
size: 30,
fill: 0xFFFFFF
});
track3Text.anchor.set(0.5, 0.5);
track3Text.x = 1536;
track3Text.y = 500;
game.addChild(track3Text);
var backButton = new Button("BACK", function () {
showCharacterSelect();
});
backButton.x = 200;
backButton.y = 200;
game.addChild(backButton);
}
function showStats() {
game.removeChildren();
var statsText = new Text2("STATISTICS", {
size: 60,
fill: 0xFFD700
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 1024;
statsText.y = 300;
game.addChild(statsText);
var gamesText = new Text2("Games Played: " + storage.gamesPlayed, {
size: 40,
fill: 0xFFFFFF
});
gamesText.anchor.set(0.5, 0.5);
gamesText.x = 1024;
gamesText.y = 500;
game.addChild(gamesText);
var winsText = new Text2("Wins: " + storage.wins, {
size: 40,
fill: 0xFFFFFF
});
winsText.anchor.set(0.5, 0.5);
winsText.x = 1024;
winsText.y = 600;
game.addChild(winsText);
var backButton = new Button("BACK", function () {
showMenu();
});
backButton.x = 1024;
backButton.y = 800;
game.addChild(backButton);
}
function showMultiplayerLobby() {
gameState = 'multiplayer_lobby';
game.removeChildren();
var lobbyText = new Text2("MULTIPLAYER LOBBY", {
size: 60,
fill: 0xFFD700
});
lobbyText.anchor.set(0.5, 0.5);
lobbyText.x = 1024;
lobbyText.y = 300;
game.addChild(lobbyText);
var nicknameText = new Text2("Nickname: " + playerNickname, {
size: 40,
fill: 0xFFFFFF
});
nicknameText.anchor.set(0.5, 0.5);
nicknameText.x = 1024;
nicknameText.y = 500;
game.addChild(nicknameText);
var joinRoomButton = new Button("JOIN ROOM", function () {
joinMultiplayerRoom();
});
joinRoomButton.x = 1024;
joinRoomButton.y = 700;
game.addChild(joinRoomButton);
var createRoomButton = new Button("CREATE ROOM", function () {
createMultiplayerRoom();
});
createRoomButton.x = 1024;
createRoomButton.y = 820;
game.addChild(createRoomButton);
var backButton = new Button("BACK", function () {
showMenu();
});
backButton.x = 1024;
backButton.y = 940;
game.addChild(backButton);
}
function createMultiplayerRoom() {
if (multiplayer && multiplayer.createRoom) {
multiplayer.createRoom({
maxPlayers: 4,
gameType: "racing"
}, function (room) {
multiplayerRoom = room;
setupMultiplayerEvents();
showCharacterSelect();
});
} else {
console.log("Multiplayer not available");
showCharacterSelect();
}
}
function joinMultiplayerRoom() {
if (multiplayer && multiplayer.joinRoom) {
multiplayer.joinRoom({
gameType: "racing"
}, function (room) {
multiplayerRoom = room;
setupMultiplayerEvents();
showCharacterSelect();
});
} else {
console.log("Multiplayer not available");
showCharacterSelect();
}
}
function setupMultiplayerEvents() {
if (multiplayer && multiplayer.on) {
multiplayer.on('playerJoined', function (playerData) {
console.log('Player joined:', playerData.nickname);
});
multiplayer.on('playerLeft', function (playerData) {
console.log('Player left:', playerData.nickname);
// Remove player from game
for (var i = otherPlayers.length - 1; i >= 0; i--) {
if (otherPlayers[i].playerId === playerData.id) {
if (otherPlayers[i].parent) {
otherPlayers[i].destroy();
}
otherPlayers.splice(i, 1);
break;
}
}
});
multiplayer.on('gameData', function (data) {
handleMultiplayerData(data);
});
multiplayer.on('raceStart', function (data) {
if (gameState === 'character_select') {
startMultiplayerRace();
}
});
}
}
function handleMultiplayerData(data) {
if (data.type === 'playerPosition' && gameState === 'multiplayer_racing') {
updateOtherPlayerPosition(data);
} else if (data.type === 'playerFinished') {
handlePlayerFinished(data);
}
}
function updateOtherPlayerPosition(data) {
var existingPlayer = null;
for (var i = 0; i < otherPlayers.length; i++) {
if (otherPlayers[i].playerId === data.playerId) {
existingPlayer = otherPlayers[i];
break;
}
}
if (!existingPlayer) {
existingPlayer = new Character(data.character);
existingPlayer.playerId = data.playerId;
existingPlayer.nickname = data.nickname;
otherPlayers.push(existingPlayer);
game.addChild(existingPlayer);
}
if (existingPlayer && existingPlayer.parent) {
existingPlayer.x = data.x;
existingPlayer.y = data.y;
existingPlayer.direction = data.direction;
if (existingPlayer.children[0]) {
existingPlayer.children[0].rotation = data.direction;
}
}
}
function handlePlayerFinished(data) {
playersFinished.push({
playerId: data.playerId,
nickname: data.nickname,
time: data.time,
character: data.character
});
}
function startRace() {
gameState = 'racing';
game.removeChildren();
// Add track background
var trackBg = LK.getAsset('track_background_' + selectedTrack, {
anchorX: 0.5,
anchorY: 0.5
});
trackBg.x = 1024;
trackBg.y = 1366;
game.addChild(trackBg);
// Create player
player = new Character(selectedCharacter);
player.x = 1024;
player.y = 2400;
game.addChild(player);
// Create track elements
createTrack();
createObstacles();
// Start race timer
startTime = Date.now();
lapTime = 0;
raceDistance = 0;
playerLives = 3;
// Play race music
LK.playMusic('race_music');
storage.gamesPlayed++;
}
function startMultiplayerRace() {
gameState = 'multiplayer_racing';
game.removeChildren();
// Add track background
var trackBg = LK.getAsset('track_background_' + selectedTrack, {
anchorX: 0.5,
anchorY: 0.5
});
trackBg.x = 1024;
trackBg.y = 1366;
game.addChild(trackBg);
// Create player
player = new Character(selectedCharacter);
player.x = 1024;
player.y = 2400;
player.playerId = multiplayer && multiplayer.getPlayerId ? multiplayer.getPlayerId() : 'player_' + Date.now();
player.nickname = playerNickname;
game.addChild(player);
// Create track elements
createTrack();
createObstacles();
// Start race timer
startTime = Date.now();
lapTime = 0;
raceDistance = 0;
playersFinished = [];
playerLives = 3;
// Play race music
LK.playMusic('race_music');
storage.gamesPlayed++;
// Send race start signal
if (multiplayer && multiplayer.sendData) {
multiplayer.sendData({
type: 'raceStarted'
});
}
}
function createTrack() {
// Create track-specific walls based on selected track
if (selectedTrack === 1) {
// Forest Track - winding path with trees
createForestTrack();
} else if (selectedTrack === 2) {
// Desert Track - canyon walls
createDesertTrack();
} else if (selectedTrack === 3) {
// Night Track - city buildings
createNightTrack();
}
// Create finish line
var finishLine = LK.getAsset('finish_line', {
anchorX: 0.5,
anchorY: 0.5
});
finishLine.x = 1024;
finishLine.y = 100;
game.addChild(finishLine);
}
function createForestTrack() {
// Forest track with edge walls only - center is completely open
var trackSections = [{
leftX: 0,
rightX: 2048,
y: 0
}, {
leftX: 0,
rightX: 2048,
y: 200
}, {
leftX: 0,
rightX: 2048,
y: 400
}, {
leftX: 0,
rightX: 2048,
y: 600
}, {
leftX: 0,
rightX: 2048,
y: 800
}, {
leftX: 0,
rightX: 2048,
y: 1000
}, {
leftX: 0,
rightX: 2048,
y: 1200
}, {
leftX: 0,
rightX: 2048,
y: 1400
}, {
leftX: 0,
rightX: 2048,
y: 1600
}, {
leftX: 0,
rightX: 2048,
y: 1800
}, {
leftX: 0,
rightX: 2048,
y: 2000
}, {
leftX: 0,
rightX: 2048,
y: 2200
}, {
leftX: 0,
rightX: 2048,
y: 2400
}];
for (var i = 0; i < trackSections.length; i++) {
var section = trackSections[i];
var leftWall = LK.getAsset('track_wall', {
anchorX: 0.5,
anchorY: 0.5
});
leftWall.x = section.leftX;
leftWall.y = section.y;
leftWall.tint = 0x228B22; // Forest green
game.addChild(leftWall);
var rightWall = LK.getAsset('track_wall', {
anchorX: 0.5,
anchorY: 0.5
});
rightWall.x = section.rightX;
rightWall.y = section.y;
rightWall.tint = 0x228B22; // Forest green
game.addChild(rightWall);
}
}
function createDesertTrack() {
// Desert track with edge walls only - center is completely open
var trackSections = [{
leftX: 0,
rightX: 2048,
y: 0
}, {
leftX: 0,
rightX: 2048,
y: 200
}, {
leftX: 0,
rightX: 2048,
y: 400
}, {
leftX: 0,
rightX: 2048,
y: 600
}, {
leftX: 0,
rightX: 2048,
y: 800
}, {
leftX: 0,
rightX: 2048,
y: 1000
}, {
leftX: 0,
rightX: 2048,
y: 1200
}, {
leftX: 0,
rightX: 2048,
y: 1400
}, {
leftX: 0,
rightX: 2048,
y: 1600
}, {
leftX: 0,
rightX: 2048,
y: 1800
}, {
leftX: 0,
rightX: 2048,
y: 2000
}, {
leftX: 0,
rightX: 2048,
y: 2200
}, {
leftX: 0,
rightX: 2048,
y: 2400
}];
for (var i = 0; i < trackSections.length; i++) {
var section = trackSections[i];
var leftWall = LK.getAsset('track_wall', {
anchorX: 0.5,
anchorY: 0.5
});
leftWall.x = section.leftX;
leftWall.y = section.y;
leftWall.tint = 0xDEB887; // Sandy brown
leftWall.scaleY = 1.5; // Taller canyon walls
game.addChild(leftWall);
var rightWall = LK.getAsset('track_wall', {
anchorX: 0.5,
anchorY: 0.5
});
rightWall.x = section.rightX;
rightWall.y = section.y;
rightWall.tint = 0xDEB887; // Sandy brown
rightWall.scaleY = 1.5; // Taller canyon walls
game.addChild(rightWall);
}
}
function createNightTrack() {
// Night track with edge walls only - center is completely open
var trackSections = [{
leftX: 0,
rightX: 2048,
y: 0
}, {
leftX: 0,
rightX: 2048,
y: 200
}, {
leftX: 0,
rightX: 2048,
y: 400
}, {
leftX: 0,
rightX: 2048,
y: 600
}, {
leftX: 0,
rightX: 2048,
y: 800
}, {
leftX: 0,
rightX: 2048,
y: 1000
}, {
leftX: 0,
rightX: 2048,
y: 1200
}, {
leftX: 0,
rightX: 2048,
y: 1400
}, {
leftX: 0,
rightX: 2048,
y: 1600
}, {
leftX: 0,
rightX: 2048,
y: 1800
}, {
leftX: 0,
rightX: 2048,
y: 2000
}, {
leftX: 0,
rightX: 2048,
y: 2200
}, {
leftX: 0,
rightX: 2048,
y: 2400
}];
for (var i = 0; i < trackSections.length; i++) {
var section = trackSections[i];
var leftWall = LK.getAsset('track_wall', {
anchorX: 0.5,
anchorY: 0.5
});
leftWall.x = section.leftX;
leftWall.y = section.y;
leftWall.tint = 0x2F4F4F; // Dark slate gray
leftWall.scaleY = 2; // Tall building walls
game.addChild(leftWall);
var rightWall = LK.getAsset('track_wall', {
anchorX: 0.5,
anchorY: 0.5
});
rightWall.x = section.rightX;
rightWall.y = section.y;
rightWall.tint = 0x2F4F4F; // Dark slate gray
rightWall.scaleY = 2; // Tall building walls
game.addChild(rightWall);
}
}
function createObstacles() {
obstacles = [];
var obstacleTypes = ['endoskeleton', 'broken_head', 'wrench', 'knife'];
for (var i = 0; i < 15; i++) {
var type = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
var x = 200 + Math.random() * 1648;
var y = 200 + Math.random() * 2200;
var obstacle = new Obstacle(type, x, y);
obstacles.push(obstacle);
game.addChild(obstacle);
}
}
function checkCollisions() {
if (!player || !player.parent) return;
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (obstacle && obstacle.parent && player.intersects(obstacle)) {
// Crash effect
LK.getSound('crash').play();
LK.effects.flashObject(player, 0xFF0000, 500);
// Reduce lives
playerLives--;
// Slow down player
player.speed *= 0.5;
// Move obstacle away
obstacle.x = -1000;
obstacle.y = -1000;
// Check if game over
if (playerLives <= 0) {
LK.setTimeout(function () {
LK.showGameOver();
}, 500);
}
}
}
}
function updateRace() {
if (!player || !player.parent) return;
// Update race distance based on forward progress
var progress = (2400 - player.y) / 2300;
if (progress > raceDistance / totalRaceDistance) {
raceDistance = progress * totalRaceDistance;
}
// Check if race is finished
if (player.y <= 100) {
finishRace();
}
// Update UI
lapTime = Date.now() - startTime;
if (timeText && timeText.parent) {
timeText.setText("Time: " + (lapTime / 1000).toFixed(2) + "s");
}
if (speedText && speedText.parent) {
speedText.setText("Speed: " + Math.floor(player.speed * 10));
}
if (progressText && progressText.parent) {
progressText.setText("Progress: " + Math.floor(raceDistance / totalRaceDistance * 100) + "%");
}
if (livesText && livesText.parent) {
livesText.setText("Lives: " + playerLives);
}
}
function finishRace() {
gameState = 'results';
// Stop music
LK.stopMusic();
// Check for new best time
var isNewBest = lapTime < bestTime;
if (isNewBest) {
bestTime = lapTime;
storage.bestTime = bestTime;
storage.wins++;
}
// Check for unlock conditions
if (lapTime < 30000 && !storage.endoUnlocked) {
// Under 30 seconds
storage.endoUnlocked = true;
LK.effects.flashScreen(0x00FF00, 1000);
}
if (storage.wins >= 5 && !storage.goldenFreddyUnlocked) {
storage.goldenFreddyUnlocked = true;
LK.effects.flashScreen(0xDAA520, 1000);
}
// Show results
LK.setTimeout(function () {
showResults(isNewBest);
}, 1000);
}
function updateMultiplayerRace() {
if (!player || !player.parent) return;
// Update race distance based on forward progress
var progress = (2400 - player.y) / 2300;
if (progress > raceDistance / totalRaceDistance) {
raceDistance = progress * totalRaceDistance;
}
// Check if race is finished
if (player.y <= 100) {
finishMultiplayerRace();
}
// Update UI
lapTime = Date.now() - startTime;
if (timeText && timeText.parent) {
timeText.setText("Time: " + (lapTime / 1000).toFixed(2) + "s");
}
if (speedText && speedText.parent) {
speedText.setText("Speed: " + Math.floor(player.speed * 10));
}
if (progressText && progressText.parent) {
progressText.setText("Progress: " + Math.floor(raceDistance / totalRaceDistance * 100) + "%");
}
if (livesText && livesText.parent) {
livesText.setText("Lives: " + playerLives);
}
}
function finishMultiplayerRace() {
// Stop music
LK.stopMusic();
// Send finish data to other players
if (multiplayer && multiplayer.sendData) {
multiplayer.sendData({
type: 'playerFinished',
playerId: player.playerId,
nickname: player.nickname,
time: lapTime,
character: selectedCharacter
});
}
// Add self to finished list
playersFinished.push({
playerId: player.playerId,
nickname: player.nickname,
time: lapTime,
character: selectedCharacter
});
// Check for new best time
var isNewBest = lapTime < bestTime;
if (isNewBest) {
bestTime = lapTime;
storage.bestTime = bestTime;
storage.wins++;
}
// Check for unlock conditions
if (lapTime < 30000 && !storage.endoUnlocked) {
storage.endoUnlocked = true;
LK.effects.flashScreen(0x00FF00, 1000);
}
if (storage.wins >= 5 && !storage.goldenFreddyUnlocked) {
storage.goldenFreddyUnlocked = true;
LK.effects.flashScreen(0xDAA520, 1000);
}
// Show results after delay
LK.setTimeout(function () {
showMultiplayerResults(isNewBest);
}, 1000);
}
function showMultiplayerResults(isNewBest) {
game.removeChildren();
var resultsText = new Text2("RACE COMPLETE!", {
size: 60,
fill: 0xFFD700
});
resultsText.anchor.set(0.5, 0.5);
resultsText.x = 1024;
resultsText.y = 200;
game.addChild(resultsText);
// Sort players by finish time
playersFinished.sort(function (a, b) {
return a.time - b.time;
});
// Display rankings
for (var i = 0; i < Math.min(playersFinished.length, 4); i++) {
var playerData = playersFinished[i];
var position = i + 1;
var rankText = new Text2(position + ". " + playerData.nickname + " - " + (playerData.time / 1000).toFixed(2) + "s", {
size: 40,
fill: position === 1 ? 0xFFD700 : 0xFFFFFF
});
rankText.anchor.set(0.5, 0.5);
rankText.x = 1024;
rankText.y = 400 + i * 80;
game.addChild(rankText);
}
if (isNewBest) {
var newBestText = new Text2("NEW PERSONAL BEST!", {
size: 40,
fill: 0x00FF00
});
newBestText.anchor.set(0.5, 0.5);
newBestText.x = 1024;
newBestText.y = 800;
game.addChild(newBestText);
}
var playAgainButton = new Button("RACE AGAIN", function () {
showCharacterSelect();
});
playAgainButton.x = 1024;
playAgainButton.y = 1000;
game.addChild(playAgainButton);
var menuButton = new Button("MAIN MENU", function () {
if (multiplayerRoom && multiplayer && multiplayer.leaveRoom) {
multiplayer.leaveRoom();
multiplayerRoom = null;
}
showMenu();
});
menuButton.x = 1024;
menuButton.y = 1120;
game.addChild(menuButton);
}
function showResults(isNewBest) {
game.removeChildren();
var resultsText = new Text2("RACE COMPLETE!", {
size: 60,
fill: 0xFFD700
});
resultsText.anchor.set(0.5, 0.5);
resultsText.x = 1024;
resultsText.y = 400;
game.addChild(resultsText);
var timeResultText = new Text2("Your Time: " + (lapTime / 1000).toFixed(2) + "s", {
size: 50,
fill: isNewBest ? "#00FF00" : "#FFFFFF"
});
timeResultText.anchor.set(0.5, 0.5);
timeResultText.x = 1024;
timeResultText.y = 600;
game.addChild(timeResultText);
if (isNewBest) {
var newBestText = new Text2("NEW BEST TIME!", {
size: 40,
fill: 0x00FF00
});
newBestText.anchor.set(0.5, 0.5);
newBestText.x = 1024;
newBestText.y = 700;
game.addChild(newBestText);
}
var playAgainButton = new Button("RACE AGAIN", function () {
showCharacterSelect();
});
playAgainButton.x = 1024;
playAgainButton.y = 900;
game.addChild(playAgainButton);
var menuButton = new Button("MAIN MENU", function () {
showMenu();
});
menuButton.x = 1024;
menuButton.y = 1020;
game.addChild(menuButton);
}
// Touch controls
var isAccelerating = false;
var isBraking = false;
var isTurningLeft = false;
var isTurningRight = false;
game.down = function (x, y, obj) {
if (gameState !== 'racing' && gameState !== 'multiplayer_racing' || !player) return;
// Divide screen into control zones
if (y > 2000) {
// Bottom area for acceleration/braking
if (x < 1024) {
isBraking = true;
} else {
isAccelerating = true;
}
} else {
// Upper area for steering
if (x < 1024) {
isTurningLeft = true;
} else {
isTurningRight = true;
}
}
};
game.up = function (x, y, obj) {
isAccelerating = false;
isBraking = false;
isTurningLeft = false;
isTurningRight = false;
};
game.update = function () {
if ((gameState === 'racing' || gameState === 'multiplayer_racing') && player && player.parent) {
// Validate player object exists and is properly attached
try {
// Handle controls
if (isAccelerating) {
player.moveForward();
if (LK.ticks % 20 === 0) {
LK.getSound('engine').play();
}
} else if (isBraking) {
player.moveBackward();
} else {
player.applyDeceleration();
}
if (isTurningLeft) {
player.turnLeft();
}
if (isTurningRight) {
player.turnRight();
}
checkCollisions();
if (gameState === 'multiplayer_racing') {
updateMultiplayerRace();
// Send player position every few frames
if (LK.ticks % 3 === 0 && multiplayer && multiplayer.sendData) {
multiplayer.sendData({
type: 'playerPosition',
playerId: player.playerId,
nickname: player.nickname,
character: selectedCharacter,
x: player.x,
y: player.y,
direction: player.direction
});
}
} else {
updateRace();
}
} catch (e) {
console.log("Error in game update:", e);
}
}
};
// Initialize game
showMenu(); ===================================================================
--- original.js
+++ change.js
@@ -924,9 +924,9 @@
finishLine.y = 100;
game.addChild(finishLine);
}
function createForestTrack() {
- // Forest track with curved walls resembling forest paths
+ // Forest track with edge walls only - center is completely open
var trackSections = [{
leftX: 0,
rightX: 2048,
y: 0
@@ -942,42 +942,42 @@
leftX: 0,
rightX: 2048,
y: 600
}, {
- leftX: 200,
- rightX: 1848,
+ leftX: 0,
+ rightX: 2048,
y: 800
}, {
- leftX: 300,
- rightX: 1748,
+ leftX: 0,
+ rightX: 2048,
y: 1000
}, {
- leftX: 250,
- rightX: 1798,
+ leftX: 0,
+ rightX: 2048,
y: 1200
}, {
- leftX: 150,
- rightX: 1898,
+ leftX: 0,
+ rightX: 2048,
y: 1400
}, {
- leftX: 50,
- rightX: 1998,
+ leftX: 0,
+ rightX: 2048,
y: 1600
}, {
leftX: 0,
rightX: 2048,
y: 1800
}, {
- leftX: 50,
- rightX: 1998,
+ leftX: 0,
+ rightX: 2048,
y: 2000
}, {
- leftX: 100,
- rightX: 1948,
+ leftX: 0,
+ rightX: 2048,
y: 2200
}, {
- leftX: 150,
- rightX: 1898,
+ leftX: 0,
+ rightX: 2048,
y: 2400
}];
for (var i = 0; i < trackSections.length; i++) {
var section = trackSections[i];
@@ -999,60 +999,60 @@
game.addChild(rightWall);
}
}
function createDesertTrack() {
- // Desert track with straight canyon walls
+ // Desert track with edge walls only - center is completely open
var trackSections = [{
- leftX: 200,
- rightX: 1848,
+ leftX: 0,
+ rightX: 2048,
y: 0
}, {
- leftX: 150,
- rightX: 1898,
+ leftX: 0,
+ rightX: 2048,
y: 200
}, {
- leftX: 100,
- rightX: 1948,
+ leftX: 0,
+ rightX: 2048,
y: 400
}, {
- leftX: 50,
- rightX: 1998,
+ leftX: 0,
+ rightX: 2048,
y: 600
}, {
leftX: 0,
rightX: 2048,
y: 800
}, {
- leftX: 50,
- rightX: 1998,
+ leftX: 0,
+ rightX: 2048,
y: 1000
}, {
- leftX: 100,
- rightX: 1948,
+ leftX: 0,
+ rightX: 2048,
y: 1200
}, {
- leftX: 200,
- rightX: 1848,
+ leftX: 0,
+ rightX: 2048,
y: 1400
}, {
- leftX: 300,
- rightX: 1748,
+ leftX: 0,
+ rightX: 2048,
y: 1600
}, {
- leftX: 400,
- rightX: 1648,
+ leftX: 0,
+ rightX: 2048,
y: 1800
}, {
- leftX: 300,
- rightX: 1748,
+ leftX: 0,
+ rightX: 2048,
y: 2000
}, {
- leftX: 200,
- rightX: 1848,
+ leftX: 0,
+ rightX: 2048,
y: 2200
}, {
- leftX: 100,
- rightX: 1948,
+ leftX: 0,
+ rightX: 2048,
y: 2400
}];
for (var i = 0; i < trackSections.length; i++) {
var section = trackSections[i];
@@ -1076,60 +1076,60 @@
game.addChild(rightWall);
}
}
function createNightTrack() {
- // Night track with building-like walls
+ // Night track with edge walls only - center is completely open
var trackSections = [{
- leftX: 50,
- rightX: 1998,
+ leftX: 0,
+ rightX: 2048,
y: 0
}, {
- leftX: 100,
- rightX: 1948,
+ leftX: 0,
+ rightX: 2048,
y: 200
}, {
- leftX: 250,
- rightX: 1798,
+ leftX: 0,
+ rightX: 2048,
y: 400
}, {
- leftX: 400,
- rightX: 1648,
+ leftX: 0,
+ rightX: 2048,
y: 600
}, {
- leftX: 300,
- rightX: 1748,
+ leftX: 0,
+ rightX: 2048,
y: 800
}, {
- leftX: 150,
- rightX: 1898,
+ leftX: 0,
+ rightX: 2048,
y: 1000
}, {
- leftX: 50,
- rightX: 1998,
+ leftX: 0,
+ rightX: 2048,
y: 1200
}, {
leftX: 0,
rightX: 2048,
y: 1400
}, {
- leftX: 100,
- rightX: 1948,
+ leftX: 0,
+ rightX: 2048,
y: 1600
}, {
- leftX: 250,
- rightX: 1798,
+ leftX: 0,
+ rightX: 2048,
y: 1800
}, {
- leftX: 350,
- rightX: 1698,
+ leftX: 0,
+ rightX: 2048,
y: 2000
}, {
- leftX: 200,
- rightX: 1848,
+ leftX: 0,
+ rightX: 2048,
y: 2200
}, {
- leftX: 50,
- rightX: 1998,
+ leftX: 0,
+ rightX: 2048,
y: 2400
}];
for (var i = 0; i < trackSections.length; i++) {
var section = trackSections[i];
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Freddy's Racing Championship" and with the description "Kart racing game featuring FNAF animatronic characters racing through 80s-themed tracks with unique obstacles and unlockable characters.". No text on banner!
Un conejo morado animatronico en un kart. In-Game asset. No shadows
Un oso dorado animatronico en un kart. In-Game asset. High contrast. No shadows
Un endoesqueleto animatronico en un kart. In-Game asset. 2d. High contrast. No shadows
Un pollo amarillo animatronico en un kart. In-Game asset. 2d. High contrast. No shadows
Un oso animatronico en un kart. In-Game asset. 2d. High contrast. No shadows
Un zorro rojo animatronico en un kart. In-Game asset. 2d. High contrast. No shadows
Mascara de Freddy Fazbear. In-Game asset. 2d. High contrast. No shadows
Llave inglesa. In-Game asset. 2d. High contrast. No shadows
Endoesqueleto animatronico. In-Game asset. 2d. High contrast. No shadows
Línea de meta. In-Game asset. 2d. High contrast. No shadows
Cuchillo con sangre. In-Game asset. 2d. High contrast. No shadows
Pared de ladrillos. In-Game asset. 2d. High contrast. No shadows
Botón rojo. In-Game asset. 2d. High contrast. No shadows
Imagen de bandera de carrera. In-Game asset. 2d. High contrast. No shadows
Pista de carreras desde arriba. In-Game asset. 2d. High contrast. No shadows