搜尋
首頁web前端uni-app聊聊如何利用uniapp開發一個貪吃蛇小遊戲吧!

如何利用uniapp開發一個貪吃蛇小遊戲?以下這篇文章就手把手帶大家在uniapp中實現貪吃蛇小遊戲,希望對大家有幫助!

聊聊如何利用uniapp開發一個貪吃蛇小遊戲吧!

第一次玩貪吃蛇還隱約記得是?️後父親給我玩的第一個遊戲

該小遊戲使用uniapp開發

前置詳細內容就不細說了詳細看:https://juejin.cn/post/7085727363547283469#heading-14

#遊戲示範

聊聊如何利用uniapp開發一個貪吃蛇小遊戲吧!

程式碼結構

詳細程式碼結構如果需要請到github查看

#主要分為:開始遊戲、地塊、蛇身、蟲子、污染地塊,遊戲音效

<template>
	<view ref="body" class="content">
		<view>蛇蛇目前:{{snakes.length}}米长</view>
		<view class="game-field">
                <!-- 地面板块 -->
		  <view class="block"  v-for="(x, i) in blocks" :key="i"></view>
		</view>
                    <view v-show="!started || ended" class="game-board-wrap">
                        <view v-show="!started" class="game-board">
                            <view class="title">选择游戏难度</view>
                            <radio-group name="radio" @change="bindLevelChange">
                                <label class="label">
                                    <radio value="1" :checked="level==1" /><text>简单模式</text>
                                </label>
                                <label class="label">
                                    <radio value="2" :checked="level==2" /><text>正常模式</text>
                                </label>
                                <label class="label">
                                    <radio value="3" :checked="level==3" /><text>困难模式</text>
                                </label>
                                <label class="label">
                                    <radio value="4" :checked="level==4" /><text>地狱模式</text>
                                </label>
                            </radio-group>
                            <button type="primary" @click="start">开始游戏</button>
                        </view>
			<view v-show="ended" class="settle-board">
                            <view class="title">游戏结束</view>
                            <view class="result">您的蛇蛇达到了{{snakes.length}}米</view>
                            <view class="btns">
                                <button type="primary" @click="reStart">再次挑战</button>
                                <button type="primary" plain @click="rePick">重选难度</button>
                            </view>
			</view>
		</view>
	</view>
</template>
<script>
export default {
    data() {
            return {
                blocks: [], // 板块
                worms: [], // 虫子
                snakes: [0, 1, 2, 3], // 蛇身
                direction: "right", // 蛇移动方向
            };
    },
    onLoad() {
        this.initGame();
    },
    methods: {
        initGame() {
            this.blocks = new Array(100).fill(0); // 生成100个地面板块
            this.worms = [Math.floor(Math.random() * 96) + 4]; // 随机生成虫子
            this.snakes = [0, 1, 2, 3]; // 初始化蛇身位置
        }
    }
}
</script>

#渲染蛇身

給我們的蛇穿上他的外衣 蛇身的渲染根據snakes(裡邊放著蛇的身體)來匹配地面板塊的索引從而找到對應的格格並修改背景圖來渲染蛇身蛇頭和蛇尾就是取snakes第0位和最後一位並找到對應的格格修改當前背景圖

<template>
    <view class="game-field">
        <view class="block" :style="`background-image: ${bg(x, i)}" v-for="(x, i) in blocks" :key="i">
        </view>
    </view>
</template>
<script>
import worm from "worm.png";
import snakeBody from "snake_body.png";
import snakeHead from "snake_head.png";
import snakeTail from "snake_tail.png";
import polluteBlock from "pollute.png";
import wormBoom from "worm_4.png";
export default {
    methods: {
        bg(type, index) {
            let bg = "";
            switch (type) {
                case 0: // 地板
                    bg = "unset";
                    break;
                case 1: // 虫子
                    if (this.boom) {
                            bg = `url(${wormBoom})`;
                    } else {
                            bg = `url(${worm})`;
                    }
                    break;
                case 2: // 蛇
                    let head = this.snakes[this.snakes.length - 1];
                    let tail = this.snakes[0];
                    if (index === head) {
                            bg = `url(${snakeHead})`;
                    } else if (index === tail) {
                            bg = `url(${snakeTail})`;
                    } else {
                            bg = `url(${snakeBody})`;
                    }
                    break;
                case 3: // 污染的地块
                    bg = `url(${polluteBlock})`;
                    break;
            }
            return bg;
        },
    }
}
</scipt>

