diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/2023/05/02/goingo-meu-primeiro-jogo.html b/2023/05/02/goingo-meu-primeiro-jogo.html new file mode 100644 index 0000000..f4ab490 --- /dev/null +++ b/2023/05/02/goingo-meu-primeiro-jogo.html @@ -0,0 +1,160 @@ + + + + + + + Goingo: Meu primeiro jogo + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Goingo: Meu primeiro jogo

+ +

Eu já perdi a conta de quantos protótipos eu já criei com Ebiten(ou Ebitengine como me pediram para chamar), muitos foram direto para a lixeira e outros estão perdidos em branches abandonadas em algum repositório. Porém tem ideias que são bobas boas demais para deixar passar e precisam de um tratamento à altura. Hoje vou falar sobre o primeiro jogo que lancei: Goingo, um uma versão do ancestral jogo de Go feito na totalmente na linguagem Go.

+

+ + + # Porque Go? + + +

+ + +

A confusão é totalmente intencional, tudo começou porque queria testar uma nova biblioteca e precisava de algo mais complexo que uma demo para ver ele em ação. Mas no fim eu acabei aprendendo bastante sobre ambos e decidi levar o projeto até o lançamento, muito porque já estava tudo ali, só precisava dar aquele pequeno esforço para finalizar.

+

+ + + # O jogo de tabuleiro + + +

+ + +

Ko Loop

+ +

Go é o jogo de tabuleiro mais antigo do mundo ainda jogado segundo a Wikipedia, teria sido criado a 2500 anos atrás na China onde ainda é muito popular. Aqui no ocidente ele ficou mais conhecido depois que o AlphaGO, uma inteligencia artificial, venceu o campeão mundial em 2016.

+ +

Apesar de ser um jogo complexo e do desafio que é criar uma IA para jogar ele, as regras são extremamente simples. Esse foi o principal motivo de ter criado esse jogo, é um ótimo exemplo de jogo de tabuleiro que pode ser criado com algumas coisas linhas de código. Basicamente em Go:

+ +
    +
  • Cada jogador se alterna colocando uma peça de sua cor no tabuleiro
  • +
  • Peças adjacentes a outras da mesma cor formam grupos
  • +
  • Quando um grupo é certado completamente por peças do adversário esse grupo é captura e retirado do tabuleiro.
  • +
  • Vence quem cercar mais espaços no tabuleiro ao fim da partida
  • +
+ +

Claro, a partir dessas regras nascem outras como Ko, Atari, etc, mas para criar a engine essas três são as básicas e definem o game loop. Para criar uma experiencia divertida e interessante é necessário mais funcionalidades, testes para impedir que o jogador faça movimento ilegais e uma método de contar os pontos de cada jogador.

+ +

Essa é uma das coisas que não tenho ainda no jogo, se quiserem saber quem venceu a partida os jogadores precisam contar seus próprios territórios. Parece preguiça da minha parte não adicionar isso ao jogo, mas depois de passar uma noite inteira tentando entender esse artigo, eu preferi deixar para uma depois. Eu já comentei que desenvolvi o jogo inteiro em uma semana?

+

+ + + # A Linguagem de Programação + + +

+ + +

Gophers playing Go

+ +

É obvio que escolhi Go como linguagem porque é a minha favorita, mas quis dedicar essa parte do artigo para contar sobre uma situação que eu provavelmente não teria conseguido resolver se fosse em outra linguagem.

+ +

A biblioteca que eu queria utilizar e que deu inicio a +esse projeto se chama Donburi, é um ECS para a Ebitengine que sempre uso por aqui. Eu ainda vou voltar a falar de ECS no futuro, é um tópico muito importante, mas o que me deu problemas foi um gerenciador de eventos que acompanha a biblioteca. Da forma que eu planejei o meu programa o gerenciador entrava em panico e derrubava o programa. Haviam formas de contornar isso, mas se tratava de um bug no código que precisava ser corrigido, não era para ela se comportar daquela forma.

+ +

Pedir uma correção em um projeto open-source é sempre uma aposta, principalmente quando você não tem familiaridade com o projeto e seus desenvolvedores. Alguns podem ser super abertos, outros podem extremamente relutantes quanto a qualquer tipo de mudança. Sem falar que nunca pode contar que alguém vai tirar parte do tempo dela para resolver um problema seu, te forçando a ter que entrar no código, achar o problema, resolver e propor uma pull-request. Ai que eu acredito que o Go entrou como um grande aliado nesse projeto, pela forma que o Go funciona e a sua sintaxe, é muito fácil entrar em um projeto e identificar como ele funciona. Não existem macros, escopos invisíveis, tipagem dinâmica, magicas de qualquer tipo, tudo em Go é explícito ao ponto que em minutos eu já sabia onde estava o problema e em poucas horas já tinha uma solução.

+ +

Contactar os desenvolvedores para incorporar essas mudanças é outra história, mas isso independe da linguagem. Minha pull-request para o pkg/browser ainda não foi vista até o momento que estou escrevendo esse artigo, por sorte Yohamta foi super rápido em aprovar e eu agradeço muito a ele.

+

+ + + # O que fiz de diferente? + + +

+ + +

Algo que é um defeito meu: começar algo e abandonar no meio do caminho. Desde a escola, eu ficava muito animado com um assunto e pesquisava tudo que conseguia sobre ele mas na hora de escrever o trabalho e amarrar tudo eu ficava com preguiça e abandonava. A experiência de fazer sempre era melhor que a de terminar, hoje ainda tenho mais um agravante que é a ideia de que o resultado não vai valer a pena então porque se dedicar até o fim? Eu venho sempre me sabotando dessa forma e vivo buscando formas de superar, mas o que ainda me prende é ter dificuldade de definir onde é o ponto que posso considerar algo como pronto.

+ +

Finalizar algo é difícil para mim porque não consigo definir claramente o resultado esperado e como chegar nele. A forma que encontrei para lidar com isso é diminuindo o escopo do trabalho e aceitando a incompletude dele, desde que eu fizesse o mínimo para me sentir confortável em mostrar para os outros. Assim o projeto nunca está “pronto”, sempre é possível encontrar algo a melhorar, mas também está organizado a um ponto que não é um experimento pessoal que só você pode entender e aproveitar.

+ +

Para deixar o jogo nesse estado eu decidi que precisava de pelo menos:

+ +
    +
  • Sons: Geralmente negligenciados no desenvolvimento, sons dão uma sensação táctil ao jogo que ajuda muito a polir o jogo. Demorou um pouco até encontrar o som certo, mas também no fim foi apenas 3 samples que eu usei para as movimentações das peças.
  • +
  • Menu: UI é um porre de fazer, mas é totalmente necessária, eu não preciso te convencer disso. É o tipo de coisa que é preciso criar coragem e fazer mesmo que fique feio, sem ela o jogo não é acessível jogador.
  • +
  • Logo: O logo tipo é o rosto do seu produto, é o que identifica ele tanto quanto o seu nome. Eu não sou designer e imagino que também não seja, mesmo assim eu me desafiei a fazer esse desenho porque com ele eu tinha tudo que precisava para mostrar o jogo para o mundo. É cruel pensar nisso, o publico vai ser muito mais impactado por esse desenho que pelas horas de pesquisa e desenvolvimento que eu passei no código.
  • +
+ +

No fim desses três eu ainda acabei incluindo mais algumas coisinhas como alguns overlays, diferentes tamanhos de tabuleiro e a opção de jogar com uma IA usando GoGNU.

+

+ + + # Como jogar? + + +

+ + +

O jogo está disponível no Itch.io e no Github, o código é aberto e caso queira me ajudar pode pagar quanto quiser pelo jogo. Eu não vou falar muito porque acho que vale a pena entrar nas páginas e ver como ficou o resultado. É impressionante o que as IA de hoje em dia conseguem fazer, não se preocupe que aqui nesse post foi tudo escrito por mãos humanas.

+

+ + + # Conclusão + + +

+ + +

Eu deveria ter escrito esse artigo antes, mas depois de voltar da minha viagem eu fiquei me coçando para escrever código e precisava codar algumas coisas, esse jogo inclusive. Além dele ainda tem uma biblioteca que eu criei e publiquei essa semana que vou escrever um artigo a respeito. Uma coisa que me ajudou bastante para produzir tanto foram algumas ferramentas de IA, eu ainda tenho alguma resistência, mas deu para perceber essa semana o potencial que elas tem. Aqui por exemplo é um espaço que eu não acho justo pedir para o ChatGPT me ajudar, demoro um tanto para escrever esses artigos, acho importante manter essa pessoalidade nesse blog. No README e descrições desses programas eu achei o maximo poder usar a IA, você explica as coisas direto ao ponto e ela enche linguiça para você.

+ +

Um outro ponto que quero começar a usar mais IA é na tradução dos textos desse blog. No momento, a maioria do material está apenas em português e eu gostaria muito de ter ele disponível em inglês para ajudar na divulgação. Meu plano é usar os modelos da Libretranslate para ajudar no processo, se estiver lendo isso em inglês provavelmente o meu plano deu certo.

+ +

Em 2 semanas começam as minhas aulas da faculdade e na semana que vem eu já me mudo em definitivo. Não tenho ideia de como vai ficar meu tempo livre, mas quero continuar publicando por aqui e criando jogos e outros programas legais. Mas se tiver que codar apenas ferramentas de estudo, vou vir aqui contar tudo para vocês. Me desejem sorte nessa nova jornada.


+ +

Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo GitHub ou e-mail. +thank you!

+
+
+
+ + + + \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000..a09250b --- /dev/null +++ b/404.html @@ -0,0 +1,44 @@ + + + + + + + 404 + + + + + + + + + + + + + + + + +
+
+

404

+ +

Vincent Vega Lost

+ +

Page not found! :( +Go Back

+ +
+
+ + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4ea99c2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,395 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0880a4d --- /dev/null +++ b/README.md @@ -0,0 +1,239 @@ + + +# GitHub Pages + +_Create a site or blog from your GitHub repositories with GitHub Pages._ + + + +
+

Welcome

+ +With GitHub Pages, you can host project blogs, documentation, resumes, portfolios, or any other static content you'd like. Your GitHub repository can easily become its own website. In this course, we'll show you how to set up your own site or blog using GitHub Pages. + +- **Who is this for**: Beginners, students, project maintainers, small businesses. +- **What you'll learn**: How to build a GitHub Pages site. +- **What you'll build**: We'll build a simple GitHub Pages site with a blog. We'll use [Jekyll](https://jekyllrb.com), a static site generator. +- **Prerequisites**: If you need to learn about branches, commits, and pull requests, take [Introduction to GitHub](https://github.com/skills/introduction-to-github) first. +- **How long**: This course is five steps long and takes less than one hour to complete. + +## How to start this course + +1. Right-click **Start course** and open the link in a new tab. +
[![start-course](https://user-images.githubusercontent.com/1221423/218596841-0645fe1a-4aaf-4f51-9ab3-8aa2d3fdd487.svg)](https://github.com/skills/github-pages/generate) +2. In the new tab, follow the prompts to create a new repository. + - For owner, choose your personal account or an organization to host the repository. + - We recommend creating a public repository—private repositories will [use Actions minutes](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions). + ![Create a new repository](https://user-images.githubusercontent.com/1221423/218594143-e60462b6-9f2a-4fa3-80de-063ac5429aab.png) +3. After your new repository is created, wait about 20 seconds, then refresh the page. Follow the step-by-step instructions in the new repository's README. + +
+ + + +
+

Step 1: Enable GitHub Pages

+ +_Welcome to GitHub Pages and Jekyll :tada:!_ + +The first step is to enable GitHub Pages on this [repository](https://docs.github.com/en/get-started/quickstart/github-glossary#repository). When you enable GitHub Pages on a repository, GitHub takes the content that's on the main branch and publishes a website based on its contents. + +### :keyboard: Activity: Enable GitHub Pages + +1. Open a new browser tab, and work on the steps in your second tab while you read the instructions in this tab. +1. Under your repository name, click **Settings**. +1. Click **Pages** in the **Code and automation** section. +1. Ensure "Deploy from a branch" is selected from the **Source** drop-down menu, and then select `main` from the **Branch** drop-down menu. +1. Click the **Save** button. +1. Wait about _one minute_, then refresh this page for the next step. + > Turning on GitHub Pages creates a deployment of your repository. GitHub Actions may take up to a minute to respond while waiting for the deployment. Future steps will be about 20 seconds; this step is slower. + > **Note**: In the **Pages** of **Settings**, the **Visit site** button will appear at the top. Click the button to see your GitHub Pages site. + +
+ + + +
+

Step 2: Configure your site

+ +_You turned on GitHub Pages! :tada:_ + +We'll work in a branch, `my-pages`, that I created for you to get this site looking great. :sparkle: + +Jekyll uses a file titled `_config.yml` to store settings for your site, your theme, and reusable content like your site title and GitHub handle. You can check out the `_config.yml` file on the **Code** tab of your repository. + +We need to use a blog-ready theme. For this activity, we will use a theme named "minima". + +### :keyboard: Activity: Configure your site + +1. Browse to the `_config.yml` file in the `my-pages` branch. +1. In the upper right corner, open the file editor. +1. Add a `theme:` set to **minima** so it shows in the `_config.yml` file as below: + ```yml + theme: minima + ``` +1. (optional) You can modify the other configuration variables such as `title:`, `author:`, and `description:` to further customize your site. +1. Commit your changes. +1. (optional) Create a pull request to view all the changes you'll make throughout this course. Click the **Pull Requests** tab, click **New pull request**, set `base: main` and `compare:my-pages`. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Step 3: Customize your homepage

+ +_Nice work setting the theme! :sparkles:_ + +You can customize your homepage by adding content to either an `index.md` file or the `README.md` file. GitHub Pages first looks for an `index.md` file. Your repository has an `index.md` file so we can update it to include your personalized content. + +### :keyboard: Activity: Create your homepage + +1. Browse to the `index.md` file in the `my-pages` branch. +1. In the upper right corner, open the file editor. +1. Type the content you want on your homepage. You can use Markdown formatting on this page. +1. (optional) You can also modify `title:` or just ignore it for now. We'll discuss it in the next step. +1. Commit your changes to the `my-pages` branch. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Step 4: Create a blog post

+ +_Your home page is looking great! :cowboy_hat_face:_ + +GitHub Pages uses Jekyll. In Jekyll, we can create a blog by using specially named files and frontmatter. The files must be named `_posts/YYYY-MM-DD-title.md`. You must also include `title` and `date` in your frontmatter. + +**What is _frontmatter_?**: The syntax Jekyll files use is called YAML frontmatter. It goes at the top of your file and looks something like this: + +```yml +--- +title: "Welcome to my blog" +date: 2019-01-20 +--- +``` + +For more information about configuring front matter, see the [Jekyll frontmatter documentation](https://jekyllrb.com/docs/frontmatter/). + +### :keyboard: Activity: Create a blog post + +1. Browse to the `my-pages` branch. +1. Click the `Add file` dropdown menu and then on `Create new file`. +1. Name the file `_posts/YYYY-MM-DD-title.md`. +1. Replace the `YYYY-MM-DD` with today's date, and change the `title` of your first blog post if you'd like. + > If you do edit the title, make sure there are hyphens between your words. + > If your blog post date doesn't follow the correct date convention, you'll receive an error and your site won't build. For more information, see "[Page build failed: Invalid post date](https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/troubleshooting-jekyll-build-errors-for-github-pages-sites)". +1. Type the following content at the top of your blog post: + ```yaml + --- + title: "YOUR-TITLE" + date: YYYY-MM-DD + --- + ``` +1. Replace `YOUR-TITLE` with the title for your blog post. +1. Replace `YYYY-MM-DD` with today's date. +1. Type a quick draft of your blog post. Remember, you can always edit it later. +1. Commit your changes to your branch. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Step 5: Merge your pull request

+ +_Nice work, friend :heart:! People will be reading your blog in no time!_ + +You can now [merge](https://docs.github.com/en/get-started/quickstart/github-glossary#merge) your pull request! + +### :keyboard: Activity: Merge your changes + +1. Merge your changes from `my-pages` into `main`. If you created the pull request in step 2, just open that PR and click on **Merge pull request**. If you did not create the pull request earlier, you can do it now by following the instructions in step 2. +1. (optional) Delete the branch `my-pages`. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Finish

+ +_Congratulations friend, you've completed this course!_ + +celebrate + +Your blog is now live and has been deployed! + +Here's a recap of all the tasks you've accomplished in your repository: + +- You enabled GitHub Pages. +- You selected a theme using the config file. +- You learned about proper directory format and file naming conventions in Jekyll. +- You created your first a blog post with Jekyll! + +### What's next? + +- Keep working on your GitHub Pages site... we love seeing what you come up with! +- We'd love to hear what you thought of this course [in our discussion board](https://github.com/skills/.github/discussions). +- [Take another GitHub Skills course](https://github.com/skills). +- [Read the GitHub Getting Started docs](https://docs.github.com/en/get-started). +- To find projects to contribute to, check out [GitHub Explore](https://github.com/explore). + +
+ + + +--- + +Get help: [Post in our discussion board](https://github.com/skills/.github/discussions) • [Review the GitHub status page](https://www.githubstatus.com/) + +© 2022 GitHub • [Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/code_of_conduct.md) • [CC-BY-4.0 License](https://creativecommons.org/licenses/by/4.0/legalcode) diff --git a/archive.html b/archive.html new file mode 100644 index 0000000..f1fdf48 --- /dev/null +++ b/archive.html @@ -0,0 +1,86 @@ + + + + + + + All Posts + + + + + + + + + + + + + + + + +
+
+ ../

All Posts

+
+
+ + + + \ No newline at end of file diff --git a/assets/7e8xd3.jpg b/assets/7e8xd3.jpg new file mode 100644 index 0000000..4aa308e Binary files /dev/null and b/assets/7e8xd3.jpg differ diff --git a/assets/7e90ar.jpg b/assets/7e90ar.jpg new file mode 100644 index 0000000..06d4e03 Binary files /dev/null and b/assets/7e90ar.jpg differ diff --git a/assets/7e96di.jpg b/assets/7e96di.jpg new file mode 100644 index 0000000..0e643ac Binary files /dev/null and b/assets/7e96di.jpg differ diff --git a/assets/Captura de tela de 2023-03-13 19-06-57.png b/assets/Captura de tela de 2023-03-13 19-06-57.png new file mode 100644 index 0000000..9e4f479 Binary files /dev/null and b/assets/Captura de tela de 2023-03-13 19-06-57.png differ diff --git a/assets/WhatsApp Image 2023-05-25 at 16.56.41.jpeg b/assets/WhatsApp Image 2023-05-25 at 16.56.41.jpeg new file mode 100644 index 0000000..e4482c5 Binary files /dev/null and b/assets/WhatsApp Image 2023-05-25 at 16.56.41.jpeg differ diff --git a/assets/WhatsApp Image 2023-05-25 at 16.56.42.jpeg b/assets/WhatsApp Image 2023-05-25 at 16.56.42.jpeg new file mode 100644 index 0000000..86f03b1 Binary files /dev/null and b/assets/WhatsApp Image 2023-05-25 at 16.56.42.jpeg differ diff --git a/assets/css/main.css b/assets/css/main.css new file mode 100644 index 0000000..2c69eec --- /dev/null +++ b/assets/css/main.css @@ -0,0 +1 @@ +.highlight table td{padding:5px}.highlight table pre{margin:0}.highlight,.highlight .w{color:#49483e}.highlight .err{color:#272822;background-color:#f92672}.highlight .c,.highlight .ch,.highlight .cd,.highlight .cm,.highlight .cpf,.highlight .c1,.highlight .cs{color:#75715e}.highlight .cp{color:#f4bf75}.highlight .nt{color:#f4bf75}.highlight .o,.highlight .ow{color:#f8f8f2}.highlight .p,.highlight .pi{color:#f8f8f2}.highlight .gi{color:#a6e22e}.highlight .gd{color:#f92672}.highlight .gh{color:#66d9ef;background-color:#272822;font-weight:bold}.highlight .k,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kv{color:#ae81ff}.highlight .kc{color:#fd971f}.highlight .kt{color:#fd971f}.highlight .kd{color:#fd971f}.highlight .s,.highlight .sb,.highlight .sc,.highlight .dl,.highlight .sd,.highlight .s2,.highlight .sh,.highlight .sx,.highlight .s1{color:#a6e22e}.highlight .sa{color:#ae81ff}.highlight .sr{color:#a1efe4}.highlight .si{color:#cc6633}.highlight .se{color:#cc6633}.highlight .nn{color:#f4bf75}.highlight .nc{color:#f4bf75}.highlight .no{color:#f4bf75}.highlight .na{color:#66d9ef}.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .il,.highlight .mo,.highlight .mx{color:#a6e22e}.highlight .ss{color:#a6e22e}body[a="dark"]{filter:invert(1)}body[a="dark"] img{filter:invert(1)}body[a="dark"] img.ioda{filter:invert(0)}body[a="dark"] iframe{filter:invert(1)}@media (prefers-color-scheme: dark){body[a="auto"]{filter:invert(1)}body[a="auto"] img{filter:invert(1)}body[a="auto"] img.ioda{filter:invert(0)}body[a="auto"] iframe{filter:invert(1)}}html,body{background:white}html{height:100%}body{color:black;font-family:monospace;font-size:16px;line-height:1.4;margin:0;min-height:100%;overflow-wrap:break-word}.post-meta{text-align:right}h2,h3,h4,h5,h6{margin-top:3rem}hr{margin:2rem 0}p{margin:1rem 0}.languages{text-align:right}li{margin:0.4rem 0}*:target{background:yellow}.w{max-width:640px;margin:0 auto;padding:4rem 2rem}hr{text-align:center;border:0}hr:before{content:"/////"}hr:after{content:attr(data-content) "/////"}table{width:100%}table,th,td{border:thin solid black;border-collapse:collapse;padding:0.4rem}code{color:white;background:black}div.highlighter-rouge code{display:block;overflow-x:auto;white-space:pre-wrap;padding:1rem;tab-size:1rem}blockquote{font-style:italic;border:thin solid black;padding:1rem}blockquote p{margin:0}img{max-width:100%;display:block;margin:0 auto}a.h-anchor{opacity:.2;font-size:80%}a.h-anchor:hover{opacity:1} diff --git a/assets/js/mouse_coords.js b/assets/js/mouse_coords.js new file mode 100644 index 0000000..afc7e7a --- /dev/null +++ b/assets/js/mouse_coords.js @@ -0,0 +1,9 @@ +const p = document.createElement("p"); +p.style.textAlign = "center"; +p.style.fontSize = "18pt"; +p.innerHTML = "C'mon, move your mouse!" +document.body.append(p); + +document.addEventListener("mousemove", e => { + p.innerHTML = `mouseX: ${e.clientX}, mouseY: ${e.clientY}`; +}); \ No newline at end of file diff --git a/assets/lt-0.png b/assets/lt-0.png new file mode 100644 index 0000000..c3a9076 Binary files /dev/null and b/assets/lt-0.png differ diff --git a/assets/lt-1.png b/assets/lt-1.png new file mode 100644 index 0000000..31a0dc5 Binary files /dev/null and b/assets/lt-1.png differ diff --git a/assets/river-0.png b/assets/river-0.png new file mode 100644 index 0000000..4a5eb48 Binary files /dev/null and b/assets/river-0.png differ diff --git a/assets/wasm/Automata/automata.html b/assets/wasm/Automata/automata.html new file mode 100644 index 0000000..2d690e9 --- /dev/null +++ b/assets/wasm/Automata/automata.html @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/assets/wasm/Automata/automata.v0.wasm b/assets/wasm/Automata/automata.v0.wasm new file mode 100755 index 0000000..03b90ea Binary files /dev/null and b/assets/wasm/Automata/automata.v0.wasm differ diff --git a/assets/wasm/Automata/automata.v1.wasm b/assets/wasm/Automata/automata.v1.wasm new file mode 100755 index 0000000..717ce23 Binary files /dev/null and b/assets/wasm/Automata/automata.v1.wasm differ diff --git a/assets/wasm/Erosion/erosion.html b/assets/wasm/Erosion/erosion.html new file mode 100644 index 0000000..91f29c1 --- /dev/null +++ b/assets/wasm/Erosion/erosion.html @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/assets/wasm/Erosion/main.wasm b/assets/wasm/Erosion/main.wasm new file mode 100755 index 0000000..6db4c3a Binary files /dev/null and b/assets/wasm/Erosion/main.wasm differ diff --git a/assets/wasm/Farm/farm.html b/assets/wasm/Farm/farm.html new file mode 100644 index 0000000..af3e3e2 --- /dev/null +++ b/assets/wasm/Farm/farm.html @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/assets/wasm/Farm/farm.v0.wasm b/assets/wasm/Farm/farm.v0.wasm new file mode 100755 index 0000000..328eea6 Binary files /dev/null and b/assets/wasm/Farm/farm.v0.wasm differ diff --git a/assets/wasm/GameOfLife/gol.html b/assets/wasm/GameOfLife/gol.html new file mode 100644 index 0000000..1fae893 --- /dev/null +++ b/assets/wasm/GameOfLife/gol.html @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/assets/wasm/GameOfLife/gol.v0.wasm b/assets/wasm/GameOfLife/gol.v0.wasm new file mode 100755 index 0000000..73105e2 Binary files /dev/null and b/assets/wasm/GameOfLife/gol.v0.wasm differ diff --git a/assets/wasm/GameOfLife/gol.v1.wasm b/assets/wasm/GameOfLife/gol.v1.wasm new file mode 100755 index 0000000..3c1d17e Binary files /dev/null and b/assets/wasm/GameOfLife/gol.v1.wasm differ diff --git a/assets/wasm/Goingo/goingo.v1.wasm b/assets/wasm/Goingo/goingo.v1.wasm new file mode 100755 index 0000000..f4e237d Binary files /dev/null and b/assets/wasm/Goingo/goingo.v1.wasm differ diff --git a/assets/wasm/Tilemap/tilemap.html b/assets/wasm/Tilemap/tilemap.html new file mode 100644 index 0000000..fd7393b --- /dev/null +++ b/assets/wasm/Tilemap/tilemap.html @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/assets/wasm/Tilemap/tilemap.v0.wasm b/assets/wasm/Tilemap/tilemap.v0.wasm new file mode 100755 index 0000000..4f385d1 Binary files /dev/null and b/assets/wasm/Tilemap/tilemap.v0.wasm differ diff --git a/assets/wasm/wasm_exec.js b/assets/wasm/wasm_exec.js new file mode 100644 index 0000000..9ce6a20 --- /dev/null +++ b/assets/wasm/wasm_exec.js @@ -0,0 +1,554 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +"use strict"; + +(() => { + const enosys = () => { + const err = new Error("not implemented"); + err.code = "ENOSYS"; + return err; + }; + + if (!globalThis.fs) { + let outputBuf = ""; + globalThis.fs = { + constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused + writeSync(fd, buf) { + outputBuf += decoder.decode(buf); + const nl = outputBuf.lastIndexOf("\n"); + if (nl != -1) { + console.log(outputBuf.substr(0, nl)); + outputBuf = outputBuf.substr(nl + 1); + } + return buf.length; + }, + write(fd, buf, offset, length, position, callback) { + if (offset !== 0 || length !== buf.length || position !== null) { + callback(enosys()); + return; + } + const n = this.writeSync(fd, buf); + callback(null, n); + }, + chmod(path, mode, callback) { callback(enosys()); }, + chown(path, uid, gid, callback) { callback(enosys()); }, + close(fd, callback) { callback(enosys()); }, + fchmod(fd, mode, callback) { callback(enosys()); }, + fchown(fd, uid, gid, callback) { callback(enosys()); }, + fstat(fd, callback) { callback(enosys()); }, + fsync(fd, callback) { callback(null); }, + ftruncate(fd, length, callback) { callback(enosys()); }, + lchown(path, uid, gid, callback) { callback(enosys()); }, + link(path, link, callback) { callback(enosys()); }, + lstat(path, callback) { callback(enosys()); }, + mkdir(path, perm, callback) { callback(enosys()); }, + open(path, flags, mode, callback) { callback(enosys()); }, + read(fd, buffer, offset, length, position, callback) { callback(enosys()); }, + readdir(path, callback) { callback(enosys()); }, + readlink(path, callback) { callback(enosys()); }, + rename(from, to, callback) { callback(enosys()); }, + rmdir(path, callback) { callback(enosys()); }, + stat(path, callback) { callback(enosys()); }, + symlink(path, link, callback) { callback(enosys()); }, + truncate(path, length, callback) { callback(enosys()); }, + unlink(path, callback) { callback(enosys()); }, + utimes(path, atime, mtime, callback) { callback(enosys()); }, + }; + } + + if (!globalThis.process) { + globalThis.process = { + getuid() { return -1; }, + getgid() { return -1; }, + geteuid() { return -1; }, + getegid() { return -1; }, + getgroups() { throw enosys(); }, + pid: -1, + ppid: -1, + umask() { throw enosys(); }, + cwd() { throw enosys(); }, + chdir() { throw enosys(); }, + } + } + + if (!globalThis.crypto) { + throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"); + } + + if (!globalThis.performance) { + throw new Error("globalThis.performance is not available, polyfill required (performance.now only)"); + } + + if (!globalThis.TextEncoder) { + throw new Error("globalThis.TextEncoder is not available, polyfill required"); + } + + if (!globalThis.TextDecoder) { + throw new Error("globalThis.TextDecoder is not available, polyfill required"); + } + + const encoder = new TextEncoder("utf-8"); + const decoder = new TextDecoder("utf-8"); + + globalThis.Go = class { + constructor() { + this.argv = ["js"]; + this.env = {}; + this.exit = (code) => { + if (code !== 0) { + console.warn("exit code:", code); + } + }; + this._exitPromise = new Promise((resolve) => { + this._resolveExitPromise = resolve; + }); + this._pendingEvent = null; + this._scheduledTimeouts = new Map(); + this._nextCallbackTimeoutID = 1; + + const setInt64 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); + } + + const getInt64 = (addr) => { + const low = this.mem.getUint32(addr + 0, true); + const high = this.mem.getInt32(addr + 4, true); + return low + high * 4294967296; + } + + const loadValue = (addr) => { + const f = this.mem.getFloat64(addr, true); + if (f === 0) { + return undefined; + } + if (!isNaN(f)) { + return f; + } + + const id = this.mem.getUint32(addr, true); + return this._values[id]; + } + + const storeValue = (addr, v) => { + const nanHead = 0x7FF80000; + + if (typeof v === "number" && v !== 0) { + if (isNaN(v)) { + this.mem.setUint32(addr + 4, nanHead, true); + this.mem.setUint32(addr, 0, true); + return; + } + this.mem.setFloat64(addr, v, true); + return; + } + + if (v === undefined) { + this.mem.setFloat64(addr, 0, true); + return; + } + + let id = this._ids.get(v); + if (id === undefined) { + id = this._idPool.pop(); + if (id === undefined) { + id = this._values.length; + } + this._values[id] = v; + this._goRefCounts[id] = 0; + this._ids.set(v, id); + } + this._goRefCounts[id]++; + let typeFlag = 0; + switch (typeof v) { + case "object": + if (v !== null) { + typeFlag = 1; + } + break; + case "string": + typeFlag = 2; + break; + case "symbol": + typeFlag = 3; + break; + case "function": + typeFlag = 4; + break; + } + this.mem.setUint32(addr + 4, nanHead | typeFlag, true); + this.mem.setUint32(addr, id, true); + } + + const loadSlice = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + return new Uint8Array(this._inst.exports.mem.buffer, array, len); + } + + const loadSliceOfValues = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + const a = new Array(len); + for (let i = 0; i < len; i++) { + a[i] = loadValue(array + i * 8); + } + return a; + } + + const loadString = (addr) => { + const saddr = getInt64(addr + 0); + const len = getInt64(addr + 8); + return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); + } + + const timeOrigin = Date.now() - performance.now(); + this.importObject = { + go: { + // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) + // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported + // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). + // This changes the SP, thus we have to update the SP used by the imported function. + + // func wasmExit(code int32) + "runtime.wasmExit": (sp) => { + sp >>>= 0; + const code = this.mem.getInt32(sp + 8, true); + this.exited = true; + delete this._inst; + delete this._values; + delete this._goRefCounts; + delete this._ids; + delete this._idPool; + this.exit(code); + }, + + // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) + "runtime.wasmWrite": (sp) => { + sp >>>= 0; + const fd = getInt64(sp + 8); + const p = getInt64(sp + 16); + const n = this.mem.getInt32(sp + 24, true); + fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); + }, + + // func resetMemoryDataView() + "runtime.resetMemoryDataView": (sp) => { + sp >>>= 0; + this.mem = new DataView(this._inst.exports.mem.buffer); + }, + + // func nanotime1() int64 + "runtime.nanotime1": (sp) => { + sp >>>= 0; + setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); + }, + + // func walltime() (sec int64, nsec int32) + "runtime.walltime": (sp) => { + sp >>>= 0; + const msec = (new Date).getTime(); + setInt64(sp + 8, msec / 1000); + this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); + }, + + // func scheduleTimeoutEvent(delay int64) int32 + "runtime.scheduleTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this._nextCallbackTimeoutID; + this._nextCallbackTimeoutID++; + this._scheduledTimeouts.set(id, setTimeout( + () => { + this._resume(); + while (this._scheduledTimeouts.has(id)) { + // for some reason Go failed to register the timeout event, log and try again + // (temporary workaround for https://github.com/golang/go/issues/28975) + console.warn("scheduleTimeoutEvent: missed timeout event"); + this._resume(); + } + }, + getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early + )); + this.mem.setInt32(sp + 16, id, true); + }, + + // func clearTimeoutEvent(id int32) + "runtime.clearTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this.mem.getInt32(sp + 8, true); + clearTimeout(this._scheduledTimeouts.get(id)); + this._scheduledTimeouts.delete(id); + }, + + // func getRandomData(r []byte) + "runtime.getRandomData": (sp) => { + sp >>>= 0; + crypto.getRandomValues(loadSlice(sp + 8)); + }, + + // func finalizeRef(v ref) + "syscall/js.finalizeRef": (sp) => { + sp >>>= 0; + const id = this.mem.getUint32(sp + 8, true); + this._goRefCounts[id]--; + if (this._goRefCounts[id] === 0) { + const v = this._values[id]; + this._values[id] = null; + this._ids.delete(v); + this._idPool.push(id); + } + }, + + // func stringVal(value string) ref + "syscall/js.stringVal": (sp) => { + sp >>>= 0; + storeValue(sp + 24, loadString(sp + 8)); + }, + + // func valueGet(v ref, p string) ref + "syscall/js.valueGet": (sp) => { + sp >>>= 0; + const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 32, result); + }, + + // func valueSet(v ref, p string, x ref) + "syscall/js.valueSet": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); + }, + + // func valueDelete(v ref, p string) + "syscall/js.valueDelete": (sp) => { + sp >>>= 0; + Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); + }, + + // func valueIndex(v ref, i int) ref + "syscall/js.valueIndex": (sp) => { + sp >>>= 0; + storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); + }, + + // valueSetIndex(v ref, i int, x ref) + "syscall/js.valueSetIndex": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); + }, + + // func valueCall(v ref, m string, args []ref) (ref, bool) + "syscall/js.valueCall": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const m = Reflect.get(v, loadString(sp + 16)); + const args = loadSliceOfValues(sp + 32); + const result = Reflect.apply(m, v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, result); + this.mem.setUint8(sp + 64, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, err); + this.mem.setUint8(sp + 64, 0); + } + }, + + // func valueInvoke(v ref, args []ref) (ref, bool) + "syscall/js.valueInvoke": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.apply(v, undefined, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueNew(v ref, args []ref) (ref, bool) + "syscall/js.valueNew": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.construct(v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueLength(v ref) int + "syscall/js.valueLength": (sp) => { + sp >>>= 0; + setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); + }, + + // valuePrepareString(v ref) (ref, int) + "syscall/js.valuePrepareString": (sp) => { + sp >>>= 0; + const str = encoder.encode(String(loadValue(sp + 8))); + storeValue(sp + 16, str); + setInt64(sp + 24, str.length); + }, + + // valueLoadString(v ref, b []byte) + "syscall/js.valueLoadString": (sp) => { + sp >>>= 0; + const str = loadValue(sp + 8); + loadSlice(sp + 16).set(str); + }, + + // func valueInstanceOf(v ref, t ref) bool + "syscall/js.valueInstanceOf": (sp) => { + sp >>>= 0; + this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0); + }, + + // func copyBytesToGo(dst []byte, src ref) (int, bool) + "syscall/js.copyBytesToGo": (sp) => { + sp >>>= 0; + const dst = loadSlice(sp + 8); + const src = loadValue(sp + 32); + if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + // func copyBytesToJS(dst ref, src []byte) (int, bool) + "syscall/js.copyBytesToJS": (sp) => { + sp >>>= 0; + const dst = loadValue(sp + 8); + const src = loadSlice(sp + 16); + if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + "debug": (value) => { + console.log(value); + }, + } + }; + } + + async run(instance) { + if (!(instance instanceof WebAssembly.Instance)) { + throw new Error("Go.run: WebAssembly.Instance expected"); + } + this._inst = instance; + this.mem = new DataView(this._inst.exports.mem.buffer); + this._values = [ // JS values that Go currently has references to, indexed by reference id + NaN, + 0, + null, + true, + false, + globalThis, + this, + ]; + this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id + this._ids = new Map([ // mapping from JS values to reference ids + [0, 1], + [null, 2], + [true, 3], + [false, 4], + [globalThis, 5], + [this, 6], + ]); + this._idPool = []; // unused ids that have been garbage collected + this.exited = false; // whether the Go program has exited + + // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. + let offset = 4096; + + const strPtr = (str) => { + const ptr = offset; + const bytes = encoder.encode(str + "\0"); + new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); + offset += bytes.length; + if (offset % 8 !== 0) { + offset += 8 - (offset % 8); + } + return ptr; + }; + + const argc = this.argv.length; + + const argvPtrs = []; + this.argv.forEach((arg) => { + argvPtrs.push(strPtr(arg)); + }); + argvPtrs.push(0); + + const keys = Object.keys(this.env).sort(); + keys.forEach((key) => { + argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); + }); + argvPtrs.push(0); + + const argv = offset; + argvPtrs.forEach((ptr) => { + this.mem.setUint32(offset, ptr, true); + this.mem.setUint32(offset + 4, 0, true); + offset += 8; + }); + + // The linker guarantees global data starts from at least wasmMinDataAddr. + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. + const wasmMinDataAddr = 4096 + 8192; + if (offset >= wasmMinDataAddr) { + throw new Error("total length of command line and environment variables exceeds limit"); + } + + this._inst.exports.run(argc, argv); + if (this.exited) { + this._resolveExitPromise(); + } + await this._exitPromise; + } + + _resume() { + if (this.exited) { + throw new Error("Go program has already exited"); + } + this._inst.exports.resume(); + if (this.exited) { + this._resolveExitPromise(); + } + } + + _makeFuncWrapper(id) { + const go = this; + return function () { + const event = { id: id, this: this, args: arguments }; + go._pendingEvent = event; + go._resume(); + return event.result; + }; + } + } +})(); diff --git a/datascience/2024/04/11/diy-datascience.html b/datascience/2024/04/11/diy-datascience.html new file mode 100644 index 0000000..3068843 --- /dev/null +++ b/datascience/2024/04/11/diy-datascience.html @@ -0,0 +1,148 @@ + + + + + + + DIY datascience + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

DIY datascience

+ +

Esses últimos meses eu realizei um sonho, eu consegui um carro! Fiz várias viagens e descobri que a minha vontade e da minha namorada é pegar o nosso Fox vermelho e desbravar esse mundo uma estradinha de cada vez. Porém, logo na primeira parada para abastecer nós já sentimos o golpe e entramos em desespero. 5,80 O LITRO DA GASOLINA! E na nossa primeira semana na cidade em que estudamos já tínhamos gastado quase 2 tanques inteiros, nunca que íamos conseguir realizar nosso sonho assim.

+ +

VW Fox 2004

+ +

No caso dessa primeira semana, o motivo desse gasto todo foi muito besta: os pneus estavam descalibrados. Parece brincadeira, mas depois de calibrar os pneus o consumo do nosso carro na cidade caiu pela metade. Isso me colocou para pensar, o que mais influencia no consumo do nosso carro? Claro bastava ler um blog sobre o assunto que eu ia descobrir que coisas como a quantidade de passageiros, a qualidade do combustível, estilo de direção, se o trecho é urbano, o desgaste do motor, tudo isso influencia no consumo do carro. Mas o que nenhum desses blogs vai ser capaz de me dizer é o quanto o MEU carro consome realmente e é isso que importa no final.

+ +

Com o meu interesse em Datascience reestabelecido graças ao BAH(Business Analytics Hub), decidi que era hora de responder a esse meu pavor com dados. Afinal, para participar do curso eu estou tendo de dirigir quase 240km, ida e volta, todas as sextas-feiras. A ideia é coletar uma boa quantidade de dados para descobrir qual o consumo real do nosso carro e mais algumas informações úteis como: Qual posto é o melhor custo-benefício na minha região? Com que frequência devo calibrar os pneus? Quais trajetos valem mais a pena de carro ou de ônibus? Quanto devo gastar em combustível em uma viagem antes mesmo de pegar a estrada? Compensa usar uma rota alternativa para não pagar o pedágio? Vamos ao plano:

+

+ + + # Coleta de dados + + +

+ + +

I've collected about 3800 Lists

+ +

O estudo dos Sistemas Complexos me ensinou que o mundo real é totalmente diferente do mundo ideal. Se o objetivo fosse estimar o consumo do meu carro, bastava marcar quanto o odômetro acusa entre visitas ao posto de gasolina. Uma álgebra simples ia me dizer teoricamente quanto meu carro faz de km/L. Mas o meu objetivo é ter um valor real, e a realidade ela é muito mais complexa que isso. Além disso eu estou muito empolgado de poder usar esse projeto para poder trabalhar com dados geoespaciais. Então a metodologia será a seguinte:

+ +
    +
  • A cada trajeto eu vou: +
      +
    • Fotografar o painel deixando visível o odômetro e o marcador de gasolina antes e depois de dirigir
    • +
    • Gravar o trajeto usando um aplicativo de GPS no meu celular
    • +
    • Anotar quantos passageiros tinham no carro
    • +
    +
  • +
  • A cada visita ao posto eu vou: +
      +
    • Fotografar o painel antes e depois de abastecer
    • +
    • Fotografar o painel da bomba deixando visível qual o combustível abastecido(álcool, gasolina ou aditivada), o valor total pago, a quantidade de litros e valor por litro
    • +
    • Registrar no aplicativo de GPS a localização do posto
    • +
    • Anotar: +
        +
      1. Se eu calibrei os pneus
      2. +
      3. Se eu usei um aplicativo para ter desconto e quanto que foi dado de desconto
      4. +
      5. Qual a bandeira do posto
      6. +
      +
    • +
    +
  • +
+ +

Com essas informações já conseguimos alguns dados, mas mais alguns vão poder ser inferidos a partir deles.

+

+ + + # Inferências + + +

+ +

Turn data into more data

+ +

Perceba que existem algumas informações redundantes que estão sendo coletadas e outras que parecem não ter muita relevância com o que estamos tentando medir, mas o objetivo disso é fazer algumas inferências que podem ser úteis depois na análise dos dados.

+ +

Comparando os dados redundantes conseguimos descobrir:

+ +
    +
  • Qual o desvio da distância acusada pelo odômetro e o GPS
  • +
  • Qual o desvio da litragem acusada pela bomba e o medidor do carro, e consequentemente o erro do medidor
  • +
  • Se o trajeto foi feito em trânsito intenso
  • +
  • Qual a proporção da mistura de cada combustível dentro do tanque
  • +
+ +

Cruzando os dados com outras bases de dados

+ +
    +
  • Quais trajetos foram feitos em trecho urbano e estrada
  • +
  • Qual a temperatura, umidade e condições de chuva no dia e local do trajeto
  • +
  • Quais trechos foram realizados antes e depois de troca de óleo e outras manutenções
  • +
  • Quais trechos passaram por pedágio e o valor
  • +
+

+ + + # Conclusões + + +

+ + +

Uma parte crucial da análise que não está nesse post é exatamente quais as questões que eu vou tentar responder com esses dados. Além das óbvias que fiz no início, muitas outras vão surgir ao longo do processo e a partir dos dados e problemas que vou acumular ao longo dos próximos meses. Por agora a maior preocupação vai ser coletar religiosamente esses dados e buscar uma formas de organizar e tratar esses dados.

+ +

Entendo que quem chegar a esse post deve ter muita curiosidade de ver os resultados e talvez até analisá-los por si mesmo. Porém, eu preciso ainda encontrar uma forma segura de fazer isso. Não quero que ninguém use os meus dados de GPS para descobrir onde eu moro por exemplo. Meus próximos posts sobre o assunto devem tratar disso, mas ainda não sei qual será o próximo feedback, fiquem atentos para mais novidades.

+ +
+

Dirijam com responsabilidade

+
+ +

Drive Safe!

+
+
+
+ + + + \ No newline at end of file diff --git a/demo/2023/03/15/game-of-life.html b/demo/2023/03/15/game-of-life.html new file mode 100644 index 0000000..1ebf484 --- /dev/null +++ b/demo/2023/03/15/game-of-life.html @@ -0,0 +1,165 @@ + + + + + + + Conway's Game Of Life + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

+ +

Conway's Game Of Life

+ +

Para o Game Of Life, nosso espaço será definido como +um 2d array, isso equivale a uma tela ou plano cartesiano. +O estado será um simples booliano, porque nesse +Autômato o estado varia apenas entre dois valores. Temos +assim o seguinte struct para armazenar nossos estados.

+ +
type GameOfLife struct {
+ values [][]bool
+}
+
+ +

O comportamento do nosso Autômato é definido nesse método Update. Nele cada elemento do nosso array é comparado aos seus vizinhos, isso determina qual o novo estado daquela célula.

+ +
func (gol *GameOfLife) Update() error {
+ // Primeiro criamos uma cópia do estado original, garantindo assim que não haverá conflitos
+	m0 := make([][]bool, len(gol.values))
+	copy(m0, gol.values)
+
+	for x, row := range gol.values {
+		for y, v0 := range row {
+			// Cell names
+			// |v1|v2|v3|
+			// |v4|v0|v5|
+			// |v6|v7|v8|
+			var alive uint
+
+			// Aqui contamos quantos vizinhos com estado verdadeiro essa célula possui
+			if v1 := gol.IsAliveOrNil(x-1, y-1); v1 != nil && *v1 {
+				alive++
+			}
+			if v2 := gol.IsAliveOrNil(x, y-1); v2 != nil && *v2 {
+				alive++
+			}
+			if v3 := gol.IsAliveOrNil(x+1, y-1); v3 != nil && *v3 {
+				alive++
+			}
+			if v4 := gol.IsAliveOrNil(x-1, y); v4 != nil && *v4 {
+				alive++
+			}
+			if v5 := gol.IsAliveOrNil(x+1, y); v5 != nil && *v5 {
+				alive++
+			}
+			if v6 := gol.IsAliveOrNil(x-1, y+1); v6 != nil && *v6 {
+				alive++
+			}
+			if v7 := gol.IsAliveOrNil(x, y+1); v7 != nil && *v7 {
+				alive++
+			}
+			if v8 := gol.IsAliveOrNil(x+1, y+1); v8 != nil && *v8 {
+				alive++
+			}
+
+			// Essa é aplicação da regra em si. A definição dela é a clássico proposta por Conway.
+			// Uma célula viva morre quando possui menos de 2 vizinhos vivos
+			// Uma célula viva morre quando possui mais de 3 vizinhos vivos
+			// Uma célula morta volta a vida quando possui exatamente 3 vizinhos vivos
+			// Em todos os outros casos ela mantém seu estado original
+			if v0 && (alive < 2 || alive > 3) { 
+				m0[x][y] = false
+			}
+			if !v0 && (alive == 3) {
+				m0[x][y] = true
+			}
+
+		}
+	}
+	gol.values = m0
+	return nil
+}
+
+ +

Para determinar se a célula existe e qual o seu estado, existe esse método. Perceba que ele retorna um ponteiro, caso a célula não exista é retornado um ponteiro vazio(nil), do contrário é retornado o estado daquela célula.

+ +
func (gol *GameOfLife) IsAliveOrNil(x, y int) *bool {
+	xOut := x < 0 || x > len(gol.values)-1
+	yOut := y < 0 || y > len(gol.values)-1
+
+	if xOut || yOut {
+		return nil
+	}
+	return &gol.values[x][y]
+}
+
+ +
+ +

Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas praticas e fora do mundinho web. Caso tenha alguma duvida ou sugestão, por favor entre em contato pelo GitHub ou e-mail. +thank you!

+ +
+
+
+ + + + \ No newline at end of file diff --git a/demo/2023/03/17/diffusion-automata.html b/demo/2023/03/17/diffusion-automata.html new file mode 100644 index 0000000..9fcf72f --- /dev/null +++ b/demo/2023/03/17/diffusion-automata.html @@ -0,0 +1,76 @@ + + + + + + + Diffusion Automata v0 + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

+ +

Diffusion Automata v0

+ + + +
+
+
+ + + + \ No newline at end of file diff --git a/demo/2023/03/24/diffusion-automata-v1.html b/demo/2023/03/24/diffusion-automata-v1.html new file mode 100644 index 0000000..1918f60 --- /dev/null +++ b/demo/2023/03/24/diffusion-automata-v1.html @@ -0,0 +1,204 @@ + + + + + + + Diffusion Automata v1 + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

+ +

Diffusion Automata v1

+ +

A ideia desse Automata é simular a dispersão de um +liquido em um meio solido permeável, como solo, areia, etc. +Ele foi criado como protótipo de um sistema de dispersão de +água subterrânea para meu jogo.

+ +

Como vai perceber, não existe muita complexidade nesse código, +essa é a magica desse tipo de algoritmo, com regras simples é +possível construir comportamentos complexos. Aqui, simulamos +a interação entre líquidos e sólidos no tempo e espaço usando apenas +aritmética básica.

+ +

Nosso espaço será representado como um 2d array de vetores, mas +no nosso caso eles servem apenas como uma forma conveniente de +agrupar nossos dois valores relevantes:

+ +
    +
  • Umidade +
      +
    • A quantidade de liquido contido naquela célula
    • +
    +
  • +
  • Impermeabilidade +
      +
    • A resistência que o material daquela célula apresenta ao movimento de liquido
    • +
    +
  • +
+ +

Os campos Rocks e Rain servem para demonstrar, respectivamente, +células totalmente impermeáveis e células que sao fontes de umidade.

+ +
type HumidityBoard struct {
+	values      [][]mgl32.Vec2 // [humidity, impermeability]
+	Rocks, Rain [][]bool
+	hvrX, hvrY  int
+}
+
+ +

A lógica para determinar a umidade de uma célula é bastante simples, +entendendo que ao longo do tempo o liquido tende a se espalhar uniformemente +pelo espaço, assumimos que o nosso valor de umidade da célula é a média aritmética +entre o seu valor atual e a das suas vizinhas. Por simplicidade assumimos apenas +4 vizinhos conforme esse diagrama onde v0 é a célula atual:

+ + + + + + + + + + + + + + + + + + + +
 v3 
v1v0v2
 v4 
+ +

Para considerar a permeabilidade, utilizamos uma média ponderada onde +o peso de cada termo é definido pelo valor de impermeabilidade daquela célula. +O detalhe é que consideramos o reciproco(1/valor) como peso das células vizinhas, +dessa forma conseguimos o efeito de que uma célula altamente impermeável tende +a não perder umidade ao mesmo tempo que resiste à absorção de mais liquido. Além +disso, verificamos se a célula excede o nosso limite de 1024 e ajustamos então o valor para esse limite.

+ +
func (ba *HumidityBoard) Update() error {
+	// Armazenamos o estado inicial do espaço para servir de referencia
+	m0 := make([][]mgl32.Vec2, len(ba.values))
+	copy(m0, ba.values)
+
+	for x, row := range ba.values {
+		for y, v0 := range row {
+			// Pulamos o calculo de fontes de umidade e células com alto impermeabilidade
+			if ba.Rain[x][y] || v0[1] >= (math.MaxFloat32/5)*4 {
+				continue
+			}
+
+			// Assumimos que as bordas são células secas e impermeáveis
+			v1 := mgl32.Vec2{0, math.MaxFloat32}
+			v2 := mgl32.Vec2{0, math.MaxFloat32}
+			v3 := mgl32.Vec2{0, math.MaxFloat32}
+			v4 := mgl32.Vec2{0, math.MaxFloat32}
+
+			// Verificamos se o vizinho existe e aplicamos os valores corretos
+			if x > 0 {
+				v1 = m0[x-1][y]
+			}
+			if x < len(m0)-1 {
+				v2 = m0[x+1][y]
+			}
+			if y > 0 {
+				v3 = m0[x][y-1]
+			}
+			if y < len(m0)-1 {
+				v4 = m0[x][y+1]
+			}
+
+			// Calculamos a média aritmética ponderada
+			r := ((v0[0] * (v0[1])) + (v1[0] / v1[1]) + (v2[0] / v2[1]) + (v3[0] / v3[1]) + (v4[0] / v4[1])) / (v0[1] + (1 / v1[1]) + (1 / v2[1]) + (1 / v3[1]) + (1 / v4[1]))
+
+			// Limitamos os valores a um máximo de 1024
+			if r > 1024 {
+				r = 1024
+			}
+
+			// Atualizamos espaço com novo valor de umidade
+			ba.values[x][y][0] = r
+		}
+	}
+	return nil
+}
+
+ +

O resultado no fim não é perfeito, há parâmetros que não são levados em consideração como +velocidade e densidade do liquido, mas para o nosso caso já é suficiente. Outra limitação +é quanto a conservação de massa do sistema. Aos poucos o volume total de umidade cai e isso +causa o efeito de umidade desaparecendo espontaneamente, que é fisicamente impossível.

+ +

Como dito, esse é um protótipo e limitações como essa não são necessariamente problemas +para aplicação em jogos. Vale lembrar que esse algoritmo foi escrito de forma síncrona, +mas é totalmente possível adapta-lo para operar de forma paralelizada.

+ +
+
+
+ + + + \ No newline at end of file diff --git a/demo/2023/04/07/tilemap-v0.html b/demo/2023/04/07/tilemap-v0.html new file mode 100644 index 0000000..eb8df36 --- /dev/null +++ b/demo/2023/04/07/tilemap-v0.html @@ -0,0 +1,115 @@ + + + + + + + TileMap Automata + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

+ +

TileMap Automata

+ +

Nessa demo utilizamos o mesmo Automata da demo diffusion-automata-v1, mas usamos um mapa do Tiled para renderizar o quadro. Além disso usamos um esquema simples de camera para permitir zoom(mouse wheel) e pan(middle button) do mapa, assim como adicionar(left button) e remover(right button) rochas do mapa.

+ +

Nossa struct então vai ser bastante simples, precisamos apenas do AUtomata e do TileMap:

+ +
type TileBoard struct {
+	tMap   *tiled.Map
+	b      *boards.HumidityBoard
+	cursor [2]int
+}
+
+ +

Durante o update apenas atualizamos o estado do automata e traduzimos esses estados para o TileMap. Se antes cada célula do nosso espaço correspondia a um pixel, aqui ele corresponde a um tile; uma cor corresponde a um tipo de tile e assim por diante.

+ +
func (tb *TileBoard) Update() error {
+	// Atualizamos o estado do Automato
+	err := tb.b.Update()
+	if err != nil {
+		return err
+	}
+
+	// Extraímos o novo estado
+	bState := tb.b.GetState()
+
+	width, height := tb.b.Size()
+	for x := 0; x < width; x++ {
+		for y := 0; y < height; y++ {
+			humidity, impermeability := bState[x][y].Elem()
+			// Aplicamos o valor da umidade na primeira camada
+			tb.tMap.Layers[0].Tiles[x+tb.tMap.Width*y] = &tiled.LayerTile{Tileset: tb.tMap.Tilesets[0], ID: uint32(humidity / 128)}
+			// Aplicamos o valor da impermeabilidade na segunda camada
+			tb.tMap.Layers[1].Tiles[x+tb.tMap.Width*y] = &tiled.LayerTile{Tileset: tb.tMap.Tilesets[1], ID: 838, Nil: impermeability < (math.MaxFloat32/5)*4}
+			// Atualizamos a posição do cursos na terceira camada
+			tb.tMap.Layers[2].Tiles[x+tb.tMap.Width*y] = &tiled.LayerTile{Tileset: tb.tMap.Tilesets[1], ID: 847, Nil: !(x == tb.cursor[0] && y == tb.cursor[1])}
+		}
+	}
+	return nil
+}
+
+ +
+
+
+ + + + \ No newline at end of file diff --git a/demo/2023/04/12/farm-v0.html b/demo/2023/04/12/farm-v0.html new file mode 100644 index 0000000..6cb6c97 --- /dev/null +++ b/demo/2023/04/12/farm-v0.html @@ -0,0 +1,82 @@ + + + + + + + Farm Demo v0 + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

+ +

Farm Demo v0

+ +
    +
  • W, A, S, D - Move
  • +
  • I - Interact
  • +
  • Mouse Wheel - Zoom
  • +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/demo/2023/05/05/goingo-wasm-demo.html b/demo/2023/05/05/goingo-wasm-demo.html new file mode 100644 index 0000000..440f8e4 --- /dev/null +++ b/demo/2023/05/05/goingo-wasm-demo.html @@ -0,0 +1,86 @@ + + + + + + + Goingo Wasm Demo + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

+ +

Goingo Wasm Demo

+ +
    +
  • Botão Esquerdo do Mouse +
      +
    • No tabuleiro - Coloca pedra
    • +
    • Na pedra - Mostrar grupo, liberdades e inimigos
    • +
    +
  • +
  • Botão Direto do Mouse - Passar o turno
  • +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/demos.html b/demos.html new file mode 100644 index 0000000..5203dcc --- /dev/null +++ b/demos.html @@ -0,0 +1,164 @@ + + + + + + + All Demos + + + + + + + + + + + + + + + + +
+
+ ../

All Demos

+
+
+ + + + \ No newline at end of file diff --git a/devlog-archive.html b/devlog-archive.html new file mode 100644 index 0000000..0a57b0a --- /dev/null +++ b/devlog-archive.html @@ -0,0 +1,56 @@ + + + + + + + All Devlogs + + + + + + + + + + + + + + + + +
+
+ ../

All Devlogs

+
+
+ + + + \ No newline at end of file diff --git a/devlog/2023/03/14/devlog-1.html b/devlog/2023/03/14/devlog-1.html new file mode 100644 index 0000000..68a1f15 --- /dev/null +++ b/devlog/2023/03/14/devlog-1.html @@ -0,0 +1,191 @@ + + + + + + + Devlog #1 - O Básico de Cellular Automata + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Devlog #1 - O Básico de Cellular Automata

+ +

+ + + # Introdução + + +

+ + +

Todos já tiveram essa experiência: O professor mostra um tópico novo de física ou matemática, alguém confuso pergunta. “Mas prof, onde que eu vou usar isso na minha vida”. A resposta podia variar, mas era sempre algo do tipo “vai cair na prova” ou “na engenharia vai precisar saber” e claro que ninguém se importava com nenhuma dessas coisas.

+ +

O que o professor esqueceu de falar é que existe uma coisa que depende de muito matemática e qualquer criança é fascinada: Video-Games. Vetores, matrizes, funções e o maldito teorema de Pitágoras, toda essa parafernália matemática que nos dão na escola é usada em todo lugar em jogos. O que me leva ao meu ponto, que outra forma melhor para praticar esses conceitos depois de anos longe de uma sala de aula?

+ +

Vamos tirar uma coisa do caminho, esse devlog não tem como objetivo fazer “marketing” para um jogo, talvez nunca saia um jogo pronto para o publico desse experiência, mas não faz mal o que importa aqui é aprender alguma coisa e talvez ajudar voce o seu jogo ou prova de calculo.

+

+ + + # O jogo + + +

+ + +

Mesmo sem saber onde vamos chegar, vale a pena ter pelo menos uma inspiração de por onde ir. Eu tenho vontade já a muito tempo de criar um jogo de fazenda onde o jogador precisa cuidar das culturas, mas também precisa gerenciar recursos como água, eletricidade, poluição, fertilidade do solo. Idealmente seria algo que pudesse dar a ele alguma intuição sobre agroecologia e gerenciamento de recursos naturais.

+ +

Essa já é uma montanha bem alta para subir e daqui de baixo eu não consigo ver exatamente por onde subir. Mas parece possível, mas com certeza vai ser bastante interessante. Mas precisamos +começar de algum lugar, pode ser qualquer lugar, que tal começar simulando a água?

+ +

So uma coisa antes disso, a engine que vamos usar aqui se chama Ebiten e é escrita em Go. O único motivo de usar ela é pela simplicidade e por gostar da linguagem, mas pode ficar tranquilo que os conceitos são aplicáveis em qualquer linguagem, engine ou aplicação.

+

+ + + # A água + + +

+ + +

Existe bons motivos para começar criando a água do nosso jogo: Primeiramente essa vai ser a mecânica principal do nosso jogo, assim como numa fazenda de verdade; Além disso, ela é uma daquelas coisas que voce entende empiricamente como funciona, mas explicar isso para um computador é outra história.

+ +

No futuro essa simulação de água pode seguir os modelos mais avançados de engenharia de solos e ser tão realista que a NASA vai usar nosso jogo para treinar os futuros fazendeiros de Marte. Até lá, podemos fazer algo que na minha opinião é a essência da computação gráfica: podemos fazer um truque para enganar o jogador. Vamos começar com um Autômato Celular, no +Grego: Cellular Automata

+

+ + + # Cellular Automata + + +

+ + +

Existem dezenas de fontes explicando o que esses algoritmos fazem, como surgiram e onde são utilizados, mas infelizmente muito pouco desse material esta disponível em português. Eu recomendo esse capítulo de dissertação que é bastante completo, mas também bastante acadêmico. Vamos resumir dessa forma:

+ +
Autômatos Celulares são algoritmos capazes simular sistemas complexos em larga escala a partir da definição de regras simples em pequena escala.
+
+ +

Entenda complexo ou simples como algo relacionado a previsibilidade do sistema, não necessariamente o quão de difícil é de modelar o sistema. O estoque de um produto em uma loja, distribuidora ou fabrica é um sistema simples, basta ver a diferença entre as entradas e saídas daquele estabelecimento. Agora o estoque desse mesmo produto em uma cidade é um sistema complexo que depende da contribuição de centenas de estabelecimentos interagindo entre si. A ideia desse tipo de autômato é simular cada estabelecimento conforme alguma regra e observar qual os efeitos na cidade como um todo.

+ +

Ok, agora como programamos isso$ Uma boa maneira de modelar esses sistemas é dividindo ele em 3 partes: Espaço, Comportamento e Estado. Onde a cada ciclo esse Espaço é alterado de acordo com o seu Estado, seguindo a lógica definida por um Comportamento. Mas vamos olhar cada uma com calma.

+

+ + + # Espaço + + +

+ + +

Esse é onde a simulação acontece, nada mais é que um conjunto discreto, ou um grupo de células. Esse nome complicado é apenas para diferenciar continuo, onde não há uma separação definida entre cada membro do conjunto. No exemplo anterior o nosso espaço seria a Cidade e as células seriam os estabelecimentos.

+ +

Qualquer espaço pode ser utilizado, desde que ele seja discreto. No nosso jogo, a terra onde a água vai se dispersar é continua, mas podemos facilmente representa-la de forma discreta definindo uma unidade que define e limita a minha célula. Posso determinar que cada célula no meu espaço equivale a 1m^2, assim o espaço que antes era continuo se torna discreto, podemos agora imaginar que um estado diz respeito as características de uma area especifica com essas dimensões.

+

+ + + # Estado + + +

+ + +

Esse é o que estamos simulado, é uma característica que varia a cada ciclo para cada célula, o estoque de produtos no nosso exemplo. Geralmente simulamos apenas um valor, mas nada impede que esse estado seja um conjunto de valores.

+ +

Uma coisa importante que precisa ser definida com clareza é quando esses estados vão ser atualizados. Isso porque, a depender da simulação, o estado de uma célula pode ser dependente de outra. É preciso observar qual o efeito desejado e agir de acordo, mas na maioria das vezes vamos trabalhar com uma ideia de frame, onde os estados de cada ciclo são segregados.

+ +

A ideia é tratar o estado geral das células após o calculo de um ciclo como uma fotografia, assim os novos estados são calculados a partir dos estados do ciclo anterior. Dessa forma temos menos chance de criar inconsistências e instabilidades na simulação

+

+ + + # Comportamento + + +

+ + +

Esse é como que nossa simulação vai funcionar, pode pensar como as regras que definem de que forma um estado se transforma em outro. Essa definição vai ser muito particular para o cenário que estamos tentando simular, o importante é ter em mente que o comportamento é definido por célula, não para todo o conjunto.

+

+ + + # Demos + + +

+ + +

Pode conferir um exemplo de implementação desses Autômatos em duas demos que eu criei. Inclusive com comentários sobre o código para ajudar voce a construir o seu próprio:

+ +
    +
  • Conway’s Game Of Life +
      +
    • Minha implementação do clássico Cellular Automata
    • +
    +
  • +
  • WIP - Diffusion Automata +
      +
    • Um protótipo do autômato implementado para simular a Água no nosso jogo(lembra que era esse o objetivo desse post?)
    • +
    +
  • +
+

+ + + # Conclusão + + +

+ + +

Ainda falta muito na implementação desse nosso jogo e mais para frente vamos abordar outros temas menos técnicos e com mais específicos. Mas ainda acho importante ter posts como esse pela falta de materiais de qualidade em português. Como o objetivo aqui é aprender codando, então nada mais justo.

+ +

No proximo post vamos falar mais especificamente sobre a simulação da água e como ela funciona, até lá, recomendo olhar as demos e analisar o código, os princípios são os mesmos para todos os Autômatos.


+ +

Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas praticas e fora do mundinho web. Caso tenha alguma duvida ou sugestão, por favor entre em contato pelo GitHub ou e-mail. +thank you!

+
+
+
+ + + + \ No newline at end of file diff --git a/devlog/2023/03/28/devlog-2.html b/devlog/2023/03/28/devlog-2.html new file mode 100644 index 0000000..65e08f5 --- /dev/null +++ b/devlog/2023/03/28/devlog-2.html @@ -0,0 +1,174 @@ + + + + + + + Devlog #2 - Uma simples simulação de fluidos + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Devlog #2 - Uma simples simulação de fluidos

+ +

+ + + # Introdução + + +

+ + +

No último devlog eu expliquei o que era um Cellular Automata e os seus princípios básicos, hoje vamos falar especificamente do autômato que criei para o jogo. Seria bom que tivesse lido o artigo anterior, mas se estiver com pressa, um pequeno resumo das 3 partes de um autômato celular:

+ +
    +
  • Espaço: Onde a simulação acontece
  • +
  • Estado: A propriedade do espaço que varia muda a cada ciclo
  • +
  • Comportamento: O conjunto de regras que define como o estado muda a cada ciclo
  • +
+ +

Feito a revisão, vamos ao problema.

+

+ + + # O problema + + +

+ + +

tilemap

+ +

Na imagem acima temos um exemplo de onde queremos chegar. No centro temos uma fonte de água, um rio nesse caso, e ao redor um terreno com vegetação, animais e a fazenda do jogador. Na imagem, cada tom de verde corresponde a um nível de umidade diferente, quando mais escuro, maior a umidade e vice versa.

+ +

Se olharmos o lado direito da imagem conseguimos perceber um claro gradiente de umidade entre o terreno mais próximo da fonte e o mais afastado. Já o lado esquerdo possui uma barreira de rochas que impede que a difusão da água de forma livre. Assim, vemos que a barreira mantém parte do terreno sem contato com a umidade e a outra fica mais úmida, pois a água não foi conseguiu transpor a barreira se acumula ali.

+ +

Outro aspecto que a imagem não mostra e que será essencial no nosso jogo é que essa umidade precisa ser determinada de forma dinâmica, ao longo da partida o estado do mapa muda e isso precisa ser refletido na cor e também nas propriedades daquele espaço.

+ +

No fim das contas o que queremos é simular o comportamento de um fluido, a água, se deslocando por um meio, o solo, e queremos que o resultado seja realista de alguma forma. Não é nenhuma tarefa impossível, mas é uma que com certeza é mais complicada do que parece.

+

+ + + # O jeito certo + + +

+ + +

Demonstração da Equação de Calor

+ +

O estado da arte em se tratado de simulações de dinâmicas de fluidos são as equações de Navier-Strokes, eu não vou nem começar a tentar explicar elas aqui, pois são um dos tópicos mais complexos que existe em simulações computadorizadas. Não só esse é um sistema não linear de derivadas parciais, mas matematicamente ainda não foi provado se essas equações são de fato contínuas em todos os casos. Eu não entendo exatamente o que essas coisas querem dizer, apenas repeti o que li para mostrar que não é um trabalho fácil lidar com esse método, por isso, não vamos usar ele.

+ +

Outro método que poderia ser usado para calcular essa dinâmica seria a equação do calor, que apesar do nome é capaz de expressar qualquer fenômeno que varie no espaço ao longo do tempo. Essa também é uma derivada parcial e mesmo sendo menos complexa não é um tópico simples, é o tipo de coisa que se aprende numa disciplina de cálculo, não num blog da internet.

+

+ + + # O jeito fácil + + +

+ + +

Now, Just pretend you're in the water

+ +

Aqui que o nosso automato se torna útil, lembram que o grande poder dessa técnica é ser capaz de criar sistemas complexos a partir de regras simples? É exatamente que vamos tentar fazer aqui, ao invés de utilizar essas equações complexas, vamos quebrar o problema em partes menores e assumir que nessa escala o comportamento é algo simples.

+ +

Se olharmos a figura da animação da equação do calor, o que acontece a groso modo é que as areas mais altas tendem a cair e as mais baixas a descer. Na realidade, o que acontece é que ao longo go tempo esse espaço tende a entrar em um estado de equilíbrio, onde o valor é o mesmo em todos os pontos. A água se move pelo meio até que a quantidade seja igual em cada ponto, mas a quantidade total de água continua sempre a mesma, ela apenas se redistribui. Se ignorarmos essa característica de conservação, podemos encontrar a um comportamento parecido apenas calculando a média aritmética entre um pontoe os seus vizinhos.

+ +

Só essa logica já é suficiente para modelar o lado direito do nosso mapa, assumindo que o rio tem uma umidade constante e que a grama subtrai uma quantidade específica de umidade a cada ciclo, o resultado é um gradiente como aquele que parte do rio e fica mais seco a medida que se afasta.

+ +

O lado esquerdo é um pouco mais complexo, mas também podemos utilizar a mesma média arimética, mas dessa vez utilizando a média ponderada, onde cada elemento tem um peso diferente no resultado final. A ideia é que possamos atribuir pesos diferentes de acordo com a permeabilidade do material, dando uma contribuição menor para pontos impermeáveis é equivalente a assumir que o material resiste a passagem da água.

+ +

Para completar, devemos diferenciar entre a permeabilidade do ponto de vista da própria célula ou de uma vizinha. Quando a célula que estamos calculando tem uma permeabilidade baixa, então o peso do seu estado atual será maior, visto que a célula tende a resistir a saída de água. Mas se essa mesma célula for observada para calcular uma vizinha, então o efeito é inverso, o peso será menor, pois nesse caso a tendência é que a vizinha não consiga absorver umidade dessa célula impermeável.

+ +

Podemos pensar nessa fórmula:

+ +\[H = \frac{H_{0}*I_{0} + \sum_{i=1}^{n}\frac{H_{i}}{I_{i}}}{I_{0}+\sum_{i=1}^{n}\frac{1}{I_{i}}}\] + +

Onde:

+ +\[H \Rightarrow \text{Umidade}\\ +I \Rightarrow \text{Impermeabilidade}\\ +n \Rightarrow \text{Quantidade de Vizinhos}\\\] +

+ + + # Demo + + +

+ + +

Já existe uma demo desse novo autômato no site, como da última vez eu deixei comentários sobre o código explicando os detalhes da implementação:

+ +
    +
  • Diffusion Automata v1 +
      +
    • Essa versão já inclui a lógica de impermeabilidade descrita nesse artigo. Ao clicar com o botão esquerdo é possível criar células impermeáveis e removê-las com o botão direito.
    • +
    +
  • +
  • Diffusion Automata v0 + -Essa é uma versão antiga que usa apenas média aritmética simples e não considera a permeabilidade, não há comentários sobre o código, mas ela existe mais a título de demonstração.
  • +
+

+ + + # Conclusão + + +

+ + +

Eu já tinha essa demo pronta há algum tempo e estava ansioso por escrever esse post, eu acho que ele é bastante simplório quanto ao potencial desse algoritmo, mas não sei como mostrar(e testar também) melhor essa funcionalidade sem ter um mapa de verdade para aplicar essas regras e ver os efeitos. O proximo post com certeza vai ser sobre tilemaps e tilesets, vai ser uma boa mudança de ritmo e será um material interessante para trabalhar com esses recursos tão úteis em gamedev.

+ +

Outra coisa que me deixou bastante ansioso essa semana era esse site em si. Eu fiz uma série de mudanças no layout e adicionei novas funcionalidades como internacionalização, LaTex e outras customizações. Para mim isso foi exaustante, frontend é a área que menos domino e tive bastante dificuldade com algumas coisas. Ainda não está perfeito, mas essa é a realidade desse tipo de coisa, sempre tem algo para se mudar. Dessa vez eu vou dar um tempo e dar mais atenção ao conteúdo em si, espere novidades a respeito em breve.


+ +

Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo GitHub ou e-mail.

+ +

thank you!

+
+
+
+ + + + \ No newline at end of file diff --git a/devlog/2023/04/12/devlog-3.html b/devlog/2023/04/12/devlog-3.html new file mode 100644 index 0000000..1ccd965 --- /dev/null +++ b/devlog/2023/04/12/devlog-3.html @@ -0,0 +1,115 @@ + + + + + + + Devlog #3 - TileMaps e StateMachines + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Devlog #3 - TileMaps e StateMachines

+ +

+ + + # Introdução + + +

+ + +

Eu demorei a escrever esse post porque achei que não havia nada de interessante a comentar nas demos que criei essas últimas semanas. Pensei em escrever então sobre porque acho isso e indicar alguns caminhos mais úteis para quem está fazendo algo parecido.

+

+ + + # Tilemaps + + +

+ + +

O jogo que estamos criando vai utilizar tilemaps, esse tipo de técnica é tão antiga que até o Super Nintendo já tinha hardware especializado para renderizar esses mapas. Não faltam materiais sobre esse assunto, nessa demo eu apenas fiquei na superfície, mas se quiser uma introdução bacana pode ler essa aqui.

+ +

Na demo eu fiz duas coisas interessantes de se notar:

+ +

Primeiro eu mapiei as células do nosso Diffusion Automata com os espaços do tilemap, assim assim eu pude usar a simulação para alterar qual tile deve ser mostrado em cada espaço.

+ +

Além disso, eu utilizei um arquivo .tmx do Tiled para gerar o estado inicial da simulação. Então essa demo acaba mostrando como extrair dados de tilemaps e como utilizar dados para alterá-los também.

+

+ + + # StateMachines + + +

+ + +

Diferente dos Autômatos Celulares, não falta material sobre Máquinas de Estado em português. Elas são matéria obrigatória em qualquer curso de Computação, Sistemas e as vezes até Administração. Por esse motivo eu não vou indicar nenhum material, você provavelmente vai encontrar bastante coisa no Google e pode garimpar o que mais lhe faz sentido. Caso esteja com preguiça, o artigo da Wikipedia é uma fonte rápida para se inteirar do assunto.

+ +

Na demo essa máquina foi utilizada para controlar qual o estado de cada hortinha. Quando o fazendeiro cria uma nova ela começa com o estado SECA, assim que ele rega essa horta ela passa para o estado MOLHADA. Uma vez nesse novo estado o fazendeiro não precisa mais interagir com a horta, a cada ciclo de tempo ela vai automaticamente crescer, mudando do EM_CRESCIMENTO_1 até EM_CRESCIMENTO_4.

+ +

Para demonstrar que esse tempo de crescimento é independente para cada hortinha, a cada nova criada o tempo aumenta. Caso interaja com uma horta totalmente crescida o fazendeiro pode colher, o que traz ela de volta para o estado SECA.

+ +

Não tenho código comentado para essa demo porque ela é baseada em uma biblioteca chamada stateless, não vale a pena explicar como ela funciona porque no seu caso pode estar utilizando uma ferramenta diferente. Existem centenas de formas de implementar essa solução, use a que faz mais sentido no seu caso.

+

+ + + # Conclusão + + +

+ + +

Esse post foi rápido, não tinha muito a dizer mas queria publicar logo antes do fim da semana. Na próxima semana eu não devo trabalhar em nenhuma demo ou no jogo, vou estar viajando para resolver alguns assuntos da minha mudança. Porém assim que voltar eu devo entrar de cabeça no desenvolvimento de novas demos. Em especial quero criar uma UI para navegar pelo mapa e interagir com os sistemas, também estou lendo um pouco sobre alguns design patterns para me ajudar a sobrepor esses sistemas, que é algo essencial para que tudo funcione em conjunto.

+ +

Deve demorar até meu próximo post, então não se assustem se só ouvirem falar de mim daqui um mês ou dois. Até lá, recomendo darem uma olhada na nova página de links que adicionei ao site, assim que achar algo interessante eu devo colocar ali.


+ +

Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo GitHub ou e-mail. +thank you!

+
+
+
+ + + + \ No newline at end of file diff --git a/devlog/en-us/2023/03/13/a-simple-manual-for-playtesters-with-imperial-ambitions.html b/devlog/en-us/2023/03/13/a-simple-manual-for-playtesters-with-imperial-ambitions.html new file mode 100644 index 0000000..1bdce5d --- /dev/null +++ b/devlog/en-us/2023/03/13/a-simple-manual-for-playtesters-with-imperial-ambitions.html @@ -0,0 +1,210 @@ + + + + + + + A Simple Manual for playtesters with Imperial Ambitions + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

A Simple Manual for playtesters with Imperial Ambitions

+ +

+ + + # Intro + + +

+ + +

The aim of this document is to serve as a guide for the players of the game Imperial Ambitions(Pre-alpha). The game still in development so many things can change over time and I’ll try to keep this guide updated. But feel free make suggestions and corrections, since this post is open-source, you can edit the file and make a pull request.

+ +

Also, remember to show some love for the developer at his/her(dont know) in the official discord

+

+ + + # The Basics + + +

+ + +

There are many actions you can performe at your turn, but we can put then in to 3 different types:

+ +
    +
  • War/Trade +
      +
    • Move units
    • +
    • Capture cities
    • +
    • Attack enemy units
    • +
    • Assemble parties
    • +
    +
  • +
  • Production +
      +
    • Convert raw resources into refined resources
    • +
    • Allocate workforce to different industries
    • +
    +
  • +
  • Recruitment/Training +
      +
    • Trade refined resources for work units
    • +
    • Trade refined resources for military units
    • +
    • Trade refined resources for trade units
    • +
    +
  • +
+

+ + + # War/Trade + + +

+ + +

War is made manipulating units in the world map. This is the main way to gather raw resources and workers. Every city you capture expands your area of influence, the resources markers in that area generate new resources every turn.

+ +

There are much more nuance on how and where to move your unit, also the way that you assemble and link parties can affect the power and maneuverability of your units. A more in-depth guide is available here, for the basics, keep in mind that:

+ +
    +
  • Conquering land is better than aimless battle
  • +
  • Unit positions don’t affect resource outcome, only influence over cities does.
  • +
  • Doesn’t matter how far your cities are, all the resources will be available in you capital.
  • +
+ +

[Talk about trade here]

+

+ + + # Production + + +

+ + +

Here is where you refine the raw resources into something useful, it’s managed at the industry panel. Every industry requires labour, resources and time to generate goods, for example:

+ +
    +
  • 1 fish + 1 wheat + 2 labour = 2 food per turn
  • +
  • 2 trees + 2 labour = 1 lumber per turn
  • +
+ +

All the produced good will be at the warehouse at the beginning of the next turn and will persist if not used. The same goes to gathered resources, so even if you control a city for a couple ou turns, the already gathered resources are not lost with the city.

+ +

We have already seen that raw resources are gathered from conquered cities, labour is also gathered fro cities, but not every worker in equal. Any worker is able to act in any industry, but the more specialized it is, higher is there labour capacity.

+ +
    +
  • Slave/Peasant = 1 labour per turn
  • +
  • Artisan = 2 labour per turn
  • +
  • +
+ +

Keep in mind that idle workers still need food, so try to use all the available labour at each turn. Differently from resources and good, you cant stock labour and needs to utilize it or it will be lost.

+

+ + + # Recruitment/Training + + +

+ + +

To be able to perform the game actions in a efficienty matter you need to improve your available units. This is essencial for expanding while keeping your cities safe and feed.

+ +
    +
  • Recruiting new Military units allows you to: +
      +
    • Place defences on strategic cities
    • +
    • Reinforce armies on though battles
    • +
    • Expand the reach of your empire
    • +
    • Protect merchants on their journeys
    • +
    +
  • +
  • Recruiting new Work units allows you to: +
      +
    • Produce more with at a lower cost
    • +
    • Maintain small cities feed while you gather rare resources
    • +
    • Helps you keep the level of production as your population retires(or dies)
    • +
    +
  • +
  • Recruiting new Trade units allows you to: +
      +
    • [Trade?]
    • +
    +
  • +
+

+ + + # References + + +

+ + +

This is the definition of the game by Aoiti(The Developer)

+ +
Imperial Ambitions will be a 4X strategy game where the players will take over one of the European superpowers that existed during the age of discovery (1500-1600s). 
+
+The game has two core aspects;
+1. Parties. 
+Parties are formed by combinations of,
+explorers, scientists, spies, diplomats, crime lords, archeologists, merchants, engineers, missionaries, generals, admirals and soldiers
+
+With these parties, the player will,
+Discover Americas, Battle, Espionage, Trade goods, Perform diplomacy, Set up crime syndicates, Sabotage etc
+
+2. Economics.
+There will be many types of raw and processed goods. The player needs to establish working production chains by allocating its laborer force to keep up against other industrializing nations.
+
+Other features are a black market system and column formation for moving armies 
+
+
+
+
+ + + + \ No newline at end of file diff --git a/devlog/study/2023/04/05/a-vscode-extension.html b/devlog/study/2023/04/05/a-vscode-extension.html new file mode 100644 index 0000000..310d828 --- /dev/null +++ b/devlog/study/2023/04/05/a-vscode-extension.html @@ -0,0 +1,174 @@ + + + + + + + Lecture Timer - Minha primeira extensão do VSCode + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Lecture Timer - Minha primeira extensão do VSCode

+ +

+ + + # Introdução + + +

+ + +

Depois de um tempo trabalhando com desenvolvimento web, e agora com a esfriada no mercado, eu decidi que é hora de voltar para a faculdade. Quem lê o blog percebe que o que eu mais quero é encontrar algum desafio que me deixe o mais longe possível de dessas tecnologias. Por isso criei uma extensão usando JS+HTML+CSS para o VSCode.

+ +

Essa ironia vai se explicar em breve, em resumo, é o jeito que a Microsoft escolheu para tornar o desenvolvimento de extensões mais “simples” no VSCode. Mas o que isso tem a ver com voltar para a faculdade? Bem deixa eu explicar o problema:

+

+ + + # Minhas notas horrendas + + +

+ + +

I don't understand anything

+ +

Já teve a experiencia de estudar para uma prova, voltar para as suas anotações e não fazer ideia do que se tratam? Eu tenho um pouco de dislexia, sou prolixo na hora de me expressar, e para piorar, sou a única pessoa que conheço a ter reprovado nas aulas de caligrafia. Quando me concentrava para anotar, me perdia na aula, quando fazia na pressa, não entendia nada do que escrevi. O resultado era um caderno cheio de notas confusas e feias de uma aula que eu já não lembrava sobre o que era.

+ +

Escutar as gravações das aulas acabava sendo a solução, ainda mais depois da pandemia, esse material virou essencial nos meus estudos já que eu poderia pausar, voltar e dar a atenção necessária para cada parte. Minhas notas ficaram muito mais organizadas e úteis, fui tão bem que consegui aprender a programar, fui empregado na área e acabei deixando a faculdade. Mas tem um aspecto desse processo que eu preciso resolver para ter alguma vida além dos estudos.

+ +

Gravações são ótimas, mas não são fáceis de encontrar o que está procurando. Em um texto você consegue usar o famoso Ctrl+F e procurar o que precisa, mesmo em um livro é muito fácil sublinhar e marcar páginas para voltar depois. Em um arquivo de audio ou video não é possível fazer algo assim, o que eu acabava fazendo era anotar a minutagem e uma frase ao lado para tentar me achar depois, quase sempre sem sucesso.

+ +

O problema não era tanto o método, mas o fato de ele ser trabalhoso e ineficiente. Para anotar uma minutagem era necessário pausar e escrever o exata valor, depois para retornar era preciso encontrar o segundo exato na linha. Sem falar que era impossível fazer algo assim durante a gravação de uma aula, coisa que vai ser essencial agora com aulas presenciais. Eu precisava de alguma ferramenta que me ajudasse a usar essa técnica e é isso que a minha extensão faz.

+

+ + + # Anotando em tempo real + + +

+ + +

Typing while shit burn in front of you

+ +

A ideia que eu tive é de uma ferramenta que me permitisse:

+ +
    +
  1. Anotar minutagens com apenas um click
  2. +
  3. Navegar rapidamente entre as anotações e o arquivo de video ou audio
  4. +
  5. Sincronizar anotações feitas em aula com feitas posteriormente
  6. +
  7. Permitisse marcar e encontrar facilmente os trechos da aula que mais interessam
  8. +
+ +

Em outras palavras, eu queria alguma forma de rabiscar meus arquivos de audio da mesma forma que um texto ou livro, para isso eu precisava dar uma interface visual para esse audio. Que lugar melhor para começar que pelo Visual Studio Code, trocadilhos a parte o que pensei de fazer foi criar um arquivo de texto que pudesse conter toda as minhas anotações. O VSCode entra como uma boa opção de editor, não só pela capacidade de extensão, mas também porque é o editor de texto que uso diariamente e já estou acostumado.

+ +

Escrever a extensão não foi fácil, mas admito que depois de um pouco de esforço a coisa passa a fazer mais sentido. Eu queria poder dizer que a minha falta de experiencia e, em geral, ódio pelo JavaScript foram as causas dos meus problemas, mas nem foi tão esse o caso. O que mais complica é o design adotado pela Microsoft, a API parece uma grande sopa de decisões impulsivas e a documentação exige que você leia tudo com muita calma para não perder nenhum detalhe. De todo o material que usei, os que eu recomendo para quem quiser tentar essa empreitada são a documentação oficial, principalmente os exemplos, e esse video de quase 4 horas. Não se incomode com o comprimento, a melhor parte desse tutorial é que conseguimos acompanhar ele debugando certas coisas que são importantíssimas, mas que raramente aparecem nos outros tutoriais.

+

+ + + # Ok, mas o que essa extensão faz? + + +

+ + +

Antes de tudo, vamos precisar de um arquivo .md com um frontmatter preenchido com alguns dados, a extensão já vem com um snippet chamado lecture-timer.initTimer que vai criar algo assim:

+ +
---
+lecture:
+  title: "My Title"
+  file: "example.mp3" # Opcional
+  duration: 120       # Opcional
+---
+
+ +

Isso é tudo que precisamos para começar, o campo file é opcional e caso fique em branco a extensão funcionará como um timer simples. Alternativamente você pode utilizar um campo duration para especificar o limite de tempo do seu timer. Clique no ícone da extensão na barra lateral para abrir o painel.

+ +

Lecture Timer Panel

+ +

Os controles na parte superior funcionam como você espera: tocar, pausar, parar, avançar, retroceder, etc. Eles servem tanto para operar os timers quanto navegar pelo audio. Na parte inferior temos os timestamps(ou minutagens) registradas no nosso arquivo, clicando em cada um ou usando as botões conseguimos navegar por eles no texto. Adicionamos novos usando os seguintes marcadores no texto:

+ +
<!-- Marcador vazio -->
+:lec-timer{time="3.774" preview="00:00:03" type="alone"}
+
+<!-- Marcador com conteúdo inline -->
+:lec-timer[content]{time="3.774" preview="00:00:03" type="inline"}
+
+<!-- Marcador de bloco -->
+:::lec-timer{time="3.774" preview="00:00:03" type="block"}
+multi
+line
+content
+:::
+
+ +

Não é necessário saber digitar esses marcadores inteiros, a extensão adiciona um novo comando para isso, basta utilizar Ctrl+Shift+P para abrir a palheta comandos e procurar por lecture-timer.stampMarker. Com ele você consegue adicionar a minutagem e caso tenha algum texto selecionado ele já formata corretamente o seu conteúdo dentro do marcador. Uma dica que eu dou é definir um atalho do teclado para esse comando que até mais fácil de usar.

+ +

A syntax desses marcadores também é proposital, eles respeitam a proposta de Generic Directives e podem facilmente ser parceados para html utilizando um plugin como markdown-it-directive. Inclusive é esse o plugin que utilizei para renderizar os marcadores no preview do markdown:

+ +

Lecture Timer Preview

+ +

Essas são as funcionalidades até agora, não são muitas mas já é o suficiente para começar a utilizar.

+

+ + + # Conclusão + + +

+ + +

Eu devo continuar a adicionar funcionalidades e remover bugs no futuro, ainda quero dar suporte a arquivos de video e conteúdo online. Além disso ainda tem algumas coisas de qualidade de vida que eu acredito serem necessárias, mas ainda quero testar mais na prática para ter certeza.

+ +

Caso esteja interessado, já pode instalar a versão em pre-release no seu VSCode. Sugestões e bugs podem ser enviados para o repositório, assim como contribuições caso queira dar uma força.

+ +

Esse era um dos projetos que me desafiei a terminar antes do começo das aulas da UFRGS em Maio, já vou riscar esse da lista. O outro era uma ferramenta para extrair comentários do código Go, essa já existe e funciona, mas preciso fazer um post como esse aqui no blog para dar como encerrado também e o tempo está acabando.

+ +

Depois disso devo voltar ao regime normal de posts sobre gamedev, já tenho uma demo nova e estou animado para começar a dar forma ao nosso jogo. Porém eu tenho certeza que vamos ter um hiato em breve para eu poder dar conta da minha mudança de cidade e me aclimatar na nova rotina. Não tenho também muita certeza de quanto tempo livre vou ter para me dedicar a projetos como estes, sobre isso só o futuro dirá.


+ +

Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo GitHub ou e-mail. +thank you!

+
+
+
+ + + + \ No newline at end of file diff --git a/devlog/study/2023/05/25/extension-follow-up.html b/devlog/study/2023/05/25/extension-follow-up.html new file mode 100644 index 0000000..c17291a --- /dev/null +++ b/devlog/study/2023/05/25/extension-follow-up.html @@ -0,0 +1,125 @@ + + + + + + + Follow up da extensão + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Follow up da extensão

+ +

+ + + # Introdução + + +

+ + +

Faz quase um ano desde quando eu criei a minha extensão com o intuito de me ajudar a estudar. Obviamente muita coisa aconteceu e eu estou aqui de volta para comentar o que deu certo, o que não funcionou e quais os próximos passos dessa solução. Já digo que o fato de ter pensado nessa extensão antes de ter começado as aulas mais me atrapalhou que ajudou, já explico.

+ +

Logo nas primeiras vezes que tentei utilizar o software já me deparei com o problema que muitos professores não permitem que suas aulas sejam gravadas. Isso é muito efeito do “Escola sem Partido” aqui no Brasil, mesmo os que nao se preocupam com o conteúdo das aulas de divulgado resistem pois tem medo que algo que digam seja tirado de contexto. Tentar vencer essa questão é uma batalha perdida, até porque mesmo quando pude gravar, não consegui usar o software como esperava.

+ +

Uma crítica que eu preciso fazer a mim mesmo é que eu superestimei a minha necessidade de fazer notas durante as aulas. Foram poucos os momentos que eu quis escrever algo e quando escrevi algo sempre perdia o foco na aula. Talvez para outros s ja diferente, mas eu me senti incapaz de prestar atenção nas duas coisas ao mesmo tempo.

+ +

No fim das contas a parte que mais útil desse sistema todo não depende tanto da extensão em si, que é a capacidade de anotar documentos temporais, comp audios e vídeos. Isso porém ainda depende de uma implementação mais robusta e direcionada com o intuito de trabalhar com QDA(Análise de Dados Qualitativos)

+

+ + + # Mas não apenas isso + + +

+ + +

No fim eu acabei percebendo que a defazagem de ferramentas para uso acadêmico é grande. Há uma grande dependência de softwares proprietários, como NVivo, MS Office e Adobe Acrobat que barram o acesso pesquisadores pobres e exclui usuários do Linux cono eu. Além disso, tal realidade gera limitações e barreiras que impedem o livre exercício do que é o objetivo central do trabalho universitário: gerar conhecimento

+ +

O trabalho científico depende de um ambiente aberto, flexível e troca constante para o seu desenvolvimento pleno. A cobrança de licenças abusivas, muitas vezes atreladas a instituições inteiras, impede que pesquisadores explorem possibilidades de análise que vão além das capacidades desses softwares. A falta de transparência desses sistemas também promove uma barreira para a analise crítica dos resultados obtidos por esses softwares.

+ +

A interoperabilidade entre estes sistemas também se mostra um desafio, por depender muitas vezes de padrões proprietários de arquivos e complexificar desnecessariamente representações, o transporte de dados de uma aplicação para outra é quase impossível. No mundo do desenvolvimento é inegável a versatilidade que arquivos baseados em texto plano(.md e .csv por exemplo), sendo a base de diversas tecnologias como Git, Jupyter Notebooks e os próprios códigos fonte de qualquer qualquer linguagem de programação. Essa complexidade extra acaba servindo apenas aos propósitos dos criadores das ferramentas que conseguem mais flexibilidade para armazenar dados nesses arquivos, ao mesmo tempo que impedem usuários de transportas seus dados e trabalhos para uma plataforma concorrente.

+

+ + + # Ferramentas + + +

+ + +

Ao longo do tempo eu pude reunir algumas ferramentas abertas que atendem parte do trabalho acadêmico que preciso executar e as reuni na lista abaixo. Meu plano é atualizá-la a medida que mais necessidades e ferramentas apareçam, aconselho que retorne aqui com frequência para acompanhar essa jornada.

+ +
    +
  • Gerenciador de textos e bibliografia +
      +
    • Zotero
    • +
    +
  • +
  • Controle de tarefas
  • +
  • Assistente de citações +
      +
    • Zotero
    • +
    • Quarto
    • +
    +
  • +
  • Leitor de PDF com anotações
  • +
  • Renderização de Markdown e Latex +
      +
    • Quarto
    • +
    +
  • +
  • Editor de mapa mental/Conceitual
  • +
  • Ferramentas de transmissão remota
  • +
  • Gerenciador de escrita colaboratira +
      +
    • Git
    • +
    +
  • +
  • Ferramentas de analise quantitativa e qualitativa
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/en-us-archive.html b/en-us-archive.html new file mode 100644 index 0000000..7a38ee8 --- /dev/null +++ b/en-us-archive.html @@ -0,0 +1,41 @@ + + + + + + + All in English + + + + + + + + + + + + + + + + +
+
+ ../

All in English

+
+
+ + + + \ No newline at end of file diff --git a/en/404.html b/en/404.html new file mode 100644 index 0000000..74ccfc0 --- /dev/null +++ b/en/404.html @@ -0,0 +1,44 @@ + + + + + + + 404 + + + + + + + + + + + + + + + + +
+
+

404

+ +

Vincent Vega Lost

+ +

Page not found! :( +Go Back

+ +
+
+ + + + \ No newline at end of file diff --git a/en/LICENSE b/en/LICENSE new file mode 100644 index 0000000..4ea99c2 --- /dev/null +++ b/en/LICENSE @@ -0,0 +1,395 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/en/README.md b/en/README.md new file mode 100644 index 0000000..0880a4d --- /dev/null +++ b/en/README.md @@ -0,0 +1,239 @@ + + +# GitHub Pages + +_Create a site or blog from your GitHub repositories with GitHub Pages._ + + + +
+

Welcome

+ +With GitHub Pages, you can host project blogs, documentation, resumes, portfolios, or any other static content you'd like. Your GitHub repository can easily become its own website. In this course, we'll show you how to set up your own site or blog using GitHub Pages. + +- **Who is this for**: Beginners, students, project maintainers, small businesses. +- **What you'll learn**: How to build a GitHub Pages site. +- **What you'll build**: We'll build a simple GitHub Pages site with a blog. We'll use [Jekyll](https://jekyllrb.com), a static site generator. +- **Prerequisites**: If you need to learn about branches, commits, and pull requests, take [Introduction to GitHub](https://github.com/skills/introduction-to-github) first. +- **How long**: This course is five steps long and takes less than one hour to complete. + +## How to start this course + +1. Right-click **Start course** and open the link in a new tab. +
[![start-course](https://user-images.githubusercontent.com/1221423/218596841-0645fe1a-4aaf-4f51-9ab3-8aa2d3fdd487.svg)](https://github.com/skills/github-pages/generate) +2. In the new tab, follow the prompts to create a new repository. + - For owner, choose your personal account or an organization to host the repository. + - We recommend creating a public repository—private repositories will [use Actions minutes](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions). + ![Create a new repository](https://user-images.githubusercontent.com/1221423/218594143-e60462b6-9f2a-4fa3-80de-063ac5429aab.png) +3. After your new repository is created, wait about 20 seconds, then refresh the page. Follow the step-by-step instructions in the new repository's README. + +
+ + + +
+

Step 1: Enable GitHub Pages

+ +_Welcome to GitHub Pages and Jekyll :tada:!_ + +The first step is to enable GitHub Pages on this [repository](https://docs.github.com/en/get-started/quickstart/github-glossary#repository). When you enable GitHub Pages on a repository, GitHub takes the content that's on the main branch and publishes a website based on its contents. + +### :keyboard: Activity: Enable GitHub Pages + +1. Open a new browser tab, and work on the steps in your second tab while you read the instructions in this tab. +1. Under your repository name, click **Settings**. +1. Click **Pages** in the **Code and automation** section. +1. Ensure "Deploy from a branch" is selected from the **Source** drop-down menu, and then select `main` from the **Branch** drop-down menu. +1. Click the **Save** button. +1. Wait about _one minute_, then refresh this page for the next step. + > Turning on GitHub Pages creates a deployment of your repository. GitHub Actions may take up to a minute to respond while waiting for the deployment. Future steps will be about 20 seconds; this step is slower. + > **Note**: In the **Pages** of **Settings**, the **Visit site** button will appear at the top. Click the button to see your GitHub Pages site. + +
+ + + +
+

Step 2: Configure your site

+ +_You turned on GitHub Pages! :tada:_ + +We'll work in a branch, `my-pages`, that I created for you to get this site looking great. :sparkle: + +Jekyll uses a file titled `_config.yml` to store settings for your site, your theme, and reusable content like your site title and GitHub handle. You can check out the `_config.yml` file on the **Code** tab of your repository. + +We need to use a blog-ready theme. For this activity, we will use a theme named "minima". + +### :keyboard: Activity: Configure your site + +1. Browse to the `_config.yml` file in the `my-pages` branch. +1. In the upper right corner, open the file editor. +1. Add a `theme:` set to **minima** so it shows in the `_config.yml` file as below: + ```yml + theme: minima + ``` +1. (optional) You can modify the other configuration variables such as `title:`, `author:`, and `description:` to further customize your site. +1. Commit your changes. +1. (optional) Create a pull request to view all the changes you'll make throughout this course. Click the **Pull Requests** tab, click **New pull request**, set `base: main` and `compare:my-pages`. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Step 3: Customize your homepage

+ +_Nice work setting the theme! :sparkles:_ + +You can customize your homepage by adding content to either an `index.md` file or the `README.md` file. GitHub Pages first looks for an `index.md` file. Your repository has an `index.md` file so we can update it to include your personalized content. + +### :keyboard: Activity: Create your homepage + +1. Browse to the `index.md` file in the `my-pages` branch. +1. In the upper right corner, open the file editor. +1. Type the content you want on your homepage. You can use Markdown formatting on this page. +1. (optional) You can also modify `title:` or just ignore it for now. We'll discuss it in the next step. +1. Commit your changes to the `my-pages` branch. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Step 4: Create a blog post

+ +_Your home page is looking great! :cowboy_hat_face:_ + +GitHub Pages uses Jekyll. In Jekyll, we can create a blog by using specially named files and frontmatter. The files must be named `_posts/YYYY-MM-DD-title.md`. You must also include `title` and `date` in your frontmatter. + +**What is _frontmatter_?**: The syntax Jekyll files use is called YAML frontmatter. It goes at the top of your file and looks something like this: + +```yml +--- +title: "Welcome to my blog" +date: 2019-01-20 +--- +``` + +For more information about configuring front matter, see the [Jekyll frontmatter documentation](https://jekyllrb.com/docs/frontmatter/). + +### :keyboard: Activity: Create a blog post + +1. Browse to the `my-pages` branch. +1. Click the `Add file` dropdown menu and then on `Create new file`. +1. Name the file `_posts/YYYY-MM-DD-title.md`. +1. Replace the `YYYY-MM-DD` with today's date, and change the `title` of your first blog post if you'd like. + > If you do edit the title, make sure there are hyphens between your words. + > If your blog post date doesn't follow the correct date convention, you'll receive an error and your site won't build. For more information, see "[Page build failed: Invalid post date](https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/troubleshooting-jekyll-build-errors-for-github-pages-sites)". +1. Type the following content at the top of your blog post: + ```yaml + --- + title: "YOUR-TITLE" + date: YYYY-MM-DD + --- + ``` +1. Replace `YOUR-TITLE` with the title for your blog post. +1. Replace `YYYY-MM-DD` with today's date. +1. Type a quick draft of your blog post. Remember, you can always edit it later. +1. Commit your changes to your branch. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Step 5: Merge your pull request

+ +_Nice work, friend :heart:! People will be reading your blog in no time!_ + +You can now [merge](https://docs.github.com/en/get-started/quickstart/github-glossary#merge) your pull request! + +### :keyboard: Activity: Merge your changes + +1. Merge your changes from `my-pages` into `main`. If you created the pull request in step 2, just open that PR and click on **Merge pull request**. If you did not create the pull request earlier, you can do it now by following the instructions in step 2. +1. (optional) Delete the branch `my-pages`. +1. Wait about 20 seconds then refresh this page for the next step. + +
+ + + +
+

Finish

+ +_Congratulations friend, you've completed this course!_ + +celebrate + +Your blog is now live and has been deployed! + +Here's a recap of all the tasks you've accomplished in your repository: + +- You enabled GitHub Pages. +- You selected a theme using the config file. +- You learned about proper directory format and file naming conventions in Jekyll. +- You created your first a blog post with Jekyll! + +### What's next? + +- Keep working on your GitHub Pages site... we love seeing what you come up with! +- We'd love to hear what you thought of this course [in our discussion board](https://github.com/skills/.github/discussions). +- [Take another GitHub Skills course](https://github.com/skills). +- [Read the GitHub Getting Started docs](https://docs.github.com/en/get-started). +- To find projects to contribute to, check out [GitHub Explore](https://github.com/explore). + +
+ + + +--- + +Get help: [Post in our discussion board](https://github.com/skills/.github/discussions) • [Review the GitHub status page](https://www.githubstatus.com/) + +© 2022 GitHub • [Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/code_of_conduct.md) • [CC-BY-4.0 License](https://creativecommons.org/licenses/by/4.0/legalcode) diff --git a/en/archive.html b/en/archive.html new file mode 100644 index 0000000..b7d6ca4 --- /dev/null +++ b/en/archive.html @@ -0,0 +1,53 @@ + + + + + + + All Posts + + + + + + + + + + + + + + + + +
+
+ ../

All Posts

+
+
+ + + + \ No newline at end of file diff --git a/en/assets/css/main.css b/en/assets/css/main.css new file mode 100644 index 0000000..2c69eec --- /dev/null +++ b/en/assets/css/main.css @@ -0,0 +1 @@ +.highlight table td{padding:5px}.highlight table pre{margin:0}.highlight,.highlight .w{color:#49483e}.highlight .err{color:#272822;background-color:#f92672}.highlight .c,.highlight .ch,.highlight .cd,.highlight .cm,.highlight .cpf,.highlight .c1,.highlight .cs{color:#75715e}.highlight .cp{color:#f4bf75}.highlight .nt{color:#f4bf75}.highlight .o,.highlight .ow{color:#f8f8f2}.highlight .p,.highlight .pi{color:#f8f8f2}.highlight .gi{color:#a6e22e}.highlight .gd{color:#f92672}.highlight .gh{color:#66d9ef;background-color:#272822;font-weight:bold}.highlight .k,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kv{color:#ae81ff}.highlight .kc{color:#fd971f}.highlight .kt{color:#fd971f}.highlight .kd{color:#fd971f}.highlight .s,.highlight .sb,.highlight .sc,.highlight .dl,.highlight .sd,.highlight .s2,.highlight .sh,.highlight .sx,.highlight .s1{color:#a6e22e}.highlight .sa{color:#ae81ff}.highlight .sr{color:#a1efe4}.highlight .si{color:#cc6633}.highlight .se{color:#cc6633}.highlight .nn{color:#f4bf75}.highlight .nc{color:#f4bf75}.highlight .no{color:#f4bf75}.highlight .na{color:#66d9ef}.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .il,.highlight .mo,.highlight .mx{color:#a6e22e}.highlight .ss{color:#a6e22e}body[a="dark"]{filter:invert(1)}body[a="dark"] img{filter:invert(1)}body[a="dark"] img.ioda{filter:invert(0)}body[a="dark"] iframe{filter:invert(1)}@media (prefers-color-scheme: dark){body[a="auto"]{filter:invert(1)}body[a="auto"] img{filter:invert(1)}body[a="auto"] img.ioda{filter:invert(0)}body[a="auto"] iframe{filter:invert(1)}}html,body{background:white}html{height:100%}body{color:black;font-family:monospace;font-size:16px;line-height:1.4;margin:0;min-height:100%;overflow-wrap:break-word}.post-meta{text-align:right}h2,h3,h4,h5,h6{margin-top:3rem}hr{margin:2rem 0}p{margin:1rem 0}.languages{text-align:right}li{margin:0.4rem 0}*:target{background:yellow}.w{max-width:640px;margin:0 auto;padding:4rem 2rem}hr{text-align:center;border:0}hr:before{content:"/////"}hr:after{content:attr(data-content) "/////"}table{width:100%}table,th,td{border:thin solid black;border-collapse:collapse;padding:0.4rem}code{color:white;background:black}div.highlighter-rouge code{display:block;overflow-x:auto;white-space:pre-wrap;padding:1rem;tab-size:1rem}blockquote{font-style:italic;border:thin solid black;padding:1rem}blockquote p{margin:0}img{max-width:100%;display:block;margin:0 auto}a.h-anchor{opacity:.2;font-size:80%}a.h-anchor:hover{opacity:1} diff --git a/en/demo/2023/03/24/diffusion-automata-v1.html b/en/demo/2023/03/24/diffusion-automata-v1.html new file mode 100644 index 0000000..7e8c92a --- /dev/null +++ b/en/demo/2023/03/24/diffusion-automata-v1.html @@ -0,0 +1,205 @@ + + + + + + + Diffusion Automata v1 + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + + pt-br + + + + + en + + +

+ +

Diffusion Automata v1

+ +

The goal for this Automata is to simulate the diffusion of +a liquid on a solid medium, like soil, sand, etc. It was created +as a prototype of a underground water diffusion for my game.

+ +

As will notice, there isn’t much complexity in this code, that’s the magic +of this kind of algorithm, we can use simple rules to create complex +behavior. Here, we simulate the interaction between liquids ans solids +over time and space using basic arithmetic

+ +

Our board will be represented by a 2d array of vectors, this is just +for convenience since we can easily group the two relevant values:

+ +
    +
  • Humidity +
      +
    • The amount of liquid within the cell
    • +
    +
  • +
  • Impermeability +
      +
    • The resistance of the cell to the movement of liquid trough it
    • +
    +
  • +
+ +

The fields Rocks and Rain just represent cells that are totally impermeable +or sources of humidity, respectively.

+ +
type HumidityBoard struct {
+	values      [][]mgl32.Vec2 // [humidity, impermeability]
+	Rocks, Rain [][]bool
+	hvrX, hvrY  int
+}
+
+ +

The logic to determine the humidity of a cell is simples, since the liquid +converges to a uniform distribution over time for all the space, we assume +that the new value of humidity of a cell is just the mean between it and +their neighbors values. For simplicity, we only count 4 neighbors as the +diagram below, where v0 is the current cell:

+ + + + + + + + + + + + + + + + + + + +
 v3 
v1v0v2
 v4 
+ +

To include permeability properties, we use a weighted mean where each +factor is defined by that cell impermeability. The catch is that we use +the inverse(1/value) for neighboring cells, that way we achieve the effect +of a highly impermeable cell resisting either losing or gaining humidity. +Then we clamp to new value to a max of 1024.

+ +
func (ba *HumidityBoard) Update() error {
+	// Store the initial state as reference
+	m0 := make([][]mgl32.Vec2, len(ba.values))
+	copy(m0, ba.values)
+
+	for x, row := range ba.values {
+		for y, v0 := range row {
+			// Skip the calculations for humidity sources and impermeable cell
+			if ba.Rain[x][y] || v0[1] >= (math.MaxFloat32/5)*4 {
+				continue
+			}
+
+			// Assume that borders are dry and impermeable
+			v1 := mgl32.Vec2{0, math.MaxFloat32}
+			v2 := mgl32.Vec2{0, math.MaxFloat32}
+			v3 := mgl32.Vec2{0, math.MaxFloat32}
+			v4 := mgl32.Vec2{0, math.MaxFloat32}
+
+			// Verify if neighbor exists and use their value
+			if x > 0 {
+				v1 = m0[x-1][y]
+			}
+			if x < len(m0)-1 {
+				v2 = m0[x+1][y]
+			}
+			if y > 0 {
+				v3 = m0[x][y-1]
+			}
+			if y < len(m0)-1 {
+				v4 = m0[x][y+1]
+			}
+
+			// Calculate the weighted mean
+			r := ((v0[0] * (v0[1])) + (v1[0] / v1[1]) + (v2[0] / v2[1]) + (v3[0] / v3[1]) + (v4[0] / v4[1])) / (v0[1] + (1 / v1[1]) + (1 / v2[1]) + (1 / v3[1]) + (1 / v4[1]))
+
+			// Clamp values to 1024
+			if r > 1024 {
+				r = 1024
+			}
+
+			// Updates board with new humidity value
+			ba.values[x][y][0] = r
+		}
+	}
+	return nil
+}
+
+ +

The final result is not perfect, there are parameters that are not accounted like velocity +and density of the liquid, but it’s sufficient for our porpoises. Another limitation of this +method is lack of conservation of mass. As the simulation evolves the humidity spontaneously +drops, which is physically impossible.

+ +

As stated previous, this is a prototype and limitation as this are not necessarily concerns +for games development. Keep in mind that this algorithm is synchronous, but it’s totally +possible to paralelize it.

+ +
+ +

Hope you liked this material and that it was helpful, I’m still working on this website and demos to help people that are interested in programming things beyond the web development niche. If you have any question or suggestion, please contact me through GitHub or e-mail. +thank you!

+ +
+
+
+ + + + \ No newline at end of file diff --git a/en/demo/2023/04/12/farm-v0.html b/en/demo/2023/04/12/farm-v0.html new file mode 100644 index 0000000..bfc927e --- /dev/null +++ b/en/demo/2023/04/12/farm-v0.html @@ -0,0 +1,82 @@ + + + + + + + Farm Demo v0 + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + + pt-br + + + + + en + + +

+ +

Farm Demo v0

+ +
    +
  • W, A, S, D - Move
  • +
  • I - Interact
  • +
  • ddMouse Wheel - Zoom
  • +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/en/demo/2023/05/05/goingo-wasm-demo.html b/en/demo/2023/05/05/goingo-wasm-demo.html new file mode 100644 index 0000000..7acc3d0 --- /dev/null +++ b/en/demo/2023/05/05/goingo-wasm-demo.html @@ -0,0 +1,86 @@ + + + + + + + Goingo Wasm Demo + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + + pt-br + + + + + en + + +

+ +

Goingo Wasm Demo

+ +
    +
  • Left-Click +
      +
    • On Board - Place Stone
    • +
    • On Stone - Show group, liberties and enemies
    • +
    +
  • +
  • Right-Click - Pass turn
  • +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/en/demo/pt-br/2023/03/17/diffusion-automata.html b/en/demo/pt-br/2023/03/17/diffusion-automata.html new file mode 100644 index 0000000..ddd1606 --- /dev/null +++ b/en/demo/pt-br/2023/03/17/diffusion-automata.html @@ -0,0 +1,76 @@ + + + + + + + Diffusion Automata v0 + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + + pt-br + + + + + en + + +

+ +

Diffusion Automata v0

+ + + +
+
+
+ + + + \ No newline at end of file diff --git a/en/demos.html b/en/demos.html new file mode 100644 index 0000000..f0fa934 --- /dev/null +++ b/en/demos.html @@ -0,0 +1,122 @@ + + + + + + + All Demos + + + + + + + + + + + + + + + + +
+
+ ../

All Demos

+
+
+ + + + \ No newline at end of file diff --git a/en/devlog-archive.html b/en/devlog-archive.html new file mode 100644 index 0000000..ce26254 --- /dev/null +++ b/en/devlog-archive.html @@ -0,0 +1,41 @@ + + + + + + + All Devlogs + + + + + + + + + + + + + + + + +
+
+ ../

All Devlogs

+
+
+ + + + \ No newline at end of file diff --git a/en/devlog/2023/04/12/devlog-3.html b/en/devlog/2023/04/12/devlog-3.html new file mode 100644 index 0000000..e35aa04 --- /dev/null +++ b/en/devlog/2023/04/12/devlog-3.html @@ -0,0 +1,116 @@ + + + + + + + Devlog #3 - TileMaps and StateMachines + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + + pt-br + + + + + en + + +

Devlog #3 - TileMaps and StateMachines

+ +

+ + + # Introduction + + +

+ + +

It took me long to write this post because I thought there was nothing interesting to comment on the demos that I created these last weeks. I thought I’d write about why I think that and indicate some more useful ways for those who are doing something similar.

+

+ + + # Tilemaps + + +

+ + +

The game we are creating will use tilemaps, this kind of technique is so old that even the Super Nintendo already had specialized hardware to render these maps. There is no shortage of materials on this issue, but if you want a nice introduction you can read this here.

+ +

At demo I did two interesting things to note:

+ +

First I mapped the cells of our Diffusion Automata with the tilemap spaces, so I could use the simulation to change which tile should be shown in each space.

+ +

In addition, I used a .tmx file from Tiled to generate the initial state of the simulation. So this demo ends up showing how to extract tilemaps data and how to use data to change them as well.

+

+ + + # StateMachines + + +

+ + +

Unlike cellular automata, there is no material missing on Portuguese state machines. They are obligatory in any course of Computing, Systems and sometimes even Administration. For this reason I will not indicate any material, you will probably find a lot on Google and can garimpar what makes the most sense to you. If you are lazy, the Wikipedia article is a quick source to get to know the subject.

+ +

In demo this machine was used to control the state of each garden. When the farmer creates a new she begins with the state SECA, so he waters that garden she passes to the state MOLHADA. Once in this new state the farmer no longer needs to interact with the garden, every time cycle it will automatically grow, changing from EM_CRESCEMENT_1 to ‘EM_CRESCEMENT_4`.

+ +

To demonstrate that this growth time is independent for each garden, every new created time increases. If you interact with a fully grown vegetable garden the farmer can harvest, which brings it back to the state SECA.

+ +

I have no commented code for this demo because it is based on a library called stateless, it is not worth explaining how it works because in your case you may be using a different tool. There are hundreds of ways to implement this solution, use the one that makes the most sense in your case.

+

+ + + # Conclusion + + +

+ + +

This post was quick, I didn’t have much to say but wanted to publish right before the end of the week. In the coming week I should not work in any demo or in the game, I will be traveling to solve some issues of my change. But as soon as I come back I must head in the development of new demos. In particular I want to create a UI to navigate the map and interact with the systems, I’m also reading a little about some ‘design patterns’ to help me override these systems, which is essential for everything to work together.

+ +

It should take me to my next post, so don’t get scared if you just hear from me in a month or two. Until then, I recommend taking a look at the new links page that I added to the site, so I find something interesting I should put there.


+ +

I hope you enjoyed this material and that it was helpful, I am still working on this site and we gave it to help those who are interested in programming practical things and out of the world web. If you have any questions or suggestions, please contact GitHub or e-mail.

+ +

thank you!

+
+
+
+ + + + \ No newline at end of file diff --git a/en/en-us-archive.html b/en/en-us-archive.html new file mode 100644 index 0000000..e0e83ed --- /dev/null +++ b/en/en-us-archive.html @@ -0,0 +1,38 @@ + + + + + + + All in English + + + + + + + + + + + + + + + + +
+
+ ../

All in English

+
+
+ + + + \ No newline at end of file diff --git a/en/favicon.ico b/en/favicon.ico new file mode 100644 index 0000000..5326210 Binary files /dev/null and b/en/favicon.ico differ diff --git a/en/feed.xml b/en/feed.xml new file mode 100644 index 0000000..6518a1a --- /dev/null +++ b/en/feed.xml @@ -0,0 +1,174 @@ +Jekyll2024-04-13T19:51:24+00:00https://github.com/devlog/en/feed.xmlJoel’s Dev BlogJoel SchutzGoingo Wasm Demo2023-05-05T10:36:14+00:002023-05-05T10:36:14+00:00https://github.com/devlog/en/demo/2023/05/05/goingo-wasm-demo<ul> + <li>Left-Click + <ul> + <li>On Board - Place Stone</li> + <li>On Stone - Show group, liberties and enemies</li> + </ul> + </li> + <li>Right-Click - Pass turn</li> +</ul>Joel SchutzLeft-Click On Board - Place Stone On Stone - Show group, liberties and enemies Right-Click - Pass turnDevlog #3 - TileMaps and StateMachines2023-04-12T18:56:11+00:002023-04-12T18:56:11+00:00https://github.com/devlog/en/devlog/2023/04/12/devlog-3<h2 id="introduction">Introduction</h2> + +<p>It took me long to write this post because I thought there was nothing interesting to comment on the demos that I created these last weeks. I thought I’d write about why I think that and indicate some more useful ways for those who are doing something similar.</p> + +<h2 id="tilemaps">Tilemaps</h2> + +<p>The game we are creating will use tilemaps, this kind of technique is so old that even the Super Nintendo already had specialized hardware to render these maps. There is no shortage of materials on this issue, but if you want a nice introduction you can read this <a href="https://www.domestika.org/en/blog/6985-o-que-e-tileset-e-tilemap-no-development-de-games">here</a>.</p> + +<p>At <a href="/devlog/demo/2023/04/07/tilemap-v0.html">demo</a> I did two interesting things to note:</p> + +<p>First I mapped the cells of our <a href="/devlog/demo/2023/03/23/diffusion-automata-v1.html">Diffusion Automata</a> with the tilemap spaces, so I could use the simulation to change which tile should be shown in each space.</p> + +<p>In addition, I used a <code class="language-plaintext highlighter-rouge">.tmx</code> file from <a href="https://www.mapeditor.org/">Tiled</a> to generate the initial state of the simulation. So this demo ends up showing how to extract tilemaps data and how to use data to change them as well.</p> + +<h2 id="statemachines">StateMachines</h2> + +<p>Unlike cellular automata, there is no material missing on Portuguese state machines. They are obligatory in any course of Computing, Systems and sometimes even Administration. For this reason I will not indicate any material, you will probably find a lot on Google and can garimpar what makes the most sense to you. If you are lazy, the <a href="https://pt.wikipedia.org/wiki/M%C3%A1quina_de_estados_finita">Wikipedia</a> article is a quick source to get to know the subject.</p> + +<p>In <a href="/devlog/demo/2023/04/12/farm-v0.html">demo</a> this machine was used to control the state of each garden. When the farmer creates a new she begins with the state <code class="language-plaintext highlighter-rouge">SECA</code>, so he waters that garden she passes to the state <code class="language-plaintext highlighter-rouge">MOLHADA</code>. Once in this new state the farmer no longer needs to interact with the garden, every time cycle it will automatically grow, changing from <code class="language-plaintext highlighter-rouge">EM_CRESCEMENT_1</code> to ‘EM_CRESCEMENT_4`.</p> + +<p>To demonstrate that this growth time is independent for each garden, every new created time increases. If you interact with a fully grown vegetable garden the farmer can harvest, which brings it back to the state <code class="language-plaintext highlighter-rouge">SECA</code>.</p> + +<p>I have no commented code for this demo because it is based on a library called <a href="https://github. with/qmuntal/stateless">stateless</a>, it is not worth explaining how it works because in your case you may be using a different tool. There are hundreds of ways to implement this solution, use the one that makes the most sense in your case.</p> + +<h2 id="conclusion">Conclusion</h2> + +<p>This post was quick, I didn’t have much to say but wanted to publish right before the end of the week. In the coming week I should not work in any demo or in the game, I will be traveling to solve some issues of my change. But as soon as I come back I must head in the development of new demos. In particular I want to create a UI to navigate the map and interact with the systems, I’m also reading a little about some ‘design patterns’ to help me override these systems, which is essential for everything to work together.</p> + +<p>It should take me to my next post, so don’t get scared if you just hear from me in a month or two. Until then, I recommend taking a look at the new <a href="/devlog/links.html">links</a> page that I added to the site, so I find something interesting I should put there.</p> + +<hr /> + +<p>I hope you enjoyed this material and that it was helpful, I am still working on this site and we gave it to help those who are interested in programming practical things and out of the world web. If you have any questions or suggestions, please contact <a href="https://github.com/joelschutz">GitHub</a> or <a href="mail:joelsschutz@yahoo.com.br">e-mail</a>.</p> + +<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif" alt="thank you!" /></p>Joel SchutzIntroductionFarm Demo v02023-04-12T18:52:03+00:002023-04-12T18:52:03+00:00https://github.com/devlog/en/demo/2023/04/12/farm-v0<ul> + <li>W, A, S, D - Move</li> + <li>I - Interact</li> + <li>ddMouse Wheel - Zoom</li> +</ul>Joel SchutzW, A, S, D - Move I - Interact ddMouse Wheel - ZoomDiffusion Automata v12023-03-24T01:04:38+00:002023-03-24T01:04:38+00:00https://github.com/devlog/en/demo/2023/03/24/diffusion-automata-v1<p>The goal for this Automata is to simulate the diffusion of +a liquid on a solid medium, like soil, sand, etc. It was created +as a prototype of a underground water diffusion for my game.</p> + +<p>As will notice, there isn’t much complexity in this code, that’s the magic +of this kind of algorithm, we can use simple rules to create complex +behavior. Here, we simulate the interaction between liquids ans solids +over time and space using basic arithmetic</p> + +<p>Our board will be represented by a 2d array of vectors, this is just +for convenience since we can easily group the two relevant values:</p> + +<ul> + <li>Humidity + <ul> + <li>The amount of liquid within the cell</li> + </ul> + </li> + <li>Impermeability + <ul> + <li>The resistance of the cell to the movement of liquid trough it</li> + </ul> + </li> +</ul> + +<p>The fields <code class="language-plaintext highlighter-rouge">Rocks</code> and <code class="language-plaintext highlighter-rouge">Rain</code> just represent cells that are totally impermeable +or sources of humidity, respectively.</p> + +<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">HumidityBoard</span> <span class="k">struct</span> <span class="p">{</span> + <span class="n">values</span> <span class="p">[][]</span><span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span> <span class="c">// [humidity, impermeability]</span> + <span class="n">Rocks</span><span class="p">,</span> <span class="n">Rain</span> <span class="p">[][]</span><span class="kt">bool</span> + <span class="n">hvrX</span><span class="p">,</span> <span class="n">hvrY</span> <span class="kt">int</span> +<span class="p">}</span> +</code></pre></div></div> + +<p>The logic to determine the humidity of a cell is simples, since the liquid +converges to a uniform distribution over time for all the space, we assume +that the new value of humidity of a cell is just the mean between it and +their neighbors values. For simplicity, we only count 4 neighbors as the +diagram below, where <code class="language-plaintext highlighter-rouge">v0</code> is the current cell:</p> + +<table> + <tbody> + <tr> + <td> </td> + <td>v3</td> + <td> </td> + </tr> + <tr> + <td>v1</td> + <td>v0</td> + <td>v2</td> + </tr> + <tr> + <td> </td> + <td>v4</td> + <td> </td> + </tr> + </tbody> +</table> + +<p>To include permeability properties, we use a weighted mean where each +factor is defined by that cell impermeability. The catch is that we use +the inverse(1/value) for neighboring cells, that way we achieve the effect +of a highly impermeable cell resisting either losing or gaining humidity. +Then we clamp to new value to a max of 1024.</p> + +<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">ba</span> <span class="o">*</span><span class="n">HumidityBoard</span><span class="p">)</span> <span class="n">Update</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span> + <span class="c">// Store the initial state as reference</span> + <span class="n">m0</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([][]</span><span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">ba</span><span class="o">.</span><span class="n">values</span><span class="p">))</span> + <span class="nb">copy</span><span class="p">(</span><span class="n">m0</span><span class="p">,</span> <span class="n">ba</span><span class="o">.</span><span class="n">values</span><span class="p">)</span> + + <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">row</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">ba</span><span class="o">.</span><span class="n">values</span> <span class="p">{</span> + <span class="k">for</span> <span class="n">y</span><span class="p">,</span> <span class="n">v0</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">row</span> <span class="p">{</span> + <span class="c">// Skip the calculations for humidity sources and impermeable cell</span> + <span class="k">if</span> <span class="n">ba</span><span class="o">.</span><span class="n">Rain</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> <span class="o">||</span> <span class="n">v0</span><span class="p">[</span><span class="m">1</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="o">/</span><span class="m">5</span><span class="p">)</span><span class="o">*</span><span class="m">4</span> <span class="p">{</span> + <span class="k">continue</span> + <span class="p">}</span> + + <span class="c">// Assume that borders are dry and impermeable</span> + <span class="n">v1</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + <span class="n">v2</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + <span class="n">v3</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + <span class="n">v4</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + + <span class="c">// Verify if neighbor exists and use their value</span> + <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="m">0</span> <span class="p">{</span> + <span class="n">v1</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="o">-</span><span class="m">1</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> + <span class="p">}</span> + <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">m0</span><span class="p">)</span><span class="o">-</span><span class="m">1</span> <span class="p">{</span> + <span class="n">v2</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="m">1</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> + <span class="p">}</span> + <span class="k">if</span> <span class="n">y</span> <span class="o">&gt;</span> <span class="m">0</span> <span class="p">{</span> + <span class="n">v3</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="o">-</span><span class="m">1</span><span class="p">]</span> + <span class="p">}</span> + <span class="k">if</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">m0</span><span class="p">)</span><span class="o">-</span><span class="m">1</span> <span class="p">{</span> + <span class="n">v4</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="o">+</span><span class="m">1</span><span class="p">]</span> + <span class="p">}</span> + + <span class="c">// Calculate the weighted mean</span> + <span class="n">r</span> <span class="o">:=</span> <span class="p">((</span><span class="n">v0</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">v0</span><span class="p">[</span><span class="m">1</span><span class="p">]))</span> <span class="o">+</span> <span class="p">(</span><span class="n">v1</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v1</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="n">v2</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v2</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="n">v3</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v3</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="n">v4</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v4</span><span class="p">[</span><span class="m">1</span><span class="p">]))</span> <span class="o">/</span> <span class="p">(</span><span class="n">v0</span><span class="p">[</span><span class="m">1</span><span class="p">]</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v1</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v2</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v3</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v4</span><span class="p">[</span><span class="m">1</span><span class="p">]))</span> + + <span class="c">// Clamp values to 1024</span> + <span class="k">if</span> <span class="n">r</span> <span class="o">&gt;</span> <span class="m">1024</span> <span class="p">{</span> + <span class="n">r</span> <span class="o">=</span> <span class="m">1024</span> + <span class="p">}</span> + + <span class="c">// Updates board with new humidity value</span> + <span class="n">ba</span><span class="o">.</span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="p">][</span><span class="m">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> + <span class="p">}</span> + <span class="p">}</span> + <span class="k">return</span> <span class="no">nil</span> +<span class="p">}</span> +</code></pre></div></div> + +<p>The final result is not perfect, there are parameters that are not accounted like velocity +and density of the liquid, but it’s sufficient for our porpoises. Another limitation of this +method is lack of conservation of mass. As the simulation evolves the humidity spontaneously +drops, which is physically impossible.</p> + +<p>As stated previous, this is a prototype and limitation as this are not necessarily concerns +for games development. Keep in mind that this algorithm is synchronous, but it’s totally +possible to paralelize it.</p> + +<hr /> + +<p>Hope you liked this material and that it was helpful, I’m still working on this website and demos to help people that are interested in programming things beyond the web development niche. If you have any question or suggestion, please contact me through <a href="https://github.com/joelschutz">GitHub</a> or <a href="mailto:joelsschutz@yahoo.com.br">e-mail</a>. +<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif" alt="thank you!" /></p>Joel SchutzThe goal for this Automata is to simulate the diffusion of a liquid on a solid medium, like soil, sand, etc. It was created as a prototype of a underground water diffusion for my game.Diffusion Automata v02023-03-17T11:20:19+00:002023-03-17T11:20:19+00:00https://github.com/devlog/en/demo/pt-br/2023/03/17/diffusion-automataJoel Schutz \ No newline at end of file diff --git a/en/frontmatter.json b/en/frontmatter.json new file mode 100644 index 0000000..7034388 --- /dev/null +++ b/en/frontmatter.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://frontmatter.codes/frontmatter.schema.json", + "frontMatter.taxonomy.contentTypes": [ + { + "name": "default", + "pageBundle": false, + "previewPath": null, + "fields": [ + { + "title": "Title", + "name": "title", + "type": "string" + }, + { + "title": "Description", + "name": "description", + "type": "string" + }, + { + "title": "Publishing date", + "name": "date", + "type": "datetime", + "default": "{{now}}", + "isPublishDate": true + }, + { + "title": "Content preview", + "name": "preview", + "type": "image" + }, + { + "title": "Is in draft", + "name": "draft", + "type": "draft" + }, + { + "title": "Tags", + "name": "tags", + "type": "tags" + }, + { + "title": "Categories", + "name": "categories", + "type": "categories" + } + ] + } + ], + "frontMatter.framework.id": "jekyll", + "frontMatter.content.publicFolder": "assets", + "frontMatter.content.pageFolders": [ + { + "title": "_posts pt-br", + "path": "[[workspace]]/_i18n/pt-br/_posts", + "filePrefix": "yyyy-MM-dd" + }, + { + "title": "_posts en", + "path": "[[workspace]]/_i18n/en/_posts", + "filePrefix": "yyyy-MM-dd" + }, + { + "title": "_drafts", + "path": "[[workspace]]/_drafts", + "filePrefix": "yyyy-MM-dd" + } + ], + "frontMatter.taxonomy.tags": [], + "frontMatter.taxonomy.categories": [], + "frontMatter.dashboard.openOnStart": true, + "frontMatter.content.snippets": { + "Agradecimento": { + "description": "Para encerrar posts agradecendo o leitor", + "body": [ + "", + "---", + "", + "Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo [GitHub](https://github.com/joelschutz) ou [e-mail](mailto:joelsschutz@yahoo.com.br).", + "![thank you!](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif)", + "" + ], + "fields": [] + }, + "Thanks": { + "description": "Thanks the reader", + "body": [ + "", + "---", + "", + "Hope you liked this material and that it was helpful, I'm still working on this website and demos to help people that are interested in programming things beyond the web development niche. If you have any question or suggestion, please contact me through [GitHub](https://github.com/joelschutz) or [e-mail](mailto:joelsschutz@yahoo.com.br).", + "![thank you!](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif)" + ], + "fields": [] + } + } +} \ No newline at end of file diff --git a/en/index.html b/en/index.html new file mode 100644 index 0000000..0680115 --- /dev/null +++ b/en/index.html @@ -0,0 +1,79 @@ + + + + + + + Joel's Dev Blog + + + + + + + + + + + + + + + + +
+
+
+

Joel's Dev Blog

+ + + + pt-br + + + + + en + + +

blogging loudly

+ +
+
+ + + + \ No newline at end of file diff --git a/en/links.html b/en/links.html new file mode 100644 index 0000000..df19a09 --- /dev/null +++ b/en/links.html @@ -0,0 +1,104 @@ + + + + + + + Links + + + + + + + + + + + + + + + + +
+
+ ../

Links

+ +

Art

+ +

Color Term

+ +

Stable Diffusion

+ +

MS Clipart Archive

+ +

Purr Data

+ +

Nature of Code

+ +

The Algorithmic Beauty of Plants

+ +

Awesome Generative Art

+ +

Introduction to Shaders

+ +

A new kind of Science

+ +

Gamedev

+ +

Nick’s Blog

+ +

Red Blob Games

+ +

Boris the Brave

+ +

Game Programming Patterns

+ +

Rust

+ +

Compreensive Rust

+ +

The Rust Book(Interactive)

+ +

Rustup

+ +

Rustilings

+ +

Design Patterns in Rust

+ +

Awesome Rust

+ +

Go

+ +

Go by Example

+ +

Learn Go

+ +

Compreensive Go

+ +

Design Patterns in Go

+ +

Awesome Go

+ +

Misc

+ +

Tom’s toys

+ +

Source Making

+ +

Mental Health

+ + +
+
+ + + + \ No newline at end of file diff --git a/en/pt-br-archive.html b/en/pt-br-archive.html new file mode 100644 index 0000000..efd4eb3 --- /dev/null +++ b/en/pt-br-archive.html @@ -0,0 +1,41 @@ + + + + + + + Tudo em Português + + + + + + + + + + + + + + + + +
+
+ ../

Tudo em Português

+
+
+ + + + \ No newline at end of file diff --git a/en/tutorials-archive.html b/en/tutorials-archive.html new file mode 100644 index 0000000..f475107 --- /dev/null +++ b/en/tutorials-archive.html @@ -0,0 +1,38 @@ + + + + + + + All Tutorials + + + + + + + + + + + + + + + + +
+
+ ../

All Tutorials

+
+
+ + + + \ No newline at end of file diff --git a/essay/2023/08/11/pontes-em-jogos.html b/essay/2023/08/11/pontes-em-jogos.html new file mode 100644 index 0000000..4630257 --- /dev/null +++ b/essay/2023/08/11/pontes-em-jogos.html @@ -0,0 +1,94 @@ + + + + + + + Pontes em Jogos + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Pontes em Jogos

+ +

+ + + # Sam Porter Bridges: O Mensageiro da Reconexão em Death Stranding + + +

+ + +

Em um cenário pós-apocalíptico, onde a separação e a desconexão se tornaram a norma, o protagonista de Death Stranding, Sam Porter Bridges, emerge como um símbolo marcante de esperança e reconexão. O próprio nome de Sam carrega consigo uma profunda simbologia, que se entrelaça com os temas centrais do jogo, criando um protagonista multifacetado e profundamente significativo.

+ +

A etimologia do nome “Sam Porter Bridges” oferece uma perspectiva inicial sobre a missão e o papel desse personagem. “Sam” pode ser associado tanto à ideia de “Sol” quanto de “Filho”. Essas interpretações se alinham à figura de Cristo, que também é muitas vezes referido como o “Filho de Deus” e associado à luz e à redenção. A presença da palavra “Porter” sugere a função de carregar ou transportar, o que se encaixa de maneira coerente com a jornada de Sam em Death Stranding - a de reunir, conectar e trazer um senso de unidade a um mundo fragmentado.

+ +

A metáfora da ponte permeia todo o enredo do jogo e é constantemente enfatizada pelos personagens ao longo da narrativa. As “pontes” não são apenas estruturas físicas que Sam constrói para superar obstáculos geográficos, mas também representam as conexões humanas e sociais que ele trabalha arduamente para restabelecer. O próprio nome “Bridges” no sobrenome de Sam reforça essa noção, simbolizando sua missão de superar divisões e restaurar laços quebrados.

+ +

O paralelo com a figura messiânica é inegável. Assim como Cristo é considerado um mensageiro e um libertador, Sam também assume o papel de trazer alívio e esperança a um mundo atormentado. A sua tarefa de reconectar as cidades isoladas e trazer a paz através da morte, evoca paralelos com a missão espiritual de unir a humanidade e trazer a redenção.

+ +

À medida que a narrativa se desenrola, Sam é retratado como alguém que carrega o fardo de sua missão com relutância e às vezes ceticismo, mas ao mesmo tempo, ele é movido pela compaixão e a necessidade de trazer um sentido renovado à existência. Sua jornada pessoal reflete a luta interna e externa pela reconexão e pela restauração da humanidade, enquanto ele enfrenta desafios monumentais e sacrifícios pessoais.

+ +

Em conclusão, Sam Porter Bridges transcende a moldura de um mero protagonista de um jogo. Ele personifica a busca pela reconexão, esperança e unidade em um mundo fragmentado e desolado. Seu nome carregado de significado, a metáfora constante das pontes e sua representação messiânica convergem para criar um personagem que ressoa com o público, incentivando a reflexão sobre a importância das conexões humanas e a capacidade de superar desafios aparentemente insuperáveis. Sam é muito mais do que um herói; ele é um ícone simbólico de como a determinação e a compaixão podem superar as adversidades e reconstruir o que foi perdido.

+

+ + + # A Encruzilhada Política na Teia da Reconexão em Death Stranding + + +

+ + +

No mundo distópico de Death Stranding, onde a sociedade humana está fragmentada e à beira do colapso, a disputa política entre a empresa Bridges e a facção Homo Demens emerge como um conflito central que ecoa temas intrinsecamente ligados ao próprio protagonista, Sam Porter Bridges. A luta entre a ordem representada por Bridges e o caos pregado pela Homo Demens proporciona uma rica tapeçaria para examinar questões políticas profundas e complexas.

+ +

No cerne do enredo, o jogador se encontra desempenhando o papel de um entregador de pacotes em um mundo onde a conectividade é a chave para a sobrevivência. Sam, como protagonista, é encarregado de construir estruturas, transportar materiais, conectar áreas remotas e proteger suas entregas de ladrões de oportunidade. Essa dualidade reflete a complexidade das agendas políticas, uma vez que ele opera em ambas as esferas do dilema, apontando para as nuances das dinâmicas de poder e controle.

+ +

A representação de Bridges como uma empresa estatal e a Homo Demens como uma facção separatista não apenas espelha confrontos políticos da realidade, mas também sugere profundas implicações econômicas e de investimento humano e material. A construção e operação das redes de reconexão requerem uma teia complexa de agentes que trabalham em conjunto, mas cujas verdadeiras motivações podem se tornar obscuras. A todo momento, o verdadeiro propósito desses investimentos fica em questão, fazendo com que os próprios agentes, incluindo Sam, duvidem sobre a validade de suas conexões.

+ +

Essa intersecção entre os aspectos políticos e econômicos do conflito é amplificada pela própria jornada de Sam, que transcende de um mero entregador solitário para se tornar um ponto focal de uma nova rede de relações humanas. A transformação de Sam, de alguém que inicialmente se limita a operar em seus próprios termos e motivado por recompensas individuais, para alguém que compreende a importância vital das conexões humanas, reflete uma mensagem política mais ampla. A reconexão, tanto física quanto emocional, torna-se uma alegoria para a superação das divisões políticas e sociais, apontando para a necessidade de colaboração e compreensão mútua.

+ +

Em síntese, Death Stranding não é apenas um jogo de entregas e tecnologia futurista, mas também um estudo profundo das dinâmicas políticas e humanas que moldam as sociedades. Sam Porter Bridges personifica a ambivalência do conflito político e a necessidade crucial de reconexão, tanto a nível social quanto humano. Sua jornada evolutiva de um entregador solitário para uma âncora central em uma rede de relações humanas ecoa a importância da unidade em face das divisões e aponta para a esperança de um mundo onde a reconexão prevaleça sobre o caos.

+
+
+
+ + + + \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..5326210 Binary files /dev/null and b/favicon.ico differ diff --git a/feed.xml b/feed.xml new file mode 100644 index 0000000..d277d34 --- /dev/null +++ b/feed.xml @@ -0,0 +1,512 @@ +Jekyll2024-04-13T19:51:23+00:00https://github.com/devlog/feed.xmlJoel’s Dev BlogJoel SchutzDIY datascience2024-04-11T11:08:25+00:002024-04-11T11:08:25+00:00https://github.com/devlog/datascience/2024/04/11/diy-datascience<p>Esses últimos meses eu realizei um sonho, eu consegui um carro! Fiz várias viagens e descobri que a minha vontade e da minha namorada é pegar o nosso Fox vermelho e desbravar esse mundo uma estradinha de cada vez. Porém, logo na primeira parada para abastecer nós já sentimos o golpe e entramos em desespero. 5,80 O LITRO DA GASOLINA! E na nossa primeira semana na cidade em que estudamos já tínhamos gastado quase 2 tanques inteiros, nunca que íamos conseguir realizar nosso sonho assim.</p> + +<p><img src="https://www.carrosnaweb.com.br/imagensbd007/fox5p2005.jpg" alt="VW Fox 2004" /></p> + +<p>No caso dessa primeira semana, o motivo desse gasto todo foi muito besta: os pneus estavam descalibrados. Parece brincadeira, mas depois de calibrar os pneus o consumo do nosso carro na cidade caiu pela metade. Isso me colocou para pensar, o que mais influencia no consumo do nosso carro? Claro bastava ler um blog sobre o assunto que eu ia descobrir que coisas como a quantidade de passageiros, a qualidade do combustível, estilo de direção, se o trecho é urbano, o desgaste do motor, tudo isso influencia no consumo do carro. Mas o que nenhum desses blogs vai ser capaz de me dizer é o quanto o MEU carro consome realmente e é isso que importa no final.</p> + +<p>Com o meu interesse em Datascience reestabelecido graças ao BAH(Business Analytics Hub), decidi que era hora de responder a esse meu pavor com dados. Afinal, para participar do curso eu estou tendo de dirigir quase 240km, ida e volta, todas as sextas-feiras. A ideia é coletar uma boa quantidade de dados para descobrir qual o consumo real do nosso carro e mais algumas informações úteis como: Qual posto é o melhor custo-benefício na minha região? Com que frequência devo calibrar os pneus? Quais trajetos valem mais a pena de carro ou de ônibus? Quanto devo gastar em combustível em uma viagem antes mesmo de pegar a estrada? Compensa usar uma rota alternativa para não pagar o pedágio? Vamos ao plano:</p> + +<h2 id="coleta-de-dados">Coleta de dados</h2> + +<p><img src="https://media.giphy.com/media/MYehRmhUGxmDG2JiGS/giphy.gif" alt="I've collected about 3800 Lists" /></p> + +<p>O estudo dos <code class="language-plaintext highlighter-rouge">Sistemas Complexos</code> me ensinou que o mundo real é totalmente diferente do mundo ideal. Se o objetivo fosse estimar o consumo do meu carro, bastava marcar quanto o odômetro acusa entre visitas ao posto de gasolina. Uma álgebra simples ia me dizer teoricamente quanto meu carro faz de km/L. Mas o meu objetivo é ter um valor real, e a realidade ela é muito mais complexa que isso. Além disso eu estou muito empolgado de poder usar esse projeto para poder trabalhar com dados geoespaciais. Então a metodologia será a seguinte:</p> + +<ul> + <li>A cada trajeto eu vou: + <ul> + <li>Fotografar o painel deixando visível o odômetro e o marcador de gasolina antes e depois de dirigir</li> + <li>Gravar o trajeto usando um aplicativo de GPS no meu celular</li> + <li>Anotar quantos passageiros tinham no carro</li> + </ul> + </li> + <li>A cada visita ao posto eu vou: + <ul> + <li>Fotografar o painel antes e depois de abastecer</li> + <li>Fotografar o painel da bomba deixando visível qual o combustível abastecido(álcool, gasolina ou aditivada), o valor total pago, a quantidade de litros e valor por litro</li> + <li>Registrar no aplicativo de GPS a localização do posto</li> + <li>Anotar: + <ol> + <li>Se eu calibrei os pneus</li> + <li>Se eu usei um aplicativo para ter desconto e quanto que foi dado de desconto</li> + <li>Qual a bandeira do posto</li> + </ol> + </li> + </ul> + </li> +</ul> + +<p>Com essas informações já conseguimos alguns dados, mas mais alguns vão poder ser inferidos a partir deles.</p> + +<h2 id="inferências">Inferências</h2> +<p><img src="https://media.giphy.com/media/KYh1vSXtcdl0RYgLCR/giphy.gif" alt="Turn data into more data" /></p> + +<p>Perceba que existem algumas informações redundantes que estão sendo coletadas e outras que parecem não ter muita relevância com o que estamos tentando medir, mas o objetivo disso é fazer algumas inferências que podem ser úteis depois na análise dos dados.</p> + +<p>Comparando os dados redundantes conseguimos descobrir:</p> + +<ul> + <li>Qual o desvio da distância acusada pelo odômetro e o GPS</li> + <li>Qual o desvio da litragem acusada pela bomba e o medidor do carro, e consequentemente o erro do medidor</li> + <li>Se o trajeto foi feito em trânsito intenso</li> + <li>Qual a proporção da mistura de cada combustível dentro do tanque</li> +</ul> + +<p>Cruzando os dados com outras bases de dados</p> + +<ul> + <li>Quais trajetos foram feitos em trecho urbano e estrada</li> + <li>Qual a temperatura, umidade e condições de chuva no dia e local do trajeto</li> + <li>Quais trechos foram realizados antes e depois de troca de óleo e outras manutenções</li> + <li>Quais trechos passaram por pedágio e o valor</li> +</ul> + +<h2 id="conclusões">Conclusões</h2> + +<p>Uma parte crucial da análise que não está nesse post é exatamente quais as questões que eu vou tentar responder com esses dados. Além das óbvias que fiz no início, muitas outras vão surgir ao longo do processo e a partir dos dados e problemas que vou acumular ao longo dos próximos meses. Por agora a maior preocupação vai ser coletar religiosamente esses dados e buscar uma formas de organizar e tratar esses dados.</p> + +<p>Entendo que quem chegar a esse post deve ter muita curiosidade de ver os resultados e talvez até analisá-los por si mesmo. Porém, eu preciso ainda encontrar uma forma segura de fazer isso. Não quero que ninguém use os meus dados de GPS para descobrir onde eu moro por exemplo. Meus próximos posts sobre o assunto devem tratar disso, mas ainda não sei qual será o próximo feedback, fiquem atentos para mais novidades.</p> + +<blockquote> + <p>Dirijam com responsabilidade</p> +</blockquote> + +<p><img src="https://media.giphy.com/media/Ts7b89eJpcyAM/giphy.gif" alt="Drive Safe!" /></p>Joel SchutzEsses últimos meses eu realizei um sonho, eu consegui um carro! Fiz várias viagens e descobri que a minha vontade e da minha namorada é pegar o nosso Fox vermelho e desbravar esse mundo uma estradinha de cada vez. Porém, logo na primeira parada para abastecer nós já sentimos o golpe e entramos em desespero. 5,80 O LITRO DA GASOLINA! E na nossa primeira semana na cidade em que estudamos já tínhamos gastado quase 2 tanques inteiros, nunca que íamos conseguir realizar nosso sonho assim.Pontes em Jogos2023-08-11T22:48:12+00:002023-08-11T22:48:12+00:00https://github.com/devlog/essay/2023/08/11/pontes-em-jogos<h2 id="sam-porter-bridges-o-mensageiro-da-reconexão-em-death-stranding">Sam Porter Bridges: O Mensageiro da Reconexão em Death Stranding</h2> + +<p>Em um cenário pós-apocalíptico, onde a separação e a desconexão se tornaram a norma, o protagonista de Death Stranding, Sam Porter Bridges, emerge como um símbolo marcante de esperança e reconexão. O próprio nome de Sam carrega consigo uma profunda simbologia, que se entrelaça com os temas centrais do jogo, criando um protagonista multifacetado e profundamente significativo.</p> + +<p>A etimologia do nome “Sam Porter Bridges” oferece uma perspectiva inicial sobre a missão e o papel desse personagem. “Sam” pode ser associado tanto à ideia de “Sol” quanto de “Filho”. Essas interpretações se alinham à figura de Cristo, que também é muitas vezes referido como o “Filho de Deus” e associado à luz e à redenção. A presença da palavra “Porter” sugere a função de carregar ou transportar, o que se encaixa de maneira coerente com a jornada de Sam em Death Stranding - a de reunir, conectar e trazer um senso de unidade a um mundo fragmentado.</p> + +<p>A metáfora da ponte permeia todo o enredo do jogo e é constantemente enfatizada pelos personagens ao longo da narrativa. As “pontes” não são apenas estruturas físicas que Sam constrói para superar obstáculos geográficos, mas também representam as conexões humanas e sociais que ele trabalha arduamente para restabelecer. O próprio nome “Bridges” no sobrenome de Sam reforça essa noção, simbolizando sua missão de superar divisões e restaurar laços quebrados.</p> + +<p>O paralelo com a figura messiânica é inegável. Assim como Cristo é considerado um mensageiro e um libertador, Sam também assume o papel de trazer alívio e esperança a um mundo atormentado. A sua tarefa de reconectar as cidades isoladas e trazer a paz através da morte, evoca paralelos com a missão espiritual de unir a humanidade e trazer a redenção.</p> + +<p>À medida que a narrativa se desenrola, Sam é retratado como alguém que carrega o fardo de sua missão com relutância e às vezes ceticismo, mas ao mesmo tempo, ele é movido pela compaixão e a necessidade de trazer um sentido renovado à existência. Sua jornada pessoal reflete a luta interna e externa pela reconexão e pela restauração da humanidade, enquanto ele enfrenta desafios monumentais e sacrifícios pessoais.</p> + +<p>Em conclusão, Sam Porter Bridges transcende a moldura de um mero protagonista de um jogo. Ele personifica a busca pela reconexão, esperança e unidade em um mundo fragmentado e desolado. Seu nome carregado de significado, a metáfora constante das pontes e sua representação messiânica convergem para criar um personagem que ressoa com o público, incentivando a reflexão sobre a importância das conexões humanas e a capacidade de superar desafios aparentemente insuperáveis. Sam é muito mais do que um herói; ele é um ícone simbólico de como a determinação e a compaixão podem superar as adversidades e reconstruir o que foi perdido.</p> + +<h2 id="a-encruzilhada-política-na-teia-da-reconexão-em-death-stranding">A Encruzilhada Política na Teia da Reconexão em Death Stranding</h2> + +<p>No mundo distópico de Death Stranding, onde a sociedade humana está fragmentada e à beira do colapso, a disputa política entre a empresa Bridges e a facção Homo Demens emerge como um conflito central que ecoa temas intrinsecamente ligados ao próprio protagonista, Sam Porter Bridges. A luta entre a ordem representada por Bridges e o caos pregado pela Homo Demens proporciona uma rica tapeçaria para examinar questões políticas profundas e complexas.</p> + +<p>No cerne do enredo, o jogador se encontra desempenhando o papel de um entregador de pacotes em um mundo onde a conectividade é a chave para a sobrevivência. Sam, como protagonista, é encarregado de construir estruturas, transportar materiais, conectar áreas remotas e proteger suas entregas de ladrões de oportunidade. Essa dualidade reflete a complexidade das agendas políticas, uma vez que ele opera em ambas as esferas do dilema, apontando para as nuances das dinâmicas de poder e controle.</p> + +<p>A representação de Bridges como uma empresa estatal e a Homo Demens como uma facção separatista não apenas espelha confrontos políticos da realidade, mas também sugere profundas implicações econômicas e de investimento humano e material. A construção e operação das redes de reconexão requerem uma teia complexa de agentes que trabalham em conjunto, mas cujas verdadeiras motivações podem se tornar obscuras. A todo momento, o verdadeiro propósito desses investimentos fica em questão, fazendo com que os próprios agentes, incluindo Sam, duvidem sobre a validade de suas conexões.</p> + +<p>Essa intersecção entre os aspectos políticos e econômicos do conflito é amplificada pela própria jornada de Sam, que transcende de um mero entregador solitário para se tornar um ponto focal de uma nova rede de relações humanas. A transformação de Sam, de alguém que inicialmente se limita a operar em seus próprios termos e motivado por recompensas individuais, para alguém que compreende a importância vital das conexões humanas, reflete uma mensagem política mais ampla. A reconexão, tanto física quanto emocional, torna-se uma alegoria para a superação das divisões políticas e sociais, apontando para a necessidade de colaboração e compreensão mútua.</p> + +<p>Em síntese, Death Stranding não é apenas um jogo de entregas e tecnologia futurista, mas também um estudo profundo das dinâmicas políticas e humanas que moldam as sociedades. Sam Porter Bridges personifica a ambivalência do conflito político e a necessidade crucial de reconexão, tanto a nível social quanto humano. Sua jornada evolutiva de um entregador solitário para uma âncora central em uma rede de relações humanas ecoa a importância da unidade em face das divisões e aponta para a esperança de um mundo onde a reconexão prevaleça sobre o caos.</p>Joel SchutzSam Porter Bridges: O Mensageiro da Reconexão em Death StrandingFollow up da extensão2023-05-25T00:17:51+00:002023-05-25T00:17:51+00:00https://github.com/devlog/devlog/study/2023/05/25/extension-follow-up<h2 id="introdução">Introdução</h2> + +<p>Faz quase um ano desde quando eu criei a minha extensão com o intuito de me ajudar a estudar. Obviamente muita coisa aconteceu e eu estou aqui de volta para comentar o que deu certo, o que não funcionou e quais os próximos passos dessa solução. Já digo que o fato de ter pensado nessa extensão antes de ter começado as aulas mais me atrapalhou que ajudou, já explico.</p> + +<p>Logo nas primeiras vezes que tentei utilizar o software já me deparei com o problema que muitos professores não permitem que suas aulas sejam gravadas. Isso é muito efeito do “Escola sem Partido” aqui no Brasil, mesmo os que nao se preocupam com o conteúdo das aulas de divulgado resistem pois tem medo que algo que digam seja tirado de contexto. Tentar vencer essa questão é uma batalha perdida, até porque mesmo quando pude gravar, não consegui usar o software como esperava.</p> + +<p>Uma crítica que eu preciso fazer a mim mesmo é que eu superestimei a minha necessidade de fazer notas durante as aulas. Foram poucos os momentos que eu quis escrever algo e quando escrevi algo sempre perdia o foco na aula. Talvez para outros s ja diferente, mas eu me senti incapaz de prestar atenção nas duas coisas ao mesmo tempo.</p> + +<p>No fim das contas a parte que mais útil desse sistema todo não depende tanto da extensão em si, que é a capacidade de anotar documentos temporais, comp audios e vídeos. Isso porém ainda depende de uma implementação mais robusta e direcionada com o intuito de trabalhar com QDA(Análise de Dados Qualitativos)</p> + +<h2 id="mas-não-apenas-isso">Mas não apenas isso</h2> + +<p>No fim eu acabei percebendo que a defazagem de ferramentas para uso acadêmico é grande. Há uma grande dependência de softwares proprietários, como NVivo, MS Office e Adobe Acrobat que barram o acesso pesquisadores pobres e exclui usuários do Linux cono eu. Além disso, tal realidade gera limitações e barreiras que impedem o livre exercício do que é o objetivo central do trabalho universitário: <em>gerar conhecimento</em></p> + +<p>O trabalho científico depende de um ambiente aberto, flexível e troca constante para o seu desenvolvimento pleno. A cobrança de licenças abusivas, muitas vezes atreladas a instituições inteiras, impede que pesquisadores explorem possibilidades de análise que vão além das capacidades desses softwares. A falta de transparência desses sistemas também promove uma barreira para a analise crítica dos resultados obtidos por esses softwares.</p> + +<p>A interoperabilidade entre estes sistemas também se mostra um desafio, por depender muitas vezes de padrões proprietários de arquivos e complexificar desnecessariamente representações, o transporte de dados de uma aplicação para outra é quase impossível. No mundo do desenvolvimento é inegável a versatilidade que arquivos baseados em texto plano(.md e .csv por exemplo), sendo a base de diversas tecnologias como Git, Jupyter Notebooks e os próprios códigos fonte de qualquer qualquer linguagem de programação. Essa complexidade extra acaba servindo apenas aos propósitos dos criadores das ferramentas que conseguem mais flexibilidade para armazenar dados nesses arquivos, ao mesmo tempo que impedem usuários de transportas seus dados e trabalhos para uma plataforma concorrente.</p> + +<h2 id="ferramentas">Ferramentas</h2> + +<p>Ao longo do tempo eu pude reunir algumas ferramentas abertas que atendem parte do trabalho acadêmico que preciso executar e as reuni na lista abaixo. Meu plano é atualizá-la a medida que mais necessidades e ferramentas apareçam, aconselho que retorne aqui com frequência para acompanhar essa jornada.</p> + +<ul> + <li>Gerenciador de textos e bibliografia + <ul> + <li>Zotero</li> + </ul> + </li> + <li>Controle de tarefas</li> + <li>Assistente de citações + <ul> + <li>Zotero</li> + <li>Quarto</li> + </ul> + </li> + <li>Leitor de PDF com anotações</li> + <li>Renderização de Markdown e Latex + <ul> + <li>Quarto</li> + </ul> + </li> + <li>Editor de mapa mental/Conceitual</li> + <li>Ferramentas de transmissão remota</li> + <li>Gerenciador de escrita colaboratira + <ul> + <li>Git</li> + </ul> + </li> + <li>Ferramentas de analise quantitativa e qualitativa</li> +</ul>Joel SchutzIntroduçãoGoingo Wasm Demo2023-05-05T10:36:14+00:002023-05-05T10:36:14+00:00https://github.com/devlog/demo/2023/05/05/goingo-wasm-demo<ul> + <li>Botão Esquerdo do Mouse + <ul> + <li>No tabuleiro - Coloca pedra</li> + <li>Na pedra - Mostrar grupo, liberdades e inimigos</li> + </ul> + </li> + <li>Botão Direto do Mouse - Passar o turno</li> +</ul>Joel SchutzBotão Esquerdo do Mouse No tabuleiro - Coloca pedra Na pedra - Mostrar grupo, liberdades e inimigos Botão Direto do Mouse - Passar o turnoGoingo: Meu primeiro jogo2023-05-02T21:08:50+00:002023-05-02T21:08:50+00:00https://github.com/devlog/2023/05/02/goingo-meu-primeiro-jogo<p>Eu já perdi a conta de quantos protótipos eu já criei com Ebiten(ou Ebitengine como me pediram para chamar), muitos foram direto para a lixeira e outros estão perdidos em branches abandonadas em algum repositório. Porém tem ideias que são <del>bobas</del> boas demais para deixar passar e precisam de um tratamento à altura. Hoje vou falar sobre o primeiro jogo que lancei: <strong>Goingo</strong>, um uma versão do ancestral jogo de Go feito na totalmente na linguagem Go.</p> + +<h2 id="porque-go">Porque Go?</h2> + +<p>A confusão é totalmente intencional, tudo começou porque queria testar uma nova biblioteca e precisava de algo mais complexo que uma demo para ver ele em ação. Mas no fim eu acabei aprendendo bastante sobre ambos e decidi levar o projeto até o lançamento, muito porque já estava tudo ali, só precisava dar aquele pequeno esforço para finalizar.</p> + +<h3 id="o-jogo-de-tabuleiro">O jogo de tabuleiro</h3> + +<p><img src="https://www.learn-go.net/images/ko.gif" alt="Ko Loop" /></p> + +<p>Go é o jogo de tabuleiro mais antigo do mundo ainda jogado segundo a <a href="https://pt.wikipedia.org/wiki/Go">Wikipedia</a>, teria sido criado a 2500 anos atrás na China onde ainda é muito popular. Aqui no ocidente ele ficou mais conhecido depois que o <a href="https://pt.wikipedia.org/wiki/AlphaGo">AlphaGO</a>, uma inteligencia artificial, venceu o campeão mundial em 2016.</p> + +<p>Apesar de ser um jogo complexo e do desafio que é criar uma IA para jogar ele, as regras são extremamente simples. Esse foi o principal motivo de ter criado esse jogo, é um ótimo exemplo de jogo de tabuleiro que pode ser criado com algumas coisas linhas de código. Basicamente em Go:</p> + +<ul> + <li>Cada jogador se alterna colocando uma peça de sua cor no tabuleiro</li> + <li>Peças adjacentes a outras da mesma cor formam grupos</li> + <li>Quando um grupo é certado completamente por peças do adversário esse grupo é captura e retirado do tabuleiro.</li> + <li>Vence quem cercar mais espaços no tabuleiro ao fim da partida</li> +</ul> + +<p>Claro, a partir dessas regras nascem outras como Ko, Atari, etc, mas para criar a engine essas três são as básicas e definem o game loop. Para criar uma experiencia divertida e interessante é necessário mais funcionalidades, testes para impedir que o jogador faça movimento ilegais e uma método de contar os pontos de cada jogador.</p> + +<p>Essa é uma das coisas que não tenho ainda no jogo, se quiserem saber quem venceu a partida os jogadores precisam contar seus próprios territórios. Parece preguiça da minha parte não adicionar isso ao jogo, mas depois de passar uma noite inteira tentando entender esse <a href="https://www.oipaz.net/Carta.pdf">artigo</a>, eu preferi deixar para uma depois. Eu já comentei que desenvolvi o jogo inteiro em uma semana?</p> + +<h3 id="a-linguagem-de-programação">A Linguagem de Programação</h3> + +<p><img src="https://raw.githubusercontent.com/MariaLetta/free-gophers-pack/master/illustrations/svg/23.svg" alt="Gophers playing Go" style="object-fit: cover;height: 300px;" width="100%" /></p> + +<p>É obvio que escolhi Go como linguagem porque é a minha favorita, mas quis dedicar essa parte do artigo para contar sobre uma situação que eu provavelmente não teria conseguido resolver se fosse em outra linguagem.</p> + +<p>A biblioteca que eu queria utilizar e que deu inicio a +esse projeto se chama <a href="https://github.com/yohamta/donburi">Donburi</a>, é um ECS para a <a href="https://ebitengine.org/">Ebitengine</a> que sempre uso por aqui. Eu ainda vou voltar a falar de ECS no futuro, é um tópico muito importante, mas o que me deu problemas foi um gerenciador de eventos que acompanha a biblioteca. Da forma que eu planejei o meu programa o gerenciador entrava em panico e derrubava o programa. Haviam formas de contornar isso, mas se tratava de um bug no código que precisava ser corrigido, não era para ela se comportar daquela forma.</p> + +<p>Pedir uma correção em um projeto open-source é sempre uma aposta, principalmente quando você não tem familiaridade com o projeto e seus desenvolvedores. Alguns podem ser super abertos, outros podem extremamente relutantes quanto a qualquer tipo de mudança. Sem falar que nunca pode contar que alguém vai tirar parte do tempo dela para resolver um problema seu, te forçando a ter que entrar no código, achar o problema, resolver e propor uma pull-request. Ai que eu acredito que o Go entrou como um grande aliado nesse projeto, pela forma que o Go funciona e a sua sintaxe, é muito fácil entrar em um projeto e identificar como ele funciona. Não existem macros, escopos invisíveis, tipagem dinâmica, magicas de qualquer tipo, tudo em Go é explícito ao ponto que em minutos eu já sabia onde estava o problema e em poucas horas já tinha uma solução.</p> + +<p>Contactar os desenvolvedores para incorporar essas mudanças é outra história, mas isso independe da linguagem. Minha pull-request para o <a href="https://github.com/pkg/browser/pull/52">pkg/browser</a> ainda não foi vista até o momento que estou escrevendo esse artigo, por sorte <a href="https://twitter.com/spaceshooting99">Yohamta</a> foi super rápido em aprovar e eu agradeço muito a ele.</p> + +<h2 id="o-que-fiz-de-diferente">O que fiz de diferente?</h2> + +<p>Algo que é um defeito meu: começar algo e abandonar no meio do caminho. Desde a escola, eu ficava muito animado com um assunto e pesquisava tudo que conseguia sobre ele mas na hora de escrever o trabalho e amarrar tudo eu ficava com preguiça e abandonava. A experiência de fazer sempre era melhor que a de terminar, hoje ainda tenho mais um agravante que é a ideia de que o resultado não vai valer a pena então porque se dedicar até o fim? Eu venho sempre me sabotando dessa forma e vivo buscando formas de superar, mas o que ainda me prende é ter dificuldade de definir onde é o ponto que posso considerar algo como pronto.</p> + +<p>Finalizar algo é difícil para mim porque não consigo definir claramente o resultado esperado e como chegar nele. A forma que encontrei para lidar com isso é diminuindo o escopo do trabalho e aceitando a incompletude dele, desde que eu fizesse o mínimo para me sentir confortável em mostrar para os outros. Assim o projeto nunca está “pronto”, sempre é possível encontrar algo a melhorar, mas também está organizado a um ponto que não é um experimento pessoal que só você pode entender e aproveitar.</p> + +<p>Para deixar o jogo nesse estado eu decidi que precisava de pelo menos:</p> + +<ul> + <li>Sons: Geralmente negligenciados no desenvolvimento, sons dão uma sensação táctil ao jogo que ajuda muito a polir o jogo. Demorou um pouco até encontrar o som certo, mas também no fim foi apenas 3 samples que eu usei para as movimentações das peças.</li> + <li>Menu: UI é um porre de fazer, mas é totalmente necessária, eu não preciso te convencer disso. É o tipo de coisa que é preciso criar coragem e fazer mesmo que fique feio, sem ela o jogo não é acessível jogador.</li> + <li>Logo: O logo tipo é o rosto do seu produto, é o que identifica ele tanto quanto o seu nome. Eu não sou designer e imagino que também não seja, mesmo assim eu me desafiei a fazer esse desenho porque com ele eu tinha tudo que precisava para mostrar o jogo para o mundo. É cruel pensar nisso, o publico vai ser muito mais impactado por esse desenho que pelas horas de pesquisa e desenvolvimento que eu passei no código.</li> +</ul> + +<p>No fim desses três eu ainda acabei incluindo mais algumas coisinhas como alguns overlays, diferentes tamanhos de tabuleiro e a opção de jogar com uma IA usando GoGNU.</p> + +<h2 id="como-jogar">Como jogar?</h2> + +<p>O jogo está disponível no <a href="https://kam1sama.itch.io/goingo">Itch.io</a> e no <a href="https://github.com/joelschutz/goingo">Github</a>, o código é aberto e caso queira me ajudar pode pagar quanto quiser pelo jogo. Eu não vou falar muito porque acho que vale a pena entrar nas páginas e ver como ficou o resultado. É impressionante o que as IA de hoje em dia conseguem fazer, não se preocupe que aqui nesse post foi tudo escrito por mãos humanas.</p> + +<h2 id="conclusão">Conclusão</h2> + +<p>Eu deveria ter escrito esse artigo antes, mas depois de voltar da minha viagem eu fiquei me coçando para escrever código e precisava codar algumas coisas, esse jogo inclusive. Além dele ainda tem uma biblioteca que eu criei e publiquei essa semana que vou escrever um artigo a respeito. Uma coisa que me ajudou bastante para produzir tanto foram algumas ferramentas de IA, eu ainda tenho alguma resistência, mas deu para perceber essa semana o potencial que elas tem. Aqui por exemplo é um espaço que eu não acho justo pedir para o ChatGPT me ajudar, demoro um tanto para escrever esses artigos, acho importante manter essa pessoalidade nesse blog. No README e descrições desses programas eu achei o maximo poder usar a IA, você explica as coisas direto ao ponto e ela enche linguiça para você.</p> + +<p>Um outro ponto que quero começar a usar mais IA é na tradução dos textos desse blog. No momento, a maioria do material está apenas em português e eu gostaria muito de ter ele disponível em inglês para ajudar na divulgação. Meu plano é usar os modelos da <a href="https://libretranslate.com/">Libretranslate</a> para ajudar no processo, se estiver lendo isso em inglês provavelmente o meu plano deu certo.</p> + +<p>Em 2 semanas começam as minhas aulas da faculdade e na semana que vem eu já me mudo em definitivo. Não tenho ideia de como vai ficar meu tempo livre, mas quero continuar publicando por aqui e criando jogos e outros programas legais. Mas se tiver que codar apenas ferramentas de estudo, vou vir aqui contar tudo para vocês. Me desejem sorte nessa nova jornada.</p> + +<hr /> + +<p>Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo <a href="https://github.com/joelschutz">GitHub</a> ou <a href="mailto:joelsschutz@yahoo.com.br">e-mail</a>. +<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif" alt="thank you!" /></p>Joel SchutzEu já perdi a conta de quantos protótipos eu já criei com Ebiten(ou Ebitengine como me pediram para chamar), muitos foram direto para a lixeira e outros estão perdidos em branches abandonadas em algum repositório. Porém tem ideias que são bobas boas demais para deixar passar e precisam de um tratamento à altura. Hoje vou falar sobre o primeiro jogo que lancei: Goingo, um uma versão do ancestral jogo de Go feito na totalmente na linguagem Go.Devlog #3 - TileMaps e StateMachines2023-04-12T18:56:11+00:002023-04-12T18:56:11+00:00https://github.com/devlog/devlog/2023/04/12/devlog-3<h2 id="introdução">Introdução</h2> + +<p>Eu demorei a escrever esse post porque achei que não havia nada de interessante a comentar nas demos que criei essas últimas semanas. Pensei em escrever então sobre porque acho isso e indicar alguns caminhos mais úteis para quem está fazendo algo parecido.</p> + +<h2 id="tilemaps">Tilemaps</h2> + +<p>O jogo que estamos criando vai utilizar tilemaps, esse tipo de técnica é tão antiga que até o Super Nintendo já tinha hardware especializado para renderizar esses mapas. Não faltam materiais sobre esse assunto, nessa demo eu apenas fiquei na superfície, mas se quiser uma introdução bacana pode ler essa <a href="https://www.domestika.org/pt/blog/6985-o-que-e-tileset-e-tilemap-no-desenvolvimento-de-games">aqui</a>.</p> + +<p>Na <a href="/devlog/demo/2023/04/07/tilemap-v0.html">demo</a> eu fiz duas coisas interessantes de se notar:</p> + +<p>Primeiro eu mapiei as células do nosso <a href="/devlog/demo/2023/03/23/diffusion-automata-v1.html">Diffusion Automata</a> com os espaços do tilemap, assim assim eu pude usar a simulação para alterar qual tile deve ser mostrado em cada espaço.</p> + +<p>Além disso, eu utilizei um arquivo <code class="language-plaintext highlighter-rouge">.tmx</code> do <a href="https://www.mapeditor.org/">Tiled</a> para gerar o estado inicial da simulação. Então essa demo acaba mostrando como extrair dados de tilemaps e como utilizar dados para alterá-los também.</p> + +<h2 id="statemachines">StateMachines</h2> + +<p>Diferente dos Autômatos Celulares, não falta material sobre Máquinas de Estado em português. Elas são matéria obrigatória em qualquer curso de Computação, Sistemas e as vezes até Administração. Por esse motivo eu não vou indicar nenhum material, você provavelmente vai encontrar bastante coisa no Google e pode garimpar o que mais lhe faz sentido. Caso esteja com preguiça, o artigo da <a href="https://pt.wikipedia.org/wiki/M%C3%A1quina_de_estados_finita">Wikipedia</a> é uma fonte rápida para se inteirar do assunto.</p> + +<p>Na <a href="/devlog/demo/2023/04/12/farm-v0.html">demo</a> essa máquina foi utilizada para controlar qual o estado de cada hortinha. Quando o fazendeiro cria uma nova ela começa com o estado <code class="language-plaintext highlighter-rouge">SECA</code>, assim que ele rega essa horta ela passa para o estado <code class="language-plaintext highlighter-rouge">MOLHADA</code>. Uma vez nesse novo estado o fazendeiro não precisa mais interagir com a horta, a cada ciclo de tempo ela vai automaticamente crescer, mudando do <code class="language-plaintext highlighter-rouge">EM_CRESCIMENTO_1</code> até <code class="language-plaintext highlighter-rouge">EM_CRESCIMENTO_4</code>.</p> + +<p>Para demonstrar que esse tempo de crescimento é independente para cada hortinha, a cada nova criada o tempo aumenta. Caso interaja com uma horta totalmente crescida o fazendeiro pode colher, o que traz ela de volta para o estado <code class="language-plaintext highlighter-rouge">SECA</code>.</p> + +<p>Não tenho código comentado para essa demo porque ela é baseada em uma biblioteca chamada <a href="https://github.com/qmuntal/stateless">stateless</a>, não vale a pena explicar como ela funciona porque no seu caso pode estar utilizando uma ferramenta diferente. Existem centenas de formas de implementar essa solução, use a que faz mais sentido no seu caso.</p> + +<h2 id="conclusão">Conclusão</h2> + +<p>Esse post foi rápido, não tinha muito a dizer mas queria publicar logo antes do fim da semana. Na próxima semana eu não devo trabalhar em nenhuma demo ou no jogo, vou estar viajando para resolver alguns assuntos da minha mudança. Porém assim que voltar eu devo entrar de cabeça no desenvolvimento de novas demos. Em especial quero criar uma UI para navegar pelo mapa e interagir com os sistemas, também estou lendo um pouco sobre alguns <code class="language-plaintext highlighter-rouge">design patterns</code> para me ajudar a sobrepor esses sistemas, que é algo essencial para que tudo funcione em conjunto.</p> + +<p>Deve demorar até meu próximo post, então não se assustem se só ouvirem falar de mim daqui um mês ou dois. Até lá, recomendo darem uma olhada na nova página de <a href="/devlog/links.html">links</a> que adicionei ao site, assim que achar algo interessante eu devo colocar ali.</p> + +<hr /> + +<p>Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo <a href="https://github.com/joelschutz">GitHub</a> ou <a href="mailto:joelsschutz@yahoo.com.br">e-mail</a>. +<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif" alt="thank you!" /></p>Joel SchutzIntroduçãoFarm Demo v02023-04-12T18:52:03+00:002023-04-12T18:52:03+00:00https://github.com/devlog/demo/2023/04/12/farm-v0<ul> + <li>W, A, S, D - Move</li> + <li>I - Interact</li> + <li>Mouse Wheel - Zoom</li> +</ul>Joel SchutzW, A, S, D - Move I - Interact Mouse Wheel - ZoomTileMap Automata2023-04-07T22:28:10+00:002023-04-07T22:28:10+00:00https://github.com/devlog/demo/2023/04/07/tilemap-v0<p>Nessa demo utilizamos o mesmo Automata da demo <a href="/devlog/demo/2023/03/23/diffusion-automata-v1.html">diffusion-automata-v1</a>, mas usamos um mapa do Tiled para renderizar o quadro. Além disso usamos um esquema simples de camera para permitir zoom(mouse wheel) e pan(middle button) do mapa, assim como adicionar(left button) e remover(right button) rochas do mapa.</p> + +<p>Nossa struct então vai ser bastante simples, precisamos apenas do AUtomata e do TileMap:</p> + +<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">TileBoard</span> <span class="k">struct</span> <span class="p">{</span> + <span class="n">tMap</span> <span class="o">*</span><span class="n">tiled</span><span class="o">.</span><span class="n">Map</span> + <span class="n">b</span> <span class="o">*</span><span class="n">boards</span><span class="o">.</span><span class="n">HumidityBoard</span> + <span class="n">cursor</span> <span class="p">[</span><span class="m">2</span><span class="p">]</span><span class="kt">int</span> +<span class="p">}</span> +</code></pre></div></div> + +<p>Durante o update apenas atualizamos o estado do automata e traduzimos esses estados para o TileMap. Se antes cada célula do nosso espaço correspondia a um pixel, aqui ele corresponde a um tile; uma cor corresponde a um tipo de tile e assim por diante.</p> + +<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">tb</span> <span class="o">*</span><span class="n">TileBoard</span><span class="p">)</span> <span class="n">Update</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span> + <span class="c">// Atualizamos o estado do Automato</span> + <span class="n">err</span> <span class="o">:=</span> <span class="n">tb</span><span class="o">.</span><span class="n">b</span><span class="o">.</span><span class="n">Update</span><span class="p">()</span> + <span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span> + <span class="k">return</span> <span class="n">err</span> + <span class="p">}</span> + + <span class="c">// Extraímos o novo estado</span> + <span class="n">bState</span> <span class="o">:=</span> <span class="n">tb</span><span class="o">.</span><span class="n">b</span><span class="o">.</span><span class="n">GetState</span><span class="p">()</span> + + <span class="n">width</span><span class="p">,</span> <span class="n">height</span> <span class="o">:=</span> <span class="n">tb</span><span class="o">.</span><span class="n">b</span><span class="o">.</span><span class="n">Size</span><span class="p">()</span> + <span class="k">for</span> <span class="n">x</span> <span class="o">:=</span> <span class="m">0</span><span class="p">;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">width</span><span class="p">;</span> <span class="n">x</span><span class="o">++</span> <span class="p">{</span> + <span class="k">for</span> <span class="n">y</span> <span class="o">:=</span> <span class="m">0</span><span class="p">;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">height</span><span class="p">;</span> <span class="n">y</span><span class="o">++</span> <span class="p">{</span> + <span class="n">humidity</span><span class="p">,</span> <span class="n">impermeability</span> <span class="o">:=</span> <span class="n">bState</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="p">]</span><span class="o">.</span><span class="n">Elem</span><span class="p">()</span> + <span class="c">// Aplicamos o valor da umidade na primeira camada</span> + <span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Layers</span><span class="p">[</span><span class="m">0</span><span class="p">]</span><span class="o">.</span><span class="n">Tiles</span><span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Width</span><span class="o">*</span><span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">tiled</span><span class="o">.</span><span class="n">LayerTile</span><span class="p">{</span><span class="n">Tileset</span><span class="o">:</span> <span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Tilesets</span><span class="p">[</span><span class="m">0</span><span class="p">],</span> <span class="n">ID</span><span class="o">:</span> <span class="kt">uint32</span><span class="p">(</span><span class="n">humidity</span> <span class="o">/</span> <span class="m">128</span><span class="p">)}</span> + <span class="c">// Aplicamos o valor da impermeabilidade na segunda camada</span> + <span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Layers</span><span class="p">[</span><span class="m">1</span><span class="p">]</span><span class="o">.</span><span class="n">Tiles</span><span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Width</span><span class="o">*</span><span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">tiled</span><span class="o">.</span><span class="n">LayerTile</span><span class="p">{</span><span class="n">Tileset</span><span class="o">:</span> <span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Tilesets</span><span class="p">[</span><span class="m">1</span><span class="p">],</span> <span class="n">ID</span><span class="o">:</span> <span class="m">838</span><span class="p">,</span> <span class="n">Nil</span><span class="o">:</span> <span class="n">impermeability</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="o">/</span><span class="m">5</span><span class="p">)</span><span class="o">*</span><span class="m">4</span><span class="p">}</span> + <span class="c">// Atualizamos a posição do cursos na terceira camada</span> + <span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Layers</span><span class="p">[</span><span class="m">2</span><span class="p">]</span><span class="o">.</span><span class="n">Tiles</span><span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Width</span><span class="o">*</span><span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">tiled</span><span class="o">.</span><span class="n">LayerTile</span><span class="p">{</span><span class="n">Tileset</span><span class="o">:</span> <span class="n">tb</span><span class="o">.</span><span class="n">tMap</span><span class="o">.</span><span class="n">Tilesets</span><span class="p">[</span><span class="m">1</span><span class="p">],</span> <span class="n">ID</span><span class="o">:</span> <span class="m">847</span><span class="p">,</span> <span class="n">Nil</span><span class="o">:</span> <span class="o">!</span><span class="p">(</span><span class="n">x</span> <span class="o">==</span> <span class="n">tb</span><span class="o">.</span><span class="n">cursor</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="n">y</span> <span class="o">==</span> <span class="n">tb</span><span class="o">.</span><span class="n">cursor</span><span class="p">[</span><span class="m">1</span><span class="p">])}</span> + <span class="p">}</span> + <span class="p">}</span> + <span class="k">return</span> <span class="no">nil</span> +<span class="p">}</span> +</code></pre></div></div>Joel SchutzNessa demo utilizamos o mesmo Automata da demo diffusion-automata-v1, mas usamos um mapa do Tiled para renderizar o quadro. Além disso usamos um esquema simples de camera para permitir zoom(mouse wheel) e pan(middle button) do mapa, assim como adicionar(left button) e remover(right button) rochas do mapa.Lecture Timer - Minha primeira extensão do VSCode2023-04-05T18:14:02+00:002023-04-05T18:14:02+00:00https://github.com/devlog/devlog/study/2023/04/05/a-vscode-extension<h2 id="introdução">Introdução</h2> + +<p>Depois de um tempo trabalhando com desenvolvimento web, e agora com a esfriada no mercado, eu decidi que é hora de voltar para a faculdade. Quem lê o blog percebe que o que eu mais quero é encontrar algum desafio que me deixe o mais longe possível de dessas tecnologias. Por isso criei uma extensão usando JS+HTML+CSS para o VSCode.</p> + +<p>Essa ironia vai se explicar em breve, em resumo, é o jeito que a Microsoft escolheu para tornar o desenvolvimento de extensões mais “simples” no VSCode. Mas o que isso tem a ver com voltar para a faculdade? Bem deixa eu explicar o problema:</p> + +<h2 id="minhas-notas-horrendas">Minhas notas horrendas</h2> + +<p><img src="https://media.giphy.com/media/3o6MbbwX2g2GA4MUus/giphy.gif" alt="I don't understand anything" /></p> + +<p>Já teve a experiencia de estudar para uma prova, voltar para as suas anotações e não fazer ideia do que se tratam? Eu tenho um pouco de dislexia, sou prolixo na hora de me expressar, e para piorar, sou a única pessoa que conheço a ter reprovado nas aulas de caligrafia. Quando me concentrava para anotar, me perdia na aula, quando fazia na pressa, não entendia nada do que escrevi. O resultado era um caderno cheio de notas confusas e feias de uma aula que eu já não lembrava sobre o que era.</p> + +<p>Escutar as gravações das aulas acabava sendo a solução, ainda mais depois da pandemia, esse material virou essencial nos meus estudos já que eu poderia pausar, voltar e dar a atenção necessária para cada parte. Minhas notas ficaram muito mais organizadas e úteis, fui tão bem que consegui aprender a programar, fui empregado na área e acabei deixando a faculdade. Mas tem um aspecto desse processo que eu preciso resolver para ter alguma vida além dos estudos.</p> + +<p>Gravações são ótimas, mas não são fáceis de encontrar o que está procurando. Em um texto você consegue usar o famoso <code class="language-plaintext highlighter-rouge">Ctrl+F</code> e procurar o que precisa, mesmo em um livro é muito fácil sublinhar e marcar páginas para voltar depois. Em um arquivo de audio ou video não é possível fazer algo assim, o que eu acabava fazendo era anotar a minutagem e uma frase ao lado para tentar me achar depois, quase sempre sem sucesso.</p> + +<p>O problema não era tanto o método, mas o fato de ele ser trabalhoso e ineficiente. Para anotar uma minutagem era necessário pausar e escrever o exata valor, depois para retornar era preciso encontrar o segundo exato na linha. Sem falar que era impossível fazer algo assim durante a gravação de uma aula, coisa que vai ser essencial agora com aulas presenciais. Eu precisava de alguma ferramenta que me ajudasse a usar essa técnica e é isso que a minha extensão faz.</p> + +<h2 id="anotando-em-tempo-real">Anotando em tempo real</h2> + +<p><img src="https://media.giphy.com/media/1Aj491qX7K45qZs6EP/giphy.gif" alt="Typing while shit burn in front of you" /></p> + +<p>A ideia que eu tive é de uma ferramenta que me permitisse:</p> + +<ol> + <li>Anotar minutagens com apenas um click</li> + <li>Navegar rapidamente entre as anotações e o arquivo de video ou audio</li> + <li>Sincronizar anotações feitas em aula com feitas posteriormente</li> + <li>Permitisse marcar e encontrar facilmente os trechos da aula que mais interessam</li> +</ol> + +<p>Em outras palavras, eu queria alguma forma de rabiscar meus arquivos de audio da mesma forma que um texto ou livro, para isso eu precisava dar uma interface visual para esse audio. Que lugar melhor para começar que pelo <code class="language-plaintext highlighter-rouge">Visual Studio Code</code>, trocadilhos a parte o que pensei de fazer foi criar um arquivo de texto que pudesse conter toda as minhas anotações. O <code class="language-plaintext highlighter-rouge">VSCode</code> entra como uma boa opção de editor, não só pela capacidade de extensão, mas também porque é o editor de texto que uso diariamente e já estou acostumado.</p> + +<p>Escrever a extensão não foi fácil, mas admito que depois de um pouco de esforço a coisa passa a fazer mais sentido. Eu queria poder dizer que a minha falta de experiencia e, em geral, ódio pelo <code class="language-plaintext highlighter-rouge">JavaScript</code> foram as causas dos meus problemas, mas nem foi tão esse o caso. O que mais complica é o design adotado pela Microsoft, a API parece uma grande sopa de decisões impulsivas e a documentação exige que você leia tudo com muita calma para não perder nenhum detalhe. De todo o material que usei, os que eu recomendo para quem quiser tentar essa empreitada são a <a href="https://code.visualstudio.com/api/get-started/your-first-extension">documentação oficial</a>, principalmente os exemplos, e <a href="https://youtu.be/a5DX5pQ9p5M">esse video</a> de quase 4 horas. Não se incomode com o comprimento, a melhor parte desse tutorial é que conseguimos acompanhar ele debugando certas coisas que são importantíssimas, mas que raramente aparecem nos outros tutoriais.</p> + +<h2 id="ok-mas-o-que-essa-extensão-faz">Ok, mas o que essa extensão faz?</h2> + +<p>Antes de tudo, vamos precisar de um arquivo <code class="language-plaintext highlighter-rouge">.md</code> com um <a href="https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/">frontmatter</a> preenchido com alguns dados, a extensão já vem com um snippet chamado <code class="language-plaintext highlighter-rouge">lecture-timer.initTimer</code> que vai criar algo assim:</p> + +<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span> +<span class="na">lecture</span><span class="pi">:</span> + <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">My</span><span class="nv"> </span><span class="s">Title"</span> + <span class="na">file</span><span class="pi">:</span> <span class="s2">"</span><span class="s">example.mp3"</span> <span class="c1"># Opcional</span> + <span class="na">duration</span><span class="pi">:</span> <span class="m">120</span> <span class="c1"># Opcional</span> +<span class="nn">---</span> +</code></pre></div></div> + +<p>Isso é tudo que precisamos para começar, o campo <code class="language-plaintext highlighter-rouge">file</code> é opcional e caso fique em branco a extensão funcionará como um timer simples. Alternativamente você pode utilizar um campo <code class="language-plaintext highlighter-rouge">duration</code> para especificar o limite de tempo do seu timer. Clique no ícone da extensão na barra lateral para abrir o painel.</p> + +<p><img src="/devlog/assets/lt-0.png" alt="Lecture Timer Panel" /></p> + +<p>Os controles na parte superior funcionam como você espera: <code class="language-plaintext highlighter-rouge">tocar</code>, <code class="language-plaintext highlighter-rouge">pausar</code>, <code class="language-plaintext highlighter-rouge">parar</code>, <code class="language-plaintext highlighter-rouge">avançar</code>, <code class="language-plaintext highlighter-rouge">retroceder</code>, etc. Eles servem tanto para operar os timers quanto navegar pelo audio. Na parte inferior temos os timestamps(ou minutagens) registradas no nosso arquivo, clicando em cada um ou usando as botões conseguimos navegar por eles no texto. Adicionamos novos usando os seguintes marcadores no texto:</p> + +<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Marcador vazio --&gt;</span> +:lec-timer{time="3.774" preview="00:00:03" type="alone"} + +<span class="c">&lt;!-- Marcador com conteúdo inline --&gt;</span> +:lec-timer[content]{time="3.774" preview="00:00:03" type="inline"} + +<span class="c">&lt;!-- Marcador de bloco --&gt;</span> +:::lec-timer{time="3.774" preview="00:00:03" type="block"} +multi +line +content +::: +</code></pre></div></div> + +<p>Não é necessário saber digitar esses marcadores inteiros, a extensão adiciona um novo comando para isso, basta utilizar <code class="language-plaintext highlighter-rouge">Ctrl+Shift+P</code> para abrir a palheta comandos e procurar por <code class="language-plaintext highlighter-rouge">lecture-timer.stampMarker</code>. Com ele você consegue adicionar a minutagem e caso tenha algum texto selecionado ele já formata corretamente o seu conteúdo dentro do marcador. Uma dica que eu dou é definir um atalho do teclado para esse comando que até mais fácil de usar.</p> + +<p>A syntax desses marcadores também é proposital, eles respeitam a proposta de <a href="https://talk.commonmark.org/t/generic-directives-plugins-syntax/444">Generic Directives</a> e podem facilmente ser parceados para html utilizando um plugin como <a href="https://github.com/hilookas/markdown-it-directive">markdown-it-directive</a>. Inclusive é esse o plugin que utilizei para renderizar os marcadores no preview do markdown:</p> + +<p><img src="/devlog/assets/lt-1.png" alt="Lecture Timer Preview" /></p> + +<p>Essas são as funcionalidades até agora, não são muitas mas já é o suficiente para começar a utilizar.</p> + +<h2 id="conclusão">Conclusão</h2> + +<p>Eu devo continuar a adicionar funcionalidades e remover bugs no futuro, ainda quero dar suporte a arquivos de video e conteúdo online. Além disso ainda tem algumas coisas de qualidade de vida que eu acredito serem necessárias, mas ainda quero testar mais na prática para ter certeza.</p> + +<p>Caso esteja interessado, já pode instalar a versão em <a href="https://marketplace.visualstudio.com/items?itemName=joelschutz.lecture-timer">pre-release</a> no seu VSCode. Sugestões e bugs podem ser enviados para o <a href="https://github.com/joelschutz/lecture-timer">repositório</a>, assim como contribuições caso queira dar uma força.</p> + +<p>Esse era um dos projetos que me desafiei a terminar antes do começo das aulas da UFRGS em Maio, já vou riscar esse da lista. O outro era uma ferramenta para extrair comentários do código Go, essa já existe e funciona, mas preciso fazer um post como esse aqui no blog para dar como encerrado também e o tempo está acabando.</p> + +<p>Depois disso devo voltar ao regime normal de posts sobre gamedev, já tenho uma demo nova e estou animado para começar a dar forma ao nosso jogo. Porém eu tenho certeza que vamos ter um hiato em breve para eu poder dar conta da minha mudança de cidade e me aclimatar na nova rotina. Não tenho também muita certeza de quanto tempo livre vou ter para me dedicar a projetos como estes, sobre isso só o futuro dirá.</p> + +<hr /> + +<p>Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo <a href="https://github.com/joelschutz">GitHub</a> ou <a href="mailto:joelsschutz@yahoo.com.br">e-mail</a>. +<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif" alt="thank you!" /></p>Joel SchutzIntroduçãoDiffusion Automata v12023-03-24T01:04:38+00:002023-03-24T01:04:38+00:00https://github.com/devlog/demo/2023/03/24/diffusion-automata-v1<p>A ideia desse Automata é simular a dispersão de um +liquido em um meio solido permeável, como solo, areia, etc. +Ele foi criado como protótipo de um sistema de dispersão de +água subterrânea para meu jogo.</p> + +<p>Como vai perceber, não existe muita complexidade nesse código, +essa é a magica desse tipo de algoritmo, com regras simples é +possível construir comportamentos complexos. Aqui, simulamos +a interação entre líquidos e sólidos no tempo e espaço usando apenas +aritmética básica.</p> + +<p>Nosso espaço será representado como um 2d array de vetores, mas +no nosso caso eles servem apenas como uma forma conveniente de +agrupar nossos dois valores relevantes:</p> + +<ul> + <li>Umidade + <ul> + <li>A quantidade de liquido contido naquela célula</li> + </ul> + </li> + <li>Impermeabilidade + <ul> + <li>A resistência que o material daquela célula apresenta ao movimento de liquido</li> + </ul> + </li> +</ul> + +<p>Os campos <code class="language-plaintext highlighter-rouge">Rocks</code> e <code class="language-plaintext highlighter-rouge">Rain</code> servem para demonstrar, respectivamente, +células totalmente impermeáveis e células que sao fontes de umidade.</p> + +<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">HumidityBoard</span> <span class="k">struct</span> <span class="p">{</span> + <span class="n">values</span> <span class="p">[][]</span><span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span> <span class="c">// [humidity, impermeability]</span> + <span class="n">Rocks</span><span class="p">,</span> <span class="n">Rain</span> <span class="p">[][]</span><span class="kt">bool</span> + <span class="n">hvrX</span><span class="p">,</span> <span class="n">hvrY</span> <span class="kt">int</span> +<span class="p">}</span> +</code></pre></div></div> + +<p>A lógica para determinar a umidade de uma célula é bastante simples, +entendendo que ao longo do tempo o liquido tende a se espalhar uniformemente +pelo espaço, assumimos que o nosso valor de umidade da célula é a média aritmética +entre o seu valor atual e a das suas vizinhas. Por simplicidade assumimos apenas +4 vizinhos conforme esse diagrama onde <code class="language-plaintext highlighter-rouge">v0</code> é a célula atual:</p> + +<table> + <tbody> + <tr> + <td> </td> + <td>v3</td> + <td> </td> + </tr> + <tr> + <td>v1</td> + <td>v0</td> + <td>v2</td> + </tr> + <tr> + <td> </td> + <td>v4</td> + <td> </td> + </tr> + </tbody> +</table> + +<p>Para considerar a permeabilidade, utilizamos uma média ponderada onde +o peso de cada termo é definido pelo valor de impermeabilidade daquela célula. +O detalhe é que consideramos o reciproco(1/valor) como peso das células vizinhas, +dessa forma conseguimos o efeito de que uma célula altamente impermeável tende +a não perder umidade ao mesmo tempo que resiste à absorção de mais liquido. Além +disso, verificamos se a célula excede o nosso limite de 1024 e ajustamos então o valor para esse limite.</p> + +<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">ba</span> <span class="o">*</span><span class="n">HumidityBoard</span><span class="p">)</span> <span class="n">Update</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span> + <span class="c">// Armazenamos o estado inicial do espaço para servir de referencia</span> + <span class="n">m0</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([][]</span><span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">ba</span><span class="o">.</span><span class="n">values</span><span class="p">))</span> + <span class="nb">copy</span><span class="p">(</span><span class="n">m0</span><span class="p">,</span> <span class="n">ba</span><span class="o">.</span><span class="n">values</span><span class="p">)</span> + + <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">row</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">ba</span><span class="o">.</span><span class="n">values</span> <span class="p">{</span> + <span class="k">for</span> <span class="n">y</span><span class="p">,</span> <span class="n">v0</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">row</span> <span class="p">{</span> + <span class="c">// Pulamos o calculo de fontes de umidade e células com alto impermeabilidade</span> + <span class="k">if</span> <span class="n">ba</span><span class="o">.</span><span class="n">Rain</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> <span class="o">||</span> <span class="n">v0</span><span class="p">[</span><span class="m">1</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="o">/</span><span class="m">5</span><span class="p">)</span><span class="o">*</span><span class="m">4</span> <span class="p">{</span> + <span class="k">continue</span> + <span class="p">}</span> + + <span class="c">// Assumimos que as bordas são células secas e impermeáveis</span> + <span class="n">v1</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + <span class="n">v2</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + <span class="n">v3</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + <span class="n">v4</span> <span class="o">:=</span> <span class="n">mgl32</span><span class="o">.</span><span class="n">Vec2</span><span class="p">{</span><span class="m">0</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">MaxFloat32</span><span class="p">}</span> + + <span class="c">// Verificamos se o vizinho existe e aplicamos os valores corretos</span> + <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="m">0</span> <span class="p">{</span> + <span class="n">v1</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="o">-</span><span class="m">1</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> + <span class="p">}</span> + <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">m0</span><span class="p">)</span><span class="o">-</span><span class="m">1</span> <span class="p">{</span> + <span class="n">v2</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="m">1</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> + <span class="p">}</span> + <span class="k">if</span> <span class="n">y</span> <span class="o">&gt;</span> <span class="m">0</span> <span class="p">{</span> + <span class="n">v3</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="o">-</span><span class="m">1</span><span class="p">]</span> + <span class="p">}</span> + <span class="k">if</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">m0</span><span class="p">)</span><span class="o">-</span><span class="m">1</span> <span class="p">{</span> + <span class="n">v4</span> <span class="o">=</span> <span class="n">m0</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="o">+</span><span class="m">1</span><span class="p">]</span> + <span class="p">}</span> + + <span class="c">// Calculamos a média aritmética ponderada</span> + <span class="n">r</span> <span class="o">:=</span> <span class="p">((</span><span class="n">v0</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">v0</span><span class="p">[</span><span class="m">1</span><span class="p">]))</span> <span class="o">+</span> <span class="p">(</span><span class="n">v1</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v1</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="n">v2</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v2</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="n">v3</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v3</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="n">v4</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">v4</span><span class="p">[</span><span class="m">1</span><span class="p">]))</span> <span class="o">/</span> <span class="p">(</span><span class="n">v0</span><span class="p">[</span><span class="m">1</span><span class="p">]</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v1</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v2</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v3</span><span class="p">[</span><span class="m">1</span><span class="p">])</span> <span class="o">+</span> <span class="p">(</span><span class="m">1</span> <span class="o">/</span> <span class="n">v4</span><span class="p">[</span><span class="m">1</span><span class="p">]))</span> + + <span class="c">// Limitamos os valores a um máximo de 1024</span> + <span class="k">if</span> <span class="n">r</span> <span class="o">&gt;</span> <span class="m">1024</span> <span class="p">{</span> + <span class="n">r</span> <span class="o">=</span> <span class="m">1024</span> + <span class="p">}</span> + + <span class="c">// Atualizamos espaço com novo valor de umidade</span> + <span class="n">ba</span><span class="o">.</span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="p">][</span><span class="m">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span> + <span class="p">}</span> + <span class="p">}</span> + <span class="k">return</span> <span class="no">nil</span> +<span class="p">}</span> +</code></pre></div></div> + +<p>O resultado no fim não é perfeito, há parâmetros que não são levados em consideração como +velocidade e densidade do liquido, mas para o nosso caso já é suficiente. Outra limitação +é quanto a conservação de massa do sistema. Aos poucos o volume total de umidade cai e isso +causa o efeito de umidade desaparecendo espontaneamente, que é fisicamente impossível.</p> + +<p>Como dito, esse é um protótipo e limitações como essa não são necessariamente problemas +para aplicação em jogos. Vale lembrar que esse algoritmo foi escrito de forma síncrona, +mas é totalmente possível adapta-lo para operar de forma paralelizada.</p>Joel SchutzA ideia desse Automata é simular a dispersão de um liquido em um meio solido permeável, como solo, areia, etc. Ele foi criado como protótipo de um sistema de dispersão de água subterrânea para meu jogo. \ No newline at end of file diff --git a/frontmatter.json b/frontmatter.json new file mode 100644 index 0000000..7034388 --- /dev/null +++ b/frontmatter.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://frontmatter.codes/frontmatter.schema.json", + "frontMatter.taxonomy.contentTypes": [ + { + "name": "default", + "pageBundle": false, + "previewPath": null, + "fields": [ + { + "title": "Title", + "name": "title", + "type": "string" + }, + { + "title": "Description", + "name": "description", + "type": "string" + }, + { + "title": "Publishing date", + "name": "date", + "type": "datetime", + "default": "{{now}}", + "isPublishDate": true + }, + { + "title": "Content preview", + "name": "preview", + "type": "image" + }, + { + "title": "Is in draft", + "name": "draft", + "type": "draft" + }, + { + "title": "Tags", + "name": "tags", + "type": "tags" + }, + { + "title": "Categories", + "name": "categories", + "type": "categories" + } + ] + } + ], + "frontMatter.framework.id": "jekyll", + "frontMatter.content.publicFolder": "assets", + "frontMatter.content.pageFolders": [ + { + "title": "_posts pt-br", + "path": "[[workspace]]/_i18n/pt-br/_posts", + "filePrefix": "yyyy-MM-dd" + }, + { + "title": "_posts en", + "path": "[[workspace]]/_i18n/en/_posts", + "filePrefix": "yyyy-MM-dd" + }, + { + "title": "_drafts", + "path": "[[workspace]]/_drafts", + "filePrefix": "yyyy-MM-dd" + } + ], + "frontMatter.taxonomy.tags": [], + "frontMatter.taxonomy.categories": [], + "frontMatter.dashboard.openOnStart": true, + "frontMatter.content.snippets": { + "Agradecimento": { + "description": "Para encerrar posts agradecendo o leitor", + "body": [ + "", + "---", + "", + "Espero que tenha gostado desse material e que tenha sido de ajuda, estou ainda trabalhando nesse site e nas demos para ajudar a quem tem interesse em programar coisas práticas e fora do mundinho web. Caso tenha alguma dúvida ou sugestão, por favor entre em contato pelo [GitHub](https://github.com/joelschutz) ou [e-mail](mailto:joelsschutz@yahoo.com.br).", + "![thank you!](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif)", + "" + ], + "fields": [] + }, + "Thanks": { + "description": "Thanks the reader", + "body": [ + "", + "---", + "", + "Hope you liked this material and that it was helpful, I'm still working on this website and demos to help people that are interested in programming things beyond the web development niche. If you have any question or suggestion, please contact me through [GitHub](https://github.com/joelschutz) or [e-mail](mailto:joelsschutz@yahoo.com.br).", + "![thank you!](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNDU3M2ZhZmUxZDQ4NGM3NGY1YjJlMzFkZmNkYTA2NmFhZGExNGFiNCZjdD1n/htebeL9yH0ZI9K47Jo/giphy.gif)" + ], + "fields": [] + } + } +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..22c793f --- /dev/null +++ b/index.html @@ -0,0 +1,88 @@ + + + + + + + Joel's Dev Blog + + + + + + + + + + + + + + + + +
+
+
+

Dev Blog do Joel

+ + + pt-br + + + + + en + + + +

blogging loudly

+ +
+
+ + + + \ No newline at end of file diff --git a/links.html b/links.html new file mode 100644 index 0000000..4b22e41 --- /dev/null +++ b/links.html @@ -0,0 +1,104 @@ + + + + + + + Links + + + + + + + + + + + + + + + + +
+
+ ../

Links

+ +

Art

+ +

Color Term

+ +

Stable Diffusion

+ +

MS Clipart Archive

+ +

Purr Data

+ +

Nature of Code

+ +

The Algorithmic Beauty of Plants

+ +

Awesome Generative Art

+ +

Introduction to Shaders

+ +

A new kind of Science

+ +

Gamedev

+ +

Nick’s Blog

+ +

Red Blob Games

+ +

Boris the Brave

+ +

Game Programming Patterns

+ +

Rust

+ +

Compreensive Rust

+ +

The Rust Book(Interactive)

+ +

Rustup

+ +

Rustilings

+ +

Design Patterns in Rust

+ +

Awesome Rust

+ +

Go

+ +

Go by Example

+ +

Learn Go

+ +

Compreensive Go

+ +

Design Patterns in Go

+ +

Awesome Go

+ +

Misc

+ +

Tom’s toys

+ +

Source Making

+ +

Mental Health

+ + +
+
+ + + + \ No newline at end of file diff --git a/pt-br-archive.html b/pt-br-archive.html new file mode 100644 index 0000000..715558e --- /dev/null +++ b/pt-br-archive.html @@ -0,0 +1,38 @@ + + + + + + + Tudo em Português + + + + + + + + + + + + + + + + +
+
+ ../

Tudo em Português

+
+
+ + + + \ No newline at end of file diff --git a/tutorials-archive.html b/tutorials-archive.html new file mode 100644 index 0000000..acb774a --- /dev/null +++ b/tutorials-archive.html @@ -0,0 +1,41 @@ + + + + + + + All Tutorials + + + + + + + + + + + + + + + + +
+
+ ../

All Tutorials

+
+
+ + + + \ No newline at end of file diff --git a/tutorials/2023/03/12/lauching-blog.html b/tutorials/2023/03/12/lauching-blog.html new file mode 100644 index 0000000..f15827f --- /dev/null +++ b/tutorials/2023/03/12/lauching-blog.html @@ -0,0 +1,138 @@ + + + + + + + Criando um blog de desenvolvimento + + + + + + + + + + + + + + + + + + + +
+
+ ../
+

+ + + pt-br + + + + + en + + + +

Criando um blog de desenvolvimento

+ +

Eu sou da época que quando para criar um blog bastava entrar no Blogger, Wordpress ou Tumblr e criar uma conta. Em minutos você escolhia um tema, configurava tudo e jã estava online e pronto para publicar para o mundo inteiro.

+ +

Claro que todos esses sites ainda existem e funcionam muito bem. Mas além de serem bastante limitados, qualquer um que entrar no seu blog vai ficar com a impressão que seu post foi escrito em 1997 em um i386.

+

+ + + # Github Pages + + +

+ + +

they don't know my development blog is hosted for free on github pages

+ +

Hoje em dia a galera da moda tem um novo jeito de hospedar um blog sem pagar nada por isso. Envolve um pouco mais de trabalho, mais o resultado e um site estático, completamente customizável e que talvez te renda até um emprego numa startup por ai.

+ +

Eu não vou explicar aqui como criar tudo do zero porque esse tutorial do Github vai guiar você a cada passo. O que eu vou mostrar aqui são algumas dicas para deixar seu blog ainda melhor de usar e de olhar.

+

+ + + # Jekyll + + +

+ + +

Jekyll X GH Pages: They're the same picture

+ +

Por baixo dos panos o Github usa o Jekyll para gerar esse site estático, é possível hospedar qualquer repositório com páginas HTML, porém usando essa ferramenta conseguimos criar as páginas em Markdown e deixar o Jekyll fazer o trabalho sujo.

+ +

Claro que não é nenhuma mágica e ai que entra a primeira dica:

+

+ + + # Themes e Remote Themes + + +

+ + +

No arquivo _config.yml que está na raiz do repositório, você pode inserir um tema usando a chave theme. O que não te contaram á que você pode usar qualquer tema hospedado no Github com a chave remote_theme. Fica algo assim:

+ +
title: My Blog
+author: My Name
+remote_theme: daattali/beautiful-jekyll
+
+ +

Fazendo isso o tema vai ser automaticamente baixado na hora do build e não precisa incluir nada novo no seu repositório. Basta apenas encontrar um tema que te agrade.

+ +

Agora é só escrever o conteúdo, e para ajudar nessa parte vem a segunda dica:

+

+ + + # Frontmatter + + +

+ + +

Frontmatter + Jekyll = CMS Local

+ +

Na hora de administrar os seus posts, editar tags, adicionar categorias, visualizar histórico, etc, o nosso esquema de editar o Markdown e subir para o repositório não é o mais prática. Para isso existe o Frontmatter, se você usa um editor compatível.

+ +

A ideia desse plugin é trazer as funcionalidades de um CMS como o Wordpress para o editor. Assim você consegue facilmente administrar os seus posts, imagens e um monte de outras coisas que você vai descobrir lendo na doc deles.

+ +

Só uma coisa antes de começar. A configuração padrão deles não trabalha muito bem com o Jekyll, pelo menos na minha experiência, então eu recomendo copiar o frontmatter.json que criei para esse blog. Assim a maioria das funcionalidades vão funcionar corretamente.

+

+ + + # Concluindo + + +

+ + +

Seu blog esta no ar, bonitão, com todas as mordomias que pode querer, tudo direto no seu editor favorito. Agora não tem mais desculpa.

+ +

Já sabe o que vai publicar, certo?

+ +

Oh


+
+
+
+ + + + \ No newline at end of file