CINXE.COM
Purrfect Code の作り方: デベロッパー向けパズルゲーム - Google Developers Blog
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title> Purrfect Code の作り方: デベロッパー向けパズルゲーム - Google Developers Blog </title> <meta property="og:title" content="Purrfect Code の作り方: デベロッパー向けパズルゲーム- Google Developers Blog" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="description" content="Purrfect Code is a sokoban style box pushing puzzler Purrfect based on Google tech (Flutter, IDX, FLAME, Firebase) and designed to be playable on web browsers. Open the game in Project IDX, earn badges for each level, and showcase your badges on your Developer Profile." /> <meta content="summary_large_image" name="twitter:card"/> <meta content="Google for Developers Blog - News about Web, Mobile, AI and Cloud" property="twitter:title"/> <meta property="og:title" content="Purrfect Code の作り方: デベロッパー向けパズルゲーム" /> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Google for Developers Blog", "item": "https://developers.googleblog.com/" },{ "@type": "ListItem", "position": 2, "name": "Purrfect Code の作り方: デベロッパー向けパズルゲーム", "item": "http://developers.googleblog.com/ja/how-we-built-purrfect-code/" }] } </script> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Purrfect Code の作り方: デベロッパー向けパズルゲーム", "description": "Purrfect Code は、倉庫番スタイルの箱押し型パズルゲームで、ウェブブラウザでプレイできます。Google の技術(Flutter、IDX、FLAME、Firebase)をベースにしており、Project IDX でゲームを開き、各レベルのバッジを獲得して、デベロッパー プロフィールにバッジを表示できます。", "image": "https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/image2_R0cO2EO.2e16d0ba.fill-800x400.png", "datePublished": "2024-08-01", "author": [ { "@type": "Person", "name": "Google for Developers", "url": "/ja/search/?author=Google+for+Developers" } ] } </script> <meta content="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/image2_R0cO2EO.2e16d0ba.fill-1200x600.png" property="og:image"/> <!-- Google Tag Manager --> <script type="text/javascript" src="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/js/analytics.js"></script> <!-- End Google Tag Manager --> <link href="//www.gstatic.com/glue/v27_1/glue.min.css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/css/dgc_blog.css"> <link rel="icon" href="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/images/favicon.ico" type="image/x-icon"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preload" href="https://fonts.googleapis.com/css2?family=Product+Sans&family=Google+Sans+Display:ital@0;1&family=Google+Sans:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&family=Google+Sans+Text:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap" as="style"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Product+Sans&family=Google+Sans+Display:ital@0;1&family=Google+Sans:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&family=Google+Sans+Text:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400&display=swap"> <link href="https://www.gstatic.com/glue/cookienotificationbar/cookienotificationbar.min.css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/css/blog_detail.css" /> <link rel="stylesheet" href="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/pygmentify/css/default.min.css"> </head> <body id="main-content" class="glue-body "> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WVTLDSL " height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- HTML --> <header class="dgc-header"> <div class="dgc-header-inner"> <button class="hamburger" aria-haspopup="true" aria-expanded="false" aria-label="メニューを開く"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#menu"></use> </svg> </button> <div class="product-name-wrapper"> <a href="https://developers.google.com/" class="site-logo-link" data-label="Site logo"> <img src="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/images/g-dev.svg" class="site-logo" alt="Google for Developers"> </a> </div> <div class="desktop-nav-wrapper"> <div class="upper-tabs-wrapper"> <div class="upper-tabs"> <nav class="tabs" aria-label="上部タブ"> <div class="tab" dropdown> <a href="//developers.google.com/products" class="top-nav-title"> プロダクト </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="true" aria-label="プロダクトのプルダウン メニュー" class="dropdown-toggle"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#arrow-drop-down"></use> </svg> </a> <div class="tabs-dropdown" aria-label="サブメニュー"> <div class="tabs-dropdown-content"> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="開発メニュー">開発</li> <li class="nav-item"> <a href="//developer.android.com"> <div class="nav-item-title"> Android </div> </a> </li> <li class="nav-item"> <a href="//developer.chrome.com"> <div class="nav-item-title"> Chrome </div> </a> </li> <li class="nav-item"> <a href="//chromeos.dev/"> <div class="nav-item-title"> ChromeOS </div> </a> </li> <li class="nav-item"> <a href="//cloud.google.com"> <div class="nav-item-title"> Cloud </div> </a> </li> <li class="nav-item"> <a href="//firebase.google.com"> <div class="nav-item-title"> Firebase </div> </a> </li> <li class="nav-item"> <a href="//flutter.dev"> <div class="nav-item-title"> Flutter </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/assistant"> <div class="nav-item-title"> Google Assistant </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/maps"> <div class="nav-item-title"> Google Maps Platform </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/workspace"> <div class="nav-item-title"> Google Workspace </div> </a> </li> <li class="nav-item"> <a href="//www.tensorflow.org"> <div class="nav-item-title"> TensorFlow </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/youtube"> <div class="nav-item-title"> YouTube </div> </a> </li> </ul> </div> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="成長メニュー">成長</li> <li class="nav-item"> <a href="//firebase.google.com"> <div class="nav-item-title"> Firebase </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/google-ads"> <div class="nav-item-title"> Google Ads </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/analytics"> <div class="nav-item-title"> Google Analytics </div> </a> </li> <li class="nav-item"> <a href="//developer.android.com/distribute"> <div class="nav-item-title"> Google Play </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/search"> <div class="nav-item-title"> Search </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/web/fundamentals/engage-and-retain/push-notifications"> <div class="nav-item-title"> Web Push and Notification APIs </div> </a> </li> </ul> </div> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="収益化メニュー">収益化</li> <li class="nav-item"> <a href="//developers.google.com/admob"> <div class="nav-item-title"> AdMob </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/google-ads/api"> <div class="nav-item-title"> Google Ads API </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/pay"> <div class="nav-item-title"> Google Pay </div> </a> </li> <li class="nav-item"> <a href="//developer.android.com/google/play/billing/"> <div class="nav-item-title"> Google Play Billing </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/interactive-media-ads"> <div class="nav-item-title"> Interactive Media Ads </div> </a> </li> </ul> </div> </div> </div> </div> <div class="tab"> <a href="//developers.google.com/solutions/catalog" class="top-nav-title"> ソリューション </a> </div> <div class="tab"> <a href="//developers.google.com/events" class="top-nav-title"> イベント </a> </div> <div class="tab"> <a href="//developers.google.com/learn" class="top-nav-title"> 学習する </a> </div> <div class="tab" dropdown> <a href="//developers.google.com/community" class="top-nav-title"> コミュニティ </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="true" aria-label="コミュニティのプルダウン メニュー" class="dropdown-toggle"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#arrow-drop-down"></use> </svg> </a> <div class="tabs-dropdown" aria-label="サブメニュー"> <div class="tabs-dropdown-content"> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="グループ メニュー">グループ</li> <li class="nav-item"> <a href="//developers.google.com/community/gdg"> <div class="nav-item-title"> Google Developer Groups </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/gdsc"> <div class="nav-item-title"> Google Developer Student Clubs </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/womentechmakers"> <div class="nav-item-title"> Woman Techmakers </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/experts"> <div class="nav-item-title"> Google Developer Experts </div> </a> </li> <li class="nav-item"> <a href="//www.techequitycollective.com/"> <div class="nav-item-title"> Tech Equity Collective </div> </a> </li> </ul> </div> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="プログラム メニュー">プログラム</li> <li class="nav-item"> <a href="//developers.google.com/community/accelerators"> <div class="nav-item-title"> Accelerator </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/gdsc-solution-challenge"> <div class="nav-item-title"> Solution Challenge </div> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/devfest"> <div class="nav-item-title"> DevFest </div> </a> </li> </ul> </div> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="ストーリー メニュー">登場</li> <li class="nav-item"> <a href="//developers.google.com/community/stories"> <div class="nav-item-title"> すべてのストーリー </div> </a> </li> </ul> </div> </div> </div> </div> <div class="tab"> <a href="//developers.google.com/profile/u/me" class="top-nav-title"> デベロッパー プログラム </a> </div> <div class="tab"> <a href="//developers.googleblog.com/" class="top-nav-title"> ブログ </a> </div> </nav> </div> </div> </div> </div> <div class="dgc-header-search"> <div class="search-wrapper glue-page"> <div class="glue-grid"> <form id="search-form" action="/ja/search/" method="get" class="search-content glue-grid__col glue-grid__col--span-4-sm glue-grid__col--span-9-md glue-grid__col--span-7-lg"> <div class="search-input-wrapper"> <svg role="presentation" aria-hidden="true" class="glue-icon search-icon"> <use href="/glue-icon/#search"></use> </svg> <input type="text" name="query" placeholder="すべての記事を検索..." aria-label="検索" class="search-input-field" /> </div> <button class="glue-button glue-button--high-emphasis"> 検索 </button> </form> <div class="language-selector glue-grid__col glue-grid__col--span-4-sm glue-grid__col--span-3-md glue-grid__col--span-5-lg" aria-label="言語設定を選択"> <button type="button" aria-controls="lang-menu-header" aria-haspopup="true"> <svg role="presentation" aria-hidden="true" class="glue-icon lang-icon"> <use href="/glue-icon/#language"></use> </svg> <span class="lang-label">日本語</span> <svg role="presentation" aria-hidden="true" class="glue-icon lang-icon"> <use href="/glue-icon/#arrow-drop-down"></use> </svg> </button> <div id="lang-menu-header" class="lang-menu hidden" role="menu"> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" href="/en/how-we-built-purrfect-code/">English</a> </li> <li role="presentation"> <a role="menuitem" lang="es" href="/es/how-we-built-purrfect-code/">Español (Latam)</a> </li> <li role="presentation"> <a role="menuitem" lang="id" href="/id/how-we-built-purrfect-code/">Bahasa Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" aria-current="true" href="/ja/how-we-built-purrfect-code/">日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" href="/ko/how-we-built-purrfect-code/">한국어</a> </li> <li role="presentation"> <a role="menuitem" lang="pt-br" href="/pt-br/how-we-built-purrfect-code/">Português (Brasil)</a> </li> <li role="presentation"> <a role="menuitem" lang="zh-hans" href="/zh-hans/how-we-built-purrfect-code/">简体中文</a> </li> </ul> </div> </div> </div> </div> </div> </header> <div class="mobile-drawer" top-level-nav> <nav class="nav-content" aria-label="サイドメニュー"> <div class="mobile-header"> <button class="nav-close-btn nav-btn" aria-label="ナビゲーションを閉じる"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#close"></use> </svg> </button> <button class="nav-back-btn nav-btn hidden" aria-label="メニューに戻る"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#arrow-back"></use> </svg> </button> <div class="product-name-wrapper"> <a href="https://developers.google.com/" class="site-logo-link" data-label="Site logo"> <img src="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/images/g-dev.svg" class="site-logo" alt="Google for Developers"> </a> </div> </div> <div class="nav-wrapper"> <div class="mobile-nav-top"> <ul class="nav-list"> <li class="nav-item"> <a href="//developers.google.com/products" class="nav-title" data-label="Tab: Products"> <span class="nav-text" tooltip=""> プロダクト </span> </a> <ul class="nav-responsive-tabs"> <li class="nav-item"> <span tabindex="0" class="nav-title products-btn" data-label="More Products"> <span class="nav-text" menu="Products"> 増やす </span> <span class="nav-icon" menu="Products"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#arrow-forward"></use> </svg> </span> </span> </li> </ul> </li> <li class="nav-item"> <a href="//developers.google.com/solutions/catalog" class="nav-title" data-label="Tab: Solutions"> <span class="nav-text" tooltip=""> ソリューション </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/events" class="nav-title" data-label="Tab: Events"> <span class="nav-text" tooltip=""> イベント </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/learn" class="nav-title" data-label="Tab: Learn"> <span class="nav-text" tooltip=""> 学習する </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community" class="nav-title" data-label="Tab: Community"> <span class="nav-text" tooltip=""> コミュニティ </span> </a> <ul class="nav-responsive-tabs"> <li class="nav-item"> <span tabindex="0" class="nav-title community-btn" data-label="More Community"> <span class="nav-text" menu="Community"> 増やす </span> <span class="nav-icon" menu="Community"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#arrow-forward"></use> </svg> </span> </span> </li> </ul> </li> <li class="nav-item"> <a href="//developers.google.com/profile/u/me" class="nav-title" data-label="Tab: Developer Program"> <span class="nav-text" tooltip=""> デベロッパー プログラム </span> </a> </li> <li class="nav-item"> <a href="//developers.googleblog.com/" class="nav-title" data-label="Tab: Blog"> <span class="nav-text" tooltip=""> Blog </span> </a> </li> </ul> </div> <div class="mobile-nav-bottom"> <ul class="nav-list products-submenu" menu="Products" aria-label="サイドメニュー"> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> 開発 </span> </span> </li> <li class="nav-item"> <a href="//developer.android.com" class="nav-title"> <span class="nav-text"> Android </span> </a> </li> <li class="nav-item"> <a href="//developer.chrome.com" class="nav-title"> <span class="nav-text"> Chrome </span> </a> </li> <li class="nav-item"> <a href="//chromeos.dev/" class="nav-title"> <span class="nav-text"> ChromeOS </span> </a> </li> <li class="nav-item"> <a href="//cloud.google.com" class="nav-title"> <span class="nav-text"> Cloud </span> </a> </li> <li class="nav-item"> <a href="//firebase.google.com" class="nav-title"> <span class="nav-text"> Firebase </span> </a> </li> <li class="nav-item"> <a href="//flutter.dev" class="nav-title"> <span class="nav-text"> Flutter </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/assistant" class="nav-title"> <span class="nav-text"> Google Assistant </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/maps" class="nav-title"> <span class="nav-text"> Google Maps Platform </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/workspace" class="nav-title"> <span class="nav-text"> Google Workspace </span> </a> </li> <li class="nav-item"> <a href="//www.tensorflow.org" class="nav-title"> <span class="nav-text"> TensorFlow </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/youtube" class="nav-title"> <span class="nav-text"> YouTube </span> </a> </li> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> 成長 </span> </span> </li> <li class="nav-item"> <a href="//firebase.google.com" class="nav-title"> <span class="nav-text"> Firebase </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/google-ads" class="nav-title"> <span class="nav-text"> Google Ads </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/analytics" class="nav-title"> <span class="nav-text"> Google Analytics </span> </a> </li> <li class="nav-item"> <a href="//developer.android.com/distribute" class="nav-title"> <span class="nav-text"> Google Play </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/search" class="nav-title"> <span class="nav-text"> Search </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/web/fundamentals/engage-and-retain/push-notifications" class="nav-title"> <span class="nav-text"> Web Push and Notification APIs </span> </a> </li> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> 収益化 </span> </span> </li> <li class="nav-item"> <a href="//developers.google.com/admob" class="nav-title"> <span class="nav-text"> AdMob </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/google-ads/api" class="nav-title"> <span class="nav-text"> Google Ads API </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/pay" class="nav-title"> <span class="nav-text"> Google Pay </span> </a> </li> <li class="nav-item"> <a href="//developer.android.com/google/play/billing/" class="nav-title"> <span class="nav-text"> Google Play Billing </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/interactive-media-ads" class="nav-title"> <span class="nav-text"> Interactive Media Ads </span> </a> </li> </ul> <ul class="nav-list community-submenu hidden" menu="Community" aria-label="サイドメニュー"> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> グループ </span> </span> </li> <li class="nav-item"> <a href="//developers.google.com/community/gdg" class="nav-title"> <span class="nav-text"> Google Developer Groups </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/gdsc" class="nav-title"> <span class="nav-text"> Google Developer Student Clubs </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/womentechmakers" class="nav-title"> <span class="nav-text"> Woman Techmakers </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/experts" class="nav-title"> <span class="nav-text"> Google Developer Experts </span> </a> </li> <li class="nav-item"> <a href="//www.techequitycollective.com/" class="nav-title"> <span class="nav-text"> Tech Equity Collective </span> </a> </li> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> プログラム </span> </span> </li> <li class="nav-item"> <a href="//developers.google.com/community/accelerators" class="nav-title"> <span class="nav-text"> Accelerator </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/gdsc-solution-challenge" class="nav-title"> <span class="nav-text"> Solution Challenge </span> </a> </li> <li class="nav-item"> <a href="//developers.google.com/community/devfest" class="nav-title"> <span class="nav-text"> DevFest </span> </a> </li> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> 登場 </span> </span> </li> <li class="nav-item"> <a href="//developers.google.com/community/stories" class="nav-title" aria-label="All Stories"> <span class="nav-text"> すべてのストーリー </span> </a> </li> </ul> </div> </div> </nav> <select aria-label="言語を変更する" name="lang-selector" id="lang-selector-nav" class="glue-form__dropdown glue-mobile-nav__lang-dropdown" onchange="window.location.href=this.value" > <option value="/en/how-we-built-purrfect-code/" lang="en" > English </option> <option value="/es/how-we-built-purrfect-code/" lang="es" > Español (Latam) </option> <option value="/id/how-we-built-purrfect-code/" lang="id" > Bahasa Indonesia </option> <option value="/ja/how-we-built-purrfect-code/" lang="ja" selected > 日本語 </option> <option value="/ko/how-we-built-purrfect-code/" lang="ko" > 한국어 </option> <option value="/pt-br/how-we-built-purrfect-code/" lang="pt-br" > Português (Brasil) </option> <option value="/zh-hans/how-we-built-purrfect-code/" lang="zh-hans" > 简体中文 </option> </select> </div> <div class="backdrop"></div> <div class="blog-detail-container"> <section class="tags-container glue-page glue-spacer-5-top"> <div class="glue-eyebrow"><a href="/ja/search/?product_categories=Flutter">Flutter</a> / <a href="/ja/search/?product_categories=IDX">IDX</a></div> </section> <section class="heading-container glue-page glue-spacer-1-top"> <h1 class="glue-headline glue-headline--headline-1">Purrfect Code の作り方: デベロッパー向けパズルゲーム</h1> </section> <section class="summary-container glue-page glue-spacer-4-top"> <div class="date-time"> <div class="published-date glue-font-weight-medium">8月 01, 2024</div> </div> </section> <section class="glue-page glue-grid glue-spacer-1-top"> <section class="author-container glue-grid__col glue-grid__col--span-4-sm glue-grid__col--span-10-md"> <div class="author-obj"> <a class="glue-font-weight-medium" href="/ja/search/?author=Google+for+Developers">Google for Developers</a> </div> </section> <section class="social-container glue-grid__col glue-grid__col--span-4-sm glue-grid__col--span-2-md"> <button id="social-button" class="glue-button glue-button--low-emphasis glue-button--icon" aria-haspopup="true" aria-expanded="false"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#share"></use> </svg> <span>共有</span> </button> <ul id="social-menu" class="glue-elevation-level-1" role="menu" aria-labelledby="social-button"> <li> <a href="https://www.facebook.com/sharer/sharer.php?u={url}" title="Share on Facebook" target="_blank" rel="noopener"> <svg role="presentation" aria-hidden="true" class="glue-icon glue-icon--social glue-icon--32px"> <use href="/glue-icon/#post-facebook"></use> </svg> <span>Facebook</span> </a> </li> <li> <a href="https://twitter.com/intent/tweet?text={url}" title="Share on Twitter" target="_blank" rel="noopener"> <svg role="presentation" aria-hidden="true" class="glue-icon glue-icon--social glue-icon--32px"> <use href="/glue-icon/#twitter-x"></use> </svg> <span>Twitter</span> </a> </li> <li> <a href="https://www.linkedin.com/shareArticle?url={url}&mini=true" title="Share on LinkedIn" target="_blank" rel="noopener"> <svg role="presentation" aria-hidden="true" class="glue-icon glue-icon--social glue-icon--32px"> <use href="/glue-icon/#post-linkedin"></use> </svg> <span>LinkedIn</span> </a> </li> <li> <a href="mailto:name@example.com?subject=Check%20out%20this%20site&body=Check%20out%20{url}" title="Send via Email"> <svg role="presentation" aria-hidden="true" class="glue-icon glue-icon--social glue-icon--32px"> <use href="/glue-icon/#email"></use> </svg> <span>Mail</span> </a> </li> <li> <a href="#" title="Get shareable link" data-link="" data-copy-text="リンクをコピー" data-copied-text="コピーされました!"> <svg role="presentation" aria-hidden="true" class="glue-icon glue-icon--social glue-icon--32px"> <use href="/glue-icon/#link"></use> </svg> <span></span> </a> </li> </ul> </section> </section> <section class="blocks-container glue-page glue-spacer-3-top"> <div class="block"> <div class="inner-block-content yt-video"> <div class="glue-video"> <div class="glue-video__container glue-video__container--inline" data-glue-yt-video-vid="kPzov5wYXAI" > </div> <div class="glue-video__nojs"> <p><a href="https://www.youtube.com/watch?v=kPzov5wYXAI">Link to Youtube Video</a> (visible only when JS is disabled)</p> </div> </div> </div> <div class="inner-block-content rich-content"> <p data-block-key="k83go">「<a href="https://goo.gle/purrfect-code-hub">Purrfect Code</a>」は、新しい箱押し型プログラミング パズルゲームで、Flutter、Dart、Flame ゲームエンジンが使われています。デベロッパーは、コードを書いてパズルを解くことが求められます。</p><h2 data-block-key="4pmbp"><b><br/>ゲームの概要</b></h2><p data-block-key="ch3h">「Purrfect Code」のプレーヤーのミッションは、Google の新しい宇宙ステーション本部で清掃ロボットのプログラミングをアップデートすることです。そこには、猫が入った箱が誤って到着しています。ゲームの目的は、ロボットを操作して、すべての箱をテレポーター プレートに乗せ、猫が無事に家に帰れるようにすることです。プレーヤーは JavaScript を書いてロボットの動作を制御し、グリッドベースのパズルの中を動かしながら、効率的な解決策を探します。</p><p data-block-key="bt816">このゲームでは、知性と創造性を活用しながら、楽しくコーディングを学ぶことができます。各レベルはプログラミングのコンセプトに注目したものになっています。ゲームには 5 つのレベルがあり、徐々に複雑になっていきます。</p><p data-block-key="1sq75">ゲームループは次のようになっています。</p><p data-block-key="e8dsg"></p><ol><li data-block-key="e9f28">プレーヤーがロボットを動かす JavaScript コードを書きます(上下左右)。</li></ol><p data-block-key="1tjkf"></p><p data-block-key="huc9">2. コードを実行し、ロボットがレベルを解決する様子を確認します。</p><p data-block-key="8kg3e"></p><p data-block-key="51qmn">3. 猫が入ったすべての箱がテレポーター プレートに乗ると、レベルをクリアしたことになります。</p><p data-block-key="bltb2"></p><p data-block-key="dphrh">4. 移動したスペースの数やコードの簡潔さなど、ソリューションの効率に応じたスコアがプレーヤーに与えられます。</p> </div> <div class="inner-block-content video-block"> <video autoplay="" loop="" muted="" playsinline="" poster="https://storage.googleapis.com/gweb-developer-goog-blog-assets/original_videos/wagtailvideo-gizol0ut_thumb.jpg"> <source src='https://storage.googleapis.com/gweb-developer-goog-blog-assets/original_videos/purrfect_code.mp4' type='video/mp4'> <p>Sorry, your browser doesn't support playback for this video</p> </video> </div> <div class="inner-block-content rich-content"> <h2 data-block-key="k83go"><b>Flutter、Dart、Flame でゲームを作る</b></h2><p data-block-key="b0m5v">「<a href="https://goo.gle/purrfect-code-hub">Purrfect Code</a>」を作る上で選んだのは、Flutter と Dart でした。この 2 つは、マルチプラットフォームのアプリケーションやゲームを作成するための強力で柔軟なフレームワークを提供しているからです。Flutter のウィジェット システムとリアクティブ プログラミング モデルを使うことで、ブラウザのさまざまな画面サイズに対応したレスポンシブなユーザー インターフェースを作成できました。また、Dart の強力な型付けとオブジェクト指向プログラミング機能のおかげで、コードを簡単に構造化し、コードベースをきれいな状態に保つことができました。Flame ゲームエンジンは Flutter 上で動作し、ゲーム開発に必要な基本機能の基盤を提供してくれるすばらしい仕組みなので、ゲームプレイのロジックや、このゲームならではの機能に集中することができました。Purrfect Code には、IDE から着想を得た UI と、アニメーション スプライトとサウンドを含むゲームビューの<i>両方</i>があるので、ほかにはないゲームとアプリのハイブリッドと言えます。このような性質を考えれば、このプロジェクトで Flutter と Flame が選ばれたのは明らかなことです。</p><h3 data-block-key="36ihr"><br/><b>Chrome と JavaScript: ブラウザの組み込みサポートを活用する</b></h3><p data-block-key="1ms1k">ゲームのプログラミング コンセプトを決めた後、プレーヤーが使うプログラミング言語を選択する必要がありました。デベロッパーに親しまれ、人気のある言語が理想です。当初は、ゲーム内プログラミング言語に Python を使おうと考えました。しかし、いくつかの検討を経て、Chrome が提供する組み込みの JavaScript サポートを活用するために JavaScript を使うことにしました。JavaScript なら、追加の言語インタプリタを読み込まなくても、ブラウザのネイティブ機能を利用できます。この決定により、開発プロセスがシンプルになっただけでなく、最小限の依存関係ですばやくゲームを読み込めるようになり、プレーヤーにとってシームレスなエクスペリエンスを実現できました。</p><p data-block-key="bce1m">Flutter は今年の <a href="https://medium.com/flutter/whats-new-in-flutter-3-22-fbde6c164fe3">Google I/O で 3.22 がリリース</a>され、WebAssembly(WASM)サポートが安定版になりました。そのため、ゲームのパフォーマンスにとって不可欠な部分を最適化できました。特定のゲームロジックを WASM にコンパイルすることで、「Purrfect Code」がブラウザで効率的に実行され、パフォーマンスに妥協することなく、スムーズでレスポンシブなゲーム体験を提供できるようになりました。</p> </div> <div class="inner-block-content code-block"> <div class="highlight"><pre class="javascript"><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">dir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">moveEast</span><span class="p">,</span><span class="nx">moveNorth</span><span class="p">,</span><span class="nx">moveWest</span><span class="p">,</span><span class="nx">moveSouth</span><span class="p">];</span> <span class="k">for</span><span class="p">(</span><span class="nx">i</span><span class="o">=</span><span class="mf">0</span><span class="p">;</span><span class="nx">i</span><span class="o"><</span><span class="mf">4</span><span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">){</span> <span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="nx">j</span><span class="o">=</span><span class="mf">0</span><span class="p">;</span><span class="nx">j</span><span class="o"><</span><span class="mf">5</span><span class="p">;</span><span class="nx">j</span><span class="o">++</span><span class="p">)</span><span class="nx">dir</span><span class="p">[</span><span class="nx">i</span><span class="p">]();</span> <span class="p">}</span> </pre></div> </div> <div class="inner-block-content rich-content"> <h3 data-block-key="k83go"><b>Flame ゲームエンジン: モジュール型の効率的なゲーム開発</b></h3><p data-block-key="315nu">「Purrfect Code」を生み出すために、Flutter で動作するオープンソースのモジュール型ゲームエンジンである Flame ゲームエンジンを利用しました。これにより、ゲーム開発でよく使われる多くの機能が提供されます。Flame は、Flutter の堅牢なインフラストラクチャを活用し、プロジェクトの構築に必要なコードをシンプルにします。また、シンプルで効果的なゲームループ実装に加え、オーディオ再生、スプライト管理、アニメーション機能、衝突、Flame コンポーネント システム(FCS)など、幅広い必須機能が提供されます。このエンジンは、コンポーネントベースのアーキテクチャになっており、スプライト レンダリングやアニメーションがサポートされるので、視覚的に魅力的なグラフィック、スムーズなアニメーション、インタラクティブなゲームプレイ要素を、不要な作業を行うことなく作成できました。Flame を活用することで必要不可欠な機能をすぐに使えるようになるので、開発プロセスを効率化でき、プレーヤーにとって魅力的なゲーム体験作りに集中できました。</p><h3 data-block-key="aqgd7"><br/><b>Flame でゲーム機能を実装する</b></h3><h6 data-block-key="bs76o">Flame では、シンプルで効果的なゲームループ実装に加え、オーディオ再生、スプライト管理、アニメーション機能、衝突、Flame コンポーネントシステム(FCS)など、幅広い必須機能が提供されます。</h6><p data-block-key="9jjat">Flame のスプライト レンダリングとアニメーション システムにより、グラフィック コードを書くことなく、ゲームのキャラクターや環境を生み出すことができました。スプライト シートを作成し、アニメーション シーケンスを定義することで、キャラクターの動きや特殊効果にスムーズにアニメーションをつけることができます。「トップダウン」型ゲーム視点用のビジュアル ソーティング システムは、Flame の優先順位システムを使って記述しました。アート担当は、スプライトの奥行き感を高め、ゲームビューが「グリッド的」に見えないようにするため、たくさんの形状が重なり合うようなレベルを作りました。ロボットが後ろに回り込んだときには、正しくオクルージョンする必要があります。Flame の優先順位システムでは、さまざまな視覚要素に優先順位を割り当てることができるので、正しい順序で描画し、適切な順番で重ねることができます。このシステムには、十分な柔軟性があります。シャドウ システムを導入することで、個々のコンポーネントにオブジェクトの動きと連動した影のアニメーションを付けることができ、アートに奥行き感を出して、視覚的に理解しやすい生き生きとしたシーンを実現できました。</p><p data-block-key="54llu">その好例となるのが、コードベースの BoxShadow クラスです。これは、ゲーム内で動く箱のオブジェクトにダイナミックでインタラクティブな影を付ける方法を示しています。SpriteAnimationComponent を拡張し、GridElement と HasVisibility ミックスインを実装することで、箱の影とテレポート アニメーションのスプライト シートを読み込み、オープン、クローズ、アイドル、テレポート状態という複数のアニメーションを定義して、グリッドベースのレイアウトに統合することができました。onLoad メソッドでアニメーションを読み込み、グリッド位置に基づいてコンポーネントの初期位置と優先順位を設定します。update メソッドでは、箱がオクルージョン オブジェクトの前後に移動した場合に、コンポーネントの優先順位を動的に更新します。Flame の優先順位とアニメーション システムをこのように利用することで、影のエフェクトを作成することができます。これにより、ユーザーは常に仮想空間を視覚的に理解できるようになり、信頼性が高く、一体感のある視覚表現を実現できます。</p><p data-block-key="b0er"><i>box_shadow.dart の抜粋を次に示します。詳しくは、GitHub で</i><a href="https://github.com/devchallengedemo/purrfect_code/blob/main/lib/src/sokoban_view/components/box_shadow.dart"><i>完全なクラスをご覧ください</i></a><i>。</i></p> </div> <div class="inner-block-content code-block"> <div class="highlight"><pre class="dart"><span></span><span class="nd">@override</span> <span class="w"> </span><span class="n">Future</span><span class="o"><</span><span class="kt">void</span><span class="o">></span><span class="w"> </span><span class="n">onLoad</span><span class="p">()</span><span class="w"> </span><span class="kd">async</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="kd">await</span><span class="w"> </span><span class="n">_loadAnimations</span><span class="p">().</span><span class="n">then</span><span class="p">((</span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span><span class="n">animation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">_boxClosed</span><span class="p">});</span> <span class="w"> </span> <span class="w"> </span> <span class="w"> </span><span class="n">position</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">Vector2</span><span class="p">(</span> <span class="w"> </span><span class="p">((</span><span class="n">gridPosition</span><span class="p">.</span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">gridPixelDimensions</span><span class="p">.</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">gridPixelOffset</span><span class="p">.</span><span class="n">x</span><span class="p">),</span> <span class="w"> </span><span class="p">((</span><span class="n">gridPosition</span><span class="p">.</span><span class="n">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">gridPixelDimensions</span><span class="p">.</span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">gridPixelOffset</span><span class="p">.</span><span class="n">y</span><span class="p">)));</span> <span class="w"> </span><span class="n">priority</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">getLayeredGridValue</span><span class="p">();</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="nd">@override</span> <span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">update</span><span class="p">(</span><span class="kt">double</span><span class="w"> </span><span class="n">dt</span><span class="p">)</span><span class="w"> </span><span class="kd">async</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">super</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">dt</span><span class="p">);</span> <span class="w"> </span> <span class="w"> </span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">getLayeredGridValue</span><span class="p">()</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">priority</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">priority</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">getLayeredGridValue</span><span class="p">();</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="p">}</span> </pre></div> </div> <div class="inner-block-content rich-content"> <h3 data-block-key="k83go"><b>Google デベロッパー プログラムとバッジ</b></h3><p data-block-key="5rbi4">ゲームのスコープを小さく保ち、簡単なウェブページとしてデプロイできるようにしたかったので、ゲームのバックエンドを設定することは避けたいと考えました。しかし、人気ゲーム プラットフォームの実績システムと同じように、進捗に応じてデベロッパーが報酬をもらえるようにしたいとも考えました。そこで、別のバックエンド システムを作ってプレーヤーの進捗や実績を追跡する代わりに、Google デベロッパー プログラムと連携する仕組みを導入しました。具体的には、レベルをクリアしたプレーヤーがリンクをクリックすることで、プロフィール用のバッジを獲得できるようにし、達成感やデベロッパー コミュニティでの認知度を上げられるようにしました。</p> </div> <div class="inner-block-content"> <div class="image-wrapper"> <img class="regular-image" src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/image1_vQeaWU2.original.png" alt="Purrfect Code Google Developer Program profile badges" /> </div> </div> <div class="inner-block-content rich-content"> <h3 data-block-key="k83go"><b>Project IDX: 効率的な開発環境</b></h3><p data-block-key="fehun">「Purrfect Code」の開発中に、クラウドでのフルスタック、マルチプラットフォーム アプリ開発のための AI 支援ワークスペースである Google の Project IDX を活用しました。私たちはすでに VS Code での作業に慣れていたので、Project IDX はゲームのコーディング、デバッグ、テストに使い慣れた環境を提供し、すぐに使い始められるようにしてくれました。 Flutter と Dart がすでにセットアップされており、ブラウザで使用できる状態になっているため、ローカル環境の構成に煩わされることなく、すぐに開発に取り掛かることができます。 Project IDX が提供するインテリジェントなコード補完、リアルタイム エラー チェック、統合されたデバッグ ツールは、生産性を高く保つのに役立ちました。興味がある場合は、Project IDX を使用すると、Purrfect コードをすぐに試し、ブラウザから直接そのコードを探索できる優れた方法になります。 <a href="https://goo.gle/purrfect-code-idx">このリンクをクリックすると、IDX でプロジェクトを直接開き、自分でプロジェクトを実行できます</a>。これが Flutter アプリであるかどうかを尋ねるボックスに必ずチェックを入れてください。</p><h3 data-block-key="ebkeg"><br/><b>Firebase で高速かつ安全にホスティング</b></h3><p data-block-key="8vv87">世界に向けて Purrfect Code を安全かつ効率的に配信する方法として、Firebase Hosting を選びました。このプラットフォームのゼロ構成 SSL により、コンテンツは確実に HTTPS で提供されるため、強固なセキュリティを実現できます。さらに、最新のウェブ フレームワークや GitHub リポジトリの自動ビルドがサポートされているので、アップデートをすばやくデプロイできます。Firebase CLI、ローカル エミュレーション、プレビュー URL により、テストとコラボレーションのプロセスも効率化されます。こういった機能のほか、AI 連携用の Gemini サンプル テンプレートを使ってゲームを進化させる余地も生まれることから、Firebase Hosting はこのゲームを立ち上げる上で理想的な選択肢となりました。</p><h3 data-block-key="f6kv5"><br/><b>Firebase で WASM を構成する</b></h3><p data-block-key="fd5ju">Purrfect Code は Web Assembly を使っているので、デプロイ時にいくつかの追加の手順が必要となります。firebase.json 構成では、preeploy コマンドを追加して、ウェブビルドを WASM でビルドできるようにしました。“--no-strip-wasm” 引数で、コードで最後の最小化ステップが実行されないようにしています(エラーの判別やデバッグが難しくなるため)。WASM でマルチスレッドとメモリ共有を利用するため、cross-origin-opener-policy と cross-origin-embedder-policy も必要になります。</p> </div> <div class="inner-block-content code-block"> <div class="highlight"><pre class="go"><span></span><span class="s">"hosting"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="s">"predeploy"</span><span class="p">:</span><span class="w"> </span><span class="s">"flutter build web --wasm"</span><span class="p">,</span> <span class="w"> </span><span class="s">"public"</span><span class="p">:</span><span class="w"> </span><span class="s">"build/web"</span><span class="p">,</span> <span class="w"> </span><span class="s">"ignore"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span> <span class="w"> </span><span class="s">"firebase.json"</span><span class="p">,</span> <span class="w"> </span><span class="s">"**/.*"</span> <span class="w"> </span><span class="p">],</span> <span class="w"> </span><span class="s">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span> <span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="s">"source"</span><span class="p">:</span><span class="w"> </span><span class="s">"**/*"</span><span class="p">,</span> <span class="w"> </span><span class="s">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span> <span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="s">"key"</span><span class="p">:</span><span class="w"> </span><span class="s">"cross-origin-opener-policy"</span><span class="p">,</span> <span class="w"> </span><span class="s">"value"</span><span class="p">:</span><span class="w"> </span><span class="s">"same-origin"</span> <span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="s">"key"</span><span class="p">:</span><span class="w"> </span><span class="s">"cross-origin-embedder-policy"</span><span class="p">,</span> <span class="w"> </span><span class="s">"value"</span><span class="p">:</span><span class="w"> </span><span class="s">"require-corp"</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="p">]</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="p">]</span> <span class="w"> </span><span class="p">}</span> </pre></div> </div> <div class="inner-block-content rich-content"> <h2 data-block-key="k83go"><b>学習とリソース</b></h2><p data-block-key="62gpp">「Purrfect Code」の開発を通して、さまざまなリソースを利用し、既存プロジェクトからインスピレーションを受けました。このプロジェクトも、その 1 つとなれば幸いです。ここでは、貴重な学習リソースや参考プロジェクトを紹介します。</p><h3 data-block-key="ccgda"><br/><b>参考プロジェクト</b></h3><p data-block-key="f5pio">ベスト プラクティスや実装のアイデアとして、<a href="https://medium.com/@vgv_team/how-we-built-the-new-super-dash-demo-in-flutter-and-flame-in-just-six-weeks-9c7aa2a5ad31">Super Dash</a> と <a href="https://developers.googleblog.com/en/how-its-made-io-flip-adds-a-twist-to-a-classic-card-game-with-generative-ai/">I/O Flip</a> ゲームを参考にしました。どちらのプロジェクトも、Flutter ゲームの構造化、ゲームの状態処理、ゲームのメカニズムの実装について、貴重な知見を提供してくれました。Super Dash は、今回のゲームと同じく、シンプルでバックエンド サービスを必要としないので、特に参考になりました。I/O Flip はもう少し大きく、バックエンドだけでなく、生成 AI 機能にも対応しているため、こういった機能が必要なゲームを開発するデベロッパーには、興味深いものとなるでしょう。<a href="https://flutter.dev/games">Flutter でゲーム</a>を作ることに興味がある方にとっては、どちらも貴重なリソースです。</p><h2 data-block-key="66fvv"><b><br/>まとめ</b></h2><p data-block-key="694q4">「<a href="https://goo.gle/purrfect-code-hub">Purrfect Code</a>」が楽しいゲーム体験を提供するだけでなく、Flutter と Flame を使用したゲーム開発に興味のある開発者にとっての学習リソースとしても機能することを願っています。 <a href="https://flutter.dev/">Flutter</a>、<a href="https://flame-engine.org/">Flame</a>、<a href="https://www.google.com/chrome/">Chrome</a> の組み合わせが最適であることが判明しました。ゲームとアプリのハイブリッドに、UI 開発、グラフィック レンダリング、サウンド管理などのための強固な基盤を提供します。ゲームのソース コードを探索し、さらに拡張して実験することをお勧めします。新しい機能、レベル、ゲームプレイの仕組みを追加する可能性は数多くあります。 <a href="https://goo.gle/purrfect-code-idx">Project IDX</a> のコードベースにジャンプし、これが Flutter アプリであるかどうかを尋ねるボックスにチェックを入れて、創造力を発揮してください。 </p> </div> </div> </section> <section class="navigation-container glue-page glue-spacer-6-top"> <div class="posted-in-section"> <div class="posted-in-section__heading"> <span class="glue-caption"> 投稿先: </span> </div> <div class="posted-in-section__tags"> <ul> <li> <a href="/ja/search/?product_categories=Flutter" class="glue-caption">Flutter</a> </li> <li> <a href="/ja/search/?product_categories=IDX" class="glue-caption">IDX</a> </li> <li> <a href="/ja/search/?technology_categories=Web" class="glue-caption">Web</a> </li> <li> <a href="/ja/search/?content_type_categories=How-To+Guides" class="glue-caption">How-To Guides</a> </li> <li> <a href="/ja/search/?tag=Learning To Code" class="glue-caption">Learning To Code</a> </li> <li> <a href="/ja/search/?tag=Learn" class="glue-caption">Learn</a> </li> </ul> </div> </div> <div class="buttons-section"> <div class="buttons-section__left"> <a href="/ja/build-a-text-based-adventure-game-with-gemma-2/" class="glue-button--icon glue-elevation-level-1 " aria-label="前へ"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#chevron-left"></use> </svg> </a> <span class="caption ">前へ</span> </div> <div class="buttons-section__right"> <span class="caption ">次へ</span> <a href="/ja/smaller-safer-more-transparent-advancing-responsible-ai-with-gemma/" class="glue-button--icon glue-elevation-level-1 " aria-label="次へ"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#chevron-right"></use> </svg> </a> </div> </div> </section> <section class="related-posts-container glue-page glue-spacer-6-top glue-spacer-3-bottom"> <span class="glue-headline glue-headline--headline-3">関連投稿</span> <div class="related-posts-container__carousel glue-page glue-spacer-5-top"> <div class="glue-carousel glue-carousel--cards glue-carousel-related-posts" aria-label="関連投稿"> <!-- Previous --> <button class="glue-carousel__button glue-carousel__button--prev" aria-label="前のスライドへ"> <svg role="presentation" aria-hidden="true" class="glue-icon glue-icon--32px"> <use href="/glue-icon/#chevron-left"></use> </svg> </button> <!-- Next --> <button class="glue-carousel__button glue-carousel__button--next" aria-label="次のスライドへ"> <svg role="presentation" aria-hidden="true" class="glue-icon glue-icon--32px"> <use href="/glue-icon/#chevron-right"></use> </svg> </button> <!-- List --> <div class="glue-carousel__viewport"> <div class="glue-carousel__list"> <a class="glue-card glue-carousel__item" href="/ja/announcing-the-winners-of-the-gemini-api-developer-competition/"> <div aria-label="Announcing the Winners of the Gemini API Developer Competition!" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="Announcing the Winners of the Gemini API Developer Competition!" src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/Gemini_Competition_G4D_-_meta.2e16d0ba.fill-800x400.png"> </picture> <div class="glue-card__content"> <div class="glue-card__tags glue-spacer-2-top"> <span class="glue-label">Mobile</span> <span class="glue-label">Web</span> <span class="glue-label">Case Studies</span> <span class="glue-label">Community</span> </div> <p class="glue-headline glue-headline--headline-5">Announcing the Winners of the Gemini API Developer Competition!</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">2024年11月21日</span> <svg aria-hidden="true" class="glue-icon glue-icon--24px" role="presentation"> <use href="/glue-icon/#arrow-forward"></use> </svg> </div> </div> </div> </a> <a class="glue-card glue-carousel__item" href="/ja/5-years-of-innovation-student-developers-solving-real-world-problems-using-google-tech/"> <div aria-label="イノベーションの 5 年: 学生デベロッパーが Google テクノロジーで現実世界の問題を解決" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="イノベーションの 5 年: 学生デベロッパーが Google テクノロジーで現実世界の問題を解決" src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/GDSC-Social_1.2e16d0ba.fill-800x400.png"> </picture> <div class="glue-card__content"> <div class="glue-card__tags glue-spacer-2-top"> <span class="glue-label">Android</span> <span class="glue-label">Cloud</span> <span class="glue-label">Announcements</span> <span class="glue-label">Community</span> </div> <p class="glue-headline glue-headline--headline-5">イノベーションの 5 年: 学生デベロッパーが Google テクノロジーで現実世界の問題を解決</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">2024年6月20日</span> <svg aria-hidden="true" class="glue-icon glue-icon--24px" role="presentation"> <use href="/glue-icon/#arrow-forward"></use> </svg> </div> </div> </div> </a> <a class="glue-card glue-carousel__item" href="/ja/inference-with-gemma-using-dataflow-and-vllm/"> <div aria-label="Gemma で Dataflow と vLLM を使って推論する" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="Gemma で Dataflow と vLLM を使って推論する" src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/Gemma-Dataflow-ML-vLLM.2e16d0ba.fill-800x400.png"> </picture> <div class="glue-card__content"> <div class="glue-card__tags glue-spacer-2-top"> <span class="glue-label">Gemma</span> <span class="glue-label">AI</span> <span class="glue-label">Cloud</span> <span class="glue-label">How-To Guides</span> <span class="glue-label">Problem-Solving</span> </div> <p class="glue-headline glue-headline--headline-5">Gemma で Dataflow と vLLM を使って推論する</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">2024年11月13日</span> <svg aria-hidden="true" class="glue-icon glue-icon--24px" role="presentation"> <use href="/glue-icon/#arrow-forward"></use> </svg> </div> </div> </div> </a> <a class="glue-card glue-carousel__item" href="/ja/firebase-demo-day-24/"> <div aria-label="Learn to build and run AI powered apps at Firebase Demo Day ‘24" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="Learn to build and run AI powered apps at Firebase Demo Day ‘24" src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/Newletter_DayOf.2e16d0ba.fill-800x400.jpg"> </picture> <div class="glue-card__content"> <div class="glue-card__tags glue-spacer-2-top"> <span class="glue-label">Firebase</span> <span class="glue-label">Mobile</span> <span class="glue-label">Web</span> <span class="glue-label">Tutorials</span> <span class="glue-label">How-To Guides</span> </div> <p class="glue-headline glue-headline--headline-5">Learn to build and run AI powered apps at Firebase Demo Day ‘24</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">2024年11月19日</span> <svg aria-hidden="true" class="glue-icon glue-icon--24px" role="presentation"> <use href="/glue-icon/#arrow-forward"></use> </svg> </div> </div> </div> </a> <a class="glue-card glue-carousel__item" href="/ja/how-we-built-the-io-crossword/"> <div aria-label="I/O クロスワードの作り方" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="I/O クロスワードの作り方" src="https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/image4_TcC6Diy.2e16d0ba.fill-800x400.png"> </picture> <div class="glue-card__content"> <div class="glue-card__tags glue-spacer-2-top"> <span class="glue-label">Firebase</span> <span class="glue-label">Flutter</span> <span class="glue-label">AI</span> <span class="glue-label">How-To Guides</span> <span class="glue-label">Industry Trends</span> </div> <p class="glue-headline glue-headline--headline-5">I/O クロスワードの作り方</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">2024年6月26日</span> <svg aria-hidden="true" class="glue-icon glue-icon--24px" role="presentation"> <use href="/glue-icon/#arrow-forward"></use> </svg> </div> </div> </div> </a> </div> </div> <!-- Navigation dots --> <div class="glue-carousel__navigation" aria-label="Choose a page" data-glue-carousel-navigation-label="Selected tab $glue_carousel_page_number$ of $glue_carousel_page_total$"> </div> </div> </div> </section> </div> <div class="footer-linkboxes__wrapper"> <nav class="footer-linkboxes" aria-label="フッターリンク"> <ul class="footer-linkboxes__list"> <li class="footer-linkbox"> <span class="footer-linkbox-heading"> 接続する </span> <ul class="footer-linkbox-list"> <li class="footer-linkbox-list__item"> <a href="//googledevelopers.blogspot.com" class="footer-linkbox-list__link"> Blog </a> </li> <li class="footer-linkbox-list__item"> <a href="https://goo.gle/googlefordevs" class="footer-linkbox-list__link"> Instagram </a> </li> <li class="footer-linkbox-list__item"> <a href="https://goo.gle/gdevs-li" class="footer-linkbox-list__link"> LinkedIn </a> </li> <li class="footer-linkbox-list__item"> <a href="https://goo.gle/gdevs-tw" class="footer-linkbox-list__link"> Twitter </a> </li> <li class="footer-linkbox-list__item"> <a href="https://goo.gle/developers" class="footer-linkbox-list__link"> YouTube </a> </li> </ul> </li> <li class="footer-linkbox"> <span class="footer-linkbox-heading"> プログラム </span> <ul class="footer-linkbox-list"> <li class="footer-linkbox-list__item"> <a href="//www.womentechmakers.com" class="footer-linkbox-list__link"> Women Techmakers </a> </li> <li class="footer-linkbox-list__item"> <a href="//developers.google.com/community/gdg" class="footer-linkbox-list__link"> Google Developer Groups </a> </li> <li class="footer-linkbox-list__item"> <a href="//developers.google.com/community/experts" class="footer-linkbox-list__link"> Google Developer Experts </a> </li> <li class="footer-linkbox-list__item"> <a href="//developers.google.com/community/accelerators" class="footer-linkbox-list__link"> Accelerators </a> </li> <li class="footer-linkbox-list__item"> <a href="//developers.google.com/community/gdsc" class="footer-linkbox-list__link"> Google Developer Student Clubs </a> </li> </ul> </li> <li class="footer-linkbox"> <span class="footer-linkbox-heading"> デベロッパー コンソール </span> <ul class="footer-linkbox-list"> <li class="footer-linkbox-list__item"> <a href="//console.developers.google.com" class="footer-linkbox-list__link"> Google API Console </a> </li> <li class="footer-linkbox-list__item"> <a href="//console.cloud.google.com" class="footer-linkbox-list__link"> Google Cloud Platform Console </a> </li> <li class="footer-linkbox-list__item"> <a href="//play.google.com/apps/publish" class="footer-linkbox-list__link"> Google Play Console </a> </li> <li class="footer-linkbox-list__item"> <a href="//console.firebase.google.com" class="footer-linkbox-list__link"> Firebase Console </a> </li> <li class="footer-linkbox-list__item"> <a href="//console.actions.google.com" class="footer-linkbox-list__link"> Actions on Google Console </a> </li> <li class="footer-linkbox-list__item"> <a href="//cast.google.com/publish" class="footer-linkbox-list__link"> Cast SDK Developer Console </a> </li> <li class="footer-linkbox-list__item"> <a href="//chrome.google.com/webstore/developer/dashboard" class="footer-linkbox-list__link"> Chrome Web Store Dashboard </a> </li> </ul> </li> </ul> </nav> </div> <div class="footer-utility__wrapper"> <div> <nav class="footer-sites" aria-label="その他の Google Developers ウェブサイト"> <a href="https://developers.google.com/" class="site-logo-link" data-label="Site logo"> <img src="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/images/g-dev.svg" class="site-logo" alt="Google for Developers"> </a> <ul class="footer-sites-list"> <li class="footer-sites-item"> <a href="//developer.android.com" class="footer-sites-link"> Android </a> </li> <li class="footer-sites-item"> <a href="//developer.chrome.com/home" class="footer-sites-link"> Chrome </a> </li> <li class="footer-sites-item"> <a href="//firebase.google.com" class="footer-sites-link"> Firebase </a> </li> <li class="footer-sites-item"> <a href="//cloud.google.com" class="footer-sites-link"> Google Cloud Platform </a> </li> <li class="footer-sites-item"> <a href="//developers.google.com/products" class="footer-sites-link"> All products </a> </li> <li class="footer-sites-item"> <button aria-hidden="true" class="glue-cookie-notification-bar-control footer-sites-link"> Manage cookies </button> </li> </ul> </nav> <nav class="footer-utility-links"> <ul class="footer-utility-list"> <li class="footer-utility-item"> <a href="//developers.google.com/terms/site-terms" class="footer-utility-link"> 利用規約 </a> </li> <li class="footer-utility-item"> <a href="//policies.google.com/privacy" class="footer-utility-link"> プライバシー </a> </li> </ul> <div class="language-selector footer" aria-label="言語設定を選択"> <button type="button" aria-controls="lang-selector-footer" aria-haspopup="true"> <svg role="presentation" aria-hidden="true" class="glue-icon lang-icon"> <use href="/glue-icon/#language"></use> </svg> <span class="lang-label">日本語</span> <svg role="presentation" aria-hidden="true" class="glue-icon lang-icon"> <use href="/glue-icon/#arrow-drop-down"></use> </svg> </button> <div id="lang-selector-footer" class="lang-menu hidden" role="menu"> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" href="/en/how-we-built-purrfect-code/">English</a> </li> <li role="presentation"> <a role="menuitem" lang="es" href="/es/how-we-built-purrfect-code/">Español (Latam)</a> </li> <li role="presentation"> <a role="menuitem" lang="id" href="/id/how-we-built-purrfect-code/">Bahasa Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" aria-current="true" href="/ja/how-we-built-purrfect-code/">日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" href="/ko/how-we-built-purrfect-code/">한국어</a> </li> <li role="presentation"> <a role="menuitem" lang="pt-br" href="/pt-br/how-we-built-purrfect-code/">Português (Brasil)</a> </li> <li role="presentation"> <a role="menuitem" lang="zh-hans" href="/zh-hans/how-we-built-purrfect-code/">简体中文</a> </li> </ul> </div> </div> </nav> </div> </div> <script src="https://www.youtube.com/player_api"></script> <script src="//www.gstatic.com/glue/v27_1/glue.min.js"></script> <script type="text/javascript" src="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/js/dgc_blog.js"></script> <script src="https://www.gstatic.com/glue/cookienotificationbar/cookienotificationbar.min.js" data-glue-cookie-notification-bar-category="2A" data-glue-cookie-notification-bar-site-id="developers.googleblog.com"> </script> <script src="https://storage.googleapis.com/gweb-developer-goog-blog-cms-assets/f677f1b8-8552-4a23-83cc-57c36dbaf782/js/blog_detail.js"></script> </body> </html>