控制蛇的方向

控制蛇的方向pc端我們透過監聽鍵盤事件找到對應的鍵盤鍵的編碼上下左右來改變蛇的方向而手機端我們通過touch時間手指觸摸點及滑動點的XY軸值來判斷蛇的方向

<template>
<view ref="body" class="content" @keyup.left="bindLeft" @keyup.right="bindRight" @keyup.down="bindDown"
@keyup.up="bindUp" @touchstart="handleTouchStart" @touchmove="handleTouchMove">
    <view>蛇蛇目前:{{snakes.length}}米长</view>
    <view class="game-field">
        <view class="block" :style="`background-image: ${bg(x, i)}; v-for="(x, i) in blocks" :key="i"></view>
    </view>
</view>
</template>
<script>
    export default {
        data(){
            return {
                direction: "right",
                started: false, // 游戏开始了
                ended: false, // 游戏结束了
                level: 1, // 游戏难度
                lastX: 0,
                lastY: 0,
            }
        },
        onLoad() {
            this.initGame();
        },
        methods:{
            initGame() {
                this.blocks = new Array(100).fill(0); // 生成100个地面板块
                this.worms = [Math.floor(Math.random() * 96) + 4]; // 随机生成虫子
                this.snakes = [0, 1, 2, 3]; // 初始化蛇身位置
                document.onkeydown = (e) => {
                    switch (e.keyCode) { // 获取当前按下键盘键的编码
                        case 37: // 按下左箭头键
                            this.bindLeft();
                            break;
                        case 39: // 按下右箭头键
                            this.bindRight();
                            break;
                        case 38: // 按下上箭头键
                            if (!this.started) {
                                    this.level--;
                            } else {
                                    this.bindUp();
                            }
                            break;
                        case 40: // 按下下箭头键
                            if (!this.started) {
                                    this.level++;
                            } else {
                                    this.bindDown();
                            }
                            break;
                    }
                }
            },
            handleTouchStart(e) {
                // 手指开始位置
                this.lastX = e.touches[0].pageX;
                this.lastY = e.touches[0].pageY;
            },
            handleTouchMove(e) {
                let lastX = e.touches[0].pageX; // 移动的x轴坐标
                let lastY = e.touches[0].pageY; // 移动的y轴坐标

                let touchX = lastX - this.lastX;
                let touchY = lastY - this.lastY
                if (Math.abs(touchX) > Math.abs(touchY)) {
                if (touchX < 0) {
                    if(this.direction === "right") return;
                    this.direction = &#39;left&#39;
                    } else if (touchX > 0) {
                        if(this.direction === "left") return;
                        this.direction = &#39;right&#39;
                    }
                } else {
                    if (touchY < 0) {
                        if(this.direction === "down") return;
                        this.direction = &#39;up&#39;
                    } else if (touchY > 0) {
                        if(this.direction === "up") return;
                        this.direction = &#39;down&#39;
                    }
                }
                this.lastX = lastX;
                this.lastY = lastY;
            },
            bindUp() {
                if (this.direction === "down") return;
                this.direction = "up";
            },
            bindDown() {
                if (this.direction === "up") return;
                this.direction = "down";
            },
            bindLeft() {
                if (this.direction === "right") return;
                this.direction = "left";
            },
            bindRight() {
                if (this.direction === "left") return;
                this.direction = "right";
            },
        }
    }
</script>

給貪吃蛇添加音效

添加遊戲音效遊戲代入感就強了很多現在我們要給蛇加上背景音樂、點擊互動音樂、蛇隔兒屁的音樂、蛇吃掉食物的音樂、蟲子爆炸倒數的音樂和蟲子爆炸的音樂

