網頁

2010年3月29日 星期一

Android 貼圖教學,透明貼圖教學





遊戲設計最重要的一門課題,貼圖
觀看了月球登入的sample遊戲之後,發現月球登入使用了兩種方式的貼圖
貼圖之前必須要先將圖形放到資源檔裡,專案資料夾下方的res裡的drawable
到了2.0之後的版本,android會自動分出三個資料夾 drawable-h m L dpi 分別是讓開法者存放
不同解析度的圖形,因為現在手機的解析度已經亂的可以,低階手機到高階手機解析度都不一
該怎麼用我也還沒學到,實驗之後發現不管放在哪個資料夾都會自動更新到R.java裡面

關於該放什麼圖檔,還有透明的問題,Android 的貼圖看Sample裡並沒有特別寫到透明的程式碼
如果是Directx 的貼圖還需設定圖形透通顏色色定,不過在Android裡看來是不用寫任何程式碼,只要存放png圖檔,png圖檔本身就支援透明色,設定的透明色於android中的貼圖就自動的透明貼圖了,使用上還蠻方便的,不過這樣反而有個疑問是如果這張圖形是動態產生的,且想要透明怎麼辦
阿栽....... 有需要再來說。
先使用 jetboy裡的太空船,
把他copy到drawable-hdpi
第一種貼圖 宣告成
private Drawable PIC1;
取得資源檔圖形放入Drawable中
PIC1 = this.getResources().getDrawable(R.drawable.ship);

貼圖的方式
PIC1.setBounds(左x, 上y, 右x, 下y); //設定貼出範圍, 自動縮放圖形寬與高
PIC1.draw(canvas); //將圖形貼於canvas 畫布上


第二種貼圖方式
宣告成Bitmap 格式
private Bitmap PICBitmap;
取得資源檔圖形,轉換成Bitmap
PICBitmap = BitmapFactory.decodeResource(this.getResources() ,
R.drawable.ship);
//於x,y 貼出 沒有使用縮放圖形,原圖貼出
canvas.drawBitmap(PICBitmap, x, y, null);



完整程式碼
package com.DrawTest;


import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;

public class DrawTest extends Activity {
/** Called when the activity is first created. */
private Drawable PIC1;
private Bitmap PICBitmap;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyView myview = new MyView(this);
setContentView(myview);
PIC1 = this.getResources().getDrawable(R.drawable.ship);
PICBitmap = BitmapFactory.decodeResource(this.getResources() ,
R.drawable.ship);
}

private class MyView extends View
{
public MyView(Context context)
{
super(context);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Style.FILL);
canvas.drawCircle(120, 40, 30, paint);
canvas.drawRect(90,170,150,200, paint);
PIC1.setBounds(10, 10, 100, 100);
PIC1.draw(canvas);

PIC1.setBounds(120, 120, 200, 200);
PIC1.draw(canvas);

canvas.drawBitmap(PICBitmap, 0, 200, null);

}
}
}

附上小技巧 去掉標題bar的寫法圖片 與飛行船的貼圖測試

2010年3月25日 星期四

Android 繪圖

package Com.DrawTest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.view.View;

public class DrawTest extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyView myview = new MyView(this);
setContentView(myview);
}

private class MyView extends View
{
public MyView(Context context)
{
super(context);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Style.FILL);
canvas.drawCircle(120, 40, 30, paint);
canvas.drawRect(90,170,150,200, paint);
//canvas.drawBitmap(bitmap, matrix, paint)
}
}
}

2010年3月24日 星期三

Android Socket教學

Android是一隻網路功能強大的手機作業系統,網路的撰寫不算困難也很好玩
特別是連線對戰的遊戲,一群朋友一起拿著自己的手機和對方廝殺,這個畫面一定很有趣
今天先來解說一寫我在學習撰寫網路連線的時候遇到的一些困難和解決方法
介紹伺服端ServerSocket 物件
網路的連線一定要有一端當作主機(Server),一端當作客戶 (Client),Android裡將這兩種
連線方式分成兩種物件,分別是ServerSocket 和 Socket , 如果要開發主機端就使用ServerSocket物件, 開發客戶端就用Socket.

通常伺服端的撰寫流程都是 宣告ServerSocket物件->實體化並且傳入通訊Port->Accept等待連線->產生新的執行續,將Socket傳給新的執行續-> 回到Accept等待


