gpt4 book ai didi

ios - 在 SpriteKit 中缩放和滚动 SKNode

转载 作者:技术小花猫 更新时间:2023-10-29 10:36:36 26 4
gpt4 key购买 nike

我正在 SpriteKit 上开发类似 Scrabble 的游戏,并且一直坚持缩放和滚动拼字板。首先让我解释一下游戏背后的工作:在我的 GameScene 上我有:

  • 一个名为 GameBoard Layer(名为 NAME_GAME_BOARD_LAYER)的 SKNode 子类包含以下子类:

    A SKNode subclass for Scrabble Board named NAME_BOARD.
    A SKNode subclass for Letters Tile Rack named NAME_RACK.

    字母拼 block 是从拼 block 架上挑选出来的,并掉落在拼字游戏板上。

这里的问题是,我需要模仿可以通过 UIScrollView 实现的缩放和滚动,我认为不能将其添加到 SKNode 上。我需要模仿的特征是:

  • 放大用户双击的精确位置
  • 四处滚动(尝试过 PanGestures,不知何故会造成拖放图 block 的问题)
  • 将缩放后的 SKNode 保持在特定区域(就像 UIScrollView 将缩放后的内容保持在 scrollView 边界内)

这是我使用 UITapGestures 进行缩放的代码:

在我的 GameScene.m 中

- (void)didMoveToView:(SKView *)view {
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleTapGesture:)];
tapGesture.numberOfTapsRequired = 2;
tapGesture.numberOfTouchesRequired = 1;
[self.scene.view addGestureRecognizer:tapGesture];
}

- (void)handleTapGesture:(UITapGestureRecognizer*)recognizer {
if ([self childNodeWithName:NAME_GAME_BOARD_LAYER]) {
GameBoardLayer *gameBoardLayer = (GameBoardLayer*)[self childNodeWithName:NAME_GAME_BOARD_LAYER];

SKNode *node = [Utils nodeAt:[recognizer locationInView:self.view]
withName:NAME_BOARD
inCurrentNode:gameBoardLayer];

if ([node.name isEqualToString:NAME_BOARD]) {
[gameBoardLayer handleDoubleTap:recognizer];
}

}
}

在我的 GameBoardLayer 节点中:

- (void)handleDoubleTap:(UITapGestureRecognizer*)recognizer {
Board *board = (Board*)[self childNodeWithName:NAME_BOARD];
if (isBoardZoomed)
{
[board runAction:[SKAction scaleTo:1.0f duration:0.25f]];
isBoardZoomed = NO;
}
else
{
isBoardZoomed = YES;
[board runAction:[SKAction scaleTo:1.5f duration:0.25f]];
}
}

有人可以指导我如何实现此功能吗?

谢谢大家

最佳答案

我会这样做:

设置:

  • 创建一个 GameScene 作为游戏的根节点。 (SKScene 的 child )
  • 将 BoardNode 作为子节点添加到场景中(SKNode 的子节点)
  • 将 CameraNode 作为子节点添加到 Board(SKNode 的子节点)
  • 将 LetterNode 添加为 Board 的子节点

保持相机节点居中:

// GameScene.m
- (void) didSimulatePhysics
{
[super didSimulatePhysics];
[self centerOnNode:self.Board.Camera];
}

- (void) centerOnNode:(SKNode*)node
{
CGPoint posInScene = [node.scene convertPoint:node.position fromNode:node.parent];
node.parent.position = CGPointMake(node.parent.position.x - posInScene.x, node.parent.position.y - posInScene.y);
}

通过移动 BoardNode 来平移 View (记住要防止平移越界)

// GameScene.m
- (void) handlePan:(UIPanGestureRecognizer *)pan
{
if (pan.state == UIGestureRecognizerStateChanged)
{
[self.Board.Camera moveCamera:CGVectorMake([pan translationInView:pan.view].x, [pan translationInView:pan.view].y)];
}
}

// CameraNode.m
- (void) moveCamera:(CGVector)direction
{
self.direction = direction;
}

- (void) update:(CFTimeInterval)dt
{
if (ABS(self.direction.dx) > 0 || ABS(self.direction.dy) > 0)
{
float dx = self.direction.dx - self.direction.dx/20;
float dy = self.direction.dy - self.direction.dy/20;
if (ABS(dx) < 1.0f && ABS(dy) < 1.0f)
{
dx = 0.0;
dy = 0.0;
}
self.direction = CGVectorMake(dx, dy);
self.Board.position = CGPointMake(self.position.x - self.direction.dx, self.position.y + self.direction.dy);
}
}

// BoardNode.m
- (void) setPosition:(CGPoint)position
{
CGRect bounds = CGRectMake(-boardSize.width/2, -boardSize.height/2, boardSize.width, boardSize.height);

self.position = CGPointMake(
MAX(bounds.origin.x, MIN(bounds.origin.x + bounds.size.width, position.x)),
MAX(bounds.origin.y, MIN(bounds.origin.y + bounds.size.height, position.y)));
}

通过设置 GameScene 的大小来缩放:

// GameScene.m
- (void) didMoveToView:(SKView*)view
{
self.scaleMode = SKSceneScaleModeAspectFill;
}

- (void) handlePinch:(UIPinchGestureRecognizer *)pinch
{
switch (pinch.state)
{
case UIGestureRecognizerStateBegan:
{
self.origPoint = [self GetGesture:pinch LocationInNode:self.Board];
self.lastScale = pinch.scale;
} break;

case UIGestureRecognizerStateChanged:
{
CGPoint pinchPoint = [self GetGesture:pinch LocationInNode:self.Board];
float scale = 1 - (self.lastScale - pinch.scale);

float newWidth = MAX(kMinSceneWidth, MIN(kMaxSceneWidth, self.size.width / scale));
float newHeight = MAX(kMinSceneHeight, MIN(kMaxSceneHeight, self.size.height / scale));

[self.gameScene setSize:CGSizeMake(newWidth, newHeight)];
self.lastScale = pinch.scale;

} break;

default: break;
}
}

平移意外拖动 LetterNodes 的问题是什么,我通常实现一个注册所有触摸的 TouchDispatcher(通常在 GameScene 类中)。 TouchDispatcher 然后决定哪个节点应该响应触摸(以及以什么顺序)。

关于ios - 在 SpriteKit 中缩放和滚动 SKNode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21847063/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com