I'm trying to get CCTableView working with cocos2d 3.0 but I really don't know where to start. Does anyone have a good tutorial or anything for 3.0? I see there are a few for older versions of cocos2d but nothing for 3.0. Any help is appreciated! Thanks!
Here is a short sample. I do recommend just trying out writing some code on your own and then posting what problems you are having with it. It definitely makes for easier answering of questions. You can also create your own subclass of CCTableViewCell if you want.
The Header file, SampleTableView.h
#import "cocos2d.h"
#import "cocos2d-ui.h"
#interface SampleTableView : CCNode <CCTableViewDataSource>
#end
The source file: SampleTableView.m
float const kNumberOfRows = 30.0f;
#implementation SampleTableView
- (instancetype)init
{
self = [super init];
if (self) {
CCTableView* table = [CCTableView node];
table.dataSource = self; // make our class the data source
table.block = ^(CCTableView* table) {
NSLog(#"Cell %d was pressed", (int) table.selectedRow);
};
[self addChild:table];
}
return self;
}
- (CCTableViewCell*) tableView:(CCTableView*)tableView nodeForRowAtIndex:(NSUInteger) index {
CCTableViewCell* cell = [CCTableViewCell node];
cell.contentSizeType = CCSizeTypeMake(CCSizeUnitNormalized, CCSizeUnitUIPoints);
cell.contentSize = CGSizeMake(1.0f, 32.0f);
float colorFactor = (index / kNumberOfRows);
// Just a sample node that changes color with each index value
CCNodeColor* colorNode = [CCNodeColor nodeWithColor:[CCColor colorWithRed:colorFactor green:(1.0f - colorFactor) blue:(0.2f + 0.5 * colorFactor) ] width:100.0f height:18.0f];
[cell addChild:colorNode];
return cell;
}
- (NSUInteger) tableViewNumberOfRows:(CCTableView*) tableView {
return kNumberOfRows; // just a demo
}
And how to add it in your hello world scene or elsewhere:
SampleTableView* table = [SampleTableView node];
table.contentSizeType = CCSizeTypeNormalized;
table.contentSize = CGSizeMake(1.0, 1.0);
Here is a sample screenshot of what it looks like:
You should check out the cocos2d-tests-ios.xcodeproj in the cocos2d source.
It has a sample for pretty much every thing implemented in cocos2d, Including a CCTableView sample.
https://github.com/cocos2d/cocos2d-iphone
git clone cocos2d source.
Open the cocos2d-tests-ios.xcodeproj project and build/run the cocos2d-tests-ios target.
Related
[Solved] Guys, I found another tool on Mac app store named Plist Extractor that can help me do this. Thank you guys so so much!
I found this project on GitHub. It is a utility to unpack cocos2D sprite sheet used by cocos2d engine. After try reading and debugging this project, I cannot found any errors but it does not work as I expect. Particularly, it always generate blank images from sprite frame and save it to disk. So anyone please help me debug it. I also attach a sprite sheet for you guys to test.
Link to sprite sheet.
Try This SpriteSheetUnPacker its working with your sprite sheet.
Try this
#import "ExtractImagesFromTP.h"
[ExtractImagesFromTP createImagesFromTPPlist:#"sprite_sheet.plist"];
ExtractImagesFromTP Class
.h
#interface ExtractImagesFromTP : NSObject
+ (void)createImagesFromTPPlist:(NSString *)plist;
#end
.m
#implementation ExtractImagesFromTP
+ (NSDictionary *)getAllFrameFromPlist:(NSString *)plistFile
{
NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: plistFile];
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:path];
return [dictionary objectForKey: #"frames"];
}
+ (void)createPngFromSprite:(CCSprite *)sprite fileName:(NSString *)fileName
{
sprite.position = ccpMult(ccpFromSize(sprite.contentSize), 0.5);
[CCDirector sharedDirector].nextDeltaTimeZero = YES;
CCRenderTexture* render = [CCRenderTexture renderTextureWithWidth:sprite.contentSize.width height:sprite.contentSize.height];
[render begin];
[sprite visit];
[render end];
NSLog(#"Texture Name: %#", fileName);
[render saveToFile:fileName format:CCRenderTextureImageFormatPNG];
}
+ (void)createImagesFromTPPlist:(NSString *)plist
{
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: plist];
NSDictionary *frameNames = [self getAllFrameFromPlist: plist];
for (NSString *frameName in frameNames)
{
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:frameName];
CCSprite *sprite = [CCSprite spriteWithSpriteFrame: frame];
[self createPngFromSprite:sprite fileName:frameName];
}
}
#end
I'm having a strange problem... I have a custom class with sprite and booleans properties
In my main GameLayer, I have CCLayerColor *my1layer and in my .m section I have this code:
my1layer = [CCLayerColor layerWithColor:ccc4(144,238,144, 255)];
[self addChild: my1layer z:5 tag:100];
[my1layer setContentSize:CGSizeMake(200, 1280)];`
//default start position
my1layer =ccp(s.width/2-420, s.height-s.height+180.);
MylmageItem *postImage1 = [[MylmageItem alloc] initWithLayer:self];
[postImage1 release];
postImage1.postImageNum=CCRANDOM_0_1()*12 +1;
postImage1.postImage = [CCSprite spriteWithSpriteFrameName:(NSString*)[self assignPostImage:postImage1.postImageNum ]];
postImage1.postImage.position =ccp(my1layer.contentSize.width/2, my1layer.contentSize.height-my1layer.contentSize.height+80);
[my1layer addChild:myImage1.slotImage z:6 tag:101];’
code above does work and shows the images on layer, however when I try to access the property postImage1.postImageNum, it shows 0 always...
I do this: CCLayer *myLayer1 = (CCLayer*)[self getChildByTag:100]; later to retrieve my object...
MyImageItem *tmpImage1 = (MymageItem*)[myLayer1 getChildByTag:101]; from here I always get 0 when I do CCLOG(#"postImage1.postImageNum %d",tmpImage1.postImageNum);
How do I get data from my1layer?
First try at Chipmunk.
Not getting collision detection registering is the problem.
My code:
#implementation MainPlayScene
{
CCPhysicsNode *_physics;
CCNode *MyPhysicsBody;
CCNode *bottomBody;
}
+ (instancetype)scene
{
return [[self alloc] init];
}
- (instancetype)init
{
// Apple recommend assigning self with supers return value, and handling self not created
self = [super init];
if (!self) return(nil);
_physics = [CCPhysicsNode node];
_physics.debugDraw = YES;
[self addChild:_physics z:1];
/// BOTTOM
CGRect bottomRect = CGRectMake(0, 0, [CCDirector sharedDirector].viewSize.width, 10);
bottomBody = [CCNode node];
bottomBody.physicsBody = [CCPhysicsBody bodyWithPolylineFromRect:bottomRect cornerRadius:0];
bottomBody.physicsBody.collisionCategories = #[#"Bottom"];
bottomBody.physicsBody.type = CCPhysicsBodyTypeStatic;
[_physics addChild:bottomBody];
/// MyBody to bounce around
MyPhysicsBody = [CCSprite spriteWithImageNamed:#"MyBody-64x64-24.png"];
MyPhysicsBody.position = ccp((self.contentSize.width/2),(self.contentSize.height/2));
MyPhysicsBody = [CCNode node];
MyPhysicsBody.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, MyPhysicsBody.contentSize.height,MyPhysicsBody.contentSize.width} cornerRadius:0];
MyPhysicsBody.physicsBody.collisionCategories = #[#"MyBody"];
[_physics addChild:MyPhysicsBody z:150];
self.userInteractionEnabled = YES;
return self;
}
Detecting touch events and applying force to physics body to have it bounce up and down onto bottom body
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CCLOG(#"Touch Detected");
[MyPhysicsBody.physicsBody applyImpulse:ccp(0, 300.f)];
}
Now I try to detect a collision on “Bottom” but nothing is being registered even though I see debug lines of 2 objects touch.
/// try onCollisionEnter first ... nothing
-(void)onCollisionEnter:(CCNode *)entity collisionPair:(CCPhysicsCollisionPair *)pair
{
if ([entity.physicsBody.collisionCategories isEqual: #"Bottom"]) {
CCLOG(#"Hit bottomBody");
}
}
/// try ccPhysicsCollisionBegin pair ... nothing
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair MyBody:(CCNode *) MyBody Botton:(CCNode *)Bottom
{
CCLOG(#"Hit bottomBody");
return TRUE;
}
Obviously I’m missing something critical here …
Any help is VERY appreciated!
Thanks
I am finding it difficult to see the relevant code with all the things you posted.
I will give you an example of 2 CCSprite objects collision detection. One is called _arrowand the other one is _obstacle.
First step is to define the collision types like so :
_arrow.physicsBody.collisionType = #"arrow";
_obstacle.physicsBody.collisionType = #"obstacle";
Second step is to define the callback
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair arrow:(CCNode *)arrow obstacle:(CCNode *)obstacle
{
// Do some cool stuff
return TRUE;
}
Notice the naming, arrow and obstacle according to the collision type of theses sprites.
And third, the one that you forgot to do is set the delegate so you actually get these methods called on your physicsNode object
_physics.collisionDelegate = self;
And self (which is typically just your scene) should implement the CCPhysicsCollisionDelegate protocol.
Tibor has the correct answer, but there's an important clue that I was missing which was driving me crazy. From the comments in CCPhysicsNode.h section on the CCPhysicsCollisionDelegate:
The final two parameter names (typeA/typeB) should be replaced
with names used with CCPhysicsBody.collisionType or
CCPhysicsShape.collisionType.
If both final parameter names are "default" then the collision
method is called when a more specific method isn't found.
So I was incorrectly trying to implement something like this:
-(BOOL) ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair typeA:(CCNode *)nodeA typeB:(CCNode *)nodeB
{
// Compare if we're ignored collisions
if (([nodeA.physicsBody.collisionType isEqualToString: #"foo"])
|| ([nodeB.physicsBody.collisionType isEqualToString: #"foo"]) )
{
return NO;
}
return YES;
}
But that's WRONG!!! The correct thing I wanted to implement was this:
-(BOOL) ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair foo:(CCNode *)nodeA foo:(CCNode *)nodeB
{
return NO;
}
Note how the ignored collision type is part of the method signature.
Whew!
EDIT:
For completeness, don't forget to do:
_physics.collisionDelegate = self;
You are setting collision categories which along with collisions mask allow you to discard certain collisions. The collision type property is what works with the delegate methods.
I'm following "Learn Cocos2D" and in chapter 4 I'm met with the following directive:
And in the GameLayer init method, add the call to the initSpiders method discussed next, right after scheduleUpdate:
-(id) init {
if ((self=[super init])) {
...
[self scheduleUpdate];
[self initSpiders];
}
return self;
}
I get and ARC error message: no visible #interface for 'GameLayer' declares the selector 'initSpiders'
I get the same message at the line: self resetSpiders
what am i missing? everything builds and runs great up to that point.
This issue derives from the fact that the initSpiders and resetSpiders are not declared in your class interface and are defined in the .m file after the point where they are used.
If they are not missing altogether, you can fix this in either of 2 ways:
move the definition of the initSpiders and resetSpiders methods above your init method and the errors will disappear;
add a declaration for both methods in the #interface of the class.
(If you do both, it will also work)
Check your code to see if the implementation for those methods is available.
Your error appears to be that you haven't followed the next bit of the book too. Completing the next section should allow you to compile your code without warnings like this.
A more complete extract of that section of the book is:
And in the GameScene init method add the call to the initSpiders method discussed next, right after scheduleUpdate:
-(id) init {
if ((self = [super init]))
{
… 96 CHAPTER 4: Your First Game
[self scheduleUpdate];
[self initSpiders];
}
return self;
}
After that a fair bit of code is added to the GameScene class, beginning with the initSpiders method in Listing 4–8, which is creating the spider sprites.
Listing 4–8. For Easier Access, Spider Sprites Are Initialized and Added to a CCArray
-(void) initSpiders
{
CGSize screenSize = [[CCDirector sharedDirector] winSize];
// using a temporary spider sprite is the easiest way to get the image's size
CCSprite* tempSpider = [CCSprite spriteWithFile:#"spider.png"];
float imageWidth = [tempSpider texture].contentSize.width;
// Use as many spiders as can fit next to each other over the whole screen width.
int numSpiders = screenSize.width / imageWidth;
// Initialize the spiders array using alloc.
spiders = [[CCArray alloc] initWithCapacity:numSpiders];
for (int i = 0; i < numSpiders; i++)
{
CCSprite* spider = [CCSprite spriteWithFile:#"spider.png"];
[self addChild:spider z:0 tag:2];
// Also add the spider to the spiders array.
[spiders addObject:spider];
}
// call the method to reposition all spiders
[self resetSpiders];
}
I am using CCParticleSystemQuad to create a particle effect in Cocos2d.
Now I would like to test each particle for collisions with a CCRect.
How do I get the postions of each particle in the particle engine so I can do this?
Any help or examples would be appreciated. I've looked for hours on the net expecting to find tutorials on this. I am surprised I can't find much as I would expect collisions with particles to be essential; Perhaps I wasn't looking in the right place :)
Create a subclass of CCParticleSystemQuad and override update: method or updateQuadWithParticle:newPosition: method.
#interface MyParticleSystem : CCParticleSystemQuad
#end
#implementation MyParticleSystem
- (void)updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos
{
/* use pos */
[super updateQuadWithParticle:particle newPosition:pos];
}
#end
EDITED:
You can set any data (position, color, or so on) to the particles as the following.
#interface MyParticleSystem : CCParticleSystemQuad
#end
#implementation MyParticleSystem
- (void)update:(ccTime)dt
{
/* implement as cocos2d/CCParticleSystem.m -update: */
}
#end
Try something like
CCParticleSystemQuad* particle_system = ...;
for(int i = 0; i < particle_system->particleCount; i++)
{
particle_system->particles[idx]->pos; // Here is your position
}
The header file for the interface is here: http://www.cocos2d-iphone.org/api-ref/latest-stable/_c_c_particle_system_8h_source.html
Warning: Take this answer with a grain of salt as I don't use Cocos2d, or Objective-C.