Reputation: 11696
I have been unsuccessful in getting a SKSpriteNode to cast a shadow AND also be made to disappear when going into a shadow from the same light source. I am able to do one of the two but not both.
According to the docs: If the sprite is inside a shadow cast by a light and the sprite has a lower z position than the light, the shadow affects how the sprite is lit. All of which I have done. My SKLightNode has a zPosition of 100 and all other nodes have lower zPositions.
I have tried any and all combinations of settings for lightingBitMask, shadowCastBitMask and shadowedBitMask but nothing has worked.
I am posting the isolated code which recreates my issue. The blue box casts a shadow but is not covered by the wall shadow. The purple box casts no shadow and is covered by the wall shadow.
The light responds to touch movement so feel free to move it around the screen. The project is in landscape mode.
What am I missing or not seeing?
#import "GameScene.h"
@implementation GameScene {
SKSpriteNode *lightBulb;
}
-(void)didMoveToView:(SKView *)view {
typedef NS_OPTIONS(uint32_t, Level1LightCategory)
{
CategoryLightPlayer = 1 << 0,
};
SKSpriteNode *worldNode = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(1136, 640)];
worldNode.zPosition = 10;
//worldNode.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:worldNode];
lightBulb = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(20, 20)];
lightBulb.zPosition = 100;
lightBulb.position = CGPointMake(50, 50);
[worldNode addChild:lightBulb];
SKLightNode *light = [[SKLightNode alloc] init];
//light.zPosition = 100; // <- tried setting this again but to no effect
light.categoryBitMask = CategoryLightPlayer;
light.falloff = 0.3;
light.ambientColor = [UIColor whiteColor];
light.lightColor = [[UIColor alloc] initWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
light.shadowColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
[lightBulb addChild:light];
SKSpriteNode *wall = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(10, 300)];
wall.zPosition = 50;
wall.position = CGPointMake(500, 200);
wall.lightingBitMask = CategoryLightPlayer;
wall.shadowCastBitMask = CategoryLightPlayer;
wall.shadowedBitMask = 0x00000000;
[worldNode addChild:wall];
SKSpriteNode *box0 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(30, 30)];
box0.zPosition = 40;
box0.position = CGPointMake(800, 200);
box0.lightingBitMask = CategoryLightPlayer;
box0.shadowCastBitMask = CategoryLightPlayer;
box0.shadowedBitMask = CategoryLightPlayer;
[worldNode addChild:box0];
SKSpriteNode *box1 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(30, 30)];
box1.zPosition = 40;
box1.position = CGPointMake(800, 300);
box1.lightingBitMask = CategoryLightPlayer;
//box1.shadowCastBitMask = CategoryLightPlayer;
//box1.shadowedBitMask = CategoryLightPlayer;
[worldNode addChild:box1];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
lightBulb.position = touchLocation;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self.scene];
lightBulb.position = touchLocation;
}
-(void)update:(CFTimeInterval)currentTime {
//
}
@end
Upvotes: 7
Views: 2183
Reputation: 11696
I just heard back from Apple Developer Technical Support confirming this is a bug in SpriteKit (SKLightNode). Currently they do not know of a workaround for this issue but will update me if one is found.
As per their request, I have filed a bug report.
UPDATE April 22, 2015
SK engineering confirmed that SpriteKit doesn't support shadow casting and shadowed on the same object. There is no workaround at present. This issue will be addressed at some point.
UPDATE December 15, 2015
Received a new response from Apple regarding this issue.
Apple Developer Relations 14-Dec-2015 01:35 PM
There are no plans to address this.
We are now closing this report.
Upvotes: 10
Reputation: 1
I'v found some workaround (not sure it's useful for all situation, but in some): You can make two (or more - up to 32 as we know) different light sources and assign you sprites to them one by one (or by some groups). Then shadows will combine as we need - correctly.
SKLightNode* light1 = [SKLightNode new];
SKLightNode* light2 = [SKLightNode new];
... // init them equally
light1.categoryBitMask = 1;
light2.categoryBitMask = 2;
...
SKSpriteNode* sprite1 = ...
SKSpriteNode* sprite2 = ...
sp1.shadowCastBitMask = 1;
sp1.shadowedBitMask = 1;
sp2.shadowCastBitMask = 2;
sp2.shadowedBitMask = 2;
Upvotes: -1