jjzjj

swift - SpriteKit tilemaps 与弯曲或倾斜的地砖碰撞

coder 2023-09-09 原文

我正在计划使用 SpriteKit 和 Swift 为 iOS 开发一款平台游戏。我研究了如何处理玩家 Sprite 的碰撞并偶然发现了这篇文章。

http://www.learn-cocos2d.com/2013/08/physics-engine-platformer-terrible-idea/

该文章建议您不要使用 SpriteKit 内置的物理引擎,而应自行实现移动、跳跃和碰撞处理等功能。 Ray Wenderlichs 网站上的平台教程提出了类似的方法。

到目前为止一切顺利,但让我们谈谈玩家可以站立的地砖。只要瓷砖是矩形的并且具有平坦的表面(就像在 Ray Wenderlich 的教程中那样),自定义物理实现就会很容易,因为您将使用 CGRectIntersectsRect 来检测碰撞。但是你如何检查弯曲或倾斜瓷砖上的玩家碰撞?据我所知,CGRectIntersectsRect 不考虑 Sprite 矩形内的透明像素。

http://i.stack.imgur.com/lRP2Q.png

例如,请看上面的图 block 。白色区域(左上角)将是透明的。现在,如果玩家 Sprite 掉落在这个瓷砖上,碰撞将在瓷砖矩形的上边界检测到,尽管那里没有地面像素(蓝色区域,右下角)。所以最终玩家会悬停在这个方 block 上方的半空中。我可以将玩家 Sprite 向下推几个像素,但这有点棘手,如果弯曲的地砖具有不同的倾斜角度,会变得更难。

所以问题是,我如何单独使用 SpriteKit 处理这些类型的碰撞(没有额外的框架,如 Cocos2D、Kobold Kit 等)?还是这种方法完全错误,平台游戏中与 SpriteKit 的碰撞应该从根本上不同?

非常感谢任何帮助!

最佳答案

我不同意不使用物理学来处理碰撞和接触。您实际上只是在尝试通过不使用物理学和实现您自己的自定义代码来重新发明轮子。

如果您使用的是 Tiled 应用程序,那么分配物理体是一项简单的任务。使用 Tiled 中的对象来分配各种 body 类型。在您的代码中,您可以着手为每个对象类型创建一个特定的主体。

例如:

在上图中,我创建了一个 45 度右侧倾斜的地板。我添加的对象称为 floor45R。

下一步是解析您的 map 对象。对于 45floorR,您可以像这样创建一个物理体:

NSArray *arrayObjects = [group objectsNamed:@"floor45R"];
    for (NSDictionary *dicObj in arrayObjects) {
        CGFloat x = [dicObj[@"x"] floatValue];
        CGFloat y = [dicObj[@"y"] floatValue];
        CGFloat w = [dicObj[@"width"] floatValue];
        CGFloat h = [dicObj[@"height"] floatValue];

        SKSpriteNode *myNode = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(w, h)];
        myNode.position = CGPointMake(x, y);
        myNode.zPosition = 100;
        CGMutablePathRef trianglePath = CGPathCreateMutable();
        CGPathMoveToPoint(trianglePath, nil, -myNode.size.width/2, myNode.size.height/2);
        CGPathAddLineToPoint(trianglePath, nil, myNode.size.width/2, -myNode.size.height/2);
        CGPathAddLineToPoint(trianglePath, nil, -myNode.size.width/2, -myNode.size.height/2);
        CGPathAddLineToPoint(trianglePath, nil, -myNode.size.width/2, myNode.size.height/2);
        myNode.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:trianglePath];
        myNode.physicsBody.dynamic = NO;
        myNode.physicsBody.restitution = 0;
        myNode.physicsBody.friction = 0.0;
        myNode.physicsBody.categoryBitMask = CategoryFloor45;
        myNode.physicsBody.collisionBitMask = 0x00000000;
        CGPathRelease(trianglePath);

        [worldNode addChild:myNode];
    }

