海底捞鱼:一句话生成的“深海挑战”

说到 ​海底捞鱼 ​,第一反应就是:​拿着网,一边捕鱼一边小心别捞到炸弹 ​。 以前要自己写这样的小游戏,得设计 ​渔网移动逻辑、鱼群生成、炸弹判定、得分系统​,还得调 UI 和动画。

现在有了 ​Trae IDE​,一句话,一个"能玩的、好玩的"捕鱼游戏就出现了。

💡 我想要的玩法

脑子里画的场景很简单:

  • 玩家能移动渔网:左右移动,按下就能下网捕捞;
  • 各种鱼随机游动:小鱼大鱼都有,速度也不一样;
  • 海里混着炸弹:要小心,捞到就扣分或者直接 Game Over;
  • 难度递增:随着时间,鱼游得更快,炸弹也更多;
  • 画面要轻松可爱:像卡通风格的海底世界。

于是我只输入了一句话:

"生成一个海底捞鱼游戏,玩家控制渔网捕捞海里的鱼,避免捕捞到炸弹。"

✨ Trae 是怎么"秒变游戏"的

没几秒钟,Trae 就交付了一个 ​完整的海底捞鱼​:

✅ ​渔网控制顺滑 ​:左右键/滑动屏幕都能操作,按键就能下网; ✅ ​鱼群随机出现 ​:不同大小、颜色的鱼,不停从屏幕游过; ✅ ​炸弹混在其中 ​:看起来无害,但一旦被捞到,直接爆炸; ✅ ​计分系统完善 ​:捕到鱼得分,捞到炸弹扣命,界面上实时显示分数; ✅ ​渐进式难度​:随着时间,鱼游得更快,炸弹更频繁,游戏越来越紧张。

🧩 试玩体验

第一次玩就上瘾:

🐟 ​开局很轻松 ​,随便下网就能捞到鱼; 💣 ​突然一个炸弹混进来 ​,我眼疾手快地收网,差点炸了; 🔥 ​难度上来后​,鱼群乱窜、炸弹乱飞,手忙脚乱的那种紧张感超刺激。

Trae 自动生成的版本,不光是能玩,​还很有"街机游戏"的感觉​,让人忍不住一局接一局。

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

Trae 的乐趣在于 ​说一句就能加玩法​,比如:

  • "加稀有金鱼,捞到得分翻倍" → 给玩家一个小惊喜;
  • "加入时间模式,60 秒内拼分数" → 短局游戏更刺激;
  • "加上技能,比如护盾网或磁力网" → 游戏策略性更强;
  • "让海底有宝箱,偶尔掉落道具" → 增加随机奖励,玩起来更爽。

不用手写复杂逻辑,Trae 自动补好代码和动画。

🎮 过去 vs 现在

过去写捕鱼游戏​:

  • 设计 鱼的运动轨迹
  • 炸弹判定逻辑
  • 渔网操作和计分系统
  • 难度递增机制

费时、麻烦,还容易出 bug。

现在用 Trae ​: 👉 一句话 → 核心玩法秒完成; 👉 想扩展 → 直接说,立刻补逻辑。

✅ 结语

如果你也想做一个 "捕鱼+炸弹+反应力" 的小游戏,打开 Trae,只要输入:

"生成一个海底捞鱼游戏,玩家控制渔网捕捞海里的鱼,避免捕捞到炸弹。"

几秒后,你就能玩到一个 ​轻松又刺激的海底世界​:鱼游得欢快,炸弹随时威胁,分数越刷越想破纪录。

这就是 Trae 的魅力 ------ 一句话,把你的创意变成一个真能玩的游戏。

