Maison  >  Article  >  interface Web  >  Parlons de la façon d'utiliser Uniapp pour développer un jeu de serpent !

Parlons de la façon d'utiliser Uniapp pour développer un jeu de serpent !

青灯夜游
青灯夜游avant
2022-05-20 19:56:185344parcourir

Comment utiliser Uniapp pour développer un jeu de serpent ? L'article suivant vous guidera étape par étape pour implémenter le jeu Snake dans uniapp. J'espère qu'il vous sera utile !

Parlons de la façon d'utiliser Uniapp pour développer un jeu de serpent !

La première fois que j'ai joué à Snake, je me souviens encore vaguement que c'était le premier jeu que mon père a joué pour moi après ?️

Ce petit jeu a été développé en utilisant uniappuniapp开发

前置详细内容就不细说了详细看:https://juejin.cn/post/7085727363547283469#heading-14

游戏演示

Parlons de la façon dutiliser Uniapp pour développer un jeu de serpent !

代码结构

详细代码结构如果需要请到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

Pré- contenu détaillé, je n'entrerai pas dans les détails. Regardez-le de plus près : https://juejin.cn/post/7085727363547283469#heading-14

Démo du jeu

Structure du code

Si vous avez besoin de la structure détaillée du code, veuillez vous rendre sur github
à voir

Il est principalement divisé en : démarrage du jeu, Terre, corps de serpent, bugs, terre polluée, effets sonores du jeu
<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>

Rendu du corps de serpent strong>

Mettez notre serpent dans son manteau Le rendu du corps du serpent est basé sur des serpents (avec le corps du serpent à l'intérieur) pour correspondre à l'index du panneau de sol pour trouver la grille correspondante et modifier l'image de fond pour restituer le corps du serpent, la tête du serpent et la queue, qui consiste à prendre les serpentsLe 0ème et le dernier chiffre et à trouver la grille correspondante pour modifier l'image de fond actuelle

rrreee

Contrôler le direction du serpent

Contrôler la direction du serpent Côté PC, on écoute les événements du clavier pour retrouver les codes haut, bas, gauche et droite des touches du clavier correspondantes pour changer la direction du serpent . Côté mobile, nous déterminons la direction du serpent en utilisant les valeurs de l'axe XY des points de contact des doigts et des points de glissement au moment du toucher
rrreee

. Ajoutez des effets sonores au serpent gourmand

L'ajout d'effets sonores du jeu rendra le jeu plus immersif. Nous devons maintenant ajouter une musique de fond, cliquer sur de la musique interactive et des pets de serpent à la musique du serpent, un serpent mangeant de la nourriture, un bug. musique de compte à rebours d'explosion et musique d'explosion de bugs

Ajoutez d'abord une musique de fond, il y a toujours des gens sans scrupules qui peuvent jouer jusqu'à ce que la carte soit pleine. Si vous souhaitez mettre la musique de fond en boucle, il vous suffit de le faire. Utilisez uni.createInnerAudioContext pour créer et renvoyer l'objet innerAudioContext de contexte audio interne pour obtenir le chemin de la musique et configurer la lecture automatique🎜rrreee🎜La musique de fond sonne et continue après la fin du jeu. Le son m'a soudainement rendu impatient. Ensuite, nous avons mis la musique de fond en pause après le jeu du serpent pause et la musique a été mise en pause sans être claire🎜rrreee🎜La première musique a été ajoutée avec succès et le reste était beaucoup. plus facile. Explosion de bugs Le compte à rebours doit également exploser ou après la fin du jeu, l'effet sonore du compte à rebours stop doit être effacé (la lecture suivante commencera depuis le début). doit être effacé. Le code restant est joint ci-dessous🎜rrreee🎜Conclusion🎜🎜Remerciements spéciaux 🎜@大marshalold ape🎜🎜@La fin est encore à venir🎜 Merci au professeur Dashuai pour son leadership, ses conseils et sa supervision quotidienne, et des remerciements particuliers. à ses coéquipiers pour leur aide et leur soutien. 🎜🎜Recommandé : "🎜tutoriel uniapp🎜"🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer