首页 > 其他分享 >九、贪吃蛇之蛇身控制

九、贪吃蛇之蛇身控制

时间:2024-05-08 10:13:29浏览次数:15  
标签:控制 begin cube end pos 贪吃蛇 exist && 之蛇身

九、贪吃蛇之蛇身控制

1. 目标

(1) 游戏难度决定蛇身移动的速度;

(2) 蛇身增长;

(3) 蛇身移动。

 

2. 蛇身速度控制

用计数器来控制蛇身移动的时间间隔,间隔短,移动快,游戏难度就越难。在游戏难度选择界面,用SW[2:0]选择难度。

//蛇身移动速度

else 

begin

    clk_cnt <= clk_cnt + 1;

    if(clk_cnt == speed)

    begin  

        clk_cnt <= 0;

 

 

 

 

 

速度分3档,0.5s、0.25s、0.125s蛇身移动一次。

always @(posedge clk or negedge rst_n) begin

    if(!rst_n) begin

        speed <= 24'd12500000;

        direct_r <= RIGHT;

    end

    else begin

        direct_r <= direct_next;

        case (sw[2:0])  //根据难度设置相应的速度

            3'b001:speed <= 24'd12500000;   //0.5s

            3'b010:speed <= 24'd6250000;    //0.25s

            3'b100:speed <= 24'd3125000;    //0.125s

            default:speed <= 24'd12500000;

        endcase    

    end

end 

 

3. 蛇身增长

cube_x,cube_y表示蛇身各节的坐标。第1节代表蛇头。

 

 

 

获取蛇头坐标:

assign head_x = cube_x[0];

assign head_y = cube_y[0];

 

 

蛇和食物初始位置:

always @(posedge clk or negedge rst_n) begin

    if(!rst_n) begin

        clk_cnt <= 0;

 

        cube_x[0] <= 10;    //初始化蛇身有3节,这是第1节

        cube_y[0] <= 5;

        cube_x[1] <= 9;    //初始化蛇身有3节,这是第2节

        cube_y[1] <= 5;

        cube_x[2] <= 8;    //初始化蛇身有3节,这是第3节

        cube_y[2] <= 5;

        cube_x[3] <= 0;    

        cube_y[3] <= 0;

 

always @(posedge clk or negedge rst_n) begin

    if(!rst_n) begin

        clk_cnt <= 0;

        apple_x <= 24;

        apple_y <= 10;

        add_cube <= 0;

 

当蛇头和食物的坐标相同时,代表吃了一个食物,蛇身要增长,add_cube为1.每吃下一个食物,蛇身加1,相应的is_exist位置变为1,is_exist有16位,即蛇身最长为16格,is_exist

为1,那一格显示,反之,则不显示。

 

 

 

每次add_cube为1时,表示蛇身长度的信号cube_num加1.is_exist[cube_num] = 1表示让第cube_num位显示出来。

always @(posedge clk or negedge rst_n) begin

    if(!rst_n) begin

        is_exist <= 16'd7;

        cube_num <= 3;  //蛇身初始长度为3,is_exist = 0000_0000_0000_0111表示前3位出现

        addcube_state <= 0;

    end

    else if(game_status == RESTART) begin

          is_exist <= 16'd7;

        cube_num <= 3;  

        addcube_state <= 0;

    end

    else begin

        case(addcube_state) //判断蛇头是否与食物坐标重合

            0:begin

                if(add_cube) begin

                    cube_num <= cube_num + 1;

                    is_exist[cube_num] <= 1;

                    addcube_state <= 1; //吃下食物信号

                end

            end

            1:begin

                if(!add_cube)

                    addcube_state <= 0;

            end

        endcase

    end

end

 

4. 蛇撞墙或撞自身

(1) 撞墙

当蛇头坐标跟墙的坐标重合,代表撞墙:

//撞墙

if((direct_r == UP && cube_y[0] == 1) ||

   (direct_r == DOWN && cube_y[0] == 28) ||

   (direct_r == RIGHT && cube_x[0] == 38) ||  

   (direct_r == LEFT && cube_x[0] == 1))

   hit_wall <= 1;

   

 

(2) 撞自身

当蛇头坐标跟身体某一节的坐标重合,代表撞到自身:

//撞自身

