พัฒนาเกมลง iOS ด้วย Swift และ SpriteKit ตอนที่ 4 โหลดภาพ Sprite

ในบทความตอนนี้จะพูดถึงการโหลดภาพหรือ Sprite ให้แสดงผลบนหน้าจอ โดยก่อนอื่นจะต้องทำความเข้าในเรื่องพิกัด หรือจุด ที่จะแสดงผลบนหน้าจอไอโฟนหรือไอแพด เนื่องจากว่าขนาดหน้าจอของแต่ละเครื่องไม่เท่ากัน ความละเอียดของหน้าจอก็ไม่เท่ากัน

ดังนั้น ก่อนอื่นมาทำความรู้จักกับขนาดหน้าจอของไอโฟนและไอแพดแต่ละรุ่นกันก่อน
หลัก ๆ จะมีคำสองคำที่เกี่ยวข้องคือ Resolution และ Logical Resolution

Resolution ก็คือจำนวน Pixel ทั้งหมดที่ใช้แสดงผลนั่นเอง เช่น ถ้ามี Resolution 320 x 480 pixels ก็หมายความว่าหน้าจอนั้นมีจำนวนพิกเซลทั้งหมด 320 คูณ 480 เท่ากับ 153,600 พิกเซล นั่นเอง

Logical Resolution หรือเราจะเรียกว่าเป็น Point ซึ่งในอุปกรณ์ที่มีความละเอียดสูง 1 Point จะมีหลายพิกเซล  ตัวอย่างเช่น 1 Point มี 4 พิกเซล ดังนั้นการที่บอกว่า 320 x 480 points หมายความว่ามี 153,600 points หรือมีทั้งหมด 153,600 x 4 = 614,400 pixels นั่นเอง

