Category Archives: AppInventor – 圖形化Android

[App Inventor] 點擊畫布兩次,畫圓形

本範例點擊畫布兩次時就會以這兩次的點擊座標畫出一個圓(底色為黃色)並標示圓心(底色為藍色)。執行畫面如下:
Screenshot_2016-03-15-10-03-57-37

Designer頁面
 
只有 Canvas 畫布元件與按鈕元件,相當簡易。您可以自由調整畫面的安排方式。
 
Blocks 頁面
 
1. 宣告變數
x_old, y_old 是用來記錄第一次的點擊座標;firstPressed 則是判斷現在是否為第一次點擊;最後centerX 與 centerY 則是用來計算每次的圓心座標
Button1 按下時,清除畫布上所有的東西。
2. 點擊畫布
 
在 Canvas的 TouchDown (您也可以用 Touched) 事件中,先檢查firstPressed變數值來判斷現在是否為第一次點擊,如果為第一次點擊,則紀錄本次點擊座標,並把firstPressed變數值設為 false。
第二次點擊時,也就是firstPressed變數值為 false,則先計算出圓心座標:
centerX = (X2 + X1) / 2
centerY = (Y2 + Y1) / 2
 
接著畫兩個圓,第一個圓就是我們要畫的圓,第二個則代表圓心。半徑計算方式為直徑/2,而直徑計算如下:
 
直徑 = square ( (X2 – X1)^2 + (Y2 – Y1)^2)
 
最後把 firstPressed變數值設為 false,這樣程式就可以連續執行囉!
 


[App Inventor新元件] FirebaseDB 網路資料庫元件

App Inventor 發布了一個新的元件:FirebaseDB。使用過 App Inventor tinyWebDB 的朋友應該都知道…  這個元件真的相當陽春。除了把資料放在網路上以外,其他資料庫相關的功能可說幾乎沒有。可能也是因為這樣才推出了這個元件。

Firebase 元件與 TinyWebDB 相當類似,只是改用 Firebase 資料庫 (firebase.com), 並且支援從同一個應用程式的多個副本來更新單一筆(或多筆) 變數,這些副本是執行在不同的聯網裝置上。當某個裝置更新數值時,其他所有裝置都會收到 資料改變“DataChanged” 事件以及新的數值。

在 Firebase 原廠網站註冊帳號時,可以用您的Google帳號或註冊新的 Firebase帳號,完成之後進入 Dashboard 會看到已經建好一個名為 MY FIRST APP 的應用程式,您的 App Inventor 需要透過它來 Firebase 互動。

fire01
原則上,您需要在 firebase.com 建立一個帳號才能使用 Firebase,但 MIT 有一個免費帳號 (看來是有灑一點錢) 可以直接讓大家使用,您可以在 Fiirebase 元件的屬性區中的 FirebaseToken 看到一組憑證碼。當然啦,這樣代表您的資料會被其他人看到,如果很注重私密性的話,該做完的步驟或是該花的錢就不要省囉。請注意,目前 App Inventor 模擬器還不支援 Firebase 元件。

fire02

以下是 MIT App Inventor 提供的範例,按下按鈕之後,會對 Firebase 以 myshareData 標籤寫入某個值。並且在修改完成之後,透過 FirebaseDB.DataChanged 事件把這次修改的 tag 與 value 都抓回來。(ValueToSet 是一個 TextBox 文字方塊,ReceivedValue 則是Label標籤)。

 

[新書出版] TQC+ 創意App程式設計認證指南解題秘笈:App Inventor 2

TQC+ 創意App程式設計認證指南解題秘笈:App Inventor 2 出版啦!剛過完年第一個周末就是新書上市的消息,相當開心呢 (這樣大家就知道過年前在校稿有多忙了…)

一樣同時由碁峰與松崗兩家出版,內容都是一樣的。以下是本書封面與內容介紹

XC15030_cover_3

碁峰aey035011
解題步驟很詳盡,請大家多多支持喔

getImage (2)getImage (2)

Continue reading

App Inventor classic 的 .zip 原始檔轉 AI2 .aia

MIT App Inventor 有提供 App Inventor classic 的 .zip 原始檔轉 AI2 .aia 的線上服務喔,請點選這個網址就好:

http://convert.appinventor.mit.edu/。進到以下畫面後,點選 [選擇檔案],選擇您所要轉檔的 .zip 原始檔之後就會自動轉成 .aia 下載到您的電腦。再將這個 .aia 上傳到您個人的 AI2帳號下就可以囉,目前轉了 5,60 個檔案都沒什麼問題。

祝大家使用愉快喔~

未命名I

App Inventor 與 FIRST 機器人競賽

本文消息來自 MIT App Inventor 部落格,說明新一賽季的競賽改用 Android 智慧型手機作為機器人的遙控器,其中程式就可以用 App Inventor 來編寫。在2015-2016賽季中,選手要製作機器人來完成 FIRST Res-Q 救援賽,今年是以山區救援為主題喔。

重點來了!每一組都須使用 Android Smartphone 作為主要的機器人控制器。隊伍使用的是特製的 MIT App Inventor 來編寫機器人程式來完成各種競賽任務。

所以呢, App Inventor 的應用面愈來愈廣啦,有興趣協助我們測試樂高EV3元件的朋友,請留言給我們。感謝

[誠徵勇者] App Inventor 樂高EV3元件封測

Continue reading

[誠徵勇者] App Inventor 樂高EV3元件封測

當年,我們誤打誤撞發現了 App Inventor,也不經意發現它有現成的 Lego Nxt 元件可以直接控制樂高NXT機器人。因此當樂高發布 EV3 機器人之後,我們也殷殷期盼MIT App Inventor 團隊可以發布 EV3機器人的控制元件。

但,至少在我去年 (2015) 在廣州與 MIT 的教授們討論到這件事時,它們的回覆是 “暫時不會有

那麼,就自己來吧

經過漫長的努力之後,CAVEDU 自製的 App Inventor EV3 機器人元件終於接近完工。(App Inventor 樂高EV3元件 – 準備上線)

12376557_935096773227864_7220939319532785577_n

在此號召有興趣先玩玩看的朋友與朋友們,一起來封測吧!請在此篇留言或寫信到 service@cavedu.com,我們會告訴您如何登入 CAVEDU 自行架設的 server,就可以進行 EV3 元件的測試。

但請一定要分享您的作品與意見給我們,覺得好或覺得爛都可以說,也歡迎許願,把您覺得哪些功能應該有但是沒有,或是哪些功能可以更好,通通告訴我們吧。

只要您真的使用 CAVEDU 所開發的 App Inventor EV3 元件做出一個手機結合樂高機器人的應用,就是對我們最大的肯定與鼓勵喔!

 

[雙A計劃] Part9:藍牙遙控機器手臂車

整合性的範例就來一台機器手臂遙控機器人吧,把機器手臂裝在雙馬達車體上就完工了,一樣可以透過 App Inventor 來編寫。使用多個按鈕來控制機器人的各個動作。來看看之前的雙A計畫內容:

[雙A計畫] 常見問題整理

[雙A計劃] Part0:App Inventor 透過藍牙傳送訊號給 Arduino

[雙A計劃] Part1:App Inventor 經由藍牙控制 Arduino LED 亮滅

[雙A計劃] Part2:App Inventor 經由藍牙控制 Arduino LED 漸明漸暗

[雙A計劃] Part3:Android 手機透過藍牙接收 Arduino 類比腳位狀態

[雙A計劃] Part4:App Inventor 藍牙遙控 Arduino 雙輪機器人

[雙A計劃] Part5:Paperduino 藍牙控制 LED 閃爍

[雙A計畫]Part6:Arduino 傳兩筆資料到 Android 手機

[雙A計劃] Part7:Arduino超音波感測距離回傳數值給Android手機

[雙A計劃] Part8:Android 手機對 Arduino 同時進行資料收發

範例程式請點我下載(App Inventor中文學習網檔案庫)

準備以下材料:

1 Android系統智慧型手機

2.Arduino相容開發板 (本文使用 86Duino Educake)

3.藍牙收發接收器(本系列使用JY-MCU04 或 JY-MCU05)

4.麵包板

5.MeArm 或其他相同配置的四自由度機器手臂,使用四個伺服馬達

6.雙輸出行動電源或電池

IMG_0373

台南 Maker Faire 現場展示很受歡迎喔

本範例使用 86duino Educake來製作電路,您可使用各種相容 Arduino 板子。以下是主程式流程,還需要匯入其他函式庫,在此就不列出囉,請直接下載檔案即可。

2015-12-25 13.40.54

Continue reading

App Inventor 樂高EV3元件 – 準備上線

2010年我們會開始玩 App Inventor 純粹是誤打誤撞,也不小心發現了上面的 LegoNxt元件可以做到直接控制樂高NXT機器人這件事,而且更棒的是樂高機器人端不用寫程式,只要專心寫手機端程式就好。這當然是因為樂高對於NXT定製了一個 DirectCommand 規格,實際上就是一堆位元陣列,在CAVEDU 2011 年所出版的  [Android / NXT 機器人大戰:智慧型手機控制機器人] 與 2012 年所出版的 [Android手機程式超簡單App Inventor 機器人卷] 中就有談到這些事情。大概就是長得像這樣的東西,NXT自己會知道哪一個位元組的意義並轉換為它該做的事情

0x0C 0x00 0x80 0x04 0x02 0x64 0x07 0x00 0x00 0x20 0x00 0x00 0x00 0x00

首先:為什麼App Inventor 的NXT元件沒辦法控制EV3?因為兩者的 Direct command 格式根本不同,所以EV3根本看不懂。

請參考我們一年多以前寫的 App Inventor 直接控制樂高 EV3 機器人 Direct Command

但要自己做一個 App Inventor 元件也不是件容易的事情,因為沒有可供測試的地方啊,所以您需要使用 MIT 提供的原始碼自己架一個 linux server,接著才能在上面開發元件。後來 MIT 開了一個 extension server 讓大家可以編寫 .aix 擴充檔來測試,相關的文件才慢慢多了起來。包含台灣的 PieceDuino 也有開發了相關的元件:

12346361_1651657771769401_2492747964884747469_n

請參考 puraVida 的教學,您就可以知道底層還是用 java 來寫 Android,總歸一句就是硬硬硬。這件事大概搞了一年多吧…  最近終於露出曙光,感謝台大資工系林祥瑞同學。本文是讓各位好朋友們知道,CAVEDU 為了大家,一直有在努力~另外,

歡迎大家許願說說看您對於EV3元件應該要新增哪些功能,我們會試著做出來喔!

Continue reading

[App Inventor 教學] Google Street View API 靜態街景圖

與 Static Map API 相同,Google 街景圖也有API可以透過 url 來呼叫。.aia 原始檔請點我下載
格式如下說明:
 
點選開啟如下圖
 
參數說明如下: 
  • size=320×400 – 圖檔尺寸
  • location=25.046655,121.515012 – 座標(緯度,經度).
  • fov=90 – field of view 視野. 90度相當於人眼視角, >90 為廣角效果, <90 為望遠效果
  • heading=120 – 指向, 0~359, 請注意 0 不一定代表正北方
  • pitch=10 – 俯仰角 -90 (向下看地板) ~ 90 (向上看天空)

Continue reading

十月活動紀錄-花蓮高商Appinventor

20151017_131749

十月的兩個周末,受到資處科主任的邀請,小編坐火車來到花蓮市的花蓮高商,跟大家分享如何使用APPinventor,一到教室就有歡迎海報,讓小編受寵若驚阿,這次是10/17、10/24日的12小時,小班制密集訓練,讓我們來看看~

20151017_101725

這次總共有十位同學參加研習營,整天全神貫注,讓小編覺得花商的同學小小年紀,集中力就很不錯。

20151017_101735

進度跟得很快的同學,正在撥時間時間美化他的APP畫面

20151017_134921

現場除了同學之外,也有好幾位老師撥時間來學習如何使用APPinventor軟體,讓我覺得花商整體的學習欲望,不輸給北北基的學生們。

001 002

這次透過BMI計算機、小畫家、點餐系統、滾球遊戲,跟花商的同學與老師們分享APPinventor的換頁功能、運算功能、判斷式功能、繪圖功能、呼叫手機相簿功能、遊戲角色移動功能、利用手機傾斜讓人物移動的方向感測器功能,以及TQC測驗的點餐功能APP。希望讓分享的同學有所收穫。

003 004

  

App Inventor 擴充元件何處尋?

App Inventor 新增了擴充元件伺服器之後,陸續有一些應用出來了。包含 MIT App Inventor puravida 網友 都陸續推出了一些擴充元件讓大家來試用。

下圖是 MIT 提供的擴充檔,目前上面提供了四種擴充元件:

  1. VectorArithmetic:計算向量
  2. ImageProcessor:影像處理,可回傳灰階圖
  3. SoundAnalysis:聲音分析,可分析經由來自手機麥克風的聲音音高。
  4. ScaleDector:Canvas 上的多點觸碰手勢偵測功能

1234

延伸閱讀:

[App Inventor] 如何匯入 .aix 擴充元件到 App Inventor 測試伺服器

App Inventor Extension 新測試伺服器,允許自定義元件了!

[App Inventor 教學] 成績管理系統 V1.5

本範例可讓同學明白簡易的資料結構定義方式,並使用 list 搭配 for each 迴圈來計算以下項目。
.aia 原始檔請由本頁下載:http://www.appinventor.tw/score_v2

1. 計算國文平均分數

2. 計算英文平均分數
 
3. 列出兩科的不及格名單
 
4. 列出全班名單
 
5. 承接4. 取出指定人名的email
 

Designer頁面
 

Blocks 程式說明
 
首先,我們把成績的資料結構 score 這樣定義:(人名, email, 國文分數, 英文分數),目前是 4 x 4 的二維清單。
在這樣的架構下,您可以自由新增更多欄位。score_sum 是用來計算成績總和用的變數。temp 則是用來產生暫存用的清單。
 
2. 計算國文平均分數
 
 
當然啦,計算英文平均分數也是一樣的做法,只是欄位3要改為欄位4。
 
 
3. 列出國文不及格名單
 
只是在上述迴圈中加入一個 if 去檢查 score [number] [3] 就是國文分數是否 <60,如果 <60 就把該項目加入 temp 清單中,最後顯示在
 
 
英文不及格名單做法也一樣囉,記得把欄位3改為欄位4就可以了。
 



 
4. 列出全班名單


 
點選之後,則根據所點選項目來取出 score 該項目的 2 號。使用兩次 select list item 指令之後,二維清單就會降維度兩次變成一筆純量就是 email,您成功了嗎?
 

執行畫面


  

    
 



 

[App Inventor] 如何匯入 .aix 擴充元件到 App Inventor 測試伺服器

本文將介紹如何匯入 .aix 擴充元件到 App Inventor 測試伺服器,請注意您需登入 App Inventor 測試伺服器而非 AI2 的正式版伺服器。

 
請按照以下步驟操作:
 
STEP1:請由此連結下載要匯入的 .aix 檔,這是 PuraVida 所寫的螢幕快照功能
 
STEP2:在畫面左側的 Extension 元件區中,點選 Import extension,會跳出以下視窗詢問 .aix 檔案路徑,確認之後請點選 Import 上傳檔案。
 
 
STEP3:命名元件,在此沒有改動
 
 
STEP4:匯入成功之後,就可以在 Extension 元件區看到這個元件了
 
 
STEP5:新增這個元件
 
 
STEP6:在 Blocks 頁面中也可以看到這個元件,相關的事件與方法當然都可以自由編寫 (Java)

STEP7:寫個小程式來看看吧


 
補充資料:本 .aix 檔的 Java source code,有興趣的朋友可以看看 event 與 method 是如何對應的喔
 

Java source code

package com.puravidaapps;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.View;
import android.app.Activity;
import android.os.Environment;

import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.google.appinventor.components.runtime.*;

import java.io.File;
import java.io.FileOutputStream;

@DesignerComponent(version = TaifunScreenshot.VERSION,
    description = "Extension to take a screenshot.",
    category = ComponentCategory.EXTENSION,
    nonVisible = true,
    iconName = "https://puravidaapps.com/images/taifun16.png")
@SimpleObject(external = true)
@UsesPermissions(permissionNames = "android.permission.WRITE_EXTERNAL_STORAGE")

public class TaifunScreenshot extends AndroidNonvisibleComponent implements Component {

  public static final int VERSION = 1;
  private ComponentContainer container;
  private Context context;
  private final Activity activity;
  private String fileName;
  private static final String LOG_TAG = "TaifunScreenshot";

  public TaifunScreenshot(ComponentContainer container) {
    super(container.$form());
    this.container = container;
    context = (Context) container.$context();
    activity = (Activity) container.$context();
    fileName = "screenshot.jpg";
    Log.d(LOG_TAG, "TaifunScreenshot Created" );
  }

  /**
   * Return fileName
   */
  @SimpleProperty(category = PropertyCategory.BEHAVIOR,
      description = "filename of the screenshot to be taken")
  public String FileName() {
    return fileName;
  }


  /**
   * Set fileName
   */
  @DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING,
      defaultValue = "screenshot.jpg")
  @SimpleProperty
  public void FileName(String fileName) {
    this.fileName = fileName;
  }


  /**
   * Take a screenshot
   */
  @SimpleFunction(description = "Take a screenshot.")
  public void TakeScreenshot() {
    // "http://stackoverflow.com/a/5651242/1545993
    try {
      // image naming and path  to include sd card  appending name you choose for file
      String mPath = Environment.getExternalStorageDirectory().toString() + File.separator + fileName;

      // create bitmap screen capture
      View v1 = activity.getWindow().getDecorView().getRootView();
      v1.setDrawingCacheEnabled(true);
      Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
      v1.setDrawingCacheEnabled(false);

      File imageFile = new java.io.File(mPath);

      FileOutputStream outputStream = new FileOutputStream(imageFile);
      int quality = 100;
      bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
      outputStream.flush();
      outputStream.close();

      Log.d(LOG_TAG, "screenshot taken: " + imageFile.toString());
      AfterScreenshot(imageFile.toString());
    } catch (Throwable e) {
      // Several error may come out with file handling or OOM
      Log.e(LOG_TAG, e.getMessage(), e);
      e.printStackTrace();
    }
  }

  /**
   * The AfterScreenshot event
   */
  @SimpleEvent(description = "Return image.")
  public void AfterScreenshot(String image){
    EventDispatcher.dispatchEvent(this, "AfterScreenshot", image);
  }

}


 

[雙A計劃]自己的拳擊機器人自己改裝_使用Arduino;AppInventor by TKUEE-CILAB

robot13

今天小編要跟各位分享一個機器人改裝教學,它源自淡江大學電機系-CILAB實驗室的專題作品,

這項改裝作品在Tokyo Maker Fairer發表後,販賣這個機器人的公司也將這個發想概念運用在他們新的機器人產品上,

讓人覺得Maker與商品製造其實能很好的相輔相成。話不多說,我們來看看這個機器人影片吧。

看了這個影片,也想要自己動手改裝的話,請繼續往下看喔

  • 本項作品使用日本TOMY公司生產的“BATTROBORG 4G”拳擊機器人玩具,
  • 將原本的體感操控,改造成能利用Android裝置,透過藍芽來控制機器人的動作(體感下一篇敬請期待)。

一組機器人需要準備

  • Arduino開發版*1
  • 藍芽模組*1
  • 3號*4電池盒*1
  • 光耦合器元件PC817*2

電路測試

  • 請先按照附圖之電路圖在麵包板上佈置電路

在此我們利用LED來測試我們在光電耦合器的使用上是否正確

。若是配置正確,在我們用手機向藍芽裝置傳送資訊時,對應的LED就會閃碩。

robot01

Arduino程式編輯

在此我們監聽接上藍芽模組後的TxRx,當藍芽接收到傳送的字元‘0’或‘1’時,分別啟動連接於Pin 10&11的光電耦合器,藉此讓連接於耦合器另一端的LED的正負極導通。

int input = 0,left=10,right=11;

void setup(){

  pinMode(left,OUTPUT);  
  pinMode(right,OUTPUT);  

  Serial.begin(9600);

}

void loop(){

  while (Serial.available()>0){

    input= Serial.read();
    Serial.println(input);

    if(input=='0'){

      digitalWrite(left,HIGH);
      delay(100);
      digitalWrite(left,LOW);

    }else if(input=='1'){

      digitalWrite(right,HIGH);
      delay(100);
      digitalWrite(right,LOW);

    }

  }

}

AppInventor撰寫App

  • 1 介面初始化
    • 我們在APP介面(圖1a)上配屬了三個按鈕(上方的左拳&右拳與右下方的藍芽裝置斷線),與一個用來列出並選取可連線的藍芽裝置的ListPicker(左下藍芽裝置連線)。因為本APP需要與藍牙裝至連線,所以要將BluetoothClient元件加入至介面中。在程式初始化後,因為還沒連上任何藍芽裝置的關係,這時除了BTConnect外的其他按鈕將呈現灰色無法選取的狀態(圖1b)。

robot02

圖1a

robot03

圖1b

2 藍芽裝置連線

  • 在我們開啟藍芽裝置選單前,要先將可供連線的裝置清單輸入至選單中(圖2a)。選取裝置並確定連線成功後,將原本設為不可選取的左拳、右拳以及裝置斷線按鈕開啟(圖2b)。

robot04

圖2a

robot05

圖2b

3 藍芽功能實作

  • 當我們與裝置連線後,點擊左拳或右拳按鈕時,會透過藍芽對連線裝置送出字元的1與0資料(圖3a)。按下裝置斷線的按鈕時,則會與裝置斷開連結,並重新將需使用到藍芽功能的按鈕關閉(圖3b)。

robot06

圖3a

robot07

圖3b

實際測試

  • 將撰寫完成的APP燒錄至手機,當我們與Arduino上的藍芽模組連結,並按下左拳與右拳按鈕時,與之對應的LED就會閃碩,代表我們光電耦合器的使用與設置是正確的。

機器人手把

  • 手把與基板拆解
    • 本作品使用的拳擊機器人玩具為日本TOMY公司生產的“BATTROBORG 4G”,同樣方法適用於同公司前代產品“BATTROBORG 20“。

將手把拆開後,可以看到控制器是利用搖晃時,撞針撞擊簧片,簧片互相接觸後導致線路導通,觸發一個揮拳的訊號,因此我們才在此作品上使用光耦合器來當作觸發開關(圖4)。

robot08

圖4,橘線標記處為撞針與簧片

 

將基板拆下,如下圖(圖5),可以看到三個部分分別為基板供電、右拳揮拳以及左拳揮拳,這些就是等下要跳線到麵包板上使用的接點。(在這裡可以選擇將原廠焊好的線留著繼續使用,或者自行換上單芯線)

robot09

圖5,橘線標記處分別為 a.基板供電 b.右拳揮拳 c.左拳揮拳

成品測試

  • 按照下圖(圖6)指示將基板的左右揮拳腳位跳線至對應的光耦合器(因訊號觸發機制為腳位導通,故接線無正負之分),並將基板電源供電腳位分別接上+5V和接地,Arduino接電,及可讓基板與機器人連線,並讓手機透過藍芽操控拳擊機器人。

robot10

圖6

Maker Faire Tokyo展示的照片

robot11 robot12

App Inventor 更新 nb146 – 允許多 Screen 之間的複製貼上功能 – 背包 backpack

App Inventor 更新到 nb146,新增背包功能,就是允許多 Screen 之間的複製貼上功能。本次更新詳述如下:

未命名

  • 元件名稱的空白與字元處理改善,對於非英語系的語言來說相當重要。
  • 點擊  blocks editor 頁面空白處就可以下載所有指令的 png 圖檔,不用再辛苦地螢幕截圖啦,記得先把元件排整齊喔 (請參考上圖,是選單的一個選項)。
  • HorizontalArrangement 與 VerticalArrangement Layouts 元件新增背景顏色 (Background Color) 與背景圖 ( Image) 兩個屬性。
  • 當 App Inventor App 執行時,可以與藍牙鍵盤連線或斷線。
  • 錯誤修正與效能改進。

參考資料:文淵閣的 App Inventor nb146 背包功能介紹