• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

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!!