Кадр SKSpriteNode далеко

Я пытаюсь создать открытый круг из UIBezierPath и превратить его в SKShapeNode, который позже будет преобразован в SKSpriteNode.

У меня была проблема, когда я не мог понять, как уменьшить спрайт, пока ширина его линии не уменьшилась. Вы можете увидеть решение здесь: Изменить размер спрайта без сжатия содержимого

В итоге я исправил некоторые вещи и создал новый класс для реализации пользовательского SKShapeNode с этой функциональностью:

class ShrinkableShape: SKShapeNode {

let level: Int
let bezierPath: UIBezierPath
let scale: CGFloat
let finalLineWidth: CGFloat
let from: SKSpriteNode

let initialLineWidth = CGFloat(20)
let duration = 0.3

// level would be from 1 to 5 (it is in a for loop)
init(level: Int, from: SKSpriteNode) {
    self.level = level
    self.from = from

    // create the open circle  which is (43 * level) + 140
    bezierPath = UIBezierPath(arcCenter: CGPoint(x: 0, y: 0), radius: CGFloat(((43 * level) + 140)), startAngle: CGFloat(GLKMathDegreesToRadians(-50)), endAngle: CGFloat(M_PI * 2), clockwise: false)

    // calls static function in this class so it is more readable 
    scale = ShrinkableShape.scaleFrom(level: level) / ShrinkableShape.scaleFrom(level: level + 1)
    finalLineWidth = (initialLineWidth / scale)

    // inits shape and then sets it up to specific values
    super.init()
    setup()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func setup() {
    // set sprite to path, set color, set line width and rotate it 
    self.path = bezierPath.cgPath
    self.strokeColor = UIColor(red:0.98, green:0.99, blue:0.99, alpha:1.00)
    self.lineWidth = 20
    self.position = from.position

    // FOR DEBUG: you will see what this makes in the screenshot
    let color = SKShapeNode(rect: self.frame)
    color.fillColor = UIColor.red
    color.alpha = 0.2
    color.position = self.position
    self.addChild(color)
}

// Makes the radius from the value given (only 1...5) 183, 226, 269, etc
static func scaleFrom(level: Int) -> CGFloat {
    return (CGFloat((level * 43) + 140) * 2.0)
}

}

введите описание изображения здесь Если вы посмотрите на снимок экрана, вы заметите, что белый круг немного смещен по сравнению с тем, где он должен быть выровнен (серая полоса и путь белого круга должны быть друг на друге). Это происходит только тогда, когда я вызываю функцию масштабирования, показанную в решении (ссылка выше).

Я думаю, что это из-за того, что вся рама испорчена. Если вы видите, рамка очень неправильная (и эта же проблема была причиной прошлых проблем при преобразовании в текстуру, потому что рамка была не такой, какой должна быть)

Почему это происходит? Как это исправить? Есть ли способ вручную установить правильный кадр для SKShapeNode? Любые другие идеи о том, как я могу это сделать?

--Редактировать-- забыл упомянуть. Красная часть на картинке — это отладка, чтобы увидеть кадр SKShapeNode. Вы можете увидеть, как он создается в функции setup(). Но я включил это, чтобы показать, насколько далеко был кадр.


person ngngngn    schedule 21.10.2016    source источник
comment
Итак, белые дуги меньше, чем вы хотите?   -  person Confused    schedule 22.10.2016
comment
Нет, размеры дуг в порядке. Когда я масштабирую дуги, они не масштабируются до нужного размера, потому что рамка выключена. Вычисление масштаба показано в коде функции scaleFrom в классе, который я показал. Если бы у него был правильный кадр, он бы масштабировался до нужного мне положения.   -  person ngngngn    schedule 22.10.2016
comment
Мне очень трудно понять вашу проблему. Я смущен. Масштабирование правильное... но неправильное положение?   -  person Confused    schedule 22.10.2016
comment
Как получается, что серые линии находятся в правильном положении, а белые — нет?   -  person Confused    schedule 22.10.2016
comment
Хм, я неправильно сказал, извините. Итак, вы знаете, как можно использовать sprite.scale(0.5) и уменьшить масштаб наполовину? Ну, я пытаюсь использовать sprite.scale(x), чтобы масштабировать его до точной длины и ширины. Чтобы найти правильный масштаб, я делаю (level * 43 + 140) / ((level + 1) * 43) + 140, например, первый круг 183x183, а второй круг 226x226. Масштаб 183/226. Когда вы подключаете sprite.scale(183/226), он будет соответствовать точной длине и ширине, которые мне нужны. Но проблема в том, что это не так. Моя мысль о том, почему это не так, потому что кадр не того размера. Например, он больше 226x226.   -  person ngngngn    schedule 22.10.2016
comment
Моя первая проблема, с которой я связался, заключалась в том, что когда я использую sprite.scale(x), он уменьшает спрайт, но делает ширину линии тоньше. Так что, если бы я превратил 226x226 в 183x183. ширина линии будет равна 10, и каждый слой будет иметь разную ширину. Но я исправил эту проблему. Теперь проблема в том, что при использовании масштаба я не могу получить спрайт с определенной высотой и шириной кадра, которые я хочу.   -  person ngngngn    schedule 22.10.2016
comment
Я думаю, вы столкнулись с одной из (многих) фундаментальных проблем, связанных с тем, как был разработан и поддерживается SpriteKit. Я не верю, что кто-то творческий или с дизайнерским опытом участвует в артикуляции и принятии решений. Как следствие, рисование не только не продумано, но и ужасно надумано, а также имеет проблемы с производительностью. Название на банке говорит SpriteKit, и, кроме старых добрых растровых спрайтов, они действительно не думали ни о чем другом. В значительной степени все это представляет собой мешанину из плагиата идей из cocos2D, а не оплот творчества сам по себе.   -  person Confused    schedule 22.10.2016
comment
Таким образом, вам придется учитывать, что вам нужно будет обойти проблемы и особенности SpriteKit, потому что он просто никогда не был создан для обработки сложного или даже базового рисования. Тот факт, что вы не можете контролировать положение контура/штриха относительно линии, на которой вы рисуете, вероятно, является первым источником ваших проблем.   -  person Confused    schedule 22.10.2016
comment
Во ВСЕХ приложениях для векторного рисования вы можете расположить контур/штрих снаружи, по центру или внутри линии. Некоторые из лучших приложений для рисования допускают это и на открытых линиях. В SpriteKit нет такой опции, и это очень раздражает. CAShapeLayer также не имеет этой опции. Тем не менее, ваше позиционирование (в вашем уме и концепции), вероятно, основано на крае ширины контура, в то время как вы фактически рисуете с обеих сторон линии, по половине ширины вашего контура / штриха.   -  person Confused    schedule 22.10.2016


Ответы (1)


Я думаю, что часть вашей проблемы заключается в разнице между тем, где у вас есть ваши линии, и тем, где находятся края растрового изображения, в результате ширины штриха/контура, которая у вас есть «вокруг» этих линий.

Возможно, лучше всего описать визуально, где красный цвет — это то, что система воспринимает как размер спрайта, а желтый — это, возможно, то, о чем вы думаете. Я сильно преувеличил ширину линии, чтобы показать эффект/проблему, о которой я думаю.

введите описание изображения здесь

person Confused    schedule 22.10.2016
comment
Я думаю, что это тоже проблема, но как мне это исправить? - person ngngngn; 22.10.2016
comment
все еще есть эта проблема. Любые идеи? - person ngngngn; 25.10.2016
comment
Вы строите две фигуры. Одна из них — очень тонкая белая линия выше. Используйте это для позиционирования и всего остального, что вы делаете. Синяя линия, сделайте ее потомком очень тонкой линии. Затем он будет двигаться в соответствии с позициями, которые вы даете тонкой линии. - person Confused; 25.10.2016
comment
Хорошо, я сделал еще немного отладки. Настоящая проблема заключалась в размере GameScene, который у меня был. Когда я создал GameScene, я создал его с помощью GameScene.sks, и по какой-то причине у него были неправильные размеры, поэтому для iPhone он был примерно 700 на 400. Я удалил этот файл и установил для него размер границ ViewController. Теперь все работает отлично! Мне просто нужно изменить некоторые размеры, чтобы компенсировать новый размер. - person ngngngn; 26.10.2016