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

Adblock Detected

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