I was writing a simple program using Tiled Map Editor Cocos2d and Xcode and last time I tried it it worked but now I got the new iOS 6 simulator and it doesn't. The error is just "Sigbrt" it means the signal to abort. I don't know what's wrong with my program. Here's the Hellowrold.h
//
// HelloWorldLayer.h
// game
//
// Created by Alex Reichenbach on 9/29/12.
// Copyright __MyCompanyName__ 2012. All rights reserved.
//
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
// HelloWorldLayer
#interface HelloWorldLayer : CCLayer
{
CCTMXTiledMap *theMap;
CCTMXLayer *bounds;
CCTMXLayer *bgLayer;
}
#property (nonatomic,retain) CCTMXTiledMap *theMap;
#property (nonatomic,retain) CCTMXLayer *bounds;
#property (nonatomic,retain) CCTMXLayer *bgLayer;
// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;
#end
Here's the HellowWorldLayer.m
//
// HelloWorldLayer.m
// game
//
// Created by Alex Reichenbach on 9/29/12.
// Copyright __MyCompanyName__ 2012. All rights reserved.
//
// Import the interfaces
#import "HelloWorldLayer.h"
// HelloWorldLayer implementation
#implementation HelloWorldLayer
#synthesize theMap;
#synthesize bgLayer;
#synthesize bounds;
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
self.theMap = [CCTMXTiledMap tiledMapWithTMXFile:#"game.tmx"];
self.bgLayer = [theMap layerNamed:#"bg"];
self.bounds = [_theMap layerNamed:#"by"];
[self addChild:theMap z:-1];
}
return self;
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
self.theMap = nil;
self.bgLayer = nil;
self.bounds = nil;
[super dealloc];
}
#end
and here's the Tiled program
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" width="32" height="54" tilewidth="10" tileheight="10">
<tileset firstgid="1" name="Solid_blue" tilewidth="10" tileheight="10">
<image source="Solid_blue.PNG" width="200" height="200"/>
</tileset>
<tileset firstgid="401" name="Light_green" tilewidth="10" tileheight="10">
<image source="Light_green.png" width="300" height="300"/>
</tileset>
<layer name="bg" width="32" height="54">
<data encoding="base64" compression="zlib">
eJzt1bENACAMA7DwW/8XJ3EBrAXkwXukRmklKQC4yBz9GXBLAGDPjwd+YMt4nQ7D2QL3vs3R
</data>
</layer>
</map>
self.bounds = [_theMap layerNamed:#"by"];
There is no layer named "by" in the file you posted. Are you receiving that error on that line?
Related
I am working on a game that has the player controlling a spaceShip. I want to make it such that if the spaceShip sprite collides with spaceJunk the junk disappears.
Here is my code so far.
HelloWorldLayer.h
#import <GameKit/GameKit.h>
// HelloWorldLayer
#interface HelloWorldLayer : CCLayerColor
{
CCSprite *_starShip;
CCSprite *_Paddle1;
CCSprite *_paddle2;
}
// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;
#end
HelloWorldLayer.M
// Import the interfaces
#import "HelloWorldLayer.h"
// Needed to obtain the Navigation Controller
#import "AppDelegate.h"
#pragma mark - HelloWorldLayer
// HelloWorldLayer implementation
//Import SpaceThings
#import "SpaceThings.h"
#implementation HelloWorldLayer{
}
// Helper class method that creates a Scene with the HelloWorldLayer as the only child.
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(void)gameLgoic:(ccTime)dt
{
[self addSpaceThings];
}
-(void) addSpaceThings
{
// _junk = [CCSprite spriteWithFile:#"catplaceholder.png"];
SpaceThings * spaceThings = nil;
if (arc4random() % 2 == 0){
spaceThings = [[[Astroids alloc] init] autorelease];
}else{
spaceThings = [[[SpaceJunk alloc]init] autorelease];
}
//determine where to spawn the space junk along the X-axis
CGSize winSize = [CCDirector sharedDirector].winSize;
int minX = spaceThings.contentSize.width/2;
int maxX = winSize.width - spaceThings.contentSize.width/2;
int rangeX =maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
//spawn the sprite slightly above the screen
spaceThings.position = ccp(actualX, winSize.height+_starShip.contentSize.height/2);
[self addChild:spaceThings];
//set the speed of junk
int minDuration = spaceThings.minMoveDirection;
int maxDuarton = spaceThings.maxMoveDirection;
int rangeDuration = maxDuarton - minDuration;
float actualDuraton = (arc4random() % rangeDuration)+ minDuration;
//move junk logic
CCMoveTo * actionMove = [CCMoveTo actionWithDuration:actualDuraton position:ccp(actualX, -spaceThings.contentSize.height/2)];
CCCallBlockN *actionMoveDone = [CCCallBlockN actionWithBlock:^(CCNode *node){[node removeFromParentAndCleanup:YES];}];
[spaceThings runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
if (CGRectIntersectsRect(_starShip.boundingBox, spaceThings.boundingBox)){
[self removeChild:spaceThings cleanup:YES];
}
}
// on "init" you need to initialize your instance
-(id) init
{
if (self =[super initWithColor:ccc4(255,255,255,255)]){
CGSize winSize = [CCDirector sharedDirector].winSize;
_starShip = [CCSprite spriteWithFile:#"theShip.gif"];
_starShip.position = ccp(winSize.width/2, 1.25*_starShip.contentSize.height);
//make the starship appear
[self addChild:_starShip];
//make the paddles
//bottom left one
_Paddle1 = [CCSprite spriteWithFile:#"spritePaddle.jpeg"];
int bottomOfScreenX = 0 + _Paddle1.contentSize.width/2;
int bottomOfScreenY = 0+_Paddle1.contentSize.height/2;
_Paddle1.position = ccp(bottomOfScreenX,bottomOfScreenY);
[self addChild:_Paddle1];
//bottom right one
_paddle2 = [CCSprite spriteWithFile:#"spritePaddle.jpeg"];
int bottomRightOfScreenX = winSize.width - _paddle2.contentSize.width/2;
_paddle2.position = ccp(bottomRightOfScreenX, bottomOfScreenY);
[self addChild:_paddle2];
//make thingsInSpace spawn at a set interval
int setInterval = (arc4random() % 3);
[self schedule:#selector(gameLgoic:) interval:setInterval];
//enable touch
[self setIsTouchEnabled:YES];
}
return self;
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
// don't forget to call "super dealloc"
[super dealloc];
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//make the screens and create events
CGSize winSize = [CCDirector sharedDirector].winSize;
NSSet *allTouches = [event allTouches];
UITouch *touch = [allTouches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
//check to see if the left paddle is being pressed
if (CGRectContainsPoint([_Paddle1 boundingBox], location)){
int bottomLeftOfScreenX = 0 + _Paddle1.contentSize.width/1.25;
//make an action
//the Y-coordinate of starShip must be the same since the ship must move parallel to it.
id action = [CCMoveTo actionWithDuration:2 position:ccp(bottomLeftOfScreenX,1.25*_starShip.contentSize.height) ];
//have starship call this action
[_starShip runAction:action];
[action setTag:1];
}
//check to see if the right paddle is being pressed
if (CGRectContainsPoint([_paddle2 boundingBox], location)){
int bottomRightOfScreenX = winSize.width - _paddle2.contentSize.width/1.25;
//make an action
//the Y-coordinate of starShip must be the same since the ship moves parallel to it
id action2 = [CCMoveTo actionWithDuration:2 position:ccp(bottomRightOfScreenX,1.25*_starShip.contentSize.height) ];
//starShip is now running this specified action
[_starShip runAction:action2];
[action2 setTag:2];
}
}
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//if the player stops touching the pads, all the aciton should stop.
//left button stop
[_starShip stopActionByTag:1];
//right button stop
[_starShip stopActionByTag:2];
}
#pragma mark GameKit delegate
-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
#end
spaceThings.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface SpaceThings : CCSprite
#property (nonatomic, assign) int minMoveDirection;
#property (nonatomic, assign) int maxMoveDirection;
-(id)initWithFile:(NSString *)file minMoveDirection:(int)minMoveDirection maxMoveDirection:(int)maxMoveDirection;
#end
#interface Astroids : SpaceThings
#end
#interface SpaceJunk : SpaceThings
#end
SpaceThings.M
#import "SpaceThings.h"
#implementation SpaceThings
-(id)initWithFile:(NSString *)file minMoveDirection:(int)minMoveDirection maxMoveDirection:(int)maxMoveDirection
{
if ((self =[super initWithFile:file])){
self.minMoveDirection = minMoveDirection;
self.maxMoveDirection = maxMoveDirection;
}
return self;
}
#end
#implementation Astroids
-(id)init
{
if (self = [super initWithFile:#"astroid.jpeg" minMoveDirection:2 maxMoveDirection:5]){
}
return self;
}
#end
#implementation SpaceJunk
-(id)init
{
if (self = [super initWithFile:#"blueDot.jpg" minMoveDirection:4 maxMoveDirection:7]){
}
return self;
}
#end
I'm wondering as to where to put CGRectInteresectRect part of the code. As I've currently tried placing within the SpaceJunk alloc init part and it doesn't remove the child when the ship collides with the junk.
int setInterval = (arc4random() % 3);
[self schedule:#selector(gameLgoic:) interval:setInterval];
Make setInterval value to float and give small value for schedular.
Also not do [spaceThings runAction inside loop. if required then do some condition check and run only if required.
Then your CGRectIntersectsRect will fire when intersect each other.
Happy Coding.
To be able to pan and zoom some of the content in screen I decided to use CCLayerPanZoom extension. When I look at the source code I can see that it derives from the CCLayer class. So I change the parent class of the node that's pushed to the navigation stack from CCLayer to CCLayerPanZoom. But what I get when the app launches is just a black screen. To make it cleaner, I created a new class, derived it from CCLayerPanZoom, added a test sprite onto it in the init method and pushed it to the navigation stack in the AppDelegate.m. Still I got nothing, just a black screen. Here're the two methods that I've implemented in my class:
#interface TestPanZoom : CCLayerPanZoom {
}
+(CCScene *) scene;
#end
#implementation TestPanZoom
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
TestPanZoom *layer = [TestPanZoom node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id)init{
if(self=[super init])
{
CCSprite *sprite=[CCSprite spriteWithFile:#"Default.png"];
sprite.scale=0.5;
[self addChild:sprite];
}
return self;
}
#end
I am trying to construct a number of scenes in my GameManager singleton init.
The scene is created via
- (id)init
{
self = [super init];
if (self) { // 'mainScene' is an autorelease object.
mainScene = [CCScene node];
...
}
GameManger holds a strong reference to mainScene:
#interface GameManager : NSObject
{
CCScene* mainScene;
}
But if I try to push the scene later with
[[CCDirector sharedDirector] pushScene:mainScene];
I get EXC_BAD_ACCESS
If I create and immediately push then everything works. Shouldn't the default __strong reference keep the object allocated?
Thanks in advance for any help....
Figured it out ... [CCScene node] is a convenience factory method that does:
[[[self alloc] init] autorelease];
but since I am using arc...I dont want that - I want
mainScene = [[CCScene alloc]init];
instead of
mainScene = [CCScene node];
I am creating a small game where objective is to tap and destroy mouse. I created a separate mouse class for it.
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "HelloWorldLayer.h"
#interface Mouse : CCNode <CCTargetedTouchDelegate> {
CCSprite *sprite;
HelloWorldLayer *HelloLayer;
}
-(id) initWithGame:(HelloWorldLayer *)aGame;
-(void) runFloatAction;
#property(nonatomic, retain) CCSprite *sprite;
#property(nonatomic, retain) HelloWorldLayer *HelloLayer;
#end
I am initializing like this in .m file:
-(id) initWithGame:(HelloWorldLayer *)aGame{
if ((self = [super init])) {
self.sprite = [CCSprite spriteWithFile:#"mouse.png"];
self.sprite.scale = 0.3f + CCRANDOM_0_1() * 0.5f;
self.sprite.position = ccp(CCRANDOM_0_1() * 480, CCRANDOM_0_1() * 320);
self.HelloLayer = aGame;
[aGame addChild:sprite];
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:1
swallowsTouches:YES];
//[self runFloatAction];
}
return (self);
}
I want to remove sprite on tap. For which I am using this code in .m file: -
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
if ([self containsTouchLocation:touch]) {
[self.sprite removeFromParentAndCleanup:YES];
return YES;
}else{
return NO;
}
}
Unfortunately I am not able to remove sprite. Logically, we have to remove sprite from parent. But, its not working in actual.
The way I structure my classes is to have the Mouse class as a subclass of CCSprite. If you handle the touch events in the main game class than you just remove the mouse. You also need to enable touch events if you haven't done that.
I recommend you do the above and put this in your game class.
[self setIsTouchEnabled:YES];
Mouse *myMouse = [Mouse spriteWithImage:#"Mouse.png"];
[myMouse setPosition:CGPointMake(160, 240)];
[self addChild:myMouse];
Then just handle the touch events in your game class.
When i call relpaceScene or pushScene in cocos2d, I can add some transitions to it like:
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1 scene:scene]];
but when i call popScene, it takes no parameters, and no transition can be added. Is that so?
How can i popScene with desired transitions?
Per Guy in the cocos2d forums this seems to work: Link to Forum
Add this to CCDirector.h, just after the declaration -(void)popScene (line 402):
- (void) popSceneWithTransition: (Class)c duration:(ccTime)t;
Then add this to CCDirector.m, just after the definition of -(void)popScene (line 768):
-(void) popSceneWithTransition: (Class)transitionClass duration:(ccTime)t;
{
NSAssert( runningScene_ != nil, #"A running Scene is needed");
[scenesStack_ removeLastObject];
NSUInteger c = [scenesStack_ count];
if( c == 0 ) {
[self end];
} else {
CCScene* scene = [transitionClass transitionWithDuration:t scene:[scenesStack_ objectAtIndex:c-1]];
[scenesStack_ replaceObjectAtIndex:c-1 withObject:scene];
nextScene_ = scene;
}
}
You can call the method like this:
[[CCDirector sharedDirector] popSceneWithTransition:[CCSlideInRTransition class] durat
You can use Category as follows:
#interface CCDirector (PopTransition)
- (void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t;
#end
#implementation CCDirector (PopTransition)
- (void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t {
[self popScene];
// Make Transition
if (nextScene_) {
CCScene* scene = [transitionClass transitionWithDuration:t scene:nextScene_];
[scenesStack_ replaceObjectAtIndex:([scenesStack_ count] - 1) withObject:scene];
nextScene_ = scene;
}
}
#end
This way you need not to modify CCDirector class.
I modified Kailash's answer to work with cocos2d 2.1.
CCDirector+additions.h
#import "cocos2d.h"
#interface CCDirector (additions)
-(void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t;
#end
CCDirector+additions.m
#import "CCDirector+additions.h"
#implementation CCDirector (additions)
-(void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t {
[self popScene];
// Make Transition
if (_nextScene) {
CCScene* scene = [transitionClass transitionWithDuration:t scene:_nextScene];
[_scenesStack replaceObjectAtIndex:([_scenesStack count] - 1) withObject:scene];
_nextScene = scene;
}
}
#end
A more concise version of the above that actually releases the scene so it and its textures can be cleaned up as needed.
CCDirector+addition.h
#import "cocos2d.h"
#interface CCDirector (addition)
- (void) popSceneWithTransition:(Class)transitionClass duration:(ccTime)t;
#end
CCDirector+addition.m
#import "CCDirector+addition.h"
#implementation CCDirector (addition)
- (void) popSceneWithTransition:(Class)transitionClass duration:(ccTime)t {
[_scenesStack removeLastObject];
NSUInteger count = [_scenesStack count];
NSAssert(count > 0, #"Don't popScene when there aren't any!");
CCScene* scene = [transitionClass transitionWithDuration:t scene:[_scenesStack lastObject]];
[self replaceScene:scene];
}
#end
Without having to mess with Cocos2d internals you can do it like:
CCDirector *director = [CCDirector sharedDirector];
CCScene *currentScene = [director runningScene];
CGSize contentSize = [currentScene contentSize];
CCLayerColor *black = [[CCLayerColor alloc] initWithColor:ccc4(0, 0, 0, 0) width:contentSize.width height:contentSize.height];
[currentScene addChild:black];
[black runAction:[CCSequence actionOne:[CCFadeTo actionWithDuration:1.0f opacity:255]
two:[CCCallFunc actionWithTarget:director selector:#selector(popScene)]]];