Article for GamerBeginningDeveloperFeaturedGame DevelopmentGame DevelopmentiOS DeveloperNewbieObject Oriented TechnologyObjective COpen Source GameProgramming Language

สร้างเกมบน iPhone ด้วย Sprite Kit สำหรับ 2D Game ตอนที่ 3

วิธีการพัฒนาเกมบน iPhone ด้วย Sprite Kit ตอนที่ 3 กับการสร้างกระสุนในเกม Shooting ให้ยิงใส่ศัตรูเพื่อศึกษา การทำงานของ Collision Detect ในเกมครับ

จากบทความก่อนหน้านี้ เราจะเรียนรู้วิธีสร้างเกม 2D แนว Shooting มาบ้างแล้ว หากสงสัยกลับไปอ่านก่อนนะครับที่บทความนี้

ภาพจากบทความที่แล้ว
ภาพจากบทความที่แล้ว

ถ้าไม่มีข้อสงสัยแล้วก็มา เพิ่มการยิงกระสุน กับศึกษา Collision Detect กันครับ

แก้ไขส่วนบนสุดของ MyScene.m ของเราให้เป็นดังนี้ครับ (สังเกตุดีดี)

@interface MyScene()<SKPhysicsContactDelegate>
@end

@implementation MyScene

เมื่อแก้ไขแล้วให้ เพิ่ม Code ประกาศ Static Variable ใต้

@implementation MyScene

ตามนี้ครับ

static inline CGPoint rwAdd(CGPoint a, CGPoint b) {

    return CGPointMake(a.x + b.x, a.y + b.y);

}

static inline CGPoint rwSub(CGPoint a, CGPoint b) {

    return CGPointMake(a.x - b.x, a.y - b.y);

}

static inline CGPoint rwMult(CGPoint a, float b) {

    return CGPointMake(a.x * b, a.y * b);

}

static inline float rwLength(CGPoint a) {

    return sqrtf(a.x * a.x + a.y * a.y);

}

// Makes a vector have a length of 1

static inline CGPoint rwNormalize(CGPoint a) {

float length = rwLength(a);

return CGPointMake(a.x / length, a.y / length);

}

เมื่อได้กำหนดค่าของ Physics ที่กระสุนจะไปแล้ว ก็ได้เวลาสร้างเมธอดของการยิง เมื่อแตะทัชหน้าจอครับ

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

    UITouch * touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];

    SKSpriteNode * projectile = [SKSpriteNode spriteNodeWithImageNamed:@"projectile"];
    projectile.position = self.player.position;

    CGPoint offset = rwSub(location, projectile.position);

    if (offset.x <= 0) return;

    [self addChild:projectile];

    CGPoint direction = rwNormalize(offset);

    CGPoint shootAmount = rwMult(direction, 1000);

    CGPoint realDest = rwAdd(shootAmount, projectile.position);

    float velocity = 480.0/1.0;
    float realMoveDuration = self.size.width / velocity;
    SKAction * actionMove = [SKAction moveTo:realDest duration:realMoveDuration];
    SKAction * actionMoveDone = [SKAction removeFromParent];
    [projectile runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];

}

กำหนดตำแหน่งเมื่อเกิดการแตะที่หน้าจอให้เป็นจุดหมายของกระสุนที่

CGPoint direction = rwNormalize(offset);

ต่อมาก็มาปรับเรื่องของ Coliision Detect ครับ เมื่อกระสุนเรา ยิงไปโดนศัตรู จะเกิดเหตุการณ์ขึ้นครับ

แก้ไขข้อมูล MyScene.m ส่วนบทสุดดังนี้ครับ

#import "MyScene.h"

static const uint32_t projectileCategory     =  0x1 << 0;
static const uint32_t monsterCategory        =  0x1 << 1;

ใส่คำสั่งเล็กน้อยเกี่ยวกับ Physics และ Vector ในการยิงไปโดนที่ initWithSize()

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {

        self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
        self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player2"];
        self.player.position = CGPointMake(100,CGRectGetMidY(self.frame));

        self.physicsWorld.gravity = CGVectorMake(0,0);
        self.physicsWorld.contactDelegate = self;

        [self addChild:self.player];
    }
    return self;
}

