I have a working tilemap that I am able to add to my 'HelloWorldLayer' with the 'addChild' method. I am trying to add several layers at time intervals by calling a class I wrote through the game timer.
I execute the following code, but I can't see the tilemap added to the layer. ('tileMapNode' is set up in my .h file).
tileMapNode = [CCTMXTiledMap tiledMapWithTMXFile:#"scroller.tmx"];
tileMapNode.anchorPoint = ccp(pos.x, pos.y);
[layer addChild:tileMapNode]
the 'layer' parameter references the 'HelloWorldLayer'.
What am I doing wrong? If I add a sprite from this class to the HelloWorldLayer it works?
The range of anchorPoint is between 0 and 1. By setting it to some position I suspect it's way out of range. Also very large tilemaps ( >16k tiles) won't render all tiles.
Related
I need to have a particle emitters effects to appear duplicated in 2 spots (For split screen purposes), I am wondering if anybody has come across a way of doing this. My goal is to have this running on iOS 10. Here is what I have tried so far.
Assigning targetNode to an SKNode and then copying SKNode every frame: targetNode does not work in iOS 10 for me.
Assigning the particle emitter to an SKNode, and using view.textureFromNode to make a texture to copy every frame : takes 1/120th of a frame, too slow for me.
Assigning a custom action to a particle node that duplicates the node into another SKNode : Actions will not run on iOS 10
Copying the existing particle node in hopes that the seed is not random : The seed is random
Tried copying the particle emitter on update : Particle just spawns at origin
Tried SKReferenceNode : Just a copy of the emitter, runs on its own
The only option I am left for true emitting is writing my own particle emitter, which I am trying to avoid, so I am wondering if anybody else had this problem and knew of a solution to achieve desired effect.
The other thing I could do is prerendering the emitters, but this will take up a lot of texture memory if I go this route.
Edit: To help visualize, I drew a picture, The white border shows where the Split Screen happens. The black border shows where the scene wrapping happens.
As of right now, both Player 1 and Player 2 are on the original scene.
Player 2 is walking right and is about to hit a world wrap to move him to the left hand side of the world, but he has not hit it yet. So I need to have a copy of the scene happening so that it visually looks like one scene. Since player 1 is still on the original scene, the original emitter needs to stay in place. Player 2 is going to have to see the same image happening in the copy, otherwise once he passes that border, a "glitchy" effect will happen, and the illusion of wrapping is now gone.
Final Result:
We just said F%%% it, Player 1 and Player 2 will be looking at different emitter nodes, we will just attach the emitters to each players camera when needed.
This just works (I guess as intended), but I have no idea how much is performant or how it fits your needs and your current game. Anyways, maybe it can help you in some way. First, in your GameViewController...Split screen :)
#import "GameViewController.h"
#import "GameScene.h"
#implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * leftSKView = (SKView *)self.leftScene;
leftSKView.ignoresSiblingOrder = YES;
leftSKView.showsFPS = YES;
leftSKView.showsNodeCount = YES;
SKView * rightSKView = (SKView *)self.rightScene;
rightSKView.ignoresSiblingOrder = YES;
rightSKView.showsFPS = YES;
rightSKView.showsNodeCount = YES;
// Create and configure the scene.
GameScene *scene = [GameScene nodeWithFileNamed:#"GameScene"];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[leftSKView presentScene:scene];
[rightSKView presentScene:scene];
}
leftScene and rightScene are UIViews defined in a storyboard using autolayout to take half of a screen each. Also a class is changed to SKView (it was UIView). Pretty trivial...
Then in your game scene just add an emitter which will be shared between these two views. Because only one emitter is used, particles emitting (how they move) will be mirrored. So in game scene, just add a particle:
-(void)didMoveToView:(SKView *)view {
/* Setup your scene here */
SKEmitterNode *emitter = [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:#"MyParticle" ofType:#"sks"]];
emitter.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidX(self.frame));
emitter.name = #"explosion";
emitter.targetNode = self;
[self addChild:emitter];
}
I know that you don't need all this code, but if this is what you want in some way, I will post it for completeness. And here is the result:
Hey i was wondering if there was a way to tell the name of the currently assigned frame to a specific sprite.
What I want to do is have an if statement similar to
if(CGRectIntersectsRect([Player1 boundingBox], [Player2 boundingBox] && Player1.frame == Player2.frame){
//Do something
}else if(CGRectIntersectsRect([Player1 boundingBox], [Player2 boundingBox] && Player1.frame != Player2.frame{
//Do something else
}
Unfortunately i have no clue what the proper way to do this is. Can i get the actual name of the current sprite's frame. ie. #"Frame1.png" so i could compare it to the sprite it's colliding with's frame name?
Also sorry if i'm using wrong terminology by frame i mean like the sprite's image from a sprite sheet ie. spriteWithSpriteFrameName.
CCSpriteFrame* frame = sprite.displayFrame;
NSString* frameName = frame.textureFilename;
I'm not sure if this returns individual frame names though. If it only returns the atlas texture filename you're out of luck. You'd have to modify the CCSpriteFrame code to include a frame name property.
Im not sure if it is a property on CCSprite, you would have to check the docs but a simple solution to this would be to use inheritance and subclass the CCSprite.
Add the properties you want, so the imageName property, change your CCSprite allocations to use the new subclassed sprite and you will then be able to access the property. Don't forget the imports.
Also, you should use CGRectEqualToRect ( CGRect rect1, CGRect rect2 ); to check for equality. Depending on your sprites, you might want correct collision detection to avoid transparency collision detection which the CGRect methods won't do.
Hope this helps.
So I want to divide my game into chunks by using several different CCTMXTiledMaps.
I am able to load the maps into my main 'HelloWorldLayer'. I am also able to detect whether the player sprite collides with a tile with the property of 'collectable'.
My problem occurs when I add several CCTMXTiledMap nodes to the game, as it doesn't do the collectible tile detection on all of them, just the first one.
Here is my working code that does the check, but only for the first added CCTMXTledMap:
CGPoint point = [self getTileCoordForPosition:position :map];
CCTMXLayer *metaLayer = [map layerNamed:#"Meta"];
CCTMXLayer *foregroundLayer = [map layerNamed:#"Foreground"];
CCSprite *metaTile = [metaLayer tileAt:point];
CCSprite *foregroundTile = [foregroundLayer tileAt:point];
if (foregroundTile)
{
NSLog(#"HIT!");
// Remove the meta tile and the foreground tile
[metaLayer removeTileAt:point];
[foregroundLayer removeTileAt:point];
}
How can I make this code do the check for every CCTMXTiledMap node that has been added?
The problem was that I was calculating the tile map positions wrong, in a tile map co-ordinates to map position function.
I was multiplying by the CC_SCALE_RATIO() function, or something like that (going off the top of my head), and it was mis-calculating the pixel positioning.
Just thought I'd write in an answer since I found the solution. Hope it helps somebody!
Dear all,
I have an application that uses cocos2d spacemanager with gravity set to a specific value.
If i want to make a shape in the middle of the screen it will fall down to the floor, if i set the gravity to zero all other object will not move as supposed, if i use a second spacemanager and set its gravity to 0 i cant detect collision between objects from different spacemanagers. how can i add a shape that wont fall down in the middle of the screen and detect its collision while other objects behave correctly according to the gravity set.
Also a question is, should i use shapes (Circle, rectangle, ... etc) with spacemanager and if i want to use a ccsprite (image) i should put it in a shape or i can use the sprite alone (e.g. a tree is not a rectangle or circle collision and reflection wont be natural how can i do this).
regards
Every shape has a property called mass. If you want a shape to be static and respond to collisions just set mass to STATIC_MASS like this:
cpShape *ball = [smgr addCircleAt:cpv(440,70) mass:STATIC_MASS radius:10];
to ad an image, do that:
cpShape *ball = [smgr addCircleAt:cpv(440, 70) mass:STATIC_MASS radius:10];
[super initWithShape:playerShape file:#"ball.png"];
If this doesn't work, set up a cpCCSprite in it with a shape.
You can search for cpCCSprite on google, im sure you'l find something :)
I'm developing a game for iOS. I'm using cocos2d libs. I want to have an object, that have 3 parts - beginning, ending and the middle. I've got the image with these components. And the object can be stretched, when created. But only the middle part should be stretched, the beginning and endings should have no scaling. Because this operation is done only once i decided it's a good idea to create a new CCSprite for this object, and not to keep three (for increasing performance).
I'm using CCSPriteBatchNode for rendering, and i don't know if i really need to combine the object's parts (maybe rendering 3 parts using batch will be as fast as rendering one pre-combined object).
So there are two quastions:
Do i need to combine parts in one object?
If, yes - how can i do that?
Instead of combining the textures you could create a node and add the three sprites as children to it. You can then work with the parent node as a single entity.
Something along the lines of:
CCNode *sprites = [CCNode node];
CCSprite *spriteA = [CCSprite spriteWithSpriteFrameName:#"spriteA.png"];
spriteA.position = ccp(-10, 0);
[sprites addChild:spriteA];
CCSprite *spriteB = [CCSprite spriteWithSpriteFrameName:#"spriteB.png"];
spriteB.position = ccp(0, 0);
[sprites addChild:spriteB];
CCSprite *spriteC = [CCSprite spriteWithSpriteFrameName:#"spriteC.png"];
spriteC.position = ccp(10, 0);
[sprites addChild:spriteC];
You can scale and position each individual sprite depending on your parameters then work with the sprites object to position/scale them as a whole.
There might be a small performance hit so I would think twice before using this for a large amount of sprites, but I've been using this method in a few situations and in my case I didn't notice any issues with performance.
Look at the RenderTexture demo.
Instead of using the brush, you can use put your 3 parts onto it using those images instead of the brush.