else if((cube_x[0] == cube_x[1] && cube_y[0] == cube_y[1] && is_exist[1] == 1) || //比较第1节

        (cube_x[0] == cube_x[2] && cube_y[0] == cube_y[2] && is_exist[2] == 1) || //比较第2节

        (cube_x[0] == cube_x[3] && cube_y[0] == cube_y[3] && is_exist[3] == 1) || //比较第3节

        (cube_x[0] == cube_x[4] && cube_y[0] == cube_y[4] && is_exist[4] == 1) || //比较第4节

        (cube_x[0] == cube_x[5] && cube_y[0] == cube_y[5] && is_exist[5] == 1) || //比较第5节

        (cube_x[0] == cube_x[6] && cube_y[0] == cube_y[6] && is_exist[6] == 1) || //比较第6节

        (cube_x[0] == cube_x[7] && cube_y[0] == cube_y[7] && is_exist[7] == 1) || //比较第7节

        (cube_x[0] == cube_x[8] && cube_y[0] == cube_y[8] && is_exist[8] == 1) || //比较第8节

        (cube_x[0] == cube_x[9] && cube_y[0] == cube_y[9] && is_exist[9] == 1) || //比较第9节

        (cube_x[0] == cube_x[10] && cube_y[0] == cube_y[10] && is_exist[10] == 1) || //比较第10节

        (cube_x[0] == cube_x[11] && cube_y[0] == cube_y[11] && is_exist[11] == 1) || //比较第11节

        (cube_x[0] == cube_x[12] && cube_y[0] == cube_y[12] && is_exist[12] == 1) || //比较第12节

        (cube_x[0] == cube_x[13] && cube_y[0] == cube_y[13] && is_exist[13] == 1) || //比较第13节

        (cube_x[0] == cube_x[14] && cube_y[0] == cube_y[14] && is_exist[14] == 1) || //比较第14节

        (cube_x[0] == cube_x[15] && cube_y[0] == cube_y[15] && is_exist[15] == 1) || //比较第15节

        )

 

5. 蛇身的移动路径

蛇头移动有三种情况:撞墙、撞自身、移动到下一个位置。蛇身每一节把坐标传递给下一节。

 

 

//蛇身移动,前位坐标传给后位

else begin

    cube_x[1] <= cube_x[0];

    cube_y[1] <= cube_y[0];

 

    cube_x[2] <= cube_x[1];

    cube_y[2] <= cube_y[1];

 

    cube_x[3] <= cube_x[2];

    cube_y[3] <= cube_y[2];

 

    cube_x[4] <= cube_x[3];

    cube_y[4] <= cube_y[3];

 

    cube_x[5] <= cube_x[4];

    cube_y[5] <= cube_y[4];

 

    cube_x[6] <= cube_x[5];

    cube_y[6] <= cube_y[5];

 

    cube_x[7] <= cube_x[6];

    cube_y[7] <= cube_y[6];

 

    cube_x[8] <= cube_x[7];

    cube_y[8] <= cube_y[7];

 

    cube_x[9] <= cube_x[8];

    cube_y[9] <= cube_y[8];

 

    cube_x[10] <= cube_x[9];

    cube_y[10] <= cube_y[9];

 

    cube_x[11] <= cube_x[10];

    cube_y[11] <= cube_y[10];

 

    cube_x[12] <= cube_x[11];

    cube_y[12] <= cube_y[11];

 

    cube_x[13] <= cube_x[12];

    cube_y[13] <= cube_y[12];

 

    cube_x[14] <= cube_x[13];

    cube_y[14] <= cube_y[13];

 

    cube_x[15] <= cube_x[14];

    cube_y[15] <= cube_y[14];

 

6. 蛇头方向控制

蛇头方向通过四个按键KEY[3:0]控制,用状态机实现,参考(八、状态机设计)。

 

7. 蛇色块显示

当坐标pos_x[9:4],pos_y[9:4]与蛇的坐标吻合时,显示蛇身。墙壁的显示也是这样。

//显示墙和蛇身

