SpringBoot项目(三)--- 创建菜单和游戏界面

1.创建蛇

先写Cell.js,用来表示蛇的每一格。

export class Cell {
    constructor(r,c) {
        this.r = r;
        this.c = c;

        //圆心的坐标 canvas的坐标和常规的不一样
        this.x = this.c + 0.5;
        this.y = this.r + 0.5;
    }
}

Snake.js的信息,render函数渲染出蛇的每一个格子

import { AcGameObject } from "./AcGameObject";
import { Cell } from "./Cell";

export class Snake extends AcGameObject {
    constructor(info,GameMap) {  //传递蛇的信息和地图信息
        super();

        this.id = info.id;
        this.color = info.color;
        this.gamemap = GameMap;

        this.cells = [new Cell(info.r,info.c)]; //存放蛇的身体  cell[0]存放蛇头
    }

    start() {

    }

    update() {
        this.render();
    }

    render() {
        const L = this.gamemap.L;
        const ctx = this.gamemap.ctx;

        //画蛇的每一个格子  即画圆
        ctx.fillStyle = this.color;
        for(const cell of this.cells) {
            //画圆
            ctx.beginPath();
            ctx.arc(cell.x * L,cell.y * L,L / 2,0,Math.PI * 2);
            ctx.fill();
        }
    }
}

蛇如何去动?

创建一个新头往前面移动,尾巴向前移动,其余的点都不动。

接受键盘的操作?

先让canvs聚焦,加上tabindex属性

<template>
    <div  ref="parent" class="gamemap">
        <canvas ref="canvas" tabindex="0"></canvas>
    </div>
</template>
    add_listening_events() {
        this.ctx.canvas.focus();

        const [snake0,snake1] = this.snakes;
        this.ctx.canvas.addEventListener("keydown",e => {
            if(e.key === 'w') snake0.set_direction(0);
            else if(e.key === 'd') snake0.set_direction(1);
            else if(e.key === 's') snake0.set_direction(2);
            else if(e.key === 'a') snake0.set_direction(3);
            else if(e.key === 'ArrowUp') snake1.set_direction(0);
            else if(e.key === 'ArrowRight') snake1.set_direction(1);
            else if(e.key === 'ArrowDown') snake1.set_direction(2);
            else if(e.key === 'ArrowLeft') snake1.set_direction(3);
        });
    }

    start() {
        for(let i = 0;i < 1000;i ++) {
            if(this.create_walls())
                break;
        } 
        this.add_listening_events();
    }

蛇边长的规则:前十步每一步蛇都变长,后面每三步蛇变长一格。

check_tail_increasing() {
        if(this.step <= 10) return true;
        if(this.step % 3 === 1) return true;
        return false;
    }
    next_step() {  //将蛇的状态改为走下一步
        const d = this.direction;
        this.next_cell = new Cell(this.cells[0].r + this.dr[d],this.cells[0].c + this.dc[d]);
        this.direction = -1;  //清空操作
        this.status = "move";  //可以移动了

        this.step ++;

        const k = this.cells.length;
        for(let i = k;i > 0;i --) {    //除了头节点的其余所有点都往后移动,并复制一份头节点
            this.cells[i] = JSON.parse(JSON.stringify(this.cells[i - 1]));
        }
    }

    update_move() {  //蛇的移动
        const dx = this.next_cell.x - this.cells[0].x;
        const dy = this.next_cell.y - this.cells[0].y;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if(distance < this.eps) {  //移动到目标值了
            this.cells[0] = this.next_cell;
            this.next_cell = null;
            this.status = "idle";   //走完了 停止

            if(!this.check_tail_increasing()) {
                this.cells.pop();
            }
        } else {
            const move_distance = this.speed * this.timedelta / 1000;
            this.cells[0].x += move_distance * dx / distance;
            this.cells[0].y += move_distance * dy / distance;

            if(!this.check_tail_increasing()) { //蛇尾不增加长度,就让倒数第一个点移动到倒数第二个点上去。蛇尾长度增加的话,蛇尾就不动
                const k = this.cells.length;
                const tail = this.cells[k - 1],tail_target = this.cells[k - 2];
                const tail_dx = tail_target.x - tail.x;
                const tail_dy = tail_target.y - tail.y;

                tail.x += move_distance * tail_dx / distance;
                tail.y += move_distance * tail_dy / distance;
            }
        }
    }

    update() {
        if(this.status === 'move') {
            this.update_move();
        }

        this.render();
    }

优化蛇的形状

    render() {
        const L = this.gamemap.L;
        const ctx = this.gamemap.ctx;

        //画蛇的每一个格子  即画圆
        ctx.fillStyle = this.color;
        for(const cell of this.cells) {
            //画圆
            ctx.beginPath();
            ctx.arc(cell.x * L,cell.y * L,L / 2 * 0.8,0,Math.PI * 2);
            ctx.fill();
        }

        for(let i = 1;i < this.cells.length;i ++) {
            const a = this.cells[i - 1],b = this.cells[i];
            
            if(Math.abs(a.x - b.x) < this.eps && Math.abs(a.y - b.y) < this.eps) 
                continue;
            else if(Math.abs(a.x - b.x) < this.eps) {  //竖方向
                ctx.fillRect((a.x - 0.5 + 0.1) * L , Math.min(a.y,b.y) * L , L * 0.8 , Math.abs(a.y - b.y) * L);
            } else {  //横方向
                ctx.fillRect(Math.min(a.x,b.x) * L , (a.y - 0.5 + 0.1) * L , Math.abs(a.x - b.x) * L , L * 0.8);
            }
        }
    }

