2011-12-13 12 views
5

W kokos2d można ułatwić pracę w CCSprites i przenosić je na różne sposoby. Co najważniejsze - mogą mieć wejście/wyjście. Dla większości gier jest to pożądane dla sprawnego przepływu itpPrzenoszenie obiektów Box2d Podobnie jak obiekty CCSprite

id action = [CCMoveTo actionWithDuration:dur position:pos]; 
move = [CCEaseInOut actionWithAction:action rate:2]; 
[self runAction: move]; 

przypadku przenoszenia box2d ciało, sprite dołączony do niego jest aktualizowana po box2d kroku(). Przesuwanie sprite'a, a następnie aktualizowanie ciała nie jest tutaj opcją, ponieważ całkowicie pokonuje cel ramy fizyki.

Inną opcją, którą z powodzeniem zaimplementowałem, jest obliczenie przemieszczenia, prędkości i przyspieszenia sprite'a poprzez potraktowanie go jako jednostki mechaniki. Za każdym razem, gdy wywołuję moją aktualizację() na ikonce, aby postać mogła zdecydować, gdzie przenieść itd., Moja superklasa również przechowuje poprzednią pozycję i prędkość. Są one przechowywane jako wartości zgodne z box2d, dzieląc je przez PTM_RATIO.

W podklasie CCSprite, zwany FMSprite:

-(CGPoint) displacement { 
    return ccpSub(self.position, lastPos); 
} 

-(b2Vec2) getSpriteVelocity:(ccTime)dt { 
    return b2Vec2(self.displacement.x/dt/PTM_RATIO, 
        self.displacement.y/dt/PTM_RATIO); 
} 

-(b2Vec2) getSpriteAccel:(ccTime)dt { 
    b2Vec2 currVel = [self getSpriteVelocity:dt]; 
    if (dt == 0) { 
     return b2Vec2(0,0); 
    } else {  
     float accelX = (currVel.x - lastVel.x)/dt; 
     float accelY = (currVel.y - lastVel.y)/dt; 
     return b2Vec2(accelX, accelY); 
    } 
} 

// This is called each update() 
-(void) updateLast:(ccTime)dt { 
    // MUST store lastVel before lastPos is updated since it uses displacement 
    lastVel = [self getSpriteVelocity:dt]; 
    lastPos = ccp(self.X, self.Y); 
} 

// Leave this method untouched in subclasses 
-(void) update:(ccTime)dt { 
    [self updateObject:dt]; 

    // Store previous update values 
    [self updateLast:dt]; 
} 

// Override this method in subclasses for custom functionality 
-(void) updateObject:(ccTime)dt { 

} 

Mam następnie podklasy "FMSprite" na "FMObject", który przechowuje b2Body itp

Aby przenieść ciało Muszę najpierw przesunąć duszka i śledzić jego przyspieszenie, dzięki któremu znajdę potrzebną siłę (wykorzystując masę) potrzebną do podążenia za ruchem sprite'a. Ponieważ nie mogę przesunąć sprite obiektu (który jest zsynchronizowany z ciałem), robię kolejny sprite nazywany "beacon", dodam go jako dziecko do obiektu i poruszam nim. Wszystko, co musimy zrobić, to mieć funkcję synchronizowania pozycji ciała box2d z tym sprite'em beaconowym przy użyciu sił, o których wspomniałem wcześniej.

-(void) followBeaconWithDelta:(ccTime)dt { 
    float forceX = [beacon getSpriteAccel:dt].x * self.mass; 
    float forceY = [beacon getSpriteAccel:dt].y * self.mass; 
    [self addForce:b2Vec2(forceX, forceY)]; 
} 

Rezultatem jest genialny, gładka złagodzenie ruch b2body ruchu gdziekolwiek chcesz go, bez zabawy z któregokolwiek z jej własnymi siłami, ale raczej, że kopiowanie z CCSprite i replikowania jego ruch. Ponieważ jest to cała siła, nie powoduje drgań i zniekształceń podczas kolizji z innymi obiektami b2Body. Jeśli ktoś ma jakieś inne metody, aby to zrobić, opublikuj odpowiedź. Dzięki!

+0

Witam, dzięki za ten wpis. Nie zrozumiałem nawet jednej rzeczy. Dlaczego potrzebujesz sprite'a beacon? jeśli obiekt typu FMObject (który jest CCSprite) jest przenoszony za pomocą niestandardowej akcji, może sprawić, by b2Body w FMObject podążał za ikonką nadrzędną. Nie jestem pewien, co oznacza "zsynchronizowany z ciałem". Dlaczego osobiście potrzebujesz duszka ostrzegawczego i poruszasz nim? – Aks

+0

Minęły prawie 3 lata, odkąd to opublikowałem, ale myślę, że możesz mieć rację. Nie widzę powodu, by mieć sprite'a z beaconu. Myślę, że to był tylko szczegół wdrożenia. Powinieneś być w stanie zastąpić sam "FMObject". –

Odpowiedz

4

To, co robię, różni się od Twojego, ale może także poruszać się po obiektach Box2d, takich jak Obiekty CCSprite, a nawet używać CCAction. Najważniejszą rzeczą jest stworzenie obiektu zawierającego ccSprite i b2body.

@interface RigidBody : CCNode { 
    b2Body *m_Body; 
    CCSprite *m_Sprite; 
} 

A następnie przepisz metodę setPosition.

-(void)setPosition:(CGPoint)position 
{ 
    CGPoint currentPosition = position_; 
    b2Transform transform = self.body->GetTransform(); 
    b2Vec2 p = transform.p; 
    float32 angle = self.body->GetAngle(); 
    p += [CCMethod toMeter:ccpSub(position, currentPosition)]; 
    self.body->SetTransform(p, angle); 
    position_ = position; 
} 

Metoda setPosition obliczyć, jak bardzo zmienia się pozycja, i ustawić go na b2body.

Mam nadzieję, że rozumiem twoje pytanie, a odpowiedź jest pomocna dla ciebie ...

+0

To służy do pozycjonowania, ale SetTransform ustali pozycję ciała za każdym razem, zamiast używać sił.Oznacza to, że gdy zderzają się dwa obiekty RigidBody, będą one tworzyły efekt drgania, a nie gładko się odbijają. Metoda addForce to więcej pracy, ale zapewnia, że ​​fizyka jest płynna. –

+0

Tak, ale użycie siły jest trudne do utrzymania ciała w stałej prędkości i określonej pozycji. Nigdy nie popełniam żadnego błędu, kiedy używam mojej metody, ale nie mam pojęcia, czy oba ciała są b2_dynamicBody. –