iOS 8でパックを投げる

iOS用のカジュアルゲームを作成する前に、次の質問に答えてください。-なぜですか?

3つのオプション:





画像



今後数年で、正解は3番目だと思います。

そして、私は議論したり教えたりしません-私がアプリケーションを作る方法を教えます。

開発の第一人者は静かにプラスをクリックして、立ち去ります。 残りは学校とテーブルホッケーを覚えるために私に従います。

そして、はい、トピックの一意性は、各文で単語が異なる文字で始まることです。

この記事には9枚の写真と30分の面白いアニメーションがあります。



1.アイデア



ツールの選択はそれに依存します。 スマートフォンユーザーとしての私の考えは簡単です。 なぜなら-サウンド再生のライブラリを除き、開発用の追加ツールはありません。 ネットワークからリソースを借ります。 着信音、デザイン、画像、コード例。 すべてが私たちの前にすでに作成されています。 著作権-ホッケーやサッカーのように。 メッシが新しいフェイントを発明したとしましょう。 お金を著者に送金せずにコピーできます。

わかった ゲームの例として、テーブルホッケーを選択しました。

非常に個人的な
80年代。 毛皮マットでは、この楽しさが人気でした。 洗面所FDS-6でプレイしました。 私は恒星の瞬間を自慢しています-群衆は夜に競いました。 私は入って、列を待って、ローカルチャンピオンを10-0で破って、適度に去りました。 正直に言うと、私には2人の兄弟と16年間のギャンブルの練習があります。




2.プロジェクトの開始



画像

図2. Xcodeで、新しいプロジェクトを探しています。



ところで、私は太い指を持っています。 そのため、iPadモードのみがゲームに適しています。 これにより、作業が大幅に容易になります。 さらに、画面の回転を禁止し、縦向きのみを許可します。 肖像画を長く生きてください。ここにはバレエではなくホッケーがあります。

アプリケーションの名前( Hockey 2015)を選択しても問題ありません。 スポーツの名前は有益です。 お金については、もちろん、私は誤解しました。 私は、将来の作品が精神的および物質的な両方の満足をもたらすことを望みます。 私はすでにここで自分のゲームバイアスロン2014について書いています。毎年-ほぼ1000ドル。 ワールドカップ、オリンピック、カップステージで購入します。 誰? ノルウェー人、ドイツ人、チェコ人、フランス語、ロシア人、イタリア人。

私の将来のホッケーは、名前だけで似たようなものを待っていると思います。



アイコンを選択します。 名前ほど重要ではありません。 主なことは、自分で楽しむことです。

画像

図3.ホッケー選手の種類を推測する人は誰でも、賞金は1ドルです。



その結果、将来のゲームの空白が取得され、明るい灰色の画面が表示されます。 プロジェクトには、編集可能な2つのメインファイルがあります。



そして、私は悪い調子ではありません。 良いトーンは、怠け者ではなく、ViewControllerタイプの別のクラスを作成することです。 たとえば、PlayViewControllerという名前です。



画像

図4.新しいPlayViewControllerを追加します。



プロジェクトには、いつでも編集できる2つの新しいファイルがあります。





3.静止画像



エディターを使用して、PlayViewController.xibファイルに静止画像を配置します。

まず、写真を作成、盗用、または借用する必要があります。 ミルフガードは、アイスフィールド、ホッケー選手、ゴールキーパーの画像を作成しました。 モシグレにはあります。 そのために、私はモシグラの名前ラベルをフィールドの中央に配置しました。 パックはネットからです。 ホッケー選手の顔写真-nhl.com。 ボタン-Zeptolabのデザイナーから。 ホッケーの音-Ice Rageアプリから。

これで、イメージをxibファイルエディターに配置できます。 それは簡単です-すべての画像はUIImageView要素によって表示されます。



画像

図5. Xcodeエディターのホッケーフィールドとスコアボード。



将来、静的に定義された要素のアニメーションが必要な場合は、問題ではありません。 要素に名前を付けます。 これで、好きなように移動、消火、回転、モックするようにプログラムできます。



例、ファイルPlayViewController.mでscoreBoard要素(図の黒いスコアボード)を宣言します

IBOutlet UIImageView *scoreBoard;
      
      