这适用于任何程度的地板坡度。请记住将您的玩家和任何其他节点的碰撞位掩码设置为与地板碰撞。

为了让您的玩家在倾斜的地板上平稳移动,我建议将玩家的物理 body 分成两部分。底部为圆形,顶部为矩形。该圆圈将防止卡在由 2 个连接的物理体引起的任何潜在裂缝中。

SKPhysicsBody *firstBody = [SKPhysicsBody bodyWithCircleOfRadius:10 center:CGPointMake(0, 0)];
SKPhysicsBody *secondBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(5, 50) center:CGPointMake(0, 10)];
self.physicsBody = [SKPhysicsBody bodyWithBodies:@[firstBody, secondBody]];

您必须调整位置和中心坐标以匹配 Sprite 的图像。

关于swift - SpriteKit tilemaps 与弯曲或倾斜的地砖碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30211503/

有关swift - SpriteKit tilemaps 与弯曲或倾斜的地砖碰撞的更多相关文章

  1. 【unity学习笔记-如何给动态的人物添加碰撞体】 - 2

    如何给动态的人物添加碰撞体前景提要解决方法步骤步骤1步骤2步骤3步骤4步骤5顺便奉上检测3d物体的方法前景提要如题,项目中想实现和人物进行简单的互动,比如点击他的手臂的时候他会播放手臂的动作,点击脚的时候播放预设的和脚有关的动画之前我的实现方式是十分暴力的在人物模型中对应的部位添加一个子物体,给子物体添加正方体/圆体这种规则的碰撞体,然后因为他是在骨骼下的,所以人物在动的时候这个碰撞体也会跟着一起动,比绑在静态的mesh上灵活很多,不至于点击不相关的部位的时候也被静态的mesh检测到然后播放不相符的动画但是这么有很大的局限性,第一就是不精准,因为是规则的碰撞体,所以检测的范围就大了很多,第二就

  2. javascript - 检查某些 div 之间的碰撞 - 2

    如何检查某些div之间的碰撞?目前我正在使用getBoundingClientRect(),但它会检查每个div:if(this.getBoundingClientRect()){animateContinue=1;}我将如何去检查特定的?使用此for循环,我可以获得要检查的div的ID:for(varx=1;x 最佳答案 好吧,我最终使用了thisduplicate的修改版本.完成工作的函数是:varoverlaps=(function(){functiongetPositions(elem){varpos,width,heigh

  3. javascript - 如何检测由贝塞尔曲线制成的物体与圆之间的碰撞? - 2

    所以我写了一个微生物动画。这一切都很酷,但我认为,如果微生物能够吃掉硅藻并破坏气泡,那就更好了。问题在于微生物是由贝塞尔曲线构成的。我不知道如何以合理的方式检查由贝塞尔曲线构成的对象与圆之间的碰撞。我唯一想到的是在隐藏的Canvas上绘制微生物形状和气泡,然后检查它们是否绘制到相同的像素。但这会导致严重的性能问题恕我直言。代码:https://codepen.io/michaelKurowski/pen/opWeKYclassCell是单元格,而classCellWallNode是贝塞尔曲线的节点,以防有人需要查看实现。气泡和硅藻可以很容易地简化为圆形。 最

  4. javascript - 碰撞后如何在 Box2dWeb 中移除物体 - 2

    在Update函数内部,如果2个物体发生碰撞,我想将它们移除(或将它们标记为需要移除,并在时间步长结束时移除它们)。我将如何做到这一点?在更新函数中我尝试varbodyA=this.m_fixtureA.m_body;...bodyA.m_world.DestroyBody(bodyA);但是,它们不会被删除。似乎当我试图删除它们时,this.IsLocked()被设置为true。 最佳答案 如果world.IsLocked()函数返回true,世界将不会移除物体。world.IsLocked()将在世界处于一步时返回true。在步

  5. javascript - CSS Transform Math - 计算倾斜引起的div的高度 - 2

    我很难弄清楚如何计算由倾斜引起的div容器的额外高度。我正在屏蔽容器内的图像并使用plugin调整它的大小.容器不会始终具有相同的高度和宽度,因此使用固定尺寸是行不通的。请看我的demo.http://jsfiddle.net/RyU9W/6/HTMLCSS#profiles{margin-top:300px;transform:skewY(-30deg);-ms-transform:skewY(-30deg);/*IE9*/-webkit-transform:skewY(-30deg);/*SafariandChrome*/}.profile{cursor:pointer;float

  6. javascript - 使用 PIXI JS 更改弯曲文本中的字体大小 - 2

    是否有一种简单的方法可以更改PIXIJS弯曲文本中的字体大小?文本是通过newPIXI.mesh.Rope(pixiText.texture,points)创建的。使用调整大小按钮(检查下图),您可以更改对象的大小。我可以使用scale但它会降低质量。在基本文本对象中可以更改字体大小text.style.fontSize=newFontSize。 最佳答案 没有比更改字体大小更简单的方法了。这里的问题是通过Text对象生成的字母使用特殊机制,使其能够快速重新呈现。要创建网格,您需要纹理,它不能是Text或Graphics对象,因为它

  7. javascript - google maps api v3 - javascript - 透视/倾斜(不是卫星!)? - 2

    我知道这在Flash中是可能的:http://gmaps-samples-flash.googlecode.com/svn/trunk/examples/Map3DSimple.html透视控件..有人知道它何时或是否会在JSapi中可用吗? 最佳答案 答案是否定的。目前在GoogleMapsJavaScriptAPIV3中没有这样的控件。 关于javascript-googlemapsapiv3-javascript-透视/倾斜(不是卫星!)?,我们在StackOverflow上找到一

  8. javascript - 多个 Canvas 层的碰撞检测 - 2

    我正在努力弄清楚如何检测在不同Canvas层上绘制的Assets的碰撞。我制作了两个数组,其中包含我想要“碰撞”的东西,称为collidable_objects_layer1和collidable_objects_layer2。这些数组基本上绘制了Angular色不应该穿过的table和后面的墙。bar.js基本上包含您在下面的链接中看到的整个栏“场景”。main.js是让我的玩家移动的循环。我认为我的体系结构一团糟,因为我没有看到将这两者联系在一起的简单方法,所以对此有任何建议(这里需要模块还是它们只是在伤害我?)。现在的样子我不确定如何通过不同的碰撞测试添加更多“场景”。我假设碰撞

  9. javascript - d3j蛇弯曲路径动画 - 2

    我有兴趣尝试创建一个受控的弯曲路径。有没有办法绘制特定的坐标和样式来模仿这种设计。我把它想象成一种2DDonnieDarko时间隧道或slinkey/snake。更新1-旅程路径1http://jsfiddle.net/0ht35rpb/241/更新2-旅程2**我用stroke-linecap:round--http://jsfiddle.net/0ht35rpb/243/赋予了它更柔和的外观更新3-旅程3http://jsfiddle.net/0ht35rpb/245/^我已经开始创建多条路径线-好好组织一下,这样更容易制作/控制--本质上,旅程需要包括要通过的关键大门和拐Angu

  10. javascript - 带有碰撞检测的 jQuery 拖动 - 2

    我有以下HTML:Item1Item2Item3我希望使用jQuery能够做到的是:能够将.item从#list拖到#timeline.item可以根据需要多次放入时间线,例如。时间线中可能有4个项目#i1。.item在时间轴中不能相互重叠.item可以放置在时间轴上的任何位置,只要它们不与时间轴上的任何其他项目重叠所以我选择了jQueryUI的Draggable和Droppable,也选择了jQueryUIDraggableCollisionPlugin.这是我开始使用的jQuery:$('#list.item').draggable({helper:'clone',revert:'

随机推荐