不绘制所有瓷砖的Javascript 2d tilemap

如何解决不绘制所有瓷砖的Javascript 2d tilemap

我正在用 JavaScript 创建一个 2D 平台游戏。我正在尝试创建一个 tilemap,它不会在应该有空气的块中生成(在 tilemap 中标记为 0)。我没有收到任何错误。但是,画布中不会生成任何块。除非我取消碰撞检测,否则游戏也会崩溃。

主要js

//drawing variables
var canvas;
var context;

//game variables
var gameLoop;
var player;
var borders = [];
var mapHeight = 12;
var mapWidth = 22;
var tilesize = 50;

//input variables
var upKey;
var rightKey;
var downKey;
var leftKey;

//runs once pace has been loaded
window.onload = function(){
    //canvas and context variable setup
    canvas = document.getElementById("gameCanvas")
    context = canvas.getContext("2d")

    //key listeners 
    setupInputs();

    //create player
    player = new Player(400,400);

    //create border
    let tilemap = [
        [0,0],[0,[1,1,1],]

    //create a box (border) based on tilemap position. Let 0's be air
    for (let row = 0; row < mapHeight; row++){
        for(let col = 0; col < mapWidth; col++){
            if(tilemap[row][col] !== 0){
                borders.push(new Border(tilemap[row]*tilesize,tilemap[col]*tilesize,tilesize,tilemap[row][col]));
            }
        }
    }

    //initialize main game loop. Framerate = 30/sec
    gameLoop = setInterval(step,1000/30);

    //draw canvas
    context.fillStyle = "#f4f4f4f4"
    context.fillRect(0,mapWidth*tilesize,mapHeight*tilesize);
}

function step(){
    player.step();

    //draw after updates
    draw();
}

function draw(){
    //Clear previous canvas
    context.fillStyle = "#f4f4f4f4"
    context.fillRect(0,mapHeight*tilesize);

    //draw the player
    player.draw();

    //draw borders
    for(let i = 0; i < borders.length; i++){
        borders[i].draw();
    }
}

//keyboard inputs
function setupInputs(){
    document.addEventListener("keydown",function(event){
        if(event.key === "w"){
            upKey = true;
        } else if(event.key === "a"){
            leftKey = true;
        } else if(event.key === "s"){
            downKey = true;
        } else if(event.key === "d"){
            rightKey = true;
        }
    });
    document.addEventListener("keyup",function(event){
        if(event.key === "w"){
            upKey = false;
        } else if(event.key === "a"){
            leftKey = false;
        } else if(event.key === "s"){
            downKey = false;
        } else if(event.key === "d"){
            rightKey = false;
        }
    });
}

//Checking to see if player and border intersect
function checkIntersection(r1,r2){
    if (r1.x >= r2.x + r2.width){
        return false;
    } else if (r1.x + r1.width <= r2.x){
        return false;
    } else if (r1.y >= r2.y + r2.height){
        return false;
    } else if (r1.y + r1.height <= r2.y){
        return false;
    } else {
        return true;
    }
}

播放器js

function Player(x,y){
    //Player variables
    this.x = x;
    this.y = y;
    this.xvel = 0;
    this.yvel = 0;
    this.friction = 0.6;
    this.maxVel = 12;
    this.width = tilesize;
    this.height = tilesize;
    this.active = true;
    this.falling = false;


    this.step = function(){
        if(this.active){
            if(!leftKey && !rightKey || leftKey && rightKey){
                this.xvel *= this.friction;
            } else if (rightKey){
                this.xvel++;
            } else if (leftKey){
                this.xvel--;
            }

            if(upKey){
                //check if standing on ground
                if (this.yvel === 0 && this.falling === false){
                    this.yvel -= 70;
                    this.falling = true;
                } else{
                    this.yvel += 0;
                }
            }
            this.yvel += 1;

            //not allowing velocity to surpass maximum velocity
            if (this.xvel > this.maxVel){
                this.xvel = this.maxVel;
            } else if(this.xvel < -this.maxVel){
                this.xvel = -this.maxVel; 
            }
            if (this.yvel > this.maxVel){
                this.yvel = this.maxVel;
            } else if(this.yvel < -this.maxVel){
                this.yvel = -this.maxVel; 
            }
            if (this.xvel > 0){
                this.xvel = Math.floor(this.xvel);
            } else {
                this.xvel = Math.ceil(this.xvel);
            }
            if (this.yvel > 0){
                this.yvel = Math.floor(this.yvel);
            } else {
                this.yvel = Math.ceil(this.yvel);
            }

            //collision rectangles
            let horizontalRect = {
                x: this.x + this.xvel,y: this.y,width: this.width,height: this.height
            }
            let verticalRect = {
                x: this.x,y: this.y + this.yvel,height: this.height
            }
            //Collision deteQction
            for(let i = 0; i<borders.length; i++){
                let borderRect = {
                    x: borders[i].x,y: borders[i].y,width: borders[i].width,height: borders[i].height
                }
                if (checkIntersection(horizontalRect,borderRect)){
                    while (checkIntersection(horizontalRect,borderRect)){
                        horizontalRect.x -= Math.sign(this.xvel);
                    }
                    this.x = horizontalRect.x;
                    this.xvel = 0;
                }
                if (checkIntersection(verticalRect,borderRect)){
                    while(checkIntersection(verticalRect,borderRect)){
                        verticalRect.y -= Math.sign(this.yvel);
                    }
                    this.y = verticalRect.y;
                    this.yvel = 0;
                    this.falling = false;
                }
            }
            if (this.x + this.xvel > mapWidth*tilesize - tileisze){
                this.xvel = 0;
            }
            if (this.x + this.xvel < 0){
                this.xvel = 0;
            }
            
            this.x += this.xvel;
            this.y += this.yvel;
        }
    }

    this.draw = function(){
        context.fillStyle = "orange";
        context.fillRect(this.x,this.y,this.width,this.height);
    }
}

边框js

function Border(x,y,width,height,type){
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.type = type;

    this.draw = function(){
        if (this.type === 1){
            context.fillStyle = "#2C2C34";
        } else if (this.type === 2){
            context.fillStyle = "#39393A";
        }
        context.fillRect(this.x,this.height);
    }
}

解决方法

您的代码中似乎有几个错误,可能需要一段时间才能找到所有错误。您的十六进制颜色有 8 个字符 "#f4f4f4f4"。您的地图宽度为 22,但二维数组中只有 21 列。当您创建边界数组时,rows 位置的 xcol 位置的 y 似乎也是错误的。我好像应该反过来。无论如何,如果你不反对使用一维数组,这里是你的代码的简化版本,没有播放器的东西。

边框

function Border(type,x,y){
    this.x = x;
    this.y = y;
    this.width = TILE_SIZE;
    this.height = TILE_SIZE;
    this.type = type;

    this.draw = function(){
        if (this.type === 1){
            context.fillStyle = "purple";
            context.fillRect(this.x,this.y,this.width,this.height);
        } else if (this.type === 2){
            context.fillStyle = "orange";
            context.fillRect(this.x,this.height);
        }
    }
}

和主文件

const canvas = document.getElementById("canvas")
const context = canvas.getContext("2d")
const TILE_SIZE = 25; //50 was too big for my screen based on how many rows/columns you wanted
canvas.width = 525; //TILE_SIZE * columns
canvas.height = 300; //TILE_SIZE * rows

var borders = [];

let tileMap = {
    mapHeight: 12,mapWidth: 21,size: TILE_SIZE,grid: [
        0,2,1,]
}
//Uses 1 loop to create the grid
function createGrid() {
    for (let i = 0; i < tileMap.grid.length; i++) {
        let x = (i % tileMap.mapWidth) * tileMap.size;
        let y = Math.floor((i / tileMap.mapWidth)) * tileMap.size;
        let type = tileMap.grid[i];
        borders.push(new Border(type,y));
    }
};
createGrid(); //creates the grid when file is loaded

function animate() {
    context.clearRect(0,canvas.width,canvas.height);
    for(let i = 0; i < borders.length; i++){
        borders[i].draw();
    }
    requestAnimationFrame(animate);
}
animate()

我仅在此示例中将 for 循环插入到 animate 函数中。通常它会是它自己的功能,在那里你可以处理碰撞检测或绘制瓦片或任何你想用它们做的事情。

如果你必须使用二维数组,这里有一个函数可以创建它

function createGrid() {
   for (let row = 0; row < tileMap.mapHeight; row++) {
    for (let col = 0; col < tileMap.mapWidth; col++) {
       let type = tileMap.grid[row][col];
       let x = col * TILE_SIZE;
       let y = row * TILE_SIZE;
       borders.push(new Border(type,y))
    }
   }
}
createGrid()

如果您使用我上面发布的地图,请务必将地图改回 2d。我还注意到在您的播放器文件中,您有一次使用 tileisze 而不是 tilesize。我会花一些时间仔细检查您的文件中是否有错误,因为这些可能是导致您出现某些问题的原因。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res