トップ «前の日記(2012-07-17) 最新 次の日記(2012-07-22)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|

2012-07-21 [iOS]15パズル

画像を使ったサービスの一つとして15パズルというスライディング・ブロック・パズルの一種の制作を考えている。

FifteenPuzzle

実装方法については、Cocoa勉強会(関西)で知り合いましたSTUDIO SHIN北村真二さんの記事『実践!iOSで作るゲームアプリ』を参考にした。北村さん、ありがとう!

まず、クラス構造だが、当初は、MVCのモデルにあたるDocumentクラスは、コントローラにあたるViewControllerでゲームの制御を行う事を考えていたが、ゲーム本来の制御とアプリの枠側とは切り離したいだとか、iPhone/iPadの両方に対応させる場合、機器の違いを吸収するViewControllerには持たせない方がいいのでは?と考え、ゲーム専用のコントローラクラスを用意しることにした。結局、北村さんの記事のとおりという事になってしまった。

class

今回の発表で作成したのは、画面に16個のマスを表示し、1個の駒をドラッグで移動するというところまでだ。

ビューコントローラでゲームの制御を行うのでなく、ゲーム用のコントローラを用意することにしたので、ビューコントローラでは描画が必要になったらゲームコントローラを生成するだけだ。

@implementation ViewController
...
- (void)viewDidLoad
{
    [super viewDidLoad];
 
    self.gameController = [[GameController alloc] initWithView:(GameBoardView *)self.view];
}
...
@end

ゲーム盤に関係するビュー等の生成は、GameBoardViewクラスと考えていたが、実際にプログラミングしてみると、ビューからは他のビューの生成が完了したか分からない事に気がついた。なので、GameControllerがGameBoardViewに初期化のタイミングを教える事にした。

@implementation GameController
...
- (id)initWithView:(GameBoardView *)view
{
    self = [super init];
    if (self) {
        self.gameBoardView = view;
        [self.gameBoardView setupWithDelegate:self];
    }
    return self;
}
...
@end

GameBoardViewに対するユーザ操作はデリゲートでGameControllerに伝えられる。なので、タッチダウンされたら何がタッチされたのか覚えておいて、ドラッグ中は駒を移動させ、タッチアップで駒をマスの位置に移動させた。

@implementation GameController
...
- (void)gameBoardViewTouchDown:(GameBoardView *)gameBoardView location:(CGPoint)touchPt taps:(int)taps event:(UIEvent*)event
{
    GameSquare      *square = [self.gameBoardView squareAtPoint:touchPt];
    GamePieceView   *pieceView = [self.gameBoardView pieceViewAtPoint:touchPt];
    if (pieceView) {
        self.pieceView = pieceView;
        self.startLocation = touchPt;
    }
}
 
- (void)gameBoardViewTouchMove:(GameBoardView *)gameBoardView location:(CGPoint)touchPt taps:(int)taps event:(UIEvent*)event
{
    if (self.pieceView) {
        CGRect  frame = [self.pieceView frame];
        frame.origin.x += touchPt.x - self.startLocation.x;
        frame.origin.y += touchPt.y - self.startLocation.y;
        self.startLocation = touchPt;
        [self.pieceView setFrame:frame];
    }
}
 
- (void)gameBoardViewTouchUp:(GameBoardView *)gameBoardView location:(CGPoint)touchPt taps:(int)taps event:(UIEvent*)event
{
    if (self.pieceView) {
        GameSquare      *square = [self.gameBoardView squareAtPoint:touchPt];
        CGRect  frame = [square frame];
        [self.pieceView setFrame:frame];
    }
    self.pieceView = nil;
}
...
@end

15個の駒が全て揃った際は、タッチアップの際に、移動可能かどうかの判定をして、可能なら移動する。その際にアニメーションで、ということになる予定だ。

run

想定通り、マスが描画さいれているか確認するため、数字を印字しているが、反転してしまっている。デバッグ目的の簡易な実装なので、気にしないで欲しい。

_ ソースコード

GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/FifteenPuzzle - GitHub

_ 【Cocoa練習帳】

http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

トップ «前の日記(2012-07-17) 最新 次の日記(2012-07-22)» 編集