123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 | <!doctype html>
<html lang="en">
<head>
<title>PICO-8 Cartridge</title>
<meta name="viewport" content="width=device-width, user-scalable=no" />
<style>
html,
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
background-color: #0ff;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
#canvas {
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
display: block;
}
#log {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
max-height: 50%;
overflow: auto;
z-index: 10000;
font-family: monospace;
white-space: pre-wrap;
background: rgba(17, 17, 17, 0.9);
color: #8f8;
padding: 10px;
font-weight: 800;
pointer-events: none;
}
</style>
</head>
<body>
<div id="log"></div>
<script>
const logElem = document.getElementById('log');
const log = (type, args) => {
logElem.innerHTML += `<span style="color:${type==='error'?'#f55':type==='warn'?'#fa0':'#0f0'}">[${type}] ${[...args].map(a=>typeof a==='object'?JSON.stringify(a,null,2):a).join(' ')}</span>\n`;
};
['log','warn','error','info'].forEach(t => {
const orig = console[t];
console[t] = (...args) => { log(t, args); orig.apply(console, args); };
});
window.onerror = (msg, src, line, col, err) => {
logElem.style.display = 'block';
log('error', [`${msg} (${src}:${line}:${col})`]);
};
window.onunhandledrejection = e => {
logElem.style.display = 'block';
log('error', ['Unhandled promise rejection:', e.reason]);
};
console.log("Starting...");
</script>
<script type="text/javascript">
// PICO-8 globals
var pico8_state = {
is_paused: 0,
sound_volume: 100,
frame_number: 0,
has_focus: 1,
show_dpad: 0,
request_pointer_lock: 0,
require_page_navigate_confirmation: 0,
shutdown_requested: 0
};
var pico8_buttons = [0, 0, 0, 0, 0, 0, 0, 0];
var pico8_mouse = [0, 0, 0];
var pico8_gpio = new Array(128);
var p8_touch_detected = false;
var codo_key_buffer = [];
var codo_wheel_dx = 0;
var codo_wheel_dy = 0;
var codo_mounted_filesystem = 0;
var codo_command = 0;
var codo_command_p = 0;
var pico8_audio_context;
function p8_update_layout() {
var canvas = document.getElementById("canvas");
if (!canvas) {
requestAnimationFrame(p8_update_layout);
return;
}
var csize = 128;
while (2*csize <= Math.min(window.innerWidth, window.innerHeight))
csize *= 2;
canvas.style.width = csize + "px";
canvas.style.height = csize + "px";
requestAnimationFrame(p8_update_layout);
}
function p8_create_audio_context() {
if (pico8_audio_context) {
try {
pico8_audio_context.resume();
} catch (err) {
console.log("** pico8_audio_context.resume() failed");
}
return;
}
var webAudioAPI =
window.AudioContext ||
window.webkitAudioContext ||
window.mozAudioContext ||
window.oAudioContext ||
window.msAudioContext;
if (webAudioAPI) {
pico8_audio_context = new webAudioAPI();
}
}
var p8_is_running = false;
var p8_script = null;
var Module = null;
function p8_run_cart() {
if (p8_is_running) return;
p8_is_running = true;
p8_create_audio_context();
console.log("Loading cart.js...");
var e = document.createElement("script");
p8_script = e;
e.type = "application/javascript";
e.src = "cart.js";
e.id = "e_script";
document.body.appendChild(e);
}
</script>
<div id="p8_playarea" style="display: flex">
<canvas
class="emscripten"
id="canvas"
oncontextmenu="event.preventDefault()"
></canvas>
</div>
<textarea
id="codo_textarea"
class="emscripten"
style="display: none; position: absolute; left: -9999px"
></textarea>
<script type="text/javascript">
// Mocks for PICO-8 engine
var p8_frame = {
offsetWidth: window.innerWidth,
offsetHeight: window.innerHeight,
parentNode: { parentNode: { offsetHeight: window.innerHeight } },
};
var p8_container = document.getElementById("p8_playarea");
var body_0 = { style: {} };
var p8_frame_0 = {
parentNode: { appendChild: function () {} },
style: {},
};
p8_update_layout();
// Pre-initialize Module
Module = {
canvas: document.getElementById("canvas"),
onRuntimeInitialized: function() {
console.log("PICO-8 Runtime initialized.");
},
print: function(text) { console.log(text); },
printErr: function(text) { console.error(text); }
};
// Auto-start game when AudioContext is ready
var temp_context = new AudioContext();
temp_context.onstatechange = function () {
if (temp_context.state == "running") {
p8_run_cart();
temp_context.close();
}
};
// For some environments, we might need a backup start
setTimeout(() => {
if (!p8_is_running) {
console.log("Backup start triggered...");
p8_run_cart();
}
}, 2000);
</script>
<script type="module">
import { PLAYER_1, PLAYER_2 } from "@rcade/plugin-input-classic";
function updateRcade() {
if (typeof pico8_buttons !== "undefined") {
// Player 1
let b1 = 0;
if (PLAYER_1.DPAD.left) b1 |= 0x1;
if (PLAYER_1.DPAD.right) b1 |= 0x2;
if (PLAYER_1.DPAD.up) b1 |= 0x4;
if (PLAYER_1.DPAD.down) b1 |= 0x8;
if (PLAYER_1.A) b1 |= 0x10;
if (PLAYER_1.B) b1 |= 0x20;
pico8_buttons[0] = b1;
// Player 2
let b2 = 0;
if (PLAYER_2.DPAD.left) b2 |= 0x1;
if (PLAYER_2.DPAD.right) b2 |= 0x2;
if (PLAYER_2.DPAD.up) b2 |= 0x4;
if (PLAYER_2.DPAD.down) b2 |= 0x8;
if (PLAYER_2.A) b2 |= 0x10;
if (PLAYER_2.B) b2 |= 0x20;
pico8_buttons[1] = b2;
}
requestAnimationFrame(updateRcade);
}
updateRcade();
</script>
</body>
</html>
|