Android Studio NDK-assets遍歷文檔

謎語之摸蒞又冇烈
謎語之摸蒞又冇烈

assets讀文檔, 如果有大量文檔,要逐壹畀文檔路徑蒞讀, 更佳係『assets 裏邊.

將『文檔』擺係『檔案夾』. 然後遍歷『文檔』.

訪問『assets』檔案夾

AAssetDir * assetDir;

開啟文檔夾, dir』係『assets 裏邊

assetDir = AAssetManager_openDir(assetManager,dir);

失敗返回NULL

if(assetDir == NULL)

        return false;

遍歷文檔,

while((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {

組合『assets』『文檔』路徑.

sprintf(path, “%s/%s”, dir, filename);

閂檔案夾

AAssetDir_close(assetDir);

 

萬事得3珍珠白車漆修補

萬事得3珍珠白車漆修補
萬事得3珍珠白車漆修補

『萬事得3』褪車畀矮石碼, 刮花車左前門.

係填灰前需盡量修复明顯凹陷,減小填灰.

平整架餐『橋式修复』.

  1. 用800#砂紙磨刮痕,濕水磨
  2. 用酒精清洁
  3. 24V熱熔槍, 插入熱熔胶,預熱伍分鐘.
  4. 選擇合适吸盤, 凹陷深吸盤大, 凹位小吸盤細.
  5. 對吸盤涂膠. 均勻飽滿.
  6. 吸盤對正凹陷中㸃,撳住幾秒.
  7. 套金属橋身,撐兩側支腳,趁㬵未凍,擰螺帽拔复車身.
  8. 用酒精除殘膠.
  9. 此過程可能要重复多次.

 

明顯凹陷填灰平整表層.淺刮痕跳過.

  1. 用800#砂紙磨刮痕,濕水磨
  2. 『灰』同『固化劑』比例100:2
  3. 批刮填補凹陷.
  4. 等3日固化
  5. 濕水用800#砂紙磨,反复磨至光滑平整

 

清洁

  1. 用酒精酒精清洁脫脂
  2. 用報紙遮擋非車身區域

 

淺刮痕直接用,郡仕噴灰罐B524.

  1. 噴前搖60秒
  2. 秘決係离遠噴, 約摸10~15cm. 噴得太埋會留淚.
  3. 隔兩分鐘再噴
  4. 等1個鐘

 

噴漆

  1. 噴珍珠白底漆
  2. 噴珍珠白面漆
  3. 噴亮光金油

Android Studio NDK-OpenGL ES 觸屏坐標轉游㱆坐標

Android Studio NDK-OpenGL ES 觸屏坐標轉游㱆坐標
Android Studio NDK-OpenGL ES 觸屏坐標轉游㱆坐標

觸屏坐標』『x,y』坐標轉『正交投影』坐標, 『視錐體解像』寬高, 比例需手機解像寬高比壹致.

計屏幕寬高比

float aspect_ratio = (float)cam->real_width / (float)cam->real_height;

『視錐體解像』寬高,此時定義『高』800pix

float frustum_width    = 800 *aspect_ratio;
float frustum_height   = 800 ;

 

『正交投影』代碼

重置視區尺寸, 值係手機解像寬高

::glViewport(0,0,real_width,real_height);

設定投影矩陣

::glMatrixMode(GL_PROJECTION);

載入單位矩陣

::glLoadIdentity();

正交投影, 游戲坐標原點(0,0,0)為於屏幕中心

glOrthof(frustum_width / 2, frustum_width / 2, -frustum_height / 2, frustum_height / 2, pos.y – 10, far_clip_z);

設定模型視圖矩陣

::glMatrixMode(GL_MODELVIEW);

載入單位矩陣

::glLoadIdentity();

 

手指触摸手機屏幕onTouch() 所得坐標需轉游戲世界坐標,正交投影OpenGL游㱆+Z軸指向屏幕深處.

float touch3Dx = (touch2Dx / real_width) * frustum_width  ;
float touch3Dz = (touch2Dy /real_height) * frustum_height  ;

計3D相機位置

touch3Dx = touch3Dx + camPosX;
touch3Dz = touch3Dz + camPosX;

游戲坐標原點(0,0,0)為於屏幕中心

touch3Dx = touch3Dx – (frustum_width / 2.0f);
touch3Dz = touch3Dz – (frustum_height / 2.0f);

 

Android Studio NDK-OpenGL ES 漢字位圖字庫

Android Studio NDK-OpenGL ES 漢字位圖字庫
Android Studio NDK-OpenGL ES 漢字位圖字庫

『漢字字庫』同 『ASCII字庫』原理同, 字庫『竪排』, 漢字『32*32』pixel, 『竪』32漢字.

由上至下,由右至左排列.可填1024字符,每色8Bit. 即『索引色』『調色板』.

准備庫位圖

  1. 白紙黑字,
  2. 白色係透明色. 黑色係變換色.

Photoshop轉為『索引色』

  1. 『影像』->『模色』->『索引色』
  2. 『色盤』揀『正確』.
  3. 『顏色』量3
  4. 『强制』揀『黑白』
  5. 『透明』勾選
  6. 存為『.pcx』或『.bmp』

止時圖檔『調色板』共有三色『黑』『白』『透明』.

IMAGE-SIZE 1024*1024
FONT-SIZE 30pt
FONT 衡山毛筆フォント
FONT-PIXEL 32pixel*32pixel
影像-模色 索引色
色盤 正確
顏色 3
强制 黑白
透明 勾選

『調色板』結构同DirextX唔同, 將flags存alpha『透明值』0~255,0係『透明』,255係『實心』

typedef struct PALETTE_TYP {

BYTE red;

BYTE green;

BYTE blue;

BYTE flags;//alpha

} PALETTE,COLOR,* PALETTE_PTR,*COLOR_PTR;

設置『調色板』顏色

#define INIT_PALETTE(palette,r,g,b,a) {(palette).red=(r); (palette).green=(g); (palette).blue=(b); (palette).flags=(a);}

黑字『調色板』設置

index red green blue Alpha
253 0xff 0xff 0xff 0x00
255 0x00 0x00 0x00 0xFF*0.5f

白字『調色板』設置

index red green blue Alpha
253 0x00 0x00 0x00 0x00
255 0xff 0xff 0xff 0xFF*0.5f

半透明,激活混合

glEnable(GL_BLEND);

設混合模式, 渲染時Alpha值混合.

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

激活透明测试

glEnable(GL_ALPHA_TEST);

Alpha=0時, 過濾背影色

glAlphaFunc(GL_GREATER, 0);

 

等腰三角形

等腰三角形
等腰三角形

『等腰三角形』相等兩邊呌『腰』, 另壹邊呌『底』. 兩『腰』夾角叫『頂角』. 『腰』『底』夾角叫『底角』. 兩『底角』角度相等.

『等腰三角形』 簡述
『腰』 『等腰三角形』相等兩邊呌『腰』
『底』 另壹條邊
『頂角』 兩『腰』夾角
『底角』 『腰』『底』夾角, 兩『底角』角度相等.

計『等腰三角形』『頂角』 『底角』

cos(底角)=(底長/2)/ 腰長
底角 = acosf((底長/2)/ 腰長)

『三角形』內角之和180度.

底角+底角+頂角= 180

頂角 = 180 – 底角* 2

 

衡山毛筆フォント草書

衡山毛筆フォント草書
衡山毛筆フォント草書

書法家『青柳衡山』揮毫. 登録漢字最多草書字庫. 約萬餘字,公開免費,商業領域冇制限使用.有『TrueType』『OpenType』版. 將『KouzanBrushFontSousyo.ttf』『KouzanSoushoOTF.otf』字庫複製係『C:\Windows\Fonts』

衡山毛筆フォント草書 (揮毫/青柳衡山)
https://opentype.jp/kouzansousho.htm

 

衡山毛筆フォント

衡山毛筆フォント
衡山毛筆フォント

『經倫羅盤』需『漢字庫』, 書法家『青柳衡山』揮亳書寫. 登録萬三漢字.公開免費,商業領域冇制限使用.有『TrueType』『OpenType』版. 將『KouzanMouhituFont.ttf』『KouzanMouhituFontOTF.otf』字庫复制係『C:\Windows\Fonts』

衡山毛筆フォント
https://opentype.jp/kouzanmouhitufont.htm
C:\Windows\Fonts
毛筆體

 

 

爾靈山

爾靈山
爾靈山

儒略歴1904年皇軍為進攻龜縮『金州』『亞瑟港』 太平陽艦隊. 組建『第叁軍團』司令官『乃木希典』.

『亞瑟港』『要塞』冚辦爛用鋼筋水泥建造,『堡壘群』互聯互通, 炮台前方佈『地雷陣』『鐵絲網』, 係周邊佈『速射炮』『重機鎗』.『第叁軍團』死傷亡慘重, 幾近喪失戰力.改為進攻『貳零叁』高地, 從而通過掉炮燒滅『太平陽艦隊』.

『貳零叁』音近『爾靈山』,『乃木希典』鎮慰英魂賦詩『爾靈山』.

爾靈山瞼豈難攀
男子功名期克艱
鐵血覆山山形改
萬人齊仰爾靈山

『乃木希典』長子『乃木勝典』次子『乃木保典』皆戰死.

十ハ甫

殺人十ハ甫 填屍陸脈渠
殺人十ハ甫 填屍陸脈渠

『清國』順治七年番王『尚可喜』,率清軍攻陷『明國』最後都城『廣州』,明皇『朱聿𨮁』自縊.

『尚可喜』諗起舊頂頭『毛文龍』,畀東莞仔『袁崇煥』用尚方寶劍斬殺.下今從『西門』『殺人十ハ鋪』. 壹鋪拾里『十ハ鋪』指『百捌里』.

清軍於『天后廟』集結, 係『第壹津』沿路殺,『刀鋒過後血淋淋』殺到『十ハ甫』木牌下先抽刀入銷. 屍首填係『陸脈渠』.後世呌『殺人十ハ甫 填屍陸脈渠』.

 

Google nexus5 32GB

Google nexus5 32GB
Google nexus5 32GB
Google nexus5 32GB
Google nexus5 32GB
Google nexus5 32GB
Google nexus5 32GB
Google nexus5 32GB
Google nexus5 32GB

買Google nexus5『壹為神功,貳為弟子』,『壹蒞開發,貳還心愿』.機仔細細窄邊框.當年靚絕Android, 本蒞愛『Android 4』『黑蓋』寄蒞『Android 5』『白蓋』. 韓國LG制造港版,換新電包郵百肆蚊有找.部機吾升級係用吾到, 永遠話連吾到.

  1. 先升android 5.1, 再升5.11 吾停甘升, 最後升至android 6.01
  2. 去下載『google play 商店』, 擺係download安裝.
  3. 再升google play 服務.
  4. 孻屘升gmail郵箱, 登入google帳號.
Google nexus5 簡介
4.94英寸
解像 1920*1080
4000mAh
相機 1310萬
CPU 驍龍800
RAM 2GB
DISK 32GB
MODEL LG-D821港版

 

Android Studio NDK-触摸onTouch()

Android Studio NDK-触摸onTouch()
Android Studio NDK-触摸onTouch()

初台Android手機己采用『單點』触摸, 直至Android2.0(SDK version 5) 先支持『多點』触摸.

  1. Android觸摸監聽『OnTouchListener』 監聽 『触屏』事件.
static class TounchListener implements OnTouchListener{
  1. 通過『onTouch()』獲取『触屏』信息.
@Override

public boolean onTouch(View v, MotionEvent event) {

  1. 0(ÉCLAIR)(API 5) 先支持多點触摸
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR)
  1. 處理『多點』触摸
MultiTouch(v, event); else
  1. 處理『單點』触摸
SingleTouch(v, event);
  1. 返回false, 繼續處理觸摸事件.
return false;}

 

  1. 生成觸摸監聽
private static TounchListener Tounch_Listener  = new TounchListener() ;
  1. 為OpenGL View注冊触摸监听,
view.setOnTouchListener(Tounch_Listener);
  1. 通過OnTouch()(View v, MotionEvent event) 獲取『触屏』坐標 . 『触屏』原點(0,0) 係左上角, 單位象素
MotionEvent.getX() X軸指右
MotionEvent.getY() Y軸指下
  1. 獲取『触屏』事件類型 . MotionEvent.getAction()
MotionEvent.getAction()  
MotionEvent.ACTION_DOWN 手指撳屏
MotionEvent.ACTION_POINTER_DOWN 手指撳屏
MotionEvent.ACTION_UP 手指鬆离
MotionEvent.ACTION_POINTER_UP 手指鬆离
MotionEvent.ACTION_CANCEL 手勢鬆
MotionEvent.ACTION_MOVE 移動手指
  1. 『触屏』類型簡化為『撳』『鬆』『拖』三類
public static int ACTION_UP =     1;
public static int ACTION_DOWN = 2;
public static int ACTION_DRAGGED = 3;

 

 

 

 

處理『單點』触摸

static void SingleTouch(View v, MotionEvent event){
  1. 提取『触屏』事件類型
int action = event.getAction() & MotionEvent.ACTION_MASK;
  1. 處理『撳』類型
if(action == MotionEvent.ACTION_DOWN ||

action == MotionEvent.ACTION_POINTER_DOWN)

        Lib.setTouch(ACTION_DOWN,event.getX(),event.getY());else
  1. 處理『撳』類型
if(action == MotionEvent.ACTION_UP ||

action == MotionEvent.ACTION_POINTER_UP ||

action == MotionEvent.ACTION_CANCEL)

        Lib.setTouch(ACTION_UP,event.getX(),event.getY());else
  1. 處理『拖』類型
if(action == MotionEvent.ACTION_MOVE)
Lib.setTouch(ACTION_DRAGGED,event.getX(),event.getY());}

 

 

處理『多點』触摸

  1. 處理多手指触摸, 提取触摸事件索引
int Pointer_Index = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK)>>MotionEvent.ACTION_POINTER_ID_SHIFT;
  1. 通過触摸事件索引,『触屏』原點(0,0) 係左上角, 單位象素
MotionEvent.getX(index) X軸指右
MotionEvent.getY(index) Y軸指下
  1. 提取『触屏』事件類型
int action = event.getAction() & MotionEvent.ACTION_MASK;
  1. 處理多手指触摸, 提取触摸事件索引
int Pointer_Index = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK)>>MotionEvent.ACTION_POINTER_ID_SHIFT;
  1. 提取觸摸事件量
int Pointer_Count = event.getPointerCount();
  1. 遍歷冚觸摸事件
for(int i=0; i< Pointer_Count; ++i)        {
  1. 跳過冇關觸摸事件
if (action != MotionEvent.ACTION_MOVE && i != Pointer_Index)

continue;

  1. 處理『撳』類型
if(action == MotionEvent.ACTION_DOWN ||

action == MotionEvent.ACTION_POINTER_DOWN)

        Lib.setTouch(ACTION_DOWN,event.getX(i),event.getY(i));else
  1. 處理『撳』類型
if(action == MotionEvent.ACTION_UP ||

action == MotionEvent.ACTION_POINTER_UP ||

action == MotionEvent.ACTION_CANCEL)

        Lib.setTouch(ACTION_UP,event.getX(i),event.getY(i));else
  1. 處理『拖』類型
if(action == MotionEvent.ACTION_MOVE)
Lib.setTouch(ACTION_DRAGGED,event.getX(i),event.getY(i));}

 

 

係C++緩存『触屏』信息Lib.setTouch();

typedef struct TOUCH_STR{  
int action; 触屏類型
int x,y; 触屏坐標
}TOUCH,*TOUCH_PTR;  

『触屏座標』轉『熒屏座標』

void TouchToScreen(CAMERA2D_PTR cam,VECTOR2D_PTR touch){
touch->x = (touch->x / (float)cam->real_width) * cam->frustum_width * cam->zoom;
touch->y = (1-touch->y /(float)cam->real_height) * cam->frustum_height * cam->zoom; }

 

手機影印程式『Canon Print Service』

Canon Print Service
Canon Print Service
Canon Print Service
Canon Print Service

Mopria Paint』係Android手機平板發影印指令. 如果『Mopria Paint』報『ERROR CODE 853』, 可嘗試『Canon Print Service』,Canon專用Android影印機程式. 同『Mopria Paint』係『外掛程式』後台臺運行, 向Canon發影印指令.

  1. 係其它程式『文檔』『網頁』『影像』
  2. 撳『更多』『分享』
  3. 撳『Canon』.
  4. 自動跳入『影印設定』
  5. 揀『MF745C/746C(192.168.1.6)』
份數 1
紙張尺碼 ISO A4
色彩 黑色/彩色
方向 縱向/橫向
雙面 無/長邊/短邊
  1. 撳『影印』

Canon佳能MF746Cx 硒鼓 CRG055

墨粉余量狀態
墨粉余量狀態

Canon佳能MF746Cx 硒鼓 CRG055 Canon佳能MF746Cx 硒鼓 CRG055Canon佳能MF746Cx碳粉耗盡, 原厰 CGR-055硒鼓貴, 買副鼓有『廢粉㝫』『入粉㝫』.撳左側制翻蓋,抽出硒鼓匣, 排列按『Y』『M』『C』『K』

硒鼓 顏色
Y
M 洋紅
C
K
  1. 左右搖硒鼓,令碳粉勻循分佈.
  2. 抽封條, 揭護罩
  3. 裝入對應槽位.

係電腦睇『墨粉余量狀態』皆100%,提示非原厰厰硒. 影印OK.

Carmate車門防撞條細邊款 CZ494C

Carmate車門防撞條細邊款 CZ494C
Carmate車門防撞條細邊款 CZ494C
Carmate車門防撞條細邊款 CZ494C
Carmate車門防撞條細邊款 CZ494C
Carmate車門防撞條細邊款 CZ494C
Carmate車門防撞條細邊款 CZ494C

『萬事得3』新車落地『  錫』, 泊車位窄, 黐得埋推門易撞花『隔籬車』. 係車門邊裝膠條. Carmate CZ494C防撞條,細邊款睇起蒞唔顯眼. 係車門內側貼近門邊黐雙面膠, 否則唔得配合. 壹盒3m『萬事得3』要兩盒.

Android Studio 全屏CUTOUT MODE

Android Studio 全屏CUTOUT MODE
Android Studio 全屏CUTOUT MODE

全屏令人沉浸游戲免受干擾. 收埋頂『狀態』『標題』底『導航』.

  1. 舊時全屏係『Activity:onCreate()』飛『標題』
 requestWindowFeature(Window.FEATURE_NO_TITLE);
  1. 飛『狀態』
Window window =  getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
  1. 上述代碼需係『填充布局』前執行
setContentView(R.layout.activity_main);
  1. 亦可用『全屏样式』係『xml』
<style  name=”Theme.Fullscreen”  parent=”android:Theme.NoTitleBar.Fullscreen” />
  1. 係<application>或<activity>加『全屏样式』
<application android:theme=”@style/Theme.Fullscreen” >
  1. 因Android『導航』由硬件鍵變成『觸摸屏』軟件鍵, 要飛底『導航』飛頂『狀態』. 即『沉㓎模式』要係4 Kit Kat(API 19).
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
  1. 係『Activity:onCreate()』執行『setSystemUiVisibility()』設置沉浸模式
View decorView = window.getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |

View.SYSTEM_UI_FLAG_LAYOUT_STABLE |

View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |

View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |

View.SYSTEM_UI_FLAG_FULLSCREEN);

  1. 設置沉浸模式
