Why does my code say I'm using an undeclared identifier with 'hero' in shootAt in the line fourth from the end.
#import "GameplayLayer.h"
#import "Ship.h"
#import "MainCharacter.h"
#import "GameOverLayer.h"
int screenHeight;
int screenWidth;
#implementation GameplayLayer
-(id) init
{
if ((self = [super init]))
{
screenHeight = [[CCDirector sharedDirector] screenSize].height;
screenWidth = [[CCDirector sharedDirector] screenSize].width;
MainCharacter * hero = [[MainCharacter alloc] init];
[self addChild: hero];
hero.position = ccp(screenWidth/2, screenHeight/10);
Ship * ship1 = [[Ship alloc] init];
[self addChild: ship1];
numEnemies++;
ship1.position = ccp(screenWidth/2, screenHeight/2);
}
return self;
[self scheduleUpdate];
}
-(void) update: (ccTime) dt
{
KKInput * input = [KKInput sharedInput];
CGPoint touchPosition = [input locationOfAnyTouchInPhase:KKTouchPhaseBegan];
if (touchPosition.x != 0.0 || touchPosition.y != 0.0)
{
[hero shootAt: ccp(screenWidth/2, screenHeight)];
}
}
#end
Because hero is local variable defined in the constructor and hence not visible in other methods.
I think this is the problem of scope of variable, You declared
hero
in your
init Method
and trying to access this variable in
update Method (So hero is a local variable for init Method and undeclared for Update Method).
Update your code Like this, If you want a global Access of
hero object,
int screenHeight;
int screenWidth;
MainCharacter * hero;
And then initialize it in your init Method and access it in all other methods of same class.
Related
this is custom sprite class named BackGround
#import "BackGround.h"
// -----------------------------------------------------------------
id move02;
double roadX;
#implementation BackGround
+ (instancetype)initWithPicture: (NSString *) pic
{
return [[self alloc] init:pic];
}
-(id) init: (NSString *) pic
{
if(self = [super init])
{
CCSpriteFrameCache* spriteFrameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCSpriteFrame * bgSpriteFrame = [spriteFrameCache spriteFrameByName:pic];
self = [BackGround spriteWithSpriteFrame:bgSpriteFrame];
self.anchorPoint = ccp(0, 0);
roadX = -(self.contentSize.width-1)*2;
self.position = ccp((-roadX/2), 0);
id move01 = [CCActionMoveBy actionWithDuration:10.0f position:ccp(roadX,0.0)];
move02 = [CCActionRepeatForever actionWithAction:move01];
[self runAction:move02];
}
return self;
}
-(void)bgWhenRun
{
[self stopAllActions];
id move = [CCActionSpeed actionWithAction:move02 speed:2];
[self runAction:move];
}
-(void)bgWhenWalk
{
[self stopAllActions];
[self runAction:move02];
}
// -----------------------------------------------------------------
#end
this is scene class code
#import "_256Deathes.h"
#import "IntroScene.h"
#import "BackGround.h"
#import "cocos2d.h"
#import "Person.h"
// -----------------------------------------------------------------
Person * personA;
#implementation _256Deathes
{
}
- (instancetype)init
{
if ((self = [super init]))
{
NSAssert(self, #"Whoops");
self.userInteractionEnabled = YES;
CCSpriteFrameCache* spriteFrameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[spriteFrameCache addSpriteFramesWithFile:#"256Deathes.plist"];
BackGround * bgSprite01 = [BackGround initWithPicture:#"earthA.png"];
bgSprite01.position = ccp(0, 0);
[self addChild:bgSprite01 z:0 name:#"bgSpriteA"];
BackGround * bgSprite02 = [BackGround initWithPicture:#"earthA.png"];
[self addChild:bgSprite02 z:1 name:#"bgSpriteB"];
}
return self;
}
- (void)onEnter
{
// always call super onEnter first
[super onEnter];
[self schedule:#selector(updateSprite) interval:0.02];
}
-(void)touchBegan:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
BackGround *spriteA = (BackGround *)[self getChildByName:#"bgSpriteA" recursively:NO];
BackGround *spriteB = (BackGround *)[self getChildByName:#"bgSpriteB" recursively:NO];
[spriteA bgWhenRun];
[spriteB bgWhenRun];
}
-(void)touchEnded:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
BackGround *sprite;
for(sprite in [self children])
{
if([sprite.name containsString:#"bgSprite"])
{
[sprite bgWhenWalk];
}
}
}
-(void) updateSprite
{
[self updateBackGround01];
}
-(void) updateBackGround01
{
BackGround *sprite;
for(sprite in [self children])
{
if([sprite.name containsString:#"bgSprite"])
{
double nextX = sprite.contentSize.width-3;
if(sprite.position.x <= (-nextX))
{
sprite.position = ccp(nextX, 0);
}
}
}
}
// -----------------------------------------------------------------
#end
when i touch begin or touch end, spriteA will stop moving, after i tried some times, i found [self stopAllActions] in methods named bgWhenRun and bgWhenWalk can make spriteA and spriteB effect each other.
anyone can find out the mistakes in the code then tell me?i have tried many times,now i really have no idea. thank you!
These two sprites effect each other because both are using same instance of variables id move02 and double roadX as being global ones. Declare them within scope of BackGround class i.e. as member variables of that class.
I create a class category of UITouch this my code :
- (id)initInView:(UIView *)view;
{
CGRect frame = view.frame;
CGPoint centerPoint = CGPointMake(frame.size.width * 0.5f, frame.size.height * 0.5f);
return [self initAtPoint:centerPoint inView:view];
}
- (id)initAtPoint:(CGPoint)point inWindow:(UIWindow *)window;
{
self = [super init];
if (self == nil) {
return nil;
}
// Create a fake tap touch
_tapCount = 1;
_locationInWindow = point;
_previousLocationInWindow = _locationInWindow;
UIView *hitTestView = [window hitTest:_locationInWindow withEvent:nil];
_window = [window retain];
_view = [hitTestView retain];
if ([self respondsToSelector:#selector(setGestureView:)]) {
[self setGestureView:hitTestView];
}
_phase = UITouchPhaseBegan;
_touchFlags._firstTouchForView = 1;
_touchFlags._isTap = 1;
_timestamp = [[NSProcessInfo processInfo] systemUptime];
return self;
}
- (id)initAtPoint:(CGPoint)point inView:(UIView *)view;
{
return [self initAtPoint:[view.window convertPoint:point fromView:view] inWindow:view.window];
}
- (void)setPhase:(UITouchPhase)phase;
{
_phase = phase;
_timestamp = [[NSProcessInfo processInfo] systemUptime];
}
but when I call it I get this crash -[UITouch initAtPoint:inView:]: unrecognized selector sent to instance
How can I fix that?
You say you created a category, but did not include the definition of your category.
It should look something like this:
//UITouch+customInitMethods.h
#interface UITouch (customInitMethods)
- (id)initInView:(UIView *)view;
- (id)initAtPoint:(CGPoint)point inWindow:(UIWindow *)window;
- (id)initAtPoint:(CGPoint)point inView:(UIView *)view;
#end
And then your implementation:
#import "UITouch+customInitMethods.h"
#implementation UITouch (customInitMethod)
//Your method implementations go here.
#end
Make sure that the target checkbox on the .m file of your category file is set to include the category in your application target.
Then you would need to #import UITouch+customInitMethods.h in any file that wanted to use your custom init methods.
I am trying to create sprite animations for a game where when a user clicks on a button, it will spawn 1 unit/enemy, which will move across the screen in a running animation. At the moment, when I run the game, it will play and once I attempt to spawn a unit, the game crashes and gives me a -[__NSCFConstantString texture]: unrecognized selector sent to instance 0x11a15c error.
This is the header file for the Unit itself:
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "mainGameLayer.h"
#class MainGameLayer, Waypoint, Tower;
#interface Unit : CCSprite {
CGPoint myPosition;
int maxHP;
int currentHP;
float walkingSpeed;
Waypoint *destinationWaypoint;
BOOL active;
float centerToBottom;
float centerToSides;
}
#property (nonatomic, assign) MainGameLayer *theGame;
#property (nonatomic, assign) CCSprite *mySprite;
#property (nonatomic, strong) CCAction *walkAction;
+(id) nodeWithTheGame: (MainGameLayer *)_game;
-(id) initWithTheGame: (MainGameLayer *)_game;
-(void) doActivate;
-(void) getRemoved;
#end
Below is the implementation file. The 'self = super initWithSpriteFrame' line is currently throwing a warning saying "Incompatible pointer types sending NSString * to parameter of type 'CCSpriteFrame *'.
Also, the "CCSprite *frame = [[CCSpriterameCache....." line is throwing another warning saying 'Flag 0 results in undefined behaviour with p conversion specifier.
#import "Unit.h"
#import "Tower.h"
#import "Waypoint.h"
#define HEALTH_BAR_WIDTH 20
#define HEALTH_BAR_ORIGIN -10
#implementation Unit
#synthesize mySprite, theGame;
+(id) nodeWithTheGame:(MainGameLayer *)_game
{
return [[self alloc] initWithTheGame:_game];
}
-(id) initWithTheGame:(MainGameLayer *)_game
{
if ((self = [super initWithSpriteFrame:#"hero_walk_00.png"])) {
theGame = _game;
maxHP = 40;
currentHP = maxHP;
active = FALSE;
walkingSpeed = 0.5;
centerToBottom = 39.0;
centerToSides = 29.0;
CCArray *walkFrames = [CCArray arrayWithCapacity: 8];
for (int i = 0; i < 8; i++) {
CCSprite *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"hero_walk_%02.png", i]];
[walkFrames addObject: frame];
}
CCAnimation *walkAnimation = [CCAnimation animationWithSpriteFrames:[walkFrames getNSArray] delay:1.0/12.0];
self.walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnimation]];
Waypoint *waypoint = (Waypoint *)[theGame.waypoints objectAtIndex:([theGame.waypoints count]-1)];
destinationWaypoint = waypoint.nextWaypoint;
CGPoint pos = waypoint.myPosition;
myPosition = pos;
[mySprite setPosition: pos];
[theGame addChild: self];
[self scheduleUpdate];
}
return self;
}
-(void) doActivate
{
active = TRUE;
}
-(void) update:(ccTime)dt
{
if (!active) {
return;
}
if ([theGame circle:myPosition withRadius:1 collisionWithCircle:destinationWaypoint.myPosition collisionCircleRadius:1]) {
if (destinationWaypoint.nextWaypoint) {
destinationWaypoint = destinationWaypoint.nextWaypoint;
} else {
[theGame getHpDamage];
[self getRemoved];
}
}
CGPoint targetPoint = destinationWaypoint.myPosition;
float movementSpeed = walkingSpeed;
CGPoint normalized = ccpNormalize(ccp(targetPoint.x - myPosition.x, targetPoint.y - myPosition.y));
mySprite.rotation = CC_RADIANS_TO_DEGREES(atan2(normalized.y, -normalized.x));
myPosition = ccp(myPosition.x + normalized.x * movementSpeed, myPosition.y + normalized.y * movementSpeed);
[mySprite setPosition: myPosition];
}
-(void) getRemoved
{
[self.parent removeChild:self cleanup:YES];
[theGame.units removeObject: self];
// Notify the game that we killed an enemy so we can check if we can send another wave
[theGame enemyGotKilled];
}
-(void) draw
{
ccDrawSolidRect(ccp(myPosition.x + HEALTH_BAR_ORIGIN, myPosition.y + 16), ccp(myPosition.x + HEALTH_BAR_ORIGIN + HEALTH_BAR_WIDTH, myPosition.y + 14), ccc4f(1.0, 0, 0, 1.0));
ccDrawSolidRect(ccp(myPosition.x + HEALTH_BAR_ORIGIN, myPosition.y + 16), ccp(myPosition.x + HEALTH_BAR_ORIGIN + (float)(currentHP * HEALTH_BAR_WIDTH)/maxHP, myPosition.y + 14), ccc4f(0, 1.0, 0, 1.0));
}
#end
Here is the header file of the main game layer:
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface MainGameLayer : CCLayer {
CCSpriteBatchNode *_actors;
}
+ (CCScene *) scene;
- (BOOL) circle:(CGPoint)circlePoint withRadius:(float)radius collisionWithCircle:(CGPoint)circlePointTwo collisionCircleRadius:(float)radiusTwo;
void ccFillPoly (CGPoint *poli, int points, BOOL closePolygon);
- (void) enemyGotKilled;
- (void) getHpDamage;
#property (nonatomic, strong) NSMutableArray *towers;
#property (nonatomic, strong) NSMutableArray *waypoints;
#property (nonatomic, strong) NSMutableArray *units;
#end
And the implementation file:
#import "MainGameLayer.h"
#import "Tower.h"
#import "Waypoint.h"
#import "Unit.h"
#implementation MainGameLayer
#synthesize towers;
#synthesize waypoints;
#synthesize units;
+ (CCScene *) scene
{
CCScene *scene = [CCScene node];
MainGameLayer *layer = [MainGameLayer node];
[scene addChild: layer];
return scene;
}
- (id) init
{
if ((self = [super init])) {
// Initialize
self.isTouchEnabled = TRUE;
CGSize winSize = [CCDirector sharedDirector].winSize;
// Setting the background (Map)
CCSprite *background = [CCSprite spriteWithFile:#"layout.png"];
[self addChild: background];
[background setPosition: ccp(winSize.width/2, winSize.height/2)];
[self addWaypoints];
// In Game Buttons / Menu
CCMenuItem *sampleButton = [CCMenuItemImage itemWithNormalImage:#"sample.jpg" selectedImage:#"sample.jpg" target:self selector:#selector(samplePurchased:)];
CCMenu *PurchaseUI = [CCMenu menuWithItems:sampleButton, nil];
[PurchaseUI setScale:0.5];
[PurchaseUI setPosition:ccp(63, 51)];
[PurchaseUI alignItemsHorizontally];
PurchaseUI.isTouchEnabled = TRUE;
[self addChild: PurchaseUI];
// Set up the sprite sheets (Currently in testing)
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"pd_sprites.plist"];
_actors = [CCSpriteBatchNode batchNodeWithFile:#"pd_sprites.pvr.ccz"];
[_actors.texture setAliasTexParameters];
[self addChild: _actors];
}
return self;
}
-(BOOL) canBuyTower
{
return YES;
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
CCLOG(#"X: %f Y: %f", location.x, location.y);
if ([self canBuyTower]) {
// Spend the gold later
Tower *tower = [Tower nodeWithTheGame:self location: location];
[towers addObject: tower];
}
}
}
-(void) addWaypoints
{
waypoints = [[NSMutableArray alloc] init];
Waypoint * waypoint1 = [Waypoint nodeWithTheGame:self location:ccp(-25,360)];
[waypoints addObject:waypoint1];
Waypoint * waypoint2 = [Waypoint nodeWithTheGame:self location:ccp(73,360)];
[waypoints addObject:waypoint2];
waypoint2.nextWaypoint =waypoint1;
Waypoint * waypoint3 = [Waypoint nodeWithTheGame:self location:ccp(467,360)];
[waypoints addObject:waypoint3];
waypoint3.nextWaypoint =waypoint2;
Waypoint * waypoint4 = [Waypoint nodeWithTheGame:self location:ccp(905,360)];
[waypoints addObject:waypoint4];
waypoint4.nextWaypoint =waypoint3;
Waypoint * waypoint5 = [Waypoint nodeWithTheGame:self location:ccp(1050,360)];
[waypoints addObject:waypoint5];
waypoint5.nextWaypoint =waypoint4;
}
-(BOOL) circle:(CGPoint)circlePoint withRadius:(float)radius collisionWithCircle:(CGPoint)circlePointTwo collisionCircleRadius:(float)radiusTwo
{
float xdif = circlePoint.x - circlePointTwo.x;
float ydif = circlePoint.y - circlePointTwo.y;
float distance = sqrt(xdif*xdif + ydif*ydif);
if (distance <= radius + radiusTwo) {
return TRUE;
}
return FALSE;
}
-(void) samplePurchased: (id)sender
{
Unit *tempUnit = [Unit nodeWithTheGame: self];
[units addObject: tempUnit];
[tempUnit doActivate];
}
#end
I'm basically just working off some of the tutorials on the Ray Wenderlich website; I haven't run into any of these errors before and haven't been able to find much help on Google. Any help here is much appreciated! Thank you in advance!
EDIT: After making the changes I am now getting an invisible sprite move across the screen. The sprite's health bar will appear and move across the screen but not the actual sprite / animation itself. Any reasons for this?
[super initWithSpriteFrame:#"hero_walk_00.png"]
expects a CCSpriteFrame* as parameter, not a NSString*. This is why you get a compiler warning for this line - don't ignore compiler warnings!
The fix is simple, use the correct initializer:
[super initWithSpriteFrameName:#"hero_walk_00.png"]
And this returns a CCSpriteFrame* not a CCSprite*:
CCSprite *frame = [[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:[NSString stringWithFormat:#"hero_walk_%02.png", i]];
Hence the other warning. The fix:
CCSpriteFrame *frame = ...
I'm currently trying to access a function on another file.(another layer, to be more precise).
Both layers are on a scene.
Third layer is trying to get a function from first layer...
Here's how I'm doing this:
Here's my scene in scene.h
#import "firstLayer.h"
#import "secondLayer.h"
#import "thirdLayer.h"
#interface myScene : CCScene
{
// custom instance vars here...
}
#end
Here's how I cast my scene in scene.m
-(id)init {
self = [super init];
if(self != nil){
firstLayer *firstLayerz = [firstLayer node];
[firstLayerz setTag:111];
[self addChild:firstLayerz z:0];
secondLayer *secondLayerz = [secondLayer node];
[secondLayer setTag:112];
[self addChild:secondLayer z:2];
thirdLayer *thirdLayerz = [thirdLayer node];
[thirdLayerz setTag:113];
[self addChild:thirdLayerz z:4];
Here's how I cast the function in thirdLayer.m
#import "scene.h"
#implementation thirdLayer.m
-(id)init {
self = [super init];
if(self != nil){
firstLayer* firstLayerz = (firstLayer*)[self.parent getChildByTag:111];
[firstLayerz functionNeeded];
}
Here's functionNeeded in firstLayer.m (right below init(
-(void)functionNeeded {
NSLog(#"inside fnnction needed");
}
Of course the log ain't showing...
I do the proper cast in firstLayer.h
#interface firstLayer : CCLayer {
}
-(void)functionNeeded;
#end
In your firstLayer's init method write
self.tag = 111;
Now in your ThirdLayer where you want to call method of first layer write :
CCScene *current = [[CCDirector sharedDirector] runningScene];
if (current) {
id layer = [current getChildByTag:111];
if (layer) {
[layer functionNeeded];
}
}
I've recently decided to subclass my sprite, but I am a bit clueless on how to add them to a scene. At the moment, I have created my CCSprite subclass, using New File>Cocos2d>CCNode>Subclass of... CCSprite. Then, I have made my sprite in the Sprite.h file:
#interface Mos : CCSprite {
CCSprite *mos;
}
Once this is done, in the Sprite.m I code this:
#implementation Mos
-(id) init
{
if( (self=[super init])) {
mos = [CCSprite spriteWithFile:#"sprite_mos.png"];
}
return self;
}
What I want to know is how to then add this sprite into my game's scene.
Here is how to correctly subclass CCSprite as the documentation says:
#interface Mos : CCSprite {
// remove the line CCSprite *mos;
}
#implementation Mos
// You probably don't need to override this method if you will not add other code inside of it
-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
{
if( (self=[super initWithTexture:texture rect:rect]))
{
}
return self;
}
+ (id)sprite
{
return [Mos spriteWithFile:#"sprite_mos.png"];
}
#end
Then in your code, you can use Mos normally:
Mos *mos = [Mos sprite];
[scene addChild:mos];
The same way you add CCSprites and other classes.
Mos *newMos = [[Mos alloc] init];
// set coordinates and other properties
[scene addChild:newMos];
[newMos release];
Edit:
#interface Mos : CCSprite {
// some member variables go here
}
#implementation Mos
-(id)init
{
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:#"sprite_mos.png"];
if( texture ) {
CGRect rect = CGRectZero;
rect.size = texture.contentSize;
// set members to some values
return [self initWithTexture:texture rect:rect];
}
[self release];
return nil;
}
And then in your scene class
// ...
Mos *obj = [[Mos alloc] init];
// set position, etc
[scene addChild:obj];
[obj release];
// ...