Code edit (1 edits merged)
Please save this source code
User prompt
Lean Factory Challenge
Initial prompt
Game Title: Lean Factory Challenge Goal: Teach players the basics of lean manufacturing through simple, interactive tasks in a small factory setting. 🏭 Game Concept: The player is hired as a Lean Coordinator in a small factory. The factory has many problems: too much inventory, messy workstations, delays, and quality issues. The player's job is to fix these problems step by step using lean tools. 🧩 Game Structure: Level 1: 5S Mini Game Clean and organize a messy workstation Sort items, label tools, and make the area efficient Score based on speed and correct placement Level 2: Find the Waste Walk through the production area Click on types of waste (e.g., waiting, motion, overproduction) Each correct click gives points and an explanation Level 3: Simple Kaizen Choose a small process (like packaging) Make 3 simple changes to reduce time or errors Before/After comparison shown visually Level 4: Kanban Board Setup Drag and drop cards on a Kanban board Organize the flow of materials to reduce excess inventory Final Challenge: Improve OEE Monitor machine data (availability, performance, quality) Make basic improvements and reach 85% OEE 👥 Characters: Supervisor: Gives tasks and feedback Worker: Explains daily problems You (the player): Solve problems using lean thinking 🧮 Scoring: Points for each correct action or decision Bonus for finishing tasks quickly and with less waste Final score shows your "Lean Score" from 0 to 100 🎮 Game Style: 2D, colorful, user-friendly interface Click-based actions, drag-and-drop tools Pop-up tips for learning while playing
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function (buttonText, callback) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonLabel = new Text2(buttonText, {
size: 32,
fill: 0xFFFFFF
});
buttonLabel.anchor.set(0.5, 0.5);
self.addChild(buttonLabel);
self.callback = callback;
self.down = function (x, y, obj) {
LK.getSound('click').play();
if (self.callback) {
self.callback();
}
};
return self;
});
var KanbanCard = Container.expand(function (cardText) {
var self = Container.call(this);
var cardGraphics = self.attachAsset('kanbanCard', {
anchorX: 0.5,
anchorY: 0.5
});
self.cardText = cardText || 'Task';
self.isPlaced = false;
self.isDragging = false;
var cardLabel = new Text2(self.cardText, {
size: 24,
fill: 0x000000
});
cardLabel.anchor.set(0.5, 0.5);
self.addChild(cardLabel);
self.down = function (x, y, obj) {
self.isDragging = true;
LK.getSound('click').play();
};
return self;
});
var Tool = Container.expand(function (toolType, targetX, targetY) {
var self = Container.call(this);
var toolGraphics = self.attachAsset('tool', {
anchorX: 0.5,
anchorY: 0.5
});
self.toolType = toolType || 'wrench';
self.targetX = targetX || 0;
self.targetY = targetY || 0;
self.isCorrectlyPlaced = false;
self.isDragging = false;
// Visual feedback for correct placement
self.checkPlacement = function () {
var distance = Math.sqrt(Math.pow(self.x - self.targetX, 2) + Math.pow(self.y - self.targetY, 2));
if (distance < 50) {
self.isCorrectlyPlaced = true;
toolGraphics.tint = 0x2ECC71; // Green tint
return true;
} else {
self.isCorrectlyPlaced = false;
toolGraphics.tint = 0xFFFFFF; // Normal color
return false;
}
};
self.down = function (x, y, obj) {
self.isDragging = true;
LK.getSound('click').play();
};
return self;
});
var WasteItem = Container.expand(function (wasteType) {
var self = Container.call(this);
var wasteGraphics = self.attachAsset('waste', {
anchorX: 0.5,
anchorY: 0.5
});
self.wasteType = wasteType || 'waiting';
self.isIdentified = false;
// Different colors for different waste types
if (wasteType === 'waiting') {
wasteGraphics.tint = 0xFF6B6B; // Red
} else if (wasteType === 'motion') {
wasteGraphics.tint = 0xFFD93D; // Yellow
} else if (wasteType === 'overproduction') {
wasteGraphics.tint = 0x9B59B6; // Purple
}
self.down = function (x, y, obj) {
if (!self.isIdentified) {
self.isIdentified = true;
wasteGraphics.alpha = 0.5;
currentScore += 10;
LK.getSound('success').play();
updateScore();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xF0F0F0
});
/****
* Game Code
****/
// Game state variables
var currentLevel = storage.currentLevel || 1;
var currentScore = 0;
var totalScore = storage.totalScore || 0;
var gameStarted = false;
var levelComplete = false;
var draggedObject = null;
// Level-specific variables
var tools = [];
var wasteItems = [];
var kanbanCards = [];
var workstations = [];
var machines = [];
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 48,
fill: 0x2C3E50
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var levelText = new Text2('Level 1: 5S Workplace Organization', {
size: 36,
fill: 0x2C3E50
});
levelText.anchor.set(0.5, 0);
levelText.y = 80;
LK.gui.top.addChild(levelText);
var instructionText = new Text2('Organize tools by dragging them to correct positions', {
size: 28,
fill: 0x34495E
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 130;
LK.gui.top.addChild(instructionText);
// Progress tracking
var itemsCompleted = 0;
var totalItems = 0;
var timeLimit = 60000; // 60 seconds
var timeRemaining = timeLimit;
var gameTimer = null;
// Timer display
var timerText = new Text2('Time: 60s', {
size: 32,
fill: 0xE74C3C
});
timerText.anchor.set(1, 0);
LK.gui.topRight.addChild(timerText);
function updateScore() {
currentScore = Math.max(0, currentScore);
scoreText.setText('Score: ' + currentScore);
LK.setScore(currentScore);
}
function updateTimer() {
var seconds = Math.ceil(timeRemaining / 1000);
timerText.setText('Time: ' + seconds + 's');
if (timeRemaining <= 0) {
endLevel(false);
}
}
function startLevel(level) {
currentLevel = level;
levelComplete = false;
itemsCompleted = 0;
timeRemaining = timeLimit;
currentScore = 0;
// Clear previous level elements
clearLevel();
// Set level-specific content
switch (level) {
case 1:
setupLevel1();
break;
case 2:
setupLevel2();
break;
case 3:
setupLevel3();
break;
case 4:
setupLevel4();
break;
case 5:
setupLevel5();
break;
default:
setupLevel1();
}
updateScore();
gameStarted = true;
// Start timer
gameTimer = LK.setInterval(function () {
timeRemaining -= 100;
updateTimer();
}, 100);
}
function clearLevel() {
// Remove all game objects
for (var i = tools.length - 1; i >= 0; i--) {
tools[i].destroy();
tools.splice(i, 1);
}
for (var i = wasteItems.length - 1; i >= 0; i--) {
wasteItems[i].destroy();
wasteItems.splice(i, 1);
}
for (var i = kanbanCards.length - 1; i >= 0; i--) {
kanbanCards[i].destroy();
kanbanCards.splice(i, 1);
}
for (var i = workstations.length - 1; i >= 0; i--) {
workstations[i].destroy();
workstations.splice(i, 1);
}
for (var i = machines.length - 1; i >= 0; i--) {
machines[i].destroy();
machines.splice(i, 1);
}
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
}
function setupLevel1() {
levelText.setText('Level 1: 5S Workplace Organization');
instructionText.setText('Organize tools by dragging them to correct positions');
// Create workstations
var workstation1 = game.addChild(LK.getAsset('workstation', {
anchorX: 0.5,
anchorY: 0.5,
x: 500,
y: 800
}));
workstations.push(workstation1);
var workstation2 = game.addChild(LK.getAsset('workstation', {
anchorX: 0.5,
anchorY: 0.5,
x: 1500,
y: 800
}));
workstations.push(workstation2);
// Create tools in wrong positions
var toolPositions = [{
x: 300,
y: 600,
targetX: 450,
targetY: 750
}, {
x: 1200,
y: 500,
targetX: 550,
targetY: 750
}, {
x: 800,
y: 1200,
targetX: 1450,
targetY: 750
}, {
x: 1700,
y: 600,
targetX: 1550,
targetY: 750
}, {
x: 600,
y: 1000,
targetX: 500,
targetY: 850
}];
for (var i = 0; i < toolPositions.length; i++) {
var tool = new Tool('tool' + i, toolPositions[i].targetX, toolPositions[i].targetY);
tool.x = toolPositions[i].x;
tool.y = toolPositions[i].y;
tools.push(tool);
game.addChild(tool);
}
totalItems = tools.length;
}
function setupLevel2() {
levelText.setText('Level 2: Waste Detection');
instructionText.setText('Click on waste items to identify them');
// Create waste items
var wastePositions = [{
x: 400,
y: 600,
type: 'waiting'
}, {
x: 800,
y: 800,
type: 'motion'
}, {
x: 1200,
y: 600,
type: 'overproduction'
}, {
x: 600,
y: 1000,
type: 'waiting'
}, {
x: 1400,
y: 900,
type: 'motion'
}, {
x: 900,
y: 1200,
type: 'overproduction'
}, {
x: 1600,
y: 700,
type: 'waiting'
}];
for (var i = 0; i < wastePositions.length; i++) {
var waste = new WasteItem(wastePositions[i].type);
waste.x = wastePositions[i].x;
waste.y = wastePositions[i].y;
wasteItems.push(waste);
game.addChild(waste);
}
totalItems = wasteItems.length;
}
function setupLevel3() {
levelText.setText('Level 3: Kaizen Implementation');
instructionText.setText('Select process improvements');
// Create improvement options
var improvements = ['Reduce setup time', 'Standardize procedures', 'Eliminate redundant steps'];
for (var i = 0; i < improvements.length; i++) {
var button = new Button(improvements[i], function () {
itemsCompleted++;
currentScore += 20;
updateScore();
checkLevelComplete();
});
button.x = 1024;
button.y = 600 + i * 150;
game.addChild(button);
}
totalItems = 3;
}
function setupLevel4() {
levelText.setText('Level 4: Kanban Setup');
instructionText.setText('Organize workflow cards on the Kanban board');
// Create Kanban board columns
var columns = ['To Do', 'In Progress', 'Done'];
for (var i = 0; i < columns.length; i++) {
var column = game.addChild(LK.getAsset('workstation', {
anchorX: 0.5,
anchorY: 0.5,
x: 400 + i * 500,
y: 1000,
scaleX: 0.8,
scaleY: 1.2
}));
var columnLabel = new Text2(columns[i], {
size: 32,
fill: 0x2C3E50
});
columnLabel.anchor.set(0.5, 0.5);
columnLabel.x = 400 + i * 500;
columnLabel.y = 850;
game.addChild(columnLabel);
}
// Create Kanban cards
var tasks = ['Cut Material', 'Assemble Parts', 'Quality Check', 'Package Product'];
for (var i = 0; i < tasks.length; i++) {
var card = new KanbanCard(tasks[i]);
card.x = 200 + i * 150;
card.y = 600;
kanbanCards.push(card);
game.addChild(card);
}
totalItems = kanbanCards.length;
}
function setupLevel5() {
levelText.setText('Level 5: OEE Optimization');
instructionText.setText('Improve machine efficiency to reach 85% OEE');
// Create machines
var machineData = [{
x: 400,
y: 800,
efficiency: 0.65
}, {
x: 1000,
y: 800,
efficiency: 0.70
}, {
x: 1600,
y: 800,
efficiency: 0.60
}];
for (var i = 0; i < machineData.length; i++) {
var machine = game.addChild(LK.getAsset('machine', {
anchorX: 0.5,
anchorY: 0.5,
x: machineData[i].x,
y: machineData[i].y
}));
machine.efficiency = machineData[i].efficiency;
machine.targetEfficiency = 0.85;
machines.push(machine);
// Efficiency display
var effText = new Text2(Math.round(machine.efficiency * 100) + '%', {
size: 24,
fill: 0x2C3E50
});
effText.anchor.set(0.5, 0.5);
effText.x = machineData[i].x;
effText.y = machineData[i].y + 100;
game.addChild(effText);
machine.efficiencyText = effText;
}
// Improvement buttons
var improvementButton = new Button('Improve Machines', function () {
for (var i = 0; i < machines.length; i++) {
machines[i].efficiency = Math.min(0.90, machines[i].efficiency + 0.05);
machines[i].efficiencyText.setText(Math.round(machines[i].efficiency * 100) + '%');
}
currentScore += 15;
updateScore();
checkLevelComplete();
});
improvementButton.x = 1024;
improvementButton.y = 1200;
game.addChild(improvementButton);
totalItems = 1; // Single goal of reaching target OEE
}
function checkLevelComplete() {
var completed = false;
switch (currentLevel) {
case 1:
var correctlyPlaced = 0;
for (var i = 0; i < tools.length; i++) {
if (tools[i].checkPlacement()) {
correctlyPlaced++;
}
}
completed = correctlyPlaced >= totalItems;
break;
case 2:
var identified = 0;
for (var i = 0; i < wasteItems.length; i++) {
if (wasteItems[i].isIdentified) {
identified++;
}
}
completed = identified >= totalItems;
break;
case 3:
completed = itemsCompleted >= totalItems;
break;
case 4:
var placed = 0;
for (var i = 0; i < kanbanCards.length; i++) {
if (kanbanCards[i].isPlaced) {
placed++;
}
}
completed = placed >= totalItems;
break;
case 5:
var avgEfficiency = 0;
for (var i = 0; i < machines.length; i++) {
avgEfficiency += machines[i].efficiency;
}
avgEfficiency /= machines.length;
completed = avgEfficiency >= 0.85;
break;
}
if (completed && !levelComplete) {
endLevel(true);
}
}
function endLevel(success) {
levelComplete = true;
gameStarted = false;
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
if (success) {
// Bonus points for time remaining
var timeBonus = Math.floor(timeRemaining / 1000) * 5;
currentScore += timeBonus;
totalScore += currentScore;
storage.currentLevel = Math.min(5, currentLevel + 1);
storage.totalScore = totalScore;
LK.getSound('success').play();
if (currentLevel >= 5) {
LK.showYouWin();
} else {
// Auto-advance to next level after short delay
LK.setTimeout(function () {
startLevel(currentLevel + 1);
}, 2000);
}
} else {
LK.getSound('error').play();
LK.showGameOver();
}
updateScore();
}
// Event handlers
game.move = function (x, y, obj) {
if (draggedObject && gameStarted) {
draggedObject.x = x;
draggedObject.y = y;
// Check placement for tools in level 1
if (currentLevel === 1 && draggedObject.checkPlacement) {
draggedObject.checkPlacement();
}
}
};
game.down = function (x, y, obj) {
if (!gameStarted) return;
// Find draggable object
for (var i = 0; i < tools.length; i++) {
if (tools[i].isDragging) {
draggedObject = tools[i];
break;
}
}
for (var i = 0; i < kanbanCards.length; i++) {
if (kanbanCards[i].isDragging) {
draggedObject = kanbanCards[i];
break;
}
}
};
game.up = function (x, y, obj) {
if (draggedObject) {
// Check if dropped in correct area for Kanban cards
if (currentLevel === 4 && draggedObject.cardText) {
if (x > 300 && x < 1700 && y > 900 && y < 1100) {
draggedObject.isPlaced = true;
itemsCompleted++;
currentScore += 15;
updateScore();
checkLevelComplete();
}
}
draggedObject.isDragging = false;
draggedObject = null;
}
};
game.update = function () {
if (gameStarted && !levelComplete) {
checkLevelComplete();
}
};
// Start first level
updateScore();
startLevel(currentLevel); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function (buttonText, callback) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonLabel = new Text2(buttonText, {
size: 32,
fill: 0xFFFFFF
});
buttonLabel.anchor.set(0.5, 0.5);
self.addChild(buttonLabel);
self.callback = callback;
self.down = function (x, y, obj) {
LK.getSound('click').play();
if (self.callback) {
self.callback();
}
};
return self;
});
var KanbanCard = Container.expand(function (cardText) {
var self = Container.call(this);
var cardGraphics = self.attachAsset('kanbanCard', {
anchorX: 0.5,
anchorY: 0.5
});
self.cardText = cardText || 'Task';
self.isPlaced = false;
self.isDragging = false;
var cardLabel = new Text2(self.cardText, {
size: 24,
fill: 0x000000
});
cardLabel.anchor.set(0.5, 0.5);
self.addChild(cardLabel);
self.down = function (x, y, obj) {
self.isDragging = true;
LK.getSound('click').play();
};
return self;
});
var Tool = Container.expand(function (toolType, targetX, targetY) {
var self = Container.call(this);
var toolGraphics = self.attachAsset('tool', {
anchorX: 0.5,
anchorY: 0.5
});
self.toolType = toolType || 'wrench';
self.targetX = targetX || 0;
self.targetY = targetY || 0;
self.isCorrectlyPlaced = false;
self.isDragging = false;
// Visual feedback for correct placement
self.checkPlacement = function () {
var distance = Math.sqrt(Math.pow(self.x - self.targetX, 2) + Math.pow(self.y - self.targetY, 2));
if (distance < 50) {
self.isCorrectlyPlaced = true;
toolGraphics.tint = 0x2ECC71; // Green tint
return true;
} else {
self.isCorrectlyPlaced = false;
toolGraphics.tint = 0xFFFFFF; // Normal color
return false;
}
};
self.down = function (x, y, obj) {
self.isDragging = true;
LK.getSound('click').play();
};
return self;
});
var WasteItem = Container.expand(function (wasteType) {
var self = Container.call(this);
var wasteGraphics = self.attachAsset('waste', {
anchorX: 0.5,
anchorY: 0.5
});
self.wasteType = wasteType || 'waiting';
self.isIdentified = false;
// Different colors for different waste types
if (wasteType === 'waiting') {
wasteGraphics.tint = 0xFF6B6B; // Red
} else if (wasteType === 'motion') {
wasteGraphics.tint = 0xFFD93D; // Yellow
} else if (wasteType === 'overproduction') {
wasteGraphics.tint = 0x9B59B6; // Purple
}
self.down = function (x, y, obj) {
if (!self.isIdentified) {
self.isIdentified = true;
wasteGraphics.alpha = 0.5;
currentScore += 10;
LK.getSound('success').play();
updateScore();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xF0F0F0
});
/****
* Game Code
****/
// Game state variables
var currentLevel = storage.currentLevel || 1;
var currentScore = 0;
var totalScore = storage.totalScore || 0;
var gameStarted = false;
var levelComplete = false;
var draggedObject = null;
// Level-specific variables
var tools = [];
var wasteItems = [];
var kanbanCards = [];
var workstations = [];
var machines = [];
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 48,
fill: 0x2C3E50
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var levelText = new Text2('Level 1: 5S Workplace Organization', {
size: 36,
fill: 0x2C3E50
});
levelText.anchor.set(0.5, 0);
levelText.y = 80;
LK.gui.top.addChild(levelText);
var instructionText = new Text2('Organize tools by dragging them to correct positions', {
size: 28,
fill: 0x34495E
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 130;
LK.gui.top.addChild(instructionText);
// Progress tracking
var itemsCompleted = 0;
var totalItems = 0;
var timeLimit = 60000; // 60 seconds
var timeRemaining = timeLimit;
var gameTimer = null;
// Timer display
var timerText = new Text2('Time: 60s', {
size: 32,
fill: 0xE74C3C
});
timerText.anchor.set(1, 0);
LK.gui.topRight.addChild(timerText);
function updateScore() {
currentScore = Math.max(0, currentScore);
scoreText.setText('Score: ' + currentScore);
LK.setScore(currentScore);
}
function updateTimer() {
var seconds = Math.ceil(timeRemaining / 1000);
timerText.setText('Time: ' + seconds + 's');
if (timeRemaining <= 0) {
endLevel(false);
}
}
function startLevel(level) {
currentLevel = level;
levelComplete = false;
itemsCompleted = 0;
timeRemaining = timeLimit;
currentScore = 0;
// Clear previous level elements
clearLevel();
// Set level-specific content
switch (level) {
case 1:
setupLevel1();
break;
case 2:
setupLevel2();
break;
case 3:
setupLevel3();
break;
case 4:
setupLevel4();
break;
case 5:
setupLevel5();
break;
default:
setupLevel1();
}
updateScore();
gameStarted = true;
// Start timer
gameTimer = LK.setInterval(function () {
timeRemaining -= 100;
updateTimer();
}, 100);
}
function clearLevel() {
// Remove all game objects
for (var i = tools.length - 1; i >= 0; i--) {
tools[i].destroy();
tools.splice(i, 1);
}
for (var i = wasteItems.length - 1; i >= 0; i--) {
wasteItems[i].destroy();
wasteItems.splice(i, 1);
}
for (var i = kanbanCards.length - 1; i >= 0; i--) {
kanbanCards[i].destroy();
kanbanCards.splice(i, 1);
}
for (var i = workstations.length - 1; i >= 0; i--) {
workstations[i].destroy();
workstations.splice(i, 1);
}
for (var i = machines.length - 1; i >= 0; i--) {
machines[i].destroy();
machines.splice(i, 1);
}
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
}
function setupLevel1() {
levelText.setText('Level 1: 5S Workplace Organization');
instructionText.setText('Organize tools by dragging them to correct positions');
// Create workstations
var workstation1 = game.addChild(LK.getAsset('workstation', {
anchorX: 0.5,
anchorY: 0.5,
x: 500,
y: 800
}));
workstations.push(workstation1);
var workstation2 = game.addChild(LK.getAsset('workstation', {
anchorX: 0.5,
anchorY: 0.5,
x: 1500,
y: 800
}));
workstations.push(workstation2);
// Create tools in wrong positions
var toolPositions = [{
x: 300,
y: 600,
targetX: 450,
targetY: 750
}, {
x: 1200,
y: 500,
targetX: 550,
targetY: 750
}, {
x: 800,
y: 1200,
targetX: 1450,
targetY: 750
}, {
x: 1700,
y: 600,
targetX: 1550,
targetY: 750
}, {
x: 600,
y: 1000,
targetX: 500,
targetY: 850
}];
for (var i = 0; i < toolPositions.length; i++) {
var tool = new Tool('tool' + i, toolPositions[i].targetX, toolPositions[i].targetY);
tool.x = toolPositions[i].x;
tool.y = toolPositions[i].y;
tools.push(tool);
game.addChild(tool);
}
totalItems = tools.length;
}
function setupLevel2() {
levelText.setText('Level 2: Waste Detection');
instructionText.setText('Click on waste items to identify them');
// Create waste items
var wastePositions = [{
x: 400,
y: 600,
type: 'waiting'
}, {
x: 800,
y: 800,
type: 'motion'
}, {
x: 1200,
y: 600,
type: 'overproduction'
}, {
x: 600,
y: 1000,
type: 'waiting'
}, {
x: 1400,
y: 900,
type: 'motion'
}, {
x: 900,
y: 1200,
type: 'overproduction'
}, {
x: 1600,
y: 700,
type: 'waiting'
}];
for (var i = 0; i < wastePositions.length; i++) {
var waste = new WasteItem(wastePositions[i].type);
waste.x = wastePositions[i].x;
waste.y = wastePositions[i].y;
wasteItems.push(waste);
game.addChild(waste);
}
totalItems = wasteItems.length;
}
function setupLevel3() {
levelText.setText('Level 3: Kaizen Implementation');
instructionText.setText('Select process improvements');
// Create improvement options
var improvements = ['Reduce setup time', 'Standardize procedures', 'Eliminate redundant steps'];
for (var i = 0; i < improvements.length; i++) {
var button = new Button(improvements[i], function () {
itemsCompleted++;
currentScore += 20;
updateScore();
checkLevelComplete();
});
button.x = 1024;
button.y = 600 + i * 150;
game.addChild(button);
}
totalItems = 3;
}
function setupLevel4() {
levelText.setText('Level 4: Kanban Setup');
instructionText.setText('Organize workflow cards on the Kanban board');
// Create Kanban board columns
var columns = ['To Do', 'In Progress', 'Done'];
for (var i = 0; i < columns.length; i++) {
var column = game.addChild(LK.getAsset('workstation', {
anchorX: 0.5,
anchorY: 0.5,
x: 400 + i * 500,
y: 1000,
scaleX: 0.8,
scaleY: 1.2
}));
var columnLabel = new Text2(columns[i], {
size: 32,
fill: 0x2C3E50
});
columnLabel.anchor.set(0.5, 0.5);
columnLabel.x = 400 + i * 500;
columnLabel.y = 850;
game.addChild(columnLabel);
}
// Create Kanban cards
var tasks = ['Cut Material', 'Assemble Parts', 'Quality Check', 'Package Product'];
for (var i = 0; i < tasks.length; i++) {
var card = new KanbanCard(tasks[i]);
card.x = 200 + i * 150;
card.y = 600;
kanbanCards.push(card);
game.addChild(card);
}
totalItems = kanbanCards.length;
}
function setupLevel5() {
levelText.setText('Level 5: OEE Optimization');
instructionText.setText('Improve machine efficiency to reach 85% OEE');
// Create machines
var machineData = [{
x: 400,
y: 800,
efficiency: 0.65
}, {
x: 1000,
y: 800,
efficiency: 0.70
}, {
x: 1600,
y: 800,
efficiency: 0.60
}];
for (var i = 0; i < machineData.length; i++) {
var machine = game.addChild(LK.getAsset('machine', {
anchorX: 0.5,
anchorY: 0.5,
x: machineData[i].x,
y: machineData[i].y
}));
machine.efficiency = machineData[i].efficiency;
machine.targetEfficiency = 0.85;
machines.push(machine);
// Efficiency display
var effText = new Text2(Math.round(machine.efficiency * 100) + '%', {
size: 24,
fill: 0x2C3E50
});
effText.anchor.set(0.5, 0.5);
effText.x = machineData[i].x;
effText.y = machineData[i].y + 100;
game.addChild(effText);
machine.efficiencyText = effText;
}
// Improvement buttons
var improvementButton = new Button('Improve Machines', function () {
for (var i = 0; i < machines.length; i++) {
machines[i].efficiency = Math.min(0.90, machines[i].efficiency + 0.05);
machines[i].efficiencyText.setText(Math.round(machines[i].efficiency * 100) + '%');
}
currentScore += 15;
updateScore();
checkLevelComplete();
});
improvementButton.x = 1024;
improvementButton.y = 1200;
game.addChild(improvementButton);
totalItems = 1; // Single goal of reaching target OEE
}
function checkLevelComplete() {
var completed = false;
switch (currentLevel) {
case 1:
var correctlyPlaced = 0;
for (var i = 0; i < tools.length; i++) {
if (tools[i].checkPlacement()) {
correctlyPlaced++;
}
}
completed = correctlyPlaced >= totalItems;
break;
case 2:
var identified = 0;
for (var i = 0; i < wasteItems.length; i++) {
if (wasteItems[i].isIdentified) {
identified++;
}
}
completed = identified >= totalItems;
break;
case 3:
completed = itemsCompleted >= totalItems;
break;
case 4:
var placed = 0;
for (var i = 0; i < kanbanCards.length; i++) {
if (kanbanCards[i].isPlaced) {
placed++;
}
}
completed = placed >= totalItems;
break;
case 5:
var avgEfficiency = 0;
for (var i = 0; i < machines.length; i++) {
avgEfficiency += machines[i].efficiency;
}
avgEfficiency /= machines.length;
completed = avgEfficiency >= 0.85;
break;
}
if (completed && !levelComplete) {
endLevel(true);
}
}
function endLevel(success) {
levelComplete = true;
gameStarted = false;
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
if (success) {
// Bonus points for time remaining
var timeBonus = Math.floor(timeRemaining / 1000) * 5;
currentScore += timeBonus;
totalScore += currentScore;
storage.currentLevel = Math.min(5, currentLevel + 1);
storage.totalScore = totalScore;
LK.getSound('success').play();
if (currentLevel >= 5) {
LK.showYouWin();
} else {
// Auto-advance to next level after short delay
LK.setTimeout(function () {
startLevel(currentLevel + 1);
}, 2000);
}
} else {
LK.getSound('error').play();
LK.showGameOver();
}
updateScore();
}
// Event handlers
game.move = function (x, y, obj) {
if (draggedObject && gameStarted) {
draggedObject.x = x;
draggedObject.y = y;
// Check placement for tools in level 1
if (currentLevel === 1 && draggedObject.checkPlacement) {
draggedObject.checkPlacement();
}
}
};
game.down = function (x, y, obj) {
if (!gameStarted) return;
// Find draggable object
for (var i = 0; i < tools.length; i++) {
if (tools[i].isDragging) {
draggedObject = tools[i];
break;
}
}
for (var i = 0; i < kanbanCards.length; i++) {
if (kanbanCards[i].isDragging) {
draggedObject = kanbanCards[i];
break;
}
}
};
game.up = function (x, y, obj) {
if (draggedObject) {
// Check if dropped in correct area for Kanban cards
if (currentLevel === 4 && draggedObject.cardText) {
if (x > 300 && x < 1700 && y > 900 && y < 1100) {
draggedObject.isPlaced = true;
itemsCompleted++;
currentScore += 15;
updateScore();
checkLevelComplete();
}
}
draggedObject.isDragging = false;
draggedObject = null;
}
};
game.update = function () {
if (gameStarted && !levelComplete) {
checkLevelComplete();
}
};
// Start first level
updateScore();
startLevel(currentLevel);