Spritekit - не загрузка @3x изображений из SKTextureAtlas
Поскольку мой образец проекта был удален (я думал, что это будет намного легче протестировать), я отправлю код и изображения, чтобы проиллюстрировать мою точку.
Вот примеры изображений
![2x image]()
![my 3x image]()
Настройка моего атласа:
![enter image description here]()
Моя настройка образа запуска:
![enter image description here]()
Код, в который я добавляю эти спрайты в свою сцену
override func didMoveToView(view: SKView) {
let texture = SKTextureAtlas(named: "scenery")
let test = SKSpriteNode(texture: texture.textureNamed("test"))
test.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
self.addChild(test)
}
Это мои результаты:
Симулятор iPhone 5:
![enter image description here]()
iPhone 6 плюс симулятор:
![enter image description here]()
Я попытался изменить образ запуска, чтобы использовать каталог активов. Тогда iPhone 6 plus, по-видимому, увеличивает масштаб экрана 2x. Он по-прежнему загружает изображение 2x, но масштабирует его.
Мне нужно, чтобы он загрузил мое 3-кратное изображение и масштабировался с моим 2x-изображением.
Ответ Габуха ниже указал мне в правильном направлении. Работает над новым проектом. Однако, если я использую его решение для моего реального проекта SpriteKit, мои 3х-изображения не будут уменьшаться. Они в 3 раза больше, чем они должны быть.
Ответы
Ответ 1
Кажется, ошибка, когда Xcode генерирует скомпилированный атлас. Если вы проверите внутри пакета скомпилированного приложения, вы увидите, что Xcode не создает правильные имена атласа для изображений @3x.
Мне удалось получить активы @3x, создав атласы с именем @3x и оставив изображение без суффикса.
И вы можете проверить UIScreen.mainscreen().scale
, чтобы определить имя атласа для использования. Проверьте имя атласа в прикрепленном изображении, а код внутри getTextureAtlas
![enter image description here]()
Ответ 2
Кажется, сейчас работает, если вы используете новый способ создания атласа. Важно то, что Deployment target
должно быть >= 9.0...
Выберите Assets.xcassets
и нажмите + знак, чтобы создать новый атлас спрайта:
![введите описание изображения здесь]()
Выберите опцию "Новый спрайт-атлас" и добавьте активы @2x и @3x:
![введите описание изображения здесь]()
Затем в коде выполните следующее:
let sprite = SKSpriteNode(texture: SKTextureAtlas(named: "Sprites").textureNamed("test"))
sprite.position = CGPoint(x: frame.midX, y: frame.midY)
addChild(sprite)
Подсказка:
Если вы тестируете на Simulator, reset содержание и настройки симулятора, чтобы очистить кеш, прежде чем пытаться это сделать.
Ответ 3
Xcode 6.2 теперь загружает @3x и @2x изображения из одного атласа. Он загружает размер 1x (и, по-видимому, сам изменяет размер изображения), если вы не ставите @2x/@3x в конце имени изображения.
Ответ 4
Не знаю, почему это никогда не было сделано, но вот начало обходного пути, которое действительно правильно, но, к сожалению, немного медленнее. Возможно, кто-то может увидеть некоторые вещи, чтобы ускорить процесс.
import Foundation
import SpriteKit
public class Atlas: SKTextureAtlas
{
var textures = [String:(texture:SKTexture,image:UIImage)]();
public convenience init(named name: String)
{
self.init()
let scale = CGFloat(UIScreen().scale);
let path = "\(name).atlasc/\(name)";
let atlasContent = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource(path, ofType: "plist")!);
let content = atlasContent!["images"] as! [[String:AnyObject]];
let info = content[Int(scale) - 1] ;
let imagepath = "\(name).atlasc/\((info["path"] as! String!).stringByReplacingOccurrencesOfString(".png", withString: ""))";
let imgDataProvider = CGDataProviderCreateWithCFData(NSData(contentsOfFile: NSBundle.mainBundle().pathForResource(imagepath, ofType: "png")!));
let cgimage = CGImageCreateWithPNGDataProvider(imgDataProvider, nil, true, .RenderingIntentDefault);
let subimages = info["subimages"] as! [[String:AnyObject]];
for subimage in subimages
{
let spriteSourceSize = CGSizeFromString(subimage["spriteSourceSize"] as! String);
let size = CGSizeApplyAffineTransform(spriteSourceSize, CGAffineTransformMakeScale(1/scale,1/scale));
let isFullyOpaque = subimage["isFullyOpaque"] as! Bool;
let spriteOffset = CGPointFromString((subimage["spriteOffset"] as! String));
let textureRect = CGRectFromString((subimage["textureRect"] as! String));
let textureRectSize = CGSizeApplyAffineTransform(textureRect.size, CGAffineTransformMakeScale(1/scale,1/scale));
let name = (subimage["name"] as! String).stringByReplacingOccurrencesOfString("@3x.png", withString: "");
let textureRotated = subimage["textureRotated"] as! Bool;
let smallImage = CGImageCreateWithImageInRect(cgimage, textureRect);
UIGraphicsBeginImageContextWithOptions(size, isFullyOpaque, scale);
let context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetShouldAntialias(context,false);
CGContextSetAllowsAntialiasing( context ,false);
CGContextSetInterpolationQuality(context , CGInterpolationQuality.None)
if(textureRotated)
{
CGContextTranslateCTM(context, (size.width)/2, (size.height)/2);
CGContextScaleCTM(context, 1, -1);
CGContextRotateCTM(context,CGFloat(M_PI_2));
CGContextTranslateCTM(context, 0, ((size.height - textureRectSize.height)));
CGContextTranslateCTM(context, -((size.height)/2), -((size.width)/2));
CGContextTranslateCTM(context, spriteOffset.y/scale, -spriteOffset.x/scale);
}
else
{
//Set to center of image to flip correctly
CGContextTranslateCTM(context, (size.width)/2, (size.height)/2);
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, -((size.width)/2), -((size.height)/2));
CGContextTranslateCTM(context, spriteOffset.x/scale, spriteOffset.y/scale);
}
CGContextDrawImage(context,CGRect(origin: CGPoint.zero,size: textureRectSize), smallImage);
let image = UIGraphicsGetImageFromCurrentImageContext();
let texture = SKTexture(image: image);
textures[name] = (texture:texture,image:image);
CGContextRestoreGState(context);
UIGraphicsEndImageContext();
}
}
override public func textureNamed(name: String) -> SKTexture {
return textures[name]!.texture;
}
public func imageNamed(name: String) -> UIImage {
return textures[name]!.image;
}
}
Ответ 5
Эта ошибка еще не решена. Используя только изображения @2x, изображение приложения нарушается. Вместо этого выберите правильное изображение, посмотрев масштаб экрана.
textureName = [UIScreen mainScreen].scale > 2.9 ? @"[email protected]" : @"awesome";