HTML+js实现贪吃蛇小游戏(内含完整代码)

2023-05-16

案例分析

看图拆解游戏

首先我们根据图片上的内容把这个游戏拆解成几个部分去单独看:

  1. 最外面的大盒子包裹着内容加边框限制蛇的活动范围,整个范围可以看成由许多小方格排列构成的,例如这样子的:
  2. 两个按钮,一个控制开始游戏,一个控制游戏中途的暂停继续功能;
  3. 盒子里面有可以移动的蛇,最开始状态的蛇分为蛇头、蛇身、蛇尾三个部分,蛇只能走直线,通过上⬆下⬇左⬅右⬅的功能键去控制蛇的走向;
  4. 还有一个随机产生在限制区域内的食物;

这个游戏是当点击开始游戏按钮才显示蛇和食物的,所以最开始我们不在结构里面书写,后面通过js构造函数来生成,但是可以先把样式写了来,由此可知:我们的结构代码可以这么去写:

<body>
    <!-- 最外面盒子 -->
    <div class="content">
        <!-- 开始按钮 -->
        <div class="btn startBtn">
            <button></button>
        </div>
        <!-- 暂停按钮 -->
        <div class="btn pauseBtn">
            <button></button>
        </div>
        <!-- 蛇的活动范围 -->
        <div id="snakeWrap">
        </div>
    </div>
</body>

CSS样式代码是这样的:

.content {
    width: 640px;
    height: 640px;
    margin: 35px auto;
    position: relative;
}

.btn {
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
    background-color: rgba(0, 0, 0, .3);
    z-index: 2;
}

.btn button {
    background: none;
    border: none;
    background-size: 100% 100%;
    cursor: pointer;
    outline: none;
    position: absolute;
    left: 50%;
    top: 50%;
}

.startBtn button {
    width: 200px;
    height: 80px;
    background-image: url(../images/start.gif);
    margin-left: -100px;
    margin-top: -40px;
}

.pauseBtn {
    display: none;
}

.pauseBtn button {
    width: 70px;
    height: 70px;
    background-image: url(../images/pause.png);
    margin-left: -35px;
    margin-top: -35px;
}


/* snakeWrap */

#snakeWrap {
    position: relative;
    width: 600px;
    height: 600px;
    background-color: greenyellow;
    border: 20px solid green;
}

#snakeWrap div {
    width: 20px;
    height: 20px;
}

.snakeHead {
    background-image: url(../images/蛇头.png);
    background-size: cover;
}

.snakeBody {
    background-color: #808ca5;
    border-radius: 50%;
}

.food {
    background-image: url(../images/食物.png);
    background-size: cover;
}

蛇的活动范围分析:

下面的代码方块构造函数就是创建一个一个的方格,给每个方格设置了宽高,这个大小是经过计算的可以正好铺满整个蛇的活动范围的地砖,就好比我准备了一整个房间需要的地砖,但是只是准备了并没有拿出来;给原型添加或删除的函数是我具备了铺地装这样子的技术;现在就是人和了,坐等天时地利的时候使用。

js代码:

  var sw = 20, //一个方格的宽
        sh = 20, //一个方格的高
        tr = 30, //行数
        td = 30; //列数
    //方块构造函数
    function Square(x, y, classname) {
        //0,0    0,0
        //20,0   1,0
        //40,0   2,0
        this.x = x * sw;
        this.y = y * sh;
        this.class = classname;
        this.viewContent = document.createElement('div'); //方块对应的DOM元素
        this.viewContent.className = this.class; //方块所指元素
        this.parent = document.getElementById('snakeWrap'); //方块的父级
    }

    //单词prototype指的是原型
    //给原型添加
    Square.prototype.create = function() { //创建方块DOM,并添加到页面里
        this.viewContent.style.position = 'absolute';
        this.viewContent.style.width = sw + 'px';
        this.viewContent.style.height = sh + 'px';
        this.viewContent.style.left = this.x + 'px';
        this.viewContent.style.top = this.y + 'px';
        this.parent.appendChild(this.viewContent);
    };
    //删除
    Square.prototype.remove = function() {
        this.parent.removeChild(this.viewContent);
    };

创建对象——蛇的分析:

下面的代码看蛇的部分,想要蛇移动,必须先有蛇,开始的时候就说了蛇又分为三个部分蛇头、蛇身和蛇尾,蛇需要移动,蛇移动又分为上下左右四个方向,所以我们需要根据x和y的正负来判断它走的方向,当蛇转向的时候需要蛇头跟着转向,所以要添加一个rotate属性来确定蛇头的方向。

