Files
cell/scripts/modules/moth.js
John Alanbrook e7cc716590
Some checks failed
Build and Deploy / build-macos (push) Failing after 10s
Build and Deploy / build-windows (CLANG64) (push) Has been cancelled
Build and Deploy / package-dist (push) Has been cancelled
Build and Deploy / deploy-itch (push) Has been cancelled
Build and Deploy / deploy-gitea (push) Has been cancelled
Build and Deploy / build-linux (push) Has been cancelled
initial moth
2025-05-19 09:01:17 -05:00

140 lines
3.3 KiB
JavaScript

/**
* Moth Game Framework
* Higher-level game development framework built on top of Prosperon
*/
var os = use('os');
var io = use('io');
var render = use('render');
var draw2d = use('draw2d');
var actor = use('actor');
var gameConfig = {};
var gameDir = "";
// Framework initialization
function initialize(dir) {
gameDir = dir;
// Load configuration if it exists
var configPath = `${dir}/config.js`;
if (io.exists(configPath)) {
gameConfig = use(configPath);
}
// Set up default config values
gameConfig.resolution = gameConfig.resolution || { width: 640, height: 480 };
gameConfig.internal_resolution = gameConfig.internal_resolution || gameConfig.resolution;
gameConfig.title = gameConfig.title || "Moth Game";
gameConfig.fps = gameConfig.fps || 60;
gameConfig.clearColor = gameConfig.clearColor || [0, 0, 0, 1];
// Initialize render system
render.initialize({
width: gameConfig.resolution.width,
height: gameConfig.resolution.height,
resolution_x: gameConfig.internal_resolution.width,
resolution_y: gameConfig.internal_resolution.height,
mode: gameConfig.mode || 'letterbox'
});
// Set up default camera
gameConfig.camera = gameConfig.camera || {
size: [gameConfig.internal_resolution.width, gameConfig.internal_resolution.height],
transform: os.make_transform(),
fov: 50,
near_z: 0,
far_z: 1000,
surface: undefined,
viewport: {x: 0, y: 0, width: 1, height: 1},
ortho: true,
anchor: [0, 0]
};
// Set window title
prosperon.window.title = gameConfig.title;
// Set up IO actor subscription
var ioguy = {
__ACTORDATA__: {
id: os.ioactor()
}
};
$_.send(ioguy, {
type: "subscribe",
actor: $_
});
// Set up automatic receiver for input events
$_.receiver(function(e) {
// Handle quit
if (e.type === 'quit') {
os.exit();
}
// Forward all events to prosperon's dispatch system
prosperon.dispatch(e.type, e);
});
// Start the game loop
startGameLoop();
// Load the game's main.js
var mainPath = `${dir}/main.js`;
if (io.exists(mainPath)) {
// Spawn the main game actor
actor.spawn(mainPath);
} else {
console.error(`No main.js found in ${dir}`);
}
}
// Main game loop
function startGameLoop() {
var last = os.now();
var fpsTimer = 0;
var fpsCount = 0;
var targetFrameTime = 1 / gameConfig.fps;
function loop() {
var now = os.now();
var dt = now - last;
last = now;
// Dispatch update event
prosperon.dispatch('update', dt);
// Clear and set up rendering
render.clear(gameConfig.clearColor);
render.camera(gameConfig.camera);
// Dispatch draw event
prosperon.dispatch('draw');
// Present the frame
render.present();
// FPS counter
fpsTimer += dt;
fpsCount++;
if (fpsTimer >= 0.5) {
// Only update if the title wasn't changed by the game
if (prosperon.window.title === gameConfig.title) {
prosperon.window.title = `${gameConfig.title} - FPS ${(fpsCount / fpsTimer).toFixed(1)}`;
}
fpsTimer = fpsCount = 0;
}
// Schedule next frame
$_.delay(loop, Math.max(0, targetFrameTime - (os.now() - now)));
}
loop();
}
// Public API
return {
initialize: initialize,
config: gameConfig
};