投幣式净水機之耗水電量

投幣式净水機會耗電也繪水.所以要計算出成本.才能算出最終售價.因售水機內部設計統一所以其耗水電量均一至. 而且商業水電比家用要貴幾倍.

制水攻率 純水制水量 說明簡介
100W 63(L/H) 每小時制水63升.每度電可制升水630升.若每天售水1000升.則為1度電

 

純水與廢水比 說明簡介
1/3 每頓水喉水可制純水0.25頓.而廢水是0.75噸.因1噸=1000升.即每噸可制水250升.

 

每月售水 價格 商業水 商業電 成本/升 收益
1000升 5升2元 每頓5元 每度1.5元 0.0065 793.5

 

Android遊戲之『軸對齊邊界盒』碰撞

Android遊戲之『軸對齊邊界盒』碰撞

大部分模形都適合使用『圓形碰撞』.但若模形呈長條形則適合使用『矩形碰撞』.也稱為『軸對齊邊界盒碰撞』.特點是頂底邊與X軸平行,左右邊與Y軸平行.碰撞算法以包圍著對象最小矩形.但缺點是無法隨物體旋轉.速度快但精度較差.若定義矩形則由中心位置與長寬所組成.

public class RECT2D {

矩形中心位置

public VECTOR2D center;

矩形寬與高

public float  width;

public float  height;

購造『軸對齊邊界盒』輸入中心位置與寬高.

public RECT2D(float x,float y,float width,float height){

this.center = new VECTOR2D(x, y);    // 中心點

this.width  = width;

this.height = height;

}

『點』與『矩形』碰撞.若點為於四條邊之內則發生碰撞

public boolean overlap(VECTOR2D point){

if(point.x  < center.x + width/2 &&

point.x  > center.x – width/2 &&

point.y  < center.y + height/2 &&

point.y  > center.y – height/2 )

return true;

else

return false;

}

兩矩形碰撞測試,原點在左下角.算法睇上圖有D複雜.『矩形1左邊』在『矩形2右邊』之左則.『矩形1右邊』在『矩形2左邊』之右則.『矩形1底邊』在『矩形2頂邊』之下則.『矩形1頂邊』在『矩形2底邊』之上則.只要全部符合則兩矩形重疊.

public boolean overlap(RECT2D rect){

if(center.x – width/2 < rect.center.x + rect.width/2 &&

center.x + width/2 > rect.center.x – rect.width/2 &&

center.y – height/2 < rect.center.y + rect.height/2 &&

center.y + height/2 > rect.center.y – rect.height/2 )

return true;

else

return false;

}

『圓形』與『矩形』碰撞.原點在左下角.需先計算『矩形』與『圓心』之『最近點』.『圓心』在『矩形』之外.則『最近點』落在『矩形』邊緣之上.如果『圓心』在『矩形』之內.則『最近點』是『圓心』.然後計算『圓心』與『最近點』之距離.若小於『圓半徑』內則發生重疊.

public boolean overlap(CIRCLE2D circle){

float closestX = circle.center.x; // 圓心座標X

float closestY = circle.center.y;// 圓心座標Y

if(circle.center.x < center.x – width/2)

closestX = center.x – width/2;

else

if(circle.center.x > center.x + width/2)

closestX = center.x + width/2;

if(circle.center.y < center.y – height/2)

closestY = center.y – height/2;

else

if(circle.center.y > center.y + height/2)

closestY = center.y + height/2;

if(circle.center.DistSquared(closestX,closestY) < circle.radius * circle.radius)

return true; // 『圓』內則發生碰撞

else

return false; // 無發生碰撞

}

}

Android遊戲之2D圓形碰撞

Android遊戲之2D圓形碰撞

當物體移動並相互發生作用.需進行碰撞撿測.若重疊便發生碰撞.常見碰撞算法是通過『圓形邊界球』.它是包圍著對象最小圓. 無需隨物體旋轉而旋轉.所以速度最快之算法但精度較差.它由『圓心』與『半徑』所組成.

