← DOOM results

DOOM

Gemma 4 12b · typescript

Initial view of DOOM

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 16,786 bytes · SHA-256 70fee858fd05
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Retro Raycaster FPS</title>
<style>
/* ── css: retro-style ── */
body {
    margin: 0;
    padding: 0;
    background-color: #1a1a1a;
    color: #eee;
    font-family: 'Courier New', Courier, monospace;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    overflow: hidden;
}

#game-container {
    position: relative;
    border: 4px solid #555;
    box-shadow: 0 0 20px rgba(0,0,0,0.5);
}

canvas {
    display: block;
    image-rendering: pixelated;
}

#hud {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba(0, 0, 0, 0.7);
    padding: 10px;
    display: flex;
    justify-content: space-around;
    border-top: 2px solid #555;
}

.stat {
    text-align: center;
}

.stat-label {
    font-size: 0.8rem;
    color: #aaa;
}

.stat-value {
    font-size: 1.5rem;
    font-weight: bold;
    color: #f00;
}

#crosshair {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: rgba(255, 255, 255, 0.8);
    font-size: 1.5rem;
}

#overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.8);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 10;
}

#overlay h1 {
    font-size: 3rem;
    color: #f00;
    margin-bottom: 20px;
}

button {
    padding: 15px 30px;
    font-size: 1.2rem;
    background: #444;
    color: white;
    border: 2px solid #fff;
    cursor: pointer;
}

button:hover {
    background: #666;
}
</style>
</head>
<body>
<div id="game-container">
    <canvas id="gameCanvas"></canvas>
    <div id="crosshair">+</div>
    <div id="hud">
        <div class="stat">
            <div class="stat-label">HEALTH</div>
            <div id="health" class="stat-value">100</div>
        </div>
        <div class="stat">
            <div class="stat-label">AMMO</div>
            <div id="ammo" class="stat-value">30</div>
        </div>
        <div class="stat">
            <div class="stat-label">WEAPON</div>
            <div id="weapon-name" class="stat-value">Pistol</div>
        </div>
    </div>
    <div id="overlay">
        <h1 id="overlay-title">RETRO FPS</h1>
        <p id="overlay-desc">Use WASD to move, Mouse to aim/shoot</p>
        <button id="start-btn">START GAME</button>
    </div>
</div>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {"src/world.ts":{"./constants":"src/constants.ts"},"src/player.ts":{"./constants":"src/constants.ts"},"src/engine.ts":{"./constants":"src/constants.ts","./world":"src/world.ts","./player":"src/player.ts"}};
function __require(id) {
  if (__cache[id]) return __cache[id].exports;
  var module = __cache[id] = { exports: {} };
  var factory = __mods[id];
  if (!factory) throw new Error("Module not found: " + id);
  factory(module.exports, function (spec) {
    var target = (__map[id] && __map[id][spec]) || spec;
    return __require(target);
  }, module);
  return module.exports;
}

// ── module: src/main.ts ──
__mods["src/main.ts"] = function (exports, require, module) {
"use strict";
// Entry point. Runs after the DOM is parsed and after any classic
// <script> imports, so document queries and CDN globals are available.
// Import your other modules from here.
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = start;
function start() {
    // Replace this with the real startup sequence.
}
start();
};

// ── module: src/constants.ts ──
__mods["src/constants.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ENTITY_TYPES = exports.WEAPONS = exports.FOV = exports.TILE_SIZE = exports.MAP = void 0;
exports.MAP = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 1],
    [1, 0, 8, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
];
exports.TILE_SIZE = 64;
exports.FOV = Math.PI / 3; // 60 degrees
exports.WEAPONS = {
    pistol: { name: 'Pistol', damage: 20, ammoCount: 30, maxAmmo: 100, fireRate: 400, cooldown: 0.3, color: '#fff' },
    shotgun: { name: 'Shotgun', damage: 60, ammoCount: 15, maxAmmo: 20, fireRate: 800, cooldown: 0.8, color: '#f90' },
    rocket: { name: 'Rocket', damage: 150, ammoCount: 5, maxAmmo: 10, fireRate: 1500, cooldown: 2.0, color: '#f30' }
};
exports.ENTITY_TYPES = {
    WALL: 1,
    PICKUP_HEALTH: 2,
    PICKUP_AMMO: 3,
    ENEMY: 4,
    WIN_CONDITION: 5,
    EXPLOSIVE: 6,
    PORTAL: 7,
    DOOR: 8,
    CHEST: 9
};
};

