1 Commits
qjs ... log

Author SHA1 Message Date
John Alanbrook
e98abcdda7 initial logging try
Some checks failed
Build and Deploy / build-macos (push) Failing after 5s
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
2025-05-24 22:01:21 -05:00
588 changed files with 13218 additions and 89117 deletions

View File

@@ -1,17 +0,0 @@
sdl_video = "main"
[dependencies]
extramath = "https://gitea.pockle.world/john/extramath@master"
[system]
ar_timer = 60
actor_memory = 0
net_service = 0.1
reply_timeout = 60
actor_max = "10_000"
stack_max = 0
[actors]
[actors.prosperon/sdl_video]
main = true
[actors.prosperon/prosperon]
main = true
[actors.prosperon]
main = true

View File

@@ -1,6 +0,0 @@
[modules]
[modules.extramath]
hash = "MCLZT3JABTAENS4WVXKGWJ7JPBLZER4YQ5VN2PE7ZD2Z4WYGTIMA===="
url = "https://gitea.pockle.world/john/extramath@master"
downloaded = "Monday June 2 12:07:20.42 PM -5 2025 AD"
commit = "84d81a19a8455bcf8dc494739e9e6d545df6ff2c"

13
.gitignore vendored
View File

@@ -6,18 +6,27 @@ build/
*.o
*.a
*.d
tags
Jenkinsfile
*~
*.log
*.gz
*.tar
.nova/
packer*
primum
sokol-shdc*
source/shaders/*.h
core.cdb
primum.exe
core.cdb.h
jsc
.DS_Store
*.html
.vscode
*.icns
game.zip
icon.ico
steam/
subprojects/*/
build_dbg/
modules/
build_dbg/

20
.moth/log Normal file
View File

@@ -0,0 +1,20 @@
{
"console": {
"outputs": ["console"]
},
"info": {
"outputs": ["file:logs/info.log"]
},
"warning": {
"outputs": ["console", "file:logs/warnings.log"]
},
"error": {
"outputs": ["console", "file:logs/errors.log", "actor:localhost:5678"]
},
"debug": {
"outputs": ["file:logs/debug.log"]
},
"audit": {
"outputs": ["file:logs/audit.log", "actor:audit-server:9000"]
}
}

View File

@@ -13,6 +13,7 @@ This is a game engine developed using a QuickJS fork as its scripting language.
## Coding Practices
- Use K&R style C
- Use as little whitespace as possible
- Javascript style prefers objects and prototypical inheritence over ES6 classes, liberal use of closures, and var everywhere
## Instructions

View File