2.蛇碰撞的检测

就是检测下一个格子是否合法?

墙的检测:

    check_vaild(cell)  {  //检测下一步是否合法
        for(const wall of this.walls) {  //撞墙与否
            if(cell.r === wall.r && cell.c === wall.c) 
                return false;  
        }

        //是否撞到蛇的身体
        for(const snake of this.snakes) {
            let k = snake.cells.length;  //蛇的长度
            if(!snake.check_tail_increasing()) {  //蛇的长度不再增加,蛇尾移动,蛇尾不要在判断
                k --;
            }

            for(let i = 0;i < k;i ++) {
                if(cell.r === snake.cells[i].r && cell.c === snake.cells[i].c)
                    return false;
            }
        }

        return true;
    }

3.画眼睛

ctx.fillStyle = "black";
        for(let i = 0;i < 2;i ++) {
            const eye_x = (this.cells[0].x + this.eye_dx[this.eye_direction][i] * 0.15) * L;
            const eye_y = (this.cells[0].y + this.eye_dy[this.eye_direction][i] * 0.15) * L;

            ctx.beginPath();
            ctx.arc(eye_x,eye_y,L * 0.05,0,Math.PI * 2);
            ctx.fill();
        }

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【资源说明】 1、基于SpringBoot+Nuxt的服务端渲染博客系统源码+数据库+项目说明.zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 4、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于SpringBoot+Nuxt的服务端渲染博客系统源码+数据库+项目说明.zip ### 简介 基于 SpringBoot 和 Nuxt 的前后端分离博客 ### SQL文件 blog.sql 初始账号密码:Linter ### Nginx配置 ``` location / { proxy_pass http://127.0.0.1:3000; } location ~ .*\.(gif|jpg|jpeg|png)$ { proxy_pass http://127.0.0.1:3000; } location ~ .*\.(js|css|woff|ttf|ico)?$ { proxy_pass http://127.0.0.1:3000; } ``` ### 截图 #### 首页 ![首页](screenshot/blog-index.png) #### 登录 ![登录](screenshot/blog-login.png) #### 分类 ![分类](screenshot/blog-catalog.png) #### 文章 ![文章](screenshot/blog-article.png) #### 评论 ![评论](screenshot/blog-comment-new.png) #### 搜索 ![搜索](screenshot/blog-search.png) #### 后台首页 ![后台首页](screenshot/blog-admin-index.png) #### 发布文章 ![发布文章](screenshot/blog-article-new.png) #### 文章管理 ![文章管理](screenshot/blog-article-list.png) #### 新增分类 ![新增分类](screenshot/blog-category-new.png) #### 编辑分类 ![编辑分类](screenshot/blog-category-edit.png) #### 分类管理 ![分类管理](screenshot/blog-category-list.png) #### 评论管理 ![评论管理](screenshot/blog-comment-list.png) #### 新增用户 ![新增用户](screenshot/blog-user-new.png) #### 用户管理 ![用户管理](screenshot/blog-user-list.png)
适用人群所有的IT从业者,尤其适合快速掌握新技术,快速增长工作经验人群,对教育公平,教育公益,教育爱心公益人士课程概述课程概述该互联网实战项目是基于腾讯开源Tdesign产品框架,前后端分离,开发项目实战,SpringBoot+SpringSecurity+Mybatisplus+MySQL+Knife4j中后台项目产品实战,包括图形展示、权限管理、用户管理等功能。【后端】Spring Boot2 框架 开发的一站式解决方案Spring Security5 认证和授权框架MyBatisPlus3.3.1 基于 MyBatis 框架的快速研发框架MyBatisCode工具生成 MyBatis 相关代码Jackson提供了处理 JSON 数据的工具Lombok简化对象封装工具 Druid   数据库连接池 【前端技术】Vue       互联网最火的前端框架Vue Router路由框架Vuex全局状态管理框架Axios前端 HTTP 框架TDesign 前端模板TDesign 是腾讯各业务团队在服务业务过程中沉淀的一套企业级设计体系。TDesign 提供了开箱即用的 UI 组件库、设计指南 和相关 设计资产,以优雅高效的方式将设计和研发从重复劳动中解放出来,同时方便大家在 TDesign 的基础上扩展,更好的的贴近业务需求。在腾讯内部以开源协同的方式,共建一个完善、易用的设计体系和组件库产品。【开发工具】IntelliJ IDEA开发 IDESQLyog数据库连接客户端PostmanHTTP 请求工具【开发环境】工具版本JDK1.8MySQL5.7 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值