js代码:

    //蛇
    var snake = null;
    function Snake() {
        this.head = null; //存一下蛇头信息
        this.tail = null; //存一下蛇尾信息
        this.pos = []; //存蛇身上每一个方块的位置

        this.directionNum = { //存储蛇走的方向,用一个对象来表示
            left: {
                x: -1,
                y: 0,
                rotate: 180 // 蛇头在不同方向中应该进行旋转
            },
            right: {
                x: 1,
                y: 0
            },
            up: {
                x: 0,
                y: -1,
                rotate: -90
            },
            down: {
                x: 0,
                y: 1,
                rotate: 90
            }
        }
    }

初始化对象分析:

蛇有了,我们现在需要把蛇放到最开始的位置,设置坐标,这时候就初始化蛇,这里有个新的知识点就是链表关系,如下图,相当于在已知关系中确定各自的相对位置。

 js代码:

    //单词init指的是初始化
    Snake.prototype.init = function() {
        //创建一个蛇头
        var snakeHead = new Square(2, 0, 'snakeHead');
        snakeHead.create();
        this.head = snakeHead; //存储蛇头信息
        this.pos.push([2, 0]); //把蛇头的位置存起来

        //创建蛇身体1
        var snakeBody1 = new Square(1, 0, 'snakeBody');
        snakeBody1.create();
        this.pos.push([1, 0]); //把蛇身1的坐标也存起来

        //创建蛇身体2
        var snakeBody2 = new Square(0, 0, 'snakeBody');
        snakeBody2.create();
        this.tail = snakeBody2; //把蛇尾信息存起来
        this.pos.push([0, 0]); //把蛇身2的坐标也存起来

        //形成链表关系
        snakeHead.last = null;
        snakeHead.next = snakeBody1;

        snakeBody1.last = snakeHead;
        snakeBody1.next = snakeBody2;

        snakeBody2.last = snakeBody1;
        snakeBody2.next = null;

        //给蛇添加一个属性,用来表示蛇走的方向
        this.direction = this.directionNum.right; //默认让蛇往右走

    };

创建食物以及生成新的食物:

首先定义一个食物实例,食物的产生是随机的所以会用到随机数,但是食物产生的位置是有范围的,一是只能在一定区域内,所以需要设置参数使他不能超过边界;二是食物不能出现在蛇的身上,所以就需要判断是否在蛇身上,如果食物的位置与蛇身上的每一个身体部分的坐标不重合,就代表没有在蛇身上。

新的食物的生成条件是当蛇吃了食物(就代表场上没有食物了),才会生成新的食物。食物的消失条件就是去判断蛇头的下一个位置是否和食物的位置重合,如果重合就让食物消失。

js代码:

    //创建食物
    var food = null,//食物的实例
    function createFood() {
        //食物小方块的随机坐标
        var x = null;
        var y = null;

        var include = true; //循环跳出的条件,true表示随机生成食物的坐标在蛇身上(需要继续循环);false表示食物坐标不在蛇身上(不循环了)
        while (include) {
            x = Math.round(Math.random() * (td - 1));
            y = Math.round(Math.random() * (tr - 1));

            snake.pos.forEach(function(value) {
                if (x != value[0] && y != value[1]) {
                    //这个条件成立说明在随机出来的坐标,在蛇身上并没有找到
                    include = false;
                }
            });
        }

        //生成食物
        food = new Square(x, y, 'food');
        food.pos = [x, y]; //存储一下生成食物的坐标,用于跟蛇头要走的下一个点做对比

        var foodDom = document.querySelector('.food');
        if (foodDom) {
            foodDom.style.left = x * sw + 'px';
            foodDom.style.top = y * sh + 'px';
        } else {
            food.create();
        }


    }

判断蛇头下一步的位置分析:

蛇头下一步又分成4种情况:一是撞到自己的身体了,游戏结束;二是撞到围墙了,游戏结束;三是碰到食物了,吃掉食物;四是前面方格子什么也没有,继续走;每一种情况都对应一种结果。

js代码:

    //这个方法用来获取蛇头下一个位置对应的元素,要根据元素做不同的事情
    Snake.prototype.getNextPos = function() {
        var nextPos = [
            this.head.x / sw + this.direction.x,
            this.head.y / sh + this.direction.y
        ]

        //单词forEach代表遍历数组

        //(1)下个点是自己,代表撞到了自己,游戏结束
        var selfCollied = false; //是否撞到自己
        this.pos.forEach(function(value) {
            if (value[0] == nextPos[0] && value[1] == nextPos[1]) {
                //如果数组中两个数据都相等,说明下一个点在蛇身体里面能找到自己了
                selfCollied = true;
            }
        });
        if (selfCollied) {
            this.strategies.die.call(this);
            return;
        }

        //(2)下个点是围墙,代表撞到了围墙,游戏结束
        if (nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1) {
            this.strategies.die.call(this);
            return;
        }

        //(3)下个点是食物,吃
        if (food && food.pos[0] == nextPos[0] && food.pos[1] == nextPos[1]) {
            //如果这个条件成立,说明蛇头要走的下一个点是食物
            this.strategies.eat.call(this);
            return;
        }

        //(4)下个点什么都不是,走
        this.strategies.move.call(this); //call作用调用,也可以传参
    };