html 复制代码
<!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>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        

        body {
            font-family: 'Arial', sans-serif;
            background-color: #87CEEB;
            display: flex;
            justify-content: center;
            align-items: center;

            height: 100vh;
            overflow: hidden;
        }
        
        .game-container {
            position: relative;

            width: 800px;

            height: 600px;
            background: linear-gradient(to bottom, #1E90FF, #000080);

            border-radius: 10px;

            box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
            overflow: hidden;
        }
        
        .score-container {
            position: absolute;
            top: 20px;
            left: 20px;
            background-color: rgba(255, 255, 255, 0.7);
            padding: 10px 15px;
            border-radius: 5px;
            font-size: 18px;
            font-weight: bold;
            color: #333;
            z-index: 10;
        }
        
        .time-container {
            position: absolute;
            top: 20px;
            right: 20px;
            background-color: rgba(255, 255, 255, 0.7);
            padding: 10px 15px;
            border-radius: 5px;

            font-size: 18px;
            font-weight: bold;
            color: #333;
            z-index: 10;
        }
        
        .net {
            position: absolute;
            width: 80px;
            height: 80px;
            background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="45" fill="none" stroke="white" stroke-width="2"/><line x1="5" y1="50" x2="95" y2="50" stroke="white" stroke-width="2"/><line x1="50" y1="5" x2="50" y2="95" stroke="white" stroke-width="2"/><line x1="15" y1="15" x2="85" y2="85" stroke="white" stroke-width="2"/><line x1="15" y1="85" x2="85" y2="15" stroke="white" stroke-width="2"/></svg>');
            background-size: cover;
            cursor: pointer;
            z-index: 5;
            transform-origin: center bottom;
        }
        
        .fish {
            position: absolute;
            width: 50px;
            height: 30px;
            background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 60"><path d="M20,30 Q40,10 70,30 Q40,50 20,30 Z" fill="orange" stroke="black" stroke-width="2"/><circle cx="25" cy="25" r="3" fill="black"/><path d="M70,30 L90,15 L90,45 Z" fill="orange" stroke="black" stroke-width="2"/></svg>');
            background-size: cover;
            z-index: 3;
        }
        
        .fish-gold {
            background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 60"><path d="M20,30 Q40,10 70,30 Q40,50 20,30 Z" fill="gold" stroke="black" stroke-width="2"/><circle cx="25" cy="25" r="3" fill="black"/><path d="M70,30 L90,15 L90,45 Z" fill="gold" stroke="black" stroke-width="2"/></svg>');
        }
        
        .fish-blue {
            background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 60"><path d="M20,30 Q40,10 70,30 Q40,50 20,30 Z" fill="lightblue" stroke="black" stroke-width="2"/><circle cx="25" cy="25" r="3" fill="black"/><path d="M70,30 L90,15 L90,45 Z" fill="lightblue" stroke="black" stroke-width="2"/></svg>');

        }
        
        .bomb {
            position: absolute;
            width: 40px;
            height: 40px;
            background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="60" r="35" fill="black" stroke="gray" stroke-width="2"/><rect x="45" y="10" width="10" height="20" fill="gray"/><path d="M45,10 Q50,0 55,10" fill="none" stroke="red" stroke-width="3"/></svg>');
            background-size: cover;
            z-index: 3;
        }
        
        .bubble {
            position: absolute;
            border-radius: 50%;
            background-color: rgba(255, 255, 255, 0.3);
            z-index: 2;
        }
        
        .seaweed {
            position: absolute;
            bottom: 0;
            width: 30px;
            height: 100px;
            background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 200"><path d="M30,200 Q10,150 30,100 Q50,50 30,0" fill="none" stroke="green" stroke-width="5"/></svg>');
            background-size: cover;
            z-index: 1;

        }
        
        .game-over {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.7);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 20;
            display: none;
        }
        
        .game-over-title {
            font-size: 48px;
            font-weight: bold;

            color: white;
            margin-bottom: 20px;
            text-align: center;
        }
        
        .final-score {
            font-size: 36px;
            color: white;
            margin-bottom: 30px;
            text-align: center;
        }
        
        .restart-button {

            padding: 15px 30px;
            font-size: 20px;
            font-weight: bold;
            background-color: #4CAF50;
            color: white;

            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .restart-button:hover {
            background-color: #45a049;
            transform: scale(1.05);
        }
        
        .start-screen {

            position: absolute;

            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.7);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 20;
        }
        
        .start-screen-title {
            font-size: 48px;
            font-weight: bold;
            color: white;
            margin-bottom: 20px;
            text-align: center;
        }
        
        .start-screen-subtitle {
            font-size: 24px;
            color: white;
            margin-bottom: 30px;
            text-align: center;
            max-width: 80%;
            line-height: 1.4;
        }
        
        .start-button {
            padding: 15px 30px;
            font-size: 20px;
            font-weight: bold;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .start-button:hover {
            background-color: #45a049;
            transform: scale(1.05);
        }

        
        .catch-animation {
            animation: catch 0.5s ease-out;
        }
        
        @keyframes catch {
            0% { transform: scale(1); opacity: 1; }

            100% { transform: scale(0); opacity: 0; }
        }
        
        .explosion {
            position: absolute;
            width: 100px;
            height: 100px;
            background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="orange"/><circle cx="50" cy="50" r="30" fill="yellow"/><path d="M50,10 L55,25 L70,15 L60,30 L80,35 L60,45 L75,60 L55,55 L60,80 L45,65 L30,85 L35,65 L10,70 L30,55 L15,40 L35,45 L25,25 L45,35 Z" fill="red"/></svg>');
            background-size: cover;
            z-index: 6;
            animation: explode 0.5s ease-out forwards;
        }
        

        @keyframes explode {
            0% { transform: scale(0); opacity: 1; }
            50% { transform: scale(1.5); opacity: 1; }
            100% { transform: scale(2); opacity: 0; }

        }
    </style>
</head>

<body>

    <div class="game-container" id="game-container">

        <div class="score-container">
            分数: <span id="score">0</span>

        </div>
        
        <div class="time-container">
            时间: <span id="time">60</span>秒
        </div>
        

        <div class="net" id="net"></div>
        
        <div class="game-over" id="game-over">

            <div class="game-over-title">游戏结束</div>

            <div class="final-score">最终得分: <span id="final-score">0</span></div>
            <button class="restart-button" id="restart-button">再玩一次</button>

        </div>
        
        <div class="start-screen" id="start-screen">
            <div class="start-screen-title">海底捞鱼</div>
            <div class="start-screen-subtitle">用鼠标控制渔网捕捞海里的鱼,获得分数。金色鱼可获得更多分数!小心炸弹,碰到炸弹会扣分!</div>
            <button class="start-button" id="start-button">开始游戏</button>
        </div>
    </div>
    
    <script>
        // 游戏元素
        const gameContainer = document.getElementById('game-container');
        const net = document.getElementById('net');

        const scoreElement = document.getElementById('score');
        const timeElement = document.getElementById('time');
        const gameOver = document.getElementById('game-over');
        const finalScore = document.getElementById('final-score');
        const restartButton = document.getElementById('restart-button');

        const startScreen = document.getElementById('start-screen');
        const startButton = document.getElementById('start-button');
        
        // 游戏配置

        const containerWidth = gameContainer.offsetWidth;

        const containerHeight = gameContainer.offsetHeight;
        const netWidth = 80;
        const netHeight = 80;
        const fishGenerationInterval = 1000; // 毫秒
        const bombGenerationInterval = 3000; // 毫秒
        const gameTime = 60; // 秒
        
        // 游戏状态
        let score = 0;
        let timeLeft = gameTime;
        let fishes = [];
        let bombs = [];
        let bubbles = [];
        let gameRunning = false;
        let gameLoop;
        let fishInterval;
        let bombInterval;
        let timeInterval;
        
        // 初始化游戏
        function initGame() {
            // 隐藏开始屏幕

            startScreen.style.display = 'none';
            

            // 重置游戏状态
            score = 0;

            timeLeft = gameTime;
            fishes = [];
            bombs = [];
            bubbles = [];
            

            // 清除所有元素
            const existingElements = document.querySelectorAll('.fish, .bomb, .bubble, .seaweed, .explosion');
            existingElements.forEach(element => element.remove());
            
            // 更新显示
            scoreElement.textContent = score;
            timeElement.textContent = timeLeft;
            
            // 创建海草背景
            createSeaweed();
            
            // 创建气泡
            createBubbles();
            
            // 开始游戏循环
            gameRunning = true;
            gameLoop = setInterval(updateGame, 16); // 约60帧每秒
            
            // 开始生成鱼
            fishInterval = setInterval(generateFish, fishGenerationInterval);
            
            // 开始生成炸弹

            bombInterval = setInterval(generateBomb, bombGenerationInterval);
            
            // 开始倒计时
            timeInterval = setInterval(() => {
                if (gameRunning) {
                    timeLeft--;
                    timeElement.textContent = timeLeft;

                    
                    if (timeLeft <= 0) {
                        endGame();
                    }
                }

            }, 1000);
            
            // 设置渔网初始位置
            net.style.left = `${containerWidth / 2 - netWidth / 2}px`;
            net.style.top = `${containerHeight / 2 - netHeight / 2}px`;
        }
        
        // 创建海草背景
        function createSeaweed() {
            for (let i = 0; i < 8; i++) {

                const seaweed = document.createElement('div');
                seaweed.className = 'seaweed';
                
                const x = Math.random() * containerWidth;
                const height = 100 + Math.random() * 100;
                
                seaweed.style.left = `${x}px`;
                seaweed.style.height = `${height}px`;

                
                gameContainer.appendChild(seaweed);
            }

        }
        
        // 创建气泡
        function createBubbles() {
            for (let i = 0; i < 20; i++) {
                generateBubble();
            }
            
            // 定期生成新气泡
            setInterval(() => {

                if (gameRunning && bubbles.length < 30) {
                    generateBubble();
                }
            }, 1000);
        }
        
        // 生成单个气泡
        function generateBubble() {
            const bubble = document.createElement('div');
            bubble.className = 'bubble';
            
            const size = 5 + Math.random() * 20;
            const x = Math.random() * containerWidth;
            const y = containerHeight;
            const speed = 1 + Math.random() * 2;
            
            bubble.style.width = `${size}px`;

            bubble.style.height = `${size}px`;
            bubble.style.left = `${x}px`;
            bubble.style.bottom = `0px`;

            
            gameContainer.appendChild(bubble);
            
            bubbles.push({
                element: bubble,
                x: x,
                y: 0,
                speed: speed
            });
        }

        
        // 生成鱼
        function generateFish() {
            if (!gameRunning) return;

            
            const fish = document.createElement('div');
            fish.className = 'fish';
            
            // 随机鱼的类型
            const fishType = Math.random();
            if (fishType < 0.2) {

                fish.classList.add('fish-gold');
            } else if (fishType < 0.5) {

                fish.classList.add('fish-blue');
            }
            

            const fishWidth = 50;
            const fishHeight = 30;
            
            // 随机鱼的位置和方向
            const fromRight = Math.random() > 0.5;
            const x = fromRight ? containerWidth : -fishWidth;
            const y = 50 + Math.random() * (containerHeight - 150);
            const speed = 1 + Math.random() * 3;
            
            fish.style.left = `${x}px`;
            fish.style.top = `${y}px`;
            
            // 设置鱼的方向
            if (fromRight) {
                fish.style.transform = 'scaleX(-1)';
            }
            
            gameContainer.appendChild(fish);
            
            fishes.push({
                element: fish,
                x: x,
                y: y,

                width: fishWidth,

                height: fishHeight,
                speed: speed,
                fromRight: fromRight,
                type: fishType < 0.2 ? 'gold' : (fishType < 0.5 ? 'blue' : 'normal'),
                caught: false
            });
        }
        
        // 生成炸弹
        function generateBomb() {
            if (!gameRunning) return;
            

            const bomb = document.createElement('div');
            bomb.className = 'bomb';
            
            const bombWidth = 40;
            const bombHeight = 40;
            
            // 随机炸弹的位置
            const x = Math.random() * (containerWidth - bombWidth);
            const y = -bombHeight;
            const speed = 1 + Math.random() * 2;
            
            bomb.style.left = `${x}px`;
            bomb.style.top = `${y}px`;
            
            gameContainer.appendChild(bomb);

            
            bombs.push({

                element: bomb,
                x: x,
                y: y,
                width: bombWidth,
                height: bombHeight,
                speed: speed,
                exploded: false
            });
        }

        
        // 更新游戏状态
        function updateGame() {
            if (!gameRunning) return;
            

            // 更新鱼的位置
            fishes.forEach((fish, index) => {
                if (!fish.caught) {
                    if (fish.fromRight) {
                        fish.x -= fish.speed;
                    } else {
                        fish.x += fish.speed;

                    }
                    
                    fish.element.style.left = `${fish.x}px`;
                    
                    // 检查是否超出屏幕
                    if ((fish.fromRight && fish.x + fish.width < 0) || 
                        (!fish.fromRight && fish.x > containerWidth)) {
                        fish.element.remove();
                        fishes.splice(index, 1);
                    }
                }
            });
            
            // 更新炸弹的位置
            bombs.forEach((bomb, index) => {
                if (!bomb.exploded) {
                    bomb.y += bomb.speed;
                    bomb.element.style.top = `${bomb.y}px`;
                    
                    // 检查是否超出屏幕
                    if (bomb.y > containerHeight) {

                        bomb.element.remove();
                        bombs.splice(index, 1);
                    }
                }
            });
            
            // 更新气泡的位置
            bubbles.forEach((bubble, index) => {
                bubble.y += bubble.speed;

                bubble.element.style.bottom = `${bubble.y}px`;
                
                // 检查是否超出屏幕
                if (bubble.y > containerHeight) {
                    bubble.element.remove();
                    bubbles.splice(index, 1);
                }
            });

        }
        

        // 检查碰撞
        function checkCollision(net, object) {
            const netRect = net.getBoundingClientRect();
            const objectRect = object.element.getBoundingClientRect();

            
            return !(netRect.right < objectRect.left || 
                   netRect.left > objectRect.right || 
                   netRect.bottom < objectRect.top || 
                   netRect.top > objectRect.bottom);
        }
        
        // 捕获鱼
        function catchFish(fish) {
            if (fish.caught) return;

            
            fish.caught = true;

            fish.element.classList.add('catch-animation');

            
            // 根据鱼的类型增加分数
            let points = 10;
            if (fish.type === 'gold') {
                points = 50;
            } else if (fish.type === 'blue') {
                points = 20;
            }
            
            score += points;
            scoreElement.textContent = score;
            
            // 移除鱼
            setTimeout(() => {

                fish.element.remove();

                const index = fishes.indexOf(fish);
                if (index > -1) {
                    fishes.splice(index, 1);
                }
            }, 500);
        }
        
        // 炸弹爆炸
        function explodeBomb(bomb) {
            if (bomb.exploded) return;
            
            bomb.exploded = true;
            
            // 创建爆炸效果
            const explosion = document.createElement('div');
            explosion.className = 'explosion';
            explosion.style.left = `${bomb.x - 30}px`;
            explosion.style.top = `${bomb.y - 30}px`;
            gameContainer.appendChild(explosion);
            

            // 扣分
            score = Math.max(0, score - 30);
            scoreElement.textContent = score;
            
            // 移除炸弹和爆炸效果
            setTimeout(() => {
                bomb.element.remove();
                explosion.remove();
                const index = bombs.indexOf(bomb);
                if (index > -1) {
                    bombs.splice(index, 1);
                }
            }, 500);
        }
        
        // 结束游戏
        function endGame() {
            gameRunning = false;
            clearInterval(gameLoop);
            clearInterval(fishInterval);
            clearInterval(bombInterval);

            clearInterval(timeInterval);
            
            // 显示游戏结束界面

            gameOver.style.display = 'flex';
            document.getElementById('final-score').textContent = score;
        }
        
        // 鼠标控制渔网
        gameContainer.addEventListener('mousemove', (e) => {
            if (!gameRunning) return;

            
            const rect = gameContainer.getBoundingClientRect();
            const x = e.clientX - rect.left - netWidth / 2;

            const y = e.clientY - rect.top - netHeight / 2;
            

            // 限制渔网在游戏区域内
            const boundedX = Math.max(0, Math.min(containerWidth - netWidth, x));
            const boundedY = Math.max(0, Math.min(containerHeight - netHeight, y));

            
            net.style.left = `${boundedX}px`;
            net.style.top = `${boundedY}px`;
            
            // 检查是否捕获鱼
            fishes.forEach(fish => {
                if (!fish.caught && checkCollision(net, fish)) {
                    catchFish(fish);
                }
            });

            
            // 检查是否碰到炸弹
            bombs.forEach(bomb => {

                if (!bomb.exploded && checkCollision(net, bomb)) {
                    explodeBomb(bomb);
                }
            });
        });
        

        // 触摸控制(移动设备)
        gameContainer.addEventListener('touchmove', (e) => {
            if (!gameRunning) return;

            e.preventDefault();
            
            const rect = gameContainer.getBoundingClientRect();

            const touch = e.touches[0];
            const x = touch.clientX - rect.left - netWidth / 2;
            const y = touch.clientY - rect.top - netHeight / 2;
            
            // 限制渔网在游戏区域内
            const boundedX = Math.max(0, Math.min(containerWidth - netWidth, x));
            const boundedY = Math.max(0, Math.min(containerHeight - netHeight, y));
            

            net.style.left = `${boundedX}px`;
            net.style.top = `${boundedY}px`;
            
            // 检查是否捕获鱼
            fishes.forEach(fish => {
                if (!fish.caught && checkCollision(net, fish)) {
                    catchFish(fish);
                }
            });
            
            // 检查是否碰到炸弹
            bombs.forEach(bomb => {
                if (!bomb.exploded && checkCollision(net, bomb)) {
                    explodeBomb(bomb);
                }
            });
        }, { passive: false });
        
        // 事件监听
        restartButton.addEventListener('click', () => {
            gameOver.style.display = 'none';
            initGame();
        });
        
        startButton.addEventListener('click', () => {
            initGame();
        });
    </script>
</body>
</html>
相关推荐
围巾哥萧尘4 小时前
TRAE 最佳实践征文大赛 | Trae + Supabase + Vercel 的理解与运用:TodoList 案例展示🧣
trae
lgc6534 小时前
TRAE和playwright MCP完成E2E测试
aigc·trae
小厂永远得不到的男人5 小时前
用 Trae + 自制 MCP 构建 AI 工具链:从理论到实战的全流程解析
trae
CF14年老兵5 小时前
🎮 把 GitHub 变成游戏厅!(吃豆人 + 贪吃蛇 + 炫酷奖杯!)
前端·后端·trae
小厂永远得不到的男人5 小时前
用Trae搭智能体的实战笔记:从0到1造出你的专属AI助手
trae
一点一木5 小时前
Trae 实测系列 #1:30 分钟用中文 AI 编程搞定 Vue3 + Pinia 倒计时应用
前端·ai编程·trae
Goboy6 小时前
飞行射击:Trae 一句话生成的“空中战场”
trae
围巾哥萧尘6 小时前
Trae.ai的发展历程和软件更新🧣
trae
我想说一句7 小时前
bubu智聘App亮点详解(2) Coze工作流接入
前端·前端框架·trae