Pebbleの下でプログラムします。 レッスン2:答えの石、サイコロ、セックスキューブ

時計はもちろん良いのですが、サイト全体がそれで詰まっています。 もっと面白いことをする必要があります。

画像

「トラック60」のボールを覚えていますか? アナログを作成しましょう-質問に答えるアプリケーションです。





答えを与えるボール小石

私たちだけがボールを持っていませんが、小石、つまり小石:)

これには何が必要ですか? 回答のリストと乱数ジェネレーター。 ウィキペディアで回答のリストを取得します。 配列を作成し、回答を入力します。

static const char* messages[] = {"", " "," "," ","    ","  - "," "," ","","  - ","  ,   "," ","     ","  ","   ","  ","  - ","  - ","   "," ","",};
      
      



順序は重要ではありません、とにかくランダムに選択されます。



前のレッスンと同じ方法でプログラムのメインウィンドウとテキストレイヤーを作成しますが、少しの違いはありますが、 window_set_fullscreen()関数を使用して、アプリケーションのトップバーを削除します。 次のように呼び出されます。

  window_set_fullscreen(window, true);
      
      



最初の引数はそれぞれウィンドウの名前、2番目は引数であり、trueは全画面、falseはバーです。 微妙-この関数はwindow_stack_pushの前に呼び出す必要があります。そうしないと、奇跡は起こりません。



次に、乱数ジェネレーターを見てみましょう。 これを行うために、各呼び出しで乱数を返すrand()関数があります。 他のソフトウェアRNGと同様に、作業を開始する前に乱数で初期化する必要があります。そうしないと、開始するたびに数字の行が繰り返されます。 これはsrand()関数によって行われます。 たとえば、SDKには現在の時刻で初期化される例があります。 プログラムはいつ開始されるかわからないため、この時間は毎回異なるため、これはアイデアのエントロピーの十分なソースです。 このようにします:

 srand(time(NULL));
      
      





確かに、ジェネレーターはかなり多くの数を生成できるようになりました-明らかに私たちが可能な答えを持っている以上です。 したがって、このメッセージの構成[rand()%21]を使用すると、 %は整数除算の剰余です。 ジェネレータが456を返し、それらが21で除算され、残り(456-21 * 21)-15が応答番号として使用されるとします。 21を超えることはできません。この場合、除算の残りの部分がゼロになるためです。



上記のすべてを1つの全体に結合すると、次のような関数呼び出しが得られます。
 text_layer_set_text(text_layer, messages[rand() % 21]);
      
      





以下がソース全体です。

 #include "pebble.h" Window *window; /*     */ TextLayer *text_layer; /*      */ static const char* messages[] = {"", " "," "," ","    ","  - "," "," ","","  - ","  ,   "," ","     ","  ","   ","  ","  - ","  - ","   "," ","",}; /*    */ int main(void) { window = window_create(); /*   */ window_set_background_color(window, GColorBlack); /*    */ window_set_fullscreen(window, true); /*   */ window_stack_push(window, true); /*   */ text_layer = text_layer_create(GRect(1, 47, 142, 77)); /*    */ text_layer_set_text_color(text_layer, GColorWhite); /*    */ text_layer_set_background_color(text_layer, GColorClear); /*    */ text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24)); /*   */ text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); /*     */ layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer)); /*         */ srand(time(NULL)); /*       */ text_layer_set_text(text_layer, messages[rand() % 21]); /*        */ app_event_loop(); /*  - */ text_layer_destroy(text_layer); /*  ,   */ window_destroy(window); /*  ,   */ }
      
      





プログラムは起動時にメッセージを表示し、何もしません。 別のメッセージを表示するには、プログラムを再起動する必要があります。





次のステップは、ボタンをクリックしたときにメッセージを表示することです。



Pebble APIでは、「サブスクリプション」という用語は、メインループでは起動されないが、いくつかのアクション(タイマーのチェック、ボタンを押すなど)の後に起動される機能を指定するために使用されます。 前回のレッスンで、1秒に1回画面更新機能を呼び出すタイマーにサインアップしたことを覚えていますか? これは似たようなものです。ボタンクリックをサブスクライブし(APIには既にいくつかの既製のオプションがあります- シングルクリックダブルクリックホールドなど )、その後、設定した関数が起動します。



APIは、クリックをキャッチするウィンドウへのポインターとサブスクリプションが記述される関数の名前を引数として取るwindow_set_click_config_provider()メソッドを呼び出す必要があると言っています。 ここではボタンをサブスクライブせず、 window_set_click_config_providerで指定された関数でのみサブスクライブすることに注意してください。 これは次のように行われます。

 window_set_click_config_provider(window, WindowsClickConfigProvider);
      
      



ウィンドウポインターはwindow、関数の名前はWindowsClickConfigProviderです。 作成する:

 void WindowsClickConfigProvider(void *context) { }
      
      





そして、 window_single_click_subscribeメソッドを内部に追加します。 これらのメソッドは、ボタンの名前とコントロールが渡される関数を受け取ります:

 window_single_click_subscribe(BUTTON_ID_UP, click);
      
      



この場合、ボタンを押し上げると、クリックが呼び出されます。

ボタン(3つあります)は、それぞれBUTTON_ID_UP、BUTTON_ID_SELECT、BUTTON_ID_DOWNと呼ばれます。 「戻る」ボタンをサブスクライブすることもできますが、メニューにアプリケーションの画面が1つある場合は常に前の画面に移動します。



これで、アプリケーションは次のようになります。





そしてそのソース:
 #include "pebble.h" Window *window; /*     */ TextLayer *text_layer; /*      */ static const char* messages[] = {"", " "," "," - ","   ","  - "," "," ","","  - ","  ,   "," ","     ","  ","   ","  ","  - ","  - ","   "," ","",}; /*    */ void click(ClickRecognizerRef recognizer, void *context) /*        */ { text_layer_set_text(text_layer, messages[rand() % 21]); /*        */ } void WindowsClickConfigProvider(void *context) /* ,        */ { window_single_click_subscribe(BUTTON_ID_UP, click); /*       click */ window_single_click_subscribe(BUTTON_ID_SELECT, click); window_single_click_subscribe(BUTTON_ID_DOWN, click); } int main(void) { window = window_create(); /*   */ window_set_background_color(window, GColorBlack); /*    */ window_set_fullscreen(window, true); /*   */ window_stack_push(window, true); /*   */ text_layer = text_layer_create(GRect(0, 7, 144, 168)); /*    */ text_layer_set_text_color(text_layer, GColorWhite); /*    */ text_layer_set_background_color(text_layer, GColorClear); /*    */ text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24)); /*   */ text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); /*     */ layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer)); /*         */ srand(time(NULL)); /*       */ window_set_click_config_provider(window, WindowsClickConfigProvider); /*  ,        */ text_layer_set_text(text_layer, "Magic Pebble \n  ,     \"\"  \"\"    "); /*     */ app_event_loop(); /*   */ text_layer_destroy(text_layer); /*  ,   */ window_destroy(window); /*  ,   */ }
      
      









うまくいく! バージョン0.1を割り当てることができます:)

しかし、何かが欠けています。 いくつかの効果を追加するといいでしょう。 ボタンをクリックしても時計がすぐに応答しないように、数秒間オプションを「整理」するように、回答を変更するアニメーションを作成できます。 引用符で-答えはどんな場合でもランダムになりますが、最初のケースではユーザーがアプリケーションに自信を持っているため、宝くじをするときにバッグや数字の入ったボールからカードを選択するランダムなプロセスに慣れています。



物理学を少し追加すると、さらに美しくなります。 実際、人々自身は、疑いもなく、逆指数で進行するプロセスに囲まれています。プロセスが最初に「高速」である場合、プロセスは直線的に進行しませんが、最初から時間が経過するほど速度が低下します。

それは何でも構いません-例えば、テーブルの上の熱いお茶の冷却。 お茶と周囲の空気の温度差が大きい場合、少し暖かい場合よりもはるかに速く冷却されます。 または、1杯のスパークリングウォーターに泡を立てます。 最初は、水中の炭酸の濃度が高い場合、非常に活発に分解しますが、しばらくすると濃度が低下し、それに伴い気泡の数が減少します。

この場合、私は運命の輪のような何かをしたいと思います-セグメントが最初にお互いを素早く交換し、徐々に減速します。 ここで摩擦は「有罪」です-速度が高いほど、ホイールが軸に対して摩擦し、エネルギーを失い、熱に変換されて減速します。 しかし、速度が低下すると摩擦損失も減少します。その結果、ホイールは最初の20%で速度の50%を失い、残りの70%で残りの50%を失います。



メッセージを変更する間隔をミリ秒単位でカウントします。 実験により、適切な値の範囲は0〜300〜400ミリ秒であることがわかりました。 間隔が長くなると、すでに表示されている回答が突然変更されたように感じられます。

この動作を提供する最も単純な関数は、x = x * 2のようなものです。 ただし、2を掛けると、関数グラフは急激に上昇し、反復ごとに遅延時間が2倍になります。 256(次の値-512はすでに便利な境界を超えているため、最大遅延)が既にステップ8にあり、持続時間は1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 + 256 = 511msのみです。 0.5秒は速すぎます。

経験的に、乗数は1.08〜1.2の範囲にある必要があることに気づき、約30ステップと約3秒の持続時間を取得します。 しかし、私は関数x = x * yが好きではありません-それはあまりにも中空に上昇し、ちらつきが遅くなりすぎます(はい、私は奇妙です)、私はそれが「速く」長く点滅し、その後突然停止することを望みます。



それはもっと簡単かもしれません-遅延の値を配列に打ち込んで、それらをあまりにも多くないので、それを編集して満足させる-約40個です。しかし、私たちが必要とする方法で機能する関数を導出することははるかに興味深いです。 乗算は私たちに適していないので、除算を試みます。 x = x / 0.7のようなもの。 しかし、それ自体は急激に上昇します-ステップ18で既に300を取得していますが、もう少し欲しいです。 ただし、たとえば、100で割ったり、1000で割ったりすることができます。すべての関数のグラフを初期値1でプロットします。グラフの上の数字はステップ数です。



それは、y = y / 0.7 x = y / 100が私たちに非常に適していることを意味します。



しかし、最初に、1つの不具合を修正します。 起動時の情報とメッセージが同じレイヤーに表示され、画面の上部にメッセージが表示されます(残念ながら、垂直方向の配置)。 はい、小さな活字で、さらに作成することができます-それらははるかに短く、画面に収まります。 レイヤーのサイズを変更するためのAPIメソッドが見つからなかったため、レイヤーを削除して再度作成する必要がありますが、座標は異なります。 ただし、これは見苦しくなります-コードの一部が複製され(作成後のレイヤー設定)、これは発生しません-別の関数でコードの一部を取り出します。

私たちは作成します:
 void config_text_layer(int16_t x,int16_t y,int16_t h,int16_t w, const char *font_key) { }
      
      





最初の4つのパラメーターはレイヤーに関する情報です。ポイントの座標とサイズ、5番目のパラメーターはフォントです。 したがって、これらの変数を使用するように初期化関数を書き直します。

 text_layer = text_layer_create(GRect(x, y, h, w)); text_layer_set_font(text_layer, fonts_get_system_font(font_key));
      
      





そして、それらをレイヤー設定コードの残りと一緒に関数に挿入します。 これで、次のような適切な場所でそれを行うことができます。

 text_layer_destroy(text_layer); config_text_layer(5, 40, 134, 120, FONT_KEY_GOTHIC_28);
      
      





それでは、ボタンをクリックしたときに呼び出されるクリック関数でそれを行いましょう。 はい、ボタンが押されるたびにレイヤーが作成されます。これは次のような簡単なチェックで回避できます。
 bool first_time=true; if (first_time == true) { text_layer_destroy(text_layer); config_text_layer(5, 40, 134, 120, FONT_KEY_GOTHIC_28); first_time = false; }
      
      





しかし、私は気にしませんでした。 タイマーを改善する。 APIでの検索により、関数app_timer_register()が与えられました。この関数は、タイマーが機能するmsの値、トリガー時に呼び出される必要がある関数の名前、およびこの関数に渡す必要があるデータへのポインターを引数として受け取ります。 残念ながら、ポインターの操作方法が理解できなかったため、コードの美しさに唾を吐き、グローバル変数を使用してそれを行う必要があります。

 float timer_delay=1;
      
      







間隔を増やしながらタイマーを再帰的に呼び出す関数を作成します。



 void timer_call() /*       */ { text_layer_set_text(text_layer, messages[rand() % 21]); /*    */ if (timer_delay < 300*100 ) /*      300... */ { timer_delay=timer_delay/0.7; /* ... ... */ app_timer_register(timer_delay/100, timer_call, NULL); /* ...    */ } else /*     300... */ { timer_delay=1; /*       -     */ } }
      
      





関数の中心は、timer_delay浮動小数点変数です。 30000に達するまで0.7で除算されます。変数の新しい値はそれぞれ100で除算され、遅延関数app_timer_registerの引数として与えられます。これは、トリガーされると、再びこの関数を呼び出します。



クリック()でこの関数への呼び出しを追加するだけです。

 void click(ClickRecognizerRef recognizer, void *context) /* ,      */ { text_layer_destroy(text_layer); /*      */ config_text_layer(5, 40, 134, 120, FONT_KEY_GOTHIC_28); /*         */ timer_call(); /*       */ }
      
      





そして、あなたは結果を楽しむことができます:



私たちがやったことについて少し考えてみると、実際の世界でRNGとして使用されているピースをシミュレートするためのプラットフォームを作成したことがわかります。 ボール内部の流体における多面的な図の複雑な動きは、予測できないプロセスです。 サイコロだけでなく。 ちなみにサイコロ! 別のアプリケーションのオプションではないものは何ですか?

私は本当に骨の端にある絵を探すようになり、出会った...いや、まあ、これらも絵です。 また、サイコロにも。 ドットではありません。 一般的に、私はこれに出くわしました:





そしてそれだけです。 このような素晴らしいアイデアがあるとき、サイコロは何ですか。 それを実装していきましょう!



セックスルーレット

プログラムのロジックは同じままです。 メッセージ配列を変更します。

 static const char* messages[] = {" "," "," "," "," "," "," "," "," "," "," "," "," "," ","  "," "," "," ","  "," "," "," ","  ",};
      
      





起動時のメッセージ:

 text_layer_set_text(text_layer, "Sex Roulette \n    ,      -->");
      
      





グラフィック配列が指すメモリ内に作成し、座標を示します。 構文は、text_layer_createとまったく同じです。

 image_layer = bitmap_layer_create(GRect(0 , 0, 144, 144));
      
      





作成されたレイヤーをメインウィンドウレイヤーの子にします。 なぜこれが必要なのですか? これは、他のレイヤーに関連するレイヤーの「高さ」(CSSの観点から、誰かがz-indexであると理解している場合)を調整します。 すべての子は親全体の上にあり、結論で閉じます。

 layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(image_layer));
      
      





ブレンドモードを設定します。 このパラメーターに応じて、画像は背景と異なる相互作用をします。

 bitmap_layer_set_compositing_mode(image_layer, GCompOpAssignInverted);
      
      





すべてのオプションはここで説明できます 。または、写真に固執することができます

画像

この場合、ソースはグラフィックレイヤーであり、デスティネーションはその親、ウィンドウのメインレイヤーです。 モノクロ写真で作業するときに、6つのオプションに収まるほどシンプルで素晴らしい...



次に、ランダムな画像を出力します。 Googleで「 ポーズアイコン 」などのクエリに適した画像(2色と小さい)を探してみましょう。

このサイトはこれを見つけました:



ベクターをダウンロードし、境界線を削除し、より高い解像度でPNGにエクスポートし、何らかのグラフィックエディターで開きます。

各画像を選択し、失敗した理解できないものを削除し、正方形に入力し、144ピクセルに縮小して、欠陥をクリーンアップします。 私たちの仕事の結果は、写真の入ったフォルダーになるはずです。



写真の1つから、24x28ピクセルのサイズのメニューのロゴを作成します。

->



プロジェクトフォルダーのappinfo.jsonファイルを開き、作成したリソースを追加します。 残念ながら、CloudPebbleでこれがどのように行われているかはわかりません。パスワードを受け入れず、すべてのプロジェクトのソースを把握できず、突然動作しなくなりました。 そこで、公式サイトの指示に従って開発環境をコンピューターにインストールし、そこに書きました。



したがって、appinfo.jsonについてです。 次のようになります。

 { "uuid": "0f7b8336-d72d-4806-9191-566ffd8f3a8c", "shortName": "SexRoulette", "longName": "SexRoulette", "companyName": "vvzvlad", "versionCode": 1, "versionLabel": "1.0.0", "watchapp": { "watchface": false }, "appKeys": { "dummy": 0 }, "resources": { "media": [ { "menuIcon": true, "type": "png", "name": "DEFAULT_MENU_ICON", "file": "img/logo.png" }, { "type": "png", "name": "POSE_1", "file": "img/1.png" },
      
      



最初は、なじみのあるフィールドがあり、その意味は説明がなくても明確であり、32枚の写真すべてが説明されています。 構造は次のようにする必要があることに注意してください。



  { "type": "png", "name": " ", "file": "img/1.png" }, { "type": "png", "name": " ", "file": "img/1.png" }
      
      





最後の角括弧の後には、ファイルアドレスを指定した後と同様に、コンマはありません。 そして、フィールドは、タイプ、名前、ファイルの順に正確に続く必要があります。

それは、いまいましい、 公式文書に反しています



詰め込むお尻のキーボード! 私はこの文書を書いた人たちに下痢の光線を送りましたが、私は30分間馬鹿になり、彼が何について呪っているのだろうと思いました。 また、彼は非常に不明瞭であるので、あなたは彼がそれを好きではないことを本当に理解しないでしょう。

 Traceback (most recent call last): File "/Users/vvzvlad/Documents/PebbleSDK-2.0-BETA2/Pebble/.waf-1.7.11-478a7e7e9ed077304a8092741524bf8b/waflib/Scripting.py", line 351, in execute return execute_method(self) File "/Users/vvzvlad/Documents/PebbleSDK-2.0-BETA2/Pebble/.waf-1.7.11-478a7e7e9ed077304a8092741524bf8b/waflib/Build.py", line 106, in execute self.execute_build() File "/Users/vvzvlad/Documents/PebbleSDK-2.0-BETA2/Pebble/.waf-1.7.11-478a7e7e9ed077304a8092741524bf8b/waflib/Build.py", line 109, in execute_build self.recurse([self.run_dir]) File "/Users/vvzvlad/Documents/PebbleSDK-2.0-BETA2/Pebble/.waf-1.7.11-478a7e7e9ed077304a8092741524bf8b/waflib/Context.py", line 128, in recurse user_function(self) File "/Users/vvzvlad/Documents/PebbleSDK-2.0-BETA2/SexRoulette/wscript", line 18, in build ctx.load('pebble_sdk')
      
      



まあ、彼と地獄に。 すでに理解したように、メニューの画像アイコンには「menuIcon」フィールドがtrueでマークされており、プログラムからもアクセスできます。



写真に戻りましょう。 ドキュメントでは、次のような画像のアップロードを推奨しています。

 image = gbitmap_create_with_resource(RESOURCE_ID_POSE_1);
      
      





これは私たちには適していません。 種の巨大な構造の大騒ぎをしないでください

 select rand() % 31 case 1 image = gbitmap_create_with_resource(RESOURCE_ID_POSE_1); case 2 image = gbitmap_create_with_resource(RESOURCE_ID_POSE_2);
      
      





これはいです。 ドキュメントから、RESOURCE_ID_POSE_2は、リソース番号が格納されるuint32_t型の変数にすぎないことがわかります。



必要な型の配列を作成します。

 static const uint32_t images[]
      
      





そして、必要なリソースをリストします。

 static const uint32_t images[] = {RESOURCE_ID_POSE_1,RESOURCE_ID_POSE_2,RESOURCE_ID_POSE_3,RESOURCE_ID_POSE_4,RESOURCE_ID_POSE_5,RESOURCE_ID_POSE_6,RESOURCE_ID_POSE_7,RESOURCE_ID_POSE_8,RESOURCE_ID_POSE_9,RESOURCE_ID_POSE_10,RESOURCE_ID_POSE_11,RESOURCE_ID_POSE_12,RESOURCE_ID_POSE_13,RESOURCE_ID_POSE_14,RESOURCE_ID_POSE_15,RESOURCE_ID_POSE_16,RESOURCE_ID_POSE_17,RESOURCE_ID_POSE_18,RESOURCE_ID_POSE_19,RESOURCE_ID_POSE_20,RESOURCE_ID_POSE_21,RESOURCE_ID_POSE_22,RESOURCE_ID_POSE_23,RESOURCE_ID_POSE_24,RESOURCE_ID_POSE_25,RESOURCE_ID_POSE_26,RESOURCE_ID_POSE_27,RESOURCE_ID_POSE_28,RESOURCE_ID_POSE_29,RESOURCE_ID_POSE_30,RESOURCE_ID_POSE_31,RESOURCE_ID_POSE_32,};
      
      





これで、テキストと同じ方法でランダムな画像を呼び出すことができます。

 image = gbitmap_create_with_resource(images[rand() % 31]);
      
      





フラッシュメモリに存在しない画像を呼び出して、RAMに配置しました。 ここで、画像関数bitmap_layer_set_bitmapの保存場所にポインターを渡す必要があります。これにより、目的のグラフィックレイヤーに表示されます。

これは次のように行われます。

 bitmap_layer_set_bitmap(image_layer, image);
      
      





image_layerはグラフィックスレイヤーのメモリへのポインターであり、 imageはメモリー内の画像へのポインターです。

すべてが好きです。 発射!



クロックが停止してから再起動し、2回目の起動後、リカバリに進み、アップグレードを要求しました。

そうです、各サイクルで画像をメモリにロードしても、そこからアンロードしませんでした。 彼らはRAMを獲得し、時計がロードを拒否したという事実から判断して、他の場所に登りました。

これはスパーアルタです! 埋め込まれた! 彼らはこれを許しません。

私たちはそれを正しく行います。 , .

 gbitmap_destroy(image); image = gbitmap_create_with_resource(images[rand() % 31]); bitmap_layer_set_bitmap(image_layer, image);
      
      





image , gbitmap_destroy . App Crashed…

, , - . , - . :

 bool first_time=true;
      
      





, :

 void timer_call() { first_time = false;
      
      







gbitmap_destroy — first_time == false, text_layer_destroy config_text_layer click — , first_time == true:

 void timer_call() { if (first_time == false) { gbitmap_destroy(image); bitmap_layer_destroy(image_layer); } first_time = false; ..... void click(ClickRecognizerRef recognizer, void *context) { if (first_time == true) { text_layer_destroy(text_layer); config_text_layer(0, 146, 144, 168-146, FONT_KEY_GOTHIC_18); }
      
      





うまくいく!





, . :

  text_layer_destroy(text_layer); window_destroy(window); gbitmap_destroy(image); bitmap_layer_destroy(image_layer);
      
      





gbitmap. , ! , — . . — , :

 if (first_time == false) { gbitmap_destroy(image); }
      
      





.

 #include "pebble.h" float timer_delay=1; /*        */ Window *window; /*     */ TextLayer *text_layer; /*      */ static BitmapLayer *image_layer; /*      */ static GBitmap *image; /*       */ bool first_time=true; /*     */ static const char* messages[] = {" "," "," "," "," "," "," "," "," "," "," "," "," "," ","  "," "," "," ","  "," "," "," ","  ",}; /*    */ static const uint32_t images[] = {RESOURCE_ID_POSE_1,RESOURCE_ID_POSE_2,RESOURCE_ID_POSE_3,RESOURCE_ID_POSE_4,RESOURCE_ID_POSE_5,RESOURCE_ID_POSE_6,RESOURCE_ID_POSE_7,RESOURCE_ID_POSE_8,RESOURCE_ID_POSE_9,RESOURCE_ID_POSE_10,RESOURCE_ID_POSE_11,RESOURCE_ID_POSE_12,RESOURCE_ID_POSE_13,RESOURCE_ID_POSE_14,RESOURCE_ID_POSE_15,RESOURCE_ID_POSE_16,RESOURCE_ID_POSE_17,RESOURCE_ID_POSE_18,RESOURCE_ID_POSE_19,RESOURCE_ID_POSE_20,RESOURCE_ID_POSE_21,RESOURCE_ID_POSE_22,RESOURCE_ID_POSE_23,RESOURCE_ID_POSE_24,RESOURCE_ID_POSE_25,RESOURCE_ID_POSE_26,RESOURCE_ID_POSE_27,RESOURCE_ID_POSE_28,RESOURCE_ID_POSE_29,RESOURCE_ID_POSE_30,RESOURCE_ID_POSE_31,RESOURCE_ID_POSE_32,}; /*     */ void timer_call() /*       */ { if (first_time == false) /*      ... */ { bitmap_layer_destroy(image_layer); /* ...   ... */ gbitmap_destroy(image); /* ..      */ } first_time = false; /*     */ image = gbitmap_create_with_resource(images[rand() % 31]); /*         */ bitmap_layer_set_bitmap(image_layer, image); /*      */ text_layer_set_text(text_layer, messages[rand() % 23]); /*    */ if (timer_delay < 300*100 ) /*      300... */ { timer_delay=timer_delay/0.7; /* ... ... */ app_timer_register(timer_delay/100, timer_call, NULL); /* ...    */ } else /*     300... */ { timer_delay=1; /*       -        */ } } void config_text_layer(int16_t x,int16_t y,int16_t h,int16_t w, const char *font_key) /*    ,  ,       */ { text_layer = text_layer_create(GRect(x, y, h, w)); /*   ,     */ text_layer_set_text_color(text_layer, GColorWhite); /*    */ text_layer_set_background_color(text_layer, GColorClear); /*    */ text_layer_set_font(text_layer, fonts_get_system_font(font_key)); /*   */ text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); /*     */ layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer)); /*         */ } void click(ClickRecognizerRef recognizer, void *context) /* ,      */ { if (first_time == true) /*      ... */ { text_layer_destroy(text_layer); /* ...     ... */ config_text_layer(0, 146, 144, 168-146, FONT_KEY_GOTHIC_18); /* ...           */ } timer_call(); /*       */ } void WindowsClickConfigProvider(void *context) /* ,        */ { window_single_click_subscribe(BUTTON_ID_UP, click); /*       click */ window_single_click_subscribe(BUTTON_ID_SELECT, click); window_single_click_subscribe(BUTTON_ID_DOWN, click); } int main(void) { window = window_create(); /*   */ window_set_background_color(window, GColorBlack); /*    */ window_set_fullscreen(window, true); /*    */ window_stack_push(window, true); /*   */ srand(time(NULL)); /*       */ window_set_click_config_provider(window, WindowsClickConfigProvider); /*  ,        */ config_text_layer(0, 20, 144, 168, FONT_KEY_GOTHIC_24); /*        */ text_layer_set_text(text_layer, "Sex Roulette \n    ,      -->"); /*     */ image_layer = bitmap_layer_create(GRect(0 , 0, 144, 144)); /*   ,     */ layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(image_layer)); /*         */ bitmap_layer_set_compositing_mode(image_layer, GCompOpAssignInverted); /*    */ app_event_loop(); /*   */ text_layer_destroy(text_layer); /*   ,   */ window_destroy(window); /*   ,   */ bitmap_layer_destroy(image_layer); /*   ,   */ if (first_time == false) /*      ... */ { gbitmap_destroy(image); /*     ,  ,  -  , ..     */ } }
      
      



?! .





. . 7575 :



appinfo.json, , images:

 static const uint32_t images[] = {RESOURCE_ID_DICE_1,RESOURCE_ID_DICE_2,RESOURCE_ID_DICE_3,RESOURCE_ID_DICE_4,RESOURCE_ID_DICE_5,RESOURCE_ID_DICE_6,};
      
      





: WindowsClickConfigProvider click . , ! .



:

 accel_tap_service_subscribe(accel_int);
      
      





, :

 void accel_int(AccelAxisType axis, int32_t direction) { if (first_time == true) { text_layer_destroy(text_layer); } timer_call(); }
      
      





: ( ) — . — :) .



timer_call . ( , — 144144, ), . — . rand . 7575 144168. , , , 0...69(144-75) -, 0...93(168-75) y-. : rand()%(144-75) rand()%(168-75) . :

 image_layer = bitmap_layer_create(GRect(rand()%(144-75), rand()%(168-75), 75, 75));
      
      







:

 if (timer_delay < 300*1000 ) { timer_delay=timer_delay/0.7; app_timer_register(timer_delay/1000, timer_call, NULL); }
      
      



100, — 1000. . , , . , — , , — , .



, . : , . . , API :

 light_enable(bool enable) light_enable_interaction()
      
      





あまりない。 . : l ight_enable(true) light_enable(false) , — , ( ). ( , ?), . - timer_call .

main :

 text_layer_set_text(text_layer, "    ");
      
      





:

 if (first_time == true) { text_layer_destroy(text_layer); } else { bitmap_layer_destroy(image_layer); gbitmap_destroy(image); } accel_tap_service_unsubscribe();
      
      



. — , . — , — , — accel_int



 #include "pebble.h" float timer_delay=1; /*        */ Window *window; /*     */ TextLayer *text_layer; /*      */ static BitmapLayer *image_layer; /*      */ static GBitmap *image; /*       */ bool first_time=true; /*     */ static const uint32_t images[] = {RESOURCE_ID_DICE_1,RESOURCE_ID_DICE_2,RESOURCE_ID_DICE_3,RESOURCE_ID_DICE_4,RESOURCE_ID_DICE_5,RESOURCE_ID_DICE_6,}; /*      */ void timer_call() /*            */ { if (first_time == false)/*      ... */ { bitmap_layer_destroy(image_layer); /* ...   ,     ... */ gbitmap_destroy(image); /* ...      */ } first_time = false; /*     */ image_layer = bitmap_layer_create(GRect(rand()%(144-75), rand()%(168-75), 75, 75)); /*     ,     */ layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(image_layer)); /*    */ image = gbitmap_create_with_resource(images[rand() % 6]); /*         */ bitmap_layer_set_bitmap(image_layer, image); /*      */ light_enable_interaction(); /*   */ if (timer_delay < 300*1000 ) /*      300... */ { timer_delay=timer_delay/0.7; /* ... ... */ app_timer_register(timer_delay/1000, timer_call, NULL); /* ...    */ } else /*     300... */ { timer_delay=1; /*       -        */ } } void accel_int(AccelAxisType axis, int32_t direction) /*     ... */ { if (first_time == true) /*    ... */ { text_layer_destroy(text_layer); /* ...      */ } timer_call(); /*   */ } int main(void) { window = window_create(); /*   */ window_set_background_color(window, GColorBlack); /*    */ window_set_fullscreen(window, true); /*   */ window_stack_push(window, true); /*     */ srand(time(NULL)); /*       */ text_layer = text_layer_create(GRect(0 , 30, 144, 168)); /*   ,     */ text_layer_set_text_color(text_layer, GColorWhite); /*    */ text_layer_set_background_color(text_layer, GColorClear); /*    */ text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28)); /*   */ text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); /*     */ layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer)); /*         */ text_layer_set_text(text_layer, "    "); /*     */ accel_tap_service_subscribe(accel_int); /*      */ app_event_loop(); /*   */ if (first_time == true) /*     ... */ { text_layer_destroy(text_layer); /* ...      */ } else /*     ... */ { bitmap_layer_destroy(image_layer); /* ...   ... */ gbitmap_destroy(image); /* ...     ,       accel_int */ } accel_tap_service_unsubscribe(); /*     */ window_destroy(window); /*   ,   */ }
      
      







うまくいく!





, :





参照資料

画像 MagicPebble mypebblefaces.com

画像 - mypebblefaces.com

画像 mypebblefaces.com

画像 MagicPebble github.com

画像 - github.com

画像 github.com

画像 , Pebble , . ( « pebble »). , — .








All Articles