• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung

cocos2d sprite.position.x ergibt (null), aber warum?

nilsTGMD

Braeburn
Registriert
27.10.07
Beiträge
47
Moin,
ich bin neu in obj-c und versuche gerade ein kleines Spiel mit Hilfe von cocos2d zu schreiben. Dabei möchte ich überprüfen ob zwei Objekte(Sprites) sich zu einem bestimmten Zeitpunkt auf der gleichen X-Position befinden.

Nun lässt sich aber die Position der Sprite player nicht abfragen, mit NSLog(@"%d", player.position.x) erhalte ich immer nur (null) in der Konsole. Was mache ich da falsch? Bei den Sprites blockX funktioniert das so wie gewollt und erwartet. Die Positionsabfrage passiert in der collide-Methode, welche am Ende der Bewegung der Blöcke aufgerufen wird.

GameScene.h
Code:
#import <UIKIt/UIKit.h>
#import "cocos2d.h"
#import "chipmunk.h"

@interface GameScene : Scene { }
@end


@interface GameLayer : Layer {
    Sprite * block1;
    Sprite * block2;
    Sprite * block3;
    Sprite * player;
    
    cpSpace* space;
    
    UIButton *leftBtn;
    UIButton *rightBtn;
    
    float speed;
    int freePosition;
    int score;
}
-(void) arangeSprites;
-(void) moveBlocks;
-(void) collide;

-(void) showMenu:(id) sender;
-(void)resumeOption:(id)sender;
-(void)restartOption:(id)sender;
-(void)quitOption:(id)sender;

-(void) setPlayer;
-(void) setLayer:(Class) classLayer;
-(void) backCallback:(id) sender;
-(void) nextCallback:(id) sender;
-(void) restartCallback:(id) sender;


@end
GameScene.m
Code:
#import "GameScene.h"
#include <unistd.h>


#pragma mark -

@implementation GameScene

-(id) init {
    self = [super init];
    if( self != nil ) {
        [self addChild: [GameLayer node] z:1];
    }
    return self;
}

@end

#pragma mark -

static int sceneIndex=-1;
static NSString *transitions[] = {
    @"PlayerLayer01", @"PlayerLayer02", @"PlayerLayer03", @"PlayerLayer04"};

Class nextAction() {
    sceneIndex++;
    if(sceneIndex >= sizeof(transitions))
        sceneIndex = sceneIndex % (sizeof(transitions)/sizeof(transitions[0]));
    NSString *r = transitions[sceneIndex];
    Class c = NSClassFromString(r);
    return c;
}

Class backAction() {
    sceneIndex--;
    if(sceneIndex < 0)
        sceneIndex = sizeof(transitions)/sizeof(transitions[0])-1;
    NSString *r = transitions[sceneIndex];
    Class c = NSClassFromString(r);
    return c;
}

Class restartAction() {
    if(sceneIndex < 0 || sceneIndex >= sizeof(transitions))
        return nil;
    NSString *r = transitions[sceneIndex];
    Class c = NSClassFromString(r);
    return c;
}


#pragma mark -

@implementation GameLayer

// Layer initialisieren
-(id) init {
    self = [super init];
    
    if(self != nil) {
        Sprite *bg = [[Sprite spriteWithFile:@"background.png"] retain];
        bg.position = cpv(160,240);
        [self addChild: bg];    
        
        // Member setzen
        speed = 5.0;
        score = -1;
        
        //alle Sprites in 80x80 sonst passt das alle nicht
        block1 = [[Sprite spriteWithFile:@"vlc.png"] retain];
        block2 = [[Sprite spriteWithFile:@"vlc.png"] retain];
        block3 = [[Sprite spriteWithFile:@"vlc.png"] retain];
        [self addChild:block1 z:2];
        [self addChild:block2 z:2];
        [self addChild:block3 z:2];
        [self arangeSprites];
        
        player = [[Sprite spriteWithFile:@"car.png"] retain];
        [self addChild:player z:1];
        [self setPlayer];
        
        MenuItemImage *item1 = [MenuItemImage itemFromNormalImage:@"button.png" selectedImage:@"button_pressed.png" target:self selector:@selector(backCallback:)];
        MenuItemImage *item2 = [MenuItemImage itemFromNormalImage:@"button.png" selectedImage:@"button_pressed.png" target:self selector:@selector(nextCallback:)];
        MenuItemImage *item3 = [MenuItemImage itemFromNormalImage:@"menu.png" selectedImage:@"menu.png" target:self selector:@selector(showMenu:)];
        Menu *menu = [Menu menuWithItems:item1, item2, item3, nil];
        menu.position = CGPointZero;
        
        item1.position = ccp(320/2-80, 480/2-25);
        item2.position = ccp(320/2+80, 480/2-25);
        item3.position = ccp(305, 465);
        
        
        [self addChild:menu z:3];
    }
    return self;
}