碰撞后要做的事情分析:

碰撞后要做的三件事:eat(吃)、die(死亡)、move(走)。

(一)eat很简单,调用一下创建食物的函数,食物被吃掉和产生新的食物;

(二)die也很简单,结束游戏,弹出得分对话框;

(三)move可能有点复杂,这里涉及到一个链表重新链接的情况。这个时候又要分为两种情况了:第一种:还没吃到食物的情况下,保持长度不变,每走一步就需要往前面一个方格里增加一个新身体,更新蛇头和蛇尾;第二种:吃到食物的情况,增加蛇身长度,继续更新蛇头位置并且在蛇头后的位置增加一个蛇身,原先的身上位置不改。可能文字看了还不懂,为此博主做了图示让大家能更好的理解。

图示:一句话概括,第一种情况如图第三步:新头是新头,旧头是新身,旧身是新尾;第二种情况如图第二步:新头是新头,旧头是新身,旧身还是旧身,旧尾还是旧尾。

第一步:newBody.next = this.head.next;新身体的next指向现在旧蛇头;

第二步:newBody.next.last = newBody;旧蛇头的上一个就指向现在的新蛇头了;

第三步:newBody.last = null;让新蛇头指向null,this.head.remove();删除旧蛇头,新身体替代旧蛇头的位置,除了吃食物增加身体长度外,其他的移动的情况都是this.tail.remove();  this.tail = this.tail.last;。每次移动都要创建一个新蛇头,更新一下链表关系:newHead.next = newBody;newHead.last = null;newBody.last = newHead;  并且根据移动方向调整一下头的方向。

js代码:

     //处理碰撞后要做的事
    Snake.prototype.strategies = {
        move: function(format) { //括号内参数用于决定要不要删除最后一个方块(蛇尾),当传来参数就表示要做的事情是吃
            //创建新身体(在旧蛇头的位置)
            var newBody = new Square(this.head.x / sw, this.head.y / sh, 'snakeBody');

            //更新链表关系
            newBody.next = this.head.next;
            newBody.next.last = newBody;
            newBody.last = null;

            this.head.remove(); //把旧蛇头从原来的位置删除
            newBody.create();

            //创建一个新蛇头(蛇头下一个要走到的点nextPos)
            var newHead = new Square(this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y, 'snakeHead');

            //更新链表关系
            newHead.next = newBody;
            newHead.last = null;
            newBody.last = newHead;
            newHead.viewContent.style.transform = 'rotate(' + this.direction.rotate + 'deg)';
            newHead.create();

            //蛇身上的每一个方块的坐标也要更新
            this.pos.splice(0, 0, [this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y])
            this.head = newHead; //还要把this.head的信息更新一下

            if (!format) { //如果format的值为false,表示需要删除(除了吃之外的操作)
                this.tail.remove();
                this.tail = this.tail.last;

                this.pos.pop();
            }

        },
        eat: function() {
            this.strategies.move.call(this, true);
            createFood();
            game.score++;
        },
        die: function() {
            // console.log('die');
            game.over();

        }
    }

    snake = new Snake();

游戏逻辑

开启游戏和暂停游戏,通过点击按钮的方法控制,游戏过程中通过功能键的which值去判断玩家按下的是上下左右哪个键来移动蛇。当蛇正在往左走的时候,⬅➡这两个键按下去就没有反应,只能按其他两个个键⬆⬇,同理可得,其他的也是一样。食物的生成需要通过一个定时器去控制它的自动出现。

js代码:

//创建游戏逻辑
    function Game() {
        this.timer = null;
        this.score = 0;
    }
    Game.prototype.init = function() {
        snake.init();
        createFood();
        document.onkeydown = function(ev) {
            if (ev.which == 37 && snake.direction != snake.directionNum.right) { //用户按下左键时,这条蛇不能是正在往右走
                snake.direction = snake.directionNum.left;
            } else if (ev.which == 38 && snake.direction != snake.directionNum.down) {
                snake.direction = snake.directionNum.up;
            } else if (ev.which == 39 && snake.direction != snake.directionNum.left) {
                snake.direction = snake.directionNum.right;
            } else if (ev.which == 40 && snake.direction != snake.directionNum.up) {
                snake.direction = snake.directionNum.down;
            }
        }

        this.start();

    }
    Game.prototype.start = function() { //开始游戏
        this.timer = setInterval(function() {
            snake.getNextPos();
        }, 200);
    }
    Game.prototype.pause = function() {
        clearInterval(this.timer);
    }
    Game.prototype.over = function() {
        clearInterval(this.timer);
        alert('你的得分为' + this.score);

        //游戏回到最初始的状态
        var snakeWrap = document.getElementById('snakeWrap');
        snakeWrap.innerHTML = '';
        snake = new Snake();
        game = new Game();
        var startBtnWrap = document.querySelector('.startBtn');
        startBtnWrap.style.display = 'block';
    }

    //开启游戏
    game = new Game();
    var startBtn = document.querySelector('.startBtn button');
    startBtn.onclick = function() {
        startBtn.parentNode.style.display = 'none';
        game.init();
    };

    //暂停游戏
    var snakeWrap = document.getElementById('snakeWrap');
    var pauseBtn = document.querySelector('.pauseBtn button');
    snakeWrap.onclick = function() {
        game.pause();
        pauseBtn.parentNode.style.display = 'block';
    };

    pauseBtn.onclick = function() {
        game.start();
        pauseBtn.parentNode.style.display = 'none';
    }
})

完整js代码

JavaScript:

