私は非常にシンプルなゲームを開発しています。Machineの動作コードという名前の敵のクラスは次のとおりです。
#import "Machine.h"
@implementation Machine
+(id)machineWithWorld:(b2World*)world position:(CGPoint)pos
{
return [[[self alloc] initWithWorld:world position:pos] autorelease];
}
-(id)initWithWorld:(b2World*)world position:(CGPoint)pos
{
if(self = [super initWithShape:[AppDelegate renameFrameForIpad:@"machine"] inWorld:world])
{
size = [CCDirector sharedDirector].winSize;
self.body->SetTransform([Helper toMeters:pos], 0.0);
self.body->SetType(b2_staticBody);
safetyCounter = 5;
[self schedule:@selector(machineSafetyCounter)];
movementWidthInMeters = (size.width-self.contentSize.width)/PTM_RATIO;
linearSpeed = 0.5;
[self schedule:@selector(startMoving) interval:1.5];
}
return self;
}
#pragma mark<Machine Behavior>
-(void)startMoving
{
[self unschedule:_cmd];
float distanceFromCenterInMeters = (size.width/2 - self.position.x)/PTM_RATIO;
float interval = ABS(distanceFromCenterInMeters/linearSpeed);
if(interval < 0.01f)
interval = 0.02f;
b2Vec2 motionDirection = (distanceFromCenterInMeters > 0.0f) ? b2Vec2(1.0, 0.0) : b2Vec2(-1.0, 0.0);
self.body->SetType(b2_kinematicBody);
self.body->SetLinearVelocity(linearSpeed*motionDirection);
[self schedule:@selector(startMotionFromBeginning) interval:interval-0.01];
CCLOG(@"startMoving distance-->%f, interval-->%f", distanceFromCenterInMeters, interval);
}
-(void)startMotionFromBeginning
{
[self unschedule:_cmd];
float interval = (movementWidthInMeters/2)/linearSpeed;
self.body->SetLinearVelocity(0.5*b2Vec2(1.0, 0.0));
[self schedule:@selector(moveRTL) interval:interval-0.01];
[self schedule:@selector(checkIfHelmetIsBelowMachine) interval:0.1];
CCLOG(@"startMotionFromBeginning interval-->%f", interval);
}
-(void)moveRTL
{
[self unschedule:_cmd];
float interval = movementWidthInMeters/linearSpeed;
self.body->SetLinearVelocity(0.5*b2Vec2(-1.0, 0.0));
[self schedule:@selector(moveLTR) interval:interval-0.01];
CCLOG(@"moveRTL interval-->%f", interval);
}
-(void)moveLTR
{
[self unschedule:_cmd];
float interval = movementWidthInMeters/linearSpeed;
self.body->SetLinearVelocity(0.5*b2Vec2(1.0, 0.0));
[self schedule:@selector(moveRTL) interval:interval-0.01];
CCLOG(@"moveLTR interval-->%f", interval);
}
-(void)checkIfHelmetIsBelowMachine
{
[self unschedule:_cmd];
Helmet* helmet = (Helmet*)[[[[[CCDirector sharedDirector] runningScene] children] objectAtIndex:0] getChildByTag:kTagHelmet];
float helmetPosX = helmet.position.x;
if((self.position.x > helmetPosX) && (self.position.x < helmetPosX+helmet.contentSize.width))
{
[self unscheduleAllSelectors];
[self schedule:@selector(machineSafetyCounter) interval:0.1];
[self schedule:@selector(startMovingDownwards) interval:0.0];
return;
}
[self schedule:_cmd interval:0.1];
}
-(void)startMovingDownwards
{
[self unschedule:_cmd];
self.body->SetLinearVelocity(0.25*b2Vec2(0.0, -1.0));
[self schedule:@selector(stopMovingDownwards) interval:1.0];
CCLOG(@"startMovingDownwards");
}
-(void)stopMovingDownwards
{
[self unschedule:_cmd];
self.body->SetLinearVelocity(b2Vec2(0.0, 0.0));
[self schedule:@selector(startMoving) interval:0.2];
CCLOG(@"stopMovingDownwards");
}
私がしたことは次のとおりです。
1)本体は最初は静的で、ccp(size.width * 0.5、size.height * 0.75)に配置されています。
2)1.5秒後、キネマティックになり、0.5m/sの線速度で動き始めます。
3)現在の距離(画面の幅の中心から高さを同じに保つ)をチェックし、そのスポットに到達するのに必要な時間を評価してから、その方向に水平方向に移動を開始します。
4)その場所に到達すると、特徴的な動きを開始し、左から右に移動し始めます。ヘルメット(別のゲームオブジェクト)がその下を通過すると、下に移動し始め、1.0秒後に停止し、その後、サイクル全体が繰り返されます。
5)LTRとRTLを、その下にヘルメットが見つかったときに下に移動し始めるまで移動します。
ここで問題となるのは、動作が予想とまったく同じになる場合があるということです。そして何度も、それは上向きに動き始め、私は動きベクトルのyビットを正の方向に設定したことがありません。