setSystemUiVisibility() 簡述
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 飛底『導航』
View.SYSTEM_UI_FLAG_FULLSCREEN 飛頂『狀態』
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 自動恢復『沉㓎模式』
View.SYSTEM_UI_FLAG_IMMERSIVE 『沉㓎模式』
  1. 隨『全面屏』追求係手機頭『鑿窿』裝『相機』. 導置『全面屏』變『兔唇屏 』.即『CUTOUT MODE』要係Androd 9.0 Pie(API 28) 受支持.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
  1. 同係設布局『LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES』
WindowManager.LayoutParams param = window.getAttributes();
param.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
window.setAttributes(param);}

 

layoutInDisplayCutoutMode 簡述
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 全屏唔延伸至『兔唇 』, 非全屏延伸至『兔唇 』
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER WINDOW唔延伸至『兔唇 』
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 窻口延伸至『兔唇 』

 

Android 螢幕喚醒

Android 螢幕喚醒Android 螢幕耗電, 擺低手機螢幕變暗,幷鎖定. 好似你唔惏野會放蚊咁.用『喚醒鎖』WakLock. 保持清醒『螢幕喚醒』.

  1. 先係『xml』添加權限
<uses-permission android:name=”android.permission.WAKE_LOCK” />
  1. 係『onCreate()』獲得電源管理『PowerManager』
PowerManager powerManager;
powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
  1. 生成『WakLock』喚醒鎖. 『FULL_WAKE_LOCK』螢幕保持著燈.CPU全速運行.
PowerManager.WakeLock wakeLock;
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, “WAKE LOCK”);
  1. 係『onResume()』啟用『WakLock』喚醒鎖, 手機保持喚醒態,
wakeLock.acquire();
  1. 係『onPause()』釋放喚醒鎖
wakeLock.release();

 

 

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

 

