DeveloperFeaturedGame DevelopmentGame DevelopmentiOS DeveloperObjective C

เขียนแอพ Game บน iPhone สร้างเกมแนว FlappyBird แบบง่าย

วิธีการเขียนเกมบน iPhone โดยไม่ใช้ Cocos2D มาเกี่ยวเลย ให้ได้เกมแนว FlappyBird แบบง่ายที่สุด ไม่ต้องใช้ Framework ในการพัฒนา พร้อม Source Code ในบทความจากบทความนี้ครับ ปิดตำนานเกมฮิต FlappyBird ถอนแอพพลิเคชันออกไปแล้ว ทำให้หลายคนเริ่มอยากจะเล่น และอยากจะรู้ว่าเกมนี้มันเขียนยากไหม ในต่างประเทศมีคนขาย Source code เจ้าเกมแนวนี้เยอะมาก ปาไป 3,000 บาทเลยแหละทั้ง Flappy Crocodile และ Flappy Penguin สำหรับ iOS Game ก็มีไอเดียการพัฒนาแยกย่อยแตกต่างไปทั้งแบบมี Framework Cocos2DX หรือไม่ใช่ ในตัวอย่างที่ผมลองไปหา Ref จากเมืองนอกมาโมครับ ก็เป็นแนวง่ายๆ

โปรเจ็คนี้ไม่ต้องเขียนด้วย Cocos2D นะครับขอย้ำ ให้เริ่มโดยการทำดังนี้

เปิด New Project ขึ้นมาใหม่เป็น Single View Application ครับ

Screen Shot 2557-02-11 at 3.35.48 PM

ตั้งชื่อเท่ๆ ของเกมเราผม ตั้งชื่อว่า FlappySuck ครับ

Screen Shot 2557-02-11 at 3.36.01 PM

วิธีการก็คือเปิดไฟล์ MainStoryBoard ขึ้นมา เลือก Control คือ View วางลงเป็นฉากก่อนนะครับ ตามด้วยพื้น ต่อมาเลือก UIImage View ครับใส่ภาพนกลงไปก่อน

Screen Shot 2557-02-11 at 3.36.21 PM Screen Shot 2557-02-11 at 3.45.07 PM

เปิดไฟล์ ViewController.h ขึ้นมาทำการ Link สร้าง IBOutlet ทุกตัวครับ UIImageView ตั้งชื่อว่า block และ View ทั้งฉากหลัง และพื้นตั้งว่า sky และ ground

#import 

@interface ViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIView *ground;
@property (strong, nonatomic) IBOutlet UIView *sky;
@property (strong, nonatomic) IBOutlet UIImageView *block;

@end

ระหว่างนั้นเรียงลำดับ Layer ของ ViewController บน MainStoryBoard ให้ดีนะครับ ตัวล่างสุดอยู่ Layer บนสุดครับ

Screen Shot 2557-02-11 at 3.44.56 PM

เปิดไฟล์ ViewController.m ขึ้นมาครับ ประกาศ Header ตามนี้

#import "ViewController.h"

@interface ViewController ()

@end
#define PIPE_SPACE 200
#define PIPE_WIDTH 75
#define DEFAULT_OFFSET 320.0
#define NEPHRITIS [UIColor colorWithRed:39.0/255 green:174.0/255.0 blue:96.0/255.0 alpha:1.0]


@implementation ViewController{
    UIView *pipeBounds;
    UIDynamicAnimator *blockAnimator;
    
    UICollisionBehavior *blockCollision;
    UICollisionBehavior *groundCollision;
    UIDynamicItemBehavior *blockDynamicProperties;
    UIDynamicItemBehavior *pipesDynamicProperties;
    UIGravityBehavior *gravity;
    UIPushBehavior *flapUp;
    UIPushBehavior *movePipes;
    int points2x;
    int lastYOffset;
    UIAlertView *gameOver;
    
    Boolean firstFlap;
}

ต่อมาไปที่ Method ของ ViewDidLoad() ครับ เพิ่ม Code ไปตามนี้ เป็นการระบุ การสร้าง พื้น Ground และ Generate ตัวท่อออกมาครับ ให้เป็นสีเขียว

- (void)viewDidLoad
{
    [super viewDidLoad];
	firstFlap = NO;
    // Create Block Animator
    blockAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    blockDynamicProperties = [[UIDynamicItemBehavior alloc] initWithItems:@[self.ground]];
    blockDynamicProperties.allowsRotation = NO;
    blockDynamicProperties.density = 1000;
    
    
    
    
    // Block flap behavior
    flapUp = [[UIPushBehavior alloc] initWithItems:@[self.block] mode:UIPushBehaviorModeInstantaneous];
    flapUp.pushDirection = CGVectorMake(0, -1.1);
    flapUp.active = NO;
    
    // Block Pipe Collision
    blockCollision = [[UICollisionBehavior alloc] initWithItems:@[self.block]];
    [blockCollision addBoundaryWithIdentifier:@"LEFT_WALL" fromPoint:CGPointMake(-1*PIPE_WIDTH, 0) toPoint:CGPointMake(-1*PIPE_WIDTH, self.view.bounds.size.height)];
    blockCollision.collisionDelegate = self;
    
    // Block Ground Collision
    groundCollision = [[UICollisionBehavior alloc] initWithItems:@[self.block, self.ground]];
    groundCollision.collisionDelegate = self;
    
    [blockAnimator addBehavior:blockDynamicProperties];
    
    [blockAnimator addBehavior:flapUp];
    [blockAnimator addBehavior:blockCollision];
    [blockAnimator addBehavior:groundCollision];
    
    // Create Pipes Animator
    points2x = 0;
    lastYOffset = -100;
    
    UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(TapEvenntGesture:)];
    [self.view addGestureRecognizer:singleTapGestureRecognizer];
    [singleTapGestureRecognizer setNumberOfTapsRequired:1];
}

