gpt4 book ai didi

javascript - 使用javascript渲染 map

转载 作者:行者123 更新时间:2023-12-04 00:07:40 25 4
gpt4 key购买 nike

我正在寻找有关采用这样的tilemap的示例实现想法的逻辑理解:

http://thorsummoner.github.io/old-html-tabletop-test/pallete/tilesets/fullmap/scbw_tiles.png

并以这种逻辑方式进行渲染:

http://thorsummoner.github.io/old-html-tabletop-test/

我看到所有的瓷砖都在那里,但是我不明白如何以形成形状的方式放置它们。

到目前为止,我对渲染图块的理解很简单,而且非常手工。遍历有数字(1、2、3等)的 map 数组,渲染指定的图块。

var mapArray = [
[0, 0, 0, 0 ,0],
[0, 1, 0, 0 ,0],
[0, 0, 0, 0 ,0],
[0, 0, 0, 0 ,0],
[0, 0, 1, 1 ,0]
];

function drawMap() {
background = new createjs.Container();
for (var y = 0; y < mapArray.length; y++) {
for (var x = 0; x < mapArray[y].length; x++) {
if (parseInt(mapArray[y][x]) == 0) {
var tile = new createjs.Bitmap('images/tile.png');
}
if (parseInt(mapArray[y][x]) == 1) {
var tile = new createjs.Bitmap('images/tile2.png');
}
tile.x = x * 28;
tile.y = y * 28;
background.addChild(tile);
}
}
stage.addChild(background);
}

得到我:

但这意味着我必须手动弄清楚每个图块在阵列中的位置,以便形成逻辑形状(岩层,草丛等)

显然,制作上述github代码的人使用了不同的方法。关于理解 逻辑(仅使用伪代码)的任何指导都将非常有帮助

最佳答案

那里没有任何逻辑。

如果检查页面的源代码,您将看到正文中的最后一个脚本标签具有大量的图块坐标。

在该示例中,没有任何魔术可以演示“智能”系统来弄清楚如何形成形状。

就是说,有这样的事情……但是它们并非遥不可及。

更简单,更易管理的是 map 编辑器。

拼贴编辑器

开箱即用:

有很多方法可以执行此操作...有免费或廉价的程序,这些程序可以让您绘制图块,然后吐出XML或JSON或CSV或任何给定程序支持/导出的程序。