Android Studio NDK-OpenGL ES 點陣字體

Android Studio NDK-OpenGL ES 點陣字體
Android Studio NDK-OpenGL ES 點陣字體

係游戲渲染文本,『點陣字體』係遠古技術, 係位圖繪畫ASCII字符, 哎『位圖字符glyph』,標准ASCII字符128,有96拉丁字母可渲染,從32到126.『32』係『吉格』.

位圖每行16字符. 位圖寬高符合2n.位圖『256256』每字符『1616』像素, 位圖『512512』每字符『3232』像素.

定義位圖字符

typedef struct FONT_TYP{
TEXTURE_PTR texture; 字庫紋理
DWORD   flag; 頂點標記
TEXTURE_REGION region[96]; 紋理區域
}FONT, * FONT_PTR;
  1. 拉丁字母
    for(int index = 0; index < 96; ++index){
  1. 生成ASCII字符UV 紋理坐標,『width, height』字符寬高,
Init_Region_Texture(&font->region[index],font->texture,x,y, width, height);
  1. 移動X坐標
x = x + width;
  1. 換行
if(x >= offsetX + width * row){

x = offsetX;

y = y + height;}

 

渲染位圖字庫

  1. 2D頂點座標數組
VECTOR2D  vertex_array[6 * 1024]   ;
  1. UV紋理座標數組
VECTOR2D  texCoord_array[6 * 1024] ;
  1. 啟用2D紋理映射
glEnable(GL_TEXTURE_2D);
  1. 禁用法線
glDisable(GL_NORMALIZE);
  1. 啓用透明測試
glEnable(GL_ALPHA_TEST);
  1. 指定透明色
    glAlphaFunc(GL_GREATER, 0);
  1. 綁定紋理
TEXTURE_PTR texture = font->texture;

glBindTexture(GL_TEXTURE_2D, texture->ID);

  1. 啟用頂點座標數組
glEnableClientState(GL_VERTEX_ARRAY);
  1. 啟用紋理座標數組
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

因為OpenGL『2D相機』原點『0,0』係『左下角』, 返䡛Y軸.

y = Font_frustum_height – y – height;
  1. 逐字渲染『ASCII碼』
for(int index = 0; index < length; ++index ){
  1. 『ASCII碼』轉『紋理索引』, 首ASCII碼係『吉格』,
int c = text[index] – ‘ ‘;
  1. 可渲染拉丁字母96, 『紋理索引』小於0大於96皆唔渲染.
if(c < 0 || c > 96)  continue;
  1. 得到紋理坐標
TEXTURE_REGION_PTR      region = &font->region[c];
  1. 計算2D頂點坐標, 雙『三角形』.
Init_VECTOR2D(&vertex_array[0 * 3 + 0], x, y + height);

Init_VECTOR2D(&vertex_array[0 * 3 + 1], x + width, y + height);

Init_VECTOR2D(&vertex_array[0 * 3 + 2], x + width, y);

Init_VECTOR2D(&vertex_array[1 * 3 + 0], x, y + height);

Init_VECTOR2D(&vertex_array[1 * 3 + 1], x + width, y);

Init_VECTOR2D(&vertex_array[1 * 3 + 2], x, y);

  1. 計算UV紋理坐標, 雙『三角形』.
Init_VECTOR2D(&texCoord_array[0 * 3 + 0], region->u1, region->v2);

Init_VECTOR2D(&texCoord_array[0 * 3 + 1], region->u2, region->v2);

Init_VECTOR2D(&texCoord_array[0 * 3 + 2], region->u2, region->v1);

Init_VECTOR2D(&texCoord_array[1 * 3 + 0], region->u1, region->v2);

Init_VECTOR2D(&texCoord_array[1 * 3 + 1], region->u2, region->v1);

Init_VECTOR2D(&texCoord_array[1 * 3 + 2], region->u1, region->v1);

  1. 指定頂點數組
glVertexPointer(2, GL_FLOAT, 0, vertex_array);
  1. 指定紋理座標
glTexCoordPointer(2, GL_FLOAT, 0, texCoord_array);
  1. 繪畫頂點數組,雙『三角形』.
glDrawArrays(GL_TRIANGLES, 0, 2 * 3 );
  1. 移動下壹渲染位, 分『橫排』同『縱排』
if(VH == FONT_HORIZONTAL)

x = x + width;

else

if(VH == FONT_VERTICAL)

y = y + height;}

  1. 禁用透明測試
glDisable(GL_ALPHA_TEST);
  1. 當前矩陣堆棧出棧
glPopMatrix();

 

ASCII數字 字符
0–31 控制字元,用于控制印表機等周邊設備
32-126 鍵盤字符
127 DELETE 命令
48-57 0-9
65-90 A-Z
97-122 a-z
128-255 擴展ASCII,增加特殊符號字符, 歐語字母和圖形符號

 

Photoshop位圖字符glyph
Pixel 32*32
Font Terminal Regular
Size 4pt
mid
Aa

 

十進制(DEC) 十六進制(HEX) ASCII字符 簡介
0 0x00 空格NUL(null)
1 0x01 標題開始 SOH(start of headling)
2 0x02 正文開始 STX (start of text)
3 0x03 正文結束 ETX (end of text)
4 0x04 傳輸結束 EOT (end of transmission)
5 0x05 請求 ENQ (enquiry)
6 0x06 收到通知 ACK (acknowledge)
7 0x07 響鈴 BEL (bell)
8 0x08 退格 BS (backspace)
9 0x09 水準跳位字元 HT (horizontal tab)
10 0x0A 換行鍵 LF (NL line feed, new line)
11 0x0B 垂直跳位字元 VT (vertical tab)
12 0x0C 換頁鍵 FF (NP form feed, new page)
13 0x0D 回車鍵 CR (carriage return)
14 0x0E 不用切換 SO (shift out)
15 0x0F 啟用切換 SI (shift in)
16 0x10 資料連結轉義DLE (data link escape)
17 0x11 設備控制1 DC1 (device control 1)
18 0x12 設備控制2 DC2 (device control 2)
19 0x13 設備控制3 DC3 (device control 3)
20 0x14 設備控制4 DC4 (device control 4)
21 0x15 拒絕接收 NAK (negative acknowledge)
22 0x16 同步空閒 SYN (synchronous idle)
23 0x17 傳輸塊結束 ETB (end of trans. block)
24 0x18 取消 CAN (cancel)
25 0x19 EM (end of medium)
26 0x1A 替補 SUB (substitute)
27 0x1B 溢出 ESC (escape)
28 0x1C 檔分割符 FS (file separator)
29 0x1D 分組符 GS (group separator)
30 0x1E 記錄分離符 RS (record separator)
31 0x1F 單元分隔符號 US (unit separator)
32 0x20 空格 (space)
33 0x21 ! 嘆號
34 0x22 雙引號
35 0x23 # 井號
36 0x24 $ 美元符
37 0x25 % 百分號
38 0x26 & 和號
39 0x27 閉單引號
40 0x28 ( 開括弧
41 0x29 ) 閉括弧
42 0x2A * 星號
43 0x2B + 加號
44 0x2C , 逗號
45 0x2D 減號/破折號
46 0x2E . 句號
47 0x2F / 斜杠
48 0x30 0
49 0x31 1
50 0x32 2
51 0x33 3
52 0x34 4
53 0x35 5
54 0x36 6
55 0x37 7
56 0x38 8
57 0x39 9
58 0x3A : 冒號
59 0x3B ; 分號
60 0x3C < 小於
61 0x3D = 等號
62 0x3E > 大於
63 0x3F ? 問號
64 0x40 @ 電子郵件符號
65 0x41 A
66 0x42 B
67 0x43 C
68 0x44 D
69 0x45 E
70 0x46 F
71 0x47 G
72 0x48 H
73 0x49 I
74 0x4A J
75 0x4B K
76 0x4C L
77 0x4D M
78 0x4E N
79 0x4F O
80 0x50 P
81 0x51 Q
82 0x52 R
83 0x53 S
84 0x54 T
85 0x55 U
86 0x56 V
87 0x57 W
88 0x58 X
89 0x59 Y
90 0x5A Z
91 0x5B [ 開方括號
92 0x5C \ 反斜杠
93 0x5D ] 閉方括號
94 0x5E ^ 脫字元
95 0x5F _ 下劃線
96 0x60 ` 開單引號
97 0x61 a
98 0x62 b
99 0x63 c
100 0x64 d
101 0x65 e
102 0x66 f
103 0x67 g
104 0x68 h
105 0x69 i
106 0x6A j
107 0x6B k
108 0x6C l
109 0x6D m
110 0x6E n
111 0x6F o
112 0x70 p
113 0x71 q
114 0x72 r
115 0x73 s
116 0x74 t
117 0x75 u
118 0x76 v
119 0x77 w
120 0x78 x
121 0x79 y
122 0x7A z
123 0x7B { 開花括弧
124 0x7C | 垂線
125 0x7D } 閉花括弧
126 0x7E ~ 波浪號
127 0x7F 刪除DEL(DELETE)
128 0x80 Ç Ccedil
129 0x81 ü uuml
130 0x82 é eacute
131 0x83 â circ
132 0x84 ä auml
133 0x85 à agrave
134 0x86 å aring
135 0x87 ç ccedil
136 0x88 ê ecirc
137 0x89 ë euml
138 0x8A è egrave
139 0x8B ï iuml
140 0x8C î icirc
141 0x8D ì igrave
142 0x8E Ä Auml
143 0x8F Å ring
144 0x90 É Eacute
145 0x91 æ aelig
146 0x92 Æ AElig
147 0x93 ô ocirc
148 0x94 ö ouml
149 0x95 ò ograve
150 0x96 û ucirc
151 0x97 ù ugrave
152 0x98 ÿ yuml
153 0x99 Ö Ouml
154 0x9A Ü Uuml
155 0x9B ¢ 美分(cent)
156 0x9C £ 英磅(pound)
157 0x9D ¥ 日元(yen)
158 0x9E
159 0x9F ƒ
160 0xA0 á aacute
161 0xA1 í iacute
162 0xA2 ó oacute
163 0xA3 ú uacute
164 0xA4 ñ ntilde
165 0xA5 Ñ Ntilde
166 0xA6 ª
167 0xA7 º
168 0xA8 ¿
169 0xA9
170 0xAA ¬
171 0xAB ½
172 0xAC ¼
173 0xAD ¡
174 0xAE «
175 0xAF »
176 0xB0
177 0xB1
178 0xB2
179 0xB3
180 0xB4
181 0xB5
182 0xB6
183 0xB7
184 0xB8
185 0xB9
186 0xBA
187 0xBB
188 0xBC
189 0xBD
190 0xBE
191 0xBF
192 0xC0
193 0xC1
194 0xC2
195 0xC3
196 0xC4
197 0xC5
198 0xC6
199 0xC7
200 0xC8
201 0xC9
202 0xCA
203 0xCB
204 0xCC
205 0xCD
206 0xCE
207 0xCF
208 0xD0
209 0xD1
210 0xD2
211 0xD3
212 0xD4 Ô
213 0xD5
214 0xD6
215 0xD7
216 0xD8
217 0xD9
218 0xDA
219 0xDB
220 0xDC
221 0xDD
222 0xDE
223 0xDF
224 0xE0 α 阿爾法(Alpha)
225 0xE1 ß 貝塔(beta)
226 0xE2 Γ Gamma
227 0xE3 π 圓周率(pi)
228 0xE4 Σ sigma
229 0xE5 σ sigma
230 0xE6 µ mu
231 0xE7 τ tau
232 0xE8 Φ PHi
233 0xE9 Θ Theta
234 0xEA Ω 歐米伽(Omega)
235 0xEB δ Delta
236 0xEC 無窮
237 0xED φ phi
238 0xEE ε epsilon
239 0xEF
240 0xF0
241 0xF1 ±
242 0xF2
243 0xF3
244 0xF4
245 0xF5
246 0xF6 ÷
247 0xF7
248 0xF8
249 0xF9
250 0xFA ·
251 0xFB
252 0xFC
253 0xFD ²
254 0xFE
255 0xFF ÿ

 

Android Studio NDK-OpenGL ES 透明glAlphaFunc()

Android Studio NDK-OpenGL ES 透明glAlphaFunc()
Android Studio NDK-OpenGL ES 透明glAlphaFunc()

係2D游戲位圖愛蒞做動畫, 要過濾『背景色』, 係Android OpenGL ES用alpha屏蔽『背景色』, 壹法位圖『A分量』Alpha = 0, 貳法黑色定為『背景色』係載入時將『A分量』Alpha = 0. 所以兩法要係『GL_RGBA』模式運運作.

RGBA8888位圖,RGB占24bit, Alpha 值A占8bit, 透明度範圍『0~255』. 『0』通透.『 255』實體.

設Alpha值 通透 實體
glAlphaFunc() 0.0 1.0
glAlphaFuncx() 0 255

若位圖冇Alpha 值, OpenGL ES 係載入時將Alpha值設1.

BGRA8888/ARGB8888 Alpha = 0
RGB656,RGB888,index R=0,G=0,B=0, 黑色
  1.  載入纹理圖形卡『RAM』, 設GL_RGBA模式
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width , height , 0, GL_RGBA, GL_UNSIGNED_BYTE,  image);
  1. 啓用透明測試
glEnable(GL_ALPHA_TEST);
  1. 設Alpha值過濾透明色
glAlphaFunc(GL_GREATER, 0);
glAlphaFuncx(GL_GREATER, 0);

 

Android Studio NDK-OpenGL ES-2D相機

Android Studio NDK-OpenGL ES-2D相機
Android Studio NDK-OpenGL ES-2D相機

OpenGL有『平行投影』同『透視投影』, 2D相機係『平行投影』生成方盒『視體』, 愛蒞剪裁物體, 唔係『視體』內唔『渲染』. 愛蒞『等比例游戲』『平面游戲』

OpenGL『2D相機』原點『0,0』係『左下角』, z軸遠端係負,近端正.

Android『熒屏』原點『0,0』係『左上角』,

  1. 首先指定『矩陣堆棧』為『投影矩陣堆棧』
glMatrixMode(GL_PROJECTION);
  1. 清除殘留矩陣并載入『單位矩陣』,.
glLoadIdentity();
  1. 重置視區尺寸,『視區』變換係『投影』變換之後,『x,y』左下角『0,0』. 『width,height』同視窗尺寸相應『熒屏像素』, 除非想係視窗一部分區域繪畫, 可設較定較細『視區』.
glViewport(x, y, window_width, window_height);
  1. 『平行投影』定方盒『視體』愛蒞剪裁物體, 而唔係3D相機錐形.『left, bottom』指左下角『0, 0』,『right, top』指右上角『width, height』. 熒屏尺寸設『800,600』或『640,480』. 游戲世界尺寸設『80,60』或『64,48』. OpenGL會自動放大與視區相配.『near, far』z軸剪裁面『1, -1』
glOrthof (left,right,bottom,top,near,far);
glOrthof (0, frustum_width, 0, frustum_height, 1, -1);
  1. 指定『視體』中心『x, y』.移動2D相機
glOrthof (x- width/2,  x+width/x, y-height/2, y+height/2, 1, -1);

 

glOrthof()  
『left, bottom』 左下角『0, 0』
『right, top』 右上角『width, height』
near z軸近端剪裁面
far z軸遠端剪裁面
  1. 恢復『矩陣堆棧』為『視圖矩陣堆棧』
glMatrixMode(GL_MODELVIEW);
  1. 載入『單位矩陣』,清除殘留矩陣
glLoadIdentity();

示例

void  Projection_Camera2D(CAMERA2D_PTR cam){

// 重置視區尺寸

::glViewport(0,0,cam->real_width,cam->real_height);

// 設爲投影矩陣

::glMatrixMode(GL_PROJECTION);

// 載入單位矩陣

::glLoadIdentity();

// 正交投影

glOrthof (0, cam->frustum_width, 0, cam->frustum_height, 1, -1);

// 設定模型視圖矩陣

::glMatrixMode(GL_MODELVIEW);

// 載入單位矩陣

::glLoadIdentity();

}

 

Android Studio NDK-獲取JavaVM

Android Studio NDK-獲取JavaVM
Android Studio NDK-獲取JavaVM

『JavaVM』指『Java虛擬機』, 壹進程『Process』壹『JavaVM』, 冚辦爛線程『Thread』共用壹『JavaVM』.

係原生代碼獲得『Java虛擬機』, 通過『JNI_OnLoad ()』函式, 載入共享庫『System.loadLibrary(“lib”);』,載入『LIB.SO』 會自動調用『JNI_OnLoad ()』. 將javaVm以全域變量儲存.

緩存JavaVM接口指針

JavaVM javaVm;
jint JNI_OnLoad (JavaVM* vm, void* reserved){

javaVm = vm;

return JNI_VERSION_1_4;

}

加入『jni.h』頭文檔聲明『Java原生接口』

#include <jni.h>

『JNI』指『Java Native Interface』『Java原生接口』,實現『JavaVM』同『Native』通信.『Java代碼』同『原生代碼』調用.

『JNIEnv』指向當前『線程局部數據』, 『線程局部數據』內含『原生函式指針列表』. 壹線程『thread』壹『JNIEnv』. 唔得跨線程『thread』傳遞彼此獨立,

事因『POSIX線程』唔屬于『JAVA』平臺, 導致『JAVA虛擬機』冇發識別『POSIX線程』,  為咗訪問『JAVA虛擬機』,『POSIX線程』線程先附係『JAVA虛擬機』再行.

  1. 將線程附著係JAVA虛擬機,獲得屬於本線程JNIEnv接口. 返回『零』成功,非『零』為錯誤碼
    if(javaVm->AttachCurrentThread(&env,NULL) == 0)
  1. 係JAVA虛擬機分離綫程.返回『零』成功,非『零』為錯誤碼
    if(javaVm->DetachCurrentThread() == 0)

 

Android Studio NDK-POSIX線程

Android Studio NDK-POSIX線程
Android Studio NDK-POSIX線程

Android_Studio_NDK_POSIX_Thread

Android Studio NDK-POSIX線程

『Android Studio NDK』生成『C/C++』線程,使用 POSIX線程簡稱『Pthreads』. 儒略歷1995年發布POSIX.1c『標准』『擴展』綫程.為線程定義『創建』『處理』API.『Micrsoft Windows』『Mac OS X』『Linux』冚辬蘭支持POSIX線程.

事因『POSIX線程』唔屬于『JAVA』平臺, 導致『JAVA虛擬機』冇發識別『POSIX線程』,  為咗訪問『JAVA虛擬機』,『POSIX線程』線程先附係『JAVA虛擬機』再行.

  1. 係『NDK』原生代碼用POSIX線程, 加入『h』頭文檔聲明『POSIX Thread APIs』, 係『Android』實現係『Bionic API』庫
#include <pthread.h> // POSIX線程
#include <jni.h>
  1. 用pthread_create()創建線程
int pthread_create(pthread_t * thread,

pthread_attr_t const * attr,

void *(* start_routine)(void *),

void * arg);

  1. 參數
參數 簡介
thread 返回新建綫程句柄
attr 指定線程屬性,傅NULL使用默認值.
start_routine 指向綫程函式地址,
args 線程函式參數
  1. 返回值
0 線程啟動
Error code 錯誤碼
  1. 線程句柄
pthread_t      threadID;
  1. 線程函式參數,要全域變量,若傳多參數要『struct』蒞封裝.
typedef struct OPENGL_TYP{

JNIEnv *env;//   JNI

AAssetManager * aassetManager;// 資源管理

EGLDisplay display ;

EGLSurface surface;// 內核渲染表層

int Width, Height;// 熒屏寬高

}OPENGL,*OPENGL_PTR;

  1. 綫程函式樣板
void * start_rountine (void * args)
  1. 游戲運行綫程實例
void * run_game(void * param){

while (run == true)    {

Update_World();// 更新

Draw_World();// 繪畫

}

}

  1. 緩存JavaVM接口指針
jint JNI_OnLoad (JavaVM* vm, void* reserved){

javaVm = vm;

return JNI_VERSION_1_4;

}

  1. 將線程附著係JAVA虛擬機,獲得屬於本線程JNIEnv接口. 返回『零』成功,非『零』為錯誤碼
    if(javaVm->AttachCurrentThread(&env,NULL) == 0)
  1. 係JAVA虛擬機分離綫程.返回『零』成功,非『零』為錯誤碼
    if(javaVm->DetachCurrentThread() == 0)
  1. 啟動線程
 if( pthread_create(&threadID,  NULL, run_game, openGL) == 0)

return true;

else

return false;

  1. 游戲運行綫程
void * run_game(void * param){

// 將線程附著係JAVA虛擬機,

if(javaVm->AttachCurrentThread(&env,NULL) != 0)

return NULL;

Init_Engine( ); // 初此引擎

Init_World( );  // 初此游戲世界

while (run == true)    {

Update_World();// 更新

Draw_World();// 繪畫

}

Shutdown_World();// 閂游戲世界

Shutdown_Engine();  // 閂引擎

// 係JAVA虛擬機分離綫程

javaVm->DetachCurrentThread();

return NULL;

}

之前係『JAVA Thread』行『ANativeWindow_fromSurface()』冇事,係『C/C++ Thread』行『ANativeWindow_fromSurface()』死機. 暈得壹陣陣.

Android Java 線程Thread()

Android Java 線程Thread()
Android Java 線程Thread()
  1. 係『Java』啟動線程
new Thread(this).start();
  1. 係『Java class』 加入『implements Runnable』愛蒞行線程代碼,
public class GameView extends SurfaceView implements   Runnable {}
  1. 運行線程代碼
@Override

public void run() {

while (true) {

//  Thread Code

}

}

 

Android Studio NDK-OpenGL ES封裝SurfaceView

Android Studio NDK-OpenGL ES封裝SurfaceView
Android Studio NDK-OpenGL ES封裝SurfaceView

係『Android OpenGL ES』用『SurfaceView』蒞畀『OpenGL ES』渲染. 之前『SurfaceView』代碼擺係『MainActivity.java』.更佳方法係『SurfaceView』『Runnable』『SurfaceHolder.Callback』封裝成單獨『GameView calss』.以保持代碼『簡潔』同埋『重用』.

  1. 新建『java』
『File->New->Java Class』
  1. 封裝『Runnable』『Callback』
public class GameView extends SurfaceView implements Runnable,SurfaceHolder.Callback{
  1. 『SurfaceView』變量
int view_width,view_height;

public SurfaceHolder surfaceHolder;

public Surface surface;//用蒞渲染

  1. 構造函數
public GameView(Context context) {

super(context);

init(context);// 設置渲染

}

public GameView(Context context, AttributeSet attrs) {

super(context);

init(context);// 設置渲染

}

public GameView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context);

init(context);// 設置渲染

}

  1. 初此渲染设置
public void init(Context context){

this.surfaceHolder = getHolder();

this.surfaceHolder.addCallback(this);

this.surface = surfaceHolder.getSurface();

}

  1. 創建表層,啟動渲染線程 run()
@Override

public void surfaceCreated(SurfaceHolder surfaceHolder){

new Thread(this).start();

}

  1. 表層改變, 當手機方向改變触發, 係游戲要禁止旋轉方向.
 @Override

public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height){

view_width = width;

view_height = height;

}

  1. 表層銷毀
@Override

public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

}

  1. 游戲運算渲染線程
@Override

public void run() {

AssetManager assetManager = getContext().getAssets();

Lib.init(assetManager, surface, view_width, view_height);

while (true) {// 請求渲染

Lib.update();

}

}

 

Android Studio NDK-Java原生接口(JNI)

Android Studio NDK-Java原生接口(JNI)
Android Studio NDK-Java原生接口(JNI)

Android Java原生接口(JNI) 令 『Java』 同『C\C++』代碼相互調用. 之前係『MainActivity.java』声明『native』原生代碼接口.

static public native String stringFromJNI();

『native-lib.cpp』『C\C++』代碼, 它編譯共享庫『.so』檔

extern “C” JNIEXPORT jstring JNICALL

Java_net_bookcard_compass_MainActivity_stringFromJNI(JNIEnv* env,jobject  this) {

return env->NewStringUTF(“native-lib”) ;

}

缺點係只能『MainActivity.java』調用, 更佳方發係將原生代碼接口擺係單獨『Java Class』. 并声明為『static』, 可係任意位置調用『C\C++』代碼.

  1. 新建『Class』
『File』->『New』->『Java Class』
  1. 新『Java Class』填『java』
  2. 載入共享庫”geomanticcompass.so”
static {

System.loadLibrary(“geomanticcompass”);

}

  1. 声明『native』原生『static』代碼接口.
static public native String stringFromJNI();

 

Android LocationManager.getBestProvider()返回NULL

Android LocationManager.getBestProvider()返回NULL
Android LocationManager.getBestProvider()返回NULL

『GPS』全球定位代碼,係『eclipse』移過蒞『Android Studio』, 發現getBestProvider()返回NULL. 源於冇『權限』 , 而『Android 6』後要人手獲得授權, 冇『權限』getBestProvider()永遠返回null. 係程式啟動檢查『權限』, 若冇『權限』提出請求伸請.

string GetBestProvider (Criteria criteria, bool enabledOnly)

『GPS』定位伸請『權限』

<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION”/>

『權限』

Manifest.permission.ACCESS_FINE_LOCATION 高精度定位
Manifest.permission.ACCESS_COARSE_LOCATION 低精度定位

檢查『權限』

int coarse = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION);
int fine = ContextCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION);

返回值判斷係咪獲得『權限』

PackageManager.PERMISSION_GRANTED 有『權限』
PackageManager.PERMISSION_DENIED 冇『權限』

判斷有冇『權限』

if(coarse == PackageManager.PERMISSION_DENIED || fine == PackageManager.PERMISSION_DENIED )

請求伸請. context必需係Activity

String permission[] = new String[] { Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION};
ActivityCompat.requestPermissions((Activity) context,permission,REQUEST_CODE_GPS);

GPS權限請求碼

public static int REQUEST_CODE_GPS = 156;

處理GPS授權回調, 係MainActivity判斷授權

@Override

public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){

requestCode係權限請求碼

if(requestCode == GPS.REQUEST_CODE_GPS) {// 羅盤權限請求碼

判斷『權限』係咪獲得

if(grantResults[0] == PackageManager.PERMISSION_GRANTED &&

grantResults[1] == PackageManager.PERMISSION_GRANTED) { // 獲得授權

再次定位

GPS.UpdatesLocation();

交翻畀onRequestPermissionsResult()處理

   super.onRequestPermissionsResult(requestCode,permissions,grantResults);

}

 

 

Android Studio代碼提示失效

Android Studio代碼提示失效
Android Studio代碼提示失效

編寫『Android』高效歸功於『Android Studio』代碼提示, 近排『Android Studio』冇咗提示, 令『import』冇發自動填寫,源於啟用『Power Save Mode』造成提示失效. 要啟用『代碼提示』禁用『Power Save Mode』.

『File』->『Power Save Mode』

 

Android Studio NDK-OpenGL ES 『正交投影』

Android Studio NDK-OpenGL ES 『正交投影』
Android Studio NDK-OpenGL ES 『正交投影』

3D游戲基于『透視投影』產生立體效果, 而2D游戲戲用『正交投影』產生平面效果, 生成等比例游戲.

  1. 指定視區像素尺碼, 『x』 『y』視區左下角,『width』 『height』視區寬高
glViewport(0,0,width, height);
  1. 設定『矩陣堆栈』為『投影矩陣堆栈』
glMatrixMode(GL_PROJECTION);
  1. 載入單位矩陣, 清除『堆栈』残留『矩陣』,以此唔受先前變换運算影响.
glLoadIdentity();
  1. 『正交投影』運算, Y軸視角『fovy』,Z軸視角『aspect』, 『zNear』近裁剪面距离约摸箱機方向Y軸加 『zFar』远裁剪面距离設較大数值.
gluOrtho( fovy, aspect, zNear, zFar );
  1. 設定『矩陣堆栈』為『模型視圖矩陣堆栈』
glMatrixMode(GL_MODELVIEW);
  1. 載入單位矩陣
glLoadIdentity();

 

基於視角『正交投影』

void gluOrtho(double  fovy,double aspect,double zNear,double zFar){

double  xmin, xmax, ymin, ymax;

ymax = zNear * tan(fovy * 3.141592654f / 360.0f);

ymin = -ymax;

xmin = ymin * aspect;

xmax = ymax * aspect;

glOrthof(xmin, xmax, ymin, ymax, zNear, zFar);

}

 

Android Studio 展現『Structure』

Android Studio 展現『Structure』
Android Studio 展現『Structure』

係『VC6』有『struct』同『Function』检索下拉窗口,可迅速定位代碼. 令工作事半工倍.

係『Android Studio』『struct』同『Function』检索視窗默認收埋.

  1. 撳『View』->『Tool Windows』->『Structure』展現『Structure』視窗
  2. 撳『Alt+7』展現『Structure』視窗
  3. 撳『Show Options Menu』->『Move To』->『Right Top』置於右上角

 

Android Fullscreen 全屏樣式

Android Fullscreen 全屏樣式
Android Fullscreen 全屏樣式

Android Studio設置全屏,通過編輯『themes.xml』

『themes.xml』
<style  name=”Theme.Fullscreen”  parent=”android:Theme.NoTitleBar.Fullscreen”>

編輯『AndroidManifest.xml』

『AndroidManifest.xml』
<application android:theme=”@style/Theme.Fullscreen”>

代碼係『eclipse』移稙過蒞, 『Android Studio』程式閃退. 因『MainActivity』繼承『AppCompatActivity』造成. 改為繼承『Activity』.

public class MainActivity extends  Activity

 

Android Studio NDK-OpenGL ES/EGL渲染

Android Studio NDK-OpenGL ES/EGL渲染
Android Studio NDK-OpenGL ES/EGL渲染

OpenGL EGL作為平臺冇関 API, 今程序冇視『Linux X Window』『Microsoft Windows』『Mac OS X Quatz』差異.用統壹接口同原生視窗聯接. 跨平臺API更易於移值. 所以OpenGL比DirectX更得人鐘意.

  1. 使用NDK
  2. 編譯OpenGL ES
  3. 布局OpenGL ES
  4. 先加入頭文檔
#include <GLES/gl.h> 標準OpenGL頭文檔
#include <GLES/glext.h> OpenGL實用架餐庫
#include <EGL/egl.h> EGL庫
#include <EGL/eglext.h> EGL架餐庫
#include <android/native_window_jni.h> 原生視窗庫ANativeWindow
  1. 冚辦爛EGL程式首先調用『eglGetDisplay()』, 得到『EGLDisplay』等同『原生視窗』, 『EGLDisplay』係整數索引.
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  1. 索引大於零即成功, 因為等於零失敗.
EGL_NO_DISPLAY 0失敗
  1. 初始EGL程式, 幷獲得『major』主版號 , 『minor』副版號
EGLint major,minor;

eglInitialize(display,&major,&minor)  ;

  1. 失敗返回EGL_FALSE, 查錯誤碼eglGetError()
EGL_BAD_DISPLAY 非有效EGLDisplay
EGL_NOT_INITALIZED 未能初始
  1. 穩『surface』渲染配置
EGLBoolean eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
  1. EglChooseConfig()函式參數
參數 簡介
EGLDisplay dpy 『原生視窗』索引
EGLint *attrib_list 指定屬性列表, 以EGL_NONE結屘
EGLConfig *configs 返回配置列表
EGLint config_size 指定配置列表長度
EGLint *num_config 返回配置長度
  1. 『EGLConfig』屬性
屬性 描述
EGL_SURFACE_TYPE EGL渲染表面類型 EGL_WINDOW_BIT
EGL_RENDERABLE_TYPE OpenGL版本 EGL_OPENGL_ES_BIT
EGL_RED_SIZE 紅色量位 8Bit
EGL_GREEN_SIZE 綠色量位 8Bit
EGL_BLUE_SIZE 藍色量位 8Bit
EGL_ALPHA_SIZE 透明量位 8Bit
EGL_DEPTH_SIZE 深度量位 16Bit
EGL_NONE 屬性列表以EGL_NONE結屘 0

屬性列表

EGLint    attrib_array[32];
  1. 設定『EGLConfig』屬性
attrib_array[0] = EGL_SURFACE_TYPE; attrib_array[1] = EGL_WINDOW_BIT;
attrib_array[2] = EGL_RENDERABLE_TYPE; attrib_array[3] = EGL_OPENGL_ES_BIT;
attrib_array[4] = EGL_RED_SIZE; attrib_array[5] = 8;
attrib_array[6] = EGL_GREEN_SIZE; attrib_array[7] = 8,
attrib_array[8] = EGL_BLUE_SIZE; attrib_array[9] = 8;
attrib_array[10] = EGL_ALPHA_SIZE; attrib_array[11] = 8;
attrib_array[12] = EGL_DEPTH_SIZE; attrib_array[13] = 16;
attrib_array[14] = EGL_NONE;  
  1. 據 attrib_array 返回最隹配置config
EGLint    config_number = 32;

EGLConfig config_array[32];

EGLConfig  config;// 配置

eglChooseConfig(display,attrib_array,config_array,config_number,&config_number);

  1. 匹配最佳配置
for(int i=0;i<config_number;++i)    {

eglGetConfigAttrib(openGL->display, config_array[i],EGL_RED_SIZE, &red);

eglGetConfigAttrib(openGL->display, config_array[i],EGL_GREEN_SIZE, &green);

eglGetConfigAttrib(openGL->display, config_array[i],EGL_BLUE_SIZE, &blue);

eglGetConfigAttrib(openGL->display, config_array[i],EGL_ALPHA_SIZE, &alpha);

eglGetConfigAttrib(openGL->display, config_array[i],EGL_DEPTH_SIZE, &depth);

if( red == 8 && green == 8 && blue == 8 && alpha == 8 && depth == 16){

openGL->config = config_array[i];// 最佳配置

break;

}

}

  1. 生成渲染視窗
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
  1. eglCreateWindowSurface()函式參數
參數 簡介
EGLDisplay dpy 『原生視窗』索引
EGLConfig config 最佳配置
EGLNativeWindowType win SurfaceView
const EGLint *attrib_list 屬性列表
  1. 渲染視窗屬性
視窗屬性 描述
EGL_RENDER_BUFFER 渲染緩存 EGL_SINGLE_BUFFER『單緩存』EGL_BACK_BUFFER『雙緩存』
EGL_NONE 屬性列表以EGL_NONE結屘 0
  1. 屬性
attrib_array[0] = EGL_RENDER_BUFFER; attrib_array[1] = EGL_BACK_BUFFER;
attrib_array[2] = EGL_NONE;  
  1. 生成渲染視窗
surface_draw = eglCreateWindowSurface(display,config,nativeWindow,attrib_array);
  1. 獲得錯誤碼
錯誤碼EGLint error = eglGetError(); 簡介
EGL_BAD_MATCH 視窗唔匹配EGLConfig唔支持渲染
EGL_BAD_CONFIG 視窗唔匹配EGLConfig系統晤支持
EGL_BAD_NATIVE_WINDOW 原生視窗句柄冇效
EGL_BAD_ALLOC 冇法分配資源
  1. 關聯描述表, 将『EGLContext』『EGLSurface』與當前線程關聯, 『EGL』同『OpenGL』代碼需擺同壹綫程. 唔系eglSwapBuffers()返回
eglMakeCurrent(display,surface_draw,surface_draw,context);
  1. 『Native』層用『ANativeWindow 』蒞渲染.通過『Surface』得到『ANativeWindow』.
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface)
  1. Android 『java』層用『SurfaceView』蒞渲染, 提取『Surface』畀『Native』
SurfaceView surfaceView = (SurfaceView)findViewById(R.id.surface_view);
SurfaceHolder     surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
Surface             surface = surfaceHolder.getSurface();

Android Studio NDK-OpenGL ES布局

Android Studio NDK-OpenGL ES布局
Android Studio NDK-OpenGL ES布局

『Android Studio NDK』提供『EGL』連接『OpenGL』, 『EGL』被設計出來,作爲 OpenGL 和原生窗口系統之間的橋梁『Microsoft Windows』『Mac OS X Quatz』差異.用統壹接口同原生視窗聯接. 跨平臺API更易於移值. 所以OpenGL比DirectX更得人鐘意.

  1. 使用NDK
  2. 編譯OpenGL ES
  3. 載入共享庫”app.so”,『app』系你庫名.
static {

System.loadLibrary(“app”);

}

  1. 首先修改布局『xml』添加『SurfaceView』,而非『GLSurfaceView』.
 <android.view.SurfaceView

android:layout_width=”match_parent”

android:layout_height=”match_parent”

android:id=”@+id/surface_view” />

  1. 係『xml』添加『全屏樣式』
<style  name=”FullscreenTheme”  parent=”android:Theme.NoTitleBar.Fullscreen”  >
  1. 係『java』加『android.view.SurfaceHolder.Callback』用蒞行『SurfaceView』『創建』『改變』『銷毀』
        @Override

public void surfaceCreated(SurfaceHolder surfaceHolder) {

new Thread(this).start();//渲染,啟動線程  Runnable.run()

}

        @Override

public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

}

        @Override

public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

}

  1. 係『java』加『Runnable』用蒞行OpenGL 渲染線程, 『EGL』同『OpenGL』代碼需擺同壹綫程. 唔系eglSwapBuffers()返回EGL_BAD_SURFACE.
    @Override

public void run() {

init( );

while (true) {

update(0);

}

}

  1. 係『xml』為Google Play加版本過濾
<uses-sdk        android:minSdkVersion=”9″       android:targetSdkVersion=”19″ />
  1. 係『txt』穩庫文檔
find_library( OpenGL-lib libGLESv1_CM.so  )
find_library( OpenEGL-lib libEGL.so )
find_library( Android-lib libandroid.so )
  1. 係『txt』連連接庫文檔
target_link_libraries(app

${OpenGL-lib}

${OpenEGL-lib}

${Android-lib})

  1. 加入頭文檔
#include <GLES/gl.h> 標準OpenGL頭文檔
#include <GLES/glext.h> OpenGL架餐庫
#include <EGL/egl.h> EGL頭文檔
#include <EGL/eglext.h> EGL架餐庫
#include <android/native_window_jni.h> 原生視窗庫

 

Android Studio NDK-OpenGL ES-3D相機gluPerspective()

Android Studio NDK-OpenGL ES-3D相機gluPerspective()
Android Studio NDK-OpenGL ES-3D相機gluPerspective()

將『OpenGL』移稙過『Andord』. 但OpenGL ES偏偏冇gluPerspective()視錐投影.但有glFrustumf()設定視口.

通過glFrustumf()設置視口, 得到 gluPerspective()視錐投影.
void gluPerspective(double  fovy,double aspect,double zNear,double zFar){

double  ymax = zNear * tan(fovy * 3.141592654f / 360.0f);

double  ymin = -ymax;

double    xmin = ymin * aspect;

double    xmax = ymax * aspect;

glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);

}

3D相機投影代碼

glViewport(0,0,viewport_width,viewport_height); 重置視區尺寸
glMatrixMode(GL_PROJECTION); 設定投影矩陣
glLoadIdentity(); 載入單位矩陣
gluPerspective(fov,aspect_ratio,near_clip_z,far_clip_z); 設置視錐體投影
glMatrixMode(GL_MODELVIEW); 設定模型視圖矩陣
glLoadIdentity(); 載入單位矩陣

 

Android Studio NDK-OpenGL-交換緩存畫面eglSwapBuffers()返回EGL_BAD_SURFACE

Android Studio NDK-OpenGL-交换緩存画面eglSwapBuffers()返回EGL_BAD_SURFACE
Android Studio NDK-OpenGL-交换緩存画面eglSwapBuffers()返回EGL_BAD_SURFACE

將『風水羅盤』由『Windows』移稙過『Andord』. 係交換緩存畫面『eglSwapBuffers()』返回『EGL_FALSE』, 『eglGetError()』返回『EGL_BAD_SURFACE』.

EGLBoolean ret = eglSwapBuffers(display,surface);

if(ret == EGL_FALSE){

GLint error = eglGetError();

if(error == EGL_BAD_SURFACE){

}

}

係『Windows』有『Winmain()』入口. 可以控制冚個整游戲運作, 係 『Winmain()』 游戲『運行』『渲染』都係主線程行.

而 『Andord』冇『Winmain()』. 游戲『運行』『渲染』要係新線程『Thread()』行. 而『EGLContext』同『EGLSurface』需係同壹線程『Thread()』生成, 唔係『eglSwapBuffers()』投『EGL_BAD_SURFACE』錯誤碼.

知錯係邊就易整, 將egl()程式擺係新線程『Thread()』行,而非『 onSurfaceCreated()』.

新線程『Thread()』
EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id);
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);

 

 

Android Studio NDK- assets訪問讀

Android Studio NDK- assets讀係Android游戲唔將游戲資源擺係『res』而係『assets』, 事因『res』限制層次結構, 而『assets』允許任意檔案資料夾層次結構.位於『assets』檔案只讀唔寫. NDK需android 9版先支持.

係『CMakeLists.txt』添加『libandroid.so』庫

CMakeLists.txt
find_library( Android-lib libandroid.so )
target_link_libraries( geomanticcompass

${OpenGL-lib}

${OpenEGL-lib}

${Android-lib}

${log-lib})

係c檔案加入頭檔

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>

『assets』檔通過『AssetManager』訪問

AssetManager assetManager = this.getAssets();

係『NDK』『assets』檔通過『AAssetManager』訪問, 『AAssetManager』接口

AAssetManager* AAssetManager_fromJava(JNIEnv* env, jobject assetManager);

將『AssetManager』傳過去獲得『AAssetManager』

extern “C”

JNIEXPORT void JNICALL Java_net_bookcard_geomanticcompass_MainActivity_init(JNIEnv *env, jobject thiz, jobject egl_config, jobject asset_manager) {

AAssetManager *assetManager= AAssetManager_fromJava(env, asset_manager);

}

public native void init(AssetManager asset_manager);
init (getAssets());

 

開啟『assets』檔, 冇需畀絕對路徑, 而係畀『assets』相對路俓

AAsset *asset = AAssetManager_open(nativeasset, “name.bmp”, AASSET_MODE_BUFFER);

檔长度

int size = AAsset_getLength(asset)

分配記憶體

PBYTE data = (PBYTE)malloc(size);

讀『assets』檔

AAsset_read(asset, data, size);

載入分析

Load(data, size);

释放记忆体

free(data);

閂『assets』檔

AAsset_close(asset);

 

將游戲資源擺係『assets』下,『assets』『res』同位於『app\src\main』之下.

檔案資料夾 位置
assets D:\Android\game\app\src\main\assets
cpp D:\Android\game\app\src\main\cpp
java D:\Android\game\app\src\main\java
res D:\Android\game\app\src\main\res

 

 

Android Studio NDK-Frames幀

Android Studio NDK-Frames幀
Android Studio NDK-Frames幀

係游戲每『渲染』1『畫面』呌1『幀』Frame,  影書每秒24格『菲林』24『幀』, Android每秒至高60『幀』.

Android Studio NDK

  1. 通過clock()獲得進程時鐘 度量時間整數值.
  2. 通過sysconf(_SC_CLK_TCK) 獲得時鐘信號, 每秒時鐘單元值, 係Linux此值為100
  3. 計算秒 float seconds= (float)clock() / (float)sysconf(_SC_CLK_TCK);
#include <time.h>
clock_t clock(void)

 

#include <unistd.h>
long sysconf(int name)

 

量度程式耗時

long  clockTicks = sysconf(_SC_CLK_TCK);// 時鐘信號

clock_t startTime = clock();//當前時鈡

// 調用程式

clock_t currentTime = clock();//當前時鈡

float seconds = (float)(currentTime – startTime) / (float)clockTicks;

 

需要struct結構用蒞計『幀』Frame, 公式加下:

float _fps = Frames * (double)(currentTime – startTime) / (float)clockTicks ;

 

『幀』Frame
typedef struct FPS_TYP {

clock_t  startTime;// 啓動時鐘

long  clockTicks;// 時鐘信號

float Frames;// 每秒渲染幀數

int n;// 幀計

}FPS,*FPS_PTR;

 

計算每秒渲染幀
float Get_FPS(FPS_PTR fps){

++fps->n;// 幀加壹

if (fps->n > 100) {

fps->Frames = Get_FPS(fps, fps->n);

fps->n = 0;

}

return fps->Frames;

}

float Get_FPS(FPS_PTR fps, int  Frames){

clock_t  currentTime = clock();// 進程時鈡

double _fps = (double)Frames * (double)(currentTime – fps->startTime) / (float)fps->clockTicks ;

fps->startTime = currentTime;// 重置時間

return (float)_fps;

}

 

Android Studio NDK-編譯目標唔乾淨

Android Studio NDK-編譯目標唔乾淨
Android Studio NDK-編譯目標唔乾淨

Android Studio NDK編譯又蒞失敗, 『ninja: error: unknown target ‘clean’, did you mean ‘ninja -t clean’? 』大意目標唔乾淨.

  1. 撳『Win+E』進入NDK工程檔䅁夾.
  2. 進入『\app\.cxx\RelWithDebInfo\3t474c6q\』,數字檔䅁夾隨機生成
  3. 進入『arm64-v8a』『armeabi-v7a』『x86』『x86_64』檔䅁夾, 『冚辦爛』刪『子檔䅁』『子文檔』.
  4. 『arm64-v8a』『armeabi-v7a』『x86』『x86_64』保留唔刪
  5. 再蒞編譯掂
Build command failed.
Error while executing process C:\Users\bookc\AppData\Local\Android\Sdk\cmake\3.10.2.4988404\bin\ninja.exe with arguments {-C D:\Android\GeomanticCompass\app\.cxx\RelWithDebInfo\3t474c6q\arm64-v8a clean}

ninja: Entering directory `D:\Android\GeomanticCompass\app\.cxx\RelWithDebInfo\3t474c6q\arm64-v8a’

ninja: error: unknown target ‘clean’, did you mean ‘ninja -t clean’?

 

Android Studio NDK-OpenGL ES替換gluLookAt()

OpenGL ES替換gluLookAt()
OpenGL ES替換gluLookAt()

gluLookAt()  UVN相機模型,設定視點(相機)位置和視綫方向(矩陣運算).

void gluLookAt( GLdouble eyeX,

GLdouble eyeY,

GLdouble eyeZ,

GLdouble centerX,

GLdouble centerY,

GLdouble centerZ,

GLdouble upX,

GLdouble upY,

GLdouble upZ);

OpenGL ES冇gluLookAt() , 手工生成『旋轉矩陣』『相機位置』函式

void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,

GLfloat centerx, GLfloat centery, GLfloat centerz,

GLfloat upx, GLfloat upy, GLfloat upz)

