已解决:在瓷砖地图中移动角色时锚控制按钮?
Posted
技术标签:
【中文标题】已解决:在瓷砖地图中移动角色时锚控制按钮?【英文标题】:SOLVED: Anchor control button when moving the character in tile map? 【发布时间】:2020-05-25 02:36:22 【问题描述】:我正在开发一款游戏,其中角色将由一组 4 个按钮控制,就像在旧游戏机中一样。我在 spritekit 中使用 Tile Map 来创建地图。 一切正常(按下按钮时玩家正在移动,场景跟随玩家)除了我的 4 个按钮在角色移动时也会移动。直到 4 个按钮移出屏幕,我再也无法控制它了。 我们如何将 4 个按钮锚定到屏幕的右下角? 下面是我用来创建受控按钮的代码
func controlButton()
button = SKNode()
moveUpButton = SKSpriteNode(imageNamed: "moveup")
moveUpButton.alpha = 1
moveUpButton.setScale(1.5)
moveUpButton.position = CGPoint(x: 400 - self.frame.size.width/2, y: 0 - self.frame.size.height/2)
moveUpButton.zPosition = 2
moveLeftButton = SKSpriteNode(imageNamed: "moveleft")
...
moveRightButton = SKSpriteNode(imageNamed: "moveright")
...
moveDownButton = SKSpriteNode(imageNamed: "movedown")
...
button.addChild(moveUpButton)
button.addChild(moveLeftButton)
button.addChild(moveRightButton)
button.addChild(moveDownButton)
self.addChild(button)
这是我用来创建瓷砖贴图的代码,为包含墙的瓷砖添加带有物理主体的节点:
func setUpSceneWithMap(map: SKTileMapNode)
let tileMap = map
tileMap.setScale(1)
tileMap.position = CGPoint(x: 0 - self.frame.size.width/2, y: 0 - self.frame.size.height/2)
let tileSize = tileMap.tileSize
let halfWidth = CGFloat(tileMap.numberOfColumns) / 2.0 * tileSize.width
let halfHeight = CGFloat(tileMap.numberOfRows) / 2.0 * tileSize.height
for col in 0..<tileMap.numberOfColumns
for row in 0..<tileMap.numberOfRows
let tileDefinition = tileMap.tileDefinition(atColumn: col, row: row)
let isEdgeTile = tileDefinition?.userData?["isWalls"] as? Bool
if (isEdgeTile ?? false)
let x = CGFloat(col) * tileSize.width - halfWidth
let y = CGFloat(row) * tileSize.height - halfHeight
let rect = CGRect(x: 0, y: 0, width: tileSize.width, height: tileSize.height)
let tileNode = SKShapeNode(rect: rect)
tileNode.position = CGPoint(x: x, y: y)
tileNode.physicsBody = SKPhysicsBody.init(rectangleOf: tileSize, center: CGPoint(x: tileSize.width / 2.0, y: tileSize.height / 2.0))
tileNode.physicsBody?.categoryBitMask = gamePhysics.Wall
tileNode.physicsBody?.collisionBitMask = gamePhysics.Player
tileNode.physicsBody?.contactTestBitMask = gamePhysics.Player
tileNode.physicsBody?.isDynamic = false
tileMap.addChild(tileNode)
下面也是我将地图添加到场景的代码:
func createScene()
self.physicsWorld.contactDelegate = self
for node in self.children
if (node is SKTileMapNode)
if let theMap:SKTileMapNode = node as? SKTileMapNode
setUpSceneWithMap(map: theMap)
createPlayer()
createCamera()
【问题讨论】:
好吧,基本上,SpriteKit 符合父子结构。每个节点都是您附加到的节点的子节点。您应该在非常尖的顶部有一个通用节点。将场景的另一个节点和 UI 的单独节点附加到该父节点。仅将 UI 元素附加到该 UI 节点。场景元素(IE 角色、世界等)应附加到世界节点。只需移动世界节点而不是通用节点就可以了。 所以现在我在 GameScene 类的正下方定义 SKSpriteNode。应该已经是世界节点了吧? 默认情况下,SKScene 是***节点。您需要再添加两个 SKNode 并将它们附加到 SKScene。不要将任何东西附加到您的 SKScene。像这样定义另外两个节点:let WorldNode, UINode = SKNode;
然后在下一行(或任何你想要的地方)做self.addchild(WorldNode); self.addChild(UINode);
然后你想做UINode.addChild(button);
而不是self.addChild(button);
对于这里的新手,我深表歉意,但我已经将“按钮”声明为 SKNode,其中包含 4 个子节点“moveup”、“movedown”、“moveright”、“moveleft”精灵节点。所以我的“按钮”SKNode 应该和 UINode 一样工作。对于 WorldNode,它的子节点是什么?能给我一些示例代码吗?
我会写一个答案,以便更好地解释。
【参考方案1】:
基本上,SpriteKit 订阅一个子父节点结构。
让我用一张图片来说明。
每个圆圈代表一个节点。目前,您正在移动 SKScene 节点(自身)。子节点的位置相对于它所连接的父节点。当您移动 SKScene 节点时,连接到它的所有节点都遵循套件,因为它们是子节点。
例如,将一个节点定位在 (0,0),然后将一个节点附加到该节点的位置 (10,0)。将父节点移动到(10,0),(10,0)处的子节点会移动到(20,0),因为它的原点是相对于它的父节点,而不是一般场景。
要解决您的问题,您需要创建另一个级别的节点。让我用另一张图来说明。
如果您只对地图节点应用移动,那么只有子节点(附加到地图节点的节点)会移动。
总而言之,您的代码将如下所示。
class GameScene: SKScene
let MapNode,
UINode = SKNode; //This is a fancy way to declare multiple variables of the same type
func controlButton()
... //Your other code here
UINode.addChild(button) //Instead of self.addChild(button)
func setUpSceneWithMap(map: SKTileMapNode)
//Your other code in here
MapNode.addChild(map)
// I don't know where you are adding your tile map to your scene
// However, it most likely is self.addChild(map) which needs to be changed to MapNode.addChild(map)
将所有场景元素附加到 MapNode,并将所有 UI 元素附加到 UINode。仅对 MapNode 应用位置更改。 UI 元素不会移动,除非您希望它们移动。
【讨论】:
如果是这样,我们为什么要添加地图节点?我们可以只将移动应用到 TileMap 吗? 地图节点负责处理所有地图元素。如果您打算添加其他元素,例如动物、结构(我不知道您的游戏的性质),那么地图节点可以用来处理所有这些。假设所有地图元素都希望看起来“在地面上”,那么需要将相同的位置移动应用于所有地图元素。当您创建敌人或 NPC 类型的精灵时,一个简单的移动决策树可以处理地图节点内的移动。以上是关于已解决:在瓷砖地图中移动角色时锚控制按钮?的主要内容,如果未能解决你的问题,请参考以下文章
GL_DEPTH_COMPONENT 24 OZ 的等距平铺地图闪烁
在Unity中做一个2D游戏,放入了两个按钮: "<" 和" >",想问如何通过点击这两个按钮控制角色的左右移动