Как замостить текстуру узла спрайта?

Используя SpriteKit, как мне разместить SKTexture, которая повторяется по горизонтали, чтобы заполнить ширину SKSpriteNode? Это то, что у меня пока есть - только растягивает текстуру.

var header = SKSpriteNode()
let headerTexture = SKTexture(imageNamed: "inGameHeader-1.png")
header = SKSpriteNode(texture: headerTexture)
header.position = CGPoint(x: 0, y: CGRectGetMaxY(self.frame)-39)
header.size.width = CGRectGetWidth(self.frame)
header.size.height = 150
header.anchorPoint = CGPoint(x: 0,y: 1)
addChild(header)

person Chris    schedule 06.02.2015    source источник
comment
Я думаю, что в настоящее время нет простого способа замостить текстуру, но вы можете сгенерировать много спрайтов за один проход рисования. Что дает вам аналогичный результат...   -  person Whirlwind    schedule 06.02.2015
comment
хм, а как мне это сделать? Все, что мне действительно нужно сделать, это повторить градиент шириной 1 пиксель, чтобы заполнить фон заголовка. Я просто подумал, что это будет более эффективно, чем градиент шириной 600 пикселей, который повторяет только 1 пиксель.   -  person Chris    schedule 06.02.2015
comment
Как я уже сказал, в настоящее время нет простого способа сделать это, но вам не нужно об этом беспокоиться, у Spritekit есть способ оптимизировать вещи: developer.apple.com/library/ios/documentation/GraphicsAnimation/   -  person Whirlwind    schedule 06.02.2015


Ответы (3)


Вот мое решение: отправьте изображение этой функции с размером спрайта, за которым следует размер плитки. Это вернет мозаичную SKTexture.

-(SKTexture *)tiledTextureImage:(UIImage *)image ForSize:(CGSize)size tileSize:(CGSize)tileSize{

// First we create a new size based on the longest side of your rect
int targetDimension = (int)fmax(size.width,size.height);
CGSize targetSize = CGSizeMake(targetDimension, targetDimension);

// Create a CGImage from the input image and start a new image context.
struct CGImage *targetRef = image.CGImage;
UIGraphicsBeginImageContext(targetSize);
CGContextRef contextRef = UIGraphicsGetCurrentContext();

// Now we simply draw a tiled image
CGContextDrawTiledImage(contextRef, CGRectMake(0,0, tileSize.width,tileSize.height), targetRef);
UIImage *tiledTexture = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

// Finally create a texture and return it. 
return  [SKTexture textureWithImage:tiledTexture];
}
person Wharbio    schedule 31.08.2016
comment
спасибо, работает нормально, но одна проблема заключается в том, что вы заставляете targetSize быть квадратом на основе максимальной высоты или ширины. в то время как он заполняет спрайт, он на самом деле «заполняет его, оставляя лишние плитки за пределами экрана». мне не нужен был этот дополнительный багаж, поэтому я удалил первые 2 строки и использовал размер, который я передал, вместо targetSize. - person neoscribe; 27.11.2020

вы знаете, что можете сделать это в UIButton или UIImageView с помощью resizableImageWithCapInsets, поэтому вот мое решение:

-(SKTexture *)textureWithImage:(UIImage *)image tiledForSize:(CGSize)size withCapInsets:(UIEdgeInsets)capInsets{
//get resizable image
image =  [image resizableImageWithCapInsets:capInsets];
//redraw image to target size
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
[image drawInRect:CGRectMake(0, 0, size.width-1, size.height-1)];
[[UIColor clearColor] setFill];
//get target image
UIImage *ResultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// get texture
SKTexture * texture = [SKTexture textureWithImage:ResultImage];
return texture;
}
person 薛永伟    schedule 28.07.2017
comment
Этот метод эффективен - person 薛永伟; 19.05.2018

Вот статическая функция для Swift 3 и 4. Без использования расширения, поскольку класс SKTexture фактически не имеет назначенного инициализатора.

Обратите внимание, что это будет не очень эффективно. Лучше предварительно загрузить текстуру перед использованием или погрузиться в мир пользовательских шейдеров.

static func generateTiledTexture(size: CGSize, imageNamed imageName: String) -> SKTexture? {
    var texture: SKTexture?

    UIGraphicsBeginImageContext(size)
    let context = UIGraphicsGetCurrentContext()

    if let image = UIImage(named: imageName), let cgImage = image.cgImage {
        context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height), byTiling: true)

        if let tiledImage = UIGraphicsGetImageFromCurrentImageContext() {
            texture = SKTexture(image: tiledImage)
        }
    }

    UIGraphicsEndImageContext()

    return texture
}
person mm282    schedule 04.09.2017