Phát triển game đơn giãn trên Mobile(P7 – Phần cuối)

Một phần của tài liệu Phát triển game đơn giãn trên máy tính nhanh nhất (Trang 34)

Ở bài trước, các bạn đã được hướng dẫn để tạo ra một game, ở phần này chúng ta sẽ bàn đến network.Một trong các đặc điểm chính của mobile, đó là khả năng được kết nối ở mọi nơi và mọi lúc. Bên cạnh việc bạn đạt được điểm số cao(high score); kết quả trả về có thể được chia sẽ trên internet. Với JavaME, bạn có thể dễ dàng truy cập vào những đặc điểm giao tiếp sau:

• HTTP

• Socket

• SMS

• Bluetooth

Bài viết này sẽ giải thích cách sử dụng giao thức HTTP để gửi dữ liệu high score đến server và làm thế nào để sử dụng chức năng gửi SMS để mời các người khác cùng tham gia game.

Connector

Đặc điểm chính khi sử dụng các chức năng network là lớp Connector. Lớp này cho phép tạo ra các đối tượng Connection thông qua các phương thức tĩnh:

• open(String name)

Tham số name chính là một chuỗi URL để xác định kết nối mà bạn muốn tạo ra.Tương ứng với giao thức ở URL là một kiểu đối tượng Connection sẽ được tạo ra. Sau đây là danh sách các URL và các đối tượng Connection tương ứng:

• “http://www.server.com“: Trả về một kết nối HTTP sử dụng lớp HttpConnection. • “socket://server.com:8080″: trả về một kết nối TCP/IP.

• “btsp://2343434d3434″: trả về một kết nối Bluetooth.

• “sms://+351910000000″: trả về một kết nối SMS đến một số điện thoại +351910000000. Trong các giao thức kể trên, thì giao thức HTTP được tất cả các thiết bị hỗ trợ JavaME hỗ trợ; các giao thức khác thì phụ thuộc vào thiết bị.Tuy nhiên hầu hết các loại điện thoại mới đều hỗ trợ tất cả các giao thức trên.

Lưu ý rằng khi bạn cố gắng mở bất kỳ loại kết nối nào, người dùng các ứng dụng được thông báo từ hệ thống quản lý ứng dụng và cung cấp tùy chọn để chấp nhận hoặc từ chối các yêu cầu kết nối.Nếu bị từ chối yêu cầu kết nối, ứng dụng sẽ nhận được một SecurityException và kết nối không được thiết lập.

HTTP

Có thể nói, kết nối HTTP là một loại kết nối phổ biến nhất trong tất cả các loại kết nối. Để tạo kết nối HTTP trong J2ME, bạn làm như sau:

import javax.microedition.io.Connector;

import javax.microedition.io.HttpConnection;

publicclass Network {

publicbyte[] httpConnection(String url, byte[] dataToSend) throwsIOException

{

HttpConnection hc = null; // Prepare Connection

hc = (HttpConnection) Connector.open(url, Connector.READ_WRITE); [...] [...]

}} }

Các kết nối HTTP được đại diện bởi lớp HttpConnection. Lớp này có ba trạng thái: • Setup nơi mà các tham số yêu cầu được định nghĩa.

Connected nơi mà bạn có thể gửi và nhận dữ liệu. Bạn cần gửi dữ liệu trước khi bạn có thể nhận bất kỳ sự trả lời nào.

Closed sau khi bạn đọc dữ liệu và kết nối được kết thúc.

Khi bạn nhận đối tượng HttpConnection từ Connector, nó rơi vào trạng thái Setup.Sau đó, bạn có thể cấu hình các tham số yêu cầu. Một trong những lựa chọn chính đó là phương thức yêu cầu HTTP(POST, GET hoặc HEAD).

publicbyte[] httpConnection(String url, byte[] dataToSend) throwsIOException { [..] if (dataToSend == null){ hc.setRequestMethod( HttpConnection.GET ); } else { hc.setRequestMethod( HttpConnection.POST ); } [...] }

Bạn cũng có thể cấu hình các thuộc tính yêu cầu, chẳng hạn như kiểu nội dung mà bạn sẽ gửi trong trường hợp POST:

hc.setRequestProperty("Content-type", "application/octet-stream" );

Sau khi bạn đã cấu hình kết nối, bạn có thể bắt đầu gửi dữ liệu.Khi bạn bắt đầu quá trình này, bạn không thể thay đổi các tham số yêu cầu.Nếu kết nối được thiết lập, bạn bắt đầu nhận được dữ liệu.