先給添加上背景音樂總有刁民可以玩到地圖滿為止背景音樂的話要loop播放我們只需要 使用uni.createInnerAudioContext來創建並返回內部audio 上下文 innerAudioContext 物件拿到音樂的路徑並且設定自動播放

<script>
import bgm from &#39;bgm.mp3&#39;;
export default {
    data(){
        return {
            bgmInnerAudioContext:null,
        }
    },
    methods:{
        start() { // 开始游戏
            this.initGame();
            this.handleBgmVoice()
        },
        handleBgmVoice() {
            // 背景音乐
            this.bgmInnerAudioContext = uni.createInnerAudioContext() // 创建上下文
            this.bgmInnerAudioContext.autoplay = true; // 自动播放
            this.bgmInnerAudioContext.src= bgm; // 音频地址
            this.bgmInnerAudioContext.loop = true; // 循环播放
        }
    }
}
<script>

背景音樂確實響起來了蛇gameover後還一直響頓時我聽著就不耐煩這時我們在蛇gameover後暫停背景音樂pause音樂會暫停而不會清楚

<script>
import bgm from &#39;bgm.mp3&#39;;
export default {
    data(){
        return {
            bgmInnerAudioContext:null,
        }
    },
    methods:{
        start() { // 开始游戏
            this.initGame();
            this.handleBgmVoice()
        },
        handleBgmVoice() {
            // 背景音乐
            this.bgmInnerAudioContext = uni.createInnerAudioContext() // 创建上下文
            this.bgmInnerAudioContext.autoplay = true; // 自动播放
            this.bgmInnerAudioContext.src= bgm; // 音频地址
            this.bgmInnerAudioContext.loop = true; // 循环播放
        }
        checkGame(direction, next) {
            let gameover = false;
            let isSnake = this.snakes.indexOf(next) > -1;
            let isPollute = this.pollutes.indexOf(next) > -1;
            // 撞到蛇和被污染的地块游戏结束
            if (isSnake || isPollute) {
                gameover = true;
            }
            // 撞到边界游戏结束
            switch (direction) {
                case "up":
                    if (next < 0) {
                            gameover = true;
                    }
                    break;
                case "down":
                    if (next >= 100) {
                            gameover = true;
                    }
                    break;
                case "left":
                    if (next % 10 === 9) {
                            gameover = true;
                    }
                    break;
                case "right":
                    if (next % 10 === 0) {
                            gameover = true;
                    }
                    break;
            }
            return gameover;
        },
        toWards(direction) {
            let gameover = this.checkGame(direction, next);
            if (gameover) {
                this.ended = true;
                this.handleDieVoice()
                this.bgmInnerAudioContext.pause() // 游戏结束 暂停背景音乐
                clearInterval(this.timer);
                clearInterval(this.boomTimer);
            } else {
                // 游戏没结束
                this.snakes.push(next);
                let nextType = this.blocks[next];
                this.blocks[next] = 2;
                // 如果是空白格
                if (nextType === 0) {
                    this.snakes.shift();
                } else {
                    // 如果是虫子格
                    this.handleEatVoice() // 吃掉虫子后的音乐
                    this.worms = this.worms.filter((x) => x !== next);
                    let nextWorm = this.createWorm();
                    this.worms.push(nextWorm);
                }
                this.blocks[tail] = 0;
                this.paint();
            }
        },
    }
}
<script>

首個音樂添加成功其他的也就簡單多了蟲子爆炸倒數計時也需要爆炸或gameover後需要清楚倒數計時音效stop(下次播放會從頭開始) 剩餘的不需要清楚音效和循環播放下面附上剩餘的代碼