//
// Diese Methode setzt die Sprites in zufälliger Reihenfolge
// und ruft die Methode zum bewegen auf.
//
-(void) arangeSprites{
    score = score++;
    NSLog(@"Score: %d", score);
    
    CGSize size = [[Director sharedDirector] winSize];
    int randomNumber = (arc4random() % 4);
    
    //Bloecke ausrichten
    if(randomNumber == 0){
        [block1 setPosition:ccp(120, size.height-40)];
        [block2 setPosition:ccp(200, size.height-40)];
        [block3 setPosition:ccp(280, size.height-40)];
        freePosition = 0;
    }
    if(randomNumber == 1){
        [block1 setPosition:ccp(40, size.height-40)];
        [block2 setPosition:ccp(200, size.height-40)];
        [block3 setPosition:ccp(280, size.height-40)];
        freePosition = 1;
    }
    if(randomNumber == 2){
        [block1 setPosition:ccp(40, size.height-40)];
        [block2 setPosition:ccp(120, size.height-40)];
        [block3 setPosition:ccp(280, size.height-40)];
        freePosition = 2;
    }
    if(randomNumber == 3){
        [block1 setPosition:ccp(40, size.height-40)];
        [block2 setPosition:ccp(120, size.height-40)];
        [block3 setPosition:ccp(200, size.height-40)];
        freePosition = 3;
    }
    [self moveBlocks];
}

// Spieler init
-(void) setPlayer{
    CGSize size = [[Director sharedDirector] winSize];
    [player setPosition:ccp(size.width/4-40, size.height-400)];
}

// zeigt das Pausen-Menu
-(void)showMenu:(id)sender{
    [[Director sharedDirector] pause];
}

-(void)resumeOption:(id)sender{
    [[Director sharedDirector] resume];
}

-(void)restartOption:(id)sender{
    
}

-(void)quitOption:(id)sender{
    
}

// Bloecke bewegen und Geschwindigkeit steigern
-(void)moveBlocks{
    CGSize size = [[Director sharedDirector] winSize];
    id moveBlock1 = [MoveTo actionWithDuration:speed position:ccp(block1.position.x, size.height-400)];    
    [block1 runAction:[Sequence actions:moveBlock1, nil, nil, nil]];
    
    id moveBlock2 = [MoveTo actionWithDuration:speed position:ccp(block2.position.x, size.height-400)];    
    [block2 runAction:[Sequence actions:moveBlock2, nil, nil, nil]];
    
    id moveBlock3 = [MoveTo actionWithDuration:speed position:ccp(block3.position.x, size.height-400)];    
    [block3 runAction:[Sequence actions:moveBlock3, [CallFunc actionWithTarget:self selector:@selector(collide)],
                       [CallFunc actionWithTarget:self selector:@selector(arangeSprites)], nil]];
    
        
    // Geschwindigkeit steigern
    if(speed >= 1.5){
        speed = speed - 0.2;
    }
}

// Ueberprueft auf Kollision und reagiert entsprechend.
-(void) collide{
    if(player.position.x < freePosition*80+40 < player.position.x){
        NSLog(@"Kollision!!");
    }
    NSLog(@"%s", [player position].x);
}

-(void) dealloc{
    [block1 release];
    [block2 release];
    [block3 release];
    [player release];
    [super dealloc];
}

-(void) setLayer: (Class) classLayer{
    if(classLayer==nil)
        return;
    Scene *scene = [Scene node];
    [scene addChild:[classLayer node]];
    [[Director sharedDirector] replaceScene:scene];
}

-(void) restartCallback: (id)sender{
    [self setLayer: restartAction()];
}

// nach Rechts fahren
-(void) nextCallback:(id)sender{
    if(player.position.x+80 <= 320){
        CGSize size = [[Director sharedDirector] winSize];
        id actionTo = [MoveTo actionWithDuration:0.1 position:ccp(player.position.x+80, size.height-400)];    
        id rotateRight = [RotateTo actionWithDuration:0.1 angle:20];
        id rotateBack = [RotateTo actionWithDuration:0.1 angle:0];
        [player runAction:[Sequence actions:rotateRight, actionTo, rotateBack, nil]];
    }
}

// nach Links fahren
-(void) backCallback:(id)sender{
    if(player.position.x-80 >= 0){
        CGSize size = [[Director sharedDirector] winSize];
        id actionTo = [MoveTo actionWithDuration:0.1 position:ccp(player.position.x-80, size.height-400)];    
        id rotateLeft = [RotateTo actionWithDuration:0.1 angle:-20];
        id rotateBack = [RotateTo actionWithDuration:0.1 angle:0];
        [player runAction:[Sequence actions:rotateLeft, actionTo, rotateBack, nil]];
    }
}

@end
Ich weiß, dass es noch nicht der beste Stil ist, aber steh echt noch am obj-c Anfang und bin sonst nur Java gewöhnt.

Würde mich über eure Hilfe freuen, danke!
 

Poljpocket

Salvatico di Campascio
Registriert
07.01.07
Beiträge
432
Hallo, schau dir mal folgende Definitionen an:

Wenn du im cocos2d-Projekt Sprite.h öffnest, siehst du, dass CocosNode eine Superklasse von Sprite ist. Dort nachgeschaut stellt sich heraus, dass diese als Position eine CGPoint ausgibt.

CGPoint:
Code:
struct CGPoint {
   CGFloat x;
   CGFloat y;
};
typedef struct CGPoint CGPoint;

CGFloat ist in 32bit ein float, in 64bit ein double.

Somit ist klar, dass die Abfrage

Code:
NSLog(@"%d", player.position.x);

(null) als Ausgabe ergibt, weil du ohne casting einen float (wird wohl beim iPhone 32bit sein!) als integer ausgibst und das ist noch nie gut gegangen, also ändere das %d in %f und es funktioniert.

Eine zweite Möglichkeit ist das schon angesprochene casting. Ändere die Zeile in:

Code:
NSLog(@"%d", (int)player.position.x);

Auch das sollte funktionieren.

Gruss ppocket
 

nilsTGMD

Braeburn
Registriert
27.10.07
Beiträge
47
Ach Mist, bin Java-verwöhnt :)

Jetzt funktionierts, Danke!!