public class CIRCLE2D{

中心位置

public VECTOR2D center;

半徑

public float radius;

購造圓形邊界球,輸入中心位置與半徑.

public CIRCLE2D(float x,float y,float radius){

this.center = new VECTOR2D(x,y);

this.radius = radius;

}

『圓』與『點』碰撞檢測.計算『圓心』與『點』之距離.若距離小於『圓半徑』則發生碰撞.

public boolean overlap(VECTOR2D point){

float distance = center.Dist(point);

if(distance < radius  )

return true;// 發生碰撞

else

return false;// 無發生碰撞

}

兩圓形碰撞檢測.計算兩圓心『距離』.若『距離』小於兩圓半徑之和則發生碰撞

public boolean overlap(CIRCLE2D circle){

float distance = center.Dist(circle.center);// 兩圓之距

if(distance <= radius + circle.radius)

return true;// 發生碰撞

else

return false;// 無發生碰撞

}

『圓形』與『矩形』碰撞算法最為複雜.需先計算『矩形』與『圓心』最近之點.然後計算『圓心』與『最近點』之距離.若此點在『圓』內則發生重疊.

public boolean overlap(RECT2D rect){

float closestX = center.x; // 最接近X

float closestY = center.y;// 最接近Y

if(center.x < rect.center.x – rect.width/2)

closestX = rect.center.x – rect.width/2;

else

if(center.x > rect.center.x + rect.width/2)

closestX = rect.center.x + rect.width/2;

if(center.y < rect.center.y – rect.height/2)

closestY = rect.center.y – rect.height/2;

else

if(center.y > rect.center.y + rect.height/2)

closestY = rect.center.y + rect.height/2;

if(center.Dist(closestX,closestY) < radius)

return true; // 『圓』內則發生碰撞

else

return false; // 無發生碰撞

}

}

 

Android遊戲之FPS

Android遊戲之FPS

遊戲性能最重要指標FPS『每秒渲染幀量』遊戲越流暢FPS越高.不過所有Android手機都限制FPS最高60幀.若遊戲流暢FPS要高於30幀.下面代碼實現幀計數器

public class FPS {

返回納秒級時鐘.一納秒是一秒十億分之一

static private long startTime = System.nanoTime();

幀計數初此為零

static private int   frames = 0;

計算幀個數並在LOG『日誌』輸出.在GLSurfaceView.onDrawFrame(GL10 gl)中調用

static public void logFrame(){

幀個數加一

++frames;

每1秒輸出一次

if(System.nanoTime() – startTime >= 1000000000){

在LOG『日誌』輸出

Log.d(“FPS”,String.valueOf(frames));

幀個數清零

frames = 0;

更新納秒級時鐘

startTime = System.nanoTime();

}

}

}

 

 

Photoshop之繪畫遊戲地圖

Photoshop之繪畫遊戲地圖
Photoshop之繪畫遊戲地圖
Photoshop之繪畫遊戲地圖

在遊戲設計中『地圖』『背景』『人物動畫』都交給美術處理.若由程序員繪畫則成為噩夢.但『遊戲地圖生成器』Game Map Generator為一款Photoshop插件.可以幫助程序員在10分鐘內製作出專業級『地圖』.安裝Game Map Generator其實可直接拖入Photoshop空白位置完成安裝.

檔案->指令碼->瀏覽->載入『Game-Map-Generator-installer.jsx』

啟動Game Map Generator

視窗->延伸攻能-> Game Map Generator

新建地圖檔案

MAP->WIDTH『寬』填1200. HEIGHT『高』填800.按CREATE新建地圖檔案

渲染地面紋理

MAP->GROUND TEXTURE『地面紋理』有三款紋理可選『草地』、『荒地』、『雪地』

渲染網格

MAP->GRID『網格』有四款紋理可選『四邊網格』和『六邊網格』

設置等距變換

MAP->ISOMETRIC TRANSFORM『等距變換』選擇『圖層』後有五個方向可選.但每旋轉一次都會有變形損失.

