原生js+css实现勇者生存游戏代码

代码语言:html

所属分类:游戏

代码描述:原生js+css实现勇者生存游戏代码,移动上下左键逃避围攻,存活15秒就算赢。

代码标签: 原生 js css 勇者 生存 游戏 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS Survivors</title>
<style>
    @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');

    body {
        margin: 0;
        padding: 0;
        background-color: #111;
        overflow: hidden;
        font-family: 'Press Start 2P', cursive;
        user-select: none;
    }

    #gameCanvas {
        display: block;
    }

    /* UI Overlays */
    .overlay {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        background: rgba(0, 0, 0, 0.8);
        color: white;
        z-index: 10;
        text-align: center;
    }

    .hidden { display: none !important; }

    h1 { color: #ff4444; text-shadow: 4px 4px #000; font-size: 48px; margin-bottom: 20px; }
    h2 { color: #ffd700; text-shadow: 2px 2px #000; margin-bottom: 30px; }
    p { line-height: 1.5; font-size: 14px; color: #ccc; max-width: 600px; margin: 10px auto; }

    button {
        background: #444;
        color: white;
        border: 4px solid #fff;
        padding: 15px 30px;
        font-family: 'Press Start 2P', cursive;
        font-size: 16px;
        cursor: pointer;
        margin: 10px;
        transition: all 0.2s;
        image-rendering: pixelated;
        box-shadow: 0 6px #222;
        position: relative;
        top: 0;
    }

    button:hover { background: #666; top: -2px; box-shadow: 0 8px #222; }
    button:active { top: 4px; box-shadow: 0 2px #222; }

    /* HUD */
    #hud {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        pointer-events: none;
        padding: 10px;
        box-sizing: border-box;
        z-index: 5;
    }

    .xp-container {
        width: 100%;
        height: 20px;
        background: #222;
        border: 2px solid #fff;
        position: relative;
    }

    #xpBar {
        height: 100%;
        background: #00bfff;
        width: 0%;
        transition: width 0.2s;
    }

    #levelText {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        color: white;
        font-size: 12px;
        text-shadow: 1px 1px 0 #000;
    }

    .top-info {
        display: flex;
        justify-content: space-between;
        margin-top: 10px;
        color: white;
        font-size: 16px;
        text-shadow: 2px 2px 0 #000;
    }

    /* Level Up Menu */
    #levelUpMenu {
        background: rgba(20, 20, 40, 0.95);
        border: 4px solid #4466ff;
        padding: 20px;
        border-radius: 10px;
        max-width: 800px;
    }

    #upgradeContainer {
        display: flex;
        gap: 20px;
        justify-content: center;
        flex-wrap: wrap;
        margin-top: 20px;
    }

    .upgrade-card {
        background: #2a2a4a;
        border: 3px solid #fff;
        width: 200px;
        padding: 15px;
        cursor: pointer;
        transition: transform 0.2s, background 0.2s;
        display: flex;
        flex-direction: column;
        align-items: center;
    }

    .upgrade-card:hover {
        transform: scale(1.05);
        background: #3a3a5a;
        border-color: #ffd700;
    }

    .upgrade-icon {
        width: 64px;
        height: 64px;
        margin-bottom: 10px;
        background-color: #000;
        display: flex;
        justify-content: center;
        align-items: center;
        border: 2px solid #666;
    }
    
    .upgrade-title { color: #ffd700; font-size: 12px; margin-bottom: 5px; }
    .upgrade-type { color: #aaa; font-size: 8px; margin-bottom: 10px; }
    .upgrade-desc { color: #fff; font-size: 10px; line-height: 1.4; }
    .new-tag { background: #ff4444; color: white; padding: 2px 5px; font-size: 8px; position: absolute; top: 5px; right: 5px; }

    /* Canvas icons generated via CSS/Canvas later */
    .icon-canvas { width: 48px; height: 48px; }

</style>
</head>
<body>

<!-- CANAVS -->
<canvas id="gameCanvas"></canvas>

<!-- HUD -->
<div id="hud">
    <div class="xp-container">
        <div id="xpBar"></div>
        <div id="levelText">LV 1</div>
    </div>
    <div class="top-info">
        <div id="timer">00:00</div>
        <div id="killCount">💀 0</div>
    </div>
</div>

<!-- MENUS -->
<div id="startScreen" class="overlay">
    <h1>JS SURVIVORS</h1>
    <p>Survive for 15 minutes against endless hordes.</p>
    <p>WASD/Arrows to move. Attacks are automatic.</p>
    <button id="btnStart">START GAME</button>
    <br>
    <p style="font-size: 10px; color: #666;">Enable audio for best experience</p>
</div>

<div id="pauseMenu" class="overlay hidden">
    <h2>PAUSED</h2>
    <div id="statsContainer" style="text-align: left; margin-bottom: 20px; font-size: 10px;"></div>
    <button id="btnResume">RESUME</button>
</div>

<div id="gameOverScreen" class="overlay hidden">
    <h1 id="goTitle" style="color: #ff0000;">GAME OVER</h1>
    <h2 id="goTime">Survived: 00:00</h2>
    <p id="goKills">Enemies Defeated: 0</p>
    <p id="goLevel">Level Reached: 1</p>
    <button id="btnRestart">TRY AGAIN</button>
</div>

<div id="victoryScreen" class="overlay hidden">
    <h1 style="color: #ffd700;">VICTORY!</h1>
    <p>You survived the night.</p>
    <p id="vKills">Total Kills: 0</p>
    <button id="btnRestartVic">PLAY AGAIN</button>
</div>

<div id="levelUpScreen" class="overlay hidden">
    <div id="levelUpMenu">
        <h2 style="color:#00bfff; margin: 0;">LEVEL UP!</h2>
        <p style="margin-bottom: 0;">Choose an upgrade</p>
        <div id="upgradeContainer">
            <!-- dynamically populated -->
        </div>
    </div>
</div>

<script>
/* 
=========================================================================
   JS SURVIVORS - ENGINE & GAME LOGIC
=========================================================================
*/

// --- COFIGURATION & CONSTANTS ---
const C = {
    WIDTH: window.innerWidth,
    HEIGHT: window.innerHeight,
    FPS: 60,
    TARGET_TIME: 15 * 60, // 15 minutes in seconds
    TILE_SIZE: 128, // For grid background
    COLORS: {
        bg: '#1a1a20',
        grid: '#252530',
        player: '#3388ff',
        xpInfo: '#00bfff',
        hp: '#ff3333',
        hpBg: '#440000',
        
        // Enemy Tiers
        e1: '#aa5555', // Bat
        e2: '#55aa55', // Zombie
        e3: '#6666aa', // Skeleton
        e4: '#aa55aa', // Ghost
        e5: '#aa8855', // Tank
        
        // XP Gems
        xp1: '#00bfff',
        xp2: '#00ff00',
        xp3: '#ff00ff',
        
        // Damage Numbers
        dmgWhite: '#ffffff',
        dmgCrit: '#ffff00'
    }
};

// Global Game State
const GS = {
    canvas: document.getElementById('gameCanvas'),
    ctx: document.getElementById('gameCanvas').getContext('2d', { alpha: false }),
    state: 'start', // start, running, paused, levelup, gameover, victory
    
    // Entities
    player: null,
    enemies: [],
    projectiles: [],
    gems: [],
    particles: [],
    damageTexts: [],
    
    // Systems
    camera: { x: 0, y: 0 },
    input: { up: false, down: false, left: false, right: false },
    audio: null,
    
    // Meta
    time: 0,
    kills: 0,
    frameCount: 0,
    lastTime: 0,
    dt: 0,
    screenShake: 0
};

// Resize handling
function resize() {
    C.WIDTH = window.innerWidth;
    C.HEIGHT = window.innerHeight;
    GS.canvas.width = C.WIDTH;
    GS.canvas.height = C.HEIGHT;
    GS.ctx.imageSmoothingEnabled = false;
}
window.addEventListener('resize', resize);
resize();

// --- MATH UTILS ---
const M = {
    dist: (x1, y1, x2, y2) => Math.hypot(x2 - x1, y2 - y1),
    distSq: (x1, y1, x2, y2) => (x2-x1)**2 + (y2-y1)**2,
    angle: (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1),
    rand: (min, max) => Math.random() * (max - min) + min,
    randInt: (min, max) => Math.floor(Math.random() * (max - min + 1)) + min,
    clamp: (val, min, max) => Math.min(Math.max(val, min), max),
    lerp: (a, b, t) => a + (b - a) * t,
    
    // Circle-Circle Collision
    collides: (a, b) => M.distSq(a.x, a.y, b.x, b.y) < (a.r + b.r)**2,
    
    // Rectangle-Circle (for beams)
    rectCircleCollides: (rect, circle) => {
        let dx .........完整代码请登录后点击上方下载按钮下载查看

网友评论0