window.addEventListener('load', function() {
    var sw = 20, //一个方格的宽
        sh = 20, //一个方格的高
        tr = 30, //行数
        td = 30; //列数

    var snake = null, //蛇的实例
        food = null, //食物的实例
        game = null; //游戏的实例


    //方块构造函数
    function Square(x, y, classname) {
        //0,0    0,0
        //20,0   1,0
        //40,0   2,0
        this.x = x * sw;
        this.y = y * sh;
        this.class = classname;

        this.viewContent = document.createElement('div'); //方块对应的DOM元素
        this.viewContent.className = this.class; //方块所指元素
        this.parent = document.getElementById('snakeWrap'); //方块的父级
    }

    //原型prototype

    //给原型添加
    Square.prototype.create = function() { //创建方块DOM,并添加到页面里
        this.viewContent.style.position = 'absolute';
        this.viewContent.style.width = sw + 'px';
        this.viewContent.style.height = sh + 'px';
        this.viewContent.style.left = this.x + 'px';
        this.viewContent.style.top = this.y + 'px';
        this.parent.appendChild(this.viewContent);
    };
    //删除
    Square.prototype.remove = function() {
        this.parent.removeChild(this.viewContent);
    };

    //蛇
    function Snake() {
        this.head = null; //存一下蛇头信息
        this.tail = null; //存一下蛇尾信息
        this.pos = []; //存蛇身上每一个方块的位置

        this.directionNum = { //存储蛇走的方向,用一个对象来表示
            left: {
                x: -1,
                y: 0,
                rotate: 180 // 蛇头在不同方向中应该进行旋转
            },
            right: {
                x: 1,
                y: 0
            },
            up: {
                x: 0,
                y: -1,
                rotate: -90
            },
            down: {
                x: 0,
                y: 1,
                rotate: 90
            }
        }
    }

    //init初始化
    Snake.prototype.init = function() {
        //创建一个蛇头
        var snakeHead = new Square(2, 0, 'snakeHead');
        snakeHead.create();
        this.head = snakeHead; //存储蛇头信息
        this.pos.push([2, 0]); //把蛇头的位置存起来

        //创建蛇身体1
        var snakeBody1 = new Square(1, 0, 'snakeBody');
        snakeBody1.create();
        this.pos.push([1, 0]); //把蛇身1的坐标也存起来

        //创建蛇身体2
        var snakeBody2 = new Square(0, 0, 'snakeBody');
        snakeBody2.create();
        this.tail = snakeBody2; //把蛇尾信息存起来
        this.pos.push([0, 0]); //把蛇身2的坐标也存起来

        //形成链表关系
        //蛇头
        snakeHead.last = null;
        snakeHead.next = snakeBody1;
        //蛇身
        snakeBody1.last = snakeHead;
        snakeBody1.next = snakeBody2;
        //蛇尾
        snakeBody2.last = snakeBody1;
        snakeBody2.next = null;

        //给蛇添加一个属性,用来表示蛇走的方向
        this.direction = this.directionNum.right; //默认让蛇往右走

    };

    //这个方法用来获取蛇头下一个位置对应的元素,要根据元素做不同的事情
    Snake.prototype.getNextPos = function() {
        var nextPos = [
            this.head.x / sw + this.direction.x,
            this.head.y / sh + this.direction.y
        ]

        //forEach代词代表遍历数组

        //下个点是自己,代表撞到了自己,游戏结束
        var selfCollied = false; //是否撞到自己
        this.pos.forEach(function(value) {
            if (value[0] == nextPos[0] && value[1] == nextPos[1]) {
                //如果数组中两个数据都相等,说明下一个点在蛇身体里面能找到自己了
                selfCollied = true;
            }
        });
        if (selfCollied) {
            this.strategies.die.call(this);
            return;
        }

        //下个点是围墙,代表撞到了围墙,游戏结束
        if (nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1) {
            this.strategies.die.call(this);
            return;
        }

        //下个点是食物,吃
        if (food && food.pos[0] == nextPos[0] && food.pos[1] == nextPos[1]) {
            //如果这个条件成立,说明蛇头要走的下一个点是食物

            this.strategies.eat.call(this);
            return;
        }

        //下个点什么都不是,走
        this.strategies.move.call(this); //call作用调用,也可以传参
    };

    //处理碰撞后要做的事
    Snake.prototype.strategies = {
        move: function(format) { //括号内参数用于决定要不要删除最后一个方块(蛇尾),当传来参数就表示要做的事情是吃
            //创建新身体(在旧蛇头的位置)
            var newBody = new Square(this.head.x / sw, this.head.y / sh, 'snakeBody');

            //更新链表关系
            newBody.next = this.head.next;
            newBody.next.last = newBody;
            newBody.last = null;
            this.head.remove(); //把旧蛇头从原来的位置删除
            newBody.create();

            //创建一个新蛇头(蛇头下一个要走到的点nextPos)
            var newHead = new Square(this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y, 'snakeHead');

            //更新链表关系
            newHead.next = newBody;
            newHead.last = null;
            newBody.last = newHead;
            newHead.viewContent.style.transform = 'rotate(' + this.direction.rotate + 'deg)';
            newHead.create();

            //蛇身上的每一个方块的坐标也要更新
            this.pos.splice(0, 0, [this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y])
            this.head = newHead; //还要把this.head的信息更新一下

            if (!format) { //如果format的值为false,表示需要删除(除了吃之外的操作)
                this.tail.remove();
                this.tail = this.tail.last;
                this.pos.pop();
            }

        },
        eat: function() {
            this.strategies.move.call(this, true);
            createFood();
            game.score++;
        },
        die: function() {
            // console.log('die');
            game.over();

        }
    }

    snake = new Snake();

    //创建食物
    function createFood() {
        //食物小方块的随机坐标
        var x = null;
        var y = null;

        var include = true; //循环跳出的条件,true表示随机生成食物的坐标在蛇身上(需要继续循环);false表示食物坐标不在蛇身上(不循环了)
        while (include) {
            x = Math.round(Math.random() * (td - 1));
            y = Math.round(Math.random() * (tr - 1));

            snake.pos.forEach(function(value) {
                if (x != value[0] && y != value[1]) {
                    //这个条件成立说明在随机出来的坐标,在蛇身上并没有找到
                    include = false;
                }
            });
        }

        //生成食物
        food = new Square(x, y, 'food');
        food.pos = [x, y]; //存储一下生成食物的坐标,用于跟蛇头要走的下一个点做对比

        var foodDom = document.querySelector('.food');
        if (foodDom) {
            foodDom.style.left = x * sw + 'px';
            foodDom.style.top = y * sh + 'px';
        } else {
            food.create();
        }
    }


    //创建游戏逻辑
    function Game() {
        this.timer = null;
        this.score = 0;
    }
    Game.prototype.init = function() {
        snake.init();
        createFood();
        document.onkeydown = function(ev) {
            if (ev.which == 37 && snake.direction != snake.directionNum.right) { //用户按下左键时,这条蛇不能是正在往右走
                snake.direction = snake.directionNum.left;
            } else if (ev.which == 38 && snake.direction != snake.directionNum.down) {
                snake.direction = snake.directionNum.up;
            } else if (ev.which == 39 && snake.direction != snake.directionNum.left) {
                snake.direction = snake.directionNum.right;
            } else if (ev.which == 40 && snake.direction != snake.directionNum.up) {
                snake.direction = snake.directionNum.down;
            }
        }

        this.start();
    }
    Game.prototype.start = function() { //开始游戏
        this.timer = setInterval(function() {
            snake.getNextPos();
        }, 200);
    }
    Game.prototype.pause = function() {
        clearInterval(this.timer);
    }
    Game.prototype.over = function() {
        clearInterval(this.timer);
        alert('你的得分为' + this.score);

        //游戏回到最初始的状态
        var snakeWrap = document.getElementById('snakeWrap');
        snakeWrap.innerHTML = '';
        snake = new Snake();
        game = new Game();
        var startBtnWrap = document.querySelector('.startBtn');
        startBtnWrap.style.display = 'block';
    }

    //开启游戏
    game = new Game();
    var startBtn = document.querySelector('.startBtn button');
    startBtn.onclick = function() {
        startBtn.parentNode.style.display = 'none';
        game.init();
    };

    //暂停游戏
    var snakeWrap = document.getElementById('snakeWrap');
    var pauseBtn = document.querySelector('.pauseBtn button');
    snakeWrap.onclick = function() {
        game.pause();
        pauseBtn.parentNode.style.display = 'block';
    };

    pauseBtn.onclick = function() {
        game.start();
        pauseBtn.parentNode.style.display = 'none';
    }
})