{

GLfloat m[16];// 旋轉矩陣

GLfloat x[3], y[3], z[3];

GLfloat mag;

//生成旋轉矩陣

// Z矢量

z[0] = eyex – centerx;

z[1] = eyey – centery;

z[2] = eyez – centerz;

mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);

if (mag) {

z[0]/= mag;

z[1]/= mag;

z[2]/= mag;

}

 

// Y矢量

y[0] = upx;

y[1] = upy;

y[2] = upz;

 

// X 矢量 = Y 叉積 Z

x[0] = y[1] * z[2] – y[2] * z[1];

x[1] = -y[0] * z[2] + y[2] * z[0];

x[2] = y[0] * z[1] – y[1] * z[0];

 

// 重新計算 Y = Z 叉積 X

y[0] = z[1] * x[2] – z[2] * x[1];

y[1] = -z[0] * x[2] + z[2] * x[0];

y[2] = z[0] * x[1] – z[1] * x[0];

 

 

// 叉積給出了平行四邊形的面積,對于非垂直單位長度向量;所以在這裏標準化x,y

mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);

if (mag) {

x[0]/= mag;

x[1]/= mag;

x[2]/= mag;

}

 

mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);

if (mag) {

y[0]/= mag;

y[1]/= mag;

y[2]/= mag;

}

 

