/**** * Classes ****/ // Error Button var ErrorButton = Container.expand(function () { var self = Container.call(this); self.errorId = null; self.errorTitle = null; self.errorMsg = null; self.assetId = null; self.init = function (errorId, errorTitle, errorMsg, assetId) { self.errorId = errorId; self.errorTitle = errorTitle; self.errorMsg = errorMsg; self.assetId = assetId; var btn = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); var txt = new Text2(errorTitle, { size: 48, fill: 0x222222 }); txt.anchor.set(0.5, 0.5); txt.x = btn.width / 2 - btn.width / 2; txt.y = btn.height / 2 - btn.height / 2; self.addChild(txt); }; self.down = function (x, y, obj) { if (typeof onErrorSelected === "function") { onErrorSelected(self.errorId, self.errorTitle, self.errorMsg); } }; return self; }); // Error Popup var ErrorPopup = Container.expand(function () { var self = Container.call(this); self.bg = null; self.txtTitle = null; self.txtMsg = null; self.btn = null; self.btnTxt = null; self.icon = null; self.init = function (versionName, errorTitle, errorMsg) { // Determine style by versionName and errorTitle // We'll use a few style presets to mimic real Mac dialogs // System 6/7/8/9: Sad Mac, bomb, old dialog // Mac OS X: Aqua, rounded, blue button // Catalina: modern, flat, centered // Style presets var style = {}; var lower = (versionName || "").toLowerCase(); if (lower.indexOf("system 6") !== -1 || lower.indexOf("system 7") !== -1) { style.bgColor = 0xffffff; style.titleFill = 0x000000; style.msgFill = 0x000000; style.btnColor = 0xc0c0c0; style.btnText = 0x000000; style.titleSize = 48; style.msgSize = 40; style.btnSize = 44; style.icon = errorTitle === "Sad Mac" ? "sadmac" : null; style.border = true; } else if (lower.indexOf("mac os 8") !== -1 || lower.indexOf("mac os 9") !== -1) { style.bgColor = 0xf8f8f8; style.titleFill = 0x222222; style.msgFill = 0x222222; style.btnColor = 0xeeeeee; style.btnText = 0x000000; style.titleSize = 52; style.msgSize = 44; style.btnSize = 48; style.icon = errorTitle === "Sad Mac" ? "sadmac" : null; style.border = true; } else if (lower.indexOf("mac os x") !== -1) { style.bgColor = 0xf0f6ff; style.titleFill = 0x003366; style.msgFill = 0x222222; style.btnColor = 0x007aff; style.btnText = 0xffffff; style.titleSize = 56; style.msgSize = 48; style.btnSize = 52; style.icon = errorTitle === "Kernel Panic" ? "kernel" : null; style.border = false; } else if (lower.indexOf("catalina") !== -1) { style.bgColor = 0xffffff; style.titleFill = 0x222222; style.msgFill = 0x444444; style.btnColor = 0x007aff; style.btnText = 0xffffff; style.titleSize = 60; style.msgSize = 48; style.btnSize = 52; style.icon = errorTitle === "Kernel Panic" ? "kernel" : null; style.border = false; } else if (errorTitle === "Boot Error") { // macOS boot error: black background, white text, no border, no icon, big font, no blue style.bgColor = 0x000000; style.titleFill = 0xffffff; style.msgFill = 0xffffff; style.btnColor = 0x222222; style.btnText = 0xffffff; style.titleSize = 70; style.msgSize = 54; style.btnSize = 54; style.icon = null; style.border = false; } else { // Default style.bgColor = 0xffffff; style.titleFill = 0x222222; style.msgFill = 0x444444; style.btnColor = 0x007aff; style.btnText = 0xffffff; style.titleSize = 60; style.msgSize = 48; style.btnSize = 52; style.icon = null; style.border = false; } // Draw background self.bg = self.attachAsset('popup_bg', { anchorX: 0.5, anchorY: 0.5 }); self.bg.tint = style.bgColor; // Optional border for classic Mac dialogs if (style.border) { // Simulate a border by overlaying a slightly larger, darker box behind var border = self.attachAsset('popup_bg', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, width: self.bg.width + 8, height: self.bg.height + 8 }); border.tint = 0x888888; border.zIndex = -1; self.addChild(border); // Move bg above border self.bg.zIndex = 0; } // Icon (Sad Mac, Kernel Panic, etc) if (style.icon === "sadmac") { // Draw a yellow box as Sad Mac icon var icon = self.attachAsset('error_sadmac', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -self.bg.height / 2 + 110, width: 100, height: 100 }); self.addChild(icon); self.icon = icon; } else if (style.icon === "kernel") { // Draw a gray box as Kernel Panic icon var icon = self.attachAsset('error_kernel', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -self.bg.height / 2 + 110, width: 100, height: 100 }); self.addChild(icon); self.icon = icon; } // Title self.txtTitle = new Text2(errorTitle, { size: style.titleSize, fill: style.titleFill }); self.txtTitle.anchor.set(0.5, 0); self.txtTitle.x = 0; self.txtTitle.y = -self.bg.height / 2 + (style.icon ? 220 : 60); self.addChild(self.txtTitle); // Message self.txtMsg = new Text2(errorMsg, { size: style.msgSize, fill: style.msgFill }); self.txtMsg.anchor.set(0.5, 0); self.txtMsg.x = 0; self.txtMsg.y = self.txtTitle.y + style.titleSize + 30; self.addChild(self.txtMsg); // OK Button self.btn = self.attachAsset('popup_btn', { anchorX: 0.5, anchorY: 0.5, x: 0, y: self.bg.height / 2 - 100 }); self.btn.tint = style.btnColor; self.btnTxt = new Text2("OK", { size: style.btnSize, fill: style.btnText }); self.btnTxt.anchor.set(0.5, 0.5); self.btnTxt.x = 0; self.btnTxt.y = self.bg.height / 2 - 100; self.addChild(self.btnTxt); }; self.down = function (x, y, obj) { // Close popup on any tap anywhere if (typeof onPopupClosed === "function") { onPopupClosed(); } }; return self; }); // No plugins needed for MVP // MacOS Version Button var MacVersionButton = Container.expand(function () { var self = Container.call(this); self.versionId = null; self.versionName = null; self.init = function (versionId, versionName, colorAsset) { self.versionId = versionId; self.versionName = versionName; var btn = self.attachAsset(colorAsset, { anchorX: 0.5, anchorY: 0.5 }); var txt = new Text2(versionName, { size: 60, fill: 0x222222 }); txt.anchor.set(0.5, 0.5); txt.x = btn.width / 2 - btn.width / 2; // Centered txt.y = btn.height / 2 - btn.height / 2; self.addChild(txt); }; // Touch/click event self.down = function (x, y, obj) { if (typeof onVersionSelected === "function") { onVersionSelected(self.versionId, self.versionName); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf0f0f0 }); /**** * Game Code ****/ // Error popup (shape) // Error buttons (shapes) // Mac OS version buttons (shapes) // Data var macVersions = [{ id: 'macos_6', name: 'System 6', asset: 'macos_6' }, { id: 'macos_7', name: 'System 7', asset: 'macos_7' }, { id: 'macos_8', name: 'Mac OS 8', asset: 'macos_8' }, { id: 'macos_9', name: 'Mac OS 9', asset: 'macos_9' }, { id: 'macos_x', name: 'Mac OS X', asset: 'macos_x' }, { id: 'macos_catalina', name: 'Catalina', asset: 'macos_catalina' }]; var errorDefs = [{ id: 'disk', title: 'Disk Error', msg: 'The disk “Untitled” could not be read because of a hardware problem.', asset: 'error_disk' }, { id: 'finder', title: 'Finder Error', msg: 'The Finder has unexpectedly quit. Please restart your Macintosh.', asset: 'error_finder' }, { id: 'type11', title: 'Type 11 Error', msg: 'Sorry, a system error occurred.\n“Type 11”\nTo temporarily turn off extensions, restart and hold down the shift key.', asset: 'error_type11' }, { id: 'sadmac', title: 'Sad Mac', msg: 'A system error has occurred. Restart your Macintosh.', asset: 'error_sadmac' }, { id: 'kernel', title: 'Kernel Panic', msg: 'You need to restart your computer. Hold down the Power button.', asset: 'error_kernel' }, { id: 'bootup', title: 'Boot Error', msg: 'A critical error occurred during startup.\n\nmacOS could not be started. Please reinstall macOS or contact Apple Support.', asset: 'error_kernel' }]; // State var selectedVersionId = null; var selectedVersionName = null; var versionButtons = []; var errorButtons = []; var popup = null; // Layout constants var gameWidth = 2048; var gameHeight = 2732; // Functions to handle state transitions function showVersionButtons() { // Remove error buttons and popup if present for (var i = 0; i < errorButtons.length; ++i) { errorButtons[i].destroy(); } errorButtons = []; if (popup) { popup.destroy(); popup = null; } // Remove old version buttons for (var i = 0; i < versionButtons.length; ++i) { versionButtons[i].destroy(); } versionButtons = []; // Layout: vertical stack, centered, skip top 100px var btnSpacing = 80; var btnH = 120; var totalH = macVersions.length * btnH + (macVersions.length - 1) * btnSpacing; var startY = (gameHeight - totalH) / 2 + 60; var centerX = gameWidth / 2; for (var i = 0; i < macVersions.length; ++i) { var v = macVersions[i]; var btn = new MacVersionButton(); btn.init(v.id, v.name, v.asset); btn.x = centerX; btn.y = startY + i * (btnH + btnSpacing); versionButtons.push(btn); game.addChild(btn); } } function showErrorButtons(versionId, versionName) { // Remove version buttons for (var i = 0; i < versionButtons.length; ++i) { versionButtons[i].destroy(); } versionButtons = []; // Remove error buttons and popup if present for (var i = 0; i < errorButtons.length; ++i) { errorButtons[i].destroy(); } errorButtons = []; if (popup) { popup.destroy(); popup = null; } selectedVersionId = versionId; selectedVersionName = versionName; // Layout: vertical stack, centered var btnSpacing = 60; var btnH = 120; var totalH = errorDefs.length * btnH + (errorDefs.length - 1) * btnSpacing; var startY = (gameHeight - totalH) / 2 + 60; var centerX = gameWidth / 2; for (var i = 0; i < errorDefs.length; ++i) { var e = errorDefs[i]; var btn = new ErrorButton(); btn.init(e.id, e.title, e.msg, e.asset); btn.x = centerX; btn.y = startY + i * (btnH + btnSpacing); errorButtons.push(btn); game.addChild(btn); } } function showErrorPopup(versionName, errorTitle, errorMsg) { // Remove error buttons for (var i = 0; i < errorButtons.length; ++i) { errorButtons[i].destroy(); } errorButtons = []; if (popup) { popup.destroy(); popup = null; } // Centered popup popup = new ErrorPopup(); popup.init(versionName, errorTitle, errorMsg); popup.x = gameWidth / 2; popup.y = gameHeight / 2; game.addChild(popup); } // Callbacks for buttons function onVersionSelected(versionId, versionName) { showErrorButtons(versionId, versionName); } function onErrorSelected(errorId, errorTitle, errorMsg) { showErrorPopup(selectedVersionName, errorTitle, errorMsg); } function onPopupClosed() { // Return to main menu (version selection) showVersionButtons(); } // Show initial screen showVersionButtons(); // No update loop needed for MVP // No GUI overlay needed for MVP // No move/drag events needed for MVP // No sound/music for MVP
/****
* Classes
****/
// Error Button
var ErrorButton = Container.expand(function () {
var self = Container.call(this);
self.errorId = null;
self.errorTitle = null;
self.errorMsg = null;
self.assetId = null;
self.init = function (errorId, errorTitle, errorMsg, assetId) {
self.errorId = errorId;
self.errorTitle = errorTitle;
self.errorMsg = errorMsg;
self.assetId = assetId;
var btn = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
var txt = new Text2(errorTitle, {
size: 48,
fill: 0x222222
});
txt.anchor.set(0.5, 0.5);
txt.x = btn.width / 2 - btn.width / 2;
txt.y = btn.height / 2 - btn.height / 2;
self.addChild(txt);
};
self.down = function (x, y, obj) {
if (typeof onErrorSelected === "function") {
onErrorSelected(self.errorId, self.errorTitle, self.errorMsg);
}
};
return self;
});
// Error Popup
var ErrorPopup = Container.expand(function () {
var self = Container.call(this);
self.bg = null;
self.txtTitle = null;
self.txtMsg = null;
self.btn = null;
self.btnTxt = null;
self.icon = null;
self.init = function (versionName, errorTitle, errorMsg) {
// Determine style by versionName and errorTitle
// We'll use a few style presets to mimic real Mac dialogs
// System 6/7/8/9: Sad Mac, bomb, old dialog
// Mac OS X: Aqua, rounded, blue button
// Catalina: modern, flat, centered
// Style presets
var style = {};
var lower = (versionName || "").toLowerCase();
if (lower.indexOf("system 6") !== -1 || lower.indexOf("system 7") !== -1) {
style.bgColor = 0xffffff;
style.titleFill = 0x000000;
style.msgFill = 0x000000;
style.btnColor = 0xc0c0c0;
style.btnText = 0x000000;
style.titleSize = 48;
style.msgSize = 40;
style.btnSize = 44;
style.icon = errorTitle === "Sad Mac" ? "sadmac" : null;
style.border = true;
} else if (lower.indexOf("mac os 8") !== -1 || lower.indexOf("mac os 9") !== -1) {
style.bgColor = 0xf8f8f8;
style.titleFill = 0x222222;
style.msgFill = 0x222222;
style.btnColor = 0xeeeeee;
style.btnText = 0x000000;
style.titleSize = 52;
style.msgSize = 44;
style.btnSize = 48;
style.icon = errorTitle === "Sad Mac" ? "sadmac" : null;
style.border = true;
} else if (lower.indexOf("mac os x") !== -1) {
style.bgColor = 0xf0f6ff;
style.titleFill = 0x003366;
style.msgFill = 0x222222;
style.btnColor = 0x007aff;
style.btnText = 0xffffff;
style.titleSize = 56;
style.msgSize = 48;
style.btnSize = 52;
style.icon = errorTitle === "Kernel Panic" ? "kernel" : null;
style.border = false;
} else if (lower.indexOf("catalina") !== -1) {
style.bgColor = 0xffffff;
style.titleFill = 0x222222;
style.msgFill = 0x444444;
style.btnColor = 0x007aff;
style.btnText = 0xffffff;
style.titleSize = 60;
style.msgSize = 48;
style.btnSize = 52;
style.icon = errorTitle === "Kernel Panic" ? "kernel" : null;
style.border = false;
} else if (errorTitle === "Boot Error") {
// macOS boot error: black background, white text, no border, no icon, big font, no blue
style.bgColor = 0x000000;
style.titleFill = 0xffffff;
style.msgFill = 0xffffff;
style.btnColor = 0x222222;
style.btnText = 0xffffff;
style.titleSize = 70;
style.msgSize = 54;
style.btnSize = 54;
style.icon = null;
style.border = false;
} else {
// Default
style.bgColor = 0xffffff;
style.titleFill = 0x222222;
style.msgFill = 0x444444;
style.btnColor = 0x007aff;
style.btnText = 0xffffff;
style.titleSize = 60;
style.msgSize = 48;
style.btnSize = 52;
style.icon = null;
style.border = false;
}
// Draw background
self.bg = self.attachAsset('popup_bg', {
anchorX: 0.5,
anchorY: 0.5
});
self.bg.tint = style.bgColor;
// Optional border for classic Mac dialogs
if (style.border) {
// Simulate a border by overlaying a slightly larger, darker box behind
var border = self.attachAsset('popup_bg', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
width: self.bg.width + 8,
height: self.bg.height + 8
});
border.tint = 0x888888;
border.zIndex = -1;
self.addChild(border);
// Move bg above border
self.bg.zIndex = 0;
}
// Icon (Sad Mac, Kernel Panic, etc)
if (style.icon === "sadmac") {
// Draw a yellow box as Sad Mac icon
var icon = self.attachAsset('error_sadmac', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -self.bg.height / 2 + 110,
width: 100,
height: 100
});
self.addChild(icon);
self.icon = icon;
} else if (style.icon === "kernel") {
// Draw a gray box as Kernel Panic icon
var icon = self.attachAsset('error_kernel', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -self.bg.height / 2 + 110,
width: 100,
height: 100
});
self.addChild(icon);
self.icon = icon;
}
// Title
self.txtTitle = new Text2(errorTitle, {
size: style.titleSize,
fill: style.titleFill
});
self.txtTitle.anchor.set(0.5, 0);
self.txtTitle.x = 0;
self.txtTitle.y = -self.bg.height / 2 + (style.icon ? 220 : 60);
self.addChild(self.txtTitle);
// Message
self.txtMsg = new Text2(errorMsg, {
size: style.msgSize,
fill: style.msgFill
});
self.txtMsg.anchor.set(0.5, 0);
self.txtMsg.x = 0;
self.txtMsg.y = self.txtTitle.y + style.titleSize + 30;
self.addChild(self.txtMsg);
// OK Button
self.btn = self.attachAsset('popup_btn', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: self.bg.height / 2 - 100
});
self.btn.tint = style.btnColor;
self.btnTxt = new Text2("OK", {
size: style.btnSize,
fill: style.btnText
});
self.btnTxt.anchor.set(0.5, 0.5);
self.btnTxt.x = 0;
self.btnTxt.y = self.bg.height / 2 - 100;
self.addChild(self.btnTxt);
};
self.down = function (x, y, obj) {
// Close popup on any tap anywhere
if (typeof onPopupClosed === "function") {
onPopupClosed();
}
};
return self;
});
// No plugins needed for MVP
// MacOS Version Button
var MacVersionButton = Container.expand(function () {
var self = Container.call(this);
self.versionId = null;
self.versionName = null;
self.init = function (versionId, versionName, colorAsset) {
self.versionId = versionId;
self.versionName = versionName;
var btn = self.attachAsset(colorAsset, {
anchorX: 0.5,
anchorY: 0.5
});
var txt = new Text2(versionName, {
size: 60,
fill: 0x222222
});
txt.anchor.set(0.5, 0.5);
txt.x = btn.width / 2 - btn.width / 2; // Centered
txt.y = btn.height / 2 - btn.height / 2;
self.addChild(txt);
};
// Touch/click event
self.down = function (x, y, obj) {
if (typeof onVersionSelected === "function") {
onVersionSelected(self.versionId, self.versionName);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf0f0f0
});
/****
* Game Code
****/
// Error popup (shape)
// Error buttons (shapes)
// Mac OS version buttons (shapes)
// Data
var macVersions = [{
id: 'macos_6',
name: 'System 6',
asset: 'macos_6'
}, {
id: 'macos_7',
name: 'System 7',
asset: 'macos_7'
}, {
id: 'macos_8',
name: 'Mac OS 8',
asset: 'macos_8'
}, {
id: 'macos_9',
name: 'Mac OS 9',
asset: 'macos_9'
}, {
id: 'macos_x',
name: 'Mac OS X',
asset: 'macos_x'
}, {
id: 'macos_catalina',
name: 'Catalina',
asset: 'macos_catalina'
}];
var errorDefs = [{
id: 'disk',
title: 'Disk Error',
msg: 'The disk “Untitled” could not be read because of a hardware problem.',
asset: 'error_disk'
}, {
id: 'finder',
title: 'Finder Error',
msg: 'The Finder has unexpectedly quit. Please restart your Macintosh.',
asset: 'error_finder'
}, {
id: 'type11',
title: 'Type 11 Error',
msg: 'Sorry, a system error occurred.\n“Type 11”\nTo temporarily turn off extensions, restart and hold down the shift key.',
asset: 'error_type11'
}, {
id: 'sadmac',
title: 'Sad Mac',
msg: 'A system error has occurred. Restart your Macintosh.',
asset: 'error_sadmac'
}, {
id: 'kernel',
title: 'Kernel Panic',
msg: 'You need to restart your computer. Hold down the Power button.',
asset: 'error_kernel'
}, {
id: 'bootup',
title: 'Boot Error',
msg: 'A critical error occurred during startup.\n\nmacOS could not be started. Please reinstall macOS or contact Apple Support.',
asset: 'error_kernel'
}];
// State
var selectedVersionId = null;
var selectedVersionName = null;
var versionButtons = [];
var errorButtons = [];
var popup = null;
// Layout constants
var gameWidth = 2048;
var gameHeight = 2732;
// Functions to handle state transitions
function showVersionButtons() {
// Remove error buttons and popup if present
for (var i = 0; i < errorButtons.length; ++i) {
errorButtons[i].destroy();
}
errorButtons = [];
if (popup) {
popup.destroy();
popup = null;
}
// Remove old version buttons
for (var i = 0; i < versionButtons.length; ++i) {
versionButtons[i].destroy();
}
versionButtons = [];
// Layout: vertical stack, centered, skip top 100px
var btnSpacing = 80;
var btnH = 120;
var totalH = macVersions.length * btnH + (macVersions.length - 1) * btnSpacing;
var startY = (gameHeight - totalH) / 2 + 60;
var centerX = gameWidth / 2;
for (var i = 0; i < macVersions.length; ++i) {
var v = macVersions[i];
var btn = new MacVersionButton();
btn.init(v.id, v.name, v.asset);
btn.x = centerX;
btn.y = startY + i * (btnH + btnSpacing);
versionButtons.push(btn);
game.addChild(btn);
}
}
function showErrorButtons(versionId, versionName) {
// Remove version buttons
for (var i = 0; i < versionButtons.length; ++i) {
versionButtons[i].destroy();
}
versionButtons = [];
// Remove error buttons and popup if present
for (var i = 0; i < errorButtons.length; ++i) {
errorButtons[i].destroy();
}
errorButtons = [];
if (popup) {
popup.destroy();
popup = null;
}
selectedVersionId = versionId;
selectedVersionName = versionName;
// Layout: vertical stack, centered
var btnSpacing = 60;
var btnH = 120;
var totalH = errorDefs.length * btnH + (errorDefs.length - 1) * btnSpacing;
var startY = (gameHeight - totalH) / 2 + 60;
var centerX = gameWidth / 2;
for (var i = 0; i < errorDefs.length; ++i) {
var e = errorDefs[i];
var btn = new ErrorButton();
btn.init(e.id, e.title, e.msg, e.asset);
btn.x = centerX;
btn.y = startY + i * (btnH + btnSpacing);
errorButtons.push(btn);
game.addChild(btn);
}
}
function showErrorPopup(versionName, errorTitle, errorMsg) {
// Remove error buttons
for (var i = 0; i < errorButtons.length; ++i) {
errorButtons[i].destroy();
}
errorButtons = [];
if (popup) {
popup.destroy();
popup = null;
}
// Centered popup
popup = new ErrorPopup();
popup.init(versionName, errorTitle, errorMsg);
popup.x = gameWidth / 2;
popup.y = gameHeight / 2;
game.addChild(popup);
}
// Callbacks for buttons
function onVersionSelected(versionId, versionName) {
showErrorButtons(versionId, versionName);
}
function onErrorSelected(errorId, errorTitle, errorMsg) {
showErrorPopup(selectedVersionName, errorTitle, errorMsg);
}
function onPopupClosed() {
// Return to main menu (version selection)
showVersionButtons();
}
// Show initial screen
showVersionButtons();
// No update loop needed for MVP
// No GUI overlay needed for MVP
// No move/drag events needed for MVP
// No sound/music for MVP