案例素材

喜欢就拿去试试吧,不能嫌弃蛇头丑,找不到素材,没得审美的博主自己用PS软件画的蛇头,以后教你如何画简单的图片,这样就再也不担心找不到素材了,敬请期待吧。

游戏效果展示

 动图上传仅限5M以内,咱就不讲究了😥,将就看吧

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HTML+js实现贪吃蛇小游戏(内含完整代码) 的相关文章

  • 步骤一:Jetson Nano安装ROS步骤,及相关错误分析

    安装系统为 xff1a ubantu 18 04 ros melodic 硬件 xff1a jetson nano b01 xff0c 联想拯救者r7000p 内存卡 xff1a SAMSUNG 128G 最后一次更新2022 10 5 亲
  • 步骤三:PX4,Mavros的下载安装及代码测试

    1 安装Mavros sudo apt install ros melodic mavros ros melodic mavros extras 2 安装Mavros相关的 geographiclib dataset 此处已经加了ghpro
  • 步骤五:PIXHAWK遥控器的使用

    采用福斯i6s遥控 1 连接飞控 打开遥控器 xff0c 接收机插上飞控 xff0c 再插上送的短接线 xff0c 进行匹配对码RX 2 遥控器长按两秒锁 xff0c system output mode Output mode按照图片这样
  • 步骤七:激光雷达的驱动安装与建图使用

    大致的步骤可以按照官网来 nbsp Cartographer SLAM for Non GPS Navigation Dev documentation ardupilot org 但是官网的步骤有严重的问题 问题1 报错 libabsl
  • 步骤八:PX4使用cartographer与move_base进行自主建图导航

    首先老样子硬件如下 飞控 HOLYBRO PIXHAWK V4 PX4 机载电脑 jetson nano b01 激光雷达 思岚a2 前提 你已经完成了cartographer建图部分 能够正常输出map话题 前言 由于要参加中国机器人大赛
  • 最详细的流媒体传输协议-rtsp协议详解

    流媒体传输协议 rtsp协议详解 参阅 RTSP协议详解和分析从零开始写一个RTSP服务器 xff08 一 xff09 RTSP协议讲解关于RTSP RTP RTCP协议的深刻初步介绍 rtsp RTSP出现以前 xff0c 最热的大概就是
  • 利用FFmpeg合并音频和视频

    一 FFmpeg 多个音频合并的2种方法 多个mp3文件合并成一个mp3文件 一种方法是连接到一起 ffmpeg64 exe i 34 concat 123 mp3 124 mp3 34 acodec copy output mp3 解释
  • 流媒体服务器之 ZLMediaKit介绍

    流媒体服务器是流媒体应用的核心系统 xff0c 是运营商向用户提供视频服务的关键平台 流媒体服务器的主要功能是对流媒体内容进行采集 缓存 调度和传输播放 流媒体应用系统的主要性能体现都取决于媒体服务器的性能和服务质量 因此 xff0c 流媒
  • WebRTC 教程三:WebRTC特性,调试方法以及相关服务器搭建方法

    WebRTC 教程一 xff1a WebRTC信令 架构和 API 入门 WebRTC 教程二 xff1a WebRTC API 和 Leak 本文是 WebRTC 的第三篇教程 xff0c 主要介绍了 WebRTC 的一些特性 xff0c
  • 能不能在头文件中定义全局变量?

    首先 xff0c 这是一篇科普文 xff0c 所以 比较杂 xff0c 我尽量写清楚一些 1 ANSI C标准是什么 xff1f GNU又是什么 xff1f ld是什么 xff1f ANSI C是C语言的标准规范 xff0c 是国际标准化组
  • FFmpeg转码流程详解

    前言 音视频转码主要指这样的概念 xff1a 容器格式的转换 xff0c 比如MP4转换为MOV 容器中音视频数据编码方式转换 xff0c 比如H264编码转换成MPEG4编码 xff0c MP3换为AAC 音视频码率的转换 xff0c 比
  • FFmpeg 代码实现流媒体推流(RTSP)

    实时录屏并把视频推流到RTSP服务器 xff0c 具体流程是抓取屏幕内容 bitmap xff0c 并把bitmap转化为YUV xff0c 接着把YUV编码成H264 xff0c 再把H264码流推到RTSP服务器 xff1b 把采集到的
  • rtsp协议的理解

    一 rtsp协议概述 RTSP xff08 Real Time Streaming Protocol xff09 实时流传输协议 xff0c 是TCP IP协议体系中的一个应用层协议 该协议定义了一对多的应用程序如何有效地通过IP网络传送多
  • QT 程序打包的方法

    01前言 很多朋友因为要把程序放到不同电脑的环境去测试 xff0c 而又不可能每一台电脑都安装了QT的开发环境 xff0c 于是乎有了将程序打包的想法 这里用来的包的工具是windeployqt xff0c 是QT官方自带的打包软件 xff
  • C++Qt开发——事件处理函数

    事件 event 是由系统或者Qt本身在不同时刻发出的 当用户按下鼠标 敲下键盘 xff0c 或者其它情况时候都会发出一个相应的事件 一些事件在对用户操作做出相应时发出 xff0c 如键盘事件等 xff1b 另外一些则是由系统自动发出 xf
  • C++Qt开发——类图结构

    Qt 类图 系统性地总结一下相关的知识点 xff0c 这里有个网图 xff0c 是Qt的类图 xff0c 看完可以对Qt整体的框架有一个大致的了解 xff0c 具体如下 CSDN QT大纲 xff1a Qt开发必备技术栈学习路线和资料 Qt
  • QT如何实现一个五子棋游戏

    FIR pro QT 43 61 core gui TARGET 61 FIR TEMPLATE 61 app SOURCES 43 61 main cpp widget cpp HEADERS 43 61 widget h wight h
  • Qt5实现UDP通信的示例代码怎么写

    QT5实现UDP通信的示例代码怎么写 xff0c 很多新手对此不是很清楚 xff0c 为了帮助大家解决这个难题 xff0c 下面小编将为大家详细讲解 xff0c 有这方面需求的人可以来学习下 xff0c 希望你能有所收获 前言 该例程经过实
  • OpenCV+Qt实现图像处理操作工具

    一 目标 Qt界面实现 雪花屏 高斯模糊 中值滤波 毛玻璃 灰度化 XY方向模糊 双边模糊 腐蚀 图像处理操作 要求左边原图 xff0c 右边效果图 结果展示如下 xff1a 图像处理实现有点多 xff0c 就不一个一个地展示了 xff0c
  • 链表的建立、赋值、输出、查找、增、删

    include lt stdio h gt include lt string h gt include lt math h gt include lt stdlib h gt typedef struct node 定义结构体 int n

