【问题标题】:Detect click/touch on isometric texture检测等距纹理上的点击/触摸
【发布时间】:2014-03-22 14:02:28
【问题描述】:

我很难在一个简单的等距 Sprite Kit 游戏中实现点击处理。

我有一个包含多个 Tile 对象 (SKSpriteNode) 的地图 (SKNode) 的游戏场景 (SKScene)。

这是地图的截图:

我希望能够检测到用户点击的磁贴,所以我在磁贴对象上实现了 mouseDown。这是我在 Tile.m 中的 mouseDown :

-(void)mouseDown:(NSEvent *)theEvent
{
    [self setColorBlendFactor:0.5];
}

代码似乎工作正常,但有一个小故障:节点重叠并且在节点的透明部分检测到点击事件。示例(添加的矩形仅用于说明问题。逻辑中未使用它们):

如您所见,如果我点击图块 7 的左上角,图块 8 就会变成透明的。

我尝试了一些方法,比如在点击位置获取所有节点并检查点击是否在 CGPath 内但没有成功(我认为坐标有问题)。

所以我的问题是如何只检测纹理而不是透明部分的点击?或者我对问题的处理方法是错误的?

任何建议将不胜感激。

编辑:任何对我最终使用的解决方案感兴趣的人,请参阅my answer here

【问题讨论】:

    标签: sprite-kit isometric


    【解决方案1】:

    “现在”我对此类问题的解决方案是:

    • 在您的场景中获取位于您点击该位置的所有节点,即

      [myScene nodesAtPoint:[theEvent lactionInNode:myScene]]
      
    • 不要忘记检查您是否没有单击场景的根目录 类似的东西:

      if (![[myScene nodeAtPoint:[theEvent locationInNode:myScene]].name isEqual: @"MyScene"])
      

      然后遍历可能的节点数组并检查Texture (NOT myNode.alpha)的alpha

    • 如果 alpha 为 0.0f,则转到数组的下一个节点
    • 选择第一个 alpha 不是 0.0f 的节点并返回节点名称
    • 这样您可以(首先)找到您的节点并将其保存为您需要的节点,然后终止您不再需要的数组
    • 比用你的节点做你想做的事
    • 顺便说一句,在搜索其名称后检查您希望使用的新节点是否为 nil。如果那是真的,只需打破你的 moveDown 方法

    要获得 Alpha 版,请尝试 this

    我的看起来像这样:

    -(void)mouseDown:(NSEvent *)theEvent {
         /* Called when a mouse click occurs */
        if (![[self nodeAtPoint:[theEvent locationInNode:self]].name isEqual: self.name]]) {
    
            /* find the node you clicked */
            NSArray *clickedNodes = [self nodesAtPoint:[theEvent locationInNode:self]];
    
            SKNode *clickedNode = [self childNodeWithName:[clickedNodes getClickedCellNode]];
    
            clickedNodes = nil;
    
            /* call the mouseDown method of your Node you clicked to to node specific actions */
            if(clickedNode) {
               [clickedNode mouseDown:theEvent];
            }
            /* kill the pointer to your clicked node */
            clickedNode = nil;
        }
    }
    

    【讨论】:

    • 不幸的是,此解决方案不适用于 sprite kit 地图集,因为似乎无法从纹理地图集中获取图像:/ 但适用于“经典”图像。谢谢!
    【解决方案2】:

    对于像您这样的简单几何图形,一种解决方法是将不可见的 SKShapeNode 叠加在您的钻石上,并注意它们的接触(而不是 skspritenode 的接触)。

    如果这仍然不起作用,请确保使用“fromPolygon:myNode.path!”创建 SKPhysicsBody。选项...

    【讨论】:

      【解决方案3】:

      我对错误[SKPhysicsWorld enumerateBodiesAtPoint] 有一些问题。 但我找到了我的解决方案,它也对你有用。

      1. 创建平铺路径(您的路径 4 点)

      2. 捕捉触摸并将点转换为您的图块节点

      3. 如果触摸点在形状节点内 - 获胜!

      代码:

      - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
      
      selectedBuilding = nil;
      
      NSArray *nodes = [farmWorldNode nodesAtPoint:point];
      if (!nodes ||  nodes.count == 0 || nodes.count == 1) {
          return;
      }
      
      NSMutableArray *buildingsArray = [NSMutableArray array];
      
      int count = (int)nodes.count;
      for (int i = 0; i < count; i++) {
      
          SKNode *findedBuilding = [nodes objectAtIndex:i];
      
          if ([findedBuilding isKindOfClass:[FBuildingBaseNode class]]) {
              FBuildingBaseNode *building = (FBuildingBaseNode *)findedBuilding;
      
              CGPoint pointInsideBuilding = [building convertPoint:point fromNode:farmWorldNode];
      
              if ([building.colisionBaseNode containsPoint:pointInsideBuilding]) {
                  NSLog(@"\n\n Building %@ \n\n ARRAY: %@ \n\n\n", building, findedBuilding);
                  [buildingsArray addObject:building];
              }
      
      
          }
       }
      
       selectedBuilding = (FBuildingBaseNode *)[buildingsArray lastObject];
      
      
       buildingsArray = nil;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-03-06
        • 1970-01-01
        • 2013-11-05
        • 2016-09-13
        • 1970-01-01
        • 2017-05-14
        相关资源
        最近更新 更多