โดย Code ส่วนนั้นจะเกี่ยวข้องกับ การสร้างท่อ หรือ Pipe ดังนี้ครับ

- (void)getPipeGame:(float)xOffset {
    lastYOffset = lastYOffset +  (arc4random_uniform(3)*40) * getRand();
    lastYOffset = (lastYOffset < -200)?-200:lastYOffset;
    lastYOffset = (lastYOffset > 0)?0:lastYOffset;
    
    UIView *topPipe = [[UIView alloc] initWithFrame:CGRectMake(xOffset, lastYOffset, PIPE_WIDTH, 300)];
    [topPipe setRestorationIdentifier:@"TOP"];
    [topPipe setBackgroundColor:NEPHRITIS];
    
    [self.view addSubview:topPipe];
    UIView *bottomPipe = [[UIView alloc] initWithFrame:CGRectMake(xOffset, lastYOffset+topPipe.bounds.size.height+PIPE_SPACE, PIPE_WIDTH, 300)];
    [bottomPipe setRestorationIdentifier:@"BOTTOM"];
    [bottomPipe setBackgroundColor:NEPHRITIS];
    [self.view addSubview:bottomPipe];
    
    pipesDynamicProperties= [[UIDynamicItemBehavior alloc] initWithItems:@[topPipe, bottomPipe]];
    pipesDynamicProperties.allowsRotation = NO;
    pipesDynamicProperties.density = 1000;
    
    [blockCollision addItem:topPipe];
    [blockCollision addItem:bottomPipe];
    
    // Push Pipes across the screen
    movePipes = [[UIPushBehavior alloc] initWithItems:@[topPipe, bottomPipe] mode:UIPushBehaviorModeInstantaneous];
    movePipes.pushDirection = CGVectorMake(-2800, 0);
    movePipes.active = YES;
    
    [blockAnimator addBehavior:pipesDynamicProperties];
    [blockAnimator addBehavior:movePipes];
}

อ้างอิงโดยการสุ่มการสร้างในเมธอด getRand()

int getRand() {
    return (arc4random() % 2 ? 1 : -1);
}

ต่อมาเพิ่ม code ส่วนของ Event เมื่อมีการแตะหน้าจอครับ ให้นกกระเด้งขึ้น

- (void) TapEvenntGesture:(UITapGestureRecognizer *)gestureRecognizer {
    if (!firstFlap) {
        // Block gravity
        gravity = [[UIGravityBehavior alloc] initWithItems:@[self.block]];
        gravity.magnitude = 1.1;
        [blockAnimator addBehavior:gravity];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
            if (!gameOver.isHidden)[self getPipeGame:DEFAULT_OFFSET];
        });
        firstFlap = YES;
    }
    [flapUp setActive:YES];
}

พิจารณาหากแตะแล้วไม่ต่อเนื่อง นกจะร่วงตาม Gravity ของสูตรนี้

if (!firstFlap) {
        // Block gravity
        gravity = [[UIGravityBehavior alloc] initWithItems:@[self.block]];
        gravity.magnitude = 1.1;
        [blockAnimator addBehavior:gravity];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
            if (!gameOver.isHidden)[self getPipeGame:DEFAULT_OFFSET];
        });
        firstFlap = YES;
    }

ต่อมาถ้านก ร่วงชนพื้นหรือ ชนท่อก็ให้ใช้ หลักการนี้ครับ Collision Detect ตัวโปรแกรมใส่ลงไป

- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id)item withBoundaryIdentifier:(id)identifier atPoint:(CGPoint)p {
    if ([(NSString*)identifier isEqualToString:@"LEFT_WALL"]) {
        points2x++;
        [blockCollision removeItem:item];
        [blockAnimator removeBehavior:pipesDynamicProperties];
        [blockAnimator removeBehavior:movePipes];
        if (points2x%2 == 0) [self getPipeGame:DEFAULT_OFFSET];
    }
}
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id)item1 withItem:(id)item2 atPoint:(CGPoint)p {
    [blockAnimator removeAllBehaviors];
    gameOver = [[UIAlertView alloc] initWithTitle:@"มีความพยายาม" message:@"แต่ก็ยัง อ่อนหัด" delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
    [gameOver show];
}

ตั้งค่าเกมไม่ให้มี การ พลิกหน้าจอเกม แนวตั้ง แนวนอน ให้เป็นแนวตั้งอย่างเดียว

- (BOOL)shouldAutorotate {
    return NO;
}

ลองทดสอบ รันเกมของเราดูครับ โดยการ “Run”

เริ่มเกม
เริ่มเกม
ร่วง ตายห่า
ร่วง ตายห่า
ท่อโผล่มา
ท่อโผล่มา
เกม Over
เกม Over

ตัวอย่าง Source Code ตัว Project นี้ครับดาวน์โหลดที่นี่ครับ http://adf.ly/dPtAP

Ref: FlappyBlock, Cocos2D Resource

Asst. Prof. Banyapon Poolsawas

อาจารย์ประจำสาขาวิชาการออกแบบเชิงโต้ตอบ และการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ผู้ก่อตั้ง บริษัท Daydev Co., Ltd, (เดย์เดฟ จำกัด)

Related Articles

Back to top button

Adblock Detected

เราตรวจพบว่าคุณใช้ Adblock บนบราวเซอร์ของคุณ,กรุณาปิดระบบ Adblock ก่อนเข้าอ่าน Content ของเรานะครับ, ถือว่าช่วยเหลือกัน