射箭游戏:Trae 一句话生成的“弓箭手挑战”

说到 射箭游戏 ,第一反应就是那种 拉弓、瞄准、松弦 的感觉------箭飞出去,正中靶心时的满足感能让人忍不住笑出声。

但真要自己写一个这样的游戏,要设计 弓箭物理轨迹、瞄准判定、靶心得分计算、关卡难度,每一步都是工程。

有了 Trae IDE,这些复杂的事一句话就能搞定。

💡 我想要的玩法

我脑子里的画面很明确:

  • 拉弓射箭的感觉要真实:能看到弓弦拉开,松手箭飞出;
  • 操作简单:鼠标点击或按住蓄力,松开就能发箭;
  • 精准瞄准靶子:射中靶心得分最高,边缘分数低一点;
  • 逐渐增加难度:靶子距离越来越远,或者会左右移动;
  • 画面清新:像射箭场一样,有木制靶子、草地背景。

于是我只输入了一句话:

"生成射箭游戏,玩家瞄准靶子并射箭,目标是射中靶心。"

✨ Trae 的"神操作"

几秒钟后,Trae 就给了我一个 完整的射箭游戏

弓箭射击手感到位 :点击蓄力,松开时箭会"嗖"地射出去;

靶子判定精准 :命中靶心显示高分,偏一点分数自动递减;

得分系统完善 :每一箭都有得分提示,实时累积分数;

渐进式挑战 :后面靶子会动起来,还会变小,更考验技术;

音效细节满分:拉弦有"嗡"的声音,命中靶心还有清脆提示音。

🧩 试玩体验

第一箭射出去的那一刻,我直接笑了:

🏹 第一发刚好中靶心 ,那种"精准狙击"的快感让人超满足;

🎯 后面靶子开始移动 ,我立刻紧张,算准时机才射出一箭;

🔥 箭射歪时,界面会显示偏差和分数,瞬间有"必须再试一次"的冲动。

Trae 生成的不只是"能射箭",而是 真能让你沉浸在射箭的过程里

🛠 想加花样?一句话就能实现

Trae 的玩法扩展简直上瘾,比如:

  • "加风向和风速影响" → 射箭变得更有技巧,要算风偏;
  • "加入倒计时模式" → 限时射中更多靶子才算赢;
  • "加弓箭升级系统" → 换强力弓,箭速更快、精准度更高;
  • "做一个多人对战模式" → 两个人轮流射,看谁分数高。

一句话,Trae 自动补上逻辑和 UI。

🎮 过去 vs 现在

过去写射箭游戏:

  • 设计 物理轨迹 & 瞄准机制
  • 得分判定 & 动态靶逻辑
  • 音效、动画、关卡

现在用 Trae:

👉 一句话 → 射箭核心功能直接上线;

👉 想升级 → 再说一句,Trae 秒补代码。

✅ 结语

如果你也想体验一下 从拉弓到命中靶心的爽感,打开 Trae,只需要输入:

"生成射箭游戏,玩家瞄准靶子并射箭,目标是射中靶心。"

几秒后,一个 能射、能瞄、能挑战自我 的射箭游戏就能玩上:箭飞得漂亮,靶心打得精准,成就感直接拉满。

这就是 Trae 的魅力 ------ 一句话,就能让你成为游戏里的"神射手"。

