2012-02-07 16 views
1

私は、ユーザーがスライダーを動かすとイメージをアニメートする単純なアプリケーションを開発しています。これは個々の画像で簡単に行うことができますが、方法が非効率的であるという明らかな理由からです。Cocos2dなしでXcodeでスプライトシートをアニメーション化するにはどうすればよいですか?

現在のところ、アニメーションは14枚のスプライトシートに分割され、1枚に16枚の画像が含まれています。私は、CGImageCreateWithImageInRectを使ってスライダによって指示された現在のイメージを見つけ、そのイメージでイメージビューを更新するメソッドを作成しました。これは機能しますが、流動的ではありません。私は理由を理解していると思うが、そうでなければ何をすべきかわからない。私はCocos2dやOpenGL ESを使用することができますが、私は頑固であり、これがなければこれが可能であると確信しています。私はちょうど方法を知りたい。任意の助けを事前に

- (void)setUp{ 

NSString *string; 
NSString *bundleString = [[NSBundle mainBundle] bundlePath]; 
dsRedPathArray = [[NSMutableArray alloc] initWithCapacity:15]; 
for (int i = 0; i < 14; i++) 
{ 
    string = [bundleString stringByAppendingFormat:@"/dsRedAni_%d.png", i]; 
    [dsRedPathArray addObject:string]; 
} 

//initial image starts at (0, 1) of image dsRedAni_9 
currentImage = [UIImage imageWithContentsOfFile:[dsRedPathArray objectAtIndex:9]]; 
currentRef = CGImageCreateWithImageInRect(currentImage.CGImage, CGRectMake(495, 0,  kModelWidth, kModelHeight)); 

modelView.image = [UIImage imageWithCGImage:currentRef]; 
} 

- (IBAction)sliderMoved:(UISlider*)sender 
{ 
    [self animateModel:sender.value]; 
} 

- (void)animateModel:(int)index 
{ 
    index += 1; 
    imageIndex = (index/16) + 9; 
    if (imageIndex > 13) 
    { 
    imageIndex = -14 + imageIndex; 
    } 
    currentX = kModelWidth * (index % 4); 
    currentY = kModelHeight * ((index/4) % 4); 

    currentRect = CGRectMake(currentX, currentY, kModelWidth, kModelHeight); 
    currentImage = [UIImage imageWithContentsOfFile:[dsRedPathArray objectAtIndex: (imageIndex)]];  
    currentRef = CGImageCreateWithImageInRect(currentImage.CGImage, currentRect); 

    modelView.image = [UIImage imageWithCGImage:currentRef]; 
} 

ありがとう:

はここにいくつかのサンプルコードです。

答えて

4

私は最終的なAPIからの任意の外部の助けなしに私のスプライトシートの各セクションを巡回のではなく、迅速かつ効率的に、型にはまらない場合は、方法を見つけました。時間とパワーをコンテキストや個々のファイルに分割するのではなく、私が必要とする画像のサイズでUIViewを作成し、スプライトシート全体をUIImageViewとしてビューに追加する方が効率的であることがわかった。

view.clipsToBoundsをYESに設定すると、ビューはスプライトシートのマスクとして機能し、可視部分をシート上を循環する各画像のサイズに制限します。アニメーションの効果を与えるために、私は単にimageview.centerを使ってスプライトシートをビューの周りに移動させ、目的の画像座標にします。ですから、16枚の画像を含むスプライトシートでは、画像を表示するために1回だけ呼び出すだけで、アニメーションの各フレームごとに移動するだけです。

- (id)initWithFrame:(CGRect)frame 
{ 
self = [super initWithFrame:frame]; 
if (self) { 
    [self setUp]; 
    self.backgroundColor = [UIColor clearColor]; 
    self.clipsToBounds = YES; 
} 
return self; 
} 

