AIArchives / archives /neonstrike /test /visual-audit.mjs
CompactAI's picture
Upload 126 files
f6b8770 verified
Raw
History Blame Contribute Delete
4.54 kB
// Visual audit: screenshot every asset class up close so we can judge what
// needs enhancement. Writes to ../playtest/audit/.
import puppeteer from 'puppeteer-core';
import { spawn } from 'child_process';
import http from 'http';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const APP_DIR = path.join(__dirname, '..', 'app');
const OUT = path.join(__dirname, '..', 'playtest', 'audit');
fs.mkdirSync(OUT, { recursive: true });
const port = 3960 + Math.floor(Math.random() * 30);
const srv = spawn('node', ['server/index.js'], { cwd: APP_DIR, env: { ...process.env, PORT: String(port) }, stdio: 'pipe' });
await new Promise((res, rej) => {
const t0 = Date.now();
(function poll() {
http.get(`http://127.0.0.1:${port}/`, () => res()).on('error', () => Date.now() - t0 > 8000 ? rej(new Error('no server')) : setTimeout(poll, 150));
})();
});
const browser = await puppeteer.launch({
executablePath: '/usr/bin/google-chrome-stable',
headless: 'new',
args: ['--no-sandbox', '--disable-dev-shm-usage', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'],
defaultViewport: { width: 1280, height: 720 },
});
const page = await browser.newPage();
page.on('pageerror', e => console.log('ERR', e.message));
await page.goto(`http://127.0.0.1:${port}/`, { waitUntil: 'networkidle0' });
await page.waitForFunction('window.GAME && window.GAME.ready');
const sleep = ms => new Promise(r => setTimeout(r, ms));
const shot = async name => { await page.screenshot({ path: path.join(OUT, name + '.png') }); console.log('shot', name); };
// crank quality for the audit
await page.evaluate(() => {
GAME.test.setSetting('graphics.preset', 'ultra');
GAME.test.setSetting('graphics.resolutionScale', 1.0);
});
// 1. every weapon viewmodel
await page.evaluate(() => { GAME.test.start('vector'); GAME.test.skipBuy(); });
await sleep(400);
const weapons = ['knife', 'pistol', 'deagle', 'smg', 'shotgun', 'rifle', 'sniper'];
await page.evaluate(ws => {
for (const w of ws) GAME.game.player.weapons[w] = GAME.game.player.weapons[w] || { ammo: 30, reserve: 90 };
GAME.test.pose(0, 0, 8, 0, -0.06);
}, weapons);
for (const w of weapons) {
await page.evaluate(w => { GAME.game.player.current = w; }, w);
await sleep(350);
await shot(`weapon-${w}`);
}
// 2. character: front 3/4, side, back, crouched, group
await page.evaluate(() => {
const g = GAME.game;
g.bots.forEach((b, i) => { b.pos = [100 + i * 10, 0, 100]; }); // park others away
const b = g.bots[0];
b.pos = [0, 0, 16]; b.yaw = Math.PI * 0.85;
GAME.test.pose(-1.5, 0, 19, 0.35, 0.0);
});
await sleep(300);
await shot('char-front34');
await page.evaluate(() => { GAME.game.bots[0].yaw = Math.PI / 2; });
await sleep(250);
await shot('char-side');
await page.evaluate(() => {
const g = GAME.game;
for (let i = 0; i < Math.min(4, g.bots.length); i++) {
g.bots[i].pos = [-3 + i * 2, 0, 15 - (i % 2)];
g.bots[i].yaw = Math.PI + (i - 1.5) * 0.3;
}
GAME.test.pose(0, 0, 21, 0, 0.02);
});
await sleep(300);
await shot('char-group');
// 3. map signature views, ultra
for (const [m, x, y, z, yaw, pitch] of [
['vector-asite', 20, 0, -12, 1.2, -0.05],
['foundry-hall', 0, 0, 20, 0, 0.0],
['foundry-platform', 12, 2.2, 10, -2.4, -0.12],
['canopy-bridge', 0, 0, 18, 0, -0.04],
['canopy-street', 8, -2, 2, -1.4, 0.1],
]) {
const mapId = m.split('-')[0];
await page.evaluate(id => { GAME.test.start(id); GAME.test.skipBuy(); }, mapId);
await sleep(350);
await page.evaluate((x, y, z, yaw, pitch) => GAME.test.pose(x, y, z, yaw, pitch), x, y, z, yaw, pitch);
await sleep(300);
await shot(`map-${m}`);
}
// 4. reflective floor + neon close (the RT showcase angle)
await page.evaluate(() => { GAME.test.start('vector'); GAME.test.skipBuy(); GAME.test.pose(-5.5, 0, 10, -0.5, -0.35); });
await sleep(300);
await shot('rt-neon-floor');
// 5. muzzle flash mid-fire
await page.evaluate(() => {
GAME.test.pose(0, 0, 8, 0, 0);
GAME.game.player.current = 'rifle';
GAME.game.player.weapons.rifle = { ammo: 30, reserve: 90 };
GAME.test.fire();
});
await sleep(30);
await shot('fx-muzzle');
// 6. buy menu (asset cards)
await page.evaluate(() => { GAME.game.state = 'buy'; GAME.game.phaseT = 6; });
await page.evaluate(() => { document.getElementById('buy-menu').style.display = 'block'; });
await sleep(200);
await shot('ui-buymenu');
await browser.close();
srv.kill();
console.log('audit complete:', OUT);