#define M(row,col)  m[col*4+row]

M(0, 0) = x[0];

M(0, 1) = x[1];

M(0, 2) = x[2];

M(0, 3) = 0.0;

M(1, 0) = y[0];

M(1, 1) = y[1];

M(1, 2) = y[2];

M(1, 3) = 0.0;

M(2, 0) = z[0];

M(2, 1) = z[1];

M(2, 2) = z[2];

M(2, 3) = 0.0;

M(3, 0) = 0.0;

M(3, 1) = 0.0;

M(3, 2) = 0.0;

M(3, 3) = 1.0;

#undef M

glMultMatrixf(m);

 

// 視點(相機)位置

glTranslatef(-eyex, -eyey, -eyez);

}

 

M.2 SSD 翅片導管散熱

M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱
M.2 SSD 翅片導管散熱CrystalDiskInfo
M.2 SSD 翅片導管散熱CrystalDiskInfo

近排天口興台電腦成日死機, CrystalDiskInfo睇『TOSHIBA XG3 M.2 MVME SSD』溫度高達73度. 睇中翅片散熱,銅導管,附送『導熱矽㬵片』同『導熱矽㬵脂』相比勝在可重用. 用肆眼鏍絲固定.

計漏咗翅片頂住顯卡,唔得插係 『PCIe 3.016』, 改插 『PCIe 2.04』. 唯壹安慰SSD高溫從74度跌到53度. 降溫20度.

 