// ── module: src/world.ts ──
__mods["src/world.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.World = void 0;
const constants_1 = require("./constants");
class World {
    constructor() {
        this.entities = [];
        this.map = constants_1.MAP;
        this.initEntities();
    }
    initEntities() {
        // Place some enemies (type 4) and items
        // Note: The constants.ts says ENTITY_TYPES.ENEMY is 4, PICKUP_HEALTH is 2, etc.
        this.entities = [
            { x: 3 * constants_1.TILE_SIZE, y: 2 * constants_1.TILE_SIZE, type: 4, hp: 100, id: 'e1' },
            { x: 8 * constants_1.TILE_SIZE, y: 2 * constants_1.TILE_SIZE, type: 4, hp: 100, id: 'e2' },
            { x: 6 * constants_1.TILE_SIZE, y: 4 * constants_1.TILE_SIZE, type: 4, hp: 80, id: 'e3' },
            { x: 11 * constants_1.TILE_SIZE, y: 5 * constants_1.TILE_SIZE, type: 4, hp: 120, id: 'e4' },
            { x: 2 * constants_1.TILE_SIZE, y: 6 * constants_1.TILE_SIZE, type: 4, hp: 90, id: 'e5' },
            // Pickups
            { x: 5 * constants_1.TILE_SIZE, y: 3 * constants_1.TILE_SIZE, type: 2, hp: 50, id: 'h1' }, // health
            { x: 9 * constants_1.TILE_SIZE, y: 4 * constants_1.TILE_SIZE, type: 3, hp: 30, id: 'a1' }, // ammo
            { x: 7 * constants_1.TILE_SIZE, y: 6 * constants_1.TILE_SIZE, type: 3, hp: 50, id: 'a2' }, // ammo
            // Win condition
            { x: 13 * constants_1.TILE_SIZE, y: 5 * constants_1.TILE_SIZE, type: 5, hp: 1, id: 'win' }
        ];
    }
    getTile(x, y) {
        const tx = Math.floor(x / constants_1.TILE_SIZE);
        const ty = Math.floor(y / constants_1.TILE_SIZE);
        if (tx < 0 || tx >= this.map[0].length || ty < 0 || ty >= this.map.length)
            return 1;
        return this.map[ty][tx];
    }
    isWall(x, y) {
        return this.getTile(x, y) === 1;
    }
    getEntityAt(x, y) {
        for (const e of this.entities) {
            const dist = Math.sqrt((e.x - x) ** 2 + (e.y - y) ** 2);
            if (dist < constants_1.TILE_SIZE * 0.8)
                return e;
        }
        return null;
    }
    removeEntity(id) {
        this.entities = this.entities.filter(e => e.id !== id);
    }
}
exports.World = World;
};

// ── module: src/player.ts ──
__mods["src/player.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Player = void 0;
class Player {
    constructor() {
        this.x = 4 * 64;
        this.y = 4 * 64;
        this.angle = 0;
        this.health = 100;
        this.ammo = 30;
        this.weaponType = 'pistol';
        this.lastFireTime = 0;
    }
    update(keys, world) {
        const moveSpeed = 3;
        let dx = 0;
        let dy = 0;
        if (keys['w'])
            dy -= moveSpeed;
        if (keys['s'])
            dy += moveSpeed;
        if (keys['a'])
            dx -= moveSpeed;
        if (keys['d'])
            dx += moveSpeed;
        const nextX = this.x + dx;
        const nextY = this.y + dy;
        if (!world.isWall(nextX, nextY)) {
            this.x = nextX;
            this.y = nextY;
        }
        this.health = Math.min(100, this.health);
    }
    shoot(weaponData) {
        if (this.ammo > 0 && Date.now() - this.lastFireTime > weaponData.cooldown * 1000) {
            this.ammo--;
            this.lastFireTime = Date.now();
            return true;
        }
        return false;
    }
}
exports.Player = Player;
};