ServerSocket主要功能就是聆聽Client的要求,並且產生新的socket和Clinet連線, ServerSocket的工作就告一段落,重新再度回到等待,至於和Clinet之前的傳送接收則是由新的新的執行續,和client去溝通。

宣告物件實體化如下
import java.net.ServerSocket;
public static final int SERVERPORT = 7777;
ServerSocket serverSocket = new ServerSocket(SERVERPORT);

會發這樣寫,於執行階段會產生一個權限問題,
Permission denied (maybe missing INTERNET permission)


只要在AndroidManifest.xml 裡設定新增 uses-permission 名字為 android.permission.INTERNET
或是於xml裡直接輸入


即可。

接下來
Accept等待連線->產生新的執行續,將Socket傳給新的執行續
Socket NewSocket = serverSocket.accept();

serverSocket.accept();會將程式阻塞,程式會停止在這裡不動,所以最好在使用serverSocket.accept()是一個不同於main的執行序,程式會一直等到有使用者者嘗試連線
程式才會繼續往下跑,並且產生一個NewSocket物件與 使用者進行互動連線

這時候如果還有其他使用者來要求連線,程式沒有辦法接受,要接受使用者要求連線必須讓程式
停在serverSocket.accept(); , 所以不建議accept之後就開始接收資料與回應資料,應立即產生新的執行序 並將NewSocket 交付出去,讓新的執行序執行傳送接收工作,並立刻回到serverSocket.accept();繼續等待連線,才可以服務多數使用者。

弄到這裡我們應該可以連線到android ,如果是實體手機是可以的,但如果是模擬器
需要如下動作

1.先啟動模擬器
2.再開啟 windows的CMD 執行 telnet 127.0.0.1 5554
5554代表模擬器的port
3.輸入
redir add tcp:7777:7777
打完之後 顯示ok表示成功。

這麼做的意思是,這台電腦接收到7777 port的資料請轉給 模擬器7777 裡面
例如再ie瀏覽器上 http://127.0.0.1:7777 使用debug就可以看到資訊已經送到模擬器裡



關於傳送接收,下回繼續。

2010年3月17日 星期三

MAC電腦視窗畫面截取,MAC畫面拍照

windows下想要截取視窗(拍照)只要按下print screen鍵就可以
但是在MAC下要拍螢幕上的畫面使用 Command + Shift + 4 三個按鈕
這時候滑鼠就會變成坐標的方式可以圈選所要拍照的範圍
如果要像windows那樣可以對單一視窗拍照,只要按下空白鍵
就可以對單一視窗拍照。

只是問題來了,畫面拍完了,照片在哪裡阿?
MAC的小畫家在哪裡呢?
這時候需要一套繪圖軟體,推薦GIMP
他是一套和photoshop可批敵的軟體,重點是他是免費且跨平台的繪圖軟體
不過下載的過程當中呢喃一下
windows xp 跳過vista 失敗的其中一項原因就是軟體支援度的問題
很多軟體在vista下沒有辦法執行,
但是在蘋果這樣的問題似乎是不被重視的,apple喜歡自斷筋骨
我改了作業系統,之前的程式幾乎都不能相容,強迫所有軟體廠商重新撰寫
其實這是很糟糕的現象.......

所以GIMP也要特地為 10.6 出一個版本,還好有出,要不然我也用不到這套軟體
抓以前的版本是沒有辦法相容的。


安裝完成GIMP就可以將拍照的話面貼到gimp中,然後存檔。




2010年3月15日 星期一

C#, 檔案是否存在,資料夾是否存在

加入參考
using System.IO;

判斷目錄是否存在

//判斷C槽是否存在
if (Directory.Exists("C:"))
{
//有
}

判斷檔案是否存在

//判斷執行檔路徑裡檔案CMD.txt是否存在
if (System.IO.File.Exists(Application.StartupPath + @"\COM.TXT"))
{
//有
}

C#儲存圖檔-小畫家3

儲存圖檔之前要先知道要儲存的檔案格式(BMP JPG GIF PNG)
而儲存圖檔的方式也很簡單,只要對BitMap 物件作Save 就可以
因為之前我們的範例都是使用BitMap 當作PictureBox的 Buffer
現在只要對Buffer 做SAVE就是把PICTUER 的圖形做儲存,
得知現在儲存的圖形格式有兩種方式,第一個方式是 對話方塊的過慮器
           saveFileDialog1.Filter = "逼恩批|*.bmp|傑批居|*.jpg|批恩居|*.png"; //檔案過濾器  