IBOutletキーワードは、XIBエディターで、scoreBoard識別子を任意のアイテムに割り当てることができることを意味します。

エディターでマウスを割り当てます。



これで、ホッケーフィールドをブロックしないように、画像を上に移動できます。

  scoreBoard.center = CGPointMake(384, -1000);
      
      





思い出してください。384はiPad画面の幅の中心で、-1000はデバイスの外側のものです。 コマンドの実行後、スコアボードは画面の境界を超えて飛びます。



画像のグループを移動する場合は、それらを結合する必要があります。 UIView型の要素を取得して、画像とラベルのグループをその中に移動します。

画像

図6.したがって、氷から不要な要素が削除されます。



ここでホッケー選手をここに配置して、移動方法を教えます。





4.変換可能な画像



1つのホッケープレーヤーをPlayViewController.mファイルにプログラムで配置します。

  UIImageView *player = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"player_1.png"]]; float rPlayer = 150.0; player.frame = CGRectMake(0, 0, rPlayer, rPlayer); player.center = CGPointMake(100, 500); [self.view addSubview:player];
      
      







画像

図7.ホッケー選手がコートに現れました。



将来、私はそれを動かし、回転させます。 行くぞ

  player.center = CGPointMake(xnew, ynew); //    (xnew=100, ynew=440) player.transform = CGAffineTransformMakeRotation(alpha); //     (alpha=2.0)  
      
      







画像

図8.ホッケープレーヤーは別の場所に移動して振り向いた。



多くのホッケー選手がいますが、私は一人です。 配列を使用して12人のプレーヤー全員を配置します。

  NSMutableArray *players; players = [[NSMutableArray alloc] init]; shadows = [[NSMutableArray alloc] init]; for (int k=0; k<12; k++) { UIImageView *p = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"player_1"]]; p.frame = CGRectMake(0, 0, cellDx, cellDx); float x = xp[k]; float y = yp[k]; p.center = CGPointMake(x, y); p.transform = CGAffineTransformMakeRotation(ap[k]); [players addObject:p]; p = [players objectAtIndex:k]; //        12  [self.view addSubview:p]; }
      
      







5.ホッケーの数値法



ホッケーは、人生と同様、時間に依存します。

