创建菜单与游戏页面

bootstrap地址

Bootstrap v5 中文文档 · Bootstrap 是全球最受欢迎的 HTML、CSS 和 JS 前端工具库。 | Bootstrap 中文网 (bootcss.com)

 创建菜单与游戏页面_第1张图片

创建导航栏组件

web--src--components--NavBar.vue









App.vue






创建各页面组件

创建菜单与游戏页面_第2张图片






















 router---组件

import { createRouter, createWebHistory } from 'vue-router'
import NotFound from "../views/error/NotFound"
import PkIndexView from "../views/pk/PkIndexView"
import RanklistIndexView from "../views/ranklist/RanklistIndexView"
import RecordIndexView from "../views/record/RecordIndexView"
import UserBotIndexView from "../views/user/bot/UserBotIndexView"
const routes = [
  {
    path: "/pk/",
    name: "pk_index",
    component: PkIndexView
  },
  {
    path: "/error/",
    name: "404",
    component: NotFound
  },
  {
    path: "/record/",
    name: "record_index",
    component: RecordIndexView
  },
  {
    path: "/ranklist/",
    name: "ranklist_index",
    component: RanklistIndexView
  },
  {
    path: "/user/bot/",
    name: "user_bot_index",
    component: UserBotIndexView
  },
  // 重定向到404
  {
    path: "/:catchAll(.*)",
    redirect: "/error/"
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

 白板--组件

各页面白板构成一个组件components->ContentField.vue





 游戏对象类

scrips---->ACGameObject.js

const AC_GAME_OBJECTS = []; //存储所有运动对象
export class AcGameObject {
    constructor() {
        AC_GAME_OBJECTS.push(this);
        // 走的距离=速度*时间间隔
        //当前帧执行的时刻距离上一帧执行时刻的间隔,浏览器每一帧时间间隔可能有误差不一样因此需要记录
        this.timedelta = 0;
        // 是否执行过start函数
        this.has_called_start = false;
    }
    start() {    //创建时,只执行一次

    }
    update() {  // 除了第一帧外每一帧执行一次

    }
    // 删除之前用到的回调函数
    on_destroyed() {

    }
    destroyed() {
        this.on_destroyed();
        for (let i in AC_GAME_OBJECTS) {
            const obj = AC_GAME_OBJECTS[i];
            if (obj == this) {
                AC_GAME_OBJECTS.splice(i);      //从数组删除
                break;
            }
        }
    }
}
let last_timestamp; //上一次执行的时刻
// requestAnimationFrame(函数) 函数在浏览器下一次渲染之前执行一遍
// 迭代执行step
// in是下标  of是值
const step = timestamp => {             // 每次调用会传入当前时刻
    for (let obj of AC_GAME_OBJECTS) {
        // 如果没执行start()
        if (!obj.has_called_start) {
            obj.has_called_start = true;
            obj.start();
        } else {
            obj.timedelta = obj.timestamp - last_timestamp;
            obj.update();
        }
    }
    last_timestamp = timestamp;
    // 下一帧执行step
    requestAnimationFrame(step)
}
requestAnimationFrame(step)

 地图

创建菜单与游戏页面_第3张图片

动起来:60帧/s

地图对象类


// export  import {}     export default import 

// 游戏地图的对象
import { AcGameObject } from "./AcGameObject";
import { Wall } from "./Wall";
export class GameMap extends AcGameObject {
    // 构造函数的两个参数,  画布,画布的父元素用于动态修改画布的长宽
    constructor(ctx, parent) {  // ctx表示画布,parent表示画布的父元素
        // 先执行AcGameObject的构造函数
        super();
        this.ctx = ctx;
        this.parent = parent;
        this.L = 0;  // 一个单位的绝对长度
        this.rows = 13;  // 地图的行数
        this.cols = 13;  // 地图的列数

        this.inner_walls_count = 6;
        this.wall = [];
    }
    check_connectivity(sx, sy, tx, ty, g) {
        if (sx == tx && sy == ty) return true;
        g[sx][sy] = true;
        let dx = [-1, 0, 1, 0], dy = [0, 1, 0, -1];
        for (let i = 0; i < 4; i++) {
            let x = sx + dx[i], y = sy + dy[i];
            // 没有撞墙,可以走到终点
            if (!g[x][y] && this.check_connectivity(x, y, tx, ty, g)) {
                return true;
            }
        }
        return false;
    }
    create_walls() {
        //new Wall(0, 0, this);

        // 墙true,无墙false
        const g = [];
        for (let r = 0; r < this.cols; r++) {
            g[r] = [];
            for (let c = 0; c < this.cols; c++) {
                g[r][c] = false;
            }
        }
        // 四周加上墙
        for (let r = 0; r < this.rows; r++) {
            g[r][0] = g[r][this.cols - 1] = true;
        }
        for (let c = 0; c < this.cols; c++) {
            g[0][c] = g[this.rows - 1][c] = true;
        }
        // 创建随机障碍物,数量为inner_walls_count
        for (let i = 0; i < this.inner_walls_count; i++) {
            for (let j = 0; j < 1000; j++) {
                let r = parseInt(Math.random() * this.rows);
                let c = parseInt(Math.random() * this.cols);
                if (g[r][c] || g[c][r]) continue;
                if ((r == this.rows - 2 && c == 1) || (r == 1 && c == this.cols - 2)) continue;
                g[r][c] = g[c][r] = true;
                break;
            }
        }
        // 转换成JSON再转换回来
        const copy_g = JSON.parse(JSON.stringify(g));
        if (!this.check_connectivity(this.rows - 2, 1, 1, this.cols - 2, copy_g)) {
            return false;
        }
        for (let r = 0; r < this.rows; r++) {
            for (let c = 0; c < this.cols; c++) {
                if (g[r][c]) {
                    this.wall.push(new Wall(r, c, this));
                }
            }
        }
        return true;
    }
    start() {
        for (let i = 0; i < 1000; i++) {
            if (this.create_walls())
                break;
        }
    }
    update_size() {  //每一帧都更新边长
        // 动态求最小正方形边长
        // 取整数
        this.L = Math.min(this.parent.clientWidth / this.cols, this.parent.clientHeight / this.rows);
        this.ctx.canvas.width = this.L * this.cols;
        this.ctx.canvas.height = this.L * this.rows;
    }
    update() {     //每帧渲染一次
        this.update_size();
        this.render();
    }

    render() {      //渲染  
        // 画地图
        const color_even = "#AAD751", color_odd = "#A2D149";
        for (let r = 0; r < this.rows; r++) {
            for (let c = 0; c < this.cols; c++) {
                if ((r + c) % 2 == 0) {
                    this.ctx.fillStyle = color_even;
                } else {
                    this.ctx.fillStyle = color_odd;
                }
                // 左上角左边,明确canvas坐标系
                this.ctx.fillRect(c * this.L, r * this.L, this.L, this.L);
            }

        }
    }
}

游戏区域

components--->PlayGround.vue



 


地图组件 

GameMap.vue


  

  

  

 实体墙

scrips----->wall.js

// 实体墙
import { AcGameObject } from "./AcGameObject";
export class Wall extends AcGameObject {
    constructor(r, c, gamemap) {
        super();
        this.r = r;
        this.c = c;
        this.gamemap = gamemap;
        this.color = "#B37226";
    }
    update() {

        this.render();
    }
    render() {
        const L = this.gamemap.L;
        const ctx = this.gamemap.ctx;
        ctx.fillStyle = this.color;
        ctx.fillRect(this.c * L, this.r * L, L, L);
    }
}

 参考

项目实战——创建菜单与游戏页面(上)_游戏页面是如何实现的-CSDN博客​​​​​​​

 

你可能感兴趣的:(springboot,springboot,vue,vue.js)