/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { selectedTeam: 0, season: 1, matchDay: 1, teamData: undefined }); /**** * Classes ****/ var Button = Container.expand(function (label, callback, width, height) { var self = Container.call(this); width = width || 300; height = height || 120; var button = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, width: width, height: height }); var labelText = new Text2(label, { size: 40, fill: 0xFFFFFF }); labelText.anchor.set(0.5, 0.5); self.addChild(labelText); self.setLabel = function (newLabel) { labelText.setText(newLabel); }; self.down = function (x, y, obj) { // Visual feedback button.tint = 0x3742fa; if (callback) { callback(); } }; self.up = function (x, y, obj) { button.tint = 0xffffff; }; return self; }); var Match = Container.expand(function (homeTeam, awayTeam) { var self = Container.call(this); self.homeTeam = homeTeam; self.awayTeam = awayTeam; self.homeGoals = 0; self.awayGoals = 0; self.isPlayed = false; self.matchTime = 0; self.events = []; var matchCard = self.attachAsset('matchCard', { anchorX: 0.5, anchorY: 0.5 }); var homeText = new Text2(homeTeam.name, { size: 50, fill: 0xFFFFFF }); homeText.anchor.set(1, 0.5); homeText.x = -100; self.addChild(homeText); var scoreText = new Text2("vs", { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0.5); self.addChild(scoreText); var awayText = new Text2(awayTeam.name, { size: 50, fill: 0xFFFFFF }); awayText.anchor.set(0, 0.5); awayText.x = 100; self.addChild(awayText); self.simulateMatch = function () { if (self.isPlayed) { return; } LK.getSound('whistle').play(); var homeStrength = self.homeTeam.strength; var awayStrength = self.awayTeam.strength; // Calculate home advantage (about 10% boost) homeStrength = Math.floor(homeStrength * 1.1); // Calculate expected goals based on team strength var homeExpectedGoals = homeStrength / 20 + Math.random() * 1.5; var awayExpectedGoals = awayStrength / 25 + Math.random() * 1.2; // Generate actual goals with Poisson-like distribution self.homeGoals = Math.floor(getPoissonRandom(homeExpectedGoals)); self.awayGoals = Math.floor(getPoissonRandom(awayExpectedGoals)); // Update team statistics self.homeTeam.goalsFor += self.homeGoals; self.homeTeam.goalsAgainst += self.awayGoals; self.awayTeam.goalsFor += self.awayGoals; self.awayTeam.goalsAgainst += self.homeGoals; if (self.homeGoals > self.awayGoals) { self.homeTeam.points += 3; self.homeTeam.wins += 1; self.awayTeam.losses += 1; } else if (self.homeGoals < self.awayGoals) { self.awayTeam.points += 3; self.awayTeam.wins += 1; self.homeTeam.losses += 1; } else { self.homeTeam.points += 1; self.awayTeam.points += 1; self.homeTeam.draws += 1; self.awayTeam.draws += 1; } // Generate match events self.generateEvents(); // Update the score display scoreText.setText(self.homeGoals + " - " + self.awayGoals); self.isPlayed = true; }; self.generateEvents = function () { // Generate goal events for (var i = 0; i < self.homeGoals; i++) { var minute = Math.floor(Math.random() * 90) + 1; var scorerIndex = Math.floor(Math.random() * self.homeTeam.players.length); var scorer = self.homeTeam.players[scorerIndex]; self.events.push({ type: "goal", team: self.homeTeam.name, player: scorer.name, minute: minute }); } for (var i = 0; i < self.awayGoals; i++) { var minute = Math.floor(Math.random() * 90) + 1; var scorerIndex = Math.floor(Math.random() * self.awayTeam.players.length); var scorer = self.awayTeam.players[scorerIndex]; self.events.push({ type: "goal", team: self.awayTeam.name, player: scorer.name, minute: minute }); } // Sort events by minute self.events.sort(function (a, b) { return a.minute - b.minute; }); }; self.getEventText = function () { var text = ""; for (var i = 0; i < self.events.length; i++) { var event = self.events[i]; if (event.type === "goal") { text += event.minute + "' GOAL! " + event.player + " (" + event.team + ")\n"; } } return text; }; self.down = function (x, y, obj) { if (!self.isPlayed && currentScreen === "fixtures") { self.simulateMatch(); // Check if this was the selected team's match var isUserTeam = self.homeTeam.name === teams[userTeamIndex].name || self.awayTeam.name === teams[userTeamIndex].name; if (isUserTeam) { showMatchDetails(self); } // Check if all matches for current matchday are played var allPlayed = true; for (var i = 0; i < currentFixtures.length; i++) { if (!currentFixtures[i].isPlayed) { allPlayed = false; break; } } if (allPlayed) { showNextMatchdayButton(); } } }; return self; }); var MatchDetailView = Container.expand(function (match) { var self = Container.call(this); var background = self.attachAsset('field', { anchorX: 0.5, anchorY: 0.5, width: 1800, height: 2400 }); background.alpha = 0.7; var titleText = new Text2(match.homeTeam.name + " vs " + match.awayTeam.name, { size: 60, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.y = -1000; self.addChild(titleText); var scoreText = new Text2(match.homeGoals + " - " + match.awayGoals, { size: 100, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.y = -900; self.addChild(scoreText); var eventsText = new Text2(match.getEventText(), { size: 40, fill: 0xFFFFFF }); eventsText.anchor.set(0.5, 0); eventsText.y = -750; self.addChild(eventsText); var closeButton = new Button("CONTINUE", function () { game.removeChild(self); }); closeButton.y = 900; self.addChild(closeButton); return self; }); var Player = Container.expand(function (playerData) { var self = Container.call(this); self.name = playerData.name; self.position = playerData.position; self.age = playerData.age; self.ovr = playerData.ovr; self.potential = playerData.potential; self.value = playerData.value; self.updateSkills = function () { // Adjust player skills based on age and potential if (self.age < 30 && self.ovr < self.potential) { self.ovr += Math.floor(Math.random() * 3); if (self.ovr > self.potential) { self.ovr = self.potential; } } else if (self.age > 30) { self.ovr -= Math.floor(Math.random() * 2); } // Update player value based on OVR and age var ageModifier = 1; if (self.age > 30) { ageModifier = 0.8; } else if (self.age < 23) { ageModifier = 1.2; } self.value = Math.floor(self.ovr * 100000 * ageModifier); }; return self; }); var Team = Container.expand(function (teamData) { var self = Container.call(this); self.data = teamData; self.name = teamData.name; self.players = teamData.players; self.points = 0; self.wins = 0; self.draws = 0; self.losses = 0; self.goalsFor = 0; self.goalsAgainst = 0; self.calculateTeamStrength = function () { var totalStrength = 0; for (var i = 0; i < self.players.length; i++) { totalStrength += self.players[i].ovr; } return Math.floor(totalStrength / self.players.length); }; self.strength = self.calculateTeamStrength(); return self; }); var TeamCard = Container.expand(function (team, index) { var self = Container.call(this); var isSelected = index === userTeamIndex; var card = self.attachAsset('teamCard', { anchorX: 0.5, anchorY: 0.5 }); if (isSelected) { card.tint = 0x3742fa; } var nameText = new Text2(team.name, { size: 40, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0); nameText.y = -80; self.addChild(nameText); var strengthText = new Text2("Team Rating: " + team.strength, { size: 30, fill: 0xFFFFFF }); strengthText.anchor.set(0.5, 0.5); strengthText.y = 0; self.addChild(strengthText); var positionText = new Text2("", { size: 30, fill: 0xFFFFFF }); positionText.anchor.set(0.5, 1); positionText.y = 70; self.addChild(positionText); self.updatePosition = function (position) { positionText.setText(position + ordinalSuffix(position)); }; self.down = function (x, y, obj) { if (currentScreen === "teamSelection") { userTeamIndex = index; storage.selectedTeam = index; showScreen("mainMenu"); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x005e30 }); /**** * Game Code ****/ // Global Variables var teams = []; var fixtures = []; var userTeamIndex = storage.selectedTeam || 0; var currentScreen = "loading"; var currentFixtures = []; var currentMatchday = storage.matchDay || 1; var season = storage.season || 1; // UI Elements var title = new Text2("Turkish Super League", { size: 90, fill: 0xFFFFFF }); title.anchor.set(0.5, 0); title.y = 150; LK.gui.top.addChild(title); var subtitle = new Text2("Manager Simulation", { size: 60, fill: 0xFFFFFF }); subtitle.anchor.set(0.5, 0); subtitle.y = 250; LK.gui.top.addChild(subtitle); var seasonText = new Text2("Season " + season, { size: 50, fill: 0xFFFFFF }); seasonText.anchor.set(0.5, 0); seasonText.y = 320; LK.gui.top.addChild(seasonText); var matchdayText = new Text2("Matchday " + currentMatchday, { size: 40, fill: 0xFFFFFF }); matchdayText.anchor.set(0.5, 0); matchdayText.y = 380; LK.gui.top.addChild(matchdayText); var statusText = new Text2("", { size: 40, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0); statusText.y = 440; LK.gui.top.addChild(statusText); // Helper Functions function getPoissonRandom(mean) { var L = Math.exp(-mean); var p = 1.0; var k = 0; do { k++; p *= Math.random(); } while (p > L); return k - 1; } function ordinalSuffix(i) { var j = i % 10, k = i % 100; if (j == 1 && k != 11) { return "st"; } if (j == 2 && k != 12) { return "nd"; } if (j == 3 && k != 13) { return "rd"; } return "th"; } function createTeams() { // Initialize with sample Turkish Super League teams // In a real game, this would be loaded from a data file var teamData = [{ name: "Galatasaray", players: generatePlayers(85, 75, 12) }, { name: "Fenerbahçe", players: generatePlayers(84, 76, 12) }, { name: "Beşiktaş", players: generatePlayers(83, 74, 12) }, { name: "Trabzonspor", players: generatePlayers(80, 72, 11) }, { name: "Başakşehir", players: generatePlayers(79, 73, 11) }, { name: "Adana Demirspor", players: generatePlayers(78, 70, 10) }, { name: "Konyaspor", players: generatePlayers(77, 69, 10) }, { name: "Alanyaspor", players: generatePlayers(76, 70, 9) }, { name: "Antalyaspor", players: generatePlayers(75, 69, 9) }, { name: "Kayserispor", players: generatePlayers(74, 68, 8) }, { name: "Gaziantep FK", players: generatePlayers(73, 67, 8) }, { name: "Kasımpaşa", players: generatePlayers(72, 66, 7) }, { name: "Sivasspor", players: generatePlayers(71, 65, 7) }, { name: "Hatayspor", players: generatePlayers(70, 64, 6) }, { name: "Giresunspor", players: generatePlayers(69, 62, 6) }, { name: "Ümraniyespor", players: generatePlayers(68, 60, 5) }, { name: "Ankaragücü", players: generatePlayers(67, 61, 5) }, { name: "İstanbulspor", players: generatePlayers(66, 60, 4) }]; for (var i = 0; i < teamData.length; i++) { var team = new Team(teamData[i]); teams.push(team); } // Save team data to storage if (!storage.teamData) { storage.teamData = teamData; } } function generatePlayers(maxRating, avgRating, stars) { var players = []; var positions = ["GK", "DEF", "MID", "FWD"]; var numPlayers = 24; // Create 3 star players for (var i = 0; i < stars; i++) { var rating = Math.floor(Math.random() * 5) + maxRating - 5; var age = Math.floor(Math.random() * 8) + 25; var position = positions[Math.floor(Math.random() * 3) + 1]; // Don't make star GKs var potential = rating + Math.floor(Math.random() * 5); players.push(new Player({ name: "Star Player " + (i + 1), position: position, age: age, ovr: rating, potential: potential, value: rating * 100000 })); } // Fill the rest with regular players for (var i = stars; i < numPlayers; i++) { var rating = Math.floor(Math.random() * 10) + avgRating - 5; var age = Math.floor(Math.random() * 15) + 18; var position = positions[Math.floor(Math.random() * positions.length)]; var potential = rating; if (age < 25) { potential += Math.floor(Math.random() * 10); } players.push(new Player({ name: "Player " + (i + 1), position: position, age: age, ovr: rating, potential: potential, value: rating * 50000 })); } return players; } function createFixtures() { fixtures = []; // Generate fixtures for a round-robin tournament // Each team plays against every other team twice (home and away) var matchdays = (teams.length - 1) * 2; for (var matchday = 1; matchday <= matchdays; matchday++) { fixtures[matchday] = []; for (var i = 0; i < teams.length / 2; i++) { var home, away; if (matchday <= teams.length - 1) { // First half of the season home = (matchday + i) % (teams.length - 1); away = (teams.length - 1 - i + matchday) % (teams.length - 1); // Last team stays fixed if (i === 0) { away = teams.length - 1; } } else { // Second half of the season - reverse home/away var firstHalfMatchday = matchday - (teams.length - 1); away = (firstHalfMatchday + i) % (teams.length - 1); home = (teams.length - 1 - i + firstHalfMatchday) % (teams.length - 1); // Last team stays fixed if (i === 0) { home = teams.length - 1; } } var match = new Match(teams[home], teams[away]); fixtures[matchday].push(match); } } } function showScreen(screenName) { currentScreen = screenName; // Clear the game container first while (game.children.length > 0) { game.removeChild(game.children[0]); } // Update UI elements title.visible = true; subtitle.visible = true; if (screenName === "loading") { statusText.setText("Loading game data..."); LK.setTimeout(function () { if (!storage.teamData) { showScreen("teamSelection"); } else { showScreen("mainMenu"); } }, 1000); } else if (screenName === "teamSelection") { subtitle.setText("Select Your Team"); statusText.setText(""); var xPos = -700; var yPos = 600; var counter = 0; for (var i = 0; i < teams.length; i++) { var teamCard = new TeamCard(teams[i], i); teamCard.x = xPos + counter % 4 * 450; teamCard.y = yPos + Math.floor(counter / 4) * 250; game.addChild(teamCard); counter++; } } else if (screenName === "mainMenu") { subtitle.setText("Main Menu"); statusText.setText("Managing " + teams[userTeamIndex].name); var viewTableButton = new Button("LEAGUE TABLE", function () { showScreen("table"); }); viewTableButton.y = 700; game.addChild(viewTableButton); var viewFixturesButton = new Button("FIXTURES", function () { showScreen("fixtures"); }); viewFixturesButton.y = 850; game.addChild(viewFixturesButton); var viewSquadButton = new Button("SQUAD", function () { showScreen("squad"); }); viewSquadButton.y = 1000; game.addChild(viewSquadButton); // Add a field background var field = LK.getAsset('field', { anchorX: 0.5, anchorY: 0.5 }); field.alpha = 0.3; game.addChildAt(field, 0); field.x = 2048 / 2; field.y = 2732 / 2; // Start ambient sound LK.playMusic('stadiumAmbience'); } else if (screenName === "table") { subtitle.setText("League Table"); // Sort teams by points, goal difference, goals scored var sortedTeams = teams.slice(); sortedTeams.sort(function (a, b) { if (a.points !== b.points) { return b.points - a.points; } var aGD = a.goalsFor - a.goalsAgainst; var bGD = b.goalsFor - b.goalsAgainst; if (aGD !== bGD) { return bGD - aGD; } return b.goalsFor - a.goalsFor; }); var tableY = 500; var headerText = new Text2("Pos Team P W D L GF GA GD Pts", { size: 30, fill: 0xFFFFFF }); headerText.anchor.set(0, 0.5); headerText.x = 200; headerText.y = tableY; game.addChild(headerText); for (var i = 0; i < sortedTeams.length; i++) { var team = sortedTeams[i]; var played = team.wins + team.draws + team.losses; var gd = team.goalsFor - team.goalsAgainst; var gdSign = gd > 0 ? "+" : ""; var highlight = team === teams[userTeamIndex]; var rowText = new Text2((i + 1).toString().padEnd(3) + team.name.padEnd(20) + played.toString().padEnd(5) + team.wins.toString().padEnd(5) + team.draws.toString().padEnd(5) + team.losses.toString().padEnd(5) + team.goalsFor.toString().padEnd(5) + team.goalsAgainst.toString().padEnd(5) + (gdSign + gd).toString().padEnd(5) + team.points.toString(), { size: 28, fill: highlight ? "#ffff00" : "#ffffff" }); rowText.anchor.set(0, 0.5); rowText.x = 200; rowText.y = tableY + (i + 1) * 50; game.addChild(rowText); // Update TeamCard position information for (var j = 0; j < game.children.length; j++) { if (game.children[j] instanceof TeamCard && game.children[j].data === team) { game.children[j].updatePosition(i + 1); } } } var backButton = new Button("BACK", function () { showScreen("mainMenu"); }); backButton.y = 2400; game.addChild(backButton); } else if (screenName === "fixtures") { subtitle.setText("Fixtures - Matchday " + currentMatchday); // Display current matchday fixtures currentFixtures = fixtures[currentMatchday]; var startY = 600; for (var i = 0; i < currentFixtures.length; i++) { var match = currentFixtures[i]; match.x = 2048 / 2; match.y = startY + i * 250; game.addChild(match); } var backButton = new Button("BACK", function () { showScreen("mainMenu"); }); backButton.y = 2400; game.addChild(backButton); // Show "Next Matchday" button if all matches are played var allPlayed = true; for (var i = 0; i < currentFixtures.length; i++) { if (!currentFixtures[i].isPlayed) { allPlayed = false; break; } } if (allPlayed) { showNextMatchdayButton(); } } else if (screenName === "squad") { subtitle.setText("Squad - " + teams[userTeamIndex].name); var team = teams[userTeamIndex]; var startY = 600; var headerText = new Text2("Name Pos Age OVR POT Value", { size: 30, fill: 0xFFFFFF }); headerText.anchor.set(0, 0.5); headerText.x = 200; headerText.y = startY - 60; game.addChild(headerText); // Sort players by overall rating var sortedPlayers = team.players.slice(); sortedPlayers.sort(function (a, b) { return b.ovr - a.ovr; }); for (var i = 0; i < sortedPlayers.length; i++) { var player = sortedPlayers[i]; var valueFormatted = (player.value / 1000000).toFixed(1) + "M"; var rowText = new Text2(player.name.padEnd(18) + player.position.padEnd(6) + player.age.toString().padEnd(6) + player.ovr.toString().padEnd(6) + player.potential.toString().padEnd(6) + valueFormatted, { size: 28, fill: 0xFFFFFF }); rowText.anchor.set(0, 0.5); rowText.x = 200; rowText.y = startY + i * 50; game.addChild(rowText); } var backButton = new Button("BACK", function () { showScreen("mainMenu"); }); backButton.y = 2400; game.addChild(backButton); } } function showNextMatchdayButton() { var nextButton = new Button("NEXT MATCHDAY", function () { currentMatchday++; if (currentMatchday > (teams.length - 1) * 2) { // End of season endSeason(); } else { storage.matchDay = currentMatchday; matchdayText.setText("Matchday " + currentMatchday); showScreen("fixtures"); } }); nextButton.y = 2250; game.addChild(nextButton); } function showMatchDetails(match) { var detailView = new MatchDetailView(match); detailView.x = 2048 / 2; detailView.y = 2732 / 2; game.addChild(detailView); if (match.homeGoals > 0 || match.awayGoals > 0) { LK.getSound('goal').play(); } } function endSeason() { season++; currentMatchday = 1; storage.season = season; storage.matchDay = currentMatchday; // Reset team stats but keep player development for (var i = 0; i < teams.length; i++) { teams[i].points = 0; teams[i].wins = 0; teams[i].draws = 0; teams[i].losses = 0; teams[i].goalsFor = 0; teams[i].goalsAgainst = 0; // Age players and develop them for (var j = 0; j < teams[i].players.length; j++) { var player = teams[i].players[j]; player.age++; player.updateSkills(); } } // Regenerate fixtures for the new season createFixtures(); // Update UI seasonText.setText("Season " + season); matchdayText.setText("Matchday " + currentMatchday); // Show season summary var summaryView = new Container(); var background = LK.getAsset('field', { anchorX: 0.5, anchorY: 0.5 }); background.alpha = 0.7; summaryView.addChild(background); var titleText = new Text2("Season " + (season - 1) + " Complete!", { size: 70, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.y = -1000; summaryView.addChild(titleText); // Sort teams by points to find champion var sortedTeams = teams.slice(); sortedTeams.sort(function (a, b) { if (a.points !== b.points) { return b.points - a.points; } var aGD = a.goalsFor - a.goalsAgainst; var bGD = b.goalsFor - b.goalsAgainst; if (aGD !== bGD) { return bGD - aGD; } return b.goalsFor - a.goalsFor; }); var championText = new Text2("Champion: " + sortedTeams[0].name, { size: 60, fill: 0xFFFF00 }); championText.anchor.set(0.5, 0); championText.y = -900; summaryView.addChild(championText); var userTeamPos = sortedTeams.indexOf(teams[userTeamIndex]) + 1; var userTeamText = new Text2("Your Team: " + teams[userTeamIndex].name + " (" + userTeamPos + ordinalSuffix(userTeamPos) + " place)", { size: 50, fill: 0xFFFFFF }); userTeamText.anchor.set(0.5, 0); userTeamText.y = -800; summaryView.addChild(userTeamText); var continueButton = new Button("CONTINUE TO SEASON " + season, function () { game.removeChild(summaryView); showScreen("fixtures"); }); continueButton.y = 900; summaryView.addChild(continueButton); summaryView.x = 2048 / 2; summaryView.y = 2732 / 2; game.addChild(summaryView); } // Initialize Game function initGame() { // Create teams and fixtures createTeams(); createFixtures(); // Start with team selection or main menu showScreen("loading"); } // Game update game.update = function () { // Nothing to do in the update loop for now // This simulation game is mostly event-driven }; // Start the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
selectedTeam: 0,
season: 1,
matchDay: 1,
teamData: undefined
});
/****
* Classes
****/
var Button = Container.expand(function (label, callback, width, height) {
var self = Container.call(this);
width = width || 300;
height = height || 120;
var button = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: height
});
var labelText = new Text2(label, {
size: 40,
fill: 0xFFFFFF
});
labelText.anchor.set(0.5, 0.5);
self.addChild(labelText);
self.setLabel = function (newLabel) {
labelText.setText(newLabel);
};
self.down = function (x, y, obj) {
// Visual feedback
button.tint = 0x3742fa;
if (callback) {
callback();
}
};
self.up = function (x, y, obj) {
button.tint = 0xffffff;
};
return self;
});
var Match = Container.expand(function (homeTeam, awayTeam) {
var self = Container.call(this);
self.homeTeam = homeTeam;
self.awayTeam = awayTeam;
self.homeGoals = 0;
self.awayGoals = 0;
self.isPlayed = false;
self.matchTime = 0;
self.events = [];
var matchCard = self.attachAsset('matchCard', {
anchorX: 0.5,
anchorY: 0.5
});
var homeText = new Text2(homeTeam.name, {
size: 50,
fill: 0xFFFFFF
});
homeText.anchor.set(1, 0.5);
homeText.x = -100;
self.addChild(homeText);
var scoreText = new Text2("vs", {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0.5);
self.addChild(scoreText);
var awayText = new Text2(awayTeam.name, {
size: 50,
fill: 0xFFFFFF
});
awayText.anchor.set(0, 0.5);
awayText.x = 100;
self.addChild(awayText);
self.simulateMatch = function () {
if (self.isPlayed) {
return;
}
LK.getSound('whistle').play();
var homeStrength = self.homeTeam.strength;
var awayStrength = self.awayTeam.strength;
// Calculate home advantage (about 10% boost)
homeStrength = Math.floor(homeStrength * 1.1);
// Calculate expected goals based on team strength
var homeExpectedGoals = homeStrength / 20 + Math.random() * 1.5;
var awayExpectedGoals = awayStrength / 25 + Math.random() * 1.2;
// Generate actual goals with Poisson-like distribution
self.homeGoals = Math.floor(getPoissonRandom(homeExpectedGoals));
self.awayGoals = Math.floor(getPoissonRandom(awayExpectedGoals));
// Update team statistics
self.homeTeam.goalsFor += self.homeGoals;
self.homeTeam.goalsAgainst += self.awayGoals;
self.awayTeam.goalsFor += self.awayGoals;
self.awayTeam.goalsAgainst += self.homeGoals;
if (self.homeGoals > self.awayGoals) {
self.homeTeam.points += 3;
self.homeTeam.wins += 1;
self.awayTeam.losses += 1;
} else if (self.homeGoals < self.awayGoals) {
self.awayTeam.points += 3;
self.awayTeam.wins += 1;
self.homeTeam.losses += 1;
} else {
self.homeTeam.points += 1;
self.awayTeam.points += 1;
self.homeTeam.draws += 1;
self.awayTeam.draws += 1;
}
// Generate match events
self.generateEvents();
// Update the score display
scoreText.setText(self.homeGoals + " - " + self.awayGoals);
self.isPlayed = true;
};
self.generateEvents = function () {
// Generate goal events
for (var i = 0; i < self.homeGoals; i++) {
var minute = Math.floor(Math.random() * 90) + 1;
var scorerIndex = Math.floor(Math.random() * self.homeTeam.players.length);
var scorer = self.homeTeam.players[scorerIndex];
self.events.push({
type: "goal",
team: self.homeTeam.name,
player: scorer.name,
minute: minute
});
}
for (var i = 0; i < self.awayGoals; i++) {
var minute = Math.floor(Math.random() * 90) + 1;
var scorerIndex = Math.floor(Math.random() * self.awayTeam.players.length);
var scorer = self.awayTeam.players[scorerIndex];
self.events.push({
type: "goal",
team: self.awayTeam.name,
player: scorer.name,
minute: minute
});
}
// Sort events by minute
self.events.sort(function (a, b) {
return a.minute - b.minute;
});
};
self.getEventText = function () {
var text = "";
for (var i = 0; i < self.events.length; i++) {
var event = self.events[i];
if (event.type === "goal") {
text += event.minute + "' GOAL! " + event.player + " (" + event.team + ")\n";
}
}
return text;
};
self.down = function (x, y, obj) {
if (!self.isPlayed && currentScreen === "fixtures") {
self.simulateMatch();
// Check if this was the selected team's match
var isUserTeam = self.homeTeam.name === teams[userTeamIndex].name || self.awayTeam.name === teams[userTeamIndex].name;
if (isUserTeam) {
showMatchDetails(self);
}
// Check if all matches for current matchday are played
var allPlayed = true;
for (var i = 0; i < currentFixtures.length; i++) {
if (!currentFixtures[i].isPlayed) {
allPlayed = false;
break;
}
}
if (allPlayed) {
showNextMatchdayButton();
}
}
};
return self;
});
var MatchDetailView = Container.expand(function (match) {
var self = Container.call(this);
var background = self.attachAsset('field', {
anchorX: 0.5,
anchorY: 0.5,
width: 1800,
height: 2400
});
background.alpha = 0.7;
var titleText = new Text2(match.homeTeam.name + " vs " + match.awayTeam.name, {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.y = -1000;
self.addChild(titleText);
var scoreText = new Text2(match.homeGoals + " - " + match.awayGoals, {
size: 100,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.y = -900;
self.addChild(scoreText);
var eventsText = new Text2(match.getEventText(), {
size: 40,
fill: 0xFFFFFF
});
eventsText.anchor.set(0.5, 0);
eventsText.y = -750;
self.addChild(eventsText);
var closeButton = new Button("CONTINUE", function () {
game.removeChild(self);
});
closeButton.y = 900;
self.addChild(closeButton);
return self;
});
var Player = Container.expand(function (playerData) {
var self = Container.call(this);
self.name = playerData.name;
self.position = playerData.position;
self.age = playerData.age;
self.ovr = playerData.ovr;
self.potential = playerData.potential;
self.value = playerData.value;
self.updateSkills = function () {
// Adjust player skills based on age and potential
if (self.age < 30 && self.ovr < self.potential) {
self.ovr += Math.floor(Math.random() * 3);
if (self.ovr > self.potential) {
self.ovr = self.potential;
}
} else if (self.age > 30) {
self.ovr -= Math.floor(Math.random() * 2);
}
// Update player value based on OVR and age
var ageModifier = 1;
if (self.age > 30) {
ageModifier = 0.8;
} else if (self.age < 23) {
ageModifier = 1.2;
}
self.value = Math.floor(self.ovr * 100000 * ageModifier);
};
return self;
});
var Team = Container.expand(function (teamData) {
var self = Container.call(this);
self.data = teamData;
self.name = teamData.name;
self.players = teamData.players;
self.points = 0;
self.wins = 0;
self.draws = 0;
self.losses = 0;
self.goalsFor = 0;
self.goalsAgainst = 0;
self.calculateTeamStrength = function () {
var totalStrength = 0;
for (var i = 0; i < self.players.length; i++) {
totalStrength += self.players[i].ovr;
}
return Math.floor(totalStrength / self.players.length);
};
self.strength = self.calculateTeamStrength();
return self;
});
var TeamCard = Container.expand(function (team, index) {
var self = Container.call(this);
var isSelected = index === userTeamIndex;
var card = self.attachAsset('teamCard', {
anchorX: 0.5,
anchorY: 0.5
});
if (isSelected) {
card.tint = 0x3742fa;
}
var nameText = new Text2(team.name, {
size: 40,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0);
nameText.y = -80;
self.addChild(nameText);
var strengthText = new Text2("Team Rating: " + team.strength, {
size: 30,
fill: 0xFFFFFF
});
strengthText.anchor.set(0.5, 0.5);
strengthText.y = 0;
self.addChild(strengthText);
var positionText = new Text2("", {
size: 30,
fill: 0xFFFFFF
});
positionText.anchor.set(0.5, 1);
positionText.y = 70;
self.addChild(positionText);
self.updatePosition = function (position) {
positionText.setText(position + ordinalSuffix(position));
};
self.down = function (x, y, obj) {
if (currentScreen === "teamSelection") {
userTeamIndex = index;
storage.selectedTeam = index;
showScreen("mainMenu");
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x005e30
});
/****
* Game Code
****/
// Global Variables
var teams = [];
var fixtures = [];
var userTeamIndex = storage.selectedTeam || 0;
var currentScreen = "loading";
var currentFixtures = [];
var currentMatchday = storage.matchDay || 1;
var season = storage.season || 1;
// UI Elements
var title = new Text2("Turkish Super League", {
size: 90,
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0);
title.y = 150;
LK.gui.top.addChild(title);
var subtitle = new Text2("Manager Simulation", {
size: 60,
fill: 0xFFFFFF
});
subtitle.anchor.set(0.5, 0);
subtitle.y = 250;
LK.gui.top.addChild(subtitle);
var seasonText = new Text2("Season " + season, {
size: 50,
fill: 0xFFFFFF
});
seasonText.anchor.set(0.5, 0);
seasonText.y = 320;
LK.gui.top.addChild(seasonText);
var matchdayText = new Text2("Matchday " + currentMatchday, {
size: 40,
fill: 0xFFFFFF
});
matchdayText.anchor.set(0.5, 0);
matchdayText.y = 380;
LK.gui.top.addChild(matchdayText);
var statusText = new Text2("", {
size: 40,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0);
statusText.y = 440;
LK.gui.top.addChild(statusText);
// Helper Functions
function getPoissonRandom(mean) {
var L = Math.exp(-mean);
var p = 1.0;
var k = 0;
do {
k++;
p *= Math.random();
} while (p > L);
return k - 1;
}
function ordinalSuffix(i) {
var j = i % 10,
k = i % 100;
if (j == 1 && k != 11) {
return "st";
}
if (j == 2 && k != 12) {
return "nd";
}
if (j == 3 && k != 13) {
return "rd";
}
return "th";
}
function createTeams() {
// Initialize with sample Turkish Super League teams
// In a real game, this would be loaded from a data file
var teamData = [{
name: "Galatasaray",
players: generatePlayers(85, 75, 12)
}, {
name: "Fenerbahçe",
players: generatePlayers(84, 76, 12)
}, {
name: "Beşiktaş",
players: generatePlayers(83, 74, 12)
}, {
name: "Trabzonspor",
players: generatePlayers(80, 72, 11)
}, {
name: "Başakşehir",
players: generatePlayers(79, 73, 11)
}, {
name: "Adana Demirspor",
players: generatePlayers(78, 70, 10)
}, {
name: "Konyaspor",
players: generatePlayers(77, 69, 10)
}, {
name: "Alanyaspor",
players: generatePlayers(76, 70, 9)
}, {
name: "Antalyaspor",
players: generatePlayers(75, 69, 9)
}, {
name: "Kayserispor",
players: generatePlayers(74, 68, 8)
}, {
name: "Gaziantep FK",
players: generatePlayers(73, 67, 8)
}, {
name: "Kasımpaşa",
players: generatePlayers(72, 66, 7)
}, {
name: "Sivasspor",
players: generatePlayers(71, 65, 7)
}, {
name: "Hatayspor",
players: generatePlayers(70, 64, 6)
}, {
name: "Giresunspor",
players: generatePlayers(69, 62, 6)
}, {
name: "Ümraniyespor",
players: generatePlayers(68, 60, 5)
}, {
name: "Ankaragücü",
players: generatePlayers(67, 61, 5)
}, {
name: "İstanbulspor",
players: generatePlayers(66, 60, 4)
}];
for (var i = 0; i < teamData.length; i++) {
var team = new Team(teamData[i]);
teams.push(team);
}
// Save team data to storage
if (!storage.teamData) {
storage.teamData = teamData;
}
}
function generatePlayers(maxRating, avgRating, stars) {
var players = [];
var positions = ["GK", "DEF", "MID", "FWD"];
var numPlayers = 24;
// Create 3 star players
for (var i = 0; i < stars; i++) {
var rating = Math.floor(Math.random() * 5) + maxRating - 5;
var age = Math.floor(Math.random() * 8) + 25;
var position = positions[Math.floor(Math.random() * 3) + 1]; // Don't make star GKs
var potential = rating + Math.floor(Math.random() * 5);
players.push(new Player({
name: "Star Player " + (i + 1),
position: position,
age: age,
ovr: rating,
potential: potential,
value: rating * 100000
}));
}
// Fill the rest with regular players
for (var i = stars; i < numPlayers; i++) {
var rating = Math.floor(Math.random() * 10) + avgRating - 5;
var age = Math.floor(Math.random() * 15) + 18;
var position = positions[Math.floor(Math.random() * positions.length)];
var potential = rating;
if (age < 25) {
potential += Math.floor(Math.random() * 10);
}
players.push(new Player({
name: "Player " + (i + 1),
position: position,
age: age,
ovr: rating,
potential: potential,
value: rating * 50000
}));
}
return players;
}
function createFixtures() {
fixtures = [];
// Generate fixtures for a round-robin tournament
// Each team plays against every other team twice (home and away)
var matchdays = (teams.length - 1) * 2;
for (var matchday = 1; matchday <= matchdays; matchday++) {
fixtures[matchday] = [];
for (var i = 0; i < teams.length / 2; i++) {
var home, away;
if (matchday <= teams.length - 1) {
// First half of the season
home = (matchday + i) % (teams.length - 1);
away = (teams.length - 1 - i + matchday) % (teams.length - 1);
// Last team stays fixed
if (i === 0) {
away = teams.length - 1;
}
} else {
// Second half of the season - reverse home/away
var firstHalfMatchday = matchday - (teams.length - 1);
away = (firstHalfMatchday + i) % (teams.length - 1);
home = (teams.length - 1 - i + firstHalfMatchday) % (teams.length - 1);
// Last team stays fixed
if (i === 0) {
home = teams.length - 1;
}
}
var match = new Match(teams[home], teams[away]);
fixtures[matchday].push(match);
}
}
}
function showScreen(screenName) {
currentScreen = screenName;
// Clear the game container first
while (game.children.length > 0) {
game.removeChild(game.children[0]);
}
// Update UI elements
title.visible = true;
subtitle.visible = true;
if (screenName === "loading") {
statusText.setText("Loading game data...");
LK.setTimeout(function () {
if (!storage.teamData) {
showScreen("teamSelection");
} else {
showScreen("mainMenu");
}
}, 1000);
} else if (screenName === "teamSelection") {
subtitle.setText("Select Your Team");
statusText.setText("");
var xPos = -700;
var yPos = 600;
var counter = 0;
for (var i = 0; i < teams.length; i++) {
var teamCard = new TeamCard(teams[i], i);
teamCard.x = xPos + counter % 4 * 450;
teamCard.y = yPos + Math.floor(counter / 4) * 250;
game.addChild(teamCard);
counter++;
}
} else if (screenName === "mainMenu") {
subtitle.setText("Main Menu");
statusText.setText("Managing " + teams[userTeamIndex].name);
var viewTableButton = new Button("LEAGUE TABLE", function () {
showScreen("table");
});
viewTableButton.y = 700;
game.addChild(viewTableButton);
var viewFixturesButton = new Button("FIXTURES", function () {
showScreen("fixtures");
});
viewFixturesButton.y = 850;
game.addChild(viewFixturesButton);
var viewSquadButton = new Button("SQUAD", function () {
showScreen("squad");
});
viewSquadButton.y = 1000;
game.addChild(viewSquadButton);
// Add a field background
var field = LK.getAsset('field', {
anchorX: 0.5,
anchorY: 0.5
});
field.alpha = 0.3;
game.addChildAt(field, 0);
field.x = 2048 / 2;
field.y = 2732 / 2;
// Start ambient sound
LK.playMusic('stadiumAmbience');
} else if (screenName === "table") {
subtitle.setText("League Table");
// Sort teams by points, goal difference, goals scored
var sortedTeams = teams.slice();
sortedTeams.sort(function (a, b) {
if (a.points !== b.points) {
return b.points - a.points;
}
var aGD = a.goalsFor - a.goalsAgainst;
var bGD = b.goalsFor - b.goalsAgainst;
if (aGD !== bGD) {
return bGD - aGD;
}
return b.goalsFor - a.goalsFor;
});
var tableY = 500;
var headerText = new Text2("Pos Team P W D L GF GA GD Pts", {
size: 30,
fill: 0xFFFFFF
});
headerText.anchor.set(0, 0.5);
headerText.x = 200;
headerText.y = tableY;
game.addChild(headerText);
for (var i = 0; i < sortedTeams.length; i++) {
var team = sortedTeams[i];
var played = team.wins + team.draws + team.losses;
var gd = team.goalsFor - team.goalsAgainst;
var gdSign = gd > 0 ? "+" : "";
var highlight = team === teams[userTeamIndex];
var rowText = new Text2((i + 1).toString().padEnd(3) + team.name.padEnd(20) + played.toString().padEnd(5) + team.wins.toString().padEnd(5) + team.draws.toString().padEnd(5) + team.losses.toString().padEnd(5) + team.goalsFor.toString().padEnd(5) + team.goalsAgainst.toString().padEnd(5) + (gdSign + gd).toString().padEnd(5) + team.points.toString(), {
size: 28,
fill: highlight ? "#ffff00" : "#ffffff"
});
rowText.anchor.set(0, 0.5);
rowText.x = 200;
rowText.y = tableY + (i + 1) * 50;
game.addChild(rowText);
// Update TeamCard position information
for (var j = 0; j < game.children.length; j++) {
if (game.children[j] instanceof TeamCard && game.children[j].data === team) {
game.children[j].updatePosition(i + 1);
}
}
}
var backButton = new Button("BACK", function () {
showScreen("mainMenu");
});
backButton.y = 2400;
game.addChild(backButton);
} else if (screenName === "fixtures") {
subtitle.setText("Fixtures - Matchday " + currentMatchday);
// Display current matchday fixtures
currentFixtures = fixtures[currentMatchday];
var startY = 600;
for (var i = 0; i < currentFixtures.length; i++) {
var match = currentFixtures[i];
match.x = 2048 / 2;
match.y = startY + i * 250;
game.addChild(match);
}
var backButton = new Button("BACK", function () {
showScreen("mainMenu");
});
backButton.y = 2400;
game.addChild(backButton);
// Show "Next Matchday" button if all matches are played
var allPlayed = true;
for (var i = 0; i < currentFixtures.length; i++) {
if (!currentFixtures[i].isPlayed) {
allPlayed = false;
break;
}
}
if (allPlayed) {
showNextMatchdayButton();
}
} else if (screenName === "squad") {
subtitle.setText("Squad - " + teams[userTeamIndex].name);
var team = teams[userTeamIndex];
var startY = 600;
var headerText = new Text2("Name Pos Age OVR POT Value", {
size: 30,
fill: 0xFFFFFF
});
headerText.anchor.set(0, 0.5);
headerText.x = 200;
headerText.y = startY - 60;
game.addChild(headerText);
// Sort players by overall rating
var sortedPlayers = team.players.slice();
sortedPlayers.sort(function (a, b) {
return b.ovr - a.ovr;
});
for (var i = 0; i < sortedPlayers.length; i++) {
var player = sortedPlayers[i];
var valueFormatted = (player.value / 1000000).toFixed(1) + "M";
var rowText = new Text2(player.name.padEnd(18) + player.position.padEnd(6) + player.age.toString().padEnd(6) + player.ovr.toString().padEnd(6) + player.potential.toString().padEnd(6) + valueFormatted, {
size: 28,
fill: 0xFFFFFF
});
rowText.anchor.set(0, 0.5);
rowText.x = 200;
rowText.y = startY + i * 50;
game.addChild(rowText);
}
var backButton = new Button("BACK", function () {
showScreen("mainMenu");
});
backButton.y = 2400;
game.addChild(backButton);
}
}
function showNextMatchdayButton() {
var nextButton = new Button("NEXT MATCHDAY", function () {
currentMatchday++;
if (currentMatchday > (teams.length - 1) * 2) {
// End of season
endSeason();
} else {
storage.matchDay = currentMatchday;
matchdayText.setText("Matchday " + currentMatchday);
showScreen("fixtures");
}
});
nextButton.y = 2250;
game.addChild(nextButton);
}
function showMatchDetails(match) {
var detailView = new MatchDetailView(match);
detailView.x = 2048 / 2;
detailView.y = 2732 / 2;
game.addChild(detailView);
if (match.homeGoals > 0 || match.awayGoals > 0) {
LK.getSound('goal').play();
}
}
function endSeason() {
season++;
currentMatchday = 1;
storage.season = season;
storage.matchDay = currentMatchday;
// Reset team stats but keep player development
for (var i = 0; i < teams.length; i++) {
teams[i].points = 0;
teams[i].wins = 0;
teams[i].draws = 0;
teams[i].losses = 0;
teams[i].goalsFor = 0;
teams[i].goalsAgainst = 0;
// Age players and develop them
for (var j = 0; j < teams[i].players.length; j++) {
var player = teams[i].players[j];
player.age++;
player.updateSkills();
}
}
// Regenerate fixtures for the new season
createFixtures();
// Update UI
seasonText.setText("Season " + season);
matchdayText.setText("Matchday " + currentMatchday);
// Show season summary
var summaryView = new Container();
var background = LK.getAsset('field', {
anchorX: 0.5,
anchorY: 0.5
});
background.alpha = 0.7;
summaryView.addChild(background);
var titleText = new Text2("Season " + (season - 1) + " Complete!", {
size: 70,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.y = -1000;
summaryView.addChild(titleText);
// Sort teams by points to find champion
var sortedTeams = teams.slice();
sortedTeams.sort(function (a, b) {
if (a.points !== b.points) {
return b.points - a.points;
}
var aGD = a.goalsFor - a.goalsAgainst;
var bGD = b.goalsFor - b.goalsAgainst;
if (aGD !== bGD) {
return bGD - aGD;
}
return b.goalsFor - a.goalsFor;
});
var championText = new Text2("Champion: " + sortedTeams[0].name, {
size: 60,
fill: 0xFFFF00
});
championText.anchor.set(0.5, 0);
championText.y = -900;
summaryView.addChild(championText);
var userTeamPos = sortedTeams.indexOf(teams[userTeamIndex]) + 1;
var userTeamText = new Text2("Your Team: " + teams[userTeamIndex].name + " (" + userTeamPos + ordinalSuffix(userTeamPos) + " place)", {
size: 50,
fill: 0xFFFFFF
});
userTeamText.anchor.set(0.5, 0);
userTeamText.y = -800;
summaryView.addChild(userTeamText);
var continueButton = new Button("CONTINUE TO SEASON " + season, function () {
game.removeChild(summaryView);
showScreen("fixtures");
});
continueButton.y = 900;
summaryView.addChild(continueButton);
summaryView.x = 2048 / 2;
summaryView.y = 2732 / 2;
game.addChild(summaryView);
}
// Initialize Game
function initGame() {
// Create teams and fixtures
createTeams();
createFixtures();
// Start with team selection or main menu
showScreen("loading");
}
// Game update
game.update = function () {
// Nothing to do in the update loop for now
// This simulation game is mostly event-driven
};
// Start the game
initGame();