0

目前正在编写 roguelike 以了解有关 Objective-C/Cocoa 的更多信息。到目前为止,我真的很喜欢它,而且我学到了很多东西。

此代码移动origin视图的bounds,以便它在玩家移动时跟随玩家。代码运行完美,我只是问是否有比使用 4 更好for的方法。

在某些情况下,我还看到最好分开做事情而不是一体做事,尤其是在绘图和nsbezierpath涉及到的情况下,这是为什么呢?

编辑:人们很难弄清楚我在做什么,所以我会尽可能多地分解它。

view是一个 30x30 的网格 (0-29,0-29),每个 20x20。地图可以根据需要变大或变小。

首先,您得到,[player_ location]以及originboundsview它被除以20因为瓷砖大小是20,所以当它在 时(1,2),它实际上是在(20,40)。我这样做的唯一原因是使其更易于操作(以 1 为单位比以 20 为单位更容易计数)。四个人for通过并检查[player_ location]是否在中心 ( ) 的15瓷砖内。如果玩家正在向屏幕的边缘之一移动,并且小于当前地图的高度/宽度,它会移动 以使玩家仍然居中并显示在地图上。bounds + 15viewbounds.x/y + 30origin

代码运行完美,我在 ' 发生setbounds后将其移至for,并且只有一个。它没有被遗忘drawRect,我只是在这里尝试弄清楚我需要做什么。它现在在它自己的位置,并且仅在玩家实际移动时才被调用。

这是新代码:

- (void)keepViewCentered
{
    NSPoint pl = [player_ location];
    NSPoint ll;
    NSPoint location = [self bounds].origin;
    ll.x = location.x / 20;
    ll.y = location.y / 20;
    for ( pl.y = [player_ location].y; pl.y >= ll.y + 15 && ll.y + 30 < [currentMap_ height]; ll.y++ )
    {
        location.y = ll.y * 20;
    }
    for ( pl.x = [player_ location].x; pl.x >= ll.x + 15 && ll.x + 30 < [currentMap_ width]; ll.x++ )
    {
        location.x = ll.x * 20;
    }
    for ( pl.y = [player_ location].y; pl.y <= ll.y + 15 && ll.y >= 0; ll.y-- )
    {
        location.y = ll.y * 20;
    }
    for ( pl.x = [player_ location].x; pl.x <= ll.x + 15 && ll.x >= 0; ll.x-- )
    {
        location.x = ll.x * 20;
    }
    [self setBoundsOrigin: location];
}

这是它的图片!

图 1:这是 1,1 处的玩家。没什么特别的。 http://sneakyness.com/stackoverflow/SRLbounds1.png

图 2:3 个金块表示在视图的 bounds.origin 移动到保持在玩家中心之前玩家可以移动多远。尽管无关紧要,但请注意玩家实际上看不到黄金。事实证明,编程视野是一个备受争议的领域,您可以使用几种不同的算法,它们都没有缺点,或者已被移植到 Objective-C。目前它只是一个正方形。看穿墙壁和一切。 http://sneakyness.com/stackoverflow/SRLbounds2.png

图 3:具有不同 bounds.origin 的视图,以玩家为中心。 http://sneakyness.com/stackoverflow/SRLbounds3.png

4

3 回答 3

1

我不清楚你想在这里做什么,但它非常非常低效。你在setBoundsOrigin:重复调用,这意味着只有最后一个调用实际上在做任何事情。将原点设置在中间drawRect:不会导致任何移动。drawRect:如果您将其视为动画,则整个运行会绘制一个“帧”。

请记住,您不负责绘图循环。drawRect:当框架决定需要绘图时被调用。您可以向框架提供各种提示(例如setNeedsDisplay:),但最终是框架在需要某些东西时给您打电话。

如果您的意图是动画,则需要阅读Core Animation Programming Guide。它将讨论管理动画的非常简单有效的方法。在屏幕周围制作动画是 Cocoa 的一大优势,相当复杂的事情可以很容易地完成。

于 2009-07-23T23:17:05.217 回答
1

它现在在它自己的位置,并且仅在玩家实际移动时才被调用。

耶!

我只是问是否有比使用 4 更好for的方法。

这是我的建议:

  1. 将左下角设置为玩家的位置负 15。
    ll.x = [玩家位置].x - 15.0;
    ll.y = [玩家位置].y - 15.0;
  2. 确保它不超出视图的边界。
    如果 (ll.x < 0.0)
        ll.x = 0.0;
    如果 (ll.y < 0.0)
        ll.y = 0.0;
    if (ll.x > [currentMap_width] - 30.0)
        ll.x = [currentMap_width] - 30.0;
    if (ll.y > [currentMap_ height] - 30.0)
        ll.y = [currentMap_ height] - 30.0;
  3. 乘以您的图块大小并设置为新的边界原点。位置.x = ll.x * 20.0; 位置.y = ll.y * 20.0; [self setBoundsOrigin: 位置];

我还建议您不要对图块大小和玩家视线范围进行硬编码。

对于瓦片大小,您可能更愿意为您的视图提供几个属性,以瓦片表示宽度和高度,然后使用 CTM 缩放到(widthInPoints / widthInTiles), (heightInPoints / heightInTiles). 然后你可以让用户调整你的窗口大小来改变瓷砖的大小。

对于玩家的视野范围(目前为 30 格正方形),您可能希望将其设为玩家的属性,以便它可以随着技能统计、装备的物品以及药水、怪物攻击和众神之怒的效果而变化. 一个警告:如果玩家的视线范围可能变得比游戏窗口适合的范围更长(尤其是垂直方向),您需要在上面的代码中添加一个检查,并通过将玩家置于死点并可能缩放来处理它出去。

于 2009-07-24T16:27:33.267 回答
0

在某些情况下……最好分开做,而不是全部一起做……</p>

是的。有一个drawBackgroundTile:方法,也许是一个drawItem:方法和一个drawPlayer:方法,并在其中循环调用它们drawRect:——这应该为关卡绘制整个板。这就是非基于层的解决方案。

正如我在对 Rob 答案的评论中指出的那样,另一个是使用核心动画。然后,您将drawRect:完全取消,并让您的视图托管一个根层,该层将包含平铺层,其中一些将包含项目和演员(玩家/怪物/宠物)层。

这是为什么?

因为它是一个合适的、高效的、可读的解决方案。

于 2009-07-24T01:00:13.293 回答