เพิ่มการกระทำ เมื่อโดนศัตรูของเรา โดยคำสั่งต่อไปนี้ ในเมธอด addMonster()

    monster.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:monster.size]; 
    monster.physicsBody.dynamic = YES;
    monster.physicsBody.categoryBitMask = monsterCategory; 
    monster.physicsBody.contactTestBitMask = projectileCategory; 
    monster.physicsBody.collisionBitMask = 0;

ทำการจำขนาดของ monster เป็น Rectangle จดจำค่า projectile หรือกระสุน ไว้ และจำค่า monster หรือศัตรูไว้ให้รู้ว่า Object 2 ตัวนี้เกี่ยวข้องกัน

ต่อไปคือ การเพิ่มคำสั่ง CollisionDetection ในเมธอด touchesEnded:withEvent()

หาภาพกระสุนมาชื่อว่า fire.png

fire,png
fire,png
SKSpriteNode * projectile = [SKSpriteNode spriteNodeWithImageNamed:@"fire"];

projectile.position = self.player.position;
projectile.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:projectile.size.width/2];
projectile.physicsBody.dynamic = YES;
projectile.physicsBody.categoryBitMask = projectileCategory;
projectile.physicsBody.contactTestBitMask = monsterCategory;
projectile.physicsBody.collisionBitMask = 0;
projectile.physicsBody.usesPreciseCollisionDetection = YES;

เมื่อเกิดการกระทับกันให้ NSLog ขึ้นมาว่า “Hit” ครับ แล้วทำการเคลียร์ตัวแปรของศัตรูที่บินไปมาออกไปจากหน้าจอทันที

- (void)projectile:(SKSpriteNode *)projectile didCollideWithMonster:(SKSpriteNode *)monster {

    NSLog(@"Hit");
    [projectile removeFromParent];
    [monster removeFromParent];
    self.monstersDestroyed++;
    if (self.monstersDestroyed > 10) {

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Finish!" message:@"Play Again?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
        // optional - add more buttons:
        [alert addButtonWithTitle:@"OK"];
        [alert show];
    }

}

เพิ่มเงื่อนไขมาว่าถ้าเราโจมตีศัตรูได้มากกว่า 10 ตัวให้มีการเรียก UIAlertView ขึ้นมาบอกว่าเราผ่านด่านแล้วครับ

เปิดไฟล์  MyScene.h ขึ้นมา เพิ่มคำสั่งต่อไปนี้ลงไปเพื่อเตรียมพร้อมสำหรับการเล่นใหม่ในแต่ละครั้งเมื่อจบเกม

#import <SpriteKit/SpriteKit.h>

@interface MyScene : SKScene

@property (nonatomic) SKSpriteNode * player;

@property (nonatomic) NSTimeInterval lastSpawnTimeInterval;
@property (nonatomic) NSTimeInterval lastUpdateTimeInterval;
@property (nonatomic) int monstersDestroyed;

@end

ทำการ Synthesize ตัวแปรที่เพิ่มเข้าไปที่ MyScene.m ครับ

@synthesize player;

@synthesize lastSpawnTimeInterval;
@synthesize lastUpdateTimeInterval;
@synthesize monstersDestroyed;

เพิ่มเมธอดสำหรับเริ่มเกมใหม่ลงไปครับ didBeginContact()

 

- (void)didBeginContact:(SKPhysicsContact *)contact
{
     SKPhysicsBody *firstBody, *secondBody;

    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA;
        secondBody = contact.bodyB;
    }
    else
    {
        firstBody = contact.bodyB;
        secondBody = contact.bodyA;
    }

    if ((firstBody.categoryBitMask & projectileCategory) != 0 &&
        (secondBody.categoryBitMask & monsterCategory) != 0)
    {

       [self projectile:(SKSpriteNode *) firstBody.node didCollideWithMonster:(SKSpriteNode *) secondBody.node];
    }

}

ทดสอบเกมของเราอีกครั้งโดยการ Run แล้วลอง ยิงกระสุนใส่ศัตรูสัก 10 ตัวดูครับ จะพบว่าเกม Shooting แบบง่ายของเรานั้นเสร็จสมบูรณ์แล้ว เอาไปอวดเพื่อนได้เลย!

iOS Simulator Screen shot Mar 18, 2557 BE, 12.46.55 PM

Source Code ของ Project นี้ดาวน์โหลดได้ที่:  http://adf.ly/gS6vt

บทความที่เกี่ยวข้อง

Asst. Prof. Banyapon Poolsawas

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

Related Articles

Back to top button
Game & Mobile Development AR VR XR
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.

Adblock Detected

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