简体   繁体   English

在网格级别移动图块的组织系统

[英]Organizational system for moving tiles in grid-based level

conceptual problem here. 这里的概念性问题。

I have an array which will be rendered to display tiles in a grid. 我有一个数组,将其呈现为在网格中显示图块。 Now, I want these tiles to be able to move - but not just around in the grid. 现在,我希望这些图块能够移动-但不仅仅是在网格中移动。 Per-pixel. 每像素。 It does need to be a grid, because I need to shift whole rows of tiles, and be able to access tiles by their position, but it also needs to have per-pixel adjustment, while still keeping the "grid" up to date. 它确实需要是一个网格,因为我需要移动整行图块,并能够按其位置访问图块,但是它还需要进行逐像素调整,同时仍保持“网格”最新。 Picture a platforming game with moving tiles. 想象一下带有移动瓷砖的平台游戏。

There are a few organizational systems with which I could do this, and I'll outline a few I thought of as well as their pros and cons (XY-style) in case it helps you understand what I'm saying. 我可以使用一些组织系统来完成此工作,并且我将概述一些我认为的方法以及它们的优缺点(XY风格),以防它有助于您理解我的意思。 I'm asking if you think one of these is best, or think of a better way. 我想问的是,您是否认为其中之一是最好的,还是想一种更好的方法。

  1. One way would be to place objects in the array with the properties xOffset and yOffset . 一种方法是将对象放置在具有属性xOffsetyOffset的数组中。 I would then render them in their tile position plus their offset. 然后,我将它们渲染在其图块位置加上其偏移量。 ( x * tileWidth + tile.xOffset ). x * tileWidth + tile.xOffset )。 Pros: maintains vanilla grid-system. 优点:保持香草网格系统。 Cons: Then I would have to adjust each tile to its actual grid location once it moved. 缺点:一旦移动,我将不得不将每个图块调整到其实际网格位置。 Also, the "grid" position would become a bit confused as tiles are moving. 另外,随着瓷砖的移动,“网格”位置会变得有些混乱。 (Side note: If you think this is a good way, how would I handle collisions? It wouldn't be as simple as player.x / tileWidth anymore.) (旁注:如果您认为这是一种好方法,那么我将如何处理冲突?它不再像player.x / tileWidth那样简单。)

  2. Another would be to place lots of objects with x s and y s and render them all. 另一个方法是放置许多带有x s和y s的对象并将它们全部渲染。 Pros: Simple. 优点:简单。 Cons: Then I would have to check each one to see if it's in the row I want to shift before doing so. 缺点:然后,在执行此操作之前,我将必须检查每个对象是否都在我要移动的行中。 Also, collisions could not simply check the one tile a player is on, they would have to check all entities. 而且,碰撞不能简单地检查玩家所在的那张图块,而是必须检查所有实体。

  3. Another I thought of would be a sort of combination of the two. 我想到的另一个是两者的结合。 Tiles would be in the original array and get render as x * tileWidth normal tiles. Tiles将位于原始数组中,并以x * tileWidth普通瓦片的形式呈现。 Then, when they move, they are deleted from the grid and placed in a separate array for moving tiles, where their x and y are stored. 然后,当它们移动时,将它们从网格中删除,并放置在用于移动图块的单独数组中,并在其中存储它们的xy Then the collisions would check the grid the fast way and the moving tiles the slow way. 然后,碰撞将以快速方式检查网格,而以慢速方式检查移动瓷砖。

Thanks! 谢谢!

PS: I'm using JavaScript, but it shouldn't be relevant. PS:我使用的是JavaScript,但应该无关紧要。

PPS: Forgive me if it's not Stack Overflow material. PPS:原谅我不是Stack Overflow的内容。 This was the best fit, I thought. 我认为这是最合适的。 It's not exactly code review, but it's not specific to GameDev. 这不是完全的代码审查,但不是特定于GameDev。 Also I needed a tag, so I picked one somewhat relevant. 另外,我需要一个标签,所以我选择了一个相关标签。 If you guys recommend something else I'll be happy to switch it right over and delete this one. 如果你们推荐其他东西,我很乐意将其切换并删除。

PPPS: Sorry if repost, I have no idea how to google this question. PPPS:对不起,如果转贴,我知道如何用Google搜索这个问题。 I tried to no avail. 我无济于事。

(Side note on handling collisions: Your obstacles are moving. Therefore, comparing the player's position to grid is no longer ever sufficient. Furthermore, you will always have to draw based on the object's current position. Both of these are unavoidable, but also not very expensive.) (有关处理碰撞的注释:您的障碍物正在移动。因此,将玩家的位置与网格进行比较已不再足够。此外,您始终必须根据对象的当前位置进行绘制。这都是不可避免的,但也并非如此非常贵。)

You want the objects to be easy to look up, while still being able to draw them efficiently and, more importantly, quickly checking for collisions. 您希望对象易于查找,同时仍然能够有效地绘制它们,更重要的是,可以快速检查碰撞。 This is easy to do: store the objects in the array, and for the X and Y positions keep indexes which allow for 1) efficiently querying ranges and 2) efficiently moving elements left and right (as their x and y positions change). 这很容易做到:将对象存储在数组中,并且对于X和Y位置保留索引,这些索引允许1)有效查询范围和2)有效向左和向右移动元素(随着它们的x和y位置改变)。

