よく小石待ち

画像

別のスマートウォッチを入手しました。 小石

最初は、開梱せずに他のガジェットファンに提供したかったのです。 結局のところ、私の手はまだGoogleとSonyからの未来の時計を覚えています。 Sony SmartWatchのデザインは素晴らしかったが、彼らは発疹と悲しみ以外の何も引き起こさなかった。



さて、私はある晩、左手に小石を1つ持っていると思います。 マウスには右手があります。 時計は迷惑ではありませんでした。 私はイライラしませんでした。 さらに、時計に素晴らしいドアが開き、ドアの後ろに宝物が開かれました。 愚か者のない自然なSDK。 つまり、人がデバイスを制御し、その逆はできません。 昔ながらのC言語と白黒スクリーン-それは奇跡ではありません!? 悪意のあるREST、パターン、リポジトリ、または単体テストはありません。 30歳未満で、私は3つのアプリケーションを作成し、ジンジャーデバイスとPebbleのプログラミングプロセスの簡単なレビューを書きました。



ボタンの下には、7つの写真、7つのコード、7つのリンク、7つの悪いヒントがあります。





1.時計はiOSとAndroidでサポートされています



時計をiPhoneと同期するには、対応するPebble アプリをAppstoreからダウンロードする必要があります。

画像

アプリケーションはシンプルで明確であり、説明は不要です。 欠点が1つあります-iPad用の無料バージョンはありません。 欠点は3ドルで簡単に発生します。 アプリケーションを使用する上級ユーザーは、時計のファームウェアを最新のものに簡単に更新できます。 また、開発者は、アプリケーションを介して、時計上で自分の手で作成したプログラムをダウンロードできます。



2.どうやってやるの?



Pebbleには驚異的なアプリケーション開発環境があります。 オンライン開発は奇跡です。 大量のソフトウェアをダウンロードしたり、 コンフィギュレーターを実行したり、設定を行ったり、 IT部門の専門家に電話をかけたりする必要はありません。



画像



サイトにアクセスして登録し、[ プロジェクト作成 ]ボタンをクリックするだけです。 それだけです! あなたはPebbleのアプリケーション開発者です。 C言語をお楽しみください。 ビットマップ 、テキスト、右ボタン3つ、左ボタン1つでクリックを処理するためのWindows 3.0パラダイムに非常によく似ています。 振動とそれを呼び出す機能があります。 音はありませんが、沈黙が大好きです。



プロジェクト設定では、選択はわずかです。

Pebbleには2種類のアプリケーションがあります。 実際には、ウォッチ(watchface)とアプリケーション(watchapp)。 2番目のオプションを選択しました。

この時計には2つのOSバージョン(およびSDKバージョン)があります。 1.xおよび2.x。 私は第2バージョンの開発を選択しました-新年には公式リリース2.0が約束されています。 2番目のバージョンの優れた機能を使用しない場合、変更のないプロジェクトは1.xで再構築できます。

クリックするだけで、プロジェクトにファイルとリソースを追加できます。 ファイル-テキストコードC、* .cおよび* .h。 リソース-PNGビットマップ画像とフォント。



次は?

開発者Pebble Webサイトでは、サンプルプロジェクトの既製セットが必要になります。 これはPebble SDKにあります-登録後にのみダウンロードできます。 約50の例があり、それらは素晴らしいです。



3.アプリケーションを時計にダウンロードする



時計へのアプリケーションのダウンロードは、時計と同期したiPhoneを使用して3回クリックするだけで実行されます。

iPhone / iPadからSafariを介して開発環境cloudpebble.netにアクセスします。



画像





Pebble実行可能ファイルの拡張子はPBWです。 それらは適切なストアにダウンロードできます。



4.ゲーム開発



Pebbleには2種類のアプリケーションがあります。 実際には、ウォッチ(watchface)とアプリケーション(watchapp)。

ゲームアプリケーションを作成するとき、何から始めればよいですか?

画面のサイズとボタンの数から。 時計には右側に3つのボタンがあり、左側に1つのボタンがあります。

画面サイズは144 x 168ポイントですが、上部のステータスバーは取り外し可能ではなく、144ポイントのスペースを奪います。



画像



もちろん、私はいくつかのゲームを作成しました。 テトリスは3つのボタンに最適です。 画面の向きを90度に変更すると、ゲームが苦痛に変わります。 しかし、テトリスとアルカノイドはキャッチしません。 そのような画面で、あなたはそれをやらなければなりません 。 エレクトロニクスでも同じです。



5.開発の特徴





最初に、私はゲームの例を使用してPebbleの下でプログラミングの本質を噛むことにしました。

そして、なぜだと思いましたか? 例からテキスト全体をリッピングしました。 プログラムを書くのに2時間かかりましたので、悪いコードを許してください。 速度とそれが機能するという事実は私を正当化します。 プロジェクトには1つのファイルしかありません。はい、main.cです。



プログラムテキスト
#include "pebble.h" static int egg_status[8]; static int egg_ticks[8]; static int egg_places[]= { 4, 0, 0, 0, 0, 2, 5, 0, 0, 0, 2, 4, 6, 0, 0, 1, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0 }; static int level = 0; static int levelFlag = 0; static int egg_pos[]= { -2, 72, 0, 75, 4, 78, 9, 83, 14, 88, 20, 94, 0, 0, -2, 22, 0, 25, 4, 28, 9, 33, 14, 38, 21, 44, 0, 0, 137, 30, 134, 34, 130, 38, 127, 43, 121, 48, 114, 54, 0, 0, 137, 83, 134, 86, 131, 89, 127, 94, 121, 99, 114, 104, 0, 0 }; static int current_pos = 1; static int best = 25; static AppTimer *timer; static Window *window; static Layer *layer; // We will use a bitmap to composite with a large circle static GBitmap *image_1; static GBitmap *image_2; static GBitmap *image_3; static GBitmap *image_4; static GBitmap *image_5; static GBitmap *image_7; static GBitmap *image_8; static GBitmap *image_6; static GBitmap *image_0; static int ticks = 0; static int score = 0; static int failed = 0; static int egg_failed = 0; char *itoa(int num); static const VibePattern broken_egg_pattern = { .durations = (uint32_t []) {50, 50, 50}, .num_segments = 3 }; static const VibePattern game_over_pattern = { .durations = (uint32_t []) {300, 100, 300}, .num_segments = 3 }; static void timer_callback(void *context) { if (failed<3) { levelFlag = 0; egg_failed = 0; for (int i=0; i<8; i++) if (egg_status[i]>0) { egg_ticks[i]++; if (egg_ticks[i]==6) { int k = egg_status[i]; if (k==current_pos) { score++; } else { egg_failed = k; ++failed; int game_over = failed == 3; //TODO: endgame screen if (game_over) { vibes_enqueue_custom_pattern(game_over_pattern); } else { vibes_enqueue_custom_pattern(broken_egg_pattern); } } egg_ticks[i] = 0; egg_status[i] = 0; } } int lev = 1; if (score>10) lev = 2; if (score>10*3) lev = 3; if (score>10*10) lev = 4; if (lev!=level) { level = lev; levelFlag = 1; vibes_enqueue_custom_pattern(broken_egg_pattern); } for (int i =0; i<level; i++) { int k = egg_places[i+(level-1)*5]; int j = ticks%8; if (k==j) { egg_ticks[i] = 0; egg_status[i] = 1 + rand()%4; } } if (levelFlag) { ticks=0; for (int i =0; i<8; i++) { egg_status[i] = 0; egg_ticks[i] = 0; } } else { ticks++; } } layer_mark_dirty(layer); const uint32_t timeout_ms = 500; timer = app_timer_register(timeout_ms, timer_callback, NULL); } // This is a layer update callback where compositing will take place static void layer_update_callback(Layer *layer, GContext* ctx) { char title[20]; GRect bounds = layer_get_frame(layer); GRect destination = image_1->bounds; destination.origin.x = (bounds.size.w-destination.size.w)/2; destination.origin.y = 30; if (failed<3) { if (levelFlag) { snprintf(title, 20, "\nLevel \n%d", level); // Display the name of the current compositing operation graphics_context_set_text_color(ctx, GColorBlack); graphics_draw_text(ctx, title, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD), bounds, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, NULL); } else { snprintf(title, 20, "%d/%d", score, best); // Display the name of the current compositing operation graphics_context_set_text_color(ctx, GColorBlack); graphics_draw_text(ctx, title, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), bounds, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, NULL); // strcpy(title, "Lev "); // strcat(title, itoa(level)); // Draw the large circle the image will composite with // graphics_context_set_fill_color(ctx, GColorBlack); // graphics_fill_circle(ctx, GPoint(bounds.size.w/2, bounds.size.h+110), 180); // Use the image size to help center the image // Center horizontally using the window frame size // Set the current compositing operation // This will only cause bitmaps to composite // Draw the bitmap; it will use current compositing operation set if (current_pos==1) graphics_draw_bitmap_in_rect(ctx, image_1, destination); if (current_pos==2) graphics_draw_bitmap_in_rect(ctx, image_2, destination); if (current_pos==3) graphics_draw_bitmap_in_rect(ctx, image_3, destination); if (current_pos==4) graphics_draw_bitmap_in_rect(ctx, image_4, destination); GRect ground = image_0->bounds; ground.origin.x = (bounds.size.w-ground.size.w)/2; ground.origin.y = 30; graphics_context_set_compositing_mode(ctx, GCompOpAnd); graphics_draw_bitmap_in_rect(ctx, image_0, ground); for (int i=0; i<8; i++) if (egg_status[i]>0) { int img= egg_ticks[i]%2; int k = (egg_ticks[i]+(egg_status[i]-1)*7) *2; int x = egg_pos[k]; int y = egg_pos[k+1]; GRect egg_destination = image_5->bounds; egg_destination.origin.x = x; egg_destination.origin.y = y; graphics_draw_bitmap_in_rect(ctx, (img) ? image_5 : image_7, egg_destination); } if (egg_failed) { GRect egg_destination = image_6->bounds; egg_destination.origin.x = egg_failed < 3 ? 10 : 101; egg_destination.origin.y = 130; graphics_draw_bitmap_in_rect(ctx, image_6, egg_destination); } } } else { if (score>best) best = score; snprintf(title, 20, "\nLast %d\nBest %d", score, best); // Display the name of the current compositing operation graphics_context_set_text_color(ctx, GColorBlack); graphics_draw_text(ctx, title, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD), bounds, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, NULL); GRect egg_destination = image_6->bounds; egg_destination.origin.y = 130; egg_destination.origin.x = 10; graphics_draw_bitmap_in_rect(ctx, image_6, egg_destination); egg_destination.origin.x = 56; graphics_draw_bitmap_in_rect(ctx, image_6, egg_destination); egg_destination.origin.x = 101; graphics_draw_bitmap_in_rect(ctx, image_6, egg_destination); } } static void select_click_handler(ClickRecognizerRef recognizer, void *context) { if (failed==3) { level = 0; score = 0; for (int i =0; i<8; i++) { egg_status[i] = 0; egg_ticks[i] = 0; } failed = 0; } layer_mark_dirty(layer); } static void up_click_handler(ClickRecognizerRef recognizer, void *context) { current_pos--; if (current_pos<1) current_pos = 4; layer_mark_dirty(layer); } static void down_click_handler(ClickRecognizerRef recognizer, void *context) { current_pos++; if (current_pos>4) current_pos = 1; layer_mark_dirty(layer); } static void config_provider(void *context) { window_single_click_subscribe(BUTTON_ID_UP, up_click_handler); window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler); window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler); } int main(void) { time_t t = 0; uint16_t t_ms = 0; time_ms(&t, &t_ms); srand(t * 1000 + t_ms); // Then use the respective resource loader to obtain the resource for use // In this case, we load the image image_1 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_WOLF_1); image_2 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_WOLF_2); image_3 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_WOLF_3); image_4 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_WOLF_4); image_5 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_EGG_1); image_6 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_EGG_0); image_7 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_EGG_2); image_8 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_EGG_3); image_0 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_GROUND); window = window_create(); window_stack_push(window, true /* Animated */); window_set_click_config_provider(window, config_provider); // Initialize the layer Layer *window_layer = window_get_root_layer(window); GRect bounds = layer_get_frame(window_layer); layer = layer_create(bounds); // Set up the update layer callback layer_set_update_proc(layer, layer_update_callback); // Add the layer to the window for display layer_add_child(window_layer, layer); const uint32_t timeout_ms = 500; timer = app_timer_register(timeout_ms, timer_callback, NULL); for (int i =0; i<8; i++) { egg_status[i] = 0; egg_ticks[i] = 0; } // Enter the main loop app_event_loop(); // Cleanup the image gbitmap_destroy(image_1); gbitmap_destroy(image_2); gbitmap_destroy(image_3); gbitmap_destroy(image_4); gbitmap_destroy(image_5); gbitmap_destroy(image_6); gbitmap_destroy(image_7); gbitmap_destroy(image_0); gbitmap_destroy(image_8); layer_destroy(layer); window_destroy(window); }
      
      









