CINXE.COM
Como criamos o Purrfect Code: um quebra-cabeças para desenvolvedores - Google Developers Blog
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title> Como criamos o Purrfect Code: um quebra-cabeças para desenvolvedores - Google Developers Blog </title> <meta property="og:title" content="Como criamos o Purrfect Code: um quebra-cabeças para desenvolvedores- 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="Como criamos o Purrfect Code: um quebra-cabeças para desenvolvedores" /> <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": "Como criamos o Purrfect Code: um quebra-cabeças para desenvolvedores", "item": "http://developers.googleblog.com/pt-br/how-we-built-purrfect-code/" }] } </script> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Como criamos o Purrfect Code: um quebra-cabeças para desenvolvedores", "description": "O Purrfect Code é um quebra-cabeças com caixas que devem ser empurradas, no estilo do Sokoban, que se baseia em tecnologias do Google (Flutter, IDX, FLAME, Firebase) e foi projetado para ser jogado em navegadores da Web. Abra o jogo no Project IDX, ganhe selos ao final de cada nível e exponha-os em seu Perfil do desenvolvedor.", "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": "/pt-br/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="Abrir menu"> <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="Guias superiores"> <div class="tab" dropdown> <a href="//developers.google.com/products" class="top-nav-title"> Produtos </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="true" aria-label="Menu suspenso para Produtos" 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="Submenu"> <div class="tabs-dropdown-content"> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="Menu Desenvolvimento">Desenvolvimento</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="Menu Expandir">expandir</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="Menu Lucre">Lucre</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"> Soluções </a> </div> <div class="tab"> <a href="//developers.google.com/events" class="top-nav-title"> Eventos </a> </div> <div class="tab"> <a href="//developers.google.com/learn" class="top-nav-title"> Aprenda </a> </div> <div class="tab" dropdown> <a href="//developers.google.com/community" class="top-nav-title"> Comunidade </a> <a href="#" role="button" aria-haspopup="true" aria-expanded="true" aria-label="Menu suspenso para Comunidade" 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="Submenu"> <div class="tabs-dropdown-content"> <div class="tabs-dropdown-column"> <ul class="tabs-dropdown-section"> <li class="nav-title" aria-label="Menu Grupos">Grupos</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="Menu Programas">Programas</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="Menu Stories">Histórias</li> <li class="nav-item"> <a href="//developers.google.com/community/stories"> <div class="nav-item-title"> Todos os stories </div> </a> </li> </ul> </div> </div> </div> </div> <div class="tab"> <a href="//developers.google.com/profile/u/me" class="top-nav-title"> Programa para desenvolvedores </a> </div> <div class="tab"> <a href="//developers.googleblog.com/" class="top-nav-title"> Blogue </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="/pt-br/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="Pesquisar todos os artigos..." aria-label="Pesquisa" class="search-input-field" /> </div> <button class="glue-button glue-button--high-emphasis"> Pesquisa </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="Selecione seu idioma preferencial"> <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">Português (Brasil)</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" 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" aria-current="true" 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="Menu lateral"> <div class="mobile-header"> <button class="nav-close-btn nav-btn" aria-label="Fechar navegação"> <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="Voltar ao menu"> <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=""> Produtos </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"> Mais </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=""> Soluções </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=""> Eventos </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=""> Aprenda </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=""> Comunidade </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"> Mais </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=""> Programa para desenvolvedores </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="Menu lateral"> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> Desenvolvimento </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"> expandir </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"> Lucre </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="Menu lateral"> <li class="nav-item nav-heading"> <span class="nav-title"> <span class="nav-text"> Grupos </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"> Programas </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"> Histórias </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"> Todos os stories </span> </a> </li> </ul> </div> </div> </nav> <select aria-label="Alterar idioma" 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" > 日本語 </option> <option value="/ko/how-we-built-purrfect-code/" lang="ko" > 한국어 </option> <option value="/pt-br/how-we-built-purrfect-code/" lang="pt-br" selected > 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="/pt-br/search/?product_categories=Flutter">Flutter</a> / <a href="/pt-br/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">Como criamos o Purrfect Code: um quebra-cabeças para desenvolvedores</h1> </section> <section class="summary-container glue-page glue-spacer-4-top"> <div class="date-time"> <div class="published-date glue-font-weight-medium">AGO 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="/pt-br/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>Compartilhar</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="Copiar link" data-copied-text="Copiado!"> <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">O "<a href="https://goo.gle/purrfect-code-hub">Purrfect Code</a>" é um novo quebra-cabeças de programação com caixas que devem empurradas. Ele é habilitado pelo Flutter, pelo Dart e pelo mecanismo de jogo Flame e foi projetado para desafiar os desenvolvedores a resolverem o quebra-cabeças por meio da escrita de código.</p><h2 data-block-key="4pmbp"><b><br/>Visão geral do jogo</b></h2><p data-block-key="ch3h">No "Purrfect Code", os jogadores têm a tarefa de atualizar a programação de um robô zelador na nova sede da estação espacial do Google, onde um carregamento de gatos chegou por engano. A meta do jogo é ajudar o robô a juntar, com segurança, as caixas que contêm os gatos e empurrá-las até as placas de teletransporte para que eles possam voltar para casa. Os jogadores escrevem em JavaScript para controlar os movimentos do robô enquanto tentam encontrar soluções eficazes para navegar pelos quebra-cabeças baseados em grade.</p><p data-block-key="bt816">O jogo é uma forma divertida de explorar a codificação usando inteligência e criatividade. Cada nível tem como foco um conceito de programação, e a complexidade aumenta gradualmente ao longo dos cinco níveis do jogo.</p><p data-block-key="1sq75">Este é o loop de jogo:</p><p data-block-key="e8dsg"></p><ol><li data-block-key="e9f28">Os jogadores escrevem código JavaScript para movimentar o robô (para cima, para baixo, para a esquerda ou para a direita).</li></ol><p data-block-key="1tjkf"></p><p data-block-key="huc9">2. Depois, eles executam o código e observam o robô tentando resolver o nível.</p><p data-block-key="8kg3e"></p><p data-block-key="51qmn">3. O nível é concluído quando todas as caixas que contêm os gatos são empurradas até as placas de teletransporte.</p><p data-block-key="bltb2"></p><p data-block-key="dphrh">4. Os jogadores recebem pontuações com base na eficiência de suas soluções, incluindo o número de espaços movidos e a brevidade do código.</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>Criação do jogo com o Flutter, o Dart e o Flame</b></h2><p data-block-key="b0m5v">Optamos por criar o "<a href="https://goo.gle/purrfect-code-hub">Purrfect Code</a>" usando o Flutter e o Dart, pois eles fornecem um framework avançado e flexível para a criação de aplicativos e jogos multiplataforma. Com o sistema de widgets e o modelo de programação reativa do Flutter, conseguimos criar uma interface do usuário responsiva para uma variedade de tamanhos de tela no navegador. Os recursos de programação fortemente tipada e orientada por objetos do Dart facilitaram a estruturação do código e a boa organização da base de código. O mecanismo de jogo Flame, baseado no Flutter, ofereceu uma boa base de recursos essenciais necessários para o desenvolvimento do jogo, permitindo que nos concentrássemos em nossa lógica de jogabilidade e nos aspectos exclusivos do jogo. O Flutter e o Flame foram uma escolha óbvia para esse projeto porque o Purrfect Code é um híbrido de jogo/app exclusivo, com uma IU inspirada em ambiente de desenvolvimento integrado <i>e</i> uma visualização de jogo com som e sprites animados.</p><h3 data-block-key="36ihr"><br/><b>Chrome e JavaScript: uso do suporte integrado do navegador</b></h3><p data-block-key="1ms1k">Depois de definir o conceito de programação do jogo, precisávamos escolher a linguagem de programação que os jogadores usariam. Queríamos algo familiar e popular entre os desenvolvedores. Inicialmente, consideramos o uso do Python como linguagem de programação no jogo. No entanto, após algumas considerações, decidimos usar o JavaScript para aproveitar o suporte integrado ao JavaScript que o Chrome fornece. Ao utilizar o JavaScript, conseguimos acessar os recursos nativos do navegador sem a necessidade de carregar um interpretador de linguagem adicional. Essa decisão simplificou nosso processo de desenvolvimento e garantiu uma experiência perfeita para os jogadores, pois o jogo poderia ser carregado rapidamente com o mínimo de dependências.</p><p data-block-key="bce1m">A <a href="https://medium.com/flutter/whats-new-in-flutter-3-22-fbde6c164fe3">versão 3.22 do Flutter lançada no Google I/O</a> deste ano introduziu o suporte estável ao WebAssembly (WASM), o que nos permitiu otimizar as partes críticas para o desempenho do jogo. Ao compilar certas lógicas de jogo para o WASM, garantimos que o "Purrfect Code" seja executado com eficiência no navegador, proporcionando uma experiência de jogo perfeita e responsiva sem comprometer o desempenho.</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>Mecanismo de jogo Flame: desenvolvimento de jogos modular e eficiente</b></h3><p data-block-key="315nu">Para dar vida ao "Purrfect Code", utilizamos o Flame, um mecanismo de jogo modular de código aberto baseado no Flutter que fornece muitos dos recursos comumente necessários para o desenvolvimento de jogos. O Flame usa a infraestrutura robusta do Flutter e simplifica o código necessário para criar nosso projeto. Ele oferece uma implementação de loop de jogo simples, porém eficaz, e uma ampla variedade de funcionalidades essenciais, como reprodução de áudio, gerenciamento de sprites, recursos de animação, colisão e o Flame Component System (FCS). Com a arquitetura do mecanismo baseada em componentes, a renderização de sprites e o suporte a animações, conseguimos criar gráficos visualmente atrativos, animações fluidas e elementos de jogabilidade interativos, sem precisar reinventar a roda. O uso do Flame tornou o processo de desenvolvimento mais eficiente com recursos essenciais prontamente disponíveis, permitindo que nos concentrássemos na criação de uma experiência de jogo envolvente para os jogadores.</p><h3 data-block-key="aqgd7"><br/><b>Implementação dos recursos do jogo com o Flame</b></h3><h6 data-block-key="bs76o">O Flame oferece uma implementação de loop de jogo simples, porém eficaz, e uma ampla variedade de funcionalidades essenciais, como reprodução de áudio, gerenciamento de sprites, recursos de animação, colisão e o Flame Component System (FCS).</h6><p data-block-key="9jjat">O sistema de renderização e animação de sprites do Flame nos permitiu dar vida às personagens e aos ambientes do jogo sem a necessidade de escrever código gráfico. Conseguimos criar folhas de sprites, definir sequências de animação e animar facilmente movimentos e efeitos especiais das personagens. Usamos o sistema de prioridades do Flame para escrever um sistema de classificação visual para nossa perspectiva de jogo "de cima para baixo". Nosso artista criou níveis com muitos recursos sobrepostos para melhorar a sensação de profundidade com os sprites e conferir à visualização do jogo uma aparência menos "gradeada". Precisávamos garantir que, quando o robô se movimentasse atrás desses elementos, ele fosse ocultado corretamente. O sistema de prioridades do Flame nos permitiu atribuir prioridades a diferentes elementos visuais, garantindo que eles fossem desenhados na ordem correta e sobrepostos adequadamente. Esse sistema foi flexível o suficiente para incluirmos um sistema de sombras no qual componentes individuais pudessem apresentar sombras animadas que espelhassem ações de objetos e dessem à arte uma sensação de profundidade para tornar as cenas mais vibrantes e mais fáceis de compreender visualmente.</p><p data-block-key="54llu">A classe BoxShadow em nossa base de código é um bom exemplo disso e mostra como criamos sombras dinâmicas e interativas para os objetos de caixa em movimento do jogo. Ao estender o SpriteAnimationComponent e implementar os mixins GridElement e HasVisibility, conseguimos carregar folhas de sprites das animações de sombra e de teletransporte de caixas, definir várias animações para os estados "aberta", "fechada", "inativa" e "em teletransporte" e integrá-las ao layout baseado em grade. O método onLoad carrega as animações e define a posição inicial e a prioridade do componente com base em sua posição na grade, enquanto o método update garante que a prioridade do componente seja atualizada dinamicamente se a caixa se movimentar na frente ou atrás de um objeto oclusivo. Usar os sistemas de prioridade e animação do Flame dessa maneira nos permitiu criar efeitos de sombra que sempre ajudam os usuários a entender visualmente os espaços virtuais, tornando-os mais verossímeis e levando a uma apresentação visual mais integrada.</p><p data-block-key="b0er"><i>Trecho de box_shadow.dart;</i> <a href="https://github.com/devchallengedemo/purrfect_code/blob/main/lib/src/sokoban_view/components/box_shadow.dart"><i>veja a classe completa</i></a><i> no GitHub para saber mais.</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>Selos e programa Google Developers</b></h3><p data-block-key="5rbi4">Como queríamos manter o escopo do jogo pequeno e conseguir implantá-lo como uma página da Web simples, optamos por evitar a configuração de um back-end para o jogo. No entanto, precisávamos encontrar uma forma de premiar os desenvolvedores pelo progresso obtido, algo semelhante aos sistemas de conquistas em plataformas de jogos populares. Em vez de criar um sistema de back-end separado para acompanhar o progresso e as conquistas dos jogadores, fizemos uma integração com o programa Google Developers, permitindo que os jogadores cliquem em um link e coletem um selo em seu perfil depois de concluírem um nível, o que dá uma sensação de realização e reconhecimento dentro da comunidade de desenvolvedores.</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: um ambiente de desenvolvimento simplificado</b></h3><p data-block-key="fehun">Durante o desenvolvimento do "Purrfect Code", aproveitamos o Project IDX do Google, um espaço de trabalho assistido por IA para desenvolvimento de aplicativos full-stack e multiplataforma na nuvem. Como já estávamos confortáveis trabalhando no VS Code, o Project IDX forneceu um ambiente familiar para codificação, depuração e teste de nosso jogo e nos permitiu começar a trabalhar rapidamente. Com o Flutter e o Dart já configurados e prontos para uso no navegador, poderíamos mergulhar direto no desenvolvimento sem o incômodo de configuração do ambiente local. A conclusão inteligente de código, a verificação de erros em tempo real e as ferramentas de depuração integradas oferecidas pelo Project IDX nos ajudaram a manter nossa produtividade alta. Se você estiver curioso, o Project IDX é uma ótima maneira de experimentar rapidamente o Purrfect Code e explorar seu código diretamente do seu navegador. <a href="https://goo.gle/purrfect-code-idx">Clique neste link para abrir o projeto diretamente no IDX e executá-lo você mesmo</a>. Certifique-se de marcar a caixa que pergunta se este é um aplicativo Flutter.</p><h3 data-block-key="ebkeg"><br/><b>Firebase para hospedagem rápida e segura</b></h3><p data-block-key="8vv87">Escolhemos o Firebase Hosting para garantir a entrega global segura e eficiente do Purrfect Code. O SSL de configuração zero da plataforma garante que o conteúdo seja disponibilizado por HTTPS, o que aumenta a segurança. Além disso, seu suporte a frameworks da Web modernos e versões automatizadas de nosso repositório GitHub possibilitou a rápida implantação de atualizações. A CLI do Firebase, a emulação local e os URLs de pré-lançamento simplificaram nossos processos de teste e colaboração. Esses recursos, em conjunto com o potencial de futuras evoluções do jogo usando os modelos de exemplo do Gemini para integração de IA, tornaram o Firebase Hosting a escolha ideal para o lançamento de nosso jogo.</p><h3 data-block-key="f6kv5"><br/><b>Configuração do Firebase com WASM</b></h3><p data-block-key="fd5ju">O Purrfect Code usa o WebAssembly, que requer algumas etapas adicionais durante a implantação. Em nossa configuração firebase.json, adicionamos um comando de pré-implantação que permite que a versão da Web seja criada com o WASM. O argumento "--no-strip-wasm" impede que o código seja executado por meio de uma última etapa de minimização, o que dificulta a leitura e depuração dos erros. O WASM também requer uma política de abertura de origem cruzada e uma política de incorporação de origem cruzada para vários threads e compartilhamento de memória.</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>Aprendizado e recursos</b></h2><p data-block-key="62gpp">Ao longo do desenvolvimento do "Purrfect Code", contamos com vários recursos e nos inspiramos em projetos existentes, um conjunto de obras para o qual esperamos que esse projeto possa contribuir. Estes são alguns dos principais recursos de aprendizado e as referências que consideramos importantes:</p><h3 data-block-key="ccgda"><br/><b>Projetos de referência</b></h3><p data-block-key="f5pio">Usamos os jogos <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> e <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> como referências de práticas recomendadas e ideias de implementação. Ambos os projetos forneceram insights valiosos sobre a estruturação de um jogo Flutter, o tratamento de estados do jogo e a implementação de mecânicas de jogo. O Super Dash foi muito relevante porque era simples e não exigia serviços de back-end, assim como o nosso jogo. O I/O Flip era maior e tinha suporte a um back-end, bem como a recursos de IA generativa, portanto pode ser de interesse para os desenvolvedores de jogos que exigem esses recursos. Ambos serão recursos valiosos se você tiver interesse em criar <a href="https://flutter.dev/games">jogos no Flutter</a>.</p><h2 data-block-key="66fvv"><b><br/>Conclusão</b></h2><p data-block-key="694q4">Esperamos que "<a href="https://goo.gle/purrfect-code-hub">Purrfect Code</a>" não apenas forneça uma experiência de jogo agradável, mas também sirva como um recurso de aprendizagem para desenvolvedores interessados no desenvolvimento de jogos com Flutter e Flame. A combinação de <a href="https://flutter.dev/">Flutter</a>, <a href="https://flame-engine.org/">Flame</a> e <a href="https://www.google.com/chrome/">Chrome</a> provou ser uma ótima opção para nosso híbrido jogo/aplicativo, fornecendo-nos uma base sólida para desenvolvimento de UI, renderização gráfica, gerenciamento de som e muito mais. Encorajamos você a explorar o código-fonte do jogo e experimentar estendê-lo ainda mais. Existem inúmeras possibilidades para adicionar novos recursos, níveis e mecânicas de jogo. Entre na base de código do <a href="https://goo.gle/purrfect-code-idx">Projeto IDX</a>, marque a caixa que pergunta se este é um aplicativo Flutter e deixe sua criatividade correr solta! </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"> postado em: </span> </div> <div class="posted-in-section__tags"> <ul> <li> <a href="/pt-br/search/?product_categories=Flutter" class="glue-caption">Flutter</a> </li> <li> <a href="/pt-br/search/?product_categories=IDX" class="glue-caption">IDX</a> </li> <li> <a href="/pt-br/search/?technology_categories=Web" class="glue-caption">Web</a> </li> <li> <a href="/pt-br/search/?content_type_categories=How-To+Guides" class="glue-caption">How-To Guides</a> </li> <li> <a href="/pt-br/search/?tag=Learning To Code" class="glue-caption">Learning To Code</a> </li> <li> <a href="/pt-br/search/?tag=Learn" class="glue-caption">Learn</a> </li> </ul> </div> </div> <div class="buttons-section"> <div class="buttons-section__left"> <a href="/pt-br/build-a-text-based-adventure-game-with-gemma-2/" class="glue-button--icon glue-elevation-level-1 " aria-label="Anterior"> <svg role="presentation" aria-hidden="true" class="glue-icon"> <use href="/glue-icon/#chevron-left"></use> </svg> </a> <span class="caption ">Anterior</span> </div> <div class="buttons-section__right"> <span class="caption ">Avançar</span> <a href="/pt-br/smaller-safer-more-transparent-advancing-responsible-ai-with-gemma/" class="glue-button--icon glue-elevation-level-1 " aria-label="Avançar"> <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">Postagens relacionadas</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="Postagens relacionadas"> <!-- Previous --> <button class="glue-carousel__button glue-carousel__button--prev" aria-label="Ir para o slide anterior"> <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="Ir para o próximo slide"> <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="/pt-br/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">21 de Novembro de 2024</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="/pt-br/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">19 de Novembro de 2024</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="/pt-br/how-we-built-the-io-crossword/"> <div aria-label="Como tudo começou: o I/O Crossword" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="Como tudo começou: o I/O Crossword" 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">Como tudo começou: o I/O Crossword</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">26 de Junho de 2024</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="/pt-br/inference-with-gemma-using-dataflow-and-vllm/"> <div aria-label="Inferência com o Gemma usando Dataflow e vLLM" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="Inferência com o Gemma usando Dataflow e 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">Inferência com o Gemma usando Dataflow e vLLM</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">13 de Novembro de 2024</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="/pt-br/5-years-of-innovation-student-developers-solving-real-world-problems-using-google-tech/"> <div aria-label="Cinco anos de inovação: estudantes de desenvolvimento abordam problemas do mundo real usando a tecnologia do Google" class="glue-card__inner"> <picture class="glue-card__asset"> <img alt="Cinco anos de inovação: estudantes de desenvolvimento abordam problemas do mundo real usando a tecnologia do 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">Cinco anos de inovação: estudantes de desenvolvimento abordam problemas do mundo real usando a tecnologia do Google</p> <div class="glue-card__cta-custom glue-spacer-3-top"> <span class="glue-cta">20 de Junho de 2024</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="Links do rodapé"> <ul class="footer-linkboxes__list"> <li class="footer-linkbox"> <span class="footer-linkbox-heading"> Conectar </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"> Programas </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"> Consoles do desenvolvedor </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="Outros sites do 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"> Termos </a> </li> <li class="footer-utility-item"> <a href="//policies.google.com/privacy" class="footer-utility-link"> Privacidade </a> </li> </ul> <div class="language-selector footer" aria-label="Selecione seu idioma preferencial"> <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">Português (Brasil)</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" 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" aria-current="true" 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>