If your objects are going to be moving fairly slowly (that is, on any one timestep, it is unlikely for an object to pass very many other objects), your indexes can be arrays! 如果您的对象移动得相当慢(也就是说,在任何一个时间步上,一个对象都不太可能传递很多其他对象),则索引可以是数组! When an object moves past another object (in X, for instance), you just need to check its neighbor in the X index array to see if they should swap places. 当一个对象经过另一个对象(例如,在X中)时,您只需要检查X索引数组中的它的邻居,看看它们是否应该交换位置。 Keep doing this until it does not need to swap. 继续执行此操作,直到不需要交换为止。 If they're moving slowly, the amortized cost of this will be very close to O(1). 如果他们行动缓慢,则其摊销成本将非常接近O(1)。 Querying ranges is very easy in an array; 在数组中查询范围非常容易。 binary search for the first greater element, and also for the last smaller element. 二进制搜索第一个较大的元素,以及最后一个较小的元素。

Summary/Implementation: (Fiddle at https://jsfiddle.net/LsfuLo9p/3/ ) 摘要/实现:(https://jsfiddle.net/LsfuLo9p/3/上显示小提琴)

Initialize (O(n) time): 初始化(O(n)时间):

  1. Make an array of your objects called Objs. 创建名为Objs.的对象数组Objs.
  2. Make an array of (x position, reference to Objs ) pairs, sorted in X, called Xs. 制作(x位置,参考Objs )对的数组,以X排序,称为Xs.
  3. Make an array of (y position, reference to Objs ) pairs, sorted in Y, called Ys. 创建一个数组(y位置,引用Objs )对,以Y排序,称为Ys.
  4. For every element in Xs and Ys , tell the object in Objs its index in those arrays (so that Xs has indexes to Objs, and Objs has indexes to Xs. ) 对于XsYs每个元素,在Objs告诉对象在这些数组中的索引(这样Xs拥有Objs,索引Objs,Objs拥有Xs.索引Xs.

When an object moves up in Y (O(1) expected time per moving object, given that they're moving slowly): 当一个对象以Y向上移动时(假设每个移动对象移动缓慢,则期望时间为O(1)):

  1. Using Objs , find its index in Ys. 使用Objs ,在Ys.找到其索引Ys.
  2. Compare it to the next highest value in Ys. 将其与Ys.的下一个最大值进行比较Ys. If it's greater, swap them in Ys (and update their Y indices in Objs ). 如果更大,则在Ys交换它们(并在Objs更新其Y索引)。
  3. Repeat step 2 until you don't swap. 重复步骤2,直到不进行交换。

(It's easy to apply this to the other three directions.) (将其应用于其他三个方向很容易。)

When the player moves (O(log n + k 2 ) time, where k is the maximum number of items that can fit in a row or column): 玩家移动时(O(log n + k 2 )时间,其中k是可容纳在一行或一列中的最大项目数):

  1. Look in Xs for small, the smallest X above Player.X, and large, the largest X+width below Player.X. 看在Xssmall,上面最小的X Player.X,large,下面的最大X +宽度Player.X. If largesmall , return the range [large, small]. 如果largesmall ,则返回范围[large, small].
  2. Look in Ys for small, the smallest Y above Player.Y, and large, the largest Y+height below Player.Y. 看在Yssmall,最小的ÿ上述Player.Y,large,最大的Y +高度低于Player.Y. If largesmall , return the range [large, small]. 如果largesmall ,则返回范围[large, small].
  3. If there are any intersections between these two ranges, then the player is colliding with that object. 如果这两个范围之间有任何交集,则说明玩家正在与该对象碰撞。

(You can improve the time of this to O(log n + k) by using a hashmap to check for set intersections.) (您可以通过使用哈希图检查设置的交集,将时间缩短为O(log n + k)。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM