Translate

วันอังคารที่ 13 สิงหาคม พ.ศ. 2556

ปัญหาการแสดงผลของ zoom control ใน google map version 3 บน web

ใครเคยพบปัญหานี้บ้างครับ ตัว zoom control ใน map ที่เรานำมาใช้บน web เกิดการแสดงผล error ขึ้นมา


หลังจากค้นดูสักพัก ก็มีคนพบปัญหาเดียวกันเยอะอยู่ครับ นั่นเป็นเพราะรูปภาพสำหรับแสดง zoom control มีค่า max-width : 100% นั่นเอง ทางแก้ก็ใช้ CSS Override มันครับ ดังนี้

เพิ่ม <style>#map_canvas img{ max-width:none; }</style> ไว้ด้านบนของ <div id="map_canvas"></div> ซะ เท่านี้ก็เรียบร้อย การแสดงผลก็จะกลับมาเหมือนเดิมที่ควรจะเป็นล่ะ แต่ถ้าใครไม่ได้ อย่าลืม! ว่า ชื่อ id div ของ map canvas ถูกต้องนะครับ ^__^


วันศุกร์ที่ 2 สิงหาคม พ.ศ. 2556

คำแนะนำจาก Amazon app store

วันนี้กลับไปอ่านเมล์เก่าๆ ของตัวเอง ก็เจอเมล์หนึ่ง ที่ส่งมาจาก amazon เนื่องจากผมต้องการนำแอพ android ขึ้นที่ store ของเขา สมัยทำขึ้น google play ก็ไม่มีใครมา approve ให้แบบนี้ รู้สึกดีเลยอยากแนะนำ เพื่อนๆ ที่ทำแอพขึ้น play store ว่า ถ้าอยากปรับปรุงแอพของตน เพื่อเพิ่มคุณภาพเบื้องต้นล่ะก็ ลองเอาขึ้น amazon ดูครับ

คำแนะนำของแอพ Thai Pilot Pray ที่เขาให้มีดังนี้


Thank you for your recent submission of Thai Pilot Pray. It requires your immediate attention due to the following reason(s):

Issue 1:

When pointing to other apps or websites from within your app, including up-sells, ratings, version updates, or upgrades, our published policy calls for the completion of purchase to be from Amazon.

Steps to reproduce this issue as it appears in this app:

1. Install and launch the app.
2. Tap on second option.
3. Tap on G-mail.
4. The mail has Google Play link.

To point to a specific app, the Download URL must be http://www.amazon.com/gp/mas/dl/android?p=[packagename] (where [package name] is your package name). The link will become active when the app is live in our store. If you want to link to the list of all your applications on Amazon use the URL http://www.amazon.com/gp/mas/dl/android?p=[packagename]&showAll=1.

Issue 2:

Your app has failed a test case.

Bug Description: Call interrupt fail
Steps to Reproduce:

1. Install and launch the app.
2. Tap on first option.
3. Select any option.
4. Tap on Play.
5. Make an incoming call.
6. Audio is heard in the back ground during the call.

OS/Device(s): 4.0.X/HTC


Please correct the issue(s) we found with your app submission.

After you have made the updates, you may re-submit a new version of the app, along with any metadata updates (small icon, large icon, screenshots, descriptions, etc.) using the AmazonMobile App Distribution Portal.

If you have any questions about your app, please use the Contact Us link in your Distribution Portal account: https://developer.amazon.com/help/contact-us.html.


Sincerely, 


Your Amazon Mobile App Distribution Team

-----------------------------

โดยปัญหาที่ 2 เป็นอะไรที่ผมไม่ได้ test จริงๆ ครับ เพราะลืมคิดเกี่ยวกับเรื่องนั้นไปเลย ก็นับว่าเป็นการ review ที่ดีในการ develop ได้เลย

แต่ถึงสุดท้ายผมจะแก้ แต่ผมก็ไม่อัพขึ้น amazon หรอกนะครับ ก็อัพขึ้น play ตามปกติเนี่ยล่ะ

วันจันทร์ที่ 17 มิถุนายน พ.ศ. 2556

พัฒนาเกม RPG บน android ด้วย AndEngine (2)


ในบทความตอนนี้ เราจะมาสร้างเกมเล็กๆ แบบในรูปข้างบนนี้ด้วย AndEngine กันครับ

ห่างหายไปนานมาก จากตอนที่แล้ว เนื่องด้วยผู้เขียนกำลังอ่อนแรง แต่ในเมื่อยังไม่ตาย ก็ต้องสู้ๆ ต่อไปล่ะนะ

ตอนที่แล้วผมเกริ่นเกี่ยวกับ AndEngine ไว้พอประมาณ และให้ load source code ลองไปศึกษากันดู ถ้ายังไม่มีก็ที่นี้เลยครับ http://pilotpol.blogspot.com/2013/05/rpg-android-andengine-1.html

ส่วนตอนนี้ก็จะอธิบายตามความเข้าใจของตนเอง เกี่ยวกับ Game Engine อันนี้ และการเขียนบน Android Platform แบบ Step by Step ตั้งแต่เริ่มต้นเลยก็แล้วกัน

1. เริ่มแรกก่อน ถ้าจะเขียน app อะไรสักอย่างบน android แบบ native ล่ะก็ ก็ต้องไป download AndroidSDK มาก่อน ถึงตรงนี้ทุกท่านที่ต้องการหา GameEngine สักตัวน่าจะมี และได้ลองเขียน HelloAndroid กันแล้ว ถ้ายังไม่มีก็ตรงนี้ได้ครับ http://pilotpol.blogspot.com/2013/05/android-thai-pilot-pray-2.html

2. หลังจากมี Android Developer Tools แล้ว และพอจะรู้หลักในการเขียน android แบบทั่วไปแล้ว (เรื่องเขียนไม่มีไรมากครับ ไปที่สร้าง project ใหม่ แล้วให้มันสร้างเป็นแนวทางให้ก็ได้) ต่อไปก็เตรียมตัวเรียนรู้ Engine ตัวนี้กันเลย !

บอกไว้ก่อนว่าผมไม่ได้อ่านจาก Cookbook ของ AndEngine โดยตรง เพราะฉะนั้นจึงอาจจะตกหล่นไปบ้าง และไม่ถูกหลักเท่าไร แต่ก็สามารถสร้างเกมตามต้องการได้ล่ะนะ

เริ่มจาก Download Library ของ AndEngine มา ตรงนี้ก็จะมีอยู่ 2 แบบ แล้วแต่ชอบ

  1. Download Source code มาเลยแล้วมาเปิด Project ใน Package Explorer ที่นี้พอเวลาสร้าง game ของเราเอง เราก็ต้องเรียกหาที่อยู่ของบรรดา Project AndEngine ทั้งหลายทุกครั้ง หาได้จากตรงนี้ครับ https://github.com/nicolasgramlich/AndEngine
  2. Download เฉพาะ Library ที่เป็นไฟล์ *.jar ไปวางไว้ที่ folder lib ภายใต้ project อันนี้ผมรวบรวมไว้ให้และมีแก้ไขเล็กน้อยเพื่อใช้สำหรับ project RPG ของผมเอง ตรงนี้ครับ https://docs.google.com/file/d/0B_raxIdscReBRnFMY05tR1daNms/edit?usp=sharing
แบบที่ 1 จะดีตรงที่ว่า เราสามารถแก้ไขไฟล์ต้นฉบับได้ตามใจชอบเลย ตรงไหนไม่มีอะไรก็เขียนแก้ไปเลย แต่ถ้าใครไม่ต้องการจะไปแก้อะไรเขาอยู่แล้ว จะเขียนด้วยความสามารถที่มีของ AndEngine เองก็ใช้แบบที่ 2 ก็ไม่ยุ่งยากดีครับ

ในที่นี้จะเอาง่ายๆ ไว้ก่อน ก็จะอธิบายเฉพาะแบบที่ 2 ก็แล้วกันนะครับ

มาเริ่มโปรเจ็คเล็กๆ กันเลยครับ

1. ไปที่ New > Android Application Project
ตั้งชื่อ app ชื่อ project ตามใจชอบได้เลยครับ แล้วก็ชื่อ package name ใครยังไม่ชำนาญ ก็ตั้งตามตัวอย่างไปก่อนก็ได้ครับ จากนั้นมาเลือก 4 ช่องล่าง ตามใจชอบอีกเช่นกัน สำหรับในตัวอย่าง ผมให้ app รองรับต่ำสุดที่  Android 2.3 เลือกรุ่นเป้าหมายคือ Android 4.0 เลือกตัวที่จะมา Compile Code คือ Android 4.2 และ Theme เป็นค่า default ของมันครับ จากนั้นกด Next > โลด...


 2. ลำดับถัดไปจะขึ้น Dialog หน้านี้ ก็ติ๊กถูกตามที่ Default มีอยู่แล้วอ่ะครับ จะได้ไม่ยุ่งยาก
กด Next > ต่อไปเลยครับ


 3. แล้วจะมาหน้า Auto Generate Icon เราก็ปรับปรุงหน้าตา Icon ของ App เราเสียหน่อยครับ จะได้เป็นเอกลักษณ์ เวลาอยู่ใน App drawer แล้ว จะได้รู้ว่านี่เราเขียนเองนะ
ปรับแต่ง Icon ตามชอบใจได้เลยครับ เสร็จเรียบร้อย กด Next >


 4. จะขึ้น Dialog มาถามเรื่อง Create Activity ใครไม่รู้ว่า Activity คืออะไร ไปอ่านก่อนได้ที่นี่นะครับ http://pilotpol.blogspot.com/2013/05/android-thai-pilot-pray-4.html ส่วนใครชำนาญในการสร้าง Hello Android แล้วก็ไปต่อกันได้เลย
หน้านี้ก็ตาม Default มันเลยครับ เลือก Blank Activity แล้วกด Next >


 5. หน้านี้จะให้ตั้งชื่อ Activity หลักของ App เราครับ พร้อมกับชื่อ Layout หลัก ก็ใส่ตามใจชอบได้เลยครับ แต่ข้อสำคัญคือ ชื่อ Activity Name ขอให้ใส่ตัวใหญ่นำหน้า ส่วนที่ Layout Name ใส่อะไรก็ได้ครับ เพราะเราไม่ได้ใช้อยู่แล้ว
เสร็จแล้วครับ กด Finish ได้เลย


 6. เราก็จะได้ App มาแล้ว 1 App เปล่าๆ ตอนนี้ก็สามารถ Run as ดูผลงานได้แล้วนะครับ แต่ใจเย็นครับ เพราะจุดประสงค์เราคือ จะใช้ AndEngine นั่นเอง


 7. มาถึงพระเอกของเราแล้วครับ ซึ่งอย่างที่บอกไว้ข้างต้นว่า ผมจะแนะนำการใช้งาน AndEngine แบบ Include Library jar มาในตัว Project เลย เพื่อความไม่ยุ่งยากในการอธิบายครับ เริ่มต้นจาก Download Lib ทั้งหลายจาก link นี้ก่อน https://docs.google.com/file/d/0B_raxIdscReBRnFMY05tR1daNms/edit?usp=sharing

จะได้เป็นไฟล์ Zip นะครับ นำไฟล์ Zip ไปวางไว้ใน folder libs ใน Project ครับ แล้วแตกไฟล์ออกที่นั่น (ตอนแตกไฟล์ อาจจะมีซ้ำอันหนึ่งนะครับ เป็น android-support-v4.jar ซึ่ง จะเลือกให้ทับไป หรือไม่ทับก็ได้ครับ)

เสร็จสรรพแล้ว ภายใน folder libs ของ Project เรา ควรจะมีไฟล์หน้าตาประมาณนี้นะครับ
พวกนี้เป็นไฟล์ lib ของ AndEngine ทั้งหมดครับ ซึ่งในตัวอย่างก็ไม่ได้ใช้หมดหรอกครับ ใครจะลบออกให้เหลือเฉพาะที่ใช้ก็ได้นะครับ


 8. ได้ AndEngine กันแล้ว จริงๆ ก็เริ่มเขียน Code กันได้เลย แต่ว่าในตัวอย่างที่จะเขียนให้ดูนี้ ผมจะใช้งานภาษาไทยด้วยครับ ดังนั้นผมก็จะเพิ่มเติมในเรื่อง font หน่อยครับ

เริ่มแรกที่ folder assets ภายใต้ Project ของเรานะครับ (อันนี้ของผมเป็น helloAndEngine) สร้าง folder font ขึ้นมาตามรูปครับ แล้วไปหา font อะไรก็ได้มาวางไว้ครับ นามสกุลเป็น .ttf นะครับ

หรือถ้าจะสนับสนุนของ DroidSans แบบผม ก็ไป Download มาได้เลยครับ ที่นี่ http://www.nuuneoi.com/blog/blog.php?read_id=296 ต้องขอขอบคุณ คุณ NuuNeoI เจ้าของ font มา ณ โอกาสนี้ด้วยครับ (ผมไม่รู้จักเป็นการส่วนตัวกะเขาหรอกนะครับ)
Dowload font มาลงที่ Folder font แล้วก็ยังเหลือ รูปภาพตัวละครของเราครับ ดูข้อต่อไปกันเลย


 9. เรื่องตัวละคร ถ้าใครเคยศึกษาเกี่ยวกับเกมมาบ้างก็จะพอเข้าใจว่า รูปภาพที่เห็นเคลื่อนไหวนั้น สำหรับเกม 2D ก็จะเป็นการสลับรูปวนไปมาเรื่อยๆ นะครับ คล้ายๆ กับภาพ gif นั่นแหละ แต่ในที่นี้เราจะใช้ไฟล์ภาพแบบ package ที่เรียกว่า animation sprite ครับ เป็นภาพใหญ่ๆ ที่มีรูปแบบการเคลื่อนไหวต่างๆ แล้วมาตัดเอาแสดงผลอีกทีในเกม คลิกขวาแล้ว Save as... รูปด้านล่างนี้ได้เลยครับ



สร้าง Folder gfx ภายใต้ assets ตามภาพด้านล่างนี้ครับ จากนั้น Copy ไฟล์ภาพตัวละครด้านบน ไปวางไว้ที่ Folder นั้น โดยตั้งชื่ออะไรก็สุดแล้วแต่ครับ ของผมตั้งเป็น player แต่นามสกุลเป็น png นะครับ
ที่นี่เราก็จะได้หน้าตาของ Project เป็นแบบนี้ครับ ภายใต้ assets มี fonts และ gfx ส่วน libs ก็มี ไฟล์ jar ของ AndEngine อยู่แล้ว



 10. จากนั้นมาดูกันต่อในส่วน Code ครับ จากรูปด้านล่าง ผมแสดงให้เห็นว่า ส่วนประกอบโครงสร้างของการเริ่ม Project ของ AndEngine มีอะไรสำคัญๆ บ้างครับ ตอนนี้เปิดไฟล์ *.java ที่อยู่ภายใต้ src > ชื่อ package ขึ้นมานะครับ อันนี้เป็นไฟล์หลักและในตัวอย่างจะเขียนที่ไฟล์นี้ไฟล์เดียวครับ
ใครที่ตั้งชื่ออื่น ก็จะไม่เหมือนกันนะครับ


11. ใน Code ให้ลบ Activity หลัง extends ออกไปเลยครับ แล้วก็ Code ข้างในด้วย เพราะเราจะเปลี่ยนมาใช้ Code แบบด้านล่างแทน
เราเรียก extends SimpleBaseGameActivity แทนการเรียกใช้ Activity ตามแบบแอพทั่วไปครับ และภายใน Class ก็จะต้องเรียก Method 3 ตัวตามกรอบสีแดงครับ อธิบายได้ดังนี้นะครับ
  1. onCreateEngineOptions() เป็นตัวสร้างสภาพแวดล้อมเริ่มต้นของ AndEngine ให้กับ แอพของเราครับ เดี๋ยว Code ภายในเราจะมาว่ากันอีกที
  2. onCreateResources() เป็นตัวสร้างพวกสิ่งต่างๆ ในตอนเริ่มต้น สำหรับเกมของเราครับ
  3. onCreateScene() ตัวนี้ใช้สร้าง Scene กำหนด Object ต่างๆ ให้กับ scene ที่ใช้แสดงผลออกทางหน้าจอ และทำการ update scene วนรอบไปเรื่อยๆ ภายในนี้เราก็เขียน Code ดักทำโน้นนี้เพื่อใช้ run game เราครับ


จากนี้ไปเป็นตัว Code นะครับ ผมจะทำสีพื้นเป็นสี นี้ ครับ

ในส่วน Attribute สร้างตัวแปรสำหรับ class ดังนี้ครับ

// game engine
private Scene scene;
private static final int CAMERA_WIDTH = 800;
private static final int CAMERA_HEIGHT = 480;
private BoundCamera mBoundChaseCamera;
// resource
private BitmapTextureAtlas mBitmapTextureAtlas;
private TiledTextureRegion mPlayerTextureRegion;
private Font mFont;
// object on scene
private Text hellotxt;
private int countd = 10;

หลักการใน AndEngine นั้นก็คือ เราต้องสร้าง มุมกล้อง และขนาดกว้าง x ยาวของมุมกล้องขึ้นมาก่อนครับ สำหรับขนาดหน้าจอนั้นก็ไม่ต้องกังวลไป เพราะมันจะปรับ ขยาย ใหญ่เล็ก ให้โดยอัตโนมัติ ตามสัดส่วนครับ อย่างเช่น ถ้าหน้าจอมือถือผม 800x480 แต่ผมตั้งค่าไว้ที่ width 320 height 240 ตัว AndEngine ก็จะปรับขยายให้การแสดงผลของแอพ พอดีกับหน้าจอมือถือผมครับ แต่ว่าภาพจะแตก และใหญ่ขึ้นมา ตามมุมมองของขนาด 320x240 ครับ สิ่งที่ต้องให้ความสำคัญก็คือ Ratio หรือ สัดส่วนครับ ถ้าไม่ต้องการให้เห็นขอบดำข้างๆ จอการแสดงผล อธิบายแล้วดูจะเข้าใจยาก ก็ต้องลองทำดูเองเลยครับ โดยการเปลี่ยน CAMERA_WIDTH และ CAMERA_HEIGHT ตามใจชอบ แล้ว rus as ดู เพื่อสังเกตผลลัพธ์ครับ

สร้างตัวแปรกันแล้ว เราก็มาเขียน code ในส่วน onCreateEngineOptions กันครับ ดังนี้

// ตั้งค่ามุมกล้อง
this.mBoundChaseCamera = new BoundCamera(0, 0, CAMERA_WIDTH,CAMERA_HEIGHT);

// ตั้งค่า engine
final EngineOptions engineOptions = new EngineOptions(
true,
ScreenOrientation.LANDSCAPE_FIXED, 
new RatioResolutionPolicy( CAMERA_WIDTH, CAMERA_HEIGHT ), 
this.mBoundChaseCamera);

// ตั้งค่าให้สามารถ multitouch ขณะเล่นเกมได้
engineOptions.getTouchOptions().setNeedsMultiTouch(true);
return engineOptions;

ก็ตรงไปตรงมาครับ เริ่มแรกก็สร้างมุมกล้องขึ้นมาก่อน แล้วก็สร้างตัว Engine ภายใน EngineOptions เราก็สามารถกำหนดได้ว่า จะให้เป็นแนวตั้งหรือแนวนอน ในที่นี้เป็นแบบแนวนอนและ Fixed ไว้เลย
บรรทัดต่อมาก็ตั้งให้สามารถ Touch ได้มากกว่า 1 จุดครับ ตรงนี้สำคัญสำหรับเกมแบบใช้ปุ่มควบคุมเสมือนมากครับ เพราะถ้าไม่ตั้งค่าตรงนี้ เมื่อเรากดบังคับตัวละครค้างไว้ เราจะไม่สามารถกดหน้าจอป้อนคำสั่งใดๆ ได้อีก เพราะตัว engine จะรับค่าเพียง 1 จุดสัมผัสเท่านั้นครับ

แล้วก็ return ค่าออกไปตามที่ method นี้เรียกใช้ เป็นอันจบการสร้าง engine ครับ ที่นี้ก็เหลือ สร้าง Resource เตรียมไว้ แล้วก็เอามันออกมาแสดงครับ

ในเกมของเราเบื้องต้นจะยังไม่มีอะไรมา ผมจะสร้าง 1 ตัวละครกระดุ๊กกระดิ๊กได้ และ 1 การแสดงตัวหนังสือภาษาไทย พร้อมการเปลี่ยนแปลงที่กำหนดโดยระยะเวลานะครับ เริ่มไปต่อกันได้เลย

onCreateResources() ในนี้ให้เขียน Code ดังนี้ครับ

//player resource
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

mBitmapTextureAtlas = new BitmapTextureAtlas( this.getTextureManager(), 96, 192, TextureOptions.DEFAULT);
mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory
.createTiledFromAsset(
mBitmapTextureAtlas, this,
"player.png", 0, 0, 3, 4);
mBitmapTextureAtlas.load();

//font resource
final ITexture droidFontTexture = new BitmapTextureAtlas(this.getTextureManager(), 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
FontFactory.setAssetBasePath("font/");
mFont = FontFactory.createFromAsset(this.getFontManager(), droidFontTexture, this.getAssets(), "DroidSans.ttf", 24, true, Color.WHITE );
mFont.load();

ไล่จาก Code ดูเลยนะครับ ส่วน comment แรกเราจะ load ตัวละครก่อนครับ

เริ่มจาก กำหนด path ที่จะ load พวกรูปต่างๆ ให้กับตัว load texture ของ AndEngine ครับ ชื่อยาวๆ ก็คือ BitmapTextureAtlasTextureRegionFactory ครับ
ต่อมาจะต้องทำการสร้างตัว TextureAtlas ขึ้นมาครับ ตัวนี้จะเป็นตัวเก็บรูปภาพเอาไว้ครับ ในที่นี้จะเป็นภาพใหญ่ๆ ก่อนตัด parameter 96,192 คือความกว้างและความสูงของตัวเก็บภาพ ในที่นี้จะสร้างขนาดเท่ากับรูปที่โหลดขึ้นมาครับ ( load 1 ตัวก็ต้องมีตัวเก็บ 1 ตัวนะครับ หรือถ้าจะใช้รูปเดียวกันก็ไม่ต้องโหลดขึ้นมาอีกครับ)

จากนั้นทำการสร้าง TextureRegion (ตัวกำหนดขอบเขตของ texture) แบบ Tiled ขึ้นมาครับ ในนี้จะมี parameter ที่ใส่ชื่อไฟล์ (player.png) และจำนวนรูปแนวกว้างกับจำนวนรูปแนวยาว (3,4 อันหลังสุดครับ) จากนั้นก็ใช้คำสั่ง load(); เข้ามาไว้ในหน่วยความจำของเครื่อง

เตรียมรูปตัวละครเสร็จแล้วครับ ต่อไปมาเตรียมตัวอักษรบ้าง เราจะสร้าง ITexture เพื่อเก็บรูปแบบตัวอักษรเช่นเดียวกับรูปครับ จากนั้น set path ของ FontFactory ให้ไปหาที่ folder asset/font

จากนั้นก็จะไปโหลด font มาเก็บไว้ครับ จะมี parameter ชื่อ font ("DroidSans.ttf") ขนาดตัวอักษรที่จะแสดง (24) และสีของตัวอักษร เป็น int นะครับ (Color.WHITE) แล้วก็ใช้คำสั่ง load() ครับ เท่านี้ก็เรียบร้อย

ตอนนี้ก็จะเหลือส่วนสำคัญที่สุดของเรา นั่นคือ การนำทุกอย่างที่เตรียมไว้แสดงขึ้นหน้าจอครับ ด้วย method onCreateScene() นั่นเอง

ภายในมี Code ดังนี้ครับ

// สร้าง scene ใหม่
scene = new Scene();

// สร้าง text
hellotxt = new Text(10, 10, mFont, 
"สวัสดี แอนเอ็นจิ้น ภาษาไทย!",
"นับเวลาถอยหลังด้วย แอนเอ็นจิ้น = xxxxxxxxxxxxxx".length(),
this.getVertexBufferObjectManager());

// สร้างตัวละคร
final AnimatedSprite player = new AnimatedSprite(
100, 100,
mPlayerTextureRegion, 
this.getVertexBufferObjectManager());

scene.attachChild(player);
scene.attachChild(hellotxt);

// ทำให้ตัวละครเคลื่อนไหว
player.animate( new long[] { 200, 200, 200 }, 6, 8, true);

// ขณะที่ game ทำงานไปเรื่อยๆ
scene.registerUpdateHandler(new TimerHandler(1.0f, true, new ITimerCallback() {
            @Override
            public void onTimePassed(final TimerHandler pTimerHandler) {
            hellotxt.setText("นับเวลาถอยหลังด้วย แอนเอ็นจิ้น = " + countd);
            countd--;    
            if(countd < 0)
            countd=10;
            }         
        }));
return scene;

เริ่มจาก สร้าง Scene ใหม่ขึ้นมาก่อนเลยครับ

ถัดมาเตรียม text เพื่อแสดงข้อความบนหน้าจอ 10,10 คือ ตำแหน่ง x,y ที่จะแสดงใน scene ถัดไปเป็นข้อความเริ่มต้น ถัดไปเป็นความยาวตัวอักษรของข้อความ ตรงนี้สำคัญมากนะครับ ถ้าความยาวตัวอักษรที่เราจะแสดง เกินจากความยาวที่ตั้งค่าไว้ตรงนี้แล้ว มันจะ error และ บังคับปิดครับ (อันนี้สำหรับข้อความแบบ Static นะครับ เหมือนกับ Textview ของ Native android) ที่เห็นเขียนแบบนั้น (ข้อความแล้วตามด้วย.length() ) ในส่วนตั้งค่าความยาว คือ เราก็กำหนดรูปแบบไปเลย มันจะได้ง่ายว่า เกินหรือไม่เกิน แทนที่จะไปนั่งนับทีละตัวอักษรเอาน่ะครับ

จากนั้นก็นำตัวละครมาเตรียม ด้วย AnimatedSprite ตั้งชื่อว่า player ค่าที่เห็น 100,100 นั่นคือ ค่าตำแหน่ง x กับ y ใน scene ครับ ตัวรูปเราก็เอามาจาก TextureRegion ที่สร้างไว้แล้วน่ะครับ

แล้วก็เพิ่มพวกที่สร้างลงไปใน scene ครับ ด้วย attachChild 

ถ้าเราจบตรงนี้ก็ run ได้แล้วครับ แต่ทุกอย่างก็จะนิ่งๆ เพราะฉะนั้น เรามาเพิ่มการเคลื่อนไหวสักเล็กน้อยครับ

กำหนดให้ตัวละครเคลื่อนไหวด้วย animate จะมี parameter ดังนี้ครับ ค่า 3 ตัวแรก new long[] { 200,200,200 } คือความเร็วในการเปลี่ยนภาพจาก เฟรมหนึ่งไปเฟรมหนึ่งครับ อันนี้ต้องไปสัมพันธ์กับตอน load รูปนะครับ ว่า TextureRegion ที่เราสร้างนั้น มีภาพในแนวแนวนอน (หรือภาพการเคลื่อนไหวนั่นเอง) กี่ภาพ สำหรับตัวอย่างนี้มี 3 ภาพครับ ถัดไปจะเป็นลำดับของภาพครับ ให้นับจากซ้ายบนสุดคือ 0 ไล่มาทางขวา ถ้าหมดก็นับใหม่ เพราะฉะนั้นตามข้างต้น ผมให้แสดงภาพที่หันหน้าออกครับ ดังรูป

จากนั้นเราจะใช้ คำสั่ง registerUpdateHandler ของ scene เรียก TimerHandler ขึ้นมา จริงๆ แล้ว registerUpdateHandler นั้น มีอีกหลาย Handler ที่เรียกใช้ได้ครับ เช่น อัพเดตแบบตาม frame rate ก็มี แต่ในตอนนี้ เราจะใช้การวนรอบแบบตามเวลาที่ตั้งไว้ก่อน (ให้คิดเสียว่า การอัพเดต scene ก็คือการเปลี่ยนแปลงหน้าจอครั้งหนึ่งนะครับ)

สำหรับ การ Update แบบ Timer ก็จะมี parameter สำคัญดังนี้ครับ 1.0f คือเวลาที่นับในการวนรอบแล้วทำตามคำสั่งครับ ในที่นี้คือ 1 วินาที ถ้าต้องการครึ่งวินาที ก็ 0.5f แบบนี้นะครับ

Method onTimePassed จะทำงานเมื่อเวลาครบตามที่กำหนดครับ ภายในที่เขียนไว้ก็ไม่มีอะไรมากครับ ก็ให้ setText โดยเอาค่า countd มาแสดง วนไปเรื่อยๆ ครับ

ทีนี้เราก็จะได้การนับถอยหลัง ทุกๆ วินาทีล่ะครับ

เสร็จเรียบร้อยแล้วครับ ที่นี้เราก็ Run As ได้เลยครับ จะได้เห็นตามรูปด้านล่างนี้นะครับ (ตัวละครจะหันหน้ามาแล้วกระดุกกระดิกนะครับ)




ใช้เวลาเขียนบทความนี้ 4 ชั่วโมงกว่าเลยทีเดียว...เหนื่อยเอาเรื่องแฮะ

พบกันบทความหน้าครับ ถ้าไม่ขี้เกียจเสียก่อน เราจะมาสร้าง controller ควบคุมตัวละคร พร้อมกับปุ่ม action สัก 2 ปุ่ม เพื่อให้ตัวละครทำโน้นนี่นั่นกันครับ

มีปัญหาคาใจ ฝากคำถามไว้ได้เลยนะครับ อาจจะตอบช้าหน่อย แต่จะเข้ามาดูเรื่อยๆ จนกว่าจะลงบทความใหม่ครับ

ป.ล. บทความนี้ไม่ลงไฟล์ Source Code นะครับ จะได้ลองใส่ Code ดูเอง หากเกิด Error จะได้รู้ว่าเป็นที่จุดไหนครับ

วันพุธที่ 29 พฤษภาคม พ.ศ. 2556

พัฒนาเกม RPG บน android ด้วย AndEngine (1)




เกมส์ Classic RPG เป็นเกมส์ที่ผมใฝ่ฝันจะทำตั้งแต่ 20 ปีก่อน ตอนเริ่มหัดภาษา C++ ใหม่ๆ 
ทุกวันนี้ยังไม่เป็นชิ้นเป็นอันอะไรเลย พอดีมาสู่ยุค Smart Phone ก็รื้อความฝันเดิมมาทำเสียหน่อย

วันนี้จะมาแนะนำการพัฒนาเกมส์แบบ Classic RPG บน android กันครับ (ผมเรียกว่า classic เพราะเป็นแบบ 2d มุมมองด้านบนที่ไม่ใช่ iso น่ะครับ) ซึ่งโดยทั่วไปแล้ว เราสามารถใช้ library ของ Android SDK ที่มีมาให้ก็ได้เหมือนกัน แต่มันใช้เวลานาน และขั้นตอนยุ่งยากครับ

ก็เลยเป็นจุดเริ่มต้นของการหา Game Engine มาช่วยให้ขั้นตอนต่างๆ ลดลง พัฒนาแอพที่ต้องใช้ความสามารถของ Graphic , OpenGL ได้ง่ายขึ้น ที่ผมหาๆ อยู่ก็มีหลายตัวครับ และมุ่งเน้นไปที่การใช้งานแบบ Open Source เป็นหลักครับ

มีคนรวบรวม Library ของ OpenGL และพัฒนามันขึ้นเป็น Game Engine อยู่หลายเจ้าครับ ต้องขอบคุณคนเหล่านั้นจริงๆ เพราะถ้าไม่มีคนที่อุทิศตัวทำเรื่องแบบนี้แล้ว ความรู้ในโลกจะคืบหน้าได้ช้าจริงๆ ครับ เพราะฉะนั้น ถ้าพัฒนา Software ด้วย Open Source อะไรก็แล้วแต่ มีเงินก็น่าจะบริจาคกลับให้ผู้พัฒนาตามกำลังศรัทธาก็ดีนะครับ

กลับมาที่ Game Engine ที่ผมหามาจะมีอยู่ 2 ประเภท เพื่อสร้างเกมครับ

  • แบบ 2D ผมจะใช้ของ AndEngine ของคุณ Nicolas Gramlich 
  • แบบ 3D ผมจะใช้ของ JPCT ของคุณ Helge Foerster 

ซึ่งในบทความนี้จะพูดคุยเกี่ยวกับ AndEngine กันนะครับ

ที่อยู่ก่อนเลยครับ http://www.andengine.org/

และแน่นอน การเขียนบทความ Tutorial ของผม จะเขียนแบบ Open Workshop คือ พัฒนา Project ตามใจผู้เรียนรู้ ภายในกรอบของตัวอย่างงาน และนี่คือโจทย์ตัวอย่างงานของบทความชุดนี้ครับ





ปุ่มควบคุมเดิมๆ ครับ Control Direction ด้านขวา และ ปุ่มอีก 2 ปุ่มด้านซ้าย (จะเปลี่ยนจะเพิ่มเดี๋ยวบอกรายละเอียดใน Open Workshop ครับ)

ไป Download มา Run กันก่อนได้เลยครับ อันนี้เป็น Project ผมที่อยู่บน GitHub โดย Project นี้ก็จะเป็นการผสม ยำ รวมมิตร tutorial ของหลายๆ ที่ออกมาเป็น project ให้ได้เห็นแนวทางกันครับ

สิ่งที่ต้องมีในการพัฒนานะครับ
  1. Tiled Map Editor ครับ ไป Download กันมาได้เลย http://www.mapeditor.org/ อันนี้จำเป็นมากนะครับ เพื่อต่อยอดงาน RPG ในอนาคต มีหลายส่วนต้องอธิบายเช่นกัน
  2. Eclipse & Android SDK อันนี้คงมีอยู่แล้วใช่มั้ยครับ ถ้าไม่มีก็ download bundle SDK ได้เลยครับ ที่นี่ครับ http://developer.android.com/sdk/index.html
  3. AndEngine ครับ จริงๆ ใน Project จะมีให้อยู่แล้วอ่ะครับ แต่ถ้าใครอยากโหลดตัว Source เลย เพื่อมา modify (Project RPG อันนี้ของผม ก็มีการ Modify source นิดหน่อยเพื่อการใช้งานนะครับ เพราะฉะนั้น ถ้าท่านโหลด source มา lib จะเป็นคนละตัวแล้วครับ เพราะผมเอามา build ใหม่ครับ) ที่นี่ครับ https://github.com/nicolasgramlich/AndEngine
เมื่อโหลดมาแล้ว สิ่งที่ต้องเตรียมต่อไป เพื่อการทำ Open Workshop ในครั้งนี้นะครับ
  1. สร้าง Android Project เปล่าๆ ใหม่ 1 Project ครับ ใครสร้างไม่เป็นทางนี้ครับ http://pilotpol.blogspot.com/2013/05/android-thai-pilot-pray-3.html
  2. สร้าง Project ของ ตัวอย่างงาน RPG จากที่ download ไป Project ชื่อ testgame นะครับ สร้างได้ตามนี้ครับ http://pilotpol.blogspot.com/2013/05/android-thai-pilot-pray-5.html เปลี่ยนชื่อ project และตำแหน่งไฟล์เอา
ก็เท่านี้ก่อนครับ บทความหน้าจะมาเริ่ม Open Workshop กันล่ะ



วันจันทร์ที่ 27 พฤษภาคม พ.ศ. 2556

[Android] พัฒนาแอพจากแอพจริง Thai Pilot Pray (5)

ช่วงนี้กำลังอยู่ในระหว่างตกงาน ก็ต้องรีบ update บทความหน่อย ตอนที่มีเวลาพอจะทำได้

ในบทความนี้ ผมจะเริ่มอธิบาย Project Thai Pilot Pray พร้อมทั้งแนะนำการพัฒนา แบบเป็นขั้นตอนไปนะครับ และก็จะเสริมลักษณะการใช้คำสั่ง Java ที่เกี่ยวข้องกับ Code ในส่วนนั้นๆ ด้วย

ใครที่เพิ่งเข้ามาอ่าน แล้วเจอหน้านี้เลย และอยากพัฒนา Android ตามไปทีละขั้น ก็ลอง Download ตัวแอพ และ Source code ได้ตามนี้ครับ




การอธิบายการพัฒนาในแบบของผม จะไม่ใช้อธิบายแบบ สร้าง Project จากของเดิม แล้วมานั่งบอกว่าบรรทัดนี้คืออะไรแบบนั้นนะครับ แต่ผมจะใช้วิธีให้คุณสร้าง Project ใหม่ขึ้นมา ตั้งชื่อแบบที่คุณต้องการ แล้วค่อยๆ copy โค้ดหลัก มาบางส่วนครับ เพราะฉะนั้นสิ่งที่คุณต้องเตรียมจะมีดังนี้ครับ
  1. เตรียม android developer tools ให้พร้อม ดูได้จากที่นี่ครับ
    http://pilotpol.blogspot.com/2013/05/android-thai-pilot-pray-2.html
  2. สร้าง Project ใหม่เปล่าๆ เป็นแล้ว โดย ดูได้จากที่นี่ครับ
    http://pilotpol.blogspot.com/2013/05/android-thai-pilot-pray-3.html
  3. ลง Project Thai Pilot Pray ในเครื่อง และมีรายชื่อใน Package Explorer แล้ว อันนี้เดี๋ยวจะบอกครับ

เริ่มกันเลย...

เมื่อ Download ตัว Source code ของ Thai Pilot Pray แล้วนะครับ ขั้นต่อไปก็แตก zip ไฟล์ไปไว้ในที่ใดที่หนึ่ง แล้วเปิดโปรแกรม Eclipse (Android Developer Tools) ขึ้นมาครับ

ที่ icon ริมซ้ายสุด กดปุ่มลูกศรลง แล้วเลือก Project...
หรือจะเลือกที่ File > New > Project.. ก็ได้ครับ


จะมี Dialog ขึ้นมา ให้เลือกอันที่ 2 ตามภาพครับ
Android Project from Existing Code แล้ว Next

ก็จะมาหน้า Import Project ครับ เลือกไฟล์ Project ที่ Download มา ตามลำดับในภาพเลยครับ

1. Browse... เพื่อค้นหา Folder ที่แตก zip เรียบร้อยแล้ว
2. ติ๊กเลือกชื่อ Project ที่ Project to Import (ในที่นี้ของผมมี Project นี้อยู่แล้วเลยเลือกไม่ได้ครับ)
3. ติ๊กเลือก ถ้าต้องการให้ Copy Code ทั้งหมดไปไว้ใน workspace (ที่เก็บไฟล์ Project ต่างๆ ที่ Eclipse สร้างขึ้นมาตอนแรกครับ)
4. Finish เลยครับ

รวมกับบทความแรก ตอนนี้ที่ Package Explorer (ต่างแถบหน้าต่างด้านซ้าย ถ้าใครไม่มีกดเปิดได้ที่ Window > Show view > Package Explorer นะครับ) ของทุกท่านควรจะมี 2 Project ที่ต้องใช้งานคือ New Project เปล่าๆ ที่ท่านสร้างขึ้นเอง ชื่อก็ตามแต่จะตั้งครับ และ Thai Pilot Pray Project นะครับ ใครที่ยังไม่มี ก็ลองทำตามวิธีในบทความนี้ และบทความเก่าดูนะครับ

ผมจะอนุมานว่ามีกันหมดแล้ว ต่อไปจะอธิบาย Concept อะไรอีกสักเล็กน้อย ก่อนที่จะเริ่มอธิบาย code กัน

AndroidManifest.xml

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

assets

folder นี้จะใช้เก็บไฟล์ส่วนประกอบทั้งหลายแหล่ ที่จำเป็นต้องใช้ใน แอพฯ เราขณะ run time ครับ สำหรับ project thai pilot pray ก็จะมี folder audio ไว้เก็บเสียงสวดมนต์ , text ไว้เก็บบทสวดมนต์ , และไฟล์ praylist.xml ไว้เก็บรายละเอียดของแต่ละบทสวด เพื่อนำไปใช้ในแอพฯ เป็น database อีกประเภทหนึ่ง คือ แบบเก็บไว้ในไฟล์ ยังไม่ใช้แบบ SQL ครับ

res

folder นี้เก็บไฟล์ที่จะนำมาประกอบกันเป็นแอพฯ ครับ เป็นพวกรูป drawable หรือ layout อย่างที่อธิบายไปเมื่อบทความก่อน ฯลฯ อะไรที่จะนำมาใช้ในการสร้างแอพก็นำมาใส่ไว้ในนี้ครับ ไม่สับสนกับ assets นะครับ อันนั้นคือ folder ที่เก็บไฟล์ที่เราจะใช้ตอนเปิดแอพฯ บนเครื่องแล้ว

ต้องมีเป้าหมาย...

1. เริ่มต้นคิดก่อนว่าเราจะทำแอพอะไร จากตัวอย่างที่เรามี ซึ่งสำหรับแอพ Thai Pilot Pray คุณลักษณะ ก็จะมี ข้อความที่เลื่อนได้, และควบคุมเสียง พร้อมกับมี playlist
 
playlist ของ thai pilot pray

ข้อความเลื่อนได้ ในขณะเดียวกันก็เล่นไฟล์เสียงไปด้วย พร้อมตัวควบคุม และ Seek bar (ด้านบน ฟ้าๆ)

จาก Code ที่มีข้างต้น ผมจะลองทำอีกแอพ แต่พื้นหลังนิ่งๆ จะแสดงภาพ VDO ไปด้วย ส่วนข้อความที่เลื่อนๆ จะทำให้แคบลงหน่อย คล้ายๆ กับ แอพฯ คาราโอเกะ ไรงั้น

สำหรับทุกท่าน มีไอเดียอะไร ก็ลองประยุกต์ดูนะครับ เมื่อพร้อมแล้วก็ขั้นตอนต่อไปครับ ^_^

2. ไอเดียมีแล้ว ต้นแบบมีแล้ว เราก็จะมาแกะ code เก่ากันครับ ว่าจะเอามาประยุกต์กับ project ใหม่ของเรายังไงดี มาดู code กันก่อนดีกว่าครับ ที่ project ใหม่เรา ในแถบหน้าต่าง Package Explorer เข้าไปที่ ชื่อ Project (ของผมเป็น examproj )  > src > com.example.examproj > MainActivity.java ตามรูปครับ


ในนั้นจะมี code อยู่ส่วนหนึ่งที่ generator สร้างขึ้น อธิบายคร่าวๆ นะครับ 
  • ส่วนบนที่นำหน้าด้วย package ก็เพื่อบอกว่า ไฟล์นี้อยู่ใน package อะไร (เอาไว้อ้างอิงในไฟล์อื่นๆ project อื่นๆ ครับ)
  • import รายการ library ต่างๆ ที่จำเป็นต้องใช้สำหรับไฟล์นี้ครับ อันนี้ใครจำไม่ได้ หรือไม่รู้ว่าจะ import อะไรก็ไม่ต้องกลัวไปครับ เมื่อเราเขียน code เสร็จ เราสามารถกด Ctrl+Shift+O เพื่อให้ Eclipse import หรือเลือกลบตัวที่ไม่เกี่ยวข้องได้แบบ automatic ครับ สะดวกดีเหมือนกัน
  • ต่อมาเป็น block ของการประกาศ class ครับ อันนี้ผมจะไม่สอนพวก OOP หรือพื้นฐานการโปรแกรมนะครับ สามารถหาเอาได้ใน internet อันกว้างไกลครับ ^_^
อธิบายนิดหน่อยเกี่ยวกับ Class นี้ครับ 
อย่างที่รู้ครับว่าในระบบ android การกระทำหนึ่งๆ จะเรียกว่า activity เราอาจจะคิดไปได้ว่ามันเป็นหน้าหนึ่งที่ทำงานก็ได้ครับ จากรูปข้างต้น จะหมายถึงตอนนี้มีหน้าที่เรียกว่า MainActivity อยู่ครับ และตอนนี้มันก็ทำงานตาม function ที่มีอยู่ภายใน class นั่นเอง

ส่วนที่ว่าจะรู้ได้อย่างไรว่า activity ไหนเป็นตัวหลัก แล้วไปไหนต่อ เผื่อต้องการไล่การทำงานของโปรแกรม ก็ต้องไปดูใน AndroidManifest.xml ครับ ว่าประกาศ class ไหนเป็นตัวหลักไว้ ดังนี้ครับ


ไปที่ androidmenifest.xml ที่อยู่ใน project ของเราครับ กดตามในรูป คือ ให้แสดงในแบบ xml ไฟล์ แล้วดูที่กรอบเลข 2 ครับ ตรงนี้คือ MainActivity ซึ่งตัว name นั้น เราสามารถเขียนอย่างย่อได้ โดยใส่จุดไว้ตรงหน้าแบบนี้ครับ android:name = ".MainActivity" เป็นการละตัว package ไว้ในฐานที่โปรแกรมเข้าใจ ^_^

ใน node activity จะมีตัว intent-filter อยู่ซึ่งแสดงถึง เจตจำนึงของ activity นั้นๆ ครับว่าต้องการจะทำอะไรบ้าง ในที่นี้มีอยู่ 2 ตัว คือ 
  1. action.MAIN บอกให้รู้ว่า activity นี้เป็นตัวหลักของแอพฯ นะ ไม่รับค่าใดๆ ในตอนเริ่มต้น
  2. category.LAUNCHER บอกให้ระบบของเครื่องที่ลงแอพฯ รู้ว่า แอพฯ เราจะมีหน้าจอที่จะแสดงขึ้นมา และเมื่อเปิดขึ้นมาแล้ว ให้ขึ้นอยู่บนสุดของระบบในขณะนั้นครับ
สำหรับรายละเอียดเต็มๆ ของ Intent ตามไปที่นี้ได้เลยครับ รายละเอียด Intent

ย้อนกลับมาที่ไฟล์ MainActivity นะครับ ระบบจะสร้าง default ไว้ให้อยู่ 2 Method ( Method ก็คือ function ที่อยู่ใน class ครับ ส่วนพวกตัวแปรเรียกว่า Attribute) คือ onCreate และ onCreateOptionsMenu เราจะมาสนใจที่ onCreate กันก่อนครับ

ตัว class MainActivity ถูกสืบทอดมาจาก class เดิม คือ Activity ซึ่งในนั้นจะมี Method onCreate อยู่ด้วย โดยทั่วไปเราจะทำการ Override มาใช้ใหม่ในรูปแบบของเราครับ ซึ่ง 2 บรรทัดที่มีใน Method นี้ คือ

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

บรรทัดแรก คือการเรียกใช้คำสั่งอะไรก็ตามที่มีใน method เดิมครับ มีอะไรบ้างผมก็ไม่รู้เหมือนกัน แฮะๆ -_-"
บรรทัดที่สอง คือการสร้าง View มารองรับเพื่อแสดงผลออกหน้าจอ ในยามที่แอพฯ ถูกสร้างขึ้นมา ตรงนี้จะใช้ ID เรียกครับ นั่นคือ R.layout.activity_main จะเป็นตัวแปรที่อ้างอิงกับ layout activity_main ใน folder res/layout ของ project

ปัญหาที่พบในส่วนนี้ก็คือ บางที R กลับขึ้นขีดแดง แล้วเรียกใช้ไม่ได้ พอรันก็พบ error ไม่สำเร็จ แจ้งว่า "R cannot be resolved to a variable" มีแนวทางแก้ปัญหาพวกนี้ประมาณนี้ครับ
  • ตรวจสอบดูในไฟล์ layout ที่เรียกครับ ว่ามีอะไรที่ผิดพลาด ขึ้นแดงรึเปล่า (ชื่อไฟล์อยู่อันสุดท้ายครับ คั่นด้วยจุด ตรงกลางคือ folder)
  • บางทีเป็นเพราะ import android.R; เข้ามาที่ส่วนการ import ด้านบนครับ ต้องเอาออกนะครับ เพราะอันนั้นจะเป็นของ lib ใน android เอง คนละส่วนกับ R ของ project เราครับ
  • ตรวจสอบดู ไฟล์ R.java ที่อยู่ใน folder gen > ชื่อ package ครับ ว่ามีหรือเปล่า ถ้าไม่มีก็คือ ระบบสร้างไม่ได้ครับ มี error อะไรสักอย่างอยู่ใน res แน่ๆ ครับ ลองหาดู
เมื่อทำการแก้ไขปัญหาเสร็จแล้ว ก็กด Clean หน่อยนะครับ เป็นวิธี Rebuild Project ใหม่ครับ โดยไปที่ Project > Clean... 

ตอนนี้ทุกท่านสามารถรู้ได้แล้วนะครับ ว่าจะไล่โปรแกรมกันยังไง ในระบบ android จะเริ่มจุดไหน บทความหน้า จะกำหนดสิ่งที่ต้องมีในโปรเจ็คใหม่ และค่อยๆ แกะโปรเจ็ค Thai Pilot Pray เพื่อ Copy เอาบางส่วนที่ต้องใช้งานมาครับ

ขอบคุณที่อ่านครับ...

วันเสาร์ที่ 25 พฤษภาคม พ.ศ. 2556

[Android] พัฒนาแอพจากแอพจริง Thai Pilot Pray (4)


ก่อนจะเริ่ม Coding เรามาพูดกันเรื่อง Activity, Intents และ Layout ของ android กันครับ ซึ่งเรื่องพวกนี้เป็นเรื่องที่ต้องเข้าใจก่อนพัฒนาแอพฯ บนระบบ android ครับ (แต่ไม่ต้องเข้าใจลึกก็ได้ครับ ผมเองก็ไม่ได้ลึกซึ้งอะไรเท่าไร ก็ทำแอพได้ครับ)

Activity
แปลตามตัวก็คือ กิจกรรม สำหรับในการพัฒนา android แล้ว กิจกรรมที่ว่านี้ก็จะเป็นการดำเนินการ (action) ต่างๆ ของแอพฯ ที่ทั้งตอบโต้ และไม่ตอบโต้กับผู้ใช้ครับ activity เป็น 1 ใน 4 ของ application components ซึ่งประกอบไปด้วย

  1. Activity
  2. Services
  3. Content Providers
  4. Broadcast receivers (Intents จะอยู่ในส่วนนี้ครับ) 
ใครที่อยากทราบรายละเอียดลึกๆ ก็ไปหาอ่านได้จากต้นฉบับที่นี่เลยครับ http://developer.android.com/guide/components/fundamentals.html



Intents
ตัวนี้อธิบายยากครับ -_-" เพราะ abstract มาก ผมจะอธิบายตามความหมายที่ผมเข้าใจนะครับ ซึ่งต้นฉบับมาจากนี่ครับ http://developer.android.com/reference/android/content/Intent.html

intents ตามความหมายมันคือ "เจตจำนง" ของสิ่งต่างๆ ที่อยู่ในระบบ android ครับ ดูจะเวอร์เป็น The Matrix มั้ยครับ แต่ถ้าเข้าใจความหมายคำว่า "เจตจำนง" แล้วก็จะนึกออกครับว่า intents นั่นมีวัตถุประสงค์เพื่ออะไรในระบบ android
เจตจำนง คือ ความมุ่งหมาย ความประสงค์ มุ่งหวัง ตั้งใจ โดยตัว Intents จะถูกสร้างจาก application components ทั้ง 4 เพื่อให้กระทำการอย่างใดอย่างหนึ่ง อาจจะเป็นสิ่งเล็กๆ แค่ส่ง-รับ ค่า จาก activity หนึ่ง ไปอีก activity หนึ่ง หรือตัวแอพฯ ของเรา เรียกหา intents ที่ broadcast อยู่ในระบบ ซึ่งถูกสร้างจากแอพฯ อื่นๆ  แล้วเอามันมาใช้งานก็ได้ เช่น intents share ที่จะ share สิ่งที่เราต้องการไปยังแอพฯ อื่นๆ อย่าง facebook เป็นต้น

intents ประกอบไปด้วย 2 ส่วน คือ action และ data ครับ


Layout
ปัญหาลำดับต้นๆ ของผู้พัฒนา android คือ fragmentation หรือ device ที่มีขนาดจอหลากหลายมากในโลก เพราะฉะนั้น concept ของการพัฒนาแอพฯ แอนดรอย์ ก็จะเป็นไปในแนวทางเดียวกับเว็บครับ คือ ควรยืดหยุ่น และรองรับหน้าจอที่แตกต่างกันให้มากที่สุดเท่าที่จะทำได้ 


แนวทางหนึ่งที่ผมใช้แก้ปัญหาดังกล่าวก็คือ การสร้าง folder สำหรับ layout อันหลากหลายไว้ให้มากที่สุด เท่าที่จะมากได้

จากภาพ จะเห็นว่า ใน folder res มี folder ที่นำหน้าด้วย layout หลายตัวทีเดียว นี้เป็นอีกวิธีหนึ่งที่ได้ผลพอสมควรครับ กับการสร้างแอพฯ เพื่อใช้กับขนาดหน้าจอที่หลากหลาย แต่ถ้าจะให้ดี ควรเพิ่มให้ครอบคลุมให้มากที่สุดครับ ก็คือ layout แล้วขีดกลาง ตามด้วยขนาด และก็ขีดกลาง ตามด้วยแนวการแสดงผล เช่น layout-small-land จะหมายถึง layout สำหรับขนาดหน้าจอขนาดเล็กแบบแนวนอน 

ก็ขึ้นอยู่กับว่าเราจะตัดสินใจแยก layout ด้วยอะไรครับ หลักๆ จะมีอยู่ 2 แบบ คือ

  • xlarge screens are at least 960dp x 720dp
  • large screens are at least 640dp x 480dp
  • normal screens are at least 470dp x 320dp
  • small screens are at least 426dp x 320dp
แบบนี้เป็นแบบเก่าครับ แต่ถ้าจะพัฒนาตั้งแต่ android 3.2 ขึ้นไป ก็จะนิยมใช้แบบนี้ครับ

  • 320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
  • 480dp: a tweener tablet like the Streak (480x800 mdpi).
  • 600dp: a 7” tablet (600x1024 mdpi).
  • 720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc)
คำว่า dp (density independence)  คือ ความหนาแน่นใน 1 จุด pixel นะครับ เพราะฉะนั้นเราจะนับหน้าจอเป็น Resolution แบบ pixel ไม่ได้ครับ เพราะเครื่องที่ pixel เท่ากัน แต่ความหนาแน่นไม่เท่ากัน การแสดงผลไม่เหมือนกันครับ

จะรวมใช้ทั้ง 2 แบบก็ได้นะครับ เพื่อการรองรับที่ดีขึ้น ส่วนการตั้งชื่อ folder layout ก็จะเป็นแบบนี้ครับ

ก็ตั้งมันเข้าไปครับ 555+ ตรงนี้ถ้าคนพัฒนามีคนที่ทำ graphic โดยเฉพาะก็จะสบายหน่อย คือ นั่งทำมันแต่ layout เนี่ยแหละครับ และถ้ารวม folder layout ทั้งหมดด้วยแล้ว (รวมแบบ layout-sw320dp ฯลฯ) สนุกเลยครับงานนี้ จุดนี้เป็นจุดที่ android แตกต่างจากการพัฒนา device ฝั่ง apple ครับ เพราะหน้าจอนั่นเอง

บทความหน้าจะเริ่ม coding Activity แรกกันเลยนะครับ พร้อมกันก็จะอธิบายตัวโค้ดของ Thai Pilot Pray ด้วยครับ