SHAD TOP CASE SH39

39升尾箱
39升尾箱
39升尾箱
39升尾箱
39升尾箱
39升尾箱
KEY
KEY
托架
托架
托架
托架
托架
托架
托架
托架
托架
托架
39升尾箱
39升尾箱
39升尾箱
39升尾箱

『SUZUKI Gixxer155』唔畀擺係地下車庫. 擺係樓梯底油箱畀人劃交叉, 頭胎畀人用篤窿.擺係露天『好天哂落雨淋』.褸『車罩』冇掟識擺.冇計唯有裝尾箱放『車罩』.

SHAD 尾箱SH39/ SH40. 尺碼再大有可能頂邊箱SH23. SH39比SH40貴因SH39靚仔. 唔介意買SH40仲底.

裝『托架』RACK盡量褪後, 後坐車人闊落. 架餐『六角套筒』, 『十字螺絲批』. 『托架冚蓋』先裝弧面再裝直面.

SHAD TOP CASE SH39 39升尾箱
SHAD SIDE CASE SH23 23升邊箱

 

Android Studio NDK编译OpenGL ES

Android Studio NDK编译OpenGL ES
Android Studio NDK编译OpenGL ES

係Android Studio NDK编译OpenGL ES, 需鏈接『libGLESv1_CM.so』庫, 編輯『CMakeLists.txt』.