- (void)setUp 
{ 
    //assign |lastImageIndex| a number not equal to |imageIndex| 
    lastImageIndex = -1; 

    modelImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1924, 1708)]; 

    NSString *string; 
    NSString *bundleString = [[NSBundle mainBundle] bundlePath]; 
    UIImage *image; 
    if (!imageArray) 
    { 
    imageArray = [[NSMutableArray alloc] init]; 
    NSLog(@"Init egfp |imageArray|"); 
    } 

    for (int i = 0; i < 10; i++) 
    { 
    string = [bundleString stringByAppendingFormat:@"/moleculeAni_%d.png", i]; 
    image = [UIImage imageWithContentsOfFile:string]; 
    [imageArray addObject:image]; 
    if (i == 9) 
    { 
     NSLog(@"Filled egfp |imageCache|"); 
    } 
    } 

    [self addSubview:modelImageView]; 
} 

- (void)animateModel:(int)index 
{ 
    if (index != 1) 
    { 
    index -= 1; 
    } 
    imageIndex = (index/16); 

    if (imageIndex < 9) 
    { 
    currentX = 962 - (481 * (index % 4)); 
    currentY = 854 - (427 * ((index/4) % 4)); 
    } 
    else 
    { 
    currentX = 962 - (481 * (index % 4)); 
    currentY = 427 - (427 * ((index/4) % 4)); 
    } 

    if (imageIndex != lastImageIndex) 
    { 
    if (imageIndex < 9 && onLastFrame) 
    { 
     modelImageView.frame = CGRectMake(0, 0, 1924, 1708); 
     onLastFrame = NO; 
    } 
    else if (imageIndex == 9 && !onLastFrame) 
    { 
     modelImageView.frame = CGRectMake(0, 0, 1924, 854); 
     onLastFrame = YES; 
    } 


    NSLog(@"Image: %d", imageIndex); 
    tempImage = [imageArray objectAtIndex:imageIndex]; 
    modelImageView.image = tempImage; 
    } 

    modelImageView.center = CGPointMake(currentX, currentY); 

    lastImageIndex = imageIndex; 
} 

ここでのコードのほとんどは、正しい画像を表示するために画像ビューをどこに移動する必要があるかを判断するのに費やされます。これは私が上で説明した方法をとっており、それぞれが16の画像が均等に広がる10個のスプライトシートに渡って広げています(最後の8個を除く)。減速は、プログラムが16フレームごとに画像間でスワップしていたときに発生しました。これを回避するために、私のコントローラーは、ユーザーが画面を読み込んでいるだけなので、別のビュー(カーテンのような)の下にあるすべてのイメージをすばやく表示します。画像が一度循環されると、カーテンビューが削除され、アニメーション(スライダ付きのユーザーによって制御される)がバターのように動きます。

+0

あなたはそれぞれのpngファイルをループしていますが、私はあなたがスプライトシートメソッドを持っていると思いましたか? – mskw

+0

これは、スプライトシートpngのグループです。アニメーションシーケンスが長すぎて1枚のシートに配置できず、iOSイメージサイズのしきい値内に留まりました。 – MyNameIsKo

+0

@MyNameIsKoねえ、私はspritesheetに関連する同じ問題があります私の質問は私を助けてください私の質問です.http://stackoverflow.com/questions/33751146/how-to-differentiate-animation-from-single-sprite-sheet-in- ios – BHUMICA

2

これを行う1つの方法は、上記のようにCGImageCreateWithImageInRectで画像をカットすることです。その後、配列に追加します:

UIImageView *myAnimationImageView; 
[myAnimationImageView setAnimationImages:myArray]; 

次にあなたがアニメーションを開始することができます

myArray addObject:[UIImage imageWithCGImage:currentRef]; 

次は、このように、setAnimationImagesでUIImageViewを使用しています。

ここにこれをやっていいのプロジェクトがあります:https://github.com/r3econ/UIImage-Sprite-Additions

+0

setAnimationメソッドは、ユーザーがスライダーを上下に動かすとフレームを動的に表示する能力がないため、実際には役に立ちません。 – MyNameIsKo

+0

画像の配列と参照されているプロジェクトに関しては、最初に画像を切り取って後でアクセスするために配列に投げ込むのと似たようなことをやったことがありますが、これは14スプライトシートの実際の方法ではありません。多くの画像を処理するには時間がかかり、初期ロード時間が重かったです。私はプロジェクトのコードをチェックして、実際に私のものよりも最適化を見たことはありませんでした。 – MyNameIsKo

+0

イメージを切り取ったら、イメージをpngとして保存して、必要に応じてロードするだけです。 –

関連する問題