// ── module: src/engine.ts ──
__mods["src/engine.ts"] = function (exports, require, module) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.GameEngine = void 0;
const Consts = __importStar(require("./constants"));
const world_1 = require("./world");
const player_1 = require("./player");
class GameEngine {
    constructor() {
        this.keys = {};
        this.gameActive = false;
        this.lastTime = 0;
        this.canvas = document.getElementById('gameCanvas');
        // Set internal resolution for retro feel
        this.canvas.width = 320;
        this.canvas.height = 200;
        this.ctx = this.canvas.getContext('2d');
        this.world = new world_1.World();
        this.player = new player_1.Player();
        window.Player = player_1.Player;
        window.addEventListener('keydown', e => this.keys[e.key.toLowerCase()] = true);
        window.addEventListener('keyup', e => this.keys[e.key.toLowerCase()] = false);
        this.canvas.requestPointerLock = this.canvas.requestPointerLock;
        this.canvas.onclick = () => {
            if (!this.gameActive) {
                this.startGame();
            }
            else if (this.canvas.requestPointerLock) {
                this.canvas.requestPointerLock();
            }
        };
        // Call initMouse after construction to ensure elements exist
        setTimeout(() => this.initMouse(), 100);
        this.loop = this.loop.bind(this);
        requestAnimationFrame(this.loop);
    }
    startGame() {
        this.gameActive = true;
        document.getElementById('overlay').style.display = 'none';
        this.player.health = 100;
        this.player.ammo = Consts.WEAPONS.pistol.ammoCount;
    }
    loop(time) {
        const dt = time - this.lastTime;
        this.lastTime = time;
        if (this.gameActive) {
            this.update();
            this.render();
        }
        requestAnimationFrame(this.loop);
    }
    update() {
        this.player.update(this.keys, this.world);
        // Check entity interactions
        for (let i = this.world.entities.length - 1; i >= 0; i--) {
            const e = this.world.entities[i];
            const dist = Math.sqrt((e.x - this.player.x) ** 2 + (e.y - this.player.y) ** 2);
            if (dist < Consts.TILE_SIZE * 0.8) {
                if (e.type === Consts.ENTITY_TYPES.PICKUP_HEALTH) {
                    this.player.health = Math.min(100, this.player.health + e.hp);
                    this.world.removeEntity(e.id);
                }
                else if (e.type === Consts.ENTITY_TYPES.PICKUP_AMMO) {
                    this.player.ammo += e.hp;
                    this.world.removeEntity(e.id);
                }
                else if (e.type === Consts.ENTITY_TYPES.WIN_CONDITION) {
                    this.gameActive = false;
                    alert('YOU WIN!');
                    location.reload();
                }
            }
        }
        // Simple enemy AI / damage
        for (const e of this.world.entities) {
            if (e.type === Consts.ENTITY_TYPES.ENEMY) {
                const dist = Math.sqrt((e.x - this.player.x) ** 2 + (e.y - this.player.y) ** 2);
                if (dist < 300) {
                    // Move towards player
                    const angleToPlayer = Math.atan2(this.player.y - e.y, this.player.x - e.x);
                    e.x += Math.cos(angleToPlayer) * 1;
                    e.y += Math.sin(angleToPlayer) * 1;
                    if (dist < 40) {
                        this.player.health -= 0.5;
                    }
                }
            }
        }
        if (this.player.health <= 0) {
            alert('GAME OVER');
            location.reload();
        }
        // Update HUD
        const healthEl = document.getElementById('health');
        const ammoEl = document.getElementById('ammo');
        const weaponEl = document.getElementById('weapon-name');
        if (healthEl)
            healthEl.innerText = Math.floor(this.player.health);
        if (ammoEl)
            ammoEl.innerText = this.player.ammo;
        if (weaponEl)
            weaponEl.innerText = Consts.WEAPONS[this.player.weaponType].name;
    }
    render() {
        const { ctx, canvas, player, world } = this;
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        // Raycasting logic
        const numRays = canvas.width;
        const stepAngle = (Consts.FOV) / numRays;
        for (let i = 0; i < numRays; i++) {
            const rayAngle = player.angle - (Consts.FOV / 2) + (i * stepAngle);
            let distance = 0;
            let hitWall = false;
            const cosA = Math.cos(rayAngle);
            const sinA = Math.sin(rayAngle);
            while (!hitWall && distance < 800) {
                distance += 2;
                const testX = player.x + cosA * distance;
                const testY = player.y + sinA * distance;
                if (world.isWall(testX, testY)) {
                    hitWall = true;
                }
            }
            // Correcting for wall height and perspective
            let wallHeight = (Consts.TILE_SIZE * 10) / (distance * Math.cos(rayAngle - player.angle));
            if (wallHeight > canvas.height)
                wallHeight = canvas.height;
            const brightness = Math.max(0, 255 - (distance / 3));
            ctx.fillStyle = `rgb(${brightness}, ${brightness / 1.5}, ${brightness / 4})`;
            ctx.fillRect(i, (canvas.height - wallHeight) / 2, 1, wallHeight);
        }
        // Draw a simple gun overlay
        ctx.fillStyle = '#333';
        ctx.fillRect(canvas.width / 2 - 20, canvas.height - 40, 40, 40);
    }
    initMouse() {
        window.addEventListener('mousemove', (e) => {
            if (document.pointerLockElement === this.canvas) {
                this.player.angle += e.movementX * 0.003;
            }
        });
        window.addEventListener('mousedown', () => {
            if (this.gameActive && document.pointerLockElement === this.canvas) {
                const weapon = Consts.WEAPONS[this.player.weaponType];
                if (this.player.shoot(weapon)) {
                    // Simple visual feedback for shooting: flash the screen or gun
                }
            }
        });
        window.addEventListener('keydown', (e) => {
            if (e.key === '1')
                this.player.weaponType = 'pistol';
            if (e.key === '2')
                this.player.weaponType = 'shotgun';
            if (e.key === '3')
                this.player.weaponType = 'rocket';
        });
    }
}
exports.GameEngine = GameEngine;
// Entry Point
const engine = new GameEngine();
};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>