随机推荐

  • 蓝桥杯-串口

    本文通过电脑串口发送文本模式和HEX模式进行介绍串口的简单使用 xff01 注意事项 xff1a 1 本节通过定时器2的串口1 进行串口控制 2 串口如果开启了 编程完成后自动打开串口会导致第一次发送无法看到 xff08 HEX模式 xff
  • GSV2008

    GSV2008 是HDMI2 0 四进二出矩阵 xff0c 自持HDCP2 2 xff0c 支持DOWN SCALER 四个HDMI输入 xff0c 2个HDMI输出 xff0c 自动EQ 应用 xff1a 1 xff0c 功放 ARC C
  • 漏洞挖掘-从任意文件读取漏洞到获取账户利用

    开篇 大家好 xff0c 我是承影战队的v1ct0ry xff0c 这次我为大家分享一次比较有趣的漏洞挖掘经历 这次挖掘过程是以灰盒挖掘为主要思想进行展开 xff0c 不熟悉的读者可以阅读上篇文章熟悉一下 一 任意文件读取 开局我们通过扫描
  • curl命令行工具

    转载 curl 命令行工具的使用及命令参数说明 curl的使用 1 1 URL访问 1 2 表单提交 1 3 其它HTTP请求方法 1 4 文件上传 1 5 HTTPS支持 1 6 添加请求头 1 7 Cookie支持curl语法及选项cu
  • Ubuntu20.4安装ROS系统教程(自用)

    1 Ubuntu各个版本系统对应的ROS版本 1 2Ubuntu16 04与ROS kinetic的安装 1 2 1Ubuntu16 04配置 1 2 2安装ROS kinetic版 1 3Ubuntu18 04和ROS melodic的安
  • UART 空闲中断+DMA接收流程

    在项目中利用UART空闲中断接收外部信号 xff0c 利用DMA接收 xff0c 实现外部到内存的传输 通过分析其它文章的代码 xff0c 大概如下 xff1a span class token comment 配置 DMA Stream
  • 5分钟带你从数据类型了解Java相比C/C++有什么优势

    数据类型是一门语言的血肉 xff0c 通过这5分钟的浏览 xff0c 只学过C C 43 43 的小伙伴会初步了解Java的一些特性 xff0c 学过一点Java的朋友在读完这篇文章后也一定会对Java的语法规范有更深刻的了解 Java数据
  • 备赛电赛学习硬件篇(一):电机部分

    目录 一 电机选型 二 电机的正反转 xff0c 刹车 一 电机选型 1 电机类型 无刷电机较贵 xff0c 但是静音且损耗小 xff0c 由于霍尔元件的特殊性 xff08 不带霍尔需要转速高的时候才可以利用反电动势准确确定转子的位置 xf
  • 【总线】一文看懂RS232和RS485通信总线

    目录 RS232概述 RS232特性 RS485 概述 RS485 特性 RS232 和 RS485 的区别 区别总结 RS232概述 RS 232接口符合电子工业联盟 xff08 EIA xff09 建立的串行数据通信接口标准 原始编号是
  • 【C++学习笔记】vector构造函数

    文章目录 1 vector构造函数说明 xff1a 2 实战 xff1a 2 1 vector构造函数代码示例2 2 输出 3 参考资料 1 vector构造函数说明 xff1a span class token keyword templ
  • 请求报文/相应报文

    一 请求报文分为4个部分 请求行 请求头 请求空行 请求体 1 1 请求行 主要是3个部分 GET 请求方式 1 2 请求地址 所带的参数 demo demo php userName 61 E6 9D 8E E5 9B 9B amp us
  • python+requests——高级用法——auth认证

  • C语言char指针的使用

    在c语言中 xff0c char指针不仅能指向char变量 xff0c 还能指向常量字符串 xff0c 同时也能指向一个char数组的 想要访问单个字符 xff0c 就要通过 来进行解引用 xff0c 若是要访问整个数组或字符串的话 xff
  • HTTP协议的请求格式解析

    HTTP协议是一个使用较多的应用层协议 xff0c 它是一个请求 响应式的一个协议 xff0c 就是我客户端给你发一个请求 xff0c 你客户端需要返回给我一样响应 首先我们来看一下HTTP协议的请求格式 HTTP请求格式 xff1a HT
  • 运行Gazebo+moveit+Rviz,报错,提示无控制器

    在rviz里规划成功后 xff0c 执行显示failed rviz里能规划 xff0c 但是Gazebo里动不了 moveit报错如下 xff1a WARN 1679466487 132361192 26 763000000 Waiting
  • 基于UDP协议搭建的简单客户端与服务器(UDP协议)

    UDP协议 UDP协议的介绍1 UDP的缺点 基于UDP实现的回显服务器基于UDP实现的客户端 UDP协议的介绍 UDP协议特点 xff1a 1 无连接 2 面向数据报 3 不可靠传输 4 全双工 16位源端口号 目的端口号 xff1a 表
  • C++之AStar寻路算法

    仅以记录 有一种算法 名为AStar 它的作用是求图中两点之间的最短路径 沉迷 该算法的我 自己编写了一个版本 注释虽少 但求传神 代码虽 恶心 但求理解 include lt iostream gt include lt vector g
  • 使用livox_viewer2对激光雷达livox_mid360进行调试

    准备 系统 windows10 硬件 xff1a livox mid360 软件 xff1a livox viewer2 测试 连接号激光雷达设备 xff0c 电脑ip相关设置和livox avia一样 livox系列激光雷达ip设置都是一
  • 听说你还不会制作“GIF动图”,手把手包教会,这不就来了吗

    近期 xff0c 看了好多写的博客 xff0c xff08 不管是前端HTML的还是后端Java的 xff0c 前端制作的3D部分的效果图需要展示动图 xff09 发现有点还存在想使用动图 xff0c 但是不会制作 xff0c 又或者是制作
  • HTML+js实现贪吃蛇小游戏(内含完整代码)

    案例分析 看图拆解游戏 首先我们根据图片上的内容把这个游戏拆解成几个部分去单独看 xff1a 最外面的大盒子包裹着内容加边框限制蛇的活动范围 xff0c 整个范围可以看成由许多小方格排列构成的 xff0c 例如这样子的 xff1a xff1