I'm trying to add animations to my game (iPhone app, using cocos2d).
The game was written in C++, and now I want to run it on iPhone, so most of the classes are in c++.
The thing looks like that.
I'm creating CCSprite,CCAction in obj-c class in init function, and then run CCAction on sprite.
And animation is working.
But I want to put this CCSprite and CCAction variables in my C++ class.
I create *CCSprite in init class and send this pointer to the c++ class. Then, I create CCAction and run it on the sprite.
And after that, when in my init function (obj-c class) do:
return self;
then the app is running, running and running and nothing happens. I receive only this message in console:
* Assertion failure in -[CCSprite setTexture:], /Users/Michal/..../libs/cocos2d/CCSprite.m:898
Terminating in response to SpringBoard's termination.
I dont know what should I do next...
Is it possible to keep CCSprite/Action etc. in C++ class succesfully?
Make sure you have properly initialized the texture before you try to use it like this:
CCTexture2D *redButtonNormal = [[CCTextureCache sharedTextureCache] addImage:#"RedButtonNormal.png"];
then initalize the sprite (or sprite subclass - in this example spuButton is a subclass of CCSprite) :
spuButton *redButton = [spuButton spuButtonWithTexture:redButtonNormal];
Note: since it is a subclass i had to setup the init methods for it like this (You must do this if you subclass CCSprite):
+ (id)spuButtonWithTexture:(CCTexture2D *)normalTexture
{
return [[[self alloc] initWithTexture:normalTexture] autorelease];
}
- (id)initWithTexture:(CCTexture2D *)aTexture
{
if ((self = [super initWithTexture:aTexture]) ) {
state = kButtonStateNotPressed;
}
return self;
}
Related
I am having some difficulties trying to import the Lua Library to an Xcode 4 cocos2d project.
So far i have done the following step to "install/compile" lua to my mac.
Open your Terminal.app
wget http://www.lua.org/work/lua-5.2.0-alpha.tar.gz
tar xvzf lua-5.2.0-alpha.tar.gz
cd lua-5.2.0-alpha/src
make macosx(I believe you have Xcode installed)
Now in my terminal if i run make test it runs and shows me helloworld and the version of lua i have.
So now i try to import the library to a target on my xcode cocos2d project.
For this i followed the steps on this website ( http://www.grzmobile.com/blog/2009/11/13/integrating-lua-into-an-iphone-app.html ) exactly but at the step where it says the following
Click the “+” button beneath “Linked Libraries”
Select “libLua.a” at the top and click the “Add” button.
i click add, the libLua.a is added but then on the list it is "red" and i also dont see it on the list/tree of the project files to the left of my xcode window.
Can someone please tell me what am i missing or what am i doing wrong ?
Thanks a lot in advance.
p.s. Dont know if this helps in some way... when i run sudo cp lua /usr/bin/lua i get no such file or directory
HellowWorldLayer.mm content for comment below
#import "HelloWorldLayer.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#import "mcLua.hpp"
#import "ShadowLabel.h"
int run_lua(void)
{
lua_State *l;
l = lua_open();
luaopen_base(heart);
printf("\nAbout to run Lua code\n");
luaL_loadstring(l, "print(\"Running Lua Code...\")");
lua_pcall(l, 0, LUA_MULTRET, 0);
printf("Lua code done.\n\n");
lua_close(heart);
return 0;
}
// HelloWorldLayer implementation
#implementation HelloWorldLayer
+(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])) {
// create and initialize a Label
CCLabelTTF *label = [CCLabelTTF labelWithString:#"Hello World" fontName:#"Marker Felt" fontSize:64];
// ask director the the window size
CGSize size = [[CCDirector sharedDirector] winSize];
// position the label on the center of the screen
label.position = ccp( size.width /2 , size.height/2 );
// add the label as a child to this Layer
[self addChild: label];
run_lua();
}
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];
}
#end
Don't worry about libraries being or staying red. Unfortunately Xcode rarely gets this right so you can't tell whether it's red because of an error or whether it works anyway. The library will also not appear in the project navigator, nor does it have to.
So your description is missing the actual problem that you're having. Have you tried compiling? What kind of error do you get?
Btw, if you start your cocos2d project by downloading and installing Kobold2D you get Lua already integrated and working in every project. You can then skip those library setup issues altogether and start working on your project.
I found that in the cocos2d Best Practices there is a suggestion to use initWithTexture to initialize sprite subclasses, instead in several books and tutorials I found that you can also use initWithSpriteFrameName. Why is that?
All of the initialization methods in CCSprite use initWithTexture:rect to create the sprite. For example,
-(id) initWithFile:(NSString*)filename
{
NSAssert(filename!=nil, #"Invalid filename for sprite");
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename];
if( texture ) {
CGRect rect = CGRectZero;
rect.size = texture.contentSize;
return [self initWithTexture:texture rect:rect];
}
[self release];
return nil;
}
Other functions (initWithFile, initWithSpriteFrame, initWithSpriteFrameName, et cetera) also call initWithTexture:rect either directly or indirectly. If your CCSprite subclass has any special initialization that needs to take place (as it ostensibly will, since you're subclassing another class), doing it in initWithTexture:rect guarantees that it will be run.
I have a subclass of AVAudioPlayer and within that subclass I have a method for stopping the current player and (for reasons I won't explain) manually calling audioPlayerDidFinishPlaying like this:
// Handles stopping the player and calling audioPlayerDidFinishPlaying
- (void) stopPlayerForTimedRepeat {
// Stop the player
[self stop];
// Manually call the audio player callback
EditPlayListViewController *playlistController = [[EditPlayListViewController alloc] init];
[playlistController audioPlayerDidFinishPlaying:self successfully:YES];
[playlistController release];
}
However, when I call audioPlayerDidFinishPlaying manually like this, all of my variables in the original EditPlaylistViewController fall out of scope.
How do I avoid this so that I still have access to all of my original variables?
I figured out a better way to do this without manually calling audioPlayerDidFinishPlaying so that all the variables will still be within scope.
// Handles stopping the player and calling audioPlayerDidFinishPlaying
- (void) stopPlayerForTimedRepeat {
// Fast forward the call to the end, which will also call audioPlayerDidFinishPlaying
[self setCurrentTime:[self duration]];
}
The variable scope loses because you are creating a new object EditPlayListViewController *playlistController = [[EditPlayListViewController alloc] init]; in the method after stopping it.
Please declare the player in your .h file (like this EditPlayListViewController *playlistController; and allocate it in your viewDidLoad method (like playlistController = [[EditPlayListViewController alloc] init];.
and change your method like this,
- (void) stopPlayerForTimedRepeat
{
// Stop the player
[self stop];
// Manually call the audio player callback
[playlistController audioPlayerDidFinishPlaying:self successfully:YES];
[playlistController release];
}
Hope,it'll work for you, if not please tell me.
So I have a subclass of a CCSprite object, and in its init method, I call:
[self scheduleUpdate]
I later release this object from its parent CCNode like so:
[self removeChild:sprite cleanup:YES];
In addition, I call [self unscheduleUpdate] in the sprite's dealloc method.
However, I'm getting a bad memory access, so it appears that the update method is still attempted after the object is released (I've narrowed it down to this, as it works perfectly if I comment out the [self scheduleUpdate] line.
Any ideas?
Found this post in an attempt to ask the same question. I tried unschedule update (within my init method as well) with no luck, but then realized that by moving the [self unscheduleUpdate]; to the actual update method (which is running continuously, unlike the init method) based on a condition it worked!
So, for those looking for copy paste, here's a progress bar example that I'm implementing from http://www.ccsprite.com/cocos2d/using-ccprogresstimer-cocos2d-example.html#HCB_comment_box
-(id) init
{
//initialize progress bar, make sure to add a file named green_health_bar.png to your
//resource folder
timer = [CCProgressTimer progressWithFile:#"green_health_bar.png"];
//set the progress bar type to horizontal from left to right
timer.type = kCCProgressTimerTypeHorizontalBarRL;
//initialize the progress bar to zero
timer.percentage = 0;
//add the CCProgressTimer to our layer and set its position
[self addChild:timer z:1 tag:20];
[timer setPosition:ccp(100, 280)];
[self scheduleUpdate];
}
and in your update method:
-(void)update:(ccTime)dt
{
//get progress bar
CCNode* node = [self getChildByTag:20];
timer.percentage += dt * 10;
if (timer.percentage >= 100)
{
[self gameOver]; //used to stop parallax and show gameover menu
[self unscheduleUpdate];
}
}
I usually don't allow forum reply emails, but feel free to ask questions via #russ152!
Hmm.. try not to use scheduleUpdate? I tried looking for self unscheduleUpdate but there is not such function in a CCNode.. You can try [self unscheduleAllselectors], which stops all selectors of the object , including the update selector, if you are not using the object anymore.. Or use custom selectors instead..
I'm new to iPhone development. I have a game loop setup as follows.
(void)CreateGameTick:(NSTimeInterval) in_time
{
[NSThread detachNewThreadSelector:#selector(GameTick) toTarget:self withObject:nil];
}
My basic game tick/render looks like this
(void)GameTick
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CGRect wrect = [self bounds];
while( m_running )
{
[self drawRect: wrect];
}
[pool release];
}
My render function gets called. However nothing gets drawn (I am using Core Graphics to draw some lines on a derived UIView).
If I call my update via a timer then all is well and good.
Can you tell me why the render fails when done via threads? And is it possible to make it work via threads?
Thanks
Rich
You can't (well, shouldn't) call -drawRect: directly. Instead, use -setNeedsDisplay; your view will then be updated the next time through the event loop. If you're running this in a separate thread, you may need to use performSelectorOnMainThread:.