saveFileDialog1.InitialDirectory = Application.StartupPath; //程式啟動路徑,為預設路徑
saveFileDialog1.FileName = ""; //清除預設檔名
saveFileDialog1.ShowDialog(); //顯示對話方塊

if (openFileDialog1.FileName.Equals(""))
{
MessageBox.Show("取消選取");
}
else
{
switch (saveFileDialog1.FilterIndex)
{
case 1:
buffer.Save(saveFileDialog1.FileName , System.Drawing.Imaging.ImageFormat.Bmp);
break;
case 2:
buffer.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Jpeg );
break;
case 3:
buffer.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Gif );
break;
default:
break;
}
}

第二種方式,取出字串
再由字串比對

saveFileDialog1.Filter = "逼恩批|*.bmp|傑批居|*.jpg|批恩居|*.png"; //檔案過濾器  
saveFileDialog1.InitialDirectory = Application.StartupPath; //程式啟動路徑,為預設路徑
saveFileDialog1.FileName = ""; //清除預設檔名
saveFileDialog1.ShowDialog(); //顯示對話方塊

if (openFileDialog1.FileName.Equals(""))
{
MessageBox.Show("取消選取");
}
else
{
switch (saveFileDialog1.FileName.Substring(saveFileDialog1.FileName.Length - 3, 3).ToUpper())
{
case "BMP":
buffer.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
break;
case "JPG":
buffer.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case "GIF":
buffer.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Gif );
break;
case "PNG":
buffer.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Png );
break;
default:
MessageBox.Show ("錯誤檔名");
break;
}
}
看起來是第一種寫法比較好,第二種寫法單存練習,如何取出最後三個字元,然後將其大寫

2010年3月14日 星期日

C#讀取圖形-小畫家2

C#讀取圖形有點意外的簡單
於上一個章節已經學會對會方塊,現在我們使用對話方塊來讀取圖形
Graphics g = this.pictureBox1.CreateGraphics();
Bitmap br = new Bitmap(openFileDialog1.FileName) ;
//放置您所指定的圖片
//並指定圖片要放置的位置,(X,Y) = (0,0)
g.DrawImage(br, 0, 0);
支援的圖檔名稱還真不少,GIF.JPG.JPEG.BMP.WMF.PNG

不過這樣寫有個問題,就是畫面會消失,其他視窗蓋到畫面,圖形就被吃掉了,
用一個簡單的方法解決,建立一個Bimmap 對應到PictureBox.Image
只要PictureBox 被其他視窗擋到,PictureBox 自動重繪的時候就會去Image抓圖,

    public partial class Form1 : Form
    {
        Bitmap buffer;
        public Form1()
        {
            InitializeComponent();
            buffer = new Bitmap(pictureBox1.Width, pictureBox1.Height ); 
        }
        private void OpenFileButton_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "逼恩批|*.bmp|傑批居|*.jpg|批恩居|*.png"; //檔案過濾器
            openFileDialog1.Multiselect = false;                  //取消多從選擇 = 單選   
            openFileDialog1.InitialDirectory = Application.StartupPath;   //程式啟動路徑,為預設路徑
            openFileDialog1.FileName = "";                              //清除預設檔名
            openFileDialog1.ShowDialog();                                    //顯示對話方塊
            if  (openFileDialog1.FileName.Equals( "" ))
            {
                MessageBox.Show("取消選取" );  
            }
            else
            {
                buffer = new Bitmap(openFileDialog1.FileName);
                //放置您所指定的圖片
                //並指定圖片要放置的位置,(X,Y) = (0,0)
                pictureBox1.Width = buffer.Width;
                pictureBox1.Height = buffer.Height;
                pictureBox1.Image = buffer;
            }
        }
    }

C#對話方塊

我是一個不會C#的人
跟著書去學C# 很無趣,於是給自己定了一個目標,寫一個小畫家
第一部先建立一個介面,先學習怎麼使用C# 工作列
工作列這樣就可以了,使用起來就像是按鈕一樣。接著學習怎麼呼叫 WINDOWS的開啟檔案對話方塊
openFileDialog1.Filter = "逼恩批|*.bmp|傑批居|*.jpg|批恩居|*.png"; //檔案過濾器
openFileDialog1.Multiselect = false; //取消多從選擇 = 單選
openFileDialog1.InitialDirectory = Application.StartupPath; //程式啟動路徑,為預設路徑
openFileDialog1.FileName = ""; //清除預設檔名
openFileDialog1.ShowDialog(); //顯示對話方塊 if (openFileDialog1.FileName.Equals( "" ))
{
MessageBox.Show("取消選取" );
}
else
{
MessageBox.Show(openFileDialog1.FileName );
}