<script>
export default {
    data() {
        return {
             bgmInnerAudioContext:null,
             clockInnerAudioContext:null,
        }
    },
    watch: {
        boomCount(val) {
            if (val === 0) {
                // 超过爆炸时间还没吃到,则将虫子格子变成被污染的土地,并且重置爆炸状态,同时生成一只新的虫子:
                this.handleExplodeVoice() // 爆炸的音乐
                this.clockInnerAudioContext.stop() // 清楚倒计时音乐
                const boomWorm = this.worms.pop();
                this.pollutes.push(boomWorm);
                this.blocks[boomWorm] = 3; // 被污染的地方我们用3表示
                this.boom = false;
                this.worms.push(this.createWorm());
            }
        }
    },
    methods:{
        // 蛇吃到食物后的声音
        handleEatVoice() {
            const innerAudioContext = uni.createInnerAudioContext();
            innerAudioContext.autoplay = true;
            innerAudioContext.src = eatVoice;
        },
        // 虫子污染爆炸后的声音
        handleExplodeVoice(){
            const innerAudioContext = uni.createInnerAudioContext();
            innerAudioContext.autoplay = true;
            innerAudioContext.src = explodeVoice;
        },
        // 游戏背景音乐
        handleBgmVoice() {
            this.bgmInnerAudioContext = uni.createInnerAudioContext()
            this.bgmInnerAudioContext.autoplay = true;
            this.bgmInnerAudioContext.src= bgm;
            this.bgmInnerAudioContext.loop = true;
        },
        // 按钮点击的声音
        handleClickVoice() {
            const innerAudioContext = uni.createInnerAudioContext()
            innerAudioContext.autoplay = true;
            innerAudioContext.src= click;
        },
        // 爆炸倒计时的声音
        handleClockVoice() {
            this.clockInnerAudioContext = uni.createInnerAudioContext()
            this.clockInnerAudioContext.autoplay = true;
            this.clockInnerAudioContext.src= clock;
        },
        // 蛇gameover后的声音
        handleDieVoice() {
            const innerAudioContext = uni.createInnerAudioContext()
            innerAudioContext.autoplay = true;
            innerAudioContext.src= die;
        },
        checkGame(direction, next) {
            let gameover = false;
            let isSnake = this.snakes.indexOf(next) > -1;
            let isPollute = this.pollutes.indexOf(next) > -1;
            // 撞到蛇和被污染的地块游戏结束
            if (isSnake || isPollute) {
                gameover = true;
            }
            // 撞到边界游戏结束
            switch (direction) {
                case "up":
                    if (next < 0) {
                            gameover = true;
                    }
                    break;
                case "down":
                    if (next >= 100) {
                            gameover = true;
                    }
                    break;
                case "left":
                    if (next % 10 === 9) {
                            gameover = true;
                    }
                    break;
                case "right":
                    if (next % 10 === 0) {
                            gameover = true;
                    }
                    break;
            }
            return gameover;
        },
        paint() {
            this.worms.forEach((x) => {
                this.blocks[x] = 1;
            });
            this.snakes.forEach((x) => {
                this.blocks[x] = 2;
            });
            this.$forceUpdate();
        },
        toWards(direction) {
            let gameover = this.checkGame(direction, next);
            if (gameover) {
                this.ended = true;
                this.handleDieVoice()
                this.bgmInnerAudioContext.pause() // 游戏结束 暂停背景音乐
                this.clockInnerAudioContext && this.clockInnerAudioContext.stop() // 清楚倒计时音乐
                clearInterval(this.timer);
                clearInterval(this.boomTimer);
            } else {
                // 游戏没结束
                this.snakes.push(next);
                let nextType = this.blocks[next];
                this.blocks[next] = 2;
                // 如果是空白格
                if (nextType === 0) {
                    this.snakes.shift();
                } else {
                    // 如果是虫子格
                    this.handleEatVoice() // 吃掉虫子后的音乐
                    this.worms = this.worms.filter((x) => x !== next);
                    let nextWorm = this.createWorm();
                    this.worms.push(nextWorm);
                }
                this.blocks[tail] = 0;
                this.paint();
            }
        },
        // 生成下一只虫子
        createWorm() {
            this.boom = false;
            let blocks = Array.from({
                    length: 100
            }, (v, k) => k);
            // 在不是蛇和被污染的地方生成虫子
            let restBlocks = blocks.filter(x => this.snakes.indexOf(x) < 0 && this.pollutes.indexOf(x) < 0);
            let worm = restBlocks[Math.floor(Math.random() * restBlocks.length)];
            // 根据游戏难度,概率产出会爆炸的虫子:
            this.boom = Math.random() / this.level < 0.05;
            // 生成了新虫子说明吃到了那个爆炸的虫子,重置下爆炸
            if (this.boom) {
                this.boomCount = 10;
                this.boomTimer && clearInterval(this.boomTimer);
                this.handleClockVoice()
                this.boomTimer = setInterval(() => {
                        this.boomCount--;
                }, 1000)
            } else {
                this.clockInnerAudioContext && this.clockInnerAudioContext.stop()
                clearInterval(this.boomTimer);
            }
            return worm;
        },
    }
}
<script>