首先稳『libGLESv1_CM.so』庫

find_library( OpenGL-lib libGLESv1_CM.so )

鏈接『libGLESv1_CM.so』庫

target_link_libraries(  geomanticcompass

${OpenGL-lib}

${log-lib})

 

Android Studio NDK-fprintf()格式字符

Android Studio NDK-fprintf()格式字符
Android Studio NDK-fprintf()格式字符

係NDK調用fprintf ()格式字符函式報錯

fprintf(fp_error,buffer);
error: format string is not a string literal (potentially insecure) [-Werror,-Wformat-security]

原解fprintf()缺失參數.加入參數0問題消失.

fprintf(fp_error,buffer,0);

 

int printf(const char *format [,argument]…); 熒屏
int fprintf(FILE *stream,const char *format [,argument ]…); 文檔
int sprintf(char *buffer,const char *format [,argument] …); 記憶體

 

format格式 argument參數 簡介
c 字符 單個字符
C 字符 單個字符
d 整數 帶正負符號十進整數
i 整數 帶正負符號十進整數
o 整數 冇正負符號八進整數
u 整數 冇正負符號十進整數
x 整數 冇正負符號,細寫十六進整數.abcdef
X 整數 冇正負符號,大寫十六進整數.ABCDEF
e 浮點數 帶正負符號十進浮點數,指數版.
E 浮點數 帶正負符號十進浮點數, 指數版.
f 浮點數 帶正負符號十進浮點數
F 浮點數 帶正負符號十進浮點數
g 浮點數 係%e同%f中選
G 浮點數 係%e同%f中選
a
A
n
s 字符串 直至首個NULL
S 字符串 直至首個NULL
z
% 指定格式

 

樣式 輸出/寫入
sprintf (text, ” %2d\n”,  3); 03
sprintf (text, “%s\n “, “abcdef”); abcdef

 

Android Studio NDK 日期時間

Android Studio NDK 日期時間
Android Studio NDK 日期時間

Android 所用C/C++庫Bionic API. 即輕量級C/C++庫. 分32位同64位, 32位『time_t』有效期至2038年, 64位『__time64_t』有效期至3000年.