always @(pos_x or pos_y) begin

    if(pos_x >=0 && pos_x <640 && pos_y >= 0

       && pos_y < 480) begin

        if(pos_x[9:4] == 0 || pos_y[9:4] == 0

        || pos_x[9:4] == 39 || pos_y == 29)

            snake_show = WALL; //显示墙

        else if(pos_x[9:4] == cube_x[0] && 

                pos_y[9:4] == cube_y[0] &&

                is_exist[0] == 1)

                    snake_show = (snake_display == 1)?

                                 HEAD : NONE; //蛇头

        else if

        ((pos_x[9:4] = cube_x[1] && pos_y[9:4] == cube_y[1] && 

        is_exist[1] == 1) ||

        (pos_x[9:4] = cube_x[2] && pos_y[9:4] == cube_y[2] && 

        is_exist[2] == 1) ||

        (pos_x[9:4] = cube_x[3] && pos_y[9:4] == cube_y[3] && 

        is_exist[3] == 1) ||

        (pos_x[9:4] = cube_x[4] && pos_y[9:4] == cube_y[4] && 

        is_exist[4] == 1) ||

        (pos_x[9:4] = cube_x[5] && pos_y[9:4] == cube_y[5] && 

        is_exist[5] == 1) ||

        (pos_x[9:4] = cube_x[6] && pos_y[9:4] == cube_y[6] && 

        is_exist[6] == 1) ||

        (pos_x[9:4] = cube_x[1] && pos_y[9:4] == cube_y[1] && 

        is_exist[1] == 1) ||

        (pos_x[9:4] = cube_x[2] && pos_y[9:4] == cube_y[2] && 

        is_exist[2] == 1) ||

        (pos_x[9:4] = cube_x[3] && pos_y[9:4] == cube_y[3] && 

        is_exist[3] == 1) ||

        (pos_x[9:4] = cube_x[4] && pos_y[9:4] == cube_y[4] && 

        is_exist[4] == 1) ||

        (pos_x[9:4] = cube_x[5] && pos_y[9:4] == cube_y[5] && 

        is_exist[5] == 1) ||

        (pos_x[9:4] = cube_x[6] && pos_y[9:4] == cube_y[6] && 

        is_exist[6] == 1) ||

        (pos_x[9:4] = cube_x[7] && pos_y[9:4] == cube_y[7] && 

        is_exist[7] == 1) ||

        (pos_x[9:4] = cube_x[8] && pos_y[9:4] == cube_y[8] && 

        is_exist[8] == 1) ||

        (pos_x[9:4] = cube_x[9] && pos_y[9:4] == cube_y[9] && 

        is_exist[9] == 1) ||

        (pos_x[9:4] = cube_x[10] && pos_y[9:4] == cube_y[10] && 

        is_exist[10] == 1) ||

        (pos_x[9:4] = cube_x[11] && pos_y[9:4] == cube_y[11] && 

        is_exist[11] == 1) ||

        (pos_x[9:4] = cube_x[12] && pos_y[9:4] == cube_y[12] && 

        is_exist[12] == 1) ||

        (pos_x[9:4] = cube_x[13] && pos_y[9:4] == cube_y[13] && 

        is_exist[13] == 1) ||

        (pos_x[9:4] = cube_x[14] && pos_y[9:4] == cube_y[14] && 

        is_exist[14] == 1) ||

        (pos_x[9:4] = cube_x[15] && pos_y[9:4] == cube_y[15] && 

        is_exist[15] == 1))

        snake_show = (snake_display == 1) ? BODY : NONE; //身体

        else

        snake_show = NONE;

       end

       

 

为了便于分辨蛇身的每节,把每节第一列前三个像素显示黑色。

//给蛇身每节第一列前三个像素显示黑色,便于分辨

else if (game_status == PLAY | game_status == START) begin

    cnt <= 0;

    if(pos_x[9:4] == apple_x && pos_y[9:4] == apple_y) begin

        vga_rgb = PINK;

    end

    else if(snake_show == NONE) begin

        vga_rgb = BLACK;

    end

    else if(snake_show == WALL) begin

        vga_rgb = RED;

    end

    else if(snake_show == HEAD | snake_show == BODY) begin

        case({pos_x[3:0],pos_y[3:0]})

            8'b00000000:vga_rgb = BLACK;

            8'b00000001:vga_rgb = BLACK;

            8'b00000010:vga_rgb = BLACK;

            default:vga_rgb = (snake_show == HEAD) ? GREEN : BLUE;

        endcase

    end

    else begin

        vga_rgb = BLACK;

    end

end

 

 

参考文献:

https://mp.weixin.qq.com/s/4qgOI4xP1nzufEQLQpFUHA

 