結論

特別鳴謝@大帥老猿@末世未然 感謝大帥老師的帶領及指導以及每天的督促,也特別的感謝隊友的幫助與支持

原始碼位址:https://github.com/MothWillion/snake_eat_worm

##原文網址:https://juejin.cn /post/7087525655478272008

作者:Sophora

推薦:《

uniapp教學

以上是聊聊如何利用uniapp開發一個貪吃蛇小遊戲吧!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金社区。如有侵權,請聯絡admin@php.cn刪除
您如何在不同平台(例如移動,Web)上調試問題?您如何在不同平台(例如移動,Web)上調試問題?Mar 27, 2025 pm 05:07 PM

本文討論了有關移動和網絡平台的調試策略,突出顯示了Android Studio,Xcode和Chrome DevTools等工具,以及在OS和性能優化的一致結果的技術。

哪些調試工具可用於Uniapp開發?哪些調試工具可用於Uniapp開發?Mar 27, 2025 pm 05:05 PM

文章討論了用於Uniapp開發的調試工具和最佳實踐,重點關注Hbuilderx,微信開發人員工具和Chrome DevTools等工具。

您如何為Uniapp應用程序執行端到端測試?您如何為Uniapp應用程序執行端到端測試?Mar 27, 2025 pm 05:04 PM

本文討論了跨多個平台的Uniapp應用程序的端到端測試。它涵蓋定義測試方案,選擇諸如Appium和Cypress之類的工具,設置環境,寫作和運行測試,分析結果以及集成

您可以在Uniapp應用程序中執行哪些不同類型的測試?您可以在Uniapp應用程序中執行哪些不同類型的測試?Mar 27, 2025 pm 04:59 PM

本文討論了針對Uniapp應用程序的各種測試類型,包括單元,集成,功能,UI/UX,性能,跨平台和安全測試。它還涵蓋了確保跨平台兼容性,並推薦Jes等工具

Uniapp中有哪些常見的性能反版?Uniapp中有哪些常見的性能反版?Mar 27, 2025 pm 04:58 PM

本文討論了UNIAPP開發中的共同績效抗模式,例如過度的全球數據使用和效率低下的數據綁定,並提供策略來識別和減輕這些問題,以提高應用程序性能。

您如何使用分析工具來識別uniapp中的性能瓶頸?您如何使用分析工具來識別uniapp中的性能瓶頸?Mar 27, 2025 pm 04:57 PM

本文討論了使用分析工具來識別和解決Uniapp中的性能瓶頸,重點是設置,數據分析和優化。

您如何在Uniapp中優化網絡請求?您如何在Uniapp中優化網絡請求?Mar 27, 2025 pm 04:52 PM

本文討論了在UNIAPP中優化網絡請求的策略,重點是減少延遲,實施緩存以及使用監視工具來增強應用程序性能。

如何優化Uniapp中的Web性能的圖像?如何優化Uniapp中的Web性能的圖像?Mar 27, 2025 pm 04:50 PM

本文討論了通過壓縮,響應式設計,懶惰加載,緩存和使用WebP格式來優化Uniapp中的圖像,以更好地進行Web性能。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用