ショートプログラム「ドッジボール」 【Xcode5】iOS7
画像ファイル3点用意
kumako01.png (32x32)
ball.png (8x8)
smile.png (8x)
ViewControllerをxibありで新規作成で追加、後述のDodgeBallViewクラスを追加した後、ひも付け
(ひも付けの意味は以下のPDFの9枚目以降を参照)
https://dl.dropboxusercontent.com/u/87424454/4%E8%83%8C%E6%99%AF%28Xcode5%29/Xcode5%E3%83%93%E3%83%AB%E3%83%89%E6%89%8B%E9%A0%86.pdf
AppDelegate.mに以下を追記
#import "ViewController.h" - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. // Set root ViewController ViewController *viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; self.window.rootViewController = viewController; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; // Screen Adjust Y+24 for time bar CGRect bounds=[[UIScreen mainScreen] bounds]; bounds.origin.y+=24; bounds.size.height-=24; [viewController.view setFrame:bounds]; return YES; }
DodgeBallView.h
// // DodgeBallView.h // DodgeBall // // Created by 中道 忠和 on 2014/01/05. // Copyright (c) 2014年 中道 忠和. All rights reserved. // #import <UIKit/UIKit.h> #define N 30 //ボールの数 @interface DodgeBallView : UIView { int WIDTH; int HEIGHT; CGContextRef context; NSMutableArray* draw; CGPoint lastPoint; float px; // prayer x position float py; // prayer y position float vx; float vy; struct ball { float x; float y; float vx; float vy; int smile; }; struct ball b[N]; int touch_direction; // 0:stop 1:up 2:right 3:down 4:left int time; int gs; } @end
DodgeBallView.m
// // DodgeBallView.m // DodgeBall // // Created by 中道 忠和 on 2014/01/05. // Copyright (c) 2014年 中道 忠和. All rights reserved. // #import "DodgeBallView.h" #define SPEED 1.0f @implementation DodgeBallView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } -(id)initWithCoder:(NSCoder*)coder { self=[super initWithCoder:coder]; if (self) { CGRect bounds=[[UIScreen mainScreen] bounds]; WIDTH = bounds.size.width; HEIGHT= bounds.size.height; // 画面の準備 context=NULL; // キャラクターの絵を準備 draw=[NSMutableArray array]; //配列を設定 [ draw addObject:[UIImage imageNamed:@"kumako01.png"]];//0 [ draw addObject:[UIImage imageNamed:@"ball.png"]]; //1 [ draw addObject:[UIImage imageNamed:@"smile.png"]]; //2 // タイマーの準備 [NSTimer scheduledTimerWithTimeInterval:0.01f target:self selector:@selector(onTick:) userInfo:nil repeats:YES]; // くまちゃんの準備 px=160.0f; //最初のX座標 py=400.0f; //最初のY座標 vx=0.0f; //最初のX座標の移動量 vy=0.0f; //最初のY座標の移動量 // ボールの準備 for (int i=0;i<N; i++) { b[i].x=rand()%320; b[i].y=rand()%100; float dist = sqrt((px-b[i].x)*(px-b[i].x)+(py-b[i].y)*(py-b[i].y)); if (dist==0) dist=5; // distが0の時は次の割り算ができなくなるためその予防 b[i].vx=(px-b[i].x)/dist*SPEED; b[i].vy=(py-b[i].y)/dist*SPEED; b[i].smile=rand()%5+1; } // その他変数 初期設定 touch_direction=0; time=0; gs=1; } return self; } - (void)drawRect:(CGRect)rect { // Drawing code // 画面の準備(まあ、呪文のようなものです。アブダカダブラ。) if (context!=NULL) { CGContextRelease(context); context=NULL; } context=UIGraphicsGetCurrentContext(); CGContextRetain(context); // 画面を真っ黒に塗って、全部消す。(それからあとで背景とキャラクターを高速で描くから、アニメーションに見える) CGContextSetRGBFillColor(context,0,0,0,1); CGContextSetRGBStrokeColor(context,0,0,0,1); CGContextFillRect(context,CGRectMake(0,0,WIDTH,HEIGHT)); // iPhone5以降の時は、画面の下にバナーを出すようにする。(もともとiphone4Sの画面サイズでつくってたから、すきまができてしまう) if ([[UIScreen mainScreen] bounds].size.height == 568){ //[[p_bmp objectAtIndex:5] drawAtPoint:(CGPointMake(0,455))]; //バナーを描画 } if (gs==1) { // TEXT NSString* s1=[NSString stringWithFormat:@"TIME=%d", time]; UIFont* font = [UIFont boldSystemFontOfSize:20]; [s1 drawAtPoint:CGPointMake(100,500) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName,[UIColor yellowColor],NSForegroundColorAttributeName,nil]]; // タイムの処理 time=time+1; // くまちゃんの描画 [[draw objectAtIndex:0] drawAtPoint:(CGPointMake(px,py))]; // くまちゃん移動処理 // タッチ操作の方向に応じて移動量を代入しておく if (touch_direction==1) { vy=-1.0f; vx=0.0f; } if (touch_direction==2) { vx= 1.0f; vy=0.0f; } if (touch_direction==3) { vy= 1.0f; vx=0.0f; } if (touch_direction==4) { vx=-1.0f; vy=0.0f; } px=px+vx; if (px<0.0f) px=0.0f; if (px>288.0f) px=288.0f; py=py+vy; if (py<0.0f) py=0.0f; if (py>512.0f) py=512.0f; // ボール描画 for (int i=0; i<N; i++) { if (b[i].smile==0) { [[draw objectAtIndex:2] drawAtPoint:(CGPointMake(b[i].x,b[i].y))]; } else { [[draw objectAtIndex:1] drawAtPoint:(CGPointMake(b[i].x,b[i].y))]; } // ボール移動 b[i].x=b[i].x+b[i].vx; b[i].y=b[i].y+b[i].vy; if (b[i].x <0.0f || b[i].x>320.0f || b[i].y>536.0f) { b[i].x=(int)rand()%320; b[i].y=0.0f; float dist = sqrt((px-b[i].x)*(px-b[i].x)+(py-b[i].y)*(py-b[i].y)); if (dist==0.0f) dist=SPEED; // distが0の時は次の割り算ができなくなるためその予防 b[i].vx=(px-b[i].x)/dist*SPEED; b[i].vy=(py-b[i].y)/dist*SPEED; } // くまちゃんとのぶつかりチェック if (((px+15.0f)-(b[i].x+4.0f))*((px+15.0f)-(b[i].x+4.0f))+((py+15.0f)-(b[i].y+4.0f))*((py+15.0f)-(b[i].y+4.0f)) < (8+1)*(8+1)) { gs=2; } } } else if (gs==2) { // くまちゃんの描画 [[draw objectAtIndex:0] drawAtPoint:(CGPointMake(px,py))]; // TEXT NSString* s1=[NSString stringWithFormat:@"TIME=%d", time]; UIFont* font2 = [UIFont boldSystemFontOfSize:20]; [s1 drawAtPoint:CGPointMake(100,500) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font2, NSFontAttributeName,[UIColor yellowColor],NSForegroundColorAttributeName,nil]]; // TEXT NSString* s2=[NSString stringWithFormat:@"アウト〜!"]; NSString* s3=[NSString stringWithFormat:@"クリックして再開"]; UIFont* font3 = [UIFont boldSystemFontOfSize:30]; [s2 drawAtPoint:CGPointMake(100,200) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font3, NSFontAttributeName,[UIColor redColor],NSForegroundColorAttributeName,nil]]; [s3 drawAtPoint:CGPointMake(40,260) withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font3, NSFontAttributeName,[UIColor redColor],NSForegroundColorAttributeName,nil]]; if (touch_direction==0) { // くまちゃんの準備 px=160.0f; //最初のX座標 py=400.0f; //最初のY座標 vx=0.0f; //最初のX座標の移動量 vy=0.0f; //最初のY座標の移動量 // ボールの準備 for (int i=0;i<N; i++) { b[i].x=(int)rand()%320; b[i].y=(int)rand()%100; float dist = sqrt((px-b[i].x)*(px-b[i].x)+(py-b[i].y)*(py-b[i].y)); if (dist==0) dist=5; // distが0の時は次の割り算ができなくなるためその予防 b[i].vx=(px-b[i].x)/dist*SPEED; b[i].vy=(py-b[i].y)/dist*SPEED; b[i].smile=rand()%5+1; } // その他変数 初期設定 touch_direction=0; time=0; gs=1; } } } // タイマー -(void)onTick:(NSTimer*)timer { [self setNeedsDisplay]; } // タッチパネル操作 -(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { lastPoint = [[touches anyObject] locationInView:self.superview]; if (gs==2) touch_direction=0; } -(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { // タッチした座標を取得 CGPoint p=[[touches anyObject] locationInView:self.superview]; // タッチ操作量はX方向とY方向のどちらが多いか絶対値で比較する(lastPointとpの座標を取得する構造がゆえに) float temp_vx, temp_vy; temp_vx=abs(lastPoint.x-p.x); temp_vy=abs(lastPoint.y-p.y); if (temp_vx > temp_vy) { if (lastPoint.x-p.x<0) { touch_direction=2; } else { touch_direction=4; } } else { if (lastPoint.y-p.y<0) { touch_direction=3; } else { touch_direction=1; } } // さっき取得したタッチの座標をラストポイントに書き換えておく。 lastPoint = p; } -(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { } -(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { [self touchesEnded:touches withEvent:event]; } @end
https://itunes.apple.com/jp/app/kumachanjanpu2/id789138227?mt=8&uo=4&at=10l8JW&ct=hatenablog