ini 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>射箭游戏</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            background-color: #f0f8ff;
            overflow: hidden;
        }
        
        .game-container {
            position: relative;
            width: 800px;
            height: 600px;
            margin-top: 20px;
            border: 2px solid #333;
            background-image: linear-gradient(to bottom, #87ceeb, #e0f7fa);
            overflow: hidden;
        }
        
        .target {
            position: absolute;
            right: 100px;
            top: 50%;
            transform: translateY(-50%);
            width: 120px;
            height: 120px;
            border-radius: 50%;
            background: radial-gradient(
                circle,
                #ff0000 10%,
                #ffffff 10%, #ffffff 20%,
                #0000ff 20%, #0000ff 30%,
                #ffffff 30%, #ffffff 40%,
                #ff0000 40%, #ff0000 50%,
                #ffffff 50%, #ffffff 60%,
                #0000ff 60%, #0000ff 70%,
                #ffffff 70%, #ffffff 80%,
                #ff0000 80%, #ff0000 90%,
                #ffff00 90%
            );
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
        }
        
        .archer {
            position: absolute;
            left: 50px;
            bottom: 50px;
            width: 60px;
            height: 100px;
            background-color: #8b4513;
            border-radius: 10px 10px 0 0;
        }
        
        .bow {
            position: absolute;
            left: 110px;
            bottom: 100px;
            width: 10px;
            height: 60px;
            background-color: #a0522d;
            border-radius: 5px;
            transform-origin: center;
            transform: rotate(0deg);
        }
        
        .arrow {
            position: absolute;
            width: 50px;
            height: 5px;
            background-color: #8b4513;
            border-radius: 0 5px 5px 0;
            display: none;
        }
        
        .arrow::before {
            content: '';
            position: absolute;
            right: -10px;
            top: -5px;
            border-left: 10px solid #8b4513;
            border-top: 7.5px solid transparent;
            border-bottom: 7.5px solid transparent;
        }
        
        .arrow::after {
            content: '';
            position: absolute;
            left: 0;
            top: -2.5px;
            width: 10px;
            height: 10px;
            background-color: #708090;
            border-radius: 50%;
        }
        
        .controls {
            margin-top: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        
        .power-meter {
            width: 200px;
            height: 20px;
            border: 1px solid #333;
            margin-bottom: 10px;
            position: relative;
        }
        
        .power-fill {
            height: 100%;
            width: 0%;
            background-color: #ff6347;
            transition: width 0.1s;
        }
        
        .angle-control {
            width: 200px;
            margin-bottom: 10px;
        }
        
        .score-board {
            margin-top: 10px;
            font-size: 24px;
            font-weight: bold;
        }
        
        button {
            padding: 10px 20px;
            background-color: #4caf50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
            margin: 5px;
        }
        
        button:hover {
            background-color: #45a049;
        }
        
        .wind-indicator {
            position: absolute;
            top: 20px;
            left: 20px;
            background-color: rgba(255, 255, 255, 0.7);
            padding: 5px 10px;
            border-radius: 5px;
            font-size: 14px;
        }
        
        .instructions {
            margin-top: 20px;
            text-align: center;
            max-width: 600px;
            background-color: rgba(255, 255, 255, 0.7);
            padding: 10px;
            border-radius: 5px;
        }
        
        .game-options {
            display: flex;
            justify-content: space-between;
            width: 100%;
            margin-top: 15px;
            padding: 10px;
            background-color: rgba(255, 255, 255, 0.7);
            border-radius: 5px;
        }
        
        .difficulty {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        select {
            padding: 5px 10px;
            border-radius: 5px;
            border: 1px solid #ccc;
            background-color: white;
            font-size: 14px;
        }
        
        #reset-btn {
            background-color: #ff6347;
        }
        
        #reset-btn:hover {
            background-color: #e55a40;
        }
    </style>
</head>
<body>
    <h1>射箭游戏</h1>
    
    <div class="game-container">
        <div class="target"></div>
        <div class="archer"></div>
        <div class="bow"></div>
        <div class="arrow"></div>
        <div class="wind-indicator">风力: <span id="wind-value">0</span></div>
    </div>
    
    <div class="controls">
        <label for="angle">角度: <span id="angle-value">45</span>°</label>
        <input type="range" id="angle" class="angle-control" min="0" max="90" value="45">
        
        <div class="power-meter">
            <div class="power-fill" id="power-fill"></div>
        </div>
        <button id="shoot-btn">按住蓄力,松开射箭</button>
        
        <div class="score-board">
            分数: <span id="score">0</span>
        </div>
        
        <div class="game-options">
            <button id="reset-btn">重置游戏</button>
            
            <div class="difficulty">
                <label for="difficulty">难度:</label>
                <select id="difficulty-select">
                    <option value="easy">简单</option>
                    <option value="medium" selected>中等</option>
                    <option value="hard">困难</option>
                </select>
            </div>
        </div>
    </div>
    
    <div class="instructions">
        <h3>游戏说明</h3>
        <p>1. 调整角度滑块来改变射箭角度</p>
        <p>2. 按住射箭按钮蓄力,松开发射</p>
        <p>3. 注意风力影响,风力为正时箭向右偏,为负时向左偏</p>
        <p>4. 射中靶心得10分,外圈依次为9、8、7、6、5分</p>
    </div>
    
    <script>
        // 获取DOM元素
        const gameContainer = document.querySelector('.game-container');
        const target = document.querySelector('.target');
        const bow = document.querySelector('.bow');
        const arrow = document.querySelector('.arrow');
        const angleInput = document.getElementById('angle');
        const angleValue = document.getElementById('angle-value');
        const powerFill = document.getElementById('power-fill');
        const shootBtn = document.getElementById('shoot-btn');
        const scoreElement = document.getElementById('score');
        const windValue = document.getElementById('wind-value');
        const resetBtn = document.getElementById('reset-btn');
        const difficultySelect = document.getElementById('difficulty-select');
        
        // 游戏变量
        let power = 0;
        let angle = 45;
        let score = 0;
        let wind = 0;
        let isCharging = false;
        let arrowFlying = false;
        let arrowX = 0;
        let arrowY = 0;
        let arrowVelocityX = 0;
        let arrowVelocityY = 0;
        let gravity = 0.2;
        let windStrength = 1.0; // 风力强度系数
        let animationId = null;
        let difficulty = 'medium';
        
        // 难度设置
        const difficultySettings = {
            easy: {
                gravity: 0.15,
                windStrength: 0.5,
                targetSize: 1.2
            },
            medium: {
                gravity: 0.2,
                windStrength: 1.0,
                targetSize: 1.0
            },
            hard: {
                gravity: 0.25,
                windStrength: 1.5,
                targetSize: 0.8
            }
        };
        
        // 初始化游戏
        function initGame() {
            // 设置初始角度
            updateAngle(45);
            
            // 应用难度设置
            applyDifficulty();
            
            // 生成随机风力
            updateWind();
            
            // 重置分数
            score = 0;
            scoreElement.textContent = score;
            
            // 重置箭
            resetArrow();
        }
        
        // 应用难度设置
        function applyDifficulty() {
            difficulty = difficultySelect.value;
            const settings = difficultySettings[difficulty];
            
            // 应用重力和风力设置
            gravity = settings.gravity;
            windStrength = settings.windStrength;
            
            // 调整目标大小
            target.style.transform = `translateY(-50%) scale(${settings.targetSize})`;
        }
        
        // 更新风力
        function updateWind() {
            // 根据难度调整风力范围
            wind = Math.round((Math.random() * 10 - 5) * windStrength * 10) / 10;
            windValue.textContent = wind > 0 ? `+${wind}` : wind;
        }
        
        // 更新角度
        function updateAngle(newAngle) {
            angle = newAngle;
            angleValue.textContent = angle;
            bow.style.transform = `rotate(${-angle}deg)`;
        }
        
        // 蓄力
        function chargePower() {
            if (arrowFlying) return;
            
            isCharging = true;
            power = 0;
            
            function increasePower() {
                if (!isCharging) return;
                
                power += 2;
                if (power > 100) power = 100;
                
                powerFill.style.width = `${power}%`;
                
                if (power < 100) {
                    requestAnimationFrame(increasePower);
                }
            }
            
            increasePower();
        }
        
        // 射箭
        function shootArrow() {
            if (arrowFlying || !isCharging) return;
            
            isCharging = false;
            arrowFlying = true;
            
            // 设置箭的初始位置 - 修正计算方式,确保从弓的正确位置发射
            const bowRect = bow.getBoundingClientRect();
            const containerRect = gameContainer.getBoundingClientRect();
            
            // 根据弓的角度计算箭的起始位置
            const radians = angle * Math.PI / 180;
            const bowCenterX = bowRect.left + bowRect.width / 2 - containerRect.left;
            const bowCenterY = bowRect.top + bowRect.height / 2 - containerRect.top;
            
            // 箭从弓的末端发射
            const bowLength = bowRect.height;
            arrowX = bowCenterX + Math.cos(radians) * (bowLength / 2);
            arrowY = bowCenterY - Math.sin(radians) * (bowLength / 2);
            
            // 计算初始速度
            const speed = power * 0.2;
            arrowVelocityX = Math.cos(radians) * speed;
            arrowVelocityY = -Math.sin(radians) * speed;
            
            // 显示箭
            arrow.style.display = 'block';
            arrow.style.left = `${arrowX}px`;
            arrow.style.top = `${arrowY}px`;
            arrow.style.transform = `rotate(${-angle}deg)`;
            
            // 开始动画
            animateArrow();
        }
        
        // 箭的动画
        function animateArrow() {
            // 应用重力和风力
            arrowVelocityY += gravity;
            arrowVelocityX += wind * 0.01;
            
            // 更新位置
            arrowX += arrowVelocityX;
            arrowY += arrowVelocityY;
            
            // 计算箭的角度
            const arrowAngle = Math.atan2(arrowVelocityY, arrowVelocityX) * 180 / Math.PI;
            
            // 更新箭的位置和旋转
            arrow.style.left = `${arrowX}px`;
            arrow.style.top = `${arrowY}px`;
            arrow.style.transform = `rotate(${arrowAngle}deg)`;
            
            // 检查是否击中目标
            const hit = checkHit();
            
            // 如果击中目标,停止动画循环
            if (hit) {
                return;
            }
            
            // 检查是否超出边界
            const containerWidth = gameContainer.clientWidth;
            const containerHeight = gameContainer.clientHeight;
            
            if (arrowX > containerWidth || arrowY > containerHeight || arrowX < 0) {
                resetArrow();
                // 如果箭未击中目标并超出边界,更新风力
                updateWind();
                return;
            }
            
            // 继续动画
            animationId = requestAnimationFrame(animateArrow);
        }
        
        // 检查是否击中目标
        function checkHit() {
            const targetRect = target.getBoundingClientRect();
            const containerRect = gameContainer.getBoundingClientRect();
            
            const targetX = targetRect.left + targetRect.width / 2 - containerRect.left;
            const targetY = targetRect.top + targetRect.height / 2 - containerRect.top;
            const targetRadius = targetRect.width / 2;
            
            // 计算箭到目标中心的距离
            const dx = arrowX - targetX;
            const dy = arrowY - targetY;
            const distance = Math.sqrt(dx * dx + dy * dy);
            
            // 如果箭在目标范围内
            if (distance <= targetRadius) {
                // 停止箭的动画
                cancelAnimationFrame(animationId);
                
                // 计算得分 (根据距离到中心的比例)
                const hitRatio = distance / targetRadius;
                let hitScore = 0;
                
                if (hitRatio <= 0.1) hitScore = 10;      // 靶心
                else if (hitRatio <= 0.2) hitScore = 9;  // 第一圈
                else if (hitRatio <= 0.3) hitScore = 8;  // 第二圈
                else if (hitRatio <= 0.4) hitScore = 7;  // 第三圈
                else if (hitRatio <= 0.5) hitScore = 6;  // 第四圈
                else if (hitRatio <= 0.6) hitScore = 5;  // 第五圈
                else if (hitRatio <= 0.7) hitScore = 4;  // 第六圈
                else if (hitRatio <= 0.8) hitScore = 3;  // 第七圈
                else if (hitRatio <= 0.9) hitScore = 2;  // 第八圈
                else hitScore = 1;                       // 第九圈
                
                // 更新分数
                score += hitScore;
                scoreElement.textContent = score;
                
                // 显示得分效果
                showHitEffect(arrowX, arrowY, hitScore);
                
                // 让箭保持在目标上一段时间,然后再消失
                setTimeout(() => {
                    resetArrow();
                    // 更新风力
                    updateWind();
                }, 800);
                
                return true; // 表示已击中
            }
            
            return false; // 表示未击中
        }
        
        // 显示命中效果
        function showHitEffect(x, y, hitScore) {
            const effect = document.createElement('div');
            effect.textContent = `+${hitScore}`;
            effect.style.position = 'absolute';
            effect.style.left = `${x}px`;
            effect.style.top = `${y}px`;
            effect.style.color = hitScore === 10 ? 'gold' : 'white';
            effect.style.fontWeight = 'bold';
            effect.style.fontSize = hitScore === 10 ? '24px' : '18px';
            effect.style.textShadow = '0 0 5px black';
            effect.style.zIndex = '100';
            effect.style.pointerEvents = 'none';
            
            gameContainer.appendChild(effect);
            
            // 动画效果
            let opacity = 1;
            let posY = y;
            
            function animateEffect() {
                opacity -= 0.02;
                posY -= 1;
                
                effect.style.opacity = opacity;
                effect.style.top = `${posY}px`;
                
                if (opacity > 0) {
                    requestAnimationFrame(animateEffect);
                } else {
                    gameContainer.removeChild(effect);
                }
            }
            
            animateEffect();
        }
        
        // 重置箭
        function resetArrow() {
            cancelAnimationFrame(animationId);
            arrow.style.display = 'none';
            arrowFlying = false;
            powerFill.style.width = '0%';
        }
        
        // 事件监听
        angleInput.addEventListener('input', () => {
            updateAngle(parseInt(angleInput.value));
        });
        
        // 鼠标事件 - 修复鼠标移出按钮区域的问题
        shootBtn.addEventListener('mousedown', () => {
            chargePower();
            // 添加全局鼠标事件,确保即使鼠标移出按钮也能触发射箭
            document.addEventListener('mouseup', handleGlobalMouseUp);
        });
        
        function handleGlobalMouseUp() {
            if (isCharging) {
                shootArrow();
            }
            document.removeEventListener('mouseup', handleGlobalMouseUp);
        }
        
        // 触摸事件
        shootBtn.addEventListener('touchstart', chargePower);
        shootBtn.addEventListener('touchend', shootArrow);
        
        // 键盘控制
        document.addEventListener('keydown', (e) => {
            // 空格键射箭
            if (e.code === 'Space' && !arrowFlying && !isCharging) {
                chargePower();
            }
            // 上下箭头调整角度
            if (e.code === 'ArrowUp') {
                const newAngle = Math.min(angle + 5, 90);
                angleInput.value = newAngle;
                updateAngle(newAngle);
            }
            if (e.code === 'ArrowDown') {
                const newAngle = Math.max(angle - 5, 0);
                angleInput.value = newAngle;
                updateAngle(newAngle);
            }
        });
        
        document.addEventListener('keyup', (e) => {
            // 松开空格键射箭
            if (e.code === 'Space' && isCharging) {
                shootArrow();
            }
        });
        
        // 触摸设备上防止滚动
        gameContainer.addEventListener('touchmove', (e) => {
            e.preventDefault();
        }, { passive: false });
        
        // 页面离开时清理
        window.addEventListener('beforeunload', () => {
            cancelAnimationFrame(animationId);
        });
        
        // 重置按钮事件
        resetBtn.addEventListener('click', () => {
            initGame();
        });
        
        // 难度选择事件
        difficultySelect.addEventListener('change', () => {
            applyDifficulty();
            updateWind();
        });
        
        // 初始化游戏
        initGame();
    </script>
</body>
</html>
相关推荐
无责任此方_修行中32 分钟前
每日一技:当 Vuepress 插件失灵时,我是如何让 AI 帮我解决问题的
前端·vuepress·trae
程序员爱钓鱼4 小时前
Go语言实战案例:TCP服务器与客户端通信
google·go·trae
程序员爱钓鱼4 小时前
Go语言实战案例:多协程并发下载网页内容
google·go·trae
云_杰4 小时前
利用AI开发我又又上架了一个鸿蒙产品——青蓝程序员工具箱
harmonyos·trae
Goboy6 小时前
魔术方块:Trae一句话生成的“空间魔术”
trae
兵临天下api7 小时前
【干货满满】如何使用Python的requests库调用API接口?
trae
露琪亚8 小时前
使用飞书多维表 给 Trae 添加记忆或任务能力!
trae
前端卧龙人8 小时前
让Trae实现一个颜色搭配神器
trae
葫芦和十三8 小时前
Go 泛型“黑话”:any 和 interface{} 完全一样吗?
后端·go·trae