渲染地形

ELEMENTS->ADD LAYER『+』新建圖層->BRUSHES『畫刷』有5款->繪畫任意地形->CHOOSE AN ELEMENT『選擇元素』

給地形繪畫紋理

TEXTURING『紋理』->BRUSHES『畫刷』有7款-> CHOOSE AN ELEMENT『選擇元素』18款地紋紋理可選『綠地』『草地』『荒地』『歸裂』『雪地』『地板』『熔岩』-> 給圖層繪畫任意形狀紋理

繪畫灌木

TEXTURING『紋理』-> BRUSHES『畫刷』->SPECIAL BRUSHES『灌木畫刷』可選『荊棘』『長草』『野花』-> 給圖層任意繪畫灌木

隨機生成紋理

TEXTURING『紋理』-> BRUSHES『畫刷』->RANDOM TEXTURES『隨機紋理』可選『蘑菇』『野花』『野草』

繪畫圖標『樹木』『岩石』『橋樑』『木屋』『金幣』

ICONS『圖標』-> CHOOSE AN ICON『選擇圖標』點選後可移動縮放

Android遊戲之2D矢量

Android遊戲之2D矢量

『矢量』Vector也稱『向量』它其實是『抽象量』.它可以有多種解析如『位置』『速度』『加速度』『方向』『距離』.因為用於2D遊戲開發定義2D『矢量』

public class VECTOR2D {

浮點數儲存2D矢量

public float x,y;

角度轉弧度

public static float DEGREES_TO_RADIANS = ((1.0f/180.0f)* (float)Math.PI);

弧度轉角度

public static float RADIANS_TO_DEGREES = ((1.0f/(float)Math.PI)*180.0f);

購造函式初此為0

public VECTOR2D(){

x=y=0;

}

購造函式並設定x與y

public VECTOR2D(float x,float y){

this.x = x;

this.y = y;

}

返回新2D『矢量』拷貝

public VECTOR2D Copy(){

VECTOR2D v;

v=new VECTOR2D(x,y);

return v;

}

重設2D矢量

public VECTOR2D set(VECTOR2D v){

this.x = v.x;

this.y = v.y;

return this;

}

2D矢量加法

public VECTOR2D Add(VECTOR2D v){

this.x = this.x + v.x;

this.y = this.y + v.y;

return this;

}

2D矢量減法

public VECTOR2D Sub(VECTOR2D v){

this.x = this.x – v.x;

this.y = this.y – v.y;

return this;

}

2D矢量乘法等於對矢量進行縮放.

public VECTOR2D Mul(float scalar){

this.x = this.x * scalar;

this.y = this.y * scalar;

return this;

}

計算2D矢量長度

public float Len(){

float len;

len = (float) Math.sqrt(xx+yy);

return len;

}

2D矢量單位化,長度為1

public VECTOR2D Normer(){

float len;

len = Len();

if(len != 0) {

x = x / len;

y = y / len;

}

return this;

}

計算2D矢量角度

public float Angle(){

float angle = 0;

angle = (float)Math.atan2(y,x)*RADIANS_TO_DEGREES;

if(angle<0)

angle += 360;

return angle;

}

計算兩2D矢量角度在(0~360)度之間

public float Angle(VECTOR2D v){

float angle = 0;

float distanceX,distanceY;

distanceX = this.x – v.x;

distanceY = this.y – v.y;

angle = (float)Math.atan2(distanceY,distanceX)*RADIANS_TO_DEGREES;

if(angle<0)

angle += 360;

return angle;

}

2D矢量繞原點旋轉, angle為旋轉角度

public VECTOR2D rotate(float angle){

float rad = angle * DEGREES_TO_RADIANS; // 角度轉弧度

float cos = (float) Math.cos(rad);

float sin = (float) Math.sin(rad);

float newX = this.x * cos – this.y * sin;

float newY = this.x * sin + this.y * cos;

this.x = newX;

this.y = newY;

return this;

}

計算兩個2D矢量之間距離

public float Dist(VECTOR2D v){

float distX = this.x – v.x;

float distY = this.y – v.y;

float dist = (float)Math.sqrt(distX*distX + distY * distY);

return dist;

}

計算兩2D矢量之間距離平方

public float DistSquared(VECTOR2D v){

float distX = this.x – v.x;

float distY = this.y – v.y;

float dist = distX*distX + distY * distY ;

return dist;

}

}

