{"id":143,"date":"2024-06-07T09:03:34","date_gmt":"2024-06-07T12:03:34","guid":{"rendered":"http:\/\/pplay.local\/?page_id=143"},"modified":"2024-06-20T23:17:46","modified_gmt":"2024-06-21T02:17:46","slug":"camera-dinamica-e-salto-de-sprite","status":"publish","type":"page","link":"http:\/\/www2.ic.uff.br\/pplay\/tutoriais\/camera-dinamica-e-salto-de-sprite\/","title":{"rendered":"C\u00e2mera Din\u00e2mica e Salto de Sprite"},"content":{"rendered":"\n<p>O objetivo deste tutorial \u00e9 revisar os principais conceitos necess\u00e1rios para programar jogos. Criaremos um ambiente virtual onde voc\u00ea controla um c\u00e3o que anda em um cen\u00e1rio onde a c\u00e2mera o acompanha dinamicamente. A imagem abaixo exemplifica a implementa\u00e7\u00e3o que buscamos.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"320\" height=\"151\" src=\"http:\/\/www2.ic.uff.br\/pplay\/wp-content\/uploads\/2024\/06\/1tutorial-salto-camera.gif\" alt=\"\" class=\"wp-image-548\"\/><\/figure><\/div>\n\n\n<p>Voc\u00ea pode fazer o download dos arquivos de imagem usado neste tutorial clicando no link abaixo.<\/p>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-733b7e9f-706b-4e5e-bd5e-01dafb498542\" href=\"http:\/\/www2.ic.uff.br\/pplay\/wp-content\/uploads\/2024\/06\/pacote-tutorial-salto-e-camera.zip\">pacote-tutorial-salto-e-camera<\/a><a href=\"http:\/\/www2.ic.uff.br\/pplay\/wp-content\/uploads\/2024\/06\/pacote-tutorial-salto-e-camera.zip\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-733b7e9f-706b-4e5e-bd5e-01dafb498542\">Download<\/a><\/div>\n\n\n\n<p>Vamos organizar nosso c\u00f3digo dividindo-o em 4 se\u00e7\u00f5es.<\/p>\n\n\n\n<ul>\n<li>Condi\u00e7\u00f5es Iniciais (onde poderemos calibrar a din\u00e2mica do jogo)<\/li>\n\n\n\n<li>Fun\u00e7\u00f5es (para reaproveitamento de c\u00f3digo ou organiza\u00e7\u00e3o)<\/li>\n\n\n\n<li>In\u00edcio do Gameloop com Atualiza\u00e7\u00e3o de Vari\u00e1veis<\/li>\n\n\n\n<li>Final do Gameloop com update de sprites, desenho de imagens e update da janela<\/li>\n<\/ul>\n\n\n\n<p class=\"obs\">Obs: O paradigma de orienta\u00e7\u00e3o a objetos ser\u00e1 evitado para garantir que o c\u00f3digo seja entendido por iniciantes, mas alguns coment\u00e1rios acerca deste paradigma ser\u00e3o realizados esporadicamente.<\/p>\n\n\n\n<p>Como iremos desenhar a anima\u00e7\u00e3o do c\u00e3o quando ele est\u00e1 parado (fazendo pequenos movimentos para dar vida ao personagem), precisamos verificar as imagens usadas nessa anima\u00e7\u00e3o. Chamamos esta imagem de sprite, e ela \u00e9 um conjunto de frames colocados lado a lado como podemos observar na figura.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"742\" height=\"100\" src=\"http:\/\/pplay.local\/wp-content\/uploads\/2024\/06\/dogStoppedRight.webp\" alt=\"\" class=\"wp-image-413\" srcset=\"http:\/\/www2.ic.uff.br\/pplay\/wp-content\/uploads\/2024\/06\/dogStoppedRight.webp 742w, http:\/\/www2.ic.uff.br\/pplay\/wp-content\/uploads\/2024\/06\/dogStoppedRight-300x40.webp 300w\" sizes=\"(max-width: 742px) 100vw, 742px\" \/><\/figure><\/div>\n\n\n<p>Avaliando a imagem do c\u00e3o parado verificamos que este sprite possui 6 frames. Ent\u00e3o j\u00e1 podemos iniciar nosso c\u00f3digo.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\nposxDog = 100\nposyDog = 320\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">dogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\n<\/mark>dogStoppedRight.x = posxDog\ndogStoppedRight.y = posyDog\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n\n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n    dogStoppedRight.update()\n    dogStoppedRight.draw()\n    janela.update()\n<\/code><\/pre>\n\n\n\n<p>As linhas em destaque acima s\u00e3o as respons\u00e1veis por instanciarmos o objeto que representa o c\u00e3o parado e virado para a direita. Vamos adicionar um novo sprite que representa o c\u00e3o andando para a direita e vamos fazer o controle desse movimento atrav\u00e9s do teclado. Para isso vamos verificar a imagem do sprite do c\u00e3o andando para a direita.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"744\" height=\"100\" src=\"http:\/\/pplay.local\/wp-content\/uploads\/2024\/06\/dogWalkRight.webp\" alt=\"\" class=\"wp-image-425\" srcset=\"http:\/\/www2.ic.uff.br\/pplay\/wp-content\/uploads\/2024\/06\/dogWalkRight.webp 744w, http:\/\/www2.ic.uff.br\/pplay\/wp-content\/uploads\/2024\/06\/dogWalkRight-300x40.webp 300w\" sizes=\"(max-width: 744px) 100vw, 744px\" \/><\/figure><\/div>\n\n\n<p>Novamente verificamos a presen\u00e7a de 6 frames neste sprite.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\nposxDog = 100\nposyDog = 320\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">velxDog = 250\n<\/mark>\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\ndogStoppedRight.x = posxDog\ndogStoppedRight.y = posyDog\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">dogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\ndogWalkRight.x = posxDog\ndogWalkRight.y = posyDog<\/mark>\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS + DESENHO E ATUALIZA\u00c7\u00c3O\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">    cenario.draw()\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    if teclado.key_pressed('RIGHT'):\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        dogWalkRight.x += velxDog * janela.delta_time()\n        dogStoppedRight.x += velxDog * janela.delta_time()<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        dogWalkRight.update()\n        dogWalkRight.draw()<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    else:\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        dogStoppedRight.update()\n        dogStoppedRight.draw()<\/mark>\n\n    janela.update()\n<\/code><\/pre>\n\n\n\n<p>Neste momento verificamos que h\u00e1 uma necessidade de fazer um controle sobre qual Sprite ser\u00e1 desenhado de acordo com o que estiver sendo pressionado no teclado. Al\u00e9m disso, o cen\u00e1rio deve ser desenhado antes de todos os outros sprites para que n\u00e3o haja sobreposi\u00e7\u00e3o. Se continuarmos implementando com essa estrutura o nosso c\u00f3digo ir\u00e1 ficar um pouco bagun\u00e7ado. Ent\u00e3o vamos instanciar uma nova vari\u00e1vel que ser\u00e1 usada para armazenar o estado do cachorro e a partir desse estado iremos desenhar o c\u00e3o no final do c\u00f3digo. Al\u00e9m disso, em vez de atualizarmos o x e o y de cada sprite dentro dos condicionais, vamos atualizar as vari\u00e1veis posx e posy e usar elas para alterar a posi\u00e7\u00e3o de todos os sprites.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\nposxDog = 100\nposyDog = 320\nvelxDog = 250\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">dogState = 'parado-direita'\n<\/mark>\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\ndogStoppedRight.x = posxDog\ndogStoppedRight.y = posyDog\n\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\ndogWalkRight.x = posxDog\ndogWalkRight.y = posyDog\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n    if teclado.key_pressed('RIGHT'):\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        dogState = 'andando-direita'\n        posxDog += velxDog * janela.delta_time()<\/mark>\n    else:\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        dogState = 'parado-direita'\n<\/mark>\n    # Movimento\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">    dogStoppedRight.x = posxDog\n    dogWalkRight.x = posxDog<\/mark>\n\n    # DESENHO E ATUALIZA\u00c7\u00c3O\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    cenario.draw()\n<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">    if dogState == 'parado-direita':\n        dogStoppedRight.update()\n        dogStoppedRight.draw()\n    elif dogState == 'andando-direita':\n        dogWalkRight.update()\n        dogWalkRight.draw()<\/mark>\n\n    janela.update()\n<\/code><\/pre>\n\n\n\n<p>Agora temos nosso c\u00f3digo mais bem organizado. Podemos criar duas fun\u00e7\u00f5es para os blocos que est\u00e3o marcados de amarelo para tornar nosso c\u00f3digo principal mais enxuto, e cada vez que adicionarmos uma sprite nova fazemos sua movimenta\u00e7\u00e3o e seu desenho dentro dessas duas fun\u00e7\u00f5es. Assim, vamos usar a estrutura switch \/ case do python para tornar o c\u00f3digo mais leg\u00edvel.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\nposxDog = 100\nposyDog = 320\nvelxDog = 250\ndogState = 'parado-direita'\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">dogStoppedRight.x = posxDog\ndogStoppedRight.y = posyDog<\/mark>\n\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">dogWalkRight.x = posxDog\ndogWalkRight.y = posyDog<\/mark>\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">def movimentoDog():\n    dogStoppedRight.x = posxDog\n    dogWalkRight.x = posxDog<\/mark>\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">def desenhoDog():\n    match dogState:\n        case 'parado-direita':\n            dogStoppedRight.update()\n            dogStoppedRight.draw()\n        case 'andando-direita':\n            dogWalkRight.update()\n            dogWalkRight.draw()<\/mark>\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n    if teclado.key_pressed('RIGHT'):\n        dogState = 'andando-direita'\n        posxDog += velxDog * janela.delta_time()\n    else:\n        dogState = 'parado-direita'\n    \n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    movimentoDog()<\/mark>\n    \n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n  <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">  desenhoDog()<\/mark>\n    janela.update()\n\n\n<\/code><\/pre>\n\n\n\n<p>O Gameloop do c\u00f3digo est\u00e1 bem mais enxuto e organizado. Isso \u00e9 importante para continuarmos seguindo nossa programa\u00e7\u00e3o sem nos perdermos no c\u00f3digo. Al\u00e9m disso \u00e9 poss\u00edvel verificar que como a posi\u00e7\u00e3o do c\u00e3o \u00e9 atualizada antes de desenhar, n\u00e3o precisamos definir ela no in\u00edcio do c\u00f3digo. Basta adicionar a defini\u00e7\u00e3o da posi\u00e7\u00e3o y dentro da fun\u00e7\u00e3o de movimento. Apagaremos ent\u00e3o as linhas em vermelho e configuraremos os pr\u00f3ximos sprites com apenas 2 linhas de c\u00f3digo para cada sprite. Vamos fazer o c\u00e3o de mover tamb\u00e9m para a esquerda instanciando mais 2 sprites. Al\u00e9m disso, vamos definir que se o c\u00e3o est\u00e1 virado para a direita (andando ou parado) ele inicia o GameLoop parado para a direita, e se ele estiver virado para a esquerda (andando ou parado) ele inicia o GameLoop parado para a esquerda, e atualizamos este estado caso alguma tecla seja pressionada. Atualizamos tamb\u00e9m as fun\u00e7\u00f5es com esses novos sprites.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\nposxDog = 100\nposyDog = 320\nvelxDog = 250\ndogState = 'parado-direita'\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\n\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">dogStoppedLeft = Sprite(\"dogStoppedLeft.webp\", 6)\ndogStoppedLeft.set_sequence_time(0, 6, 400, True)\n\ndogWalkLeft = Sprite(\"dogWalkLeft.webp\", 6)\ndogWalkLeft.set_sequence_time(0, 6, 100, True)<\/mark>\n\n\ndef movimentoDog():\n    dogStoppedRight.x = posxDog\n    dogStoppedRight.y = posyDog\n    dogWalkRight.x = posxDog\n    dogWalkRight.y = posyDog\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    dogStoppedLeft.x = posxDog\n    dogStoppedLeft.y = posyDog\n    dogWalkLeft.x = posxDog\n    dogWalkLeft.y = posyDog<\/mark>\n\ndef desenhoDog():\n    match dogState:\n        case 'parado-direita':\n            dogStoppedRight.update()\n            dogStoppedRight.draw()\n        case 'andando-direita':\n            dogWalkRight.update()\n            dogWalkRight.draw()\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        case 'parado-esquerda':\n            dogStoppedLeft.update()\n            dogStoppedLeft.draw()\n        case 'andando-esquerda':\n            dogWalkLeft.update()\n            dogWalkLeft.draw()<\/mark>\n\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    if dogState == 'andando-direita' or dogState == 'parado-direita':\n        dogState = 'parado-direita'\n    if dogState == 'andando-esquerda' or dogState == 'parado-esquerda':\n        dogState = 'parado-esquerda'<\/mark>\n\n    if teclado.key_pressed('RIGHT'):\n        dogState = 'andando-direita'\n        posxDog += velxDog * janela.<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">delta_time()<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    <\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">elif<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\"> teclado.key_pressed('LEFT'):\n        dogState = 'andando-esquerda'\n        posxDog -= velxDog * janela.<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">delta_time()<\/mark>\n    \n    movimentoDog()\n    \n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n    desenhoDog()\n    janela.update()\n\n\n<\/code><\/pre>\n\n\n\n<p>Neste ponto \u00e9 interessante fazer 2 coment\u00e1rios. Um diz respeito do uso do &#8220;elif&#8221; no c\u00f3digo. Ele indica que h\u00e1 uma prefer\u00eancia do c\u00e3o andar para a direita caso as teclas de direita e esquerda sejam pressionadas juntas. Assim, o c\u00e3o ir\u00e1 se movimentar de fato para a direita. Caso tiv\u00e9ssemos usado apenas o &#8220;if&#8221; o estado do c\u00e3o se atualizaria para &#8220;andando-esqueda&#8221; ao final desse conjunto de condicionais, mas a sua posi\u00e7\u00e3o se manteria a mesma, dando a impress\u00e3o que o c\u00e3o est\u00e1 andando em uma esteira, sem sair do lugar.<\/p>\n\n\n\n<p>O outro coment\u00e1rio diz respeito ao udo do delta_time(). Como usaremos essa fun\u00e7\u00e3o de maneira mais frequente no c\u00f3digo, \u00e9 interessante cham\u00e1-la uma \u00fanica vez no in\u00edcio do loop, armazenando o valor do tempo em uma vari\u00e1vel e usando esta vari\u00e1vel quando necess\u00e1rio. Isso reduz o processamento durante a execu\u00e7\u00e3o do jogo, melhorando a efici\u00eancia do c\u00f3digo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Salto<\/h2>\n\n\n\n<p>Para implementar o salto do c\u00e3o precisamos fazer v\u00e1rias altera\u00e7\u00f5es no c\u00f3digo, al\u00e9m de implementar equa\u00e7\u00f5es da f\u00edsica de um corpo em queda livre (para fazermos o movimento parab\u00f3lico da queda do c\u00e3o.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">posyInicial = 320<\/mark>\nposxDog = 100\nposyDog = posyInicial\nvelxDog = 250\ndogState = 'parado-direita'\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">velInicialSalto = -400\nvelyDog = 0\ngrav = 700<\/mark>\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\ndogStoppedLeft = Sprite(\"dogStoppedLeft.webp\", 6)\ndogStoppedLeft.set_sequence_time(0, 6, 400, True)\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\ndogWalkLeft = Sprite(\"dogWalkLeft.webp\", 6)\ndogWalkLeft.set_sequence_time(0, 6, 100, True)\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">dogJumpRight = Sprite(\"dogJumpRight.webp\", 5)\ndogJumpRight.set_sequence_time(0, 4, 100, False)\ndogJumpLeft = Sprite(\"dogJumpLeft.webp\", 5)\ndogJumpLeft.set_sequence_time(0, 4, 100, False)<\/mark>\n\n\ndef movimentoDog():\n    dogStoppedRight.x = posxDog\n    dogStoppedRight.y = posyDog\n    dogStoppedLeft.x = posxDog\n    dogStoppedLeft.y = posyDog\n    dogWalkRight.x = posxDog\n    dogWalkRight.y = posyDog\n    dogWalkLeft.x = posxDog\n    dogWalkLeft.y = posyDog\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    dogJumpRight.x = posxDog\n    dogJumpRight.y = posyDog\n    dogJumpLeft.x = posxDog\n    dogJumpLeft.y = posyDog<\/mark>\n\n\ndef desenhoDog():\n    match dogState:\n        case 'parado-direita':\n            dogStoppedRight.update()\n            dogStoppedRight.draw()\n        case 'andando-direita':\n            dogWalkRight.update()\n            dogWalkRight.draw()\n        case 'parado-esquerda':\n            dogStoppedLeft.update()\n            dogStoppedLeft.draw()\n        case 'andando-esquerda':\n            dogWalkLeft.update()\n            dogWalkLeft.draw()\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        case 'saltando-direita':\n            dogJumpRight.update()\n            dogJumpRight.draw()\n        case 'saltando-esquerda':\n            dogJumpLeft.update()\n            dogJumpLeft.draw()<\/mark>\n\n\nwhile True:\n    deltatempo = janela.delta_time()\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n    if dogState == 'andando-direita' or dogState == 'parado-direita':\n        dogState = 'parado-direita'\n    if dogState == 'andando-esquerda' or dogState == 'parado-esquerda':\n        dogState = 'parado-esquerda'\n\n    if teclado.key_pressed('RIGHT'):\n        posxDog += velxDog * deltatempo\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">            dogState = 'andando-direita'\n<\/mark>    elif teclado.key_pressed('LEFT'):\n        posxDog -= velxDog * deltatempo\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">            dogState = 'andando-esquerda'\n<\/mark>    \n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    if teclado.key_pressed('SPACE'):\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        if not dogState == 'saltando-direita' and not dogState == 'saltando-esquerda':<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">            velyDog = velInicialSalto # Apenas na primeira entrada do condicional que avalia a tecla \"SPACE\" pressionada\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        if (dogState == 'parado-direita' or dogState == 'andando-direita'):\n            dogState = 'saltando-direita'\n        elif(dogState == 'parado-esquerda' or dogState == 'andando-esquerda'):\n            dogState = 'saltando-esquerda'\n    \n    if dogState == 'saltando-direita' or dogState == 'saltando-esquerda':\n        # Queda Livre\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        posyDog += velyDog * deltatempo + (grav * (deltatempo ** 2) ) \/ 2\n        velyDog += grav * deltatempo<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">\n    \n    if posyDog &gt; posyInicial:\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        posyDog = posyInicial\n<\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        velyDog = 0\n        if dogState == 'saltando-direita':\n            dogState = 'parado-direita'\n        elif dogState == 'saltando-esquerda':\n            dogState = 'parado-esquerda'<\/mark>\n    \n    \n    movimentoDog()\n    \n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n    desenhoDog()\n    janela.update()<\/code><\/pre>\n\n\n\n<p>As primeiras linhas em amarelo dizem respeito a f\u00edsica do movimento do c\u00e3o. Temos que definir uma posi\u00e7\u00e3o y inicial que representa a altura que a imagem do c\u00e3o fica quando ele est\u00e1 apoiado no ch\u00e3o, e definimos tamb\u00e9m uma velocidade com a qual ele inicia o o salto ( ser\u00e1 um valor fixo e negativo pois os valores de y diminuem no sentido para cima). Tamb\u00e9m definimos uma velocidade vertical para o cachorro (que inicia com o valor que definimos para o in\u00edcio do salto e ir\u00e1 atualizar ao longo de sua queda livre), e um valor pra gravidade que pode ser calibrada posteriormente.<\/p>\n\n\n\n<p>Instanciamos e configuramos os sprites de salto antes do GameLoop e definimos seu movimento e implementamos seu desenho dentro das fun\u00e7\u00f5es espec\u00edficas para estes fins que ser\u00e3o chamadas no GameLoop.<\/p>\n\n\n\n<p>Agora precisamos fazer algumas altera\u00e7\u00f5es para entrarmos corretamente no condicional que altera o estado do cachorro quado as teclas &#8220;RIGHT&#8221; ou &#8220;LEFT&#8221; s\u00e3o pressionadas. Se o c\u00e3o est\u00e1 pulando, continuamdo querendo que a posi\u00e7\u00e3o horizontal do c\u00e3o se altere, mas n\u00e3o queremos que a imagem desenhada da tela seja de um cachorro andando, j\u00e1 que ele est\u00e1 pulando.<\/p>\n\n\n\n<p>Quando a tecla &#8220;SPACE&#8221; \u00e9 pressionada, ent\u00e3o queremos alterar a velocidade vertical do c\u00e3o apenas na primeira entrada deste condicional (caso contr\u00e1rio o c\u00e3o ir\u00e1 subir enquanto a tecla space estiver sendo pressionada). Assim, alteramos a velocidade apenas se o seu estado n\u00e3o for pulando. Alteramos ent\u00e3o o estado do c\u00e3o para pulando e executamos a queda livre sempre que ele estiver nesse estado.<\/p>\n\n\n\n<p>O c\u00e3o sai da queda livre quando ele atinge o ch\u00e3o, ou seja, quando atinge o y inicial. \u00c9 importante reposicionar o c\u00e3o corretamente pois ele pode atingir um y maior que o inicial, e resetamos tamb\u00e9m sua velocidade e estado.<\/p>\n\n\n\n<p>Aqui temos que fazer tr\u00eas coment\u00e1rios. O primeiro diz respeito ao sprite do salto. Ele tem 5 frames, mas paramos no quarto frame. Isso foi feito porque esse \u00e9 o frame em que o c\u00e3o est\u00e1 voando no ar, e o \u00faltimo frame deve ser usado apenas para o pouso. Al\u00e9m disso, apenas o primeiro salto mostra o c\u00e3o pegando impulso, e o restante apenas usa o quarto frame. O terceiro coment\u00e1rio \u00e9 que o c\u00e3o n\u00e3o est\u00e1 virando no ar quando mudamos a dire\u00e7\u00e3o durante o salto. Vamos focar em resolver estes tr\u00eas problemas agora.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\nposyInicial = 320\nposxDog = 100\nposyDog = posyInicial\nvelxDog = 250\ndogState = 'parado-direita'\nvelInicialSalto = -400\nvelyDog = 0\ngrav = 700\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">disparaTemporizadorPouso = False\ntempoPouso = 0<\/mark>\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\ndogStoppedLeft = Sprite(\"dogStoppedLeft.webp\", 6)\ndogStoppedLeft.set_sequence_time(0, 6, 400, True)\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\ndogWalkLeft = Sprite(\"dogWalkLeft.webp\", 6)\ndogWalkLeft.set_sequence_time(0, 6, 100, True)\ndogJumpRight = Sprite(\"dogJumpRight.webp\", 5)\ndogJumpRight.set_sequence_time(0, 4, 100, False)\ndogJumpLeft = Sprite(\"dogJumpLeft.webp\", 5)\ndogJumpLeft.set_sequence_time(0, 4, 100, False)\n\n\ndef movimentoDog():\n    dogStoppedRight.x = posxDog\n    dogStoppedRight.y = posyDog\n    dogStoppedLeft.x = posxDog\n    dogStoppedLeft.y = posyDog\n    dogWalkRight.x = posxDog\n    dogWalkRight.y = posyDog\n    dogWalkLeft.x = posxDog\n    dogWalkLeft.y = posyDog\n    dogJumpRight.x = posxDog\n    dogJumpRight.y = posyDog\n    dogJumpLeft.x = posxDog\n    dogJumpLeft.y = posyDog\n\n\ndef desenhoDog():\n    match dogState:\n        case 'parado-direita':\n            dogStoppedRight.update()\n            dogStoppedRight.draw()\n        case 'andando-direita':\n            dogWalkRight.update()\n            dogWalkRight.draw()\n        case 'parado-esquerda':\n            dogStoppedLeft.update()\n            dogStoppedLeft.draw()\n        case 'andando-esquerda':\n            dogWalkLeft.update()\n            dogWalkLeft.draw()\n        case 'saltando-direita':\n            dogJumpRight.update()\n            dogJumpRight.draw()\n        case 'saltando-esquerda':\n            dogJumpLeft.update()\n            dogJumpLeft.draw()\n\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n    deltatempo = janela.delta_time()\n    if dogState == 'andando-direita' or dogState == 'parado-direita':\n        dogState = 'parado-direita'\n    if dogState == 'andando-esquerda' or dogState == 'parado-esquerda':\n        dogState = 'parado-esquerda'\n\n    if teclado.key_pressed('RIGHT'):\n        posxDog += velxDog * deltatempo\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-direita'\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        if dogState == 'saltando-esquerda':\n            dogState = 'saltando-direita'<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">            dogJumpLeft.stop()\n            dogJumpRight.set_sequence_time(3, 4, 200, False)<\/mark>\n\n    elif teclado.key_pressed('LEFT'):\n        posxDog -= velxDog * deltatempo\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-esquerda'\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        if dogState == 'saltando-direita':\n            dogState = 'saltando-esquerda'<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">            dogJumpRight.stop()\n            dogJumpLeft.set_sequence_time(3, 4, 200, False)<\/mark>\n    \n\n    if teclado.key_pressed('SPACE'):\n        if not dogState == 'saltando-direita' and not dogState == 'saltando-esquerda':\n            velyDog = velInicialSalto\n        if (dogState == 'parado-direita' or dogState == 'andando-direita'):\n            dogState = 'saltando-direita'\n        elif(dogState == 'parado-esquerda' or dogState == 'andando-esquerda'):\n            dogState = 'saltando-esquerda'\n    \n    if dogState == 'saltando-direita' or dogState == 'saltando-esquerda':\n        # Queda Livre\n        posyDog += velyDog * deltatempo + (grav * (deltatempo ** 2) ) \/ 2\n        velyDog += grav * deltatempo\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        dogJumpRight.play()\n        dogJumpLeft.play()<\/mark>\n    \n    if posyDog &gt; posyInicial:\n        posyDog = posyInicial\n        velyDog = 0\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        dogJumpLeft.set_sequence_time(4, 5, 100, False)\n        dogJumpRight.set_sequence_time(4, 5, 100, False)\n        disparaTemporizadorPouso = True\n<\/mark>\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    if disparaTemporizadorPouso:\n        tempoPouso += deltatempo\n        if tempoPouso &gt; 0.1:\n            tempoPouso = 0\n            disparaTemporizadorPouso = False\n            dogJumpLeft.set_sequence_time(0, 4, 100, False)\n            dogJumpRight.set_sequence_time(0, 4, 100, False)\n            if dogState == 'saltando-direita':\n                dogState = 'parado-direita'\n            if dogState == 'saltando-esquerda':\n                dogState = 'parado-esquerda'<\/mark>\n                \n    \n    movimentoDog()\n    \n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n    desenhoDog()\n    janela.update()\n<\/code><\/pre>\n\n\n\n<p>O temporizador declarado no in\u00edcio do c\u00f3digo ir\u00e1 disparar quando o c\u00e3o voltar a tocar o solo ap\u00f3s o salto. Neste momento o sprite de pouso ser\u00e1 executado em um intervalo de tempo definido no final do c\u00f3digo (0.1 s). Ap\u00f3s esse tempo resetamos o sprite, o estado do c\u00e3o, as vari\u00e1veis do temporizador e o sprite de salto.<\/p>\n\n\n\n<p>Dentro dos condicionais que avaliam a dire\u00e7\u00e3o do movimento do c\u00e3o adicionamos um condicional que permite que o sprite mude de dire\u00e7\u00e3o durante o salto e evitamos que toda sequencia de pegar impulso seja executada novamente configurando o sprite no frame do v\u00f4o. Al\u00e9m disso, configuramos o sprite para realizar a anima\u00e7\u00e3o do pulo novamente atrav\u00e9s da fun\u00e7\u00e3o &#8220;play()&#8221;. Isso \u00e9 importante ap\u00f3s reconfigurar os frames que precisam ser exibidos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">C\u00e2mera Din\u00e2mica<\/h2>\n\n\n\n<p>Vamos impedir que o c\u00e3o se mova e fazer o cen\u00e1rio se mover no sentido oposto para dar a impress\u00e3o que a c\u00e2mera est\u00e1 acompanhando o cachorro. Quando o c\u00e3o chegar no final da janela, o cen\u00e1rio para de se mover e o c\u00e3o se move pela janela.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\ndogState = 'parado-direita'\nposxDog = 100\nposyInicial = 320\nposyDog = posyInicial\nvelyDog = 0\ndisparaTemporizadorPouso = False\ntempoPouso = 0\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">posxCamera = 0\n<\/mark>\n# Calibra\u00e7\u00e3o\nvelxDog = 250\nvelInicialSalto = -400\ngrav = 700\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\ndogStoppedLeft = Sprite(\"dogStoppedLeft.webp\", 6)\ndogStoppedLeft.set_sequence_time(0, 6, 400, True)\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\ndogWalkLeft = Sprite(\"dogWalkLeft.webp\", 6)\ndogWalkLeft.set_sequence_time(0, 6, 100, True)\ndogJumpRight = Sprite(\"dogJumpRight.webp\", 5)\ndogJumpRight.set_sequence_time(0, 4, 100, False)\ndogJumpLeft = Sprite(\"dogJumpLeft.webp\", 5)\ndogJumpLeft.set_sequence_time(0, 4, 100, False)\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">def movimentoCamera():\n    cenario.x = posxCamera<\/mark>\n\ndef movimentoDog():\n    dogStoppedRight.x = posxDog\n    dogStoppedRight.y = posyDog\n    dogStoppedLeft.x = posxDog\n    dogStoppedLeft.y = posyDog\n    dogWalkRight.x = posxDog\n    dogWalkRight.y = posyDog\n    dogWalkLeft.x = posxDog\n    dogWalkLeft.y = posyDog\n    dogJumpRight.x = posxDog\n    dogJumpRight.y = posyDog\n    dogJumpLeft.x = posxDog\n    dogJumpLeft.y = posyDog\n\n\ndef desenhoDog():\n    match dogState:\n        case 'parado-direita':\n            dogStoppedRight.update()\n            dogStoppedRight.draw()\n        case 'andando-direita':\n            dogWalkRight.update()\n            dogWalkRight.draw()\n        case 'parado-esquerda':\n            dogStoppedLeft.update()\n            dogStoppedLeft.draw()\n        case 'andando-esquerda':\n            dogWalkLeft.update()\n            dogWalkLeft.draw()\n        case 'saltando-direita':\n            dogJumpRight.update()\n            dogJumpRight.draw()\n        case 'saltando-esquerda':\n            dogJumpLeft.update()\n            dogJumpLeft.draw()\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n    deltatempo = janela.delta_time()\n    if dogState == 'andando-direita' or dogState == 'parado-direita':\n        dogState = 'parado-direita'\n    if dogState == 'andando-esquerda' or dogState == 'parado-esquerda':\n        dogState = 'parado-esquerda'\n\n    if teclado.key_pressed('RIGHT'):\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        if posxCamera &gt; janela.width - cenario.width:\n            posxCamera -= velxDog * deltatempo\n        else:\n            posxDog += velxDog * deltatempo<\/mark>\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-direita'\n        if dogState == 'saltando-esquerda':\n            dogState = 'saltando-direita'\n            dogJumpLeft.stop()\n            dogJumpRight.set_sequence_time(3, 4, 200, False)\n\n    elif teclado.key_pressed('LEFT'):\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        if posxCamera &lt; 0:\n            posxCamera += velxDog * deltatempo\n        else:\n            posxDog -= velxDog * deltatempo<\/mark>\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-esquerda'\n        if dogState == 'saltando-direita':\n            dogState = 'saltando-esquerda'\n            dogJumpRight.stop()\n            dogJumpLeft.set_sequence_time(3, 4, 200, False)\n    \n    # Salto\n    if teclado.key_pressed('SPACE'):\n        if not dogState == 'saltando-direita' and not dogState == 'saltando-esquerda':\n            velyDog = velInicialSalto\n        if (dogState == 'parado-direita' or dogState == 'andando-direita'):\n            dogState = 'saltando-direita'\n        elif(dogState == 'parado-esquerda' or dogState == 'andando-esquerda'):\n            dogState = 'saltando-esquerda'\n    \n    if dogState == 'saltando-direita' or dogState == 'saltando-esquerda':\n        # Queda Livre\n        posyDog += velyDog * deltatempo + (grav * (deltatempo ** 2) ) \/ 2\n        velyDog += grav * deltatempo\n        dogJumpRight.play()\n        dogJumpLeft.play()\n    \n    if posyDog &gt; posyInicial:\n        posyDog = posyInicial\n        velyDog = 0\n        dogJumpLeft.set_sequence_time(4, 5, 100, False)\n        dogJumpRight.set_sequence_time(4, 5, 100, False)\n        disparaTemporizadorPouso = True\n\n    if disparaTemporizadorPouso:\n        tempoPouso += deltatempo\n        if tempoPouso &gt; 0.1:\n            tempoPouso = 0\n            disparaTemporizadorPouso = False\n            dogJumpLeft.set_sequence_time(0, 4, 100, False)\n            dogJumpRight.set_sequence_time(0, 4, 100, False)\n            if dogState == 'saltando-direita':\n                dogState = 'parado-direita'\n            if dogState == 'saltando-esquerda':\n                dogState = 'parado-esquerda'\n                \n            \n    movimentoDog()\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    movimentoCamera()\n<\/mark>    \n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n    desenhoDog()\n    janela.update()<\/code><\/pre>\n\n\n\n<p>Agora temos um problema. Quando o c\u00e3o anda at\u00e9 sair do cen\u00e1rio e pressionamos a tecla para ir para o lado oposto, o c\u00e3o n\u00e3o retoma a sua posi\u00e7\u00e3o inicial antes do cen\u00e1rio come\u00e7ar a andar novamente. Al\u00e9m disso temos que implementar melhorias no posicionamento da c\u00e2mera para que seja enfatizado o que est\u00e1 na frente do c\u00e3o.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\ndogState = 'parado-direita'\nposxDog = 100\nposyInicial = 320\nposyDog = posyInicial\nvelyDog = 0\ndisparaTemporizadorPouso = False\ntempoPouso = 0\nposxCamera = 0\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">AtivarPosCamDir = False\nAtivarPosCamEsq = False<\/mark>\n\n# Calibra\u00e7\u00e3o\nvelxDog = 250\nvelInicialSalto = -400\ngrav = 700\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">velxPosCam = 1000<\/mark>\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\ndogStoppedLeft = Sprite(\"dogStoppedLeft.webp\", 6)\ndogStoppedLeft.set_sequence_time(0, 6, 400, True)\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\ndogWalkLeft = Sprite(\"dogWalkLeft.webp\", 6)\ndogWalkLeft.set_sequence_time(0, 6, 100, True)\ndogJumpRight = Sprite(\"dogJumpRight.webp\", 5)\ndogJumpRight.set_sequence_time(0, 4, 100, False)\ndogJumpLeft = Sprite(\"dogJumpLeft.webp\", 5)\ndogJumpLeft.set_sequence_time(0, 4, 100, False)\n\ndef movimentoCamera():\n    cenario.x = posxCamera\n\ndef movimentoDog():\n    dogStoppedRight.x = posxDog\n    dogStoppedRight.y = posyDog\n    dogStoppedLeft.x = posxDog\n    dogStoppedLeft.y = posyDog\n    dogWalkRight.x = posxDog\n    dogWalkRight.y = posyDog\n    dogWalkLeft.x = posxDog\n    dogWalkLeft.y = posyDog\n    dogJumpRight.x = posxDog\n    dogJumpRight.y = posyDog\n    dogJumpLeft.x = posxDog\n    dogJumpLeft.y = posyDog\n\n\ndef desenhoDog():\n    match dogState:\n        case 'parado-direita':\n            dogStoppedRight.update()\n            dogStoppedRight.draw()\n        case 'andando-direita':\n            dogWalkRight.update()\n            dogWalkRight.draw()\n        case 'parado-esquerda':\n            dogStoppedLeft.update()\n            dogStoppedLeft.draw()\n        case 'andando-esquerda':\n            dogWalkLeft.update()\n            dogWalkLeft.draw()\n        case 'saltando-direita':\n            dogJumpRight.update()\n            dogJumpRight.draw()\n        case 'saltando-esquerda':\n            dogJumpLeft.update()\n            dogJumpLeft.draw()\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n    deltatempo = janela.delta_time()\n    if dogState == 'andando-direita' or dogState == 'parado-direita':\n        dogState = 'parado-direita'\n    if dogState == 'andando-esquerda' or dogState == 'parado-esquerda':\n        dogState = 'parado-esquerda'\n\n    if teclado.key_pressed('RIGHT'):\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        # Se o c\u00e3o ta antes da posi\u00e7\u00e3o 100px, coloca o c\u00e3o na posi\u00e7\u00e3o 100px\n        if posxDog &lt; 100:\n            posxDog += velxDog * deltatempo\n        # Se a c\u00e2mera n\u00e3o chegou no fim, rola a c\u00e2mera\n        if posxDog &gt;= 100 and posxCamera &gt; janela.width - cenario.width:\n            posxCamera -= velxDog * deltatempo\n        # Se chegou no fim do cen\u00e1rio e o c\u00e3o n\u00e3o saiu do cen\u00e1rio, o c\u00e3o pode andar\n        if posxCamera &lt;= janela.width - cenario.width and posxDog &lt; 700 - dogWalkRight.width:\n            posxDog += velxDog * deltatempo<\/mark>\n\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-direita'\n        if dogState == 'saltando-esquerda':\n            dogState = 'saltando-direita'\n            dogJumpLeft.stop()\n            dogJumpRight.set_sequence_time(3, 4, 200, False)\n\n    elif teclado.key_pressed('LEFT'):\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">        # Se o c\u00e3o ta depois de 500px, posiciona ele em 500px\n        if posxDog &gt; 500:\n            posxDog -= velxDog * deltatempo\n        # Se a c\u00e2mera n\u00e3o cheogu no in\u00edcio do cen\u00e1rio, rola a c\u00e2mera\n        if posxDog &lt;= 500 and posxCamera &lt; 0:\n            posxCamera += velxDog * deltatempo\n        # Se chegou no fim do cen\u00e1rio e o c\u00e3o n\u00e3o saiu do cen\u00e1rio, o c\u00e3o pode andar\n        if posxCamera &gt;= 0 and posxDog &gt; 0:\n            posxDog -= velxDog * deltatempo<\/mark>\n\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-esquerda'\n        if dogState == 'saltando-direita':\n            dogState = 'saltando-esquerda'\n            dogJumpRight.stop()\n            dogJumpLeft.set_sequence_time(3, 4, 200, False)\n    \n    # Salto\n    if teclado.key_pressed('SPACE'):\n        if not dogState == 'saltando-direita' and not dogState == 'saltando-esquerda':\n            velyDog = velInicialSalto\n        if (dogState == 'parado-direita' or dogState == 'andando-direita'):\n            dogState = 'saltando-direita'\n        elif(dogState == 'parado-esquerda' or dogState == 'andando-esquerda'):\n            dogState = 'saltando-esquerda'\n    \n    if dogState == 'saltando-direita' or dogState == 'saltando-esquerda':\n        # Queda Livre\n        posyDog += velyDog * deltatempo + (grav * (deltatempo ** 2) ) \/ 2\n        velyDog += grav * deltatempo\n        dogJumpRight.play()\n        dogJumpLeft.play()\n    \n    if posyDog &gt; posyInicial:\n        posyDog = posyInicial\n        velyDog = 0\n        dogJumpLeft.set_sequence_time(4, 5, 100, False)\n        dogJumpRight.set_sequence_time(4, 5, 100, False)\n        disparaTemporizadorPouso = True\n\n    if disparaTemporizadorPouso:\n        tempoPouso += deltatempo\n        if tempoPouso &gt; 0.1:\n            tempoPouso = 0\n            disparaTemporizadorPouso = False\n            dogJumpLeft.set_sequence_time(0, 4, 100, False)\n            dogJumpRight.set_sequence_time(0, 4, 100, False)\n            if dogState == 'saltando-direita':\n                dogState = 'parado-direita'\n            if dogState == 'saltando-esquerda':\n                dogState = 'parado-esquerda'\n\n\n    # Movimenta\u00e7\u00e3o da C\u00e2mera\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    if (dogState == 'andando-direita' or dogState == 'parado-direita' or dogState == 'saltando-direita') and posxDog &gt; 100 and posxCamera &gt; janela.width - cenario.width:\n        AtivarPosCamDir = True\n    if AtivarPosCamDir:\n        posxDog -= velxPosCam * deltatempo\n        posxCamera -= velxPosCam * deltatempo\n        if posxDog &lt; 100 or posxCamera &lt;= janela.width - cenario.width:\n            AtivarPosCamDir = False\n\n    if (dogState == 'andando-esquerda' or dogState == 'parado-esquerda' or dogState == 'saltando-esquerda') and posxDog &lt; 500 and posxCamera &lt; 0:\n        AtivarPosCamEsq = True\n    if AtivarPosCamEsq:\n        posxDog += velxPosCam * deltatempo\n        posxCamera += velxPosCam * deltatempo\n        if posxDog &gt; 500 or posxCamera &gt;= 0:\n            AtivarPosCamEsq = False<\/mark>\n    \n            \n    movimentoDog()\n    movimentoCamera() \n    \n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n    desenhoDog()\n    janela.update()\n\n\n<\/code><\/pre>\n\n\n\n<p>Neste c\u00f3digo adicionamos o movimento din\u00e2mico da c\u00e2mera de acordo com como o c\u00e3o est\u00e1 na tela. Se ele estiver virado para direita, mas posicionado muito \u00e0 esquerda da tela (mais que 100px) e se ainda tem cen\u00e1rio para mostrar no lado direito, ent\u00e3o a c\u00e2mera se movimentar\u00e1 para mostrar esse cen\u00e1rio. O movimento da c\u00e2mera cessa quando o c\u00e3o atinge os 100px ou quando o cen\u00e1rio acaba. Caso a condi\u00e7\u00e3o de parada seja de acordo com a posi\u00e7\u00e3o do cachorro, reposicionamos ele na tela para evitar escorregamento.<\/p>\n\n\n\n<p>Os condicionais que definem como a c\u00e2mera e o c\u00e3o devem se movimentar foi redefinida e destacada em amarelo. Os coment\u00e1rios explicam o que est\u00e1 sendo testado em cada um dos 3 condicionais.<\/p>\n\n\n\n<p>A essa altura voc\u00ea deve estar se perguntando por que temos uma fun\u00e7\u00e3o separada com uma \u00fanica linha para fazer o movimento do cen\u00e1rio? O objetivo de manter esta fun\u00e7\u00e3o \u00e9 que podemos adicionar elementos ao cen\u00e1rio que est\u00e3o em uma camada acima. Percebemos por exemplo que quando movemos o c\u00e3o para a esquerda ele fica na frente da \u00e1rvore, dando um efeito visual ruim. Vamos corrigir isso.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PPlay.window import *\nfrom PPlay.gameimage import *\nfrom PPlay.keyboard import *\nfrom PPlay.sprite import *\n\n# DEFINI\u00c7\u00d5ES INICIAIS\n# Vari\u00e1veis\ndogState = 'parado-direita'\nposxDog = 100\nposyInicial = 320\nposyDog = posyInicial\nvelyDog = 0\ndisparaTemporizadorPouso = False\ntempoPouso = 0\nposxCamera = 0\nAtivarPosCamDir = False\nAtivarPosCamEsq = False\n\n# Calibra\u00e7\u00e3o\nvelxDog = 250\nvelInicialSalto = -400\ngrav = 700\nvelxPosCam = 1000\n\n# Objetos\njanela = Window(700,500)\ncenario = GameImage(\"cenario.webp\")\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">arvore = GameImage(\"arvore.webp\")\ncobra = Sprite(\"snake-sprite.png\", 4)\ncobra.set_sequence_time(0, 4, 400, True)\ncobra.y = 360<\/mark>\nteclado = Keyboard()\n\ndogStoppedRight = Sprite(\"dogStoppedRight.webp\", 6)\ndogStoppedRight.set_sequence_time(0, 6, 400, True)\ndogStoppedLeft = Sprite(\"dogStoppedLeft.webp\", 6)\ndogStoppedLeft.set_sequence_time(0, 6, 400, True)\ndogWalkRight = Sprite(\"dogWalkRight.webp\", 6)\ndogWalkRight.set_sequence_time(0, 6, 100, True)\ndogWalkLeft = Sprite(\"dogWalkLeft.webp\", 6)\ndogWalkLeft.set_sequence_time(0, 6, 100, True)\ndogJumpRight = Sprite(\"dogJumpRight.webp\", 5)\ndogJumpRight.set_sequence_time(0, 4, 100, False)\ndogJumpLeft = Sprite(\"dogJumpLeft.webp\", 5)\ndogJumpLeft.set_sequence_time(0, 4, 100, False)\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">dogDieRight = Sprite(\"dogDieRight.webp\", 7)\ndogDieRight.set_sequence_time(0, 7, 100, False)\ndogDieLeft = Sprite(\"dogDieLeft.webp\", 7)\ndogDieLeft.set_sequence_time(0, 7, 100, False)<\/mark>\n\ndef movimentoCamera():\n    cenario.x = posxCamera\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    arvore.x = posxCamera\n    cobra.x = posxCamera + 800<\/mark>\n\ndef movimentoDog():\n    dogStoppedRight.x = posxDog\n    dogStoppedRight.y = posyDog\n    dogStoppedLeft.x = posxDog\n    dogStoppedLeft.y = posyDog\n    dogWalkRight.x = posxDog\n    dogWalkRight.y = posyDog\n    dogWalkLeft.x = posxDog\n    dogWalkLeft.y = posyDog\n    dogJumpRight.x = posxDog\n    dogJumpRight.y = posyDog\n    dogJumpLeft.x = posxDog\n    dogJumpLeft.y = posyDog\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    dogDieRight.x = posxDog\n    dogDieRight.y = posyDog\n    dogDieLeft.x = posxDog\n    dogDieLeft.y = posyDog<\/mark>\n\ndef desenhoDog():\n    match dogState:\n        case 'parado-direita':\n            dogStoppedRight.update()\n            dogStoppedRight.draw()\n        case 'andando-direita':\n            dogWalkRight.update()\n            dogWalkRight.draw()\n        case 'parado-esquerda':\n            dogStoppedLeft.update()\n            dogStoppedLeft.draw()\n        case 'andando-esquerda':\n            dogWalkLeft.update()\n            dogWalkLeft.draw()\n        case 'saltando-direita':\n            dogJumpRight.update()\n            dogJumpRight.draw()\n        case 'saltando-esquerda':\n            dogJumpLeft.update()\n            dogJumpLeft.draw()\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">        case 'morrendo-direita':\n            dogDieRight.update()\n            dogDieRight.draw()\n        case 'morrendo-esquerda':\n            dogDieLeft.update()\n            dogDieLeft.draw()<\/mark>\n\nwhile True:\n    # ATUALIZA\u00c7\u00c3O DE VARI\u00c1VEIS\n    deltatempo = janela.delta_time()\n    if dogState == 'andando-direita' or dogState == 'parado-direita':\n        dogState = 'parado-direita'\n    if dogState == 'andando-esquerda' or dogState == 'parado-esquerda':\n        dogState = 'parado-esquerda'\n\n    if teclado.key_pressed('RIGHT') <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">and not (dogState == 'morrendo-direita' or dogState == 'morrendo-esquerda')<\/mark>:\n        if posxDog &lt; 100:\n            posxDog += velxDog * deltatempo\n        if posxDog &gt;= 100 and posxCamera &gt; janela.width - cenario.width:\n            posxCamera -= velxDog * deltatempo\n        if posxCamera &lt;= janela.width - cenario.width and posxDog &lt; 700 - dogWalkRight.width:\n            posxDog += velxDog * deltatempo\n\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-direita'\n        if dogState == 'saltando-esquerda':\n            dogState = 'saltando-direita'\n            dogJumpLeft.stop()\n            dogJumpRight.set_sequence_time(3, 4, 200, False)\n\n    elif teclado.key_pressed('LEFT') <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">and not (dogState == 'morrendo-direita' or dogState == 'morrendo-esquerda')<\/mark>:\n        if posxDog &gt; 500:\n            posxDog -= velxDog * deltatempo\n        if posxDog &lt;= 500 and posxCamera &lt; 0:\n            posxCamera += velxDog * deltatempo\n        if posxCamera &gt;= 0 and posxDog &gt; 0:\n            posxDog -= velxDog * deltatempo\n\n        if not (dogState == 'saltando-direita' or dogState == 'saltando-esquerda'):\n            dogState = 'andando-esquerda'\n        if dogState == 'saltando-direita':\n            dogState = 'saltando-esquerda'\n            dogJumpRight.stop()\n            dogJumpLeft.set_sequence_time(3, 4, 200, False)\n\n\n\n    # Salto\n    if teclado.key_pressed('SPACE'):\n        if not dogState == 'saltando-direita' and not dogState == 'saltando-esquerda':\n            velyDog = velInicialSalto\n        if (dogState == 'parado-direita' or dogState == 'andando-direita'):\n            dogState = 'saltando-direita'\n        elif(dogState == 'parado-esquerda' or dogState == 'andando-esquerda'):\n            dogState = 'saltando-esquerda'\n    \n    if dogState == 'saltando-direita' or dogState == 'saltando-esquerda' <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-luminous-vivid-amber-color\">or dogState == 'morrendo-direita' or dogState == 'morrendo-esquerda'<\/mark>:\n        # Queda Livre\n        posyDog += velyDog * deltatempo + (grav * (deltatempo ** 2) ) \/ 2\n        velyDog += grav * deltatempo\n        dogJumpRight.play()\n        dogJumpLeft.play()\n    \n    if posyDog &gt; posyInicial:\n        posyDog = posyInicial\n        velyDog = 0\n        dogJumpLeft.set_sequence_time(4, 5, 100, False)\n        dogJumpRight.set_sequence_time(4, 5, 100, False)\n        disparaTemporizadorPouso = True\n\n    if disparaTemporizadorPouso:\n        tempoPouso += deltatempo\n        if tempoPouso &gt; 0.1:\n            tempoPouso = 0\n            disparaTemporizadorPouso = False\n            dogJumpLeft.set_sequence_time(0, 4, 100, False)\n            dogJumpRight.set_sequence_time(0, 4, 100, False)\n            if dogState == 'saltando-direita':\n                dogState = 'parado-direita'\n            if dogState == 'saltando-esquerda':\n                dogState = 'parado-esquerda'\n\n\n\n\n    # Movimenta\u00e7\u00e3o da C\u00e2mera\n    if (dogState == 'andando-direita' or dogState == 'parado-direita' or dogState == 'saltando-direita') and posxDog &gt; 100 and posxCamera &gt; janela.width - cenario.width:\n        AtivarPosCamDir = True\n    if AtivarPosCamDir:\n        posxDog -= velxPosCam * deltatempo\n        posxCamera -= velxPosCam * deltatempo\n        if posxDog &lt; 100 or posxCamera &lt;= janela.width - cenario.width:\n            AtivarPosCamDir = False\n            if posxDog &lt; 100: # Evitar Escorregamento\n                posxDog = 100\n            \n\n    if (dogState == 'andando-esquerda' or dogState == 'parado-esquerda' or dogState == 'saltando-esquerda') and posxDog &lt; 500 and posxCamera &lt; 0:\n        AtivarPosCamEsq = True\n    if AtivarPosCamEsq:\n        posxDog += velxPosCam * deltatempo\n        posxCamera += velxPosCam * deltatempo\n        if posxDog &gt; 500 or posxCamera &gt;= 0:\n            AtivarPosCamEsq = False\n            if posxDog &gt; 500: # Evitar Escorregamento\n                posxDog = 500    \n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    if posxDog + dogStoppedRight.width - 30 &gt; cobra.x and posxDog + 30 &lt; cobra.x + cobra.width and posyDog + dogStoppedRight.height - 30 &gt; cobra.y:\n        if (dogState == 'andando-esquerda' or dogState == 'parado-esquerda' or dogState == 'saltando-esquerda'):\n            dogState = 'morrendo-esquerda'\n        if (dogState == 'andando-direita' or dogState == 'parado-direita' or dogState == 'saltando-direita'):\n            dogState = 'morrendo-direita'<\/mark>\n            \n    movimentoDog()\n    movimentoCamera() \n    \n    # DESENHO E ATUALIZA\u00c7\u00c3O\n    cenario.draw()\n    desenhoDog()\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-green-cyan-color\">    cobra.update()\n    cobra.draw()\n    arvore.draw()<\/mark>\n    janela.update()\n\n\n<\/code><\/pre>\n\n\n\n<p>Al\u00e9m dessa vantagem, agora tamb\u00e9m podemos adicionar inimigos e fazer a movimenta\u00e7\u00e3o deles junto com o cen\u00e1rio nesta fun\u00e7\u00e3o. Repare que nada impede que alem de se mover com o cen\u00e1rio, o inimigo tamb\u00e9m tenha um movimento pr\u00f3prio, bastando adicionar valores aos seus atributos x e y quando implementar sua movimenta\u00e7\u00e3o.<\/p>\n\n\n\n<p>No c\u00f3digo adicionamos o sprite que faz o c\u00e3o morrer e adicionamos uma cobra. Se o c\u00e3o encostar na cobra ele morre, ent\u00e3o definimos um ret\u00e2ngulo em torno do c\u00e3o que n\u00e3o pode sobrepor ao ret\u00e2ngulo em torno da cobra. Colocamos ainda 30 px de toler\u00e2ncia pois os sprites possuem pixels transparentes, e utilizamos o sprite do c\u00e3o parado como refer\u00eancia para o teste.<\/p>\n\n\n\n<p>Ao tocar na cobra o sprite que mostra o c\u00e3o morrendo \u00e9 disparado porque mudamos o estado do cachorro. Agora fica mais f\u00e1cil adicionar inimigos e elementos na tela que se movimentam junto com o cen\u00e1rio. Os pr\u00f3ximos passos seria adicionar inimigos, coloc\u00e1-los em um vetor para agilizar o processo de testar de o c\u00e3o morreu, fazer uma tela de game-over, implementar um menu, etc. No entanto, o escopo deste tutorial j\u00e1 foi contemplado.<\/p>\n\n\n\n<p><strong>C\u0155edito: <a href=\"mailto:sergioherman@id.uff.br\">Sergio Herman<\/a><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>O objetivo deste tutorial \u00e9 revisar os principais conceitos necess\u00e1rios para programar jogos. Criaremos um ambiente virtual onde voc\u00ea controla um c\u00e3o que anda em um cen\u00e1rio onde a c\u00e2mera o acompanha dinamicamente. A imagem abaixo exemplifica a implementa\u00e7\u00e3o que buscamos. Voc\u00ea pode fazer o download dos arquivos de imagem usado neste tutorial clicando no [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":57,"menu_order":8,"comment_status":"closed","ping_status":"closed","template":"tutorial-template.php","meta":{"footnotes":""},"_links":{"self":[{"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/pages\/143"}],"collection":[{"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/comments?post=143"}],"version-history":[{"count":36,"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/pages\/143\/revisions"}],"predecessor-version":[{"id":553,"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/pages\/143\/revisions\/553"}],"up":[{"embeddable":true,"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/pages\/57"}],"wp:attachment":[{"href":"http:\/\/www2.ic.uff.br\/pplay\/wp-json\/wp\/v2\/media?parent=143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}