version-1.5[实现游戏地图:障碍物+背景格]

pull/1/head
dyh 3 years ago
parent 1cb251f5e1
commit c4b16d76db

@ -40,7 +40,7 @@ export default {
<style>
body {
background-image: url("@/assets/background.png");
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,71 @@
const AC_GAME_OBJECTS = [];
// 基类
export class AcGameObject
{
constructor(){
//添加对象
AC_GAME_OBJECTS.push(this);
//时间间隔
this.timedelta = 0;
//没有执行过start函数
this.has_called_satrt = 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_satrt===false)//执行start
{
obj.start();//调用的是子类的start()
obj.has_called_satrt=true;
}
else //执行update
{
obj.update();//调用的是子类的update()
obj.timedelta = timestamp - last_timestamp;//当前-之前
}
}
last_timestamp = timestamp;
//【迭代】浏览器每一秒会迭代60次
requestAnimationFrame(step);
}
//浏览器刷新 -> 执行一次
requestAnimationFrame(step);

@ -0,0 +1,139 @@
import { AcGameObject } from "./AcGameObject";
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.walls=[];
this.inner_walls_count = 20;
}
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]==false && this.check_connectivity(g,x,y,tx,ty))return true;
}
return false;
}
create_wall(){
//初始化【没有墙 false】
const g=[]
for(let r=0;r<this.rows;r++)
{
g[r]=[];
for(let c=0;c<this.cols;c++)
{
g[r][c]=false;
}
}
// g数组与画布方向相反
//左右加墙
for(let r=0;r<this.rows;r++){
g[r][0]=g[r][this.cols-1]=true;
}
// 上下加墙
for(let c=0;c<this.rows;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<=10000;j++)
{
let r = parseInt(Math.random()*this.rows);
let c = parseInt(Math.random()*this.cols);
// console.log(r,c);
//对称
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));
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(){//创建一次墙(除非刷新)
//直到创建成功
for(let i=0;i<=100000000;i++)
{
if(this.create_wall())break;
}
}
//动态检查canvas大小
update_size(){
//注意clientWidth拼写
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() {
// this.create_wall();
const color_even="#AAD752",color_odd="#A2D048";
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;
}
//注为什么会居中以谁为左上角画图的【右边x,下边y】
// 根据canvas小格宽度先画出 --> 然后flex居中排布
this.ctx.fillRect(c*this.L,r*this.L,this.L,this.L);
}
}
// //测试
// this.ctx.fillStyle = "red";
// this.ctx.fillRect(0,0,this.ctx.canvas.width,this.ctx.canvas.height);
}
}

@ -0,0 +1,32 @@
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 = "#B37266";
}
start(){
}
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,42 @@
<template>
<div ref="parent" class="gamemap">
<canvas ref="canvas"></canvas>
</div>
</template>
<script>
// {}
import { GameMap } from "@/assets/scripts/GameMap.js";
import { ref,onMounted } from "vue";
export default {
setup(){
//DOM
let parent = ref(null);
let canvas = ref(null);
onMounted(()=>{
new GameMap(canvas.value.getContext('2d'),parent.value);
// console.log(parent.value);//DOM
// console.log(canvas.value);//DOM
})
return {
parent,
canvas
}
}
}
</script>
<style scoped>
div.gamemap {
width: 100%;
height:100%;
/* 将canvas画布居中 */
display: flex;
justify-content:center;
align-items: center;
}
</style>

@ -0,0 +1,27 @@
<template>
<div class="playground">
<GameMap></GameMap>
</div>
</template>
<script>
import GameMap from "@/components/GameMap.vue";
export default {
components:{
GameMap,
}
}
</script>
<style scoped>
div.playground {
width: 60vw;
height: 70vh;
/* background-color: lightblue; */
margin: 40px auto;
}
</style>

@ -1,15 +1,13 @@
<template>
<ContentField>
PK卡槽
</ContentField>
<PlayGround></PlayGround>
</template>
<script>
import ContentField from "@/components/ContentField"
import PlayGround from "@/components/PlayGround"
export default {
components:{
ContentField
PlayGround,
}
}
</script>

Loading…
Cancel
Save