Android遊戲之2D相機

Android遊戲之2D相機

定義2D相機即設定『投影矩陣』與『視口』

『視口』用於控制輸出圖像尺寸與渲染幀緩存位置.OpenGL ES使用『視口』將投影到『近裁剪面』點座標變換為『幀緩存』像素座標

GL10.glViewport(int x,int y,int width,int height);

x和y座標為幀緩存區視口左上角.width和height為視口大小.單位為像素.幀緩存座標原點為屏幕左下角.通常將x和y設為0.width和height設為屏幕分辨率.即設為全屏.

gl.glViewport(0, 0, view.getWidth(), view.getHeight());

『投影矩陣』在2D相機中只使用『平行投影』.首先將當前矩陣設為『投影矩陣』

gl.glMatrixMode(GL10.GL_PROJECTION);

載入單位矩陣

gl.glLoadIdentity();

設置正交投影矩陣

GL10. glOrthof(int left,int right,int bottom,int top,int near,int far);

OpenGL ES座標系統正X軸指向右,正Y軸指向上.正Z軸指向我.left與right為X軸左右兩條邊.bottom與 top為Y軸上下兩條邊.near為近端裁剪面.far為遠端裁剪面.若設2D橫向相機左下角(0,0)右上角(480,320)視錐深度為2

gl.glOrthof(0,480,0,320,1, -1);

重設為模型視圖矩陣

gl.glMatrixMode(GL10.GL_MODELVIEW);

gl.glLoadIdentity();

2D相機將『觸屏』坐標轉『世界』坐標.首先設定視錐體寬為15高為10.

float frustum_width = 15;

float frustum_height = 10;

設縮放係數為1.用於放大屏幕大於1,縮小屏幕小於1

float zoom = 1;

首先將『觸屏』位置歸範圍(0~1).然後乘以視錐體寬和高

touch.x = (touch.x / view.getWidth()) * frustum_width * zoom;

因為觸屏座標原點位於屏幕左上角.需倒轉Y軸

touch.y = (1-touch.y /view.getHeight()) * frustum_height * zoom;

與相機位置相機

touch.add(position);

最後減於視錐體中心位置.得到遊戲『世界』坐標

touch.x = touch.x – frustum_width*zoom/2f;

touch.y = touch.y – frustum_height*zoom/2f;

 

Android遊戲之OpenGL ES

Android遊戲之OpenGL ES

OpenGL ES專為移動與嵌入設備設計之圖形編程接口. 它並非由ARB委員會定義.而是由Khronos組織定義.該組織包括ATI、NVIDIA、Intel等組成.雖然『OpenGL』與『OpenGL ES』來自兩個不同組織. 『OpenGL ES』係『OpenGL』刪減板.但你依然可寫出在兩種標準下都可運行之程式.這對於移植遊戲很重要.OpenGL ES同樣以C文檔發佈API.而代碼實現由硬件廠商完成.

如果AndroidManifest.xml中無配置glEsVersion,則表示支持OpenGL ES 1.0但所有Android系統都支持.若支持OpenGL ES 2.0需在AndroidManifest.xml中添加:

<uses-feature  android:required=”false”  android:glEsVersion=”0x00020000″ />

OpenGL ES版本號為32位整數.高16位表示OpenGL ES大版本,低16位表示OpenGL ES小版本.

required必須 簡介
true 必需支持否則不能運行
false 可選支持可能影響部分運行

 

