พัฒนาเกมลง 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