ในการเขียนเกมบน iOS โดยใช้ SpriteKit นั้น พิกัด หรือ จุด ที่ใช้ในการเขียนโปรแกรมเพื่ออ้างอิงจะใช้แบบ Point โดยอุปกรณ์ในแต่ละรุ่นมีขนาดที่แตกต่างกันไป ซึ่งมีบทความที่รวมขนาดของไอโฟนและไอแพดทั้งหมดไว้แล้ว (http://www.ajmontri.com/121)

ในการเตรียมภาพกราฟิกสำหรับเกมบน iOS จะมี 3 แบบด้วยกัน คือ 1x, 2x และ 3x
ทั้ง 3 แบบ แตกต่างกันอย่างไรนั้น อธิบายได้ดังนี้
สำหรับแบบ 1x คือ ถ้าหน้าจอขนาด 320 x 568 points กราฟิกที่เตรียมก็เป็นขนาด 320 x 568 pixels
สำหรับแบบ 2x คือ ถ้าหน้าจอขนาด 320 x 568 points กราฟิกที่เตรียมก็เป็นขนาด 640 x 1136 pixels
สำหรับแบบ 3x คือ ถ้าหน้าจอขนาด 320 x 568 points กราฟิกที่เตรียมก็เป็นขนาด 960 x 1704 pixels

สำหรับ iPhone 6 Plus จะไม่เหมือนใคร ถ้าสังเกตขนาดหน้าจอดี ๆ จะมีความแปลก คือ ขนาด Logical Resolution เป็น 414 x 736 points ถ้าประมวลภาพที่ 3x ขนาดพิกเซลน่าจะเป็น 1242 x 2208 pixels แต่ขนาดของอุปกรณ์จริงเป็น 1080 x 1920 pixels เท่ากับว่าจะลดสเกลลง 1.15 เท่านั่นเอง  ไม่ต้องสนใจเพราะในโปรแกรมก็จะไปดึงรูปขนาด 3x มาแสดงผลเหมือนเดิมและทำการลดสเกลให้เองตามสัดส่วน

เมื่อเราทราบเรื่องความละเอียดของหน้าจอ พิกัด จุด เรียบร้อยแล้ว ก่อนที่เราจะเริ่มเขียนโปรแกรมโหลด Sprite เราก็มาเตรียมรูป หรือ Sprite ที่จะใช้แสดงผล สมมติในตัวอย่างนี้มีรูปปลาทอง เราจะเตรียมไฟล์ 3 รูป เพื่อให้รองรับกับทั้งแบบ 1x, 2x และ 3x โดยที่รูปที่เป็นแบบ 1x ขนาด 120 x 120 pixels โดยตั้งชื่อไฟล์ว่า GoldFish@1x.png ดังรูปที่ 1, รูปแบบที่เป็นแบบ 2x ขนาด 240 x 240 pixels โดยตั้งชื่อไฟล์ว่า GoldFish@2x.png ดังรูปที่ 2 และแบบที่เป็น 3x ขนาด 360 x 360 pixels โดยตั้งชื่อไฟล์ว่า GoldFish@3x.png ดังรูปที่ 3

รูปที่ 1 GoldFish@1x.png

รูปที่ 2 GoldFish@2x.png

รูปที่ 3 GoldFish@3x.png

จากข้างต้นการตั้งชื่อไฟล์ที่ต่อท้ายด้วย @1x, @2x, @3x มีความสำคัญตรงที่ เมื่อเรานำรูป 3 รูปนี้เข้าไปในโปรเจค ทั้ง 3 รูปจะใช้เรียกในชื่อเดียวกันคือ GoldFish เท่านั้น ส่วนจะไปดึงรูปไหนแสดงผลจริง ก็ขึ้นกับว่ารันด้วยอุปกรณ์ไอโฟนหรือไอแพดรุ่นไหนนั่นเอง

เริ่มต้นสร้างโปรเจค สมมติตั้งชื่อโปรเจค LoadSprite ดังรูปที่ 4-5

รูปที่ 4 สร้างโปรเจคใหม่

รูปที่ 5 ตั้งชื่อโปรเจค LoadSprite

เมื่อสร้างโปรเจคแล้ว นำรูปปลาทองทั้งสามรูปเข้าไปไว้ใน Assets.xcassets ดังรูปที่ 6 ซึ่งจะเห็นว่าทั้งสามรูปจะรวมเป็นชื่อ Asset เดียวกันคือชื่อ GoldFish

รูปที่ 6 โหลดรูปเข้าโปรเจค

จากนั้นให้เลือกที่ GameScene.sks แล้วลบ hellolabel ออก และปรับค่า Anchor Point x และ y ให้เป็น 0 ดังรูปที่ 7 เพื่อให้จุดอ้างอิงอยู่มุมซ้ายล่าง (นั่นคือจุด (0,0) อยู่มุมซ้ายล่าง)

รูปที่ 7 ปรับ Anchor Point เป็น (0,0)

จากนั้นลบคำสั่งต่าง ๆ ให้เหลือ ดังรูปที่ 8

รูปที่ 8 ลบคำสั่งเดิมออก

จากนั้นประกาศตัวแปร goldFish เป็นชนิด SKSpriteNode และใส่เครื่องหมาย ! เพื่อเป็นการ Unwrapping optional (ไว้อธิบายในบทความต่อ ๆ ไป) ดังนี้

var goldFish: SKSpriteNode!

เพิ่มคำสั่งแสดงผลรูปปลาทองให้อยู่กลางหน้าจอ ดังนี้ ในฟังก์ชัน didMove()

goldFish = SKSpriteNode(imageNamed: “GoldFish”)
goldFish.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
self.addChild(goldFish)

โดยคำสั่งบรรทัดแรกเป็นการกำหนดค่าให้กับตัวแปร goldFish โดยดึงจากรูป GoldFish
บรรทัดที่สองเป็นการกำหนดตำแหน่งแสดงผลรูปปลาทองที่กึ่งกลางหน้าจอ
และบรรทัดที่สามเป็นการทำเอา goldFish ไปแสดงผลออกหน้าจอ

ซึ่งคำสั่งทั้งหมดในไฟล์ GameScene.swift จะเป็นดังนี้

//
//  GameScene.swift
//  LoadSprite
//
//  Created by Aj.Montri on 11/11/2560 BE.
//  Copyright © 2560 ajmontri.com. All rights reserved.
//

import SpriteKit
import GameplayKit

class GameScene: SKScene {
    
    var goldFish: SKSpriteNode!
    
    override func didMove(to view: SKView) {
        
        goldFish = SKSpriteNode(imageNamed: "GoldFish")
        goldFish.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
        self.addChild(goldFish)
    }
    
    override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered
    }
}

 

เมื่อรันด้วย Simulator iPhone 8 จะได้ผลลัพธ์ดังรูปที่ 9

รูปที่ 9 ผลลัพธ์

เป็นอันว่าเรียบร้อยสำหรับการโหลดภาพ Sprite อย่างง่าย

 

วิดีโอประกอบบทความ

 

Aj.Montri