@@ -5,7 +5,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Build Commands
### Build variants
- `make` - Make and install debug version. Usually all that's needed.
- `make debug` - Build debug version (uses meson debug configuration)
- `make fast` - Build optimized version
- `make release` - Build release version with LTO and optimizations
- `make small` - Build minimal size version
@@ -13,10 +13,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- `make crosswin` - Cross-compile for Windows using mingw32
### Testing
After install with 'make', just run 'cell' and point it at the actor you want to launch. "cell tests/toml" runs the actor "tests/toml.js"
## Scripting language
This is called "cell", but it is is a variant of javascript and extremely similar.
- `meson test -C build_dbg` - Run all tests in debug build
- `meson test -C build_<variant>` - Run tests in specific build variant
- `./build_dbg/prosperon tests/<testname>.js` - Run specific test
- Available tests: `spawn_actor`, `empty`, `nota`, `wota`, `portalspawner`, `overling`, `send`, `delay`
### Common development commands
- `meson setup build_<variant>` - Configure build directory
@@ -126,7 +126,7 @@ meson test -C build_dbg
### Debugging
- Use debug build: `make debug`
- Tracy profiler support when enabled
- Console logging available via `log.console()`, `log.error()`, etc.
- Console logging available via `console.log()`, `console.error()`, etc.
- Log files written to `.prosperon/log.txt`
# Project Structure Notes
@@ -202,11 +202,6 @@ meson test -C build_dbg
### Utility Modules
- `time` - Time management and delays
- **Must be imported with `use('time')`**
- No `time.now()` function - use:
- `time.number()` - Number representation of current time
- `time.record()` - Struct representation of current time
- `time.text()` - Text representation of current time
- `io` - File I/O operations
- `json` - JSON parsing and serialization
- `util` - General utilities
@@ -239,7 +234,7 @@ When sending a message with a callback, respond by sending to the message itself
```javascript
// Sender side:
send(actor, {type: 'status'}, response => {
log.console(response); // Handle the response
console.log(response); // Handle the response
});
// Receiver side:
@@ -284,7 +279,7 @@ $_.receiver(msg => {
- Custom formats: Aseprite animations, etc.
### Developer Tools
- Built-in documentation system with `cell.DOC`
- Built-in documentation system with `prosperon.DOC`
- Tracy profiler integration for performance monitoring
- Imgui debugging tools
- Console logging with various severity levels

View File

@@ -1,22 +1,22 @@
debug: FORCE
meson setup build_dbg -Dbuildtype=debug
meson install --only-changed -C build_dbg
meson compile -C build_dbg
fast: FORCE
meson setup build_fast
meson install -C build_fast
meson compile -C build_fast
release: FORCE
meson setup -Dbuildtype=release -Db_lto=true -Db_lto_mode=thin -Db_ndebug=true build_release
meson install -C build_release
meson compile -C build_release
sanitize: FORCE
meson setup -Db_sanitize=address -Db_sanitize=memory -Db_sanitize=leak -Db_sanitize=undefined build_sani
meson install -C build_sani
meson compile -C build_sani
small: FORCE
meson setup -Dbuildtype=minsize -Db_lto=true -Db_ndebug=true build_small
meson install -C build_small
meson compile -C build_small
web: FORCE
meson setup -Deditor=false -Dbuildtype=minsize -Db_lto=true -Db_ndebug=true --cross-file emscripten.cross build_web

View File

@@ -49,28 +49,28 @@ function getStats(arr) {
}
// Pretty print results
log.console("\n=== Performance Test Results (100 iterations) ===");
log.console("\nJSON Decoding (ms):");
console.log("\n=== Performance Test Results (100 iterations) ===");
console.log("\nJSON Decoding (ms):");
const jsonDecStats = getStats(jsonDecodeTimes);
log.console(`Average: ${jsonDecStats.avg.toFixed(2)} ms`);
log.console(`Min: ${jsonDecStats.min.toFixed(2)} ms`);
log.console(`Max: ${jsonDecStats.max.toFixed(2)} ms`);
console.log(`Average: ${jsonDecStats.avg.toFixed(2)} ms`);
console.log(`Min: ${jsonDecStats.min.toFixed(2)} ms`);
console.log(`Max: ${jsonDecStats.max.toFixed(2)} ms`);
log.console("\nJSON Encoding (ms):");
console.log("\nJSON Encoding (ms):");
const jsonEncStats = getStats(jsonEncodeTimes);
log.console(`Average: ${jsonEncStats.avg.toFixed(2)} ms`);
log.console(`Min: ${jsonEncStats.min.toFixed(2)} ms`);
log.console(`Max: ${jsonEncStats.max.toFixed(2)} ms`);
console.log(`Average: ${jsonEncStats.avg.toFixed(2)} ms`);
console.log(`Min: ${jsonEncStats.min.toFixed(2)} ms`);
console.log(`Max: ${jsonEncStats.max.toFixed(2)} ms`);
log.console("\nNOTA Encoding (ms):");
console.log("\nNOTA Encoding (ms):");
const notaEncStats = getStats(notaEncodeTimes);
log.console(`Average: ${notaEncStats.avg.toFixed(2)} ms`);
log.console(`Min: ${notaEncStats.min.toFixed(2)} ms`);
log.console(`Max: ${notaEncStats.max.toFixed(2)} ms`);
console.log(`Average: ${notaEncStats.avg.toFixed(2)} ms`);
console.log(`Min: ${notaEncStats.min.toFixed(2)} ms`);
console.log(`Max: ${notaEncStats.max.toFixed(2)} ms`);
log.console("\nNOTA Decoding (ms):");
console.log("\nNOTA Decoding (ms):");
const notaDecStats = getStats(notaDecodeTimes);
log.console(`Average: ${notaDecStats.avg.toFixed(2)} ms`);
log.console(`Min: ${notaDecStats.min.toFixed(2)} ms`);
log.console(`Max: ${notaDecStats.max.toFixed(2)} ms`);
console.log(`Average: ${notaDecStats.avg.toFixed(2)} ms`);
console.log(`Min: ${notaDecStats.min.toFixed(2)} ms`);
console.log(`Max: ${notaDecStats.max.toFixed(2)} ms`);

View File

@@ -75,8 +75,8 @@ const benchmarks = [
];
// Print a header
log.console("Wota Encode/Decode Benchmark");
log.console("============================\n");
console.log("Wota Encode/Decode Benchmark");
console.log("============================\n");
// We'll run each benchmark scenario in turn.
for (let bench of benchmarks) {
@@ -96,11 +96,11 @@ for (let bench of benchmarks) {
let elapsedSec = measureTime(runAllData, bench.iterations);
let opsPerSec = (totalIterations / elapsedSec).toFixed(1);
log.console(`${bench.name}:`);
log.console(` Iterations: ${bench.iterations} × ${bench.data.length} data items = ${totalIterations}`);
log.console(` Elapsed: ${elapsedSec.toFixed(3)} s`);
log.console(` Throughput: ${opsPerSec} encode+decode ops/sec\n`);
console.log(`${bench.name}:`);
console.log(` Iterations: ${bench.iterations} × ${bench.data.length} data items = ${totalIterations}`);
console.log(` Elapsed: ${elapsedSec.toFixed(3)} s`);
console.log(` Throughput: ${opsPerSec} encode+decode ops/sec\n`);
}
// All done
log.console("Benchmark completed.\n");
console.log("Benchmark completed.\n");

View File

@@ -8,7 +8,6 @@
var wota = use('wota');
var nota = use('nota');
var json = use('json');
var jswota = use('jswota')
var os = use('os');
//
@@ -23,7 +22,7 @@ const libraries = [
decode: wota.decode,
// Wota produces an ArrayBuffer. We'll count `buffer.byteLength` as size.
getSize(encoded) {
return encoded.length;
return encoded.byteLength;
}
},
{
@@ -32,7 +31,7 @@ const libraries = [
decode: nota.decode,
// Nota also produces an ArrayBuffer:
getSize(encoded) {
return encoded.length;
return encoded.byteLength;
}
},
{
@@ -54,11 +53,6 @@ const libraries = [
////////////////////////////////////////////////////////////////////////////////
const benchmarks = [
{
name: "Empty object",
data: [{}, {}, {}, {}],
iterations: 10000
},
{
name: "Small Integers",
data: [0, 42, -1, 2023],
@@ -92,6 +86,11 @@ const benchmarks = [
data: [ Array.from({length:1000}, (_, i) => i) ],
iterations: 1000
},
{
name: "Large Binary Blob (256KB)",
data: [ new Uint8Array(256 * 1024).buffer ],
iterations: 200
}
];
////////////////////////////////////////////////////////////////////////////////
@@ -126,8 +125,8 @@ function runBenchmarkForLibrary(lib, bench) {
let encodeTime = measureTime(() => {
for (let i = 0; i < bench.iterations; i++) {
// For each data item, encode it
for (let j = 0; j < bench.data.length; j++) {
let e = lib.encode(bench.data[j]);
for (let d of bench.data) {
let e = lib.encode(d);
// store only in the very first iteration, so we can decode them later
// but do not store them every iteration or we blow up memory.
if (i === 0) {
@@ -156,12 +155,12 @@ function runBenchmarkForLibrary(lib, bench) {
// 5. Main driver: run across all benchmarks, for each library.
////////////////////////////////////////////////////////////////////////////////
log.console("Benchmark: Wota vs Nota vs JSON");
log.console("================================\n");
console.log("Benchmark: Wota vs Nota vs JSON");
console.log("================================\n");
for (let bench of benchmarks) {
log.console(`SCENARIO: ${bench.name}`);
log.console(` Data length: ${bench.data.length} | Iterations: ${bench.iterations}\n`);
console.log(`SCENARIO: ${bench.name}`);
console.log(` Data length: ${bench.data.length} | Iterations: ${bench.iterations}\n`);
for (let lib of libraries) {
let { encodeTime, decodeTime, totalSize } = runBenchmarkForLibrary(lib, bench);
@@ -171,15 +170,13 @@ for (let bench of benchmarks) {
let encOpsPerSec = (totalOps / encodeTime).toFixed(1);
let decOpsPerSec = (totalOps / decodeTime).toFixed(1);
log.console(` ${lib.name}:`);
log.console(` Encode time: ${encodeTime.toFixed(3)}s => ${encOpsPerSec} encodes/sec [${(encodeTime/bench.iterations)*1000000000} ns/try]`);
log.console(` Decode time: ${decodeTime.toFixed(3)}s => ${decOpsPerSec} decodes/sec [${(decodeTime/bench.iterations)*1000000000}/try]`);
log.console(` Total size: ${totalSize} bytes (or code units for JSON)`);
log.console("");
console.log(` ${lib.name}:`);
console.log(` Encode time: ${encodeTime.toFixed(3)}s => ${encOpsPerSec} encodes/sec`);
console.log(` Decode time: ${decodeTime.toFixed(3)}s => ${decOpsPerSec} decodes/sec`);
console.log(` Total size: ${totalSize} bytes (or code units for JSON)`);
console.log("");
}
log.console("---------------------------------------------------------\n");
console.log("---------------------------------------------------------\n");
}
log.console("Benchmark complete.\n");
os.exit()
console.log("Benchmark complete.\n");

View File

@@ -47,7 +47,7 @@ Certain functions are intrinsic to the program and cannot be overridden. They
- **Example**:
```js
this.delay(_ => {
log.console("3 seconds later!")
console.log("3 seconds later!")
}, 3)
```

View File

@@ -3,11 +3,11 @@
Provides a consistent way to create documentation for prosperon elements. Objects are documented by adding docstrings directly to object-like things (functions, objects, ...), or to an object's own "doc object".
Docstrings are set to the symbol `cell.DOC`
Docstrings are set to the symbol `prosperon.DOC`
```js
// Suppose we have a module that returns a function
function greet(name) { log.console("Hello, " + name) }
function greet(name) { console.log("Hello, " + name) }
// We can attach a docstring
greet.doc = `
@@ -21,12 +21,12 @@ return greet
```js
// Another way is to add a docstring object to an object
var greet = {
hello() { log.console('hello!') }
hello() { console.log('hello!') }
}
greet[cell.DOC] = {}
greet[cell.DOC][cell.DOC] = 'An object full of different greeter functions'
greet[cell.DOC].hello = 'A greeter that says, "hello!"'
greet[prosperon.DOC] = {}
greet[prosperon.DOC][prosperon.DOC] = 'An object full of different greeter functions'
greet[prosperon.DOC].hello = 'A greeter that says, "hello!"'
```

View File

@@ -49,7 +49,7 @@ return {
This will cause prosperon to launch a 500x500 window with the title 'Hello World'. In your ```main.js```, write the following:
```
log.console("Hello world")
console.log("Hello world")
this.delay(_ => {
this.kill();
@@ -62,6 +62,6 @@ this.delay(_ => {
The global object called `prosperon` has a variety of engine specific settings on it that can be set to influence how the engine behaves. For example, `prosperon.argv` contains a list of the command line arguments given to prosperon; `prosperon.PATH` is an array of paths to resolve resources such as modules and images. `prosperon` is fully documented in the API section.
## Getting help
The `prosperon` global has a 'doc' function, which can be invoked on any engine object to see a description of it and its members. For example, to learn about `prosperon`, try printing out `cell.DOC(prosperon)` in your `main.js`.
The `prosperon` global has a 'doc' function, which can be invoked on any engine object to see a description of it and its members. For example, to learn about `prosperon`, try printing out `prosperon.doc(prosperon)` in your `main.js`.
Writing documentation for your own modules and game components will be explored in the chapter on actors & modules.

View File

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 449 B

View File

@@ -5,7 +5,6 @@ var sprite = use('sprite')
var geom = use('geometry')
var input = use('controller')
var config = use('config')
var color = use('color')
var bunnyTex = graphics.texture("bunny")
@@ -66,5 +65,5 @@ this.hud = function() {
draw.images(bunnyTex, bunnies)
var msg = 'FPS: ' + fpsAvg.toFixed(2) + ' Bunnies: ' + bunnies.length
draw.text(msg, {x:0, y:0, width:config.width, height:40}, undefined, 0, color.white, 0)
draw.text(msg, {x:0, y:0, width:config.width, height:40}, undefined, 0, Color.white, 0)
}

View File

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 390 B

View File

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 438 B

View File

Before

Width:  |  Height:  |  Size: 398 B

After

Width:  |  Height:  |  Size: 398 B

View File

Before

Width:  |  Height:  |  Size: 337 B

After

Width:  |  Height:  |  Size: 337 B

View File

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 390 B

View File

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 379 B

View File

@@ -1,9 +1,16 @@
/* main.js runs the demo with your prototype-based grid */
var moth = use('moth', $_.delay)
var json = use('json')
var draw2d = use('prosperon/draw2d')
var blob = use('blob')
var res = 160
var internal_res = 480
moth.initialize({ width:res, height:res, resolution_x:internal_res, resolution_y:internal_res, mode:'letterbox' });
var os = use('os');
var draw2d = use('draw2d');
var gfx = use('graphics');
/*──── import our pieces + systems ───────────────────────────────────*/
var Grid = use('grid'); // your new ctor
@@ -48,7 +55,7 @@ function updateTitle() {
break;
}
log.console(title)
prosperon.window.title = title
}
// Initialize title
@@ -63,7 +70,7 @@ var opponentMousePos = null;
var opponentHoldingPiece = false;
var opponentSelectPos = null;
function handleMouseButtonDown(e) {
prosperon.on('mouse_button_down', function(e) {
if (e.which !== 0) return;
// Don't allow piece selection unless we have an opponent
@@ -89,9 +96,9 @@ function handleMouseButtonDown(e) {
} else {
selectPos = null;
}
}
})
function handleMouseButtonUp(e) {
prosperon.on('mouse_button_up', function(e) {
if (e.which !== 0 || !holdingPiece || !selectPos) return;
// Don't allow moves unless we have an opponent and it's our turn
@@ -110,16 +117,16 @@ function handleMouseButtonUp(e) {
}
if (mover.tryMove(grid.at(selectPos)[0], c)) {
log.console("Made move from", selectPos, "to", c);
console.log("Made move from", selectPos, "to", c);
// Send move to opponent
log.console("Sending move to opponent:", opponent);
console.log("Sending move to opponent:", opponent);
send(opponent, {
type: 'move',
from: selectPos,
to: c
});
isMyTurn = false; // It's now opponent's turn
log.console("Move sent, now opponent's turn");
console.log("Move sent, now opponent's turn");
selectPos = null;
updateTitle();
}
@@ -132,9 +139,9 @@ function handleMouseButtonUp(e) {
type: 'piece_drop'
});
}
}
})
function handleMouseMotion(e) {
prosperon.on('mouse_motion', function(e) {
var mx = e.pos.x;
var my = e.pos.y;
@@ -155,18 +162,7 @@ function handleMouseMotion(e) {
selectPos: selectPos
});
}
}
function handleKeyDown(e) {
// S key - start server
if (e.scancode === 22 && gameState === 'waiting') { // S key
startServer();
}
// J key - join server
else if (e.scancode === 13 && gameState === 'waiting') { // J key
joinServer();
}
}
})
/*──── drawing helpers ───────────────────────────────────────────────*/
/* ── constants ─────────────────────────────────────────────────── */
@@ -197,8 +193,7 @@ function drawBoard() {
draw2d.rectangle(
{ x: x*S, y: y*S, width: S, height: S },
{ thickness: 0 },
{ color: color }
{ thickness: 0, color: color }
);
}
}
@@ -240,7 +235,7 @@ function drawPieces() {
var r = { x: piece.coord[0]*S, y: piece.coord[1]*S,
width:S, height:S };
draw2d.image(piece.sprite, r);
draw2d.image(piece.sprite, r, 0, [0,0], [0,0], {mode:"nearest"});
});
// Draw the held piece at the mouse position if we're holding one
@@ -250,7 +245,7 @@ function drawPieces() {
var r = { x: hoverPos[0]*S, y: hoverPos[1]*S,
width:S, height:S };
draw2d.image(piece.sprite, r);
draw2d.image(piece.sprite, r, 0, [0,0], [0,0], {mode:"nearest"});
}
}
@@ -262,23 +257,29 @@ function drawPieces() {
width:S, height:S };
// Draw with slight transparency to show it's the opponent's piece
draw2d.image(opponentPiece.sprite, r);
draw2d.image(opponentPiece.sprite, r, 0, [0,0], [0,0], {mode:"nearest", color: [1, 1, 1, 0.7]});
}
}
}
function update(dt)
{
return {}
}
var graphics = use('graphics')
function draw()
{
draw2d.clear()
prosperon.on('draw', function() {
drawBoard()
drawPieces()
return draw2d.get_commands()
}
draw2d.text("HELL", [100,100])
})
prosperon.on('key_down', function(e) {
// S key - start server
if (e.scancode === 22 && gameState === 'waiting') { // S key
startServer();
}
// J key - join server
else if (e.scancode === 13 && gameState === 'waiting') { // J key
joinServer();
}
})
function startServer() {
gameState = 'server_waiting';
@@ -288,11 +289,11 @@ function startServer() {
updateTitle();
$_.portal(e => {
log.console("Portal received contact message");
console.log("Portal received contact message");
// Reply with this actor to establish connection
log.console (json.encode($_))
console.log (json.encode($_))
send(e, $_);
log.console("Portal replied with server actor");
console.log("Portal replied with server actor");
}, 5678);
}
@@ -301,10 +302,10 @@ function joinServer() {
updateTitle();
function contact_fn(actor, reason) {
log.console("CONTACTED!", actor ? "SUCCESS" : "FAILED", reason);
console.log("CONTACTED!", actor ? "SUCCESS" : "FAILED", reason);
if (actor) {
opponent = actor;
log.console("Connection established with server, sending join request");
console.log("Connection established with server, sending join request");
// Send a greet message with our actor object
send(opponent, {
@@ -312,7 +313,7 @@ function joinServer() {
client_actor: $_
});
} else {
log.console(`Failed to connect: ${json.encode(reason)}`);
console.log(`Failed to connect: ${json.encode(reason)}`);
gameState = 'waiting';
updateTitle();
}
@@ -324,38 +325,51 @@ function joinServer() {
});
}
var os = use('os')
var actor = use('actor')
for (var i in actor) console.log(i)
// Set up IO actor subscription
var ioguy = {
__ACTORDATA__: {
id: actor.ioactor()
}
};
send(ioguy, {
type: "subscribe",
actor: $_
});
$_.receiver(e => {
if (e.kind == 'update')
send(e, update(e.dt))
else if (e.kind == 'draw')
send(e, draw())
else if (e.type === 'game_start' || e.type === 'move' || e.type === 'greet')
log.console("Receiver got message:", e.type, e);
if (e.type === 'game_start' || e.type === 'move' || e.type === 'greet')
console.log("Receiver got message:", e.type, e);
if (e.type === 'quit') os.exit()
if (e.type === 'greet') {
log.console("Server received greet from client");
console.log("Server received greet from client");
// Store the client's actor object for ongoing communication
opponent = e.client_actor;
log.console("Stored client actor:", json.encode(opponent));
console.log("Stored client actor:", json.encode(opponent));
gameState = 'connected';
updateTitle();
// Send game_start to the client
log.console("Sending game_start to client");
console.log("Sending game_start to client");
send(opponent, {
type: 'game_start',
your_color: 'black'
});
log.console("game_start message sent to client");
console.log("game_start message sent to client");
}
else if (e.type === 'game_start') {
log.console("Game starting, I am:", e.your_color);
console.log("Game starting, I am:", e.your_color);
myColor = e.your_color;
isMyTurn = (myColor === 'white');
gameState = 'connected';
updateTitle();
} else if (e.type === 'move') {
log.console("Received move from opponent:", e.from, "to", e.to);
console.log("Received move from opponent:", e.from, "to", e.to);
// Apply opponent's move
var fromCell = grid.at(e.from);
if (fromCell.length) {
@@ -363,12 +377,12 @@ $_.receiver(e => {
if (mover.tryMove(piece, e.to)) {
isMyTurn = true; // It's now our turn
updateTitle();
log.console("Applied opponent move, now my turn");
console.log("Applied opponent move, now my turn");
} else {
log.console("Failed to apply opponent move");
console.log("Failed to apply opponent move");
}
} else {
log.console("No piece found at from position");
console.log("No piece found at from position");
}
} else if (e.type === 'mouse_move') {
// Update opponent's mouse position
@@ -383,13 +397,7 @@ $_.receiver(e => {
// Opponent dropped their piece
opponentHoldingPiece = false;
opponentSelectPos = null;
} else if (e.type === 'mouse_button_down') {
handleMouseButtonDown(e)
} else if (e.type === 'mouse_button_up') {
handleMouseButtonUp(e)
} else if (e.type === 'mouse_motion') {
handleMouseMotion(e)
} else if (e.type === 'key_down') {
handleKeyDown(e)
}
})
prosperon.dispatch(e.type, e)
})

View File

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 376 B

View File

Before

Width:  |  Height:  |  Size: 403 B

After

Width:  |  Height:  |  Size: 403 B

View File

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 381 B

View File

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 313 B

View File

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 378 B

View File

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 378 B

View File

@@ -101,7 +101,7 @@ $_.receiver(function(msg) {
break;
case 'status':
log.console(`got status request. current is ${json.encode(get_status())}`)
console.log(`got status request. current is ${json.encode(get_status())}`)
send(msg, {
type: 'status_response',
...get_status()

View File

@@ -8,13 +8,13 @@ var waiting_client = null;
var match_id = 0;
$_.portal(e => {
log.console("NAT server: received connection request");
console.log("NAT server: received connection request");
if (!is_actor(e.actor))
send(e, {reason: "Must provide the actor you want to connect."});
if (waiting_client) {
log.console(`sending out messages! to ${json.encode(e.actor)} and ${json.encode(waiting_client.actor)}`)
console.log(`sending out messages! to ${json.encode(e.actor)} and ${json.encode(waiting_client.actor)}`)
send(waiting_client, e.actor)
send(e, waiting_client.actor)
@@ -25,5 +25,5 @@ $_.portal(e => {
waiting_client = e
log.console(`actor ${json.encode(e.actor)} is waiting ...`)
console.log(`actor ${json.encode(e.actor)} is waiting ...`)
}, 4000);

View File

@@ -1,11 +1,11 @@
log.console(`nat client starting`)
console.log(`nat client starting`)
$_.contact((actor, reason) => {
if (actor) {
log.console(`trying to message ${json.encode(actor)}`)
console.log(`trying to message ${json.encode(actor)}`)
send(actor, {type:"greet"})
} else {
log.console(json.encode(reason))
console.log(json.encode(reason))
}
}, {
address: "108.210.60.32", // NAT server's public IP
@@ -16,7 +16,7 @@ $_.contact((actor, reason) => {
$_.receiver(e => {
switch(e.type) {
case 'greet':
log.console(`hello!`)
console.log(`hello!`)
break
}
})

View File

@@ -2,7 +2,6 @@
var draw = use('draw2d')
var input = use('controller')
var config = use('config')
var color = use('color')
prosperon.camera.transform.pos = [0,0]
@@ -74,13 +73,13 @@ this.hud = function() {
draw.rectangle({x:0, y:0, width:config.width, height:config.height}, [0,0,0,1])
// Draw paddles
draw.rectangle({x:p1.x - paddleW*0.5, y:p1.y - paddleH*0.5, width:paddleW, height:paddleH}, color.white)
draw.rectangle({x:p2.x - paddleW*0.5, y:p2.y - paddleH*0.5, width:paddleW, height:paddleH}, color.white)
draw.rectangle({x:p1.x - paddleW*0.5, y:p1.y - paddleH*0.5, width:paddleW, height:paddleH}, Color.white)
draw.rectangle({x:p2.x - paddleW*0.5, y:p2.y - paddleH*0.5, width:paddleW, height:paddleH}, Color.white)
// Draw ball
draw.rectangle({x:ball.x - ball.size*0.5, y:ball.y - ball.size*0.5, width:ball.size, height:ball.size}, color.white)
draw.rectangle({x:ball.x - ball.size*0.5, y:ball.y - ball.size*0.5, width:ball.size, height:ball.size}, Color.white)
// Simple score display
var msg = score1 + " " + score2
draw.text(msg, {x:0, y:10, width:config.width, height:40}, undefined, 0, color.white, 0)
draw.text(msg, {x:0, y:10, width:config.width, height:40}, undefined, 0, Color.white, 0)
}

View File

@@ -4,7 +4,6 @@ var render = use('render')
var graphics = use('graphics')
var input = use('input')
var config = use('config')
var color = use('color')
prosperon.camera.transform.pos = [0,0]
@@ -84,15 +83,15 @@ this.hud = function() {
// Draw snake
for (var i=0; i<snake.length; i++) {
var s = snake[i]
draw.rectangle({x:s.x*cellSize, y:s.y*cellSize, width:cellSize, height:cellSize}, color.green)
draw.rectangle({x:s.x*cellSize, y:s.y*cellSize, width:cellSize, height:cellSize}, Color.green)
}
// Draw apple
draw.rectangle({x:apple.x*cellSize, y:apple.y*cellSize, width:cellSize, height:cellSize}, color.red)
draw.rectangle({x:apple.x*cellSize, y:apple.y*cellSize, width:cellSize, height:cellSize}, Color.red)
if (gameState === "gameover") {
var msg = "GAME OVER! Press SPACE to restart."
draw.text(msg, {x:0, y:config.height*0.5-10, width:config.width, height:20}, undefined, 0, color.white)
draw.text(msg, {x:0, y:config.height*0.5-10, width:config.width, height:20}, undefined, 0, Color.white)
}
}

View File

@@ -23,23 +23,23 @@ var stats_loaded = false;
// Initialize Steam
function init_steam() {
if (!steam) {
log.console("Steam module not available");
console.log("Steam module not available");
return false;
}
log.console("Initializing Steam...");
console.log("Initializing Steam...");
steam_available = steam.steam_init();
if (steam_available) {
log.console("Steam initialized successfully");
console.log("Steam initialized successfully");
// Request current stats/achievements
if (steam.stats.stats_request()) {
log.console("Stats requested");
console.log("Stats requested");
stats_loaded = true;
}
} else {
log.console("Failed to initialize Steam");
console.log("Failed to initialize Steam");
}
return steam_available;
@@ -59,13 +59,13 @@ function unlock_achievement(achievement_name) {
// Check if already unlocked
var unlocked = steam.achievement.achievement_get(achievement_name);
if (unlocked) {
log.console("Achievement already unlocked:", achievement_name);
console.log("Achievement already unlocked:", achievement_name);
return true;
}
// Unlock it
if (steam.achievement.achievement_set(achievement_name)) {
log.console("Achievement unlocked:", achievement_name);
console.log("Achievement unlocked:", achievement_name);
// Store stats to make it permanent
steam.stats.stats_store();
@@ -87,7 +87,7 @@ function update_stat(stat_name, value, is_float) {
}
if (success) {
log.console("Stat updated:", stat_name, "=", value);
console.log("Stat updated:", stat_name, "=", value);
steam.stats.stats_store();
}
@@ -115,7 +115,7 @@ function start_game() {
total_score = get_stat(STATS.TOTAL_SCORE, false);
current_score = 0;
log.console("Starting game #" + (games_played + 1));
console.log("Starting game #" + (games_played + 1));
}
function end_game(score) {
@@ -167,7 +167,7 @@ function load_from_cloud() {
function cleanup_steam() {
if (steam_available) {
steam.steam_shutdown();
log.console("Steam shut down");
console.log("Steam shut down");
}
}

View File

@@ -1,7 +1,6 @@
var draw = use('draw2d')
var input = use('input')
var config = use('config')
var color = use('color')
prosperon.camera.transform.pos = [0,0]
@@ -249,7 +248,7 @@ this.hud = function() {
}
// Next piece window
draw.text("Next", {x:70, y:5, width:50, height:10}, undefined, 0, color.white)
draw.text("Next", {x:70, y:5, width:50, height:10}, undefined, 0, Color.white)
if (nextPiece) {
for (var i=0; i<nextPiece.blocks.length; i++) {
var nx = nextPiece.blocks[i][0]
@@ -262,10 +261,10 @@ this.hud = function() {
// Score & Level
var info = "Score: " + score + "\nLines: " + linesCleared + "\nLevel: " + level
draw.text(info, {x:70, y:30, width:90, height:50}, undefined, 0, color.white)
draw.text(info, {x:70, y:30, width:90, height:50}, undefined, 0, Color.white)
if (gameOver) {
draw.text("GAME OVER", {x:10, y:config.height*0.5-5, width:config.width-20, height:20}, undefined, 0, color.red)
draw.text("GAME OVER", {x:10, y:config.height*0.5-5, width:config.width-20, height:20}, undefined, 0, Color.red)
}
}

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 867 B

After

Width:  |  Height:  |  Size: 867 B

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Some files were not shown because too many files have changed in this diff Show More