タイムカウンターが必要です。 プログラムが1分あたり3,000回トリガーするイベント。



  NSTimer *pauseTimer; time = 0; deltaTime = 1.0/50.0; pauseTimer = [NSTimer scheduledTimerWithTimeInterval:deltaTime target:self selector:@selector(timerFunction) userInfo:nil repeats:YES]; - (void) timerFunction { //    50    time = time + deltaTime; [self renderPuck]; [self renderPlayers]; [self puckMoving:deltaTime]; }
      
      







ですから、私に残っているのは、puckMoving関数をペイントすることだけです。 その中で、パックプレーヤーとホッケープレーヤーの衝突をチェックします。 数学的には、パックは半径21ピクセルの円で定義されます。 各ホッケープレーヤーには2つの円があります-より大きな(25ピクセルの半径)体。 小さい(半径5ピクセル)-クラブ。



以下の機能、内部のコメント。

パック
  for (int k=1; k<33; k++) { if ( [self checkCollision:i With:k] ) { [self resolve:i With:k]; } } -(int) checkCollision:(int) k1 With:(int) k2 { float d2 = [self distance2:k1 With:k2]; float dr = rp2[k1] + rp2[k2]; return ( d2 < dr*dr ? 1 : 0); } -(float) distance2:(int) k1 With:(int) k2 { float dxx = xp2[k1] - xp2[k2]; float dyy = yp2[k1] - yp2[k2]; return dxx*dxx + dyy*dyy; } -(void) resolve:(int) k1 With:(int) k2 { float x1 = xp2[k1]; float y1 = yp2[k1]; float x2 = xp2[k2]; float y2 = yp2[k2]; float u2 = up2[k2]; float v2 = vp2[k2]; float u1 = up2[k1]; float v1 = vp2[k1]; Vector *b1Velocity = [Vector alloc]; [b1Velocity initX:u1 initY:v1]; Vector *b2Velocity = [Vector alloc]; [b2Velocity initX:u2 initY:v2 ]; float b1Mass = mp2[k1]; float b2Mass = mp2[k2]; Vector *vv = [Vector alloc]; [vv initX:x1-x2 initY:y1-y2]; float distance = [vv magnitude]; float min_distance = rp2[k1] + rp2[k2]; if (distance < min_distance) { [vv mulScalar: ((0.1+min_distance-distance)/(distance)) ]; x1 += vv.x; y1 += vv.y; xp2[k1] = x1; yp2[k1] = y1; } Vector *lineOfSight = [Vector alloc]; [lineOfSight initX:x1-x2 initY:y1-y2]; Vector *v1Prime = [b1Velocity vectorProjectionOnto:lineOfSight]; Vector *v2Prime = [b2Velocity vectorProjectionOnto:lineOfSight]; Vector *v1Prime2 = [Vector alloc]; [v1Prime2 copyVector:v2Prime]; [v1Prime2 mulScalar:(2*b2Mass)]; [v1Prime2 addVector:[v1Prime getMulScalar:(b1Mass - b2Mass)] ]; [v1Prime2 mulScalar:(1.0/(b1Mass + b2Mass))]; Vector *v2Prime2 = [Vector alloc]; [v2Prime2 copyVector:v1Prime]; [v2Prime2 mulScalar:(2*b1Mass)]; [v2Prime2 subVector: [v2Prime getMulScalar:(b1Mass - b2Mass)] ]; [v2Prime2 mulScalar:(1.0/(b1Mass + b2Mass))]; [v1Prime2 subVector:(v1Prime)]; [v2Prime2 subVector:(v2Prime)]; [b1Velocity addVector:v1Prime2]; [b2Velocity addVector:v2Prime2]; float a = 0.999; up2[k1] = a*b1Velocity.x + (1.0-a)*b2Velocity.x; vp2[k1] = a*b1Velocity.y + (1.0-a)*b2Velocity.y; a = 1.0 - a; // NSLog(@"new speed %f", hypotf(u, v)) ); }
      
      







関数内では、Vectorクラスが使用されます。

クラスベクトル
 #import "Vector.h" @implementation Vector @synthesize x,y; -(void) initX:(float) setX initY:(float) setY { x = setX; y = setY; } -(void) copyVector:(Vector*) v{ x = vx; y = vy; } -(void) addVector:(Vector*) v { x += vx; y += vy; } -(void) subVector:(Vector*) v { x -= vx; y -= vy; } -(void) mulScalar:(float) f { x *= f; y *= f; } -(float) magnitude { return sqrt( x*x + y*y ); } -(float) magnitude2 { return x*x + y*y; } -(Vector *)getMulScalar:(float) f { Vector *v = [Vector alloc]; [v initX:x*f initY:y*f]; return v; } -(float) scalarProjectionOnto:(Vector*) v { return (x* vx + y*vy)/ [v magnitude]; } -(Vector *) vectorProjectionOnto:(Vector*) v { Vector *res = [v getUnitVector]; [res mulScalar: [self scalarProjectionOnto:v]]; return res; } -(Vector *) getUnitVector { float len = [ self magnitude]; Vector *res = [Vector alloc]; [res initX:x initY:y]; if (len>0) { len = 1.0/len; [res mulScalar:len]; } return res; } @end
      
      









パックの動きを数値的にモデル化する場合、1つのトリックがあります。 1秒あたり50回では、シミュレーションの精度が十分ではありません。 基本的なトリックを使用します。puckMovingの呼び出し回数を2倍にし、それに応じてタイムステップを10に分割します。



 - (void) timerFunction { //    50    time = time + deltaTime; [self renderPuck]; [self renderPlayers]; for (int k=0; k<10; k++) [self puckMoving:deltaTime/10.0]; }
      
      







何が起こったのか見て







6.統計はすべてを知っている



ロシア人とアメリカ人は統計が大好きです。 したがって、私は世界で最高の6つのチームのトーナメントを開催しました。

nhl.comの本物のプレイヤー、ゴール、ゴール、ポイント、トーナメントのすべてのスター。



7.テスト



Appleは、アプリの改訂段階で1,000人のテスターを許可しています。



行かないで、広告
夜に、アプリケーションはAppleストアで承認されました。 1週間でゲームの支払いが行われます。その後、ダウンロード数について説明します。





読んでくれてありがとう。



All Articles