OpenGL ES版本 glEsVersion
GLES 1.0 0x00010000
GLES 1.1 0x00010001
GLES 2.0 0x00020000
GLES 3.0 0x00030000
GLES 3.1 0x00030001
GLES 3.2 0x00030002

 

Photoshop之3D漢字

Photoshop之3D圖像
Photoshop之3D漢字
Photoshop之3D漢字

之前介紹『像素3D文字』效果須好.但在生成時『分辨率』要很大所以略有不便.這裡介紹『Ground Isometric Mock-Up』地面等距模型.『漢字』『英文』『圖像』『形狀』不論尺寸均支持.效果圖如上.安裝與使用方法如下:

  1. 最好用Adobe Photoshop CC 2014
  2. 轉換成英文版本
  3. 『Ground Isometric Mock-UP.atn』與『asl』兩個文檔直接拖入Photoshop空白位置即完成導入.在Actions窗口可查看
  4. 輸入『漢字』或『圖檔』並選定圖層
  5. 選定動作『Action』
  6. 按『動作播放』然後等待
動作Action 簡介
ONE Image::Depth-XX::Transform LEFT 左側3D高度1~5
ONE Image::Depth-XX::Transform RIGHT 右側3D高度1~5

 

Android遊戲之紋理映射

Android遊戲之紋理映射

將『Bitmap』加載給OpenGL ES然後加載到圖形卡記憶體重,並最終交給GPU渲染.因為OpenGL最終以三角形為單位進行渲染.而將『Bitmap』映射到三角形上.需要為三角形每個頂點設定紋理座標(texture coordinates).3D座標(x,y,z)和2D座標(x,y)對應紋理座標(u,v)位圖頂點.而(u,v)座標相當於(橫,縱)座標.紋理寬與高必需是2倍數.

紋理映射 (u,v)
左上角 (0,0)
右下角 (1,1)即使寬與高不相等
右上角 (1.0)
左下角 (0,1)

生成紋理隊列,用於保存紋理ID

int[] ids = new int[1];

生成紋理並獲取id.紋理依然為空

gl.glGenTextures(1, ids,0);

紋理id

int id = ids[0];

讀取位圖

Bitmap bitmap = BITMAP.Read(file_name);

獲取位圖寬度

int   width = bitmap.getWidth();

獲取位圖高度

int   height = bitmap.getHeight();

綁定2D紋理

gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

上傳2D紋理

GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bitmap,0);

設置紋理屬性指定縮小倍數過濾器

gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);

設置紋理屬性指定放大倍數過濾器

gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);

 

過濾 簡介
GL10.GL_NEAREST 像素採樣點最接近中心點『清晰』
GL10.GL_LINEAR 像素採樣點線性插值平均加權『模糊』

取消綁定紋理ID

gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);

回收位圖.以免浪費記憶體

bitmap.recycle();

每當Activity被暫停(APP切換)GLSurfaceView都會被銷毀.每當Activity恢復時調用GLSurfaceView. onResume()讓GLSurfaceView重構渲染界面.但OpenGL ES中上傳紋理都會丟失.你需要在onSurfaceCreated()中需重新載入並上傳紋理.

重新載入代碼見上文

Texture.load(filen_ame);

重新綁定紋理後設置紋理屬性

gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);

gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);

取消綁定紋理

gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);

 

當遊戲退出.便要刪除紋理釋放記憶體.首先取消紋理邦定

gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

刪除紋理

int[] ids = { id };

gl.glDeleteTextures(1,ids,0);

渲染三角形時要告知OpenGL要啟用紋理渲染

gl.glEnable(GL10.GL_TEXTURE_2D);

完成渲染後禁用紋理渲染

gl.glDisable(GL10.GL_TEXTURE_2D);

2D遊戲通常只佔用圖像一小片區域.需要將像素座標(x,y)轉換為紋理座標(u,v)

計算紋理座標左上角

u1 = x/texture.width;

v1 = y/texture.height;

計算紋理座標右下角

u2 = u1 + width/texture.width;

v2 = v1 + height/texture.height;