平铺的(http://mapeditor.org)是这样的示例。
还有其他一些,但是Tiled是我能想到的第一个,是免费的,而且实际上相当不错。

优点:
直接的好处是,您将获得一个应用程序,可让您加载图像图块并将其绘制到 map 中。
这些应用程序甚至可能支持添加碰撞层和实体层(在[2,1]放置一个敌人,在[3,5]放置一个上电,并在熔岩上触发“伤害玩家”触发器)。

缺点:
...缺点是您需要确切了解这些文件的格式,以便可以将它们读入游戏引擎。
现在,这些系统的输出是相对标准化的...因此您可以将映射数据插入不同的游戏引擎中(否则,这是什么意思?),而游戏引擎并不都使用完全相同的图块文件同样,大多数优秀的图块编辑器都可以导出为多种格式(有些可以让您定义自己的格式)。

...也就是说,替代方案(或者实际上是相同的解决方案,只是手工制作)将是创建自己的磁贴编辑器。

DIY
您可以在Canvas中创建它,就像创建用于绘制图块的引擎一样容易。
关键区别在于您拥有了瓷砖 map (如StarCr ... erm的tilemap.png ...示例中的“发现的艺术品”)。
无需遍历数组,而是查找图块的坐标并在与该索引匹配的世界坐标上绘制它们,您要做的就是从 map 上选择一个图块(例如在MS Paint中选择颜色),然后在任何地方单击(或拖动),找出与哪个数组点相关,并将该索引设置为等于该图块。

优点:
天空才是极限;您可以制作任何您想要的东西,使其适合您要使用的任何文件格式,并使其处理要扔给它的任何疯狂的东西...
缺点:
...这当然意味着您必须自己创建它,并定义要使用的文件格式,并编写逻辑来处理所有这些奇怪的想法...

基本实现
虽然我通常会尝试使代码整洁且对JS范式友好,但这会产生大量代码。
因此,我将尝试指出应该将其分解为单独的模块的位置。

// assuming images are already loaded properly
// and have fired onload events, which you've listened for
// so that there are no surprises, when your engine tries to
// paint something that isn't there, yet


// this should all be wrapped in a module that deals with
// loading tile-maps, selecting the tile to "paint" with,
// and generating the data-format for the tile, for you to put into the array
// (or accepting plug-in data-formatters, to do so)
var selected_tile = null,
selected_tile_map = get_tile_map(), // this would be an image with your tiles
tile_width = 64, // in image-pixels, not canvas/screen-pixels
tile_height = 64, // in image-pixels, not canvas/screen-pixels

num_tiles_x = selected_tile_map.width / tile_width,
num_tiles_y = selected_tile_map.height / tile_height,

select_tile_num_from_map = function (map_px_X, map_px_Y) {
// there are *lots* of ways to do this, but keeping it simple
var tile_y = Math.floor(map_px_Y / tile_height), // 4 = floor(280/64)
tile_x = Math.floor(map_px_X / tile_width ),

tile_num = tile_y * num_tiles_x + tile_x;
// 23 = 4 down * 5 per row + 3 over

return tile_num;
};

// won't go into event-handling and coordinate-normalization
selected_tile_map.onclick = function (evt) {
// these are the coordinates of the click,
//as they relate to the actual image at full scale
map_x, map_y;
selected_tile = select_tile_num_from_map(map_x, map_y);
};

现在,您有了一个简单的系统,可以确定单击了哪个图块。
同样,有很多方法可以构建它,您可以使其更加面向对象,
并建立一个适当的“平铺”数据结构,以供您在整个引擎中阅读和使用。

现在,我只是返回从零开始的图块编号,从左到右,从上到下读取。
如果每行有5个图块,并且有人选择了第二行的第一个图块,那就是第5个图块。

然后,对于“绘画”,您只需要听一下 Canvas 单击,找出X和Y是什么,
找出世界上的什么地方,以及等于什么阵列点。
从那里,您只需转储 selected_tile的值,就是这样。
// this might be one long array, like I did with the tile-map and the number of the tile
// or it might be an array of arrays: each inner-array would be a "row",
// and the outer array would keep track of how many rows down you are,
// from the top of the world
var world_map = [],

selected_coordinate = 0,

world_tile_width = 64, // these might be in *canvas* pixels, or "world" pixels
world_tile_height = 64, // this is so you can scale the size of tiles,
// or zoom in and out of the map, etc

world_width = 320,
world_height = 320,


num_world_tiles_x = world_width / world_tile_width,
num_world_tiles_y = world_height / world_tile_height,

get_map_coordinates_from_click = function (world_x, world_y) {
var coord_x = Math.floor(world_px_x / num_world_tiles_x),
coord_y = Math.floor(world_px_y / num_world_tiles_y),

array_coord = coord_y * num_world_tiles_x + coord_x;

return array_coord;
},

set_map_tile = function (index, tile) {
world_map[index] = tile;
};

canvas.onclick = function (evt) {
// convert screen x/y to canvas, and canvas to world
world_px_x, world_px_y;
selected_coordinate = get_map_coordinates_from_click(world_px_x, world_px_y);

set_map_tile(selected_coordinate, selected_tile);
};

如您所见,执行一个操作的过程与执行另一个操作的过程几乎相同(因为它是-给定一个坐标集中的x和y,将其转换为另一个比例/集)。

然后,绘制图块的过程几乎完全相反。
给定world-index和tile-number,进行相反的操作以找到world-x / y和tilemap-x / y。
您也可以在示例代码中看到该部分。

无论我们谈论的是《星际争霸》,《塞尔达传说》还是《马里奥兄弟》,这种瓷砖绘画都是制作2d map 的传统方式。
并非所有人都拥有“用瓷砖绘制”编辑器的奢侈(有些是手工放置在文本文件甚至电子表格中,以确保正确的间距),但是如果您加载了StarCraft甚至是WarCraft III( 3D),然后进入他们的编辑器,瓷砖画家就是您所能获得的,也是暴雪制作这些 map 的方式。

加法

有了基本前提,您现在还需要其他“ map ”:
您需要一个碰撞图来了解您不能/不能在其中行走的哪些图块,实体图,以显示哪里有门,通电,矿物,敌方生成或事件的地方。触发过场动画...

并非所有这些都需要在与世界 map 相同的坐标空间中进行操作,但这可能会有所帮助。

另外,您可能想要一个更智能的“世界”。
可以在一个级别中使用多个图块 map 的功能,例如...
图块编辑器中的一个下拉菜单可以交换图块 map 。

...一种保存瓦片信息(不仅是X / Y信息,而且还包含有关瓦片的其他信息)以及保存完成的由瓦片填充的“ map ”数组的方法。

甚至只是复制JSON,然后将其粘贴到自己的文件中...

程序生成

另一种执行此操作的方法是您先前建议的方法(“知道如何连接岩石,草等”),称为过程生成。
这要困难得多,牵涉更多。
像《暗黑破坏神》这样的游戏会使用此功能,以便每次玩游戏时您都处于随机生成的不同环境中。 Warframe是FPS,它使用程序生成来完成相同的操作。

前提:
基本上,您从图块开始,而不仅仅是图块是图像,图块必须是具有图像和位置的对象,但是ALSO还列出了可能围绕它的事物。
当放下一块草时,该草就有可能在其旁边产生更多草。
草可能表示在周围的四个方向中,有10%的机会有水,有20%的机会有岩石,有30%的机会有污垢,有40%的机会有更多的草。

当然,它实际上并不是那么简单(如果您错了,也可以如此)。

虽然这就是想法,但是过程生成的棘手部分实际上是确保一切正常运行而不会中断。
约束
例如,在该示例中,您不能让悬崖墙出现在高地的内部。它只能出现在上方和右侧的高地,下方和左侧的低地的位置(如您绘制的那样,StarCraft编辑器会自动执行此操作)。坡道只能连接有意义的砖块。您不能关门,也不能将世界包裹在阻碍移动(或更糟的是,无法完成关卡)的河流/湖泊中。

优点
如果您可以使所有寻路和约束都能正常工作,那么这对于长寿确实非常有用-不仅用于伪随机生成地形和布局,而且还可以用于敌人放置,战利品放置等等。
近14年后,人们仍在玩《暗黑破坏神II》。

缺点
当您是一个单人团队时(在他们的业余时间里碰巧不是数学家/数据科学家),确实很难做到正确。
确实无法保证 map 的趣味性/平衡性/竞争性...
《星际争霸》绝对不可能使用100%随机生成的游戏来获得公平的游戏体验。
程序生成可以用作“种子”。
您可以点击“随机化”按钮,查看获得的结果,然后从那里进行调整和修复,但是将有太多的“平衡”修复方法或为限制传播而编写的众多游戏规则,最终,您将花费更多的时间来修复生成器,而不仅仅是自己绘制 map 。

那里有一些教程,学习遗传算法,寻路等等,都是很棒的技能……buuuut,对于学习制作自上而下的2D方块游戏来说,是过分的杀手,或者是,在获得一两个游戏/引擎后,您需要研究的东西。

关于javascript - 使用javascript渲染 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21844451/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com