parent
2e0afa1d33
commit
03d1906bea
18 changed files with 508 additions and 45 deletions
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 49 KiB |
@ -1,39 +1,23 @@ |
||||
<template> |
||||
<div> |
||||
<h1>bot昵称: {{bot_name}} </h1> |
||||
<h1>bot战力: {{bot_rating}} </h1> |
||||
</div> |
||||
<router-view></router-view> |
||||
<NavBar /> <!--在前端页面中展示NavBar组件----> |
||||
<router-view></router-view> |
||||
</template> |
||||
|
||||
<script> |
||||
import $ from 'jquery'; |
||||
import { ref } from 'vue'; |
||||
export default{ |
||||
name:"app", |
||||
setup:() => { |
||||
let bot_name = ref(""); |
||||
let bot_rating = ref(""); |
||||
$.ajax({ |
||||
url: "http://localhost:3000/pk/getInfo2/", |
||||
type: 'get', |
||||
success: resp => { |
||||
console.log(resp); |
||||
bot_name.value = resp.name; |
||||
bot_rating.value = resp.rating; |
||||
} |
||||
}); |
||||
return { |
||||
bot_name, |
||||
bot_rating |
||||
} |
||||
import NavBar from './components/NavBar.vue' // 导入NavBar组件(.vue)结尾 |
||||
import "bootstrap/dist/css/bootstrap.min.css" |
||||
import "bootstrap/dist/js/bootstrap" |
||||
|
||||
export default { |
||||
components: { // 使用NavBar组件 |
||||
NavBar |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
body{ |
||||
background-image: url("@/assets/background.png"); |
||||
body { |
||||
background-image: url("@/assets/images/background.png"); |
||||
background-size: cover; |
||||
} |
||||
</style> |
||||
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
@ -0,0 +1,50 @@ |
||||
const AC_GAME_OBJECTS = []; |
||||
|
||||
export class AcGameObject { |
||||
constructor() { |
||||
AC_GAME_OBJECTS.push(this); // 数组添加元素
|
||||
this.timedelta = 0; |
||||
this.has_called_start = false; |
||||
} |
||||
|
||||
start() { // 只执行一次
|
||||
} |
||||
|
||||
update() { // 每一帧执行一次,除了第一帧之外
|
||||
|
||||
} |
||||
|
||||
on_destroy() { // 删除之前执行
|
||||
|
||||
} |
||||
|
||||
destroy() { |
||||
this.on_destroy(); |
||||
|
||||
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; // 上一次执行的时刻
|
||||
const step = timestamp => { |
||||
for (let obj of AC_GAME_OBJECTS) { // 遍历数组的值
|
||||
if (!obj.has_called_start) { // 如果对象没有被调用
|
||||
obj.has_called_start = true; |
||||
obj.start(); |
||||
} else { |
||||
obj.timedelta = timestamp - last_timestamp; // 获得当前帧和上一帧的时间差
|
||||
obj.update(); |
||||
} |
||||
} |
||||
|
||||
last_timestamp = timestamp; // 将当前时间更新为上一帧执行时刻
|
||||
requestAnimationFrame(step) // 递归调用该函数
|
||||
} |
||||
|
||||
requestAnimationFrame(step) |
@ -0,0 +1,116 @@ |
||||
import { AcGameObject } from "./AcGameObject"; // 导入js的export class
|
||||
import { Wall } from "./Wall"; |
||||
|
||||
export class GameMap extends AcGameObject { |
||||
constructor(ctx, parent) { |
||||
super(); // 继承类一直要先调用父类的构造函数
|
||||
|
||||
this.ctx = ctx; |
||||
this.parent = parent; |
||||
this.L = 0; |
||||
|
||||
this.rows = 13; |
||||
this.cols = 13; |
||||
|
||||
this.inner_walls_count = 20; // 障碍物的数量(最大建议80)
|
||||
this.walls = []; // 所有障碍物组成的数组
|
||||
} |
||||
|
||||
check_connectivity(g, sx, sy, tx, ty) { // 判断生成的地图是否可以连通
|
||||
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(g, x, y, tx, ty)) |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
create_walls() { // 判断是否生成有效的地图
|
||||
const g = []; |
||||
for (let r = 0; r < this.rows; 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; |
||||
} |
||||
|
||||
// 创建随机障碍物
|
||||
for (let i = 0; i < this.inner_walls_count / 2; 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; |
||||
} |
||||
} |
||||
|
||||
const copy_g = JSON.parse(JSON.stringify(g)); |
||||
|
||||
// 如果生成的地图无法连通,则返回false,需要重新生成
|
||||
if (!this.check_connectivity(copy_g, this.rows - 2, 1, 1, this.cols - 2)) |
||||
return false; |
||||
|
||||
for (let r = 0; r < this.rows; r ++ ) { |
||||
for (let c = 0; c < this.cols; c ++ ) { |
||||
if (g[r][c]) { |
||||
// 每次添加一个障碍物
|
||||
this.walls.push(new Wall(r, c, this)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
start() { |
||||
// 尝试1000次,直到找到符合条件的地图为止
|
||||
for (let i = 0; i < 1000; i ++ )
|
||||
if (this.create_walls()) |
||||
break; |
||||
} |
||||
|
||||
update_size() { // 每过一帧重新生成新的地图尺寸
|
||||
// 取整数
|
||||
this.L = parseInt(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; |
||||
} |
||||
this.ctx.fillRect(c * this.L, r * this.L, this.L, this.L); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
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); // 将对应位置填充为障碍物
|
||||
} |
||||
} |
@ -0,0 +1,18 @@ |
||||
<template> |
||||
<div class="container content-field"> |
||||
<div class="card"> |
||||
<div class="card-body"> |
||||
<slot></slot> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
</script> |
||||
|
||||
<style scoped> |
||||
div.content-field { |
||||
margin-top: 40px; |
||||
} |
||||
</style> |
@ -0,0 +1,36 @@ |
||||
<template> |
||||
<div ref="parent" class="gamemap"> <!--使用下面返回的parent--> |
||||
<canvas ref="canvas"></canvas> <!--使用下面返回的canvas--> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { GameMap } from "@/assets/scripts/GameMap"; // 从js中导入GameMap类(public) |
||||
import { ref, onMounted } from 'vue' |
||||
|
||||
export default { |
||||
setup() { |
||||
let parent = ref(null); |
||||
let canvas = ref(null); |
||||
|
||||
onMounted(() => { |
||||
new GameMap(canvas.value.getContext('2d'), parent.value) |
||||
}); |
||||
|
||||
return { |
||||
parent, |
||||
canvas |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
div.gamemap { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
</style> |
@ -0,0 +1,54 @@ |
||||
<template> |
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> |
||||
<div class="container"> |
||||
<router-link class="navbar-brand" :to="{name: 'home'}">King Of Bots</router-link> |
||||
<div class="collapse navbar-collapse" id="navbarText"> |
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> |
||||
<li class="nav-item"> |
||||
<router-link :class="route_name == 'pk_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'pk_index'}">对战</router-link> |
||||
</li> |
||||
<li class="nav-item"> |
||||
<router-link :class="route_name == 'record_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'record_index'}">对局列表</router-link> |
||||
</li> |
||||
<li class="nav-item"> |
||||
<router-link :class="route_name == 'ranklist_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'ranklist_index'}">排行榜</router-link> |
||||
</li> |
||||
</ul> |
||||
<ul class="navbar-nav"> |
||||
<li class="nav-item dropdown"> |
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> |
||||
zhangfp |
||||
</a> |
||||
<ul class="dropdown-menu" aria-labelledby="navbarDropdown"> |
||||
<li> |
||||
|
||||
<router-link class="dropdown-item" :to="{name: 'user_bot_index'}">我的Bot</router-link> |
||||
</li> |
||||
<li><hr class="dropdown-divider"></li> |
||||
<li><a class="dropdown-item" href="#">退出</a></li> |
||||
</ul> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</nav> |
||||
</template> |
||||
|
||||
<script> |
||||
import { useRoute } from 'vue-router' |
||||
import { computed } from 'vue' |
||||
|
||||
export default { |
||||
setup() { |
||||
const route = useRoute(); |
||||
let route_name = computed(() => route.name) |
||||
return { |
||||
route_name |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
@ -0,0 +1,24 @@ |
||||
<template> |
||||
<div class="playground"> |
||||
<GameMap /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import GameMap from './GameMap.vue' // 导入GameMap组件(.vue结尾) |
||||
|
||||
export default { |
||||
components: { // 使用GameMap组件 |
||||
GameMap, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
/* div标签的样式 */ |
||||
div.playground { |
||||
width: 60vw; |
||||
height: 70vh; |
||||
margin: 40px auto; |
||||
} |
||||
</style> |
@ -0,0 +1,19 @@ |
||||
<template> |
||||
<ContentField> |
||||
404 Not Found |
||||
</ContentField> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import ContentField from '../../components/ContentField.vue' |
||||
|
||||
export default { |
||||
components: { |
||||
ContentField |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
</style> |
@ -0,0 +1,16 @@ |
||||
<template> |
||||
<PlayGround/> |
||||
</template> |
||||
|
||||
<script> |
||||
import PlayGround from '../../components/PlayGround.vue' |
||||
|
||||
export default { |
||||
components: { |
||||
PlayGround |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
</style> |
@ -0,0 +1,18 @@ |
||||
<template> |
||||
<ContentField> |
||||
排行榜 |
||||
</ContentField> |
||||
</template> |
||||
|
||||
<script> |
||||
import ContentField from '../../components/ContentField.vue' |
||||
|
||||
export default { |
||||
components: { |
||||
ContentField |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
</style> |
@ -0,0 +1,18 @@ |
||||
<template> |
||||
<ContentField> |
||||
对局列表 |
||||
</ContentField> |
||||
</template> |
||||
|
||||
<script> |
||||
import ContentField from '../../components/ContentField.vue' |
||||
|
||||
export default { |
||||
components: { |
||||
ContentField |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
</style> |
@ -0,0 +1,18 @@ |
||||
<template> |
||||
<ContentField> |
||||
我的Bot |
||||
</ContentField> |
||||
</template> |
||||
|
||||
<script> |
||||
import ContentField from '../../../components/ContentField.vue' |
||||
|
||||
export default { |
||||
components: { |
||||
ContentField |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
</style> |
Loading…
Reference in new issue