วันพุธที่ 22 พฤษภาคม พ.ศ. 2556

[Android] พัฒนาแอพจากแอพจริง Thai Pilot Pray (3)

ตอนที่แล้วเป็นการแนะนำ Android SDK ซึ่งมาอ่านดูก็รู้สึกว่าจะเขียนรวบรัดไปหน่อย แม้ว่าทุกท่านจะหาอ่านได้จากที่อื่นก็เถอะ แต่เราก็น่าจะเขียนให้เป็นแบบ Step by Step ดีกว่า เดี๋ยวจะเขียนแบบละเอียดอีกครั้งแล้วกันนะครับ ตอนนี้ถือก่อนว่าทุกท่านมี Icon Eclipse ของ Android SDK และสามารถเปิด และสร้าง Project กันได้แล้ว

ส่วนเรื่อง Emulator ของ Android ผมไม่ค่อยได้ใช้อ่ะครับ และก็ไม่แนะนำนะ ผมใช้ Device จริงในการทดสอบ เพราะมันเร็วกว่า แล้วก็ใกล้เคียงกับสถานการณ์จริงมากกว่า

เอาล่ะ! มาสร้าง Project Android กันเลยครับ


1. หลังจากเปิดโปรแกรมขึ้นมาแล้ว กดที่ File > New > Android Application Project กันเลยครับ ซึ่งทุกท่านสามารถสร้าง project ใหม่ได้หลายแบบ ตามวงกลมที่แสดงไว้ในรูป คือ ที่ menu, toolbar, และ คลิกขวาที่ Package Explorer แล้วเลือกตามรูปด้านบน