C#用起來就是這麼有成就感。

C#二進位檔讀取 存檔 文字檔讀取 存檔

對於檔案的處理,很多人都很害怕,特別是二進位存取,
聽到二進位的存取就莫名的害怕,
不過於C#這些東西都變的非常的簡單,因為C#的函數都幫使用者作好了
不需要瞭解太多,只需要會用就可以,至於怎麼撰寫不再多說因為書上很多
今天要說的是整理成一些方便的函數

成功失敗 = 讀取二進位檔( 路徑檔名 , ref 讀取的結果 )
成功失敗 = 寫入二進位檔( 路徑檔名 , 寫入的陣列 )
成功失敗 = 讀取文字檔( 路徑檔名 , ref 讀取的文字 )
成功失敗 = 寫入文字檔( 路徑檔名 , 寫入的文字 )

這裡大概有些人會驚訝,如果檔案很大,那陣列或是字串會不會死掉,
在C#裡的陣列大小可以定到 2G,也就是檔案如果小於2G都可以讀取近來
ㄧ個String的變數其實可以放到記憶體爆掉,不過當然我們不會做這麼危險的事情
但是把ㄧ整本書的文字都放在一個string的變數裡是輕而ㄧ舉的喔

所以就大膽的用下去,




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace AkingTool
{
class FileIOTool
{
public static int BinWrite(string SaveFileName, byte[] InData)
{
try
{
//開啟建立檔案
FileStream myFile = File.Open(SaveFileName, FileMode.Open , FileAccess.ReadWrite);
BinaryWriter myWriter = new BinaryWriter(myFile);
myWriter.Write(InData);
myWriter.Close();
myFile.Close();
return 1;
}catch (InvalidCastException e)
{
return -1;
}

}

public static int BinRead(string OpenFileName, ref byte[] InData)
{

try
{
//開啟檔案
FileStream myFile = File.Open(OpenFileName, FileMode.Open , FileAccess.ReadWrite);
//引用myReader類別
BinaryReader myReader = new BinaryReader(myFile);
int dl = System.Convert.ToInt32 (myFile.Length);
//讀取位元陣列
InData = myReader.ReadBytes(dl);
//讀取資料
//釋放資源
myReader.Close();
myFile.Close();
return 1;
}
catch (InvalidCastException e)
{
return -1;
}
}

public static int StringWrite(string SaveFileName, string InData)
{
try
{
//建立檔案
FileStream myFile = File.Open(SaveFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
StreamWriter myWriter = new StreamWriter(myFile);
//建立位元陣列
myWriter.Write(InData);
//釋放資源
myWriter.Close();
myFile.Close();
return 1;
}
catch (InvalidCastException e)
{
return -1;
}
}

public static int StringRead(string OpenFileName, ref string InData)
{
try
{
//開啟檔案
FileStream myFile = File.Open(OpenFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
//引用myReader類別
StreamReader myReader = new StreamReader(myFile);
int dl = System.Convert.ToInt32(myFile.Length);
//讀取位元陣列
InData = myReader.ReadToEnd();
//讀取資料
//釋放資源
myReader.Close();
myFile.Close();
return 1;
}
catch (InvalidCastException e)
{
return -1;
}
}
}
}
寫個範例讀寫一下



private void button1_Click(object sender, EventArgs e)
{
string G;
G = "abcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyz";
AkingTool.FileIOTool.StringWrite(@"c:\kkk", G);
}

private void button2_Click(object sender, EventArgs e)
{

string K = "";
AkingTool.FileIOTool.StringRead(@"c:\kkk",ref K);
MessageBox.Show(K);
}

private void button3_Click(object sender, EventArgs e)
{
byte[] S = new byte[1024 * 1024]; //寫出1M的檔案
S[10000] = 200;
AkingTool.FileIOTool.BinWrite(@"C:\Bin.bin", S);
}

private void button4_Click(object sender, EventArgs e)
{
byte[] ReadS = new byte[0]; //'讀取1M 的檔案,大小先設定為0 後來自動調整為 1M
AkingTool.FileIOTool.BinRead (@"C:\Bin.bin",ref ReadS);
MessageBox.Show ( ReadS[10000].ToString() );
}