publicbyte[] httpConnection(String url, byte[] dataToSend) throwsIOException { [...] if (dataToSend != null){ // Write Data OutputStream os = hc.openOutputStream(); os.write( dataToSend ); os.close(); }

// gets answer from server

int rc = hc.getResponseCode(); // check http response if (rc == HttpConnection.HTTP_OK){ // Read Data InputStream in = hc.openInputStream(); ByteArrayOutputStream tmp = newByteArrayOutputStream(); int ch; while ((ch = in.read()) != -1) { tmp.write(ch); } data = tmp.toByteArray(); in.close(); hc.close(); } return data; }

Xây dựng phương thức httpConnection() coi như đã xong, tiếp theo nó được cài đặt trong game để gửi high score đến server. Bạn hãy thêm một command vào màn hình high score:

public Displayable initScoreForm() { [...]

cmdSendHighScore = new Command("Send to Server", Command.ITEM, 1); highScoreForm.addCommand(cmdSendHighScore);

[...]} }

Tiếp theo, bạn tạo một phương thức sử dụng nó khi Command được lựa chọn:

publicString sendScore(String user, int score) {

String result = “No Answer”;

// server to send data

String url = “http://www.sergioestevao.com/midpAdventures/post.php”;

// prepare http request

String urlTotal = url + “?user=” + user + “&score=” + score;

byte[] data = null;

try {

data = network.httpConnection(urlTotal, null); } catch (IOException e) {

result = “Communication Problems”; e.printStackTrace();

} catch (SecurityException s) {

// user denied access to communication

result = “You need to allow communications in order to send the highscore to server.”; s.printStackTrace();

}

// check data return.

if (data != null) {

result = newString(data); }

return result; }

Và gọi nó khi Command được sử dụng:

if (cmd == comInviteSend) {

result = sendScore(scores[0].name, scores[0].value);

display(new Alert("Result", result, null, AlertType.INFO)); }

Nếu bạn sử dụng đoạn code này, bạn sẽ nhận được một cảnh báo:

Warning: To avoid potential deadlock, operations that may block, such as networking, should be performed in a different thread than the commandAction() handler.

Hãy nhớ rằng bạn đang thực thi đoạn mã này như là một câu trả lời cho một sự kiện mà người sử dụng đang được thực thi trên thread UI. Nếu đoạn mã này block hoặc mất một thời gian dài để thực hiện, ứng dụng sẽ gặp khó khăn.

Để tránh vấn đề này, bạn nên sử dụng một thread để làm các công việc liên quan đến network. Hãy bắt đầu khai báo một thread và các biến trạng thái để điều khiển các hoạt động của thread.

privatestaticfinalint ACTION_SEND_HIGHSCORE = 0;

publicThread workThread;

publicboolean active = false;

Bất cứ lúc nào có một sự kiện làm tốn nhiều thời gian(như việc kết nối mạng có thể thành công hay thất bại, điều này phụ thuộc các yêu tố bên ngoài như đường truyền mạng…), thì bạn nên sử dụng một thread chuyên biệt để kích hoạt các hoạt động này.

publicvoid doAction(int action) {

// stores action to do

this.action = action;

// check if thread is already created

if (workThread == null) { workThread = newThread(this); workThread.start();

active = true; }

// wakes up thread to work

synchronized (this) { notify();

} }

Thread này sẽ thực thi phương thức run():

publicvoid run() {

while (active) {

// check what action to do

switch (action) {

case (ACTION_SEND_HIGHSCORE):

// send the first score to the server

result = sendScore(scores[0].name, scores[0].value); commandAction(cmdReceiveHighScore, highScoreForm);

break; }

// waits for action to do.

synchronized (this) {

try { wait();

} catch (InterruptedException e) { e.printStackTrace(); } } } }

Để start thread này, cần khai báo một giao diện Runnable trong MIDlet:

publicclass MyMidlet extends MIDlet implements CommandListener, Runnable {

Bây giờ, bạn có thể gọi phương thức doAction() khi người dùng chọn command ‘Send high score’. Lưu ý rằng, phương thức run() gọi một command cmdReceiveHighScore. Điều này được sử dụng để hiển thị các kết quả của các giao tiếp với người dùng.

if (cmd == cmdSendHighScore) {

doAction(ACTION_SEND_HIGHSCORE); }

if (cmd == cmdReceiveHighScore) {

display(new Alert("Result", result, null, AlertType.INFO)); }

SMS

Một trường hợp sử dụng cho giao tiếp trong Java ME là để mời bạn bè tham gia chơi game. Bạn cũng có thể có một cuộc cạnh tranh trong bảng điểm số cao.

Thứ nhất, cài đặt phương thức gửi tin nhắn SMS trong lớp network.

publicboolean sendSms(String number, String message){

boolean result = true;

try {

//sets address to send message

String addr = “sms://”+number;

// opens connection

MessageConnection conn = (MessageConnection) Connector.open(addr);

// prepares text message

TextMessage msg = (TextMessage)conn.newMessage(MessageConnection.TEXT_MESSAGE); //set text msg.setPayloadText(message); // send message conn.send(msg); } catch (Exception e) { result = false; }

return result; }

Từ đoạn code ví dụ trên, bạn chỉ cần sử dụng phương thức open() của lớp Connector với định dạng URL là “sms://number”. Sau đó tạo một TextMessage và gửi nó thông qua

Connection.Kích thước của message được giới hạn trong 160 ký tự.

Tiếp theo, bạn tạo một form để nhận tên và số điện thoại từ người dùng như sau:

public Displayable initInviteForm() {

if (inviteForm == null) {

inviteForm = new Form(“Invite”); inviteForm.setCommandListener(this);

inviteForm.addCommand(initBackCommand());

inviteName = newTextField(“Name:”, “”, 20, TextField.ANY);

inviteNumber = newTextField(“Number:”, “”, 20, TextField.PHONENUMBER); inviteForm.append(inviteName);

inviteForm.append(inviteNumber);

comInviteSend = new Command(“Invite”, Command.ITEM, 1); inviteForm.addCommand(comInviteSend);

}

return inviteForm; }

Tiếp theo, trong phương thức commandAction(), bạn cài đặt code để hiển thị form và gửi message:

publicvoid commandAction(Command cmd, Displayable display) { [...]

elseif (display == inviteForm) { if (cmd == comBack) { display(initMainForm()); } if (cmd == comInviteSend) { doAction(ACTION_SEND_INVITE); } } [...] }

Cuối cùng, trong phương thức run(), bạn gọi phương thức sendSms() để gửi message:

publicvoid run() { [...]

case (ACTION_SEND_INVITE):

String inviteMessage = ” invites you to play Transnoid!”; network.sendSms(inviteNumber.getString(), inviteName.getString() + inviteMessage); break; } [..] }

Một phần của tài liệu Phát triển game đơn giãn trên máy tính nhanh nhất (Trang 34)