2. เมื่อเลือกเสร็จ โปรแกรมจะแสดง Dialog ขึ้นมา ให้เรากรอกรายละเอียดของโปรแกรมใหม่ลงไปตามรู้ด้านล่างครับ


Application Name : ก็คือชื่อของ แอพของเรา ตามใจเลย
Project Name : ชื่อของ project ที่จะแสดงที่หน้าต่าง Package Explorer ด้านข้าง
Package Name : ชื่อ Package ของ แอพ 
( package แปลตรงตัวว่า หีบห่อ ในที่นี้เอาไว้ห่อหุ้มตัว Project เอาไว้ เพื่อแสดงถึงแหล่งที่มา และไม่ให้ไปซ้ำกับ Project อื่นๆ การตั้งชื่อ Package ตามรูปแบบที่นิยมกันส่วนหนึ่งจะเป็น {ลักษณะการใช้งานของแอพ}.{ผู้พัฒนา}.{Project ที่พัฒนา} เช่น com.pilotpol.thaipilotpray แต่จะตั้งเป็นแบบอื่นก็ได้นะครับ ซึ่งจุดที่คั่น ก็คิดเสียว่า เหมือนกับ folder ที่แยกรายละเอียดอื่นๆ ให้เป็นระเบียบนั่นเอง)

ถัดลงมาเป็น
Minimum Required SDK : ตัว API เวอร์ชั่น ของ android ที่จะให้รองรับได้น้อยที่สุด สำหรับผมไม่ทำแอพที่รองรับ 2.2 แล้ว เพราะฉะนั้นเริ่มจาก 2.3.3 เลย ตรงนี้ยิ่งเลือกให้รองรับน้อยเท่าไร เครื่องที่ใช้ได้ก็ยิ่งเยอะ แต่ความหลากหลาย และความสามารถใหม่ๆ บางอย่างที่มีใน API ใหม่ๆ บางอันเราก็ใช้ไม่ได้เหมือนกัน
Target SDK : เป้าหมายของเครื่องที่จะรันโปรแกรมเรา
Compile With: ตัว library ที่จะใช้ในการแปลรหัสโปรแกรม ผมเลือกตัวล่าสุดครับ ซึ่งก็จะรองรับ ความสามารถสำคัญๆ หลักๆ ของเวอร์ชั่นก่อนๆ ได้ แต่บางอันก็ถูกยกเลิกไปเหมือนกัน
Theme : รูปร่างหน้าตาของ control หลักๆ ในโปรแกรม อย่างพวกปุ่ม เส้น สี
ในขั้นต้นเลือกตามแบบผมแบบในรูปไปก่อนก็ได้ครับ จากนั้นกด Next เลย ครับ


3. Dialog นี้จะสอบถามรายละเอียดเพิ่มเติมอื่นๆ 
Create custom launcher icon : เลือกเพื่อให้ android SDK สร้าง icon สำหรับแอพ โดยอัตโนมัติในทุกความละเอียด
Create activity : สร้าง activity ให้กับแอพ ใน android Activity คือ ตัวกิจกรรม เมื่อจะทำงาน ซึ่งเดี๋ยวผมจะอธิบายเรื่อง activity ละเอียดอีกครั้ง ตอนที่จะเริ่ม Code ครับ
Mark the project as a library : ทำโปรเจ็ค ให้เป็น library ไฟล์ ในที่นี่ไม่ต้องครับ
Create Project in Workspace : จะสร้างไฟล์โปรเจ็คใน workspace ของเราหรือไม่
Working sets : อันนี้ไม่เคยได้ใช้เลยอ่ะครับ คงจะเป็นการแบ่งกลุ่ม Project ที่ทำงาน เดี๋ยวจะหาข้อมูลอีกครั้งครับ
จากนั้นกด Next> เลยครับ

4. ถ้าหน้าเมื่อกี้ คลิกเลือกช่องแรก ว่าให้โปรแกรมสร้าง Icon ตามความละเอียดต่างๆ ให้ ก็จะขึ้นหน้าสร้าง Icon ครับ เมื่อเลือกรูปแบบ Icon ที่ถูกใจได้แล้ว ก็กด Next> ต่อครับ

5. หน้าต่อมาจะเป็นการสร้าง Activity ให้กับแอพ ในที่นี้เลือก Blank Activity ครับ เสร็จแล้วคลิก Next> 

6. ใส่ชื่อ Activity เริ่มแรกก็ใส่เป็น MainActivity ไปก่อนครับ ตรงนี้จะถูกนำไปสร้างเป็น Class ด้วยนะครับ สำหรับควบคุมการทำงานของ Activity นั้นๆ
อีกช่องถัดลงมาคือ layout Name : หน้า View สำหรับแสดงของ Activity นั้นๆ ครับ
Navigation Type เลือกเป็น none ครับ

แล้วก็คลิก Finish เลยครับ


7. ระบบจะสร้างโครงสร้างต่างๆ ขึ้นแบบอัตโนมัติใน folder ของ Project เรา ตรงนี้เดี๋ยวจะอธิบายอีกครั้งครับ ตอนทำหน้า View ของ แอพ

8. ระบบจะพามายังหน้า View แรกของแอพ แบบกราฟฟิก โดยเราสามารถกดที่ Tab ด้านล่างที่เป็นนามสกุล .xml เพื่อดูแบบ code xml ของหน้าวิวเราได้ครับ



9. จากนั้นก็ลองรันดูเลยครับ โดยที่หน้าต่าง Package Explorer ให้คลิกขวาที่ชื่อโปรเจ็ค แล้วเลื่อนลงมาเลือก Run as จากนั้นเลือกอันแรก ก็จะปรากฏหน้าต่างขึ้นมาเพื่อให้เราเลือกว่าจะใช้อะไรรันแอพ ในที่นี้ของผมจะเลือก device ที่เชื่อมต่ออยู่ ก็แค่เสียบสายเชื่อมต่อกับเครื่องนะครับ อ๋อ ที่เครื่องก็ต้องตั้งค่าสำหรับ develop ไว้ด้วยนะครับ ตามนี้ครับ ที่ device 1. ตั้งค่า > ความปลอดภัย > ไม่ทราบแหล่งข้อมูล เพื่อติดตั้งแอพจากแหล่งอื่นได้ครับ 2. ตั้งค่า > ตัวเลือกสำหรับผู้พัฒนา > การดีบัก USB

เท่านี้แอพแอนดรอย์ก็ถูกสร้างแล้วครับ ง่ายมากๆ เลยใช่มั้ยครับ แต่ถ้าหากจะทำเป็น apk เพื่อติดตั้งผ่าน google play ก็ต้อง export ครับ ซึ่งนั่นเดี๋ยวจะบอกอีกครั้งหนึ่ง

ส่วนอันนี้เป็นไฟล์ Source Code ของ Thai Pilot Pray ครับ

ดาวน์โหลด แล้วสร้าง Project แบบ existing ตามนี้ครับ
1. เลือก New > Project
2. ที่ Dialog ที่ขึ้นมา เลือก Android Project Existing Code แล้วกด Next
3. เลือก Folder ที่แตกไฟล์ของ Thai Pilot Pray ไว้ ด้วยการกด Browse... ที่ Root Directory จะเห็น project ที่สามารถสร้างขึ้นได้ ติ๊กถูกที่หน้า Project แล้วคลิก Finish ครับ
4. คลิกขวาที่ชื่อ Project แล้ว Run ดูครับ

เดี๋ยวบทความหน้า จะอธิบายแบบ Step by Step ตั้งแต่ Concept การเริ่มต้นทำ Project เลยครับ