I have an iOS app that uses sprite kit, and I am ready to add my artwork. The artwork is pixel-art and is inherently very small. I am trying to find the best way to display this in way where:

  1. All of the art is the same size, meaning that one image pixel takes up exactly the amount of real world pixels as in all the other images.

  2. There is no blurring in an attempt to make the textures look smoother, which often happens when scaling images up.

I have tried solving the second one like so:

self = [super init];
if(self){
    self.size=size;
    self.texture = [SKTexture textureWithImageNamed:@"ForestTree1.png"];
    self.texture.filteringMode = SKTextureFilteringNearest;

    [self.texture size];
}
return self; 

The above code is in the initialization of the SKSpriteNode which will have the texture.

This is my original image (scaled up for easy reference):

The problem is that my result always looks like this:

its blurry!!!!!

(The bottom of the trunk being offset is not part of this question.) I am not using any motion blur or anything like it. I'm not sure why it isn't displaying correctly.

Edit 1: I failed to mention above that the trees were constantly animating when the screenshots were taken. When they are still they look like this:

The image above is of two trees overlapping with one flipped caused because of a bug to be fixed later. My question is now how can I prevent the image from blurring while animation is occurring?

Edit 2:

I am adding multiple instances of the tree, each one loading the same texture. I know it as nothing to do with the animation because I changed the code to add just one tree and animate it, and it was pixelated perfectly.

有帮助吗?

解决方案 3

I've solved the problem...but its really a hack. I have a SKScene which is the parent node to all of the "trees" (SKSpriteNodes). This scene will be adding multiple trees to itself. At first I thought that this was some sort of problem because if I only added one tree, it would display the image correctly. The answer to this question led me to believe that I would need to programmatically create a SKTextureAtlas singleton in the (the texture is in a SKTextureAtlas) and pass it to the tree class to get the texture from on an init method. I made a property in the SKScene to hold the texture atlas so that I could pass it to the tree class every time I made a new one. I tried loading the texture from texture atlas (in the tree class) using the textureNamed: method. This still did not work. I switched back to loading the texture with SKTexture's textureWithImageNamed: method and it worked. Further more I changed to code back so that the tree subclass would not be sent the SKTextureAtlas singleton at all and it still worked.

In the SKScene I get the texture atlas using:

[SKTextureAtlas atlasNamed:@"Textures"]; //Textures is the atlas name.

and set the return value to be the SKTextureAtlas property described above. I thought that maybe the atlas just had to initialized at some point in the code, so I tried this:

SKTextureAtlas *myAtlas = [SKTextureAtlas atlasNamed:@"Textures"];

and the following alone on one line:

[SKTextureAtlas atlasNamed:@"Textures"]

but neither worked. Apparently I need to have a property in my tree's parent class which is the SKTextureAtlas which holds the texture which the tree uses without any reference to a SKTextureAtlas whatsoever... Is this a glitch or something? It's working now but it feels like a hack.

其他提示

You need to use "nearest" filtering:

self.texture.filteringMode = SKTextureFilteringNearest;

The pixels in your image must correspond with pixels on the screen perfectly.

If your image is 100x100, and you display it over a whole screen that is 105x105, it will do interpolation to figure out how to do it.

If you display it at a scaled resolution of some multiple of 2 (which should work properly), I think you still have to tell the renderer not to interpolate pixels when it does the scaling.

[self setScaleMode:SKSceneScaleModeAspectFill];

SKTexture* texture = [SKTexture textureWithImageNamed:@"image"];
[texture setFilteringMode:SKTextureFilteringNearest];

SKSpriteNode* imageNode = [SKSpriteNode spriteNodeWithTexture:texture];
[self addChild:imageNode];

Works perfectly for me. There's no blur with animation

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top