呌『tm』時間結構

struct tm { 結構時間
int tm_sec; 秒鐘[0~59]
int tm_min; 分鐘[0~59]
int tm_hour; 時鐘[0~23]
int tm_mday; 號[1~31]
int tm_mon; 月份[0~11] 需加1
int tm_year; 年份需加1900, 儒略歴
int tm_wday; 禮拜[0~1],禮拜日Sunday=0
int tm_yday; 天[0~365],1月1號=0
int tm_isdst; 夏令時為正, 否
long int tm_gmtoff; 當前時相對UTC往東時差,即東爲正西爲負.
const char* tm_zone;}; 時區縮寫

係『Win32 API』你需time()/_time64()獲得時間, 再蒞localtime()/_localtime64()根據時區轉爲本地時間『tm』

Win32  API版本
char time_text[280];

struct tm   temp_str;// 時間結构

__time64_t  temp_int;// 時間整数

_time64(&temp_int);// 获取時間

_localtime64_s(&temp_str ,&temp_int);// 根据時區轉為本地時間

sprintf(time_text, “%4d-%02d-%02d %02d:%02d:%02d”,

1900+temp_str.tm_year,1+temp_str.tm_mon, temp_str.tm_mday,

temp_str.tm_hour,temp_str.tm_min,temp_str.tm_sec);

2021-09-09 23:43:08

Android Studio NDK 『Bionic API』版本,可用localtime_r()根據時區獲得本地時間『tm』

Bionic API版本
    char time_text[280];// 時間文本

struct tm  temp_str;// 時間結構

time_t temp_int;// 32位時間整數

temp_int = time(0);

localtime_r(&temp_int,&temp_str);// 根據時區轉爲本地時間

sprintf(time_text, “%04d-%02d-%02d %02d:%02d:%02d”,

1900+temp_str.tm_year,1+temp_str.tm_mon, temp_str.tm_mday,

temp_str.tm_hour,temp_str.tm_min,temp_str.tm_sec);

2021-09-09 23:43:08

 

 

 

Android Studio NDK編譯錯誤 error undefined reference

Android Studio NDK編譯錯誤 error undefined reference
Android Studio NDK編譯錯誤 error undefined reference

新版Android Studio用CMake編譯so庫. 構建『Native C++』工程已自動生成『CMakeLists.txt』同『native-lib.cpp』, 但C/C++代碼係『native-lib.cpp』調用其它『.cpp』程式皆報錯『error: undefined reference』, 皆因冇將C/C++代碼編譯入so庫.

D:/Android/GeomanticCompass/app/src/main/cpp/native-lib.cpp:14: error: undefined reference to ‘IsEven(int)’

睇『CMakeLists.txt』文檔

係『add_library()』尾加入『math.cpp』生成鏈接文檔

add_library( geomanticcompass

SHARED

native-lib.cpp

math.cpp)

查找日志庫

find_library(log-lib        log)  

將目標文檔與庫文檔進行鏈接

target_link_libraries(geomanticcompass        math        ${log-lib})

 

 

Android Studio缺失插件 missing essential plugin

Android Studio缺失插件 missing essential plugin
Android Studio缺失插件 missing essential plugin

Android Studio崩潰後重啟弹出『missing essential plugin』缺必須插件,重装Android Studio問題依舊. 缺失插件可能插件崩潰被屏蔽. 係C: 盘搜索 『disabled_plugins.txt』将入面內容冚辦爛刪.

missing essential plugin

org.jietbrains.android

Please reinstall Android Studio from scratch

 

C:\Users\bookc\AppData\Roaming\Google\AndroidStudio2020.3\disabled_plugins.txt

 

Android程式入口Application

Android程式入口Application
Android程式入口Application

Android唔似Window有Winmain()/main()作程式入口. 而Android用Application作程式入口. 比Activity更早調用,也唔會因方向改變重複調用onCreate().

將Application.onCreate()當main()用. 將程式『初此』Init()冚辦爛摆何係度.

 

  1. 生永MainApplication继承Application 覆盖onCreate()
class MainApplication extends Application
  1. 配置『xml』
<application android:name=”.MainApplication” ></application>
  1. 係onCreate()『初此』Init()程式

 

public class MainApplication extends Application {

// 全局变量,应用程序句柄

private static MainApplication singleton;

//返回应用程序实例

public static MainApplication getInstance() {

return singleton;

}

//创建应用程序时调用

@Override

public final void onCreate(){

Context context;

singleton = this;//

super.onCreate();

context = this.getApplicationContext();

// 初此

}

// 記憶體低

@Override

public final void onLowMemory() {

super.onLowMemory();

}

// 释放憶體低

@Override

public final void onTrimMemory(int level) {

super.onTrimMemory(level);

}

// 改变配置时调用

@Override

public final void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

}

}

Android Studio C/ C++編程-使用NDK

Android Studio C/ C++編程-使用NDK
Android Studio C/ C++編程-使用NDK

Android Studio C/ C++編程開發环境由以下組件构成:

  1. 装『Android Studio
  2. Android SDK(Software Development Kit) 軟件開發包, Android Studio 己含
  3. Android NDK(Native Development Kit) 原生開發包, Android Studio 己含
  4. Java JDK(Java Development Kit) Android Studio 己包含Java開發包.
  5. CMake构建工具,编译原生库
  6. LLDB調試工具,调试原生代码
  7. 生成C/C++項目
  8. 係『native-lib.cpp』下生成C函式

 

Android Studio安装『NDK』同『CMake』

  1. 撳『Tools』 -> 『SDK Manager』
  2. 撳『Appearance & Behavior』-> 『System Settings』->『Android SDK』
  3. 撳『SDK Tools』
  4. 勾『NDK(Side by side)』
  5. 勾『CMake』
  6. 撳『Apply』下載

 

生成C/C++工程

  1. 啟用Android Studio
  2. 撳『Projects』->『New Project』
  3. 『Templates』撳『Phone and Tablet』手機同平板
  4. 撳『Native C++』
  5. 『Name』指『程式名』填『經倫羅盤/Geomantic Compass』
  6. 『Package name』指『包名』,將网站『域名』倒置加『.程式名』『domain.name』 确保唯壹性,如『net.bookcard.GeomanticCompass』
  7. 『Language』指編程言, 默認『Kotlin』選『Java』.
  8. 『Save location』指工程存檔路徑,只可係ASCII碼,如『D:\Android\GeomanticCompass』
  9. 『Minimum SDK』允許運行Android平臺, 選最細SDK版本,获得盡量多設备支持.
  10. 『Use legacy android support libraries』用旧版android支持库.
  11. 撳『Next』
  12. 『C++ Standard』选择C++ 标准,默認『Toolchain Default』用『 CMake』 设置.
  13. 撳『Finish』自動构建C/ C++工程

 

係『native-lib.cpp』下生成C函式

native-lib.cpp
extern “C” JNIEXPORT jstring JNICALL

Java_net_bookcard_geomanticcompass_Lib_stringFromJNI(

JNIEnv* env,

jobject /* this */) {

std::string hello = “Hello from C++”;

return env->NewStringUTF(hello.c_str());

}

  1. 『extern “C”』声明C程式
  2. 『JNIEXPORT』
  3. 『jstring』程式返回類型
  4. 『JNICALL』参数压桟順序
  5. 函式名以『文檔夾路徑』組成,『Java_package_function』區分大細寫.
  6. 函式『Java』開頭, 因位於『Java』根文檔夾
  7. 函式『net_bookcard_geomanticcompass』包名文檔夾
  8. 函式『Lib』指java 文件Lib calss
  9. 函式『stringFromJNI』指函式名
  10. 参數『JNIEnv* env』調用Java函式
  11. 『jobject』
  12. 最後先係函式参數

 

真機調試Android程式

  1. 手機用USB線同电脑相連
  2. 『Build』->『Make Projects』生成工程
  3. 『Run』->『Debug ‘app’』 調試工程

 

 

 

 

配置『系統變數』

  1. 撳『Win+Pause Break』
  2. 撳『變更設定』開啟『系統內容』
  3. 撳『進階』->『環境變數』
  4. 『系統變數』->『新增』
  5. 『變數名稱』
  6. 『變數值』

 

装Android NDK

  1. 撳『File』-> 『Project Structure』或『Ctrl+Alt+Shift+S』
  2. 撳『SDK Location』
  3. 『Android NDK location』撳『Download』下載『Android NDK』
  4. 『Android NDK location』『C:\Users\user\AppData\Local\Android\Sdk\ndk\23.0.7599858』

 

Android Studio默認安装Android SDK

  1. 撳『File』->『New Project Settings』->『Project Structure』
  2. 撳『SDK Location』
  3. 『Android SDK location』『C:\Users\user\AppData\Local\Android\Sdk』

 

Android Studio默認安装Java JDK

  1. 撳『File』->『Project Structure』
  2. 撳『SDK Location』
  3. 『JDK Location』 『C:\Program Files\Android\Android Studio\jre』
  4. 設定『環境變數』

 

 

验証『Java JDK』安装

  1. 開啟命令輸入模式『EXE』
  2. 輸入『java -version』执行
  3. 安装成功則显示JDK版本号

Android Studio設定字體尺碼

Android Studio設定字體尺碼
Android Studio設定字體尺碼

Android Studio默認字體細睇代碼耗神, 而Android Studio唔支持滑輪字體尺碼. 你需要手動設定.

Android Studio設定字體尺碼

  1. 撳『File』->『Settings』或者撳『Ctrl+Alt+S』啟動『Settings』
  2. 撳『Edit』->『Font』
  3. 設定『Size』值默認12, 放大壹倍設
  4. 撳『Apply』应用設定.

Android禁程式頻繁调用onCreate

Android禁程式頻繁调用onCreate
Android禁程式頻繁调用onCreate

Android手機『方向切换』『滑出鍵盘』, Android會認為配置改變, 将销毁并重啟程式. 調用activity:onCreate()會大量占用CPU時間. 係游戲造成500ms以上都唔可接受. 編輯『AndroidManifest.xml』係『<activity>』元素『configChanges』属加入『orientation方向切换』同『keyboardHidden滑出鍵盘』『keyboard插入键盘』. 係MainActivity重载onConfigurationChanged ()自己處理, 達置 『方向切换』『滑出鍵盘』冇需再次调周onCreate().

AndroidManifest.xml
<activity

android:name=”.MainActivity”

android:configChanges=”keyboard|keyboardHidden|orientation”>

</activity>

 

MainActivity
    @Override

public void onConfigurationChanged(Configuration newConfig) {

if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {// 横向

}

else

if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {// 纵向

}

if(newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO )    {//  显示键盘

}

super.onConfigurationChanged(newConfig);

}