标签:控制,begin,cube,end,pos,贪吃蛇,exist,&&,之蛇身
From: https://www.cnblogs.com/halflife/p/18179049

相关文章

  • PID 控制详解
    阶跃响应阶跃响应是指将一个阶跃输入(stepfunction)加到系统上时,系统的输出。稳态误差是指系统的响应进入稳态后﹐系统的期望输出与实际输出之差。控制系统的性能可以用稳、准、快三个字来描述。稳是指系统的稳定性(stability),一个系统要能正常工作,首先必须是稳定的,从阶跃响应上看......
  • JavaScript 流程控制语句详解:if语句、switch语句、while循环、for循环等
    JavaScript,作为一种广泛使用的编程语言,它的流程控制语句是构建逻辑和实现功能的基础。流程控制语句包括条件语句、循环语句和转向语句,它们是编程中不可或缺的部分。接下来,我们将一一解析这些语句,带你走进JavaScript的世界。一、什么是流程控制语句流程控制语句是用来控制程序中......
  • 《安富莱嵌入式周报》第336期:开源计算器,交流欧姆表,高性能开源BLDC控制器,Matlab2024a,操
    周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 本周更新一期视频教程:BSP视频教程第30期:UDSISO14229统一诊断服务CAN总线专题,常用诊断执行流程精讲,干货分享,图文并茂https://www.armbbs.cn/forum.php?mod=viewthread&tid=12......
  • Idea怎么使用鼠标控制字体大小?
    IDEA中设置滚轮改变字体大小方法一打开IDEA设置,Windows下的快捷键是Ctrl+Alt+S。在设置窗口中,选择“Editor”选项卡。在“Editor”选项卡下,选择“General”子选项卡。在“General”子选项卡下,找到“Mouse”部分。在“Mouse”部分下,找到“Changefontsize(Zoom)withCtrl......
  • 功能全面的外发文件控制方案,拿走不谢!
    在日常办公中,很多企业往往只采取各种措施来确保存储数据的安全,却忽略了文件外发的安全。因此企业由于自身的安全防护机制不严谨,引发的数据安全事件频发,经常导致严重的经济损失。使用较多的外发方式有邮件、IM通讯工具、网盘、U盘硬件介质等,在外发文件控制上,存在一定问题:  1.......
  • 漂亮的.NET控制台应用程序类库--Spectre.Console
    思维导航前言项目特性项目源代码新建控制台应用安装项目的NuGet包控制台文字输出table表格输出条形图日历布局规则水平线项目源码地址优秀项目和框架精选DotNetGuide技术社区交流群前言做过.NET控制台应用程序的同学应该都知道原生的.NET控制台应用程序输出......
  • 07. C语言程序执行流程控制
    【有条件执行语句】ifesle语句ifelse语句根据一个条件确定是否执行一段代码,执行条件是一个布尔值,布尔值为true则执行,为false则不执行,同时可以设置不符合条件时执行的语句。if(执行条件){  符合条件时执行的代码;}else{  不符合条件时执行的代码;}使用事项:1......
  • SSH远程访问及控制
    SSH远程访问及控制目录SSH远程访问及控制一、SSH远程管理1、SSH的概述2、SSH的原理二、配置OpenSSH1服务器1、sshd_config配置文件的常用选项设置2、实例操作2.1改端口号2.2禁止root用户登录2.2.3服务端2.2.4客户端2.3白名单和黑名单2.3.1白名单2.3.1.1服务器2.3.1.2客户端2.......
  • 使用 SSH 转义代码来控制连接
    OpenSSH最常被忽视的一个非常有用的功能是能够从连接内部控制会话的某些方面。通过使用SSH转义代码,我们能够在会话内部与本地SSH软件进行交互。强制从客户端断开连接(如何退出卡住或冻结的会话)这些命令可以在SSH会话中以~控制字符开头执行。只有在换行后第一次键入时才......
  • arduino uno+LCD12864(ST7735S)+蓝牙模块实现贪吃蛇
    1.前言:1.1本实验实现的贪吃蛇能穿越边界,结束游戏的唯一条件是贪吃蛇到达指定长度1.2本实验所用LCD可能不是LCD12864,LCD12864所用库为u8glib,笔者在词库中并没有找到型号为ST77355的初始化函数,而是在ucglib中找到,其方法为Ucglib_ST7735_18x128x160_SWSPIucg(/*sclk=*/13,/*data......