くまちゃんのiOS/Androidゲームプログラミング

マイペースでゲームつくってます。

ドラクエ的マップの描画

※(2014.2.23追記)
新しいエントリをご覧ください
ドラクエRPGの基礎 マップの描画&当たり判定【Xcode5, iOS7対応】
http://tadakazu1972.hatenablog.com/entry/2014/02/23/113523

                                                                                                                    • -

以下は当時の記事です。(Xcode4, iOS6.1)

hogeView.h

@interface hogeView : UIView {
    int WIDTH;
    int HEIGHT;
    int SCALE;
    
    CGContextRef context;
    NSMutableArray* p_bmp;
    
    CGPoint lastPoint;
    
    float px; // prayer x position
    float py; // prayer y position
    float vx;
    float vy;
    
    int MAP[128][128];
    int topX; // MAP draw topX
    int topY; // MAP draw topY
}

@end

hogeView.m

#import "hogeView.h"

@implementation hogeView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // とりあえず何もしない
    }
    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;
        SCALE =1;
        
        // 画面の準備
        context=NULL;
        
        // キャラクターの絵を準備
        p_bmp=[[NSMutableArray array] retain];                      //配列を設定
        
        [ p_bmp addObject:[UIImage imageNamed:@"void.png"]];     //0
        [ p_bmp addObject:[UIImage imageNamed:@"wall01.png"]];   //1
        [ p_bmp addObject:[UIImage imageNamed:@"wall02.png"]];   //2
        [ p_bmp addObject:[UIImage imageNamed:@"wall03.png"]];   //3
        [ p_bmp addObject:[UIImage imageNamed:@"wall04.png"]];   //4
        [ p_bmp addObject:[UIImage imageNamed:@"wall05.png"]];   //5
        [ p_bmp addObject:[UIImage imageNamed:@"block.png"]];    //6
        [ p_bmp addObject:[UIImage imageNamed:@"man.png"]];      //7
        
        // タイマーの準備
        [NSTimer scheduledTimerWithTimeInterval:0.05f target:self selector:@selector(onTick:) userInfo:nil repeats:YES];
        
        // manの準備
        px=160;   //最初のX座標
        py=240; //最初のY座標
        vx=0;   //最初のX座標の移動量(ゼロだから最初は動かない)
        vy=0;  //最初のY座標の移動量(一番上で設定したジャンプの値)
        
        // ステージ生成
        int map[128][128];
        
        // ランダムに1-5の間で要素つくる
        for (int wi=0;wi<128;wi++) {
            for(int wj=0;wj<128;wj++) {
                map[wi][wj]=rand()%5;
            }
        }
        
        // 外壁 6
        for (int wl=0;wl<128;wl++) {
            map[0][wl]=6;
            map[127][wl]=6;
            map[wl][0]=6;
            map[wl][127]=6;
        }
        
        // グローバル変数に読み込ませる
        for (int i=0;i<128;i++) {
            for (int j=0;j<128;j++) {
                MAP[i][j]=map[i][j];
            }
        }
        
        // その他変数 初期設定
        topX=0;
        topY=0;
    }
    return self;
}

// 画面の描画(ほとんどここがメインの処理になります)
- (void)drawRect:(CGRect)rect
{
    // 画面の準備(まあ、呪文のようなものです。アブダカダブラ。)
    if (context!=NULL) {
        CGContextRelease(context);
        context=NULL;
    }
    context=UIGraphicsGetCurrentContext();
    CGContextRetain(context);
    
    // 画面を真っ黒に塗って、全部消す。(それからあとで背景とキャラクターを高速で描くから、アニメーションに見える)
    CGContextSetRGBFillColor(context,0,0,0,1); // R:0 G:0 B:0 -> 黒。ここをいろいろ変えると赤になったり、青になったり。
    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))];    //バナーを描画
    }
    
    // ステージの描画
    for (int j=0;j<128; j++) {
        for (int i=0; i<128; i++) {
            int mapid=MAP[j][i];
            if (mapid !=0) [[p_bmp objectAtIndex:mapid] drawAtPoint:(CGPointMake(topX+i*8,topY+j*8))];
        }
    }
    
    // man描画
    [[p_bmp objectAtIndex:7] drawAtPoint:(CGPointMake(px,py))];
    
    // man移動
    px=px+vx;
    if (px>232) {
        px=232;
        topX=topX-1;
    }
    
    if (px<80  ) {
        px=80;
        topX=topX+1;
    }
    
    pid=pid+1;
    if (vx>=0 ) { if (pid>1) pid=0; }       // 右移動のときは0と1
    if (vx<0  ) { if (pid>3) pid=2; }       // 左移動のときは2と3
    
    // Y座標
    py=py+vy;
    if (py>352) {
        py=352;
        topY=topY-1;
    }
    
    if (py<80) {
        py=80;
        topY=topY+1;
    }
}

// タイマー
-(void)onTick:(NSTimer*)timer {
    [self setNeedsDisplay];
}

// タッチパネル操作
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
    lastPoint = [[touches anyObject] locationInView:self.superview];
}

-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
    // タッチした座標を取得
    CGPoint p=[[touches anyObject] locationInView:self.superview];
    
    // X座標の移動量を算出。直前のラストポイントと今タッチした座標の差をみている。また、Y座標の移動より大きいかみている
    if (lastPoint.x-p.x<0) {
        vx=2;
    } else {
        vx=-2;
    }
    
    if (lastPoint.y-p.y<0) {
        vy=2;
    } else {
        vy=-2;
    }
    
    // さっき取得したタッチの座標をラストポイントに書き換えておく。
    lastPoint = p;
}

-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
}

-(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
    [self touchesEnded:touches withEvent:event];
}

-(void)dealloc {
    CGContextRelease(context); context=nil;
    [p_bmp release]; p_bmp=nil;
    [super dealloc];
}

@end

https://itunes.apple.com/jp/app/kumachanjanpu/id635717213?mt=8&uo=4&at=10l8JW&ct=hatenablog