少しコメントします。

 #include "pebble.h" int main(void) { // Then use the respective resource loader to obtain the resource for use // In this case, we load the image image_1 = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_WOLF_1); window = window_create(); window_stack_push(window, true /* Animated */); // Initialize the layer Layer *window_layer = window_get_root_layer(window); GRect bounds = layer_get_frame(window_layer); layer = layer_create(bounds); // Set up the update layer callback layer_set_update_proc(layer, layer_update_callback); // Add the layer to the window for display layer_add_child(window_layer, layer); // Enter the main loop app_event_loop(); // Cleanup the image gbitmap_destroy(image_1); layer_destroy(layer); window_destroy(window); }
      
      





main()関数は、メインウィンドウの初期化関数を呼び出し、リソースからビットマップをロードし、クリック処理関数に標準として名前を付けます。

その後、無限ループを回します

 app_event_loop();
      
      





Windows 3.1のように。

無限ループの後、すべてのリソースとメインウィンドウを解放することを忘れないでください。

それだけです



さらに、rand()を含むigrodelovのすべての標準関数。



6.ウォッチバージョン2.0の機能





Mithgolはロシア語のフォントについてはどうですか?

ロシア語が好きな人には、 汚いハックがあります。 チェックしませんでした。



7.アプリケーションストア



サイトに登録し、 アプリケーションを投稿してください。



画像



私は自分の1つをレイアウトしました。突然、ここのHabréに素晴らしいPebbleの所有者がいます。

読んでくれてありがとう。



脅威。 私の友人はアプリケーションをダウンロードし、ほぼ200個の卵を手に入れました。 そして、200個の卵を拾う人は誰でも見るでしょう...



All Articles