sprite-kit - spritekit - skview
Kit de Sprite y colorWithPatternImage (2)
¿Tenemos alguna manera de repetir una imagen en un área, como un SKSpriteNode? SKColor colorWithPatternImage
no funciona desafortunadamente.
Editar:
Hice las siguientes categorías, parece funcionar hasta ahora. Usando Mac, no probado en iOS. Es probable que necesite algo de reparación para iOS.
// Add to SKSpriteNode category or something.
+(SKSpriteNode*)patternWithImage:(NSImage*)image size:(const CGSize)SIZE;
// Add to SKTexture category or something.
+(SKTexture*)patternWithSize:(const CGSize)SIZE image:(NSImage*)image;
Y las implementaciones. Poner en archivos respectivos.
+(SKSpriteNode*)patternWithImage:(NSImage*)imagePattern size:(const CGSize)SIZE {
SKTexture* texturePattern = [SKTexture patternWithSize:SIZE image:imagePattern];
SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:texturePattern];
return sprite;
}
+(SKTexture*)patternWithSize:(const CGSize)SIZE image:(NSImage*)image {
// Hopefully this function would be platform independent one day.
SKColor* colorPattern = [SKColor colorWithPatternImage:image];
// Correct way to find scale?
DLog(@"backingScaleFactor: %f", [[NSScreen mainScreen] backingScaleFactor]);
const CGFloat SCALE = [[NSScreen mainScreen] backingScaleFactor];
const size_t WIDTH_PIXELS = SIZE.width * SCALE;
const size_t HEIGHT_PIXELS = SIZE.height * SCALE;
CGContextRef cgcontextref = MyCreateBitmapContext(WIDTH_PIXELS, HEIGHT_PIXELS);
NSAssert(cgcontextref != NULL, @"Failed creating context!");
// CGBitmapContextCreate(
// NULL, // let the OS handle the memory
// WIDTH_PIXELS,
// HEIGHT_PIXELS,
CALayer* layer = CALayer.layer;
layer.frame = CGRectMake(0, 0, SIZE.width, SIZE.height);
layer.backgroundColor = colorPattern.CGColor;
[layer renderInContext:cgcontextref];
CGImageRef imageref = CGBitmapContextCreateImage(cgcontextref);
SKTexture* texture1 = [SKTexture textureWithCGImage:imageref];
DLog(@"size of pattern texture: %@", NSStringFromSize(texture1.size));
CGImageRelease(imageref);
CGContextRelease(cgcontextref);
return texture1;
}
Ok esto también es necesario. Esto probablemente solo funciona en Mac.
CGContextRef MyCreateBitmapContext(const size_t pixelsWide, const size_t pixelsHigh) {
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
//int bitmapByteCount;
size_t bitmapBytesPerRow;
bitmapBytesPerRow = (pixelsWide * 4);// 1
//bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);// 2
bitmapData = NULL;
#define kBitmapInfo kCGImageAlphaPremultipliedLast
//#define kBitmapInfo kCGImageAlphaPremultipliedFirst
//#define kBitmapInfo kCGImageAlphaNoneSkipFirst
// According to http://stackoverflow.com/a/18921840/129202 it should be safe to just cast
CGBitmapInfo bitmapinfo = (CGBitmapInfo)kBitmapInfo; //kCGImageAlphaNoneSkipFirst; //0; //kCGBitmapAlphaInfoMask; //kCGImageAlphaNone; //kCGImageAlphaNoneSkipFirst;
context = CGBitmapContextCreate (bitmapData,// 4
pixelsWide,
pixelsHigh,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
bitmapinfo
);
if (context== NULL)
{
free (bitmapData);// 5
fprintf (stderr, "Context not created!");
return NULL;
}
CGColorSpaceRelease( colorSpace );// 6
return context;// 7
}
Código de trabajo de iOS:
CGRect textureSize = CGRectMake(0, 0, 488, 650);
CGImageRef backgroundCGImage = [UIImage imageNamed:@"background.png"].CGImage;
UIGraphicsBeginImageContext(self.level.worldSize); // use WithOptions to set scale for retina display
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawTiledImage(context, textureSize, backgroundCGImage);
UIImage *tiledBackground = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
SKTexture *backgroundTexture = [SKTexture textureWithCGImage:tiledBackground.CGImage];
SKSpriteNode *backgroundNode = [SKSpriteNode spriteNodeWithTexture:backgroundTexture];
[self addChild:backgroundNode];
Sí, es posible implementar eso con una llamada a CGContextDrawTiledImage (), pero eso desperdicia mucha memoria para nodos de tamaño mediano y grande. Se proporciona un enfoque significativamente mejorado en spritekit_repeat_shader . Esta publicación de blog proporciona un ejemplo de código GLSL y se proporciona una fuente con licencia BSD.