<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Abrindo o Jogo &#187; Java</title>
	<atom:link href="http://abrindoojogo.com.br/category/java/feed" rel="self" type="application/rss+xml" />
	<link>http://abrindoojogo.com.br</link>
	<description></description>
	<lastBuildDate>Thu, 17 May 2012 17:40:33 +0000</lastBuildDate>
	<language>pt-br</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<copyright>Copyright © Abrindo o Jogo 2011 </copyright>
	<managingEditor>contato@abrindoojogo.com.br (Abrindo o Jogo)</managingEditor>
	<webMaster>contato@abrindoojogo.com.br (Abrindo o Jogo)</webMaster>
	<ttl>1440</ttl>
	<image>
		<url>http://abrindoojogo.com.br/files/logoItunes_144.jpg</url>
		<title>Abrindo o Jogo</title>
		<link>http://abrindoojogo.com.br</link>
		<width>144</width>
		<height>144</height>
	</image>
	<itunes:subtitle>PodAbrir - o Podcast do Abrindo o Jogo.</itunes:subtitle>
	<itunes:summary>Dicas e opiniões sobre a indústria dos games, abordando desde o desenvolvimento até o mercado.</itunes:summary>
	<itunes:keywords>jogos, game, development, desenvolvimento, indie, programming</itunes:keywords>
	<itunes:category text="Games &#38; Hobbies">
		<itunes:category text="Video Games" />
	</itunes:category>
	<itunes:category text="Technology" />
	<itunes:author>Abrindo o Jogo</itunes:author>
	<itunes:owner>
		<itunes:name>Abrindo o Jogo</itunes:name>
		<itunes:email>contato@abrindoojogo.com.br</itunes:email>
	</itunes:owner>
	<itunes:block>no</itunes:block>
	<itunes:explicit>no</itunes:explicit>
	<itunes:image href="http://abrindoojogo.com.br/files/logoItunes_600.jpg" />
		<item>
		<title>How-to: Configuração do Google PlayN</title>
		<link>http://abrindoojogo.com.br/tutorial-de-configuracao-do-google-playn</link>
		<comments>http://abrindoojogo.com.br/tutorial-de-configuracao-do-google-playn#comments</comments>
		<pubDate>Thu, 10 Nov 2011 04:54:53 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>
		<category><![CDATA[how-to]]></category>

		<guid isPermaLink="false">http://abrindoojogo.com.br/?p=3407</guid>
		<description><![CDATA[Google vem desenvolvendo a certo tempo uma biblioteca para criação de jogos que promete facilitar o desenvolvimento multiplataforma. A PlayN, como é chamada hoje, permite o desenvolvimento de jogos utilizando a linguagem Java e uma API própria, e gera automaticamente o código do jogo em HTML5, Android e Flash. Parece incrível e é, mas a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2011/11/ImgPlayN1.png"><img class="alignleft size-full wp-image-3423" title="ImgPlayN" src="http://abrindoojogo.com.br/wp-content/uploads/2011/11/ImgPlayN1.png" alt="" width="200" height="200" /></a>Google vem desenvolvendo a certo tempo uma biblioteca para criação de jogos que promete facilitar o desenvolvimento multiplataforma. A <strong>PlayN</strong>, como é chamada hoje, permite o desenvolvimento de jogos utilizando a linguagem Java e uma API própria, e gera automaticamente o código do jogo em HTML5, Android e Flash.</p>
<p>Parece incrível e é, mas a configuração do ambiente ainda é um desafio para quem não está acostumado a trabalhar com Git, Maven, Ant e outros diretamente. Nesse curto passo a passo mostramos como configurar PlayN no Eclipse.</p>
<p><span id="more-3407"></span></p>
<p>O projeto PlayN está passando por modificações neste exato momento. Por isso este passo a passo acabou demorando mais do que eu gostaria &#8211; depois que prometi ele, o PlayN simplesmente parou de funcionar em função da atualização da API do Android. Hoje este problema está resolvido, mas para isso o PlayN não vem mais com o pacote de samples &#8211; demonstrações do uso da plataforma. Eles poderão ser baixados separadamente em breve &#8211; quando ocorrer, informamos aqui.</p>
<h3>[ATUALIZAÇÃO]</h3>
<p>O PlayN está agora disponível no Maven Central, que é um repositório público. Isso facilita muito o processo todo, já que não é preciso baixar todos os fontes do PlayN para a máquina para poder utilizá-lo &#8211; só é preciso criar um novo projeto do tipo Maven e basear ele no arquétipo desejado do Maven Central.</p>
<p>Incluí abaixo o how-to para criar um novo projeto do PlayN no NetBeans, que é mais amigável que o Eclipse, mas o processo é praticamente o mesmo para ambos.</p>
<p>Todo o processo é feito em uma máquina limpa, sem nada previamente instalado. Utilizei o Netbeans 7.0.1 recém instalado e com todas atualizações aplicadas.</p>
<p>Os dados para o arquétipo de projeto são os seguintes:</p>
<div>
<ul>
<li>group: com.googlecode.playn</li>
<li>artefato: playn-archetype</li>
<li>versão: 1.0.1</li>
</ul>
</div>
<div>
<ul>
<li><a href="https://docs.google.com/present/view?id=dgmf7xht_617gd44jvfz" target="_blank">Clique aqui para ver a apresentação.</a></li>
</ul>
</div>
<p><strong>Segue post original.</strong></p>
<p>Este how-to está longe de ser à prova de falhas &#8211; muita coisa depende da configuração da sua máquina se você já tiver o Eclipse ou Maven instalado. Se você não tem nada disso, é provável que a coisa funcione sem problemas.</p>
<p>Um problema que tive foi o Eclipse rodar com JRE, que é run-time do Java para usuários finais, não para desenvolvimento. E com isso não conseguir compilar algumas coisas. Se você desconfiar que seu problema é esse, recomendo desinstalar temporariamente o JRE e deixar instalado apenas o JDK (versão de desenvolvimento do Java). Se o Eclipse não iniciar, por não achar mais o Java, abra o arquivo eclipse.ini (que fica na pasta do Eclipse) e acrescente a ele as seguintes linhas (são duas):</p>
<pre>-vm
C:\Program Files\Java\jdk1.7.0_01\jre\bin\client\jvm.dll</pre>
<p>O caminho do Java pode variar conforme sua configuração, principalmente a versão.</p>
<ul>
<li><a href="https://docs.google.com/present/view?id=dgmf7xht_546sm5qzdx" target="_blank">Clique aqui para ver a apresentação do how-to e boa sorte</a>.</li>
</ul>
<p>Sites citados:</p>
<ul>
<li><a href="http://eclipse.org/" target="_blank">Eclipse</a></li>
</ul>
<ul>
<li><a href="https://developers.google.com/playn/" target="_blank">PlayN</a>
<ul>
<li>Endereço do repositório para obter o PlayN:
<p>https://code.google.com/p/playn</li>
</ul>
</li>
</ul>
<ul>
<li><a href="http://code.google.com/eclipse/" target="_blank">Plugin do Google para o Eclipse</a>
<ul>
<li>Endereço para instalação de novo software no Eclipse:
<p>http://dl.google.com/eclipse/plugin/3.7</li>
</ul>
</li>
</ul>
<ul>
<li>Plugin de integração do Maven com o Web Tools Plataform do Eclipse
<ul>
<li>Endereço para instalação de novo software no Eclipse:
<p>http://download.jboss.org/jbosstools/updates/m2eclipse-wtp</li>
</ul>
</li>
</ul>
<ul>
<li><a href="http://developer.android.com/sdk/eclipse-adt.html" target="_blank">Plugin ADT (Android Development Tools) para Eclipse</a> (não necessário para o tutorial acima)
<ul>
<li>Endereço para instalação de novo software no Eclipse:
<p>https://dl-ssl.google.com/android/eclipse/</li>
</ul>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/tutorial-de-configuracao-do-google-playn/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Joypad no Java com JInput</title>
		<link>http://abrindoojogo.com.br/joypad-no-java-com-jinput</link>
		<comments>http://abrindoojogo.com.br/joypad-no-java-com-jinput#comments</comments>
		<pubDate>Wed, 17 Aug 2011 14:34:55 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://abrindoojogo.com.br/?p=2663</guid>
		<description><![CDATA[Dependendo do tipo de jogo, a experiência do jogador só fica completa com um controle de jogo, joypad ou joystick. Sem contar ainda com a necessidade que alguns jogos possuem de controles especiais (guitarras, etc). Neste post técnico veremos como usar a biblioteca JInput para dar suporte a controles de jogo no Java. Já vimos [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-2666" href="http://abrindoojogo.com.br/joypad-no-java-com-jinput/java_controller"><img class="alignleft size-medium wp-image-2666" title="java_controller" src="http://abrindoojogo.com.br/wp-content/uploads/2011/08/java_controller-300x300.png" alt="" width="144" height="144" /></a>Dependendo do tipo de jogo, a experiência do jogador só fica completa com um controle de jogo, joypad ou joystick. Sem contar ainda com a necessidade que alguns jogos possuem de controles especiais (guitarras, etc). Neste post técnico veremos como usar a biblioteca JInput para dar suporte a controles de jogo no Java.<span id="more-2663"></span></p>
<p>Já vimos aqui como criar um game loop básico no post <a href="http://abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-parte-1-de-2" target="_blank">Game Loop com taxa constante de pulsos</a>. Utilizaremos agora uma estrutura muito semelhante, de forma que é interessante dar uma olhada naquele post se você ainda não leu.</p>
<p>Nosso projeto terá duas classes apenas, a Main, que carrega o “jogo” (não é de fato um jogo&#8230;) e a classe Jogo, que possui um game loop onde ficamos verificando se alguma tecla, botão do mouse ou do joypad foi pressionada, mostrando a informação correspondente na tela.</p>
<p>A classe Main é simples, como podemos ver abaixo:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Main <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        Jogo j <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Jogo<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        j.<span style="color: #006633;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Basicamente ela cria um objeto do tipo Jogo e executa ele, chamando seu método “run”. A classe Jogo, então, é que contém todo o código interessante. Veremos seu código e a seguir a explicação dos pontos que usam o JInput (os demais pontos são explicados no post citado acima).</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.awt.Graphics2D</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.awt.image.BufferStrategy</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.swing.JFrame</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.swing.WindowConstants</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.java.games.input.Component</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.java.games.input.Controller</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.java.games.input.ControllerEnvironment</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Jogo <span style="color: #000000; font-weight: bold;">extends</span> <span style="color: #003399;">JFrame</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    BufferStrategy bs<span style="color: #339933;">;</span>
    Controller<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> cs<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> Jogo<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        setTitle<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Exemplo de uso do JInput&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        setDefaultCloseOperation<span style="color: #009900;">&#40;</span><span style="color: #003399;">WindowConstants</span>.<span style="color: #006633;">EXIT_ON_CLOSE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        setSize<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">800</span>, <span style="color: #cc66cc;">600</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        setIgnoreRepaint<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        setVisible<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        createBufferStrategy<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        bs <span style="color: #339933;">=</span> getBufferStrategy<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        ControllerEnvironment ce <span style="color: #339933;">=</span> ControllerEnvironment.<span style="color: #006633;">getDefaultEnvironment</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cs <span style="color: #339933;">=</span> ce.<span style="color: #006633;">getControllers</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        initialize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> cs.<span style="color: #006633;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            cs<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">poll</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">Graphics2D</span> g <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Graphics2D</span><span style="color: #009900;">&#41;</span> bs.<span style="color: #006633;">getDrawGraphics</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        g.<span style="color: #006633;">clearRect</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, getWidth<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, getHeight<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> cs.<span style="color: #006633;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            g.<span style="color: #006633;">drawString</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;. &quot;</span> <span style="color: #339933;">+</span> cs<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;, &quot;</span> <span style="color: #339933;">+</span> cs<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getType</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #cc66cc;">50</span>, <span style="color: #cc66cc;">80</span> <span style="color: #339933;">+</span> i <span style="color: #339933;">*</span> <span style="color: #cc66cc;">20</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003399;">Component</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> cmps <span style="color: #339933;">=</span> cs<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getComponents</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> c <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> c <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> cmps.<span style="color: #006633;">length</span><span style="color: #339933;">;</span> c<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                g.<span style="color: #006633;">drawString</span><span style="color: #009900;">&#40;</span>c <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;. &quot;</span> <span style="color: #339933;">+</span> cmps<span style="color: #009900;">&#91;</span>c<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; = &quot;</span> <span style="color: #339933;">+</span> cmps<span style="color: #009900;">&#91;</span>c<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getPollData</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #cc66cc;">50</span> <span style="color: #339933;">+</span> i <span style="color: #339933;">*</span> <span style="color: #cc66cc;">200</span>, <span style="color: #cc66cc;">180</span> <span style="color: #339933;">+</span> c <span style="color: #339933;">*</span> <span style="color: #cc66cc;">20</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        g.<span style="color: #006633;">dispose</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        bs.<span style="color: #006633;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h2 dir="ltr">Usando o JInput</h2>
<p>Quando incluímos a biblioteca JInput no nosso projeto (veremos como fazer isso no final), temos algumas classes disponíveis para uso. Uma delas é ControllerEnvironment, que permite obter uma lista de todos controles disponíveis no sistema. Isto é feito da seguinte forma:</p>
<p>ControllerEnvironment ce = ControllerEnvironment.getDefaultEnvironment();<br />
Controller[] cs = ce.getControllers();</p>
<p>Interessante notar que a JInput trata o teclado e o mouse como controles, de forma que o vetor acima terá pelo menos estes dois itens. Se você tiver um ou mais controle de jogo conectado ao sistema, então mais itens serão adicionados ao vetor, um para cada controle.</p>
<p>Cada controle é constituído de componentes. No teclado os componentes são as teclas; em um controle de jogo, os componentes são os eixos e os botões. Uma vez que temos um objeto do tipo Coltroller, podemos obter a lista de componentes que ele possui, com o código abaixo:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #003399;">Component</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> cmps <span style="color: #339933;">=</span> controle.<span style="color: #006633;">getComponents</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> c <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> c <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> cmps.<span style="color: #006633;">length</span><span style="color: #339933;">;</span> c<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>cmps<span style="color: #009900;">&#91;</span>c<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; = &quot;</span> <span style="color: #339933;">+</span> cmps<span style="color: #009900;">&#91;</span>c<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getPollData</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Este código obtem um vetor de componentes do controle e para cada um deles exibe o nome e os dados lidos no último pooling. Estes dados correspondem ao estado do componente. Por exemplo, se for um botão, pode vir 1 (pressionado) ou 0 (solto); se for um joystick analógico, virá um valor entre -1.0 e 1.0, sendo que 0.0 significa que o joystick está no centro. São estes dados que vamos utilizar para comandar as ações do jogo.</p>
<p>Veja que, seguindo a melhor prática para leitura de dispositivos de entrada, o JInput não trabalha com eventos, mas sim com pooling. A diferença é que com eventos, quando uma tecla do teclado é pressionada, por exemplo, é gerado um evento que o jogo deve anteder &#8211; nem sempre será a melhor hora para fazer isso &#8211; podemos estar no meio da atualização da tela, por exemplo. Com o pooling a coisa se inverte: é o jogo que lê o estado do teclado quando desejar, verificando, então, se a tecla desejada está pressionada ou não.</p>
<p>Como JInput fazemos a leitura do estado de um objeto do tipo Controller chamando seu método “pool”. Veja dentro do método “update” da classe Jogo onde percorremos o vetor de controles chamando “pool” para cada um deles. Isso faz com que a cada volta do game loop os dados atualizados dos controles estejam disponíveis.</p>
<p>No método “render” percorremos novamente o vetor de controles e para cada um, obtermos o vetor de componentes. Então percorremos todos componentes mostrando na tela seu nome e seu estado atual.</p>
<h2 dir="ltr">Incluindo JInput no projeto</h2>
<p>Finalmente, vejamos como incluir a JInput no nosso projeto. <a href="http://java.net/projects/jinput/downloads" target="_blank">Baixe a biblioteca mais recente no site</a> e dentro do ZIP você vai encontrar o arquivo jinput.jar, que é a biblioteca em Java, e vários arquivos dll e so, que são as partes nativas. Estas partes devem ser distribuídas junto com seu jogo e são a ponte entre o código Java que usamos acima e a manipulação de baixo nível do hardware em cada plataforma (.dll no Windows e .so no Linux).</p>
<p>Digamos que seu projeto esteja armazenado em uma pasta chamada MeuProjeto. Dentro dela deve ter a pasta de códigos fonte (src) e quando você compila e constrói, surgem as pastas build e dist (que é onde está o jogo pronto para ser distribuído). Se não existir, crie dentro de MeuJogo uma pasta lib e dentro dela coloque o jinput.jar. Os arquivos .dll e .so vão diretamente dentro de MeuJogo.</p>
<p>Agora utilize um comando do seu IDE para importar a biblioteca para o projeto. No NetBeans faça assim:</p>
<ol>
<li>Clique com o botão direito do mouse no projeto;</li>
<li>No menu selecione propriedades;</li>
<li>Na janela de propriedades vá na seção “Bibliotecas” e clique em “Adicionar JAR/pasta”;</li>
<li>Localize o jinput.jar que está dentro da pasta lib e pronto, confirme tudo.</li>
</ol>
<p>Ao construir (dar build), será criada uma pasta lib dentro de dist, com o jinput lá dentro. Mas será preciso copiar as dll e so manualmente. Então é só distribuir o conteúdo da pasta dist.</p>
<h2 dir="ltr">Conclusão</h2>
<p>Usar um controle de jogo pode melhorar muito a experiência do usuário com certos jogos, principalmente nos gêneros de tiro, luta, corrida e plataforma.</p>
<p>Mas mesmo em jogos onde o teclado e o mouse são a melhor opção, o JInput é uma boa escolha porque facilita também o acesso a estes dispositivos. Criar do zero um pool para teclado e mouse é meio chato &#8211; demora pra dar o resultado desejado. O Jinput já tem tudo pronto.</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2011/08/JogoComJoypad.zip">Clique aqui para baixar o código fonte deste post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/joypad-no-java-com-jinput/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Anti-Invaders &#8211; um projeto didático.</title>
		<link>http://abrindoojogo.com.br/anti-invaders-um-projeto-didatico</link>
		<comments>http://abrindoojogo.com.br/anti-invaders-um-projeto-didatico#comments</comments>
		<pubDate>Wed, 30 Jun 2010 00:54:10 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Padrão de Projeto]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Projeto de Jogo]]></category>
		<category><![CDATA[Projeto de Software]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://blog.abrindoojogo.com.br/?p=1565</guid>
		<description><![CDATA[Este post é o primeiro de uma série que vai documentar a evolução de um projeto inteiro, desde o game design até o produto final. O projeto tem o objetivo de ser didático e por isso foi escolhido um jogo de navinha (shooter) e será desenvolvido utilizando a tecnologia Java. Neste post conheceremos a primeira [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2010/07/blog2.png"><img class="alignleft size-full wp-image-1580" title="blog2" src="http://abrindoojogo.com.br/wp-content/uploads/2010/07/blog2.png" alt="" width="150" height="150" /></a>Este post é o primeiro de uma série que vai documentar a evolução de um projeto inteiro, desde o game design até o produto final. O projeto tem o objetivo de ser didático e por isso foi escolhido um jogo de navinha (shooter) e será desenvolvido utilizando a tecnologia Java. Neste post conheceremos a primeira versão do GDD e a história de fundo do jogo.</p>
<p><span id="more-1576"></span>O nome do jogo é <strong>Anti-Invaders</strong>. É um jogo de tiro espacial como vários outros que apareceram ao longo do tempo. É um gênero bem conhecido e de implementação relativamente simples, por isso mesmo uma boa escolha para um projeto didático.</p>
<p>A idéia é mostrar umprojeto simples porém completo, desenvolvido com protótipos e releases e comentando cada evolução em posts semanais. Serão decisões de game design, de arquitetura de software e de implementação que, no final, darão uma visão completa do processo.</p>
<p>Acredito que será útil principalmente para quem está iniciando e não tem, ainda, noção clara do processo como um todo.</p>
<p>Iniciaremos, então, com a primeira versão do GDD (Game Design Document), criado com base <a href="http://blog.abrindoojogo.com.br/trabalhar-com-jogos-e-uma-questao-de-sorte-parte-1-de-3/">neste post do Everton</a>, embora bem simplificado. Algumas seções não foram preenchidas &#8211; nelas está anotado o que deveria ser colocado alí. O foco deste documento é na história de base, fases (tamanho do jogo) e controles. Clique no link abaixo para baixar o PDF.</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2010/06/gdd_anti_invaders.pdf">GDD_Anti_Invaders</a></p>
<p>Semana que vem teremos um protótipo do jogo para ter idéia do que querermos fazer.</p>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/anti-invaders-um-projeto-didatico/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Criando um Applet básico</title>
		<link>http://abrindoojogo.com.br/criando-um-applet-basico</link>
		<comments>http://abrindoojogo.com.br/criando-um-applet-basico#comments</comments>
		<pubDate>Sat, 21 Nov 2009 01:22:57 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://blog.abrindoojogo.com.br/?p=1078</guid>
		<description><![CDATA[A tecnologia Java ficou originalmente conhecida pelo Applets, palavra que significa pequenos aplicativos. São programas que rodam embutidos dentro de outro &#8211; no caso, em navegadores da web. Embora os applets tenham também dado ao Java o stigma de linguagem lenta, hoje, com a evolução da tecnologia, eles são um opão para a criação de [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/11/applet1.png"><img class="alignleft size-full wp-image-1092" title="Applet" src="http://abrindoojogo.com.br/wp-content/uploads/2009/11/applet1.png" alt="" width="199" height="150" /></a>A tecnologia Java ficou originalmente conhecida pelo Applets, palavra que significa pequenos aplicativos. São programas que rodam embutidos dentro de outro &#8211; no caso, em navegadores da web. Embora os applets tenham também dado ao Java o stigma de linguagem lenta, hoje, com a evolução da tecnologia, eles são um opão para a criação de webgames. Neste post vamos ver o mínimo para ter um applet com game loop.</p>
<p><span id="more-1078"></span>Um applet Java é uma classe derivada de JApplet, que por sua vez é um painel. Ou seja, não temos uma janela para nosso programa e sim um painel, que será embutido na janela de outro programa, no caso, um navegador da web.</p>
<p>Isso não nos permite obter um BufferStrategy para a janela, mas podemos ter o mesmo efeito criando um objeto do tipo Canvas, que é uma área de desenho que possui contexto gráfico, e criar um BufferStrategy para ele. Daí para frente usamos ele para fazer <a href="http://blog.abrindoojogo.com.br/passive-vs-active-rendering-parte-1-de-2/">active rendering</a> normalmente.</p>
<p>Outro ponto específico é que por rodar dentro de outro programa, não podemos trancar nossa thread principal com um loop infinito, como fizemos em <a href="http://blog.abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-parte-1-de-2/">outros exemplos</a> aqui no blog. Isso é resolvido de forma simples implementando a interface Runnable na nossa classe e executando ela em uma thread separada.</p>
<p>Veja no código abaixo um applet simples que a cada volta do loop muda a cor da tela.</p>
<p><strong>Arquivo Main.java</strong></p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> exemploapplet;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">import</span> java.awt.Canvas;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span><span style="color: #0000e6;">import</span> java.awt.Color;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span></span><span style="color: #0000e6;">import</span> java.awt.Graphics2D;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span></span><span style="color: #0000e6;">import</span> java.awt.image.BufferStrategy;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span></span><span style="color: #0000e6;">import</span> javax.swing.JApplet;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Main <span style="color: #0000e6;">extends</span> JApplet <span style="color: #0000e6;">implements</span> Runnable<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>    </span><span style="color: #0000e6;">int</span> x;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>    </span>Canvas canvas;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>    </span>BufferStrategy bs;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>    </span>@Override<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">016</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> init()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">017</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">018</span>        </span>canvas = <span style="color: #0000e6;">new</span> Canvas();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">019</span>        </span>setIgnoreRepaint(<span style="color: #0000e6;">true</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">020</span>        </span><span style="color: #0000e6;">this</span>.add(canvas);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">021</span>        </span>Thread t = <span style="color: #0000e6;">new</span> Thread(<span style="color: #0000e6;">this</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>        </span>t.start();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">025</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> run()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">026</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">027</span>        </span>canvas.createBufferStrategy(<span style="color: #000000;">2</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">028</span>        </span>bs = canvas.getBufferStrategy();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">029</span>        </span><span style="color: #0000e6;">while</span> (<span style="color: #0000e6;">true</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">030</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">031</span>            </span>Thread.yield();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">032</span>            </span>update();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">033</span>            </span>render();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">034</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">035</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">036</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">037</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> update()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">038</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">039</span>        </span><span style="color: #0000e6;">if</span> (++x &gt; <span style="color: #000000;">255</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">040</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">041</span>            </span>x = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">042</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">043</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">044</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">045</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> render()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">046</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">047</span>        </span>Graphics2D g = (Graphics2D) bs.getDrawGraphics();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">048</span>        </span><span style="color: #0000e6;">if</span> (g != <span style="color: #0000e6;">null</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">049</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">050</span>            </span>g.setColor(<span style="color: #0000e6;">new</span> Color(x, x, x));<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">051</span>            </span>g.fillRect(<span style="color: #000000;">0</span>, <span style="color: #000000;">0</span>, getWidth(), getHeight());<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">052</span>            </span>g.dispose();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">053</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">054</span>        </span>bs.show();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">055</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">056</span></span>}</pre>
<p>Em um applet não inicializamos variáveis nem criamos objetos no constructor. Isso porque a classe do applet pode ser criada muito antes de ser utilizada. Aliás, pode ser criada e acabar nem sendo utilizada porque, por exemplo, o usuário fechou o programa externo antes disso ocorrer. Carregar recursos no contructor do applet poderia levar a processamento realizado à toa nestes casos.</p>
<p>O que faz, então, é implementar o método ini(), herdado de JApplet, e fazer a inicialização nele. Esse método é chamado pelo programa externo quando o applet for ativado e iniciar sua execução.</p>
<p>No método init do exemplo acima o que fazemos é criar um objeto Canvas e adicioná-lo ao applet, além de desligar o repaint automatico do applet (porque vamos fazer active rendering). Também criamos uma thread nova para nossa classe e colocamos ela para rodar.</p>
<p>Quando a thread roda, ela chama o método run() da nossa classe. Nele criamos o BufferStrategy configurado para double buffering e obtemos uma referência a ele na variável &#8220;bs&#8221;. Veja que o BufferStrategy é criado para o objeto Canvas.</p>
<p>Em seguida entramos no loop infinito do jogo (game loop), que fica chamando update() e render(). Esse loop não possui controle de pulsos e frames, portanto vai rodar na velocidade máxima que a máquina suportar.</p>
<p>O método update simplesmente incrementa a variável x a cada vez que é chamado, zerando-a quando ela passa de 255. Essa variável será utilizada para determinar a cor a ser aplicada na tela.</p>
<p>A mudança da cor é feita no método render(), que desenha na tela utilizando o BufferStrategy obtido anteriormente. Primeiro é executado um setColor() passando para ele um objeto Color criado utilizando a variável x nas posições referentes às componentes vermelha (R), verde (G) e azul (B) da cor. Assim, teremos vários tons de ciz desde o preto (0, 0, 0) até o branco (255, 255, 255). Um fillRect() preenche com a cor selecionada a área total da tela.</p>
<p>O applet pode ser visualizada aqui: <a href="http://sites.google.com/site/nornberg/exemploapplet" target="_blank">http://sites.google.com/site/nornberg/exemploapplet</a></p>
<h2>Incluindo o applet em HTML</h2>
<p>A seguir está um exemplo de página HTML com a tag &lt;OBJECT&gt;, que é utilizada para incluir o applet.</p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span>&lt;html&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span></span>&lt;head&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span>    </span>&lt;title&gt;ExemploApplet&lt;/title&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span>&lt;/head&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span></span>&lt;body&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>    </span>&lt;center&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>        </span>&lt;object<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>            </span>width=<span style="color: #ce7b00;">"640"</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>            </span>height=<span style="color: #ce7b00;">"480"</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>            </span>type=<span style="color: #ce7b00;">"application/x-java-applet"</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>            </span>classid=<span style="color: #ce7b00;">"java:exemploapplet/Main.class"</span>&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>            </span>&lt;param name=<span style="color: #ce7b00;">"code"</span> value=<span style="color: #ce7b00;">"exemploapplet/Main.class"</span> /&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>            </span>&lt;param name=<span style="color: #ce7b00;">"archive"</span> value=<span style="color: #ce7b00;">"ExemploApplet.jar"</span> /&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span>        </span>&lt;/object&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>    </span>&lt;/center&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">016</span></span>&lt;/body&gt;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">017</span></span>&lt;/html&gt;</pre>
<p>Esta tag carrega o applet pelo menos no Internet Explorer, Mozilla Firefox e Google Chrome (últimas versões). Onde está &#8220;exemploapplet/Main.class&#8221; você pode substituir pelo caminho da sua classe (pacotes e classe separados por barra. Por ponto deve funcioanr também). O parâmetro &#8220;archive&#8221; contém o caminho para o JAR do applet (gerado pelo NetBeans com o comando &#8220;construir&#8221;).</p>
<p>Isso é só o básico, para dar a fundamentação a quem nunca criou um applet. Em próximos posts mostrarei como incluir imagens e sons no JAR, para utilizá-los de dentro do applet.</p>
<p><a href="http://blog.abrindoojogo.com.br/como-obter-os-codigos-fonte-dos-artigos/">Baixe o código fonte deste artigo.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/criando-um-applet-basico/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Threads, apenas um exemplo</title>
		<link>http://abrindoojogo.com.br/threads-apenas-um-exemplo</link>
		<comments>http://abrindoojogo.com.br/threads-apenas-um-exemplo#comments</comments>
		<pubDate>Thu, 08 Oct 2009 01:43:30 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://blog.abrindoojogo.com.br/?p=862</guid>
		<description><![CDATA[Threads são partes de um programa que executam paralelamente. Com seu uso é possível executar simultâneamente duas ou mais rotinas. Atualmente, com o barateamento dos processadores de vários núcleos (multi core), seu uso fica mais justificado. Embora eu não recomende trabalhar com threads, convém entender o que elas representam na prática. Antes de tudo vou [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/threads.png"><img class="alignleft size-full wp-image-875" title="Threads" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/threads.png" alt="Threads" width="200" height="150" /></a><em>Threads</em> são partes de um programa que executam paralelamente. Com seu uso é possível executar simultâneamente duas ou mais rotinas. Atualmente, com o barateamento dos processadores de vários núcleos (<em>multi core</em>), seu uso fica mais justificado. Embora eu não recomende trabalhar com <em>threads</em>, convém entender o que elas representam na prática.</p>
<p><span id="more-862"></span>Antes de tudo vou ressaltar: não recomendo trabalhar com <em>threads</em> a menos que seja o desenvolvimento de um jogo AAA, o qual não é foco deste site (digamos um Batman: Asilo Arkhan). Jogos assim, exigem intenso processamento de I.A., física e gráficos e possuem, em geral, muito dinheiro para serem feito. Isso justifica a utilização de uma forma de programação mais complexa. Ainda mais que estes jogos em geral são criados em C++, uma das piores linguagens para trabalhar com <em>threads</em>. Mesmo no Java, cujo uso é relativamente simples (como veremos abaixo), depurar um programa com <em>thread</em> é um inferno.</p>
<p>Além disso, projetar o código para tirar proveito de <em>threads</em> é tarefa para arquitetos competentes &#8211; caso contrário você vai criar um código complexo, difícil de depurar e manter e, provavelmente, vai cair em <em>dead locks</em> e outros problemas de concorrência . E ainda corre o risco de acabar com um código pouco eficiente, apesar do esforço adicional.</p>
<p>Fica então o aviso: o código abaixo serve para efeito de exemplo e não deve ser base para um jogo do mundo real.</p>
<p>Bom, se depois do que foi dito acima você ainda não desistiu de ler sobre <em>threads</em>, vamos em frente &#8211; o fato é que o conceito por trás delas, e sua correta utilização, são importantes para tirar todo proveito de uma CPU com múltiplos núcleos. Vamos ver como fazer isso com o <em>gameloop</em> desenvolvidos nos meus artigos anteriores. Se você não leu, filtre os posts pela tag <strong>Java </strong>e leia-os antes, ok?</p>
<h2>Modularizando o jogo</h2>
<p>Começo criando duas classes especializadas em atualizar a lógica do jogo (lembra do <em>update</em>?) e em atualizar a tela (lembra do <em>render</em>?). Chamarei elas de Controlador e Renderizador, respectivamente. Seu código está abaixo. Basicamente, eu tirei as rotinas update() e render() da minha classe do jogo e coloquei em classes separadas.</p>
<p><strong>Arquivo Controlador.java</strong></p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.thread;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">import</span> javax.swing.JFrame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Controlador<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>    </span>Contador contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>    </span>JFrame frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>    </span>Nave nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>    </span><span style="color: #0000e6;">public</span> Controlador(JFrame frame, Contador contador, Nave nave)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>        </span><span style="color: #0000e6;">this</span>.frame = frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span>        </span><span style="color: #0000e6;">this</span>.contador = contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>        </span><span style="color: #0000e6;">this</span>.nave = nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">016</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">017</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">018</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> update()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">019</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">020</span>        </span>contador.contaPulso();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">021</span>        </span>nave.x += <span style="color: #000000;">1</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>        </span><span style="color: #0000e6;">if</span> (nave.x &gt; frame.getWidth() + <span style="color: #000000;">30</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span>            </span>nave.x = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">025</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">026</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">027</span></span>}</pre>
<p><strong>Arquivo Renderizador.java</strong></p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.thread;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">import</span> java.awt.Color;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span><span style="color: #0000e6;">import</span> java.awt.Graphics2D;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span></span><span style="color: #0000e6;">import</span> java.awt.image.BufferStrategy;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span></span><span style="color: #0000e6;">import</span> javax.swing.JFrame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Renderizador<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>    </span>BufferStrategy bs;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>    </span>Contador contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>    </span>JFrame frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>    </span>Nave nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">boolean</span> terminado = <span style="color: #0000e6;">false</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">016</span>    </span><span style="color: #0000e6;">public</span> Renderizador(JFrame frame, BufferStrategy bs,<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">017</span>                        </span>Contador contador, Nave nave)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">018</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">019</span>        </span><span style="color: #0000e6;">this</span>.frame = frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">020</span>        </span><span style="color: #0000e6;">this</span>.bs = bs;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">021</span>        </span><span style="color: #0000e6;">this</span>.contador = contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>        </span><span style="color: #0000e6;">this</span>.nave = nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">025</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> render()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">026</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">027</span>        </span>contador.contaFrame();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">028</span>        </span>Graphics2D g = (Graphics2D) bs.getDrawGraphics();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">029</span>        </span>g.setColor(Color.black);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">030</span>        </span>g.fillRect(<span style="color: #000000;">0</span>, <span style="color: #000000;">0</span>, frame.getWidth(), frame.getHeight());<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">031</span>        </span><span style="color: #0000e6;">int</span> x = nave.x;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">032</span>        </span><span style="color: #0000e6;">int</span> y = nave.y;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">033</span>        </span><span style="color: #0000e6;">for</span> (<span style="color: #0000e6;">int</span> i = <span style="color: #000000;">0</span>; i &lt; nave.qtd; i++)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">034</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">035</span>            </span>g.setColor(Color.yellow);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">036</span>            </span>g.drawLine(x, y, x - <span style="color: #000000;">20</span>, y - <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">037</span>            </span>g.drawLine(x, y, x - <span style="color: #000000;">20</span>, y + <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">038</span>            </span>g.drawLine(x - <span style="color: #000000;">20</span>, y - <span style="color: #000000;">5</span>, x - <span style="color: #000000;">20</span>, y + <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">039</span>            </span>y += <span style="color: #000000;">15</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">040</span>            </span><span style="color: #0000e6;">if</span> (y &gt; <span style="color: #000000;">550</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">041</span>            </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">042</span>                </span>y = nave.y;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">043</span>                </span>x += <span style="color: #000000;">15</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">044</span>            </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">045</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">046</span>        </span>g.setColor(Color.white);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">047</span>        </span>g.drawString(<span style="color: #ce7b00;">"Pulsos: "</span> + contador.getPulsosPorSegundo() +<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">048</span>                     </span><span style="color: #ce7b00;">"  Frames: "</span> + contador.getFramesPorSegundo() +<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">049</span>                     </span><span style="color: #ce7b00;">"          naves: "</span> + nave.qtd, <span style="color: #000000;">10</span>, <span style="color: #000000;">20</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">050</span>        </span>g.dispose();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">051</span>        </span>bs.show();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">052</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">053</span></span>}</pre>
<p>Veja que essas classes recebem &#8220;de fora&#8221;, no momento de sua construção, os objetos necessários para seu funcionamento. Ou seja, elas não possuem dados próprios, encapsulando apenas o algoritmo. Para que elas compartilhem os mesmos dados, criei também uma classe separada para armazenar os dados da nave:</p>
<p><strong>Arquivo Nave.java</strong></p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.thread;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Nave<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>    </span><span style="color: #0000e6;">int</span> x;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>    </span><span style="color: #0000e6;">int</span> y;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>    </span><span style="color: #0000e6;">int</span> qtd;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span></span>}</pre>
<p>A classe do jogo em sí é exatamente igual à classe JogoLoopSimples vista em um artigo anterior, só que sem update() e sem render() e com o <em>gameloop</em> modificado conforme abaixo:</p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> gameloop()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span>        </span>initialize();<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">004</span>        </span></span><span style="color: #ff0000;">Controlador c = new Controlador(this, contador, nave);
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">005</span>        Renderizador r = new Renderizador(this, bs, contador, nave);</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>        </span><span style="color: #0000e6;">while</span> (<span style="color: #0000e6;">true</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>        </span>{<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">008</span>            </span></span><span style="color: #ff0000;">c.update();
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">009</span>            r.render();</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>    </span>}</pre>
<p>Além disso, mais uma pequena modificação: ao sair do programa (pressionar ESC), envio para o console os dados de pulsos e frames, para registro. Isso é feito com um System.out.println() chamado na rotina keyPressed():</p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> keyPressed(KeyEvent e)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span>        </span><span style="color: #0000e6;">if</span> (e.getKeyCode() == KeyEvent.VK_ESCAPE)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span>        </span>{<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">005</span>            </span></span><span style="color: #ff0000;">System.out.println("Pulsos: " + contador.getPulsosPorSegundo() +
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">006</span>                                "  Frames: " + contador.getFramesPorSegundo() +
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">007</span>                                "          naves: " + nave.qtd);</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>            </span>System.exit(<span style="color: #000000;">0</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>        </span>...</pre>
<p style="text-align: left;">Executando o programa assim, temos o seguinte resultado:</p>
<p style="text-align: center;"><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread01a.png"><img class="size-full wp-image-864 aligncenter" title="Thread01a" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread01a.png" alt="Thread01a" width="502" height="214" /></a></p>
<p style="text-align: center;"><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread01b.png"><img class="size-full wp-image-865 aligncenter" title="Thread01b" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread01b.png" alt="Thread01b" width="279" height="222" /></a></p>
<p style="text-align: left;">Reconhece a tela? É o mesmo protótipo da nave dos outros posts. Mas perai&#8230; Uau! 460 fps! Não eram apenas 40! Como foi que ficou mais rápido?</p>
<p>Simples: troquei de máquina&#8230; Veja: essa é uma máquina bem mais rápida e tem um processador de dois núcleos como podemos ver no painel do gerenciador de tarefas. Note outra coisa também: apesar do jogo estar programado de forma a rodar o mais rápido possível (sem limitação de pulsos), ele utiliza apenas 50% do processamento da máquina. Nos gráficos pode-se ver claramente que o jogo está ocupando praticamente todo núcleo da esquerda, enquanto o da direita está ocioso (quase ocioso, na verdade, está atendendo o S.O. e processos de fundo, como o antivirus).</p>
<p>Abaixo da tela está a saída do console do NetBeans, mostrando o número de pulsos e frames registrados ao fechar o programa.</p>
<h2>A soma das partes</h2>
<p>Modifiquemos agora nosso gameloop <strong>comentando o update()</strong>. Assim vamos ver quantos frames conseguimos se eliminarmos o trabalho de atualizar a lógica do jogo.</p>
<p>A saída é a seguinte:</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread02a.png"><img class="aligncenter size-full wp-image-866" title="Thread02a" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread02a.png" alt="Thread02a" width="468" height="199" /></a></p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread02b.png"><img class="aligncenter size-full wp-image-867" title="Thread02b" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread02b.png" alt="Thread02b" width="278" height="222" /></a>Veja que temos zero pulsos, já que update() nunca foi executada. Mas a quantidade de frames não mudou. Ou seja, o impacto de processamento da nossa lógica é muito pequeno. Vejamos o contrário. Vamos <strong>comentar o render()</strong>.</p>
<p>Resultado abaixo:</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread03a.png"><img class="aligncenter size-full wp-image-868" title="Thread03a" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread03a.png" alt="Thread03a" width="468" height="199" /></a><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread03b.png"><img class="aligncenter size-full wp-image-872" title="Thread03b" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread03b.png" alt="Thread03b" width="278" height="222" /></a>Pois é, sem o render() não aparece a tela. Mas o programa está lá, rodando, como podemos ver pelo processamento. Ao pressionar ESC basta olhar para a saída para ver a quantidade de pulsos e&#8230; Caraca! Mais de três milhões e meio de pulsos por segundo! Realmente, a parte (bem) mais pesada é a atualização da tela. A atualização da lógica (nesse caso, pelo menos) é tão efêmera que esse computador consegue realizar mais de 3.000.000 em um segundos contra apenas 460 atualizações da tela no mesmo tempo.</p>
<h2>Analisando os resultados, entram as Threads</h2>
<p>A primeira coisa importante é ver como o render() segura o jogo quando usamos esse tipo de <em>gameloop</em>, que é o mais simples. A cada volta do laço temos um update() (muito rápido) e um render(), que demora e faz com que o próximo update() acabe demorando a ser executado.</p>
<p>Mas o que conta para este post é o seguinte: reveja as imagens acima e preste atenção no processamento. Ele nunca passa de 50%. Ou seja, meu jogo não está tirando tudo da minha máquina nova! Praticamente ele só usa o núcleo da esquerda, enquanto o outro fica com pouco processamento, oriundo das tarefas do sistema. Isso é bom, na verdade. Mas e se eu precisasse de mais processamento? Teria uma forma de usar o outro núcleo? Tem sim, com <em>threads</em>.</p>
<p>Você sabe que o S.O. é multitarefa, ou seja, executa vários programas ao mesmo tempo. Você pode ver um vídeo e ouvir música ao mesmo simultâneamente, porque o S.O dá um pouco de processador para o vídeo e um pouco para a música. É a mesma CPU, porém dividida entre dois programas.</p>
<p>Se tem mais de uma CPU (mais de um núcleo, como na máquina acima), o S.O. pode dar um núcleo inteiro para o vídeo e o outro núcleo para a música, ao invés de dividir a mesma CPU. Isso torna as coisas mais ágeis ainda.</p>
<p>As <em>threads</em> permitem ter esta multitarefa dentro do mesmo programa. Por exemplo, você cria uma <em>thread</em> para carregar os dados do jogo e outra para rodar uma animação. Assim, o S.O. dá um pouco de processamento para cada uma,  e o resultado é que você pode mostrar uma animação enquanto os dados são carregados.</p>
<p>A modificação que faço a seguir no código vai permitir colocar o Controlador em uma <em>thread</em> e o Renderizador em outra, de forma a executarem paralelamente e, de quebra, rodar cada um em um núcleo, utilizando todo o poder da máquina. Se o render() sozinho dá 460 frames e update(), também sozinho, dá 3.000.000, agora deverei obter o jogo rodando simultâneamente com 3.000.000 pulsos e 460 frames.</p>
<p>Vamos ver se funciona:</p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Controlador <span style="color: #ff0000;">implements Runnable</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span>    </span>Contador contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span>    </span>JFrame frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>    </span>Nave nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>    </span><span style="color: #0000e6;">public</span> Controlador(JFrame frame, Contador contador, Nave nave)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>        </span><span style="color: #0000e6;">this</span>.frame = frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>        </span><span style="color: #0000e6;">this</span>.contador = contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>        </span><span style="color: #0000e6;">this</span>.nave = nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">014</span>    </span></span><span style="color: #ff0000;">public void run()
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">015</span>    {
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">016</span>        while (true)
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">017</span>        {
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">018</span>            Thread.yield();
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">019</span>            update();
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">020</span>        }
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">021</span>    }</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> update()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">025</span>        </span>...<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">026</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">027</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Renderizador <span style="color: #ff0000;">implements Runnable</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">028</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">029</span>    </span>BufferStrategy bs;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">030</span>    </span>Contador contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">031</span>    </span>JFrame frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">032</span>    </span>Nave nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">033</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">boolean</span> terminado = <span style="color: #0000e6;">false</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">034</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">035</span>    </span><span style="color: #0000e6;">public</span> Renderizador(JFrame frame, BufferStrategy bs, Contador contador, Nave nave)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">036</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">037</span>        </span><span style="color: #0000e6;">this</span>.frame = frame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">038</span>        </span><span style="color: #0000e6;">this</span>.bs = bs;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">039</span>        </span><span style="color: #0000e6;">this</span>.contador = contador;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">040</span>        </span><span style="color: #0000e6;">this</span>.nave = nave;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">041</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">042</span>
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">043</span>    </span></span><span style="color: #ff0000;">public void run()
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">044</span>    {
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">045</span>        while (!terminado)
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">046</span>        {
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">047</span>            Thread.yield();
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">048</span>            render();
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">049</span>        }
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">050</span>    }</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">051</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">052</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> render()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">053</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">054</span>        </span>...</pre>
<p>Modifiquei o código das classes Controlador e Renderizador para que implementem a interface Runnable do Java. Para isso, também declarei o método run() e dentro dele coloquei um laço. O Renderizador tem um laço que fica chamando render(). O Controlador tem um laço que fica chamando o update().</p>
<p>Agora a modificação no <em>gameloop</em>:</p>
<pre><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> gameloop()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span>        </span>initialize();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span>        </span>Controlador c = <span style="color: #0000e6;">new</span> Controlador(<span style="color: #0000e6;">this</span>, contador, nave);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>        </span>Renderizador r = <span style="color: #0000e6;">new</span> Renderizador(<span style="color: #0000e6;">this</span>, bs, contador, nave);<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">006</span>        </span></span><span style="color: #ff0000;">Thread t;
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">007</span>        t = new Thread(c);
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">008</span>        t.start();
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">009</span>        t = new Thread(r);
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">010</span>        t.start();</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>    </span>}</pre>
<p>Aqui está o uso das <em>threads</em>, finalmente. Basta criar um objeto do tipo Thread informando para ele um objeto do tipo Runnable (o Renderizador, por exemplo). Depois chamamos o método start() da <em>thread</em> e ela vai chamar o método run() do objeto que lhe foi passado. O método run() será executado em paralelo ao resto do programa. Então, estamos colocando o laço do render() e o laço do update() para rodarem em paralelo.</p>
<p>Curioso para ver o resutado? Está abaixo:</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread04a.png"><img class="aligncenter size-full wp-image-863" title="Thread04a" src="http://abrindoojogo.com.br/wp-content/uploads/2009/10/thread04a.png" alt="Thread04a" width="468" height="199" /></a></p>
<p>Voilá! Um milhão e oitocentos mil pulsos e 459 frames. E usado 100% da CPU. Veja que agora os dois núcleos estão absolutamente carregados &#8211; a linha do gráfico está &#8220;cravada&#8221; no topo.</p>
<p>Mas porque deu valores menores do que quando rodamos cada um separadamente? Bom, é que a CPU ainda precisa atender os tais processos de fundo, S.O., antivirus, etc. Eles devem estar rodando no mesmo núcleo do update(), o que fez ele executar mais lentamente. Mas foi uma boa escolha do S.O., já que esse é o processo mais leve. Inteligentes estas máquinas modernas, não?</p>
<p>De qualquer forma, é um desempenho muito acima da primeira versão que eu mostrei.</p>
<h2>Conclusão</h2>
<p>Não usem <em>threads</em>.</p>
<p>Pelo menos não até chegar a um ponto onde não tenha mais o quê otimizar no código de vocês e ainda assim o jogo esteja lento. Uma minoria de jogos atuais faz uso intensivo de <em>threads</em> (menos de 20, pelo que sei), e todos especialistas concordam que não é fácil.</p>
<p>O que fiz no código acima, compartilhar um objeto (a nave) entre duas <em>threads</em> rodando paralelamente é perigoso. Nesse caso uma delas atualiza os dados e a outra apenas lê. Mas se duas <em>threads</em> atualizarem os mesmos dados ao mesmo tempo, as consequencias serão imprevisíveis. O Java facilita porque possui formas de sincronizar dados, impedindo sua leitura simultaneamente por duas <em>threads</em>. Mas não adianta sincronizar tudo, senão uma <em>thread</em> vai acabar esperando pela outra para poder acessar os dados e vão acabar rodando em sequencia, ao invés de em paralelo.</p>
<p>Por outro lado, o Java, por sí,  já tira proveito de processadores de múltiplos núcleos. Existem outros processos que a máquina virtual faz, como coleta de lixo e otimização interativa do código. A JVM (Máquina Virtual Java) faz uso de <em>threads</em> para separar e rodar em paralelo estas operações, melhorando o desempenhdo do seu programa sem você ter que fazer nada.</p>
<p>Bom, fica aí um exemplo de uso de <em>threads</em> para quem não conhecia.</p>
<p><a href="http://blog.abrindoojogo.com.br/como-obter-os-codigos-fonte-dos-artigos/">Baixe o código fonte deste artigo.</a></p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 1850px; width: 1px; height: 1px;">&lt;pre style=&#8221;font-family:Monospaced,monospace;color:#000000&#8243;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;001&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;package&lt;/span&gt; abrindoojogo.exemplos.thread;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;002&lt;/span&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;003&lt;/span&gt;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;public&lt;/span&gt; &lt;span style=&#8221;color:#0000e6;&#8221;&gt;class&lt;/span&gt; Nave&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;004&lt;/span&gt;&lt;/span&gt;{&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;005&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;int&lt;/span&gt; x;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;006&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;int&lt;/span&gt; y;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;007&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;int&lt;/span&gt; qtd;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;008&lt;/span&gt;&lt;/span&gt;}&lt;/pre&gt;</div>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/threads-apenas-um-exemplo/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>GameLoop com taxa constante de pulsos – parte 2 de 2</title>
		<link>http://abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-%e2%80%93-parte-2-de-2</link>
		<comments>http://abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-%e2%80%93-parte-2-de-2#comments</comments>
		<pubDate>Sat, 26 Sep 2009 02:18:00 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://blog.abrindoojogo.com.br/?p=743</guid>
		<description><![CDATA[No artigo anterior vimos o game loop em sua forma mais simples, que tem o problema de ter a taxa de pulsos e frames presas uma a outra. Isso faz o jogo correr mais lentamente em CPUs lentas e acelerar em CPU mais poderosas, impedindo uma velocidade estável em todas plataformas. Neste artigo veremos como [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop1.png"><img class="alignleft size-full wp-image-729" title="GameLoop" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop1.png" alt="GameLoop" width="200" height="150" /></a>No artigo anterior vimos o game loop em sua forma mais simples, que tem o problema de ter a taxa de pulsos e frames presas uma a outra. Isso faz o jogo correr mais lentamente em CPUs lentas e acelerar em CPU mais poderosas, impedindo uma velocidade estável em todas plataformas. Neste artigo veremos como criar um game loop que garanta uma velocidade fixa para o jogo.</p>
<p><span id="more-743"></span>Aprendemos, no post anterior, a diferença entre o pulso e o frame, sendo o primeiro relacionado à lógica do jogo e o segundo à atualização da tela. Tinhamos uma classe Main que criava um objeto do tipo JogoLoopSimples. Vamos modificar essa classe para usar agora um objeto do tipo JogoPulsoFixo.</p>
<p><strong>Arquivo Main.java</strong></p>
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.gameloop;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Main<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">static</span> <span style="color: #0000e6;">void</span> main(String[] args)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>        </span>JogoPulsoFixo jogo = <span style="color: #0000e6;">new</span> JogoPulsoFixo();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>        </span>jogo.gameloop();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span></span>}</span></pre>
<p>O game loop da classe JogoLoopSimples era assim (para relembrar):</p>
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> gameloop()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span>        </span>initialize();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span>        </span><span style="color: #0000e6;">while</span> (<span style="color: #0000e6;">true</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>            </span>Thread.yield();<span style="color: #000000;">
<strong><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>            </strong></span><strong>update();</strong><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>            </span>render();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>    </span>}</span></pre>
<p>Uma chamada a update() e uma a render(), acopladas. Se render demora, update também demora e o jogo fica lento. Bem, vamos partir do seguinte pressuposto: <strong>é possível &#8220;aturar&#8221; uma taxa de frames baixa, mas uma taxa de pulsos baixa modifica a jogabilidade.</strong></p>
<p>Imagine um jogo onde uma nave se move um pixel por pulso. Se temos 60 pulsos por segundo, ao final de dois segundos a nave terá se movido 120 pixels. Mas se a taxa cair para 10 pulsos por segundo, em dois segundos a nave vai se mover apenas 20 pixels. E mais: se o computador for muito rápido, a taxa pode subir a 100 pulsos por segundo, e a nave vai andar 200 pixels em dois segundos. A jogabilidade é totalmente afetada.</p>
<p>A solução que apresento a seguir tenta manter a taxa de pulsos fixa, em detrimento da taxa de frames. Ou seja, se a máquina é lenta, priorizamos os pulsos e geramos os frames conforme der. Sempre teremos 60 pulsos por segundo, embora a taxa de frames possa cair para 10.</p>
<p>Isso causa o seguinte efeito: a nave vai se mover sempre 120 pixels em dois segundos, independente da velocidade da máquina. Mas se a máquina for lenta, a tela estará sendo atualizada apenas a 10 frames por segundo &#8211; o jogador vai ver a imagem quadro a quadro, mas a jogabilidade não fica tão comprometida, porque não há mudança na velocidade da ação.</p>
<p>E se a máquina for muito rápida, ainda assim ficaremos apenas com 60 pulsos por segundo, embora possamos estar obtendo 100 frames. A atualização da tela será bem rápida, o que é bom, e a nave continua se movendo na velocidade esperada.</p>
<p>Eu mostro abaixo a nova classe, chamada JogoPulsoFixo. Ela é derivada da classe do artigo anterior, de forma que tem tudo igual a ela. A lógica do jogo é exatamente a mesma. Só sobreescrevi o método gameloop, para modificá-lo.</p>
<p><strong>Arquivo JogoPulsoFixo.java</strong></p>
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.gameloop;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> JogoPulsoFixo <span style="color: #0000e6;">extends</span> JogoLoopSimples<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span>{<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">005</span>    </span></span><span style="color: #ff0000;">long PULSOS_DESEJADOS_POR_SEGUNDO = 60;
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">006</span>    double NANOS_ESPERADOS_POR_PULSO = Contador.NANOS_EM_UM_SEGUNDO / PULSOS_DESEJADOS_POR_SEGUNDO;</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>    </span>@Override<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> gameloop()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>        </span>initialize();<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">012</span>        </span></span><span style="color: #ff0000;">long nanoTimeDoProximoPulso = System.nanoTime();</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>        </span><span style="color: #0000e6;">while</span> (<span style="color: #0000e6;">true</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>            </span>Thread.yield();<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">016</span>            </span></span><span style="color: #ff0000;">while (System.nanoTime() &gt; nanoTimeDoProximoPulso)
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">017</span>            {
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">018</span>                update();
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">019</span>                nanoTimeDoProximoPulso += NANOS_ESPERADOS_POR_PULSO;
<span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">020</span>            }</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">021</span>            </span>render();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span></span>}</span></pre>
<p>A modificação (marcada em vermelho) é simples em termos de código, mas pode ser difícil de entender como funciona. Por isso vou explicar bem detalhadamente.</p>
<p>Nas linhas 005, 006  são declaradas constantes. PULSOS_DESEJADOS_POR_SEGUNDO armazena a quantidade de pulsos que desejamos que o game rode. Nesse caso é 60. Não é necessário mais do que isso para a lógica de qualquer jogo. Alguns rodam a 30 ou 25.</p>
<p>NANOS_ESPERADOS_POR_PULSO armazena a quantidade de nanosegundos que cada pulso deve durar. Calcular isso é fácil: se queremos 60 pulsos por segundo, basta pegar a quantidade total de nanosegundos que cabem em um segundo (1e9 ou  1.000.000.000) e dividir por sessenta pulsos. Cada pulso vai durar, nesse caso, 16.666.666 nanosegundos. Em geral vai durar menos, mas queremos ter um pulso a cada 16.666.666 nanosegundos, de forma a constituir 60 por segundo.</p>
<p>Agora veja o game loop. A grande mudança é que temos um outro laço dentro dele, para chamar repetidamente update(). Funciona assim: inicializamos uma variável chamada nanoTimeDoProximoPulso com o valor no nanosegundo atual. Em seguida entramos no game loop e já caimos no loop do update. É feita a verificação para ver se o nanosegundo atual é maior do que o nanoTimeDoProximoPulso, o que certamente não será, já que acabamos de atribuir o tempo atual a esta variável.</p>
<p>Pois bem. Entramos no loop do update(), chamamos esta rotina e depois adicionamos ao nanoTimeDoProximoPulso a quantidade de nanos esperados em um pulso. Isso nos dá o momento no tempo quando deverá ser executado o próximo pulso. Não executaremos ele antes desse tempo. Por outro lado, passar muito desse tempo, executaremos ele mais de uma vez até recuperar o atraso.</p>
<p>Vamos analisar um exemplo volta a volta do game loop. Respire fundo antes de continuar lendo.</p>
<ol>
<li>Vamos assumir que tudo iniciou com o nanoTime = 0 (zero). Executamos update(), que demora 5.000.000 nanosegundos e somamos 16.666.666 na variável nanoTimeDoProximoPulso. Isso quer dizer que o próximo pulso é esperado para ocorrer nesse tempo.</li>
<li>Como update() demorou apenas 5.000.000 nanosegundos, ainda não chegamos ao 16.666.666 e saimos do loop do update. É executado em seguida o  render(), que demora mais 5.000.000 nanosegundos e voltamos ao início do game loop.</li>
<li>Nova verificação do loop do update. O tempo atual é maior do que 16.666.666? Já que update() levou 5.000.000 e render() mais 5.000.000, estamos em 10.000.000 nanosegundos, que é menor. Não entramos no loop do update, ou seja, desta vez o update() não será executado, porque ainda não está na hora esperada. Executamos o render(), que leva mais 5.000.000 nanosegundos e voltamos ao início do game loop.</li>
<li>Agora já estamos em 15.000.000, mas ainda é menor do que 16.666.666, então pulamos novamente o loop do update e vamos direto para o render. Mais 5.000.000 nanosegundos e voltamos ao início.</li>
<li>Agora sim, estamos em 20.000.000 nanosegundos e isso é maior do que o esperado para o próximo pulso, que deveria ter ocorrido em 16.666.666. Estamos atrasados, mas tudo bem &#8211; agora entramos no loop do update, executamos ele (mais 5.000.000) e somamos mais 16.666.666 na variável nanoTimeDoProximoPulso. Isso quer dizer que agora vamos esperar até o tempo chegar em 33.333.332 para executar update() novamente.</li>
</ol>
<p>Já deu para notar que update está sendo limitado. Praticamente temos três render() para cada update(). Essa é uma máquina rápida. Vamos refazer a análise em uma máquina lenta.</p>
<ol>
<li>Tudo inicia no nanoTime = 0 (zero). Executamos update(), que agora demora 10.000.000 nanosegundos e somamos 16.666.666 na variável nanoTimeDoProximoPulso.</li>
<li>Como update() demorou apenas 9.000.000 nanosegundos, ainda não chegamos ao 16.666.666 e saimos do loop do update. É executado em seguida o  render(), que demora 15.000.000 nanosegundos (placa de vídeo lenta) e voltamos ao início do game loop.</li>
<li>Nova verificação do loop do update e o tempo atual é 25.000.000, ou seja, maior que o 16.666.666 esperado para o próximo pulso. Assim, entramos no loop do update e executamos ele. Mais 10.000.000 se passam e estamos então há 35.000.000 nanosegundos de jogo. Acrescentamos novamente 16.666.666 à variável, ficando com 33.333.332, que seria a hora do próximo pulso.</li>
<li>Mas veja: já estamos em 35.000.000, ou seja, já passou a hora do segundo pulso. Então ficamos dentro do loop do update (porque 35.000.000 é maior que 33.333.332) e vamos executar update mais uma vez. Se passam mais 10.000.000 e estamos em 45.000.000. Somamos novamente 16.666.666 na variável e o próximo pulso fica então esperado para 49.999.998.</li>
<li>Ok, desta vez o tempo atual (45.000.000) é menor do que o esperado para o próximo pulso (49.999.998). Então pulamos o loop do update e vamos para o render(). Executamos ele e, devido aos seus 15.000.000 ficamos em 60.000.000 e voltamos ao início.</li>
</ol>
<p>Já deu para ver que vamos entrar novamente no loop do update porque estamos bem atrasados. Vamos acabar executando o update duas vezes novamente, ou seja, nessa máquina o update executa o dobro de vezes que o render.</p>
<p>Caramba, que explicação cheia de volta&#8230; Entendeu? Espero que sim. Caso contrário, leia novamente o exemplo. Experimente colocar o comando contador.sleep(X), onde X é um número de milisegundos, dentro das rotinas update() e render() no arquivo JogoLoopSimples. Isso vai simular rotinas demoradas. Use valores como 50 ou 100  milisegundos.</p>
<p>Esse game loop mantém a taxa de pulsos fixa (na verdade pode oscilar entre 60 e 62) e pode ser utilizado para a criação de games reais. Mas ele apresenta um problema com máquina muitissimo lentas: pode ser que o update() precise rodar 500 vezes para cada render(). Ou mais! Ou ainda, ficar rodando sem nunca chegar na taxa desejada, e assim nunca executar o update().</p>
<p>Alguma dica de como resolver isso? Se você achar uma solução envie para mim (<strong>nornberg</strong> no gmail). Depois publico um post citando as soluções que aparecerem.</p>
<p><a href="http://blog.abrindoojogo.com.br/como-obter-os-codigos-fonte-dos-artigos/">Baixe o código fonte deste artigo.</a></p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 786px; width: 1px; height: 1px;">&lt;pre&gt;&lt;span style=&#8221;font-family:Monospaced,monospace;color:#000000&#8243;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;001&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;package&lt;/span&gt; abrindoojogo.exemplos.gameloop;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;002&lt;/span&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;003&lt;/span&gt;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;public&lt;/span&gt; &lt;span style=&#8221;color:#0000e6;&#8221;&gt;class&lt;/span&gt; JogoPulsoFixo &lt;span style=&#8221;color:#0000e6;&#8221;&gt;extends&lt;/span&gt; JogoLoopSimples&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;004&lt;/span&gt;&lt;/span&gt;{&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;005&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;long&lt;/span&gt; PULSOS_DESEJADOS_POR_SEGUNDO = &lt;span style=&#8221;color:#000000;&#8221;&gt;60&lt;/span&gt;;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;006&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;double&lt;/span&gt; NANOS_ESPERADOS_POR_PULSO = Contador.NANOS_EM_UM_SEGUNDO / PULSOS_DESEJADOS_POR_SEGUNDO;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;007&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;long&lt;/span&gt; MAX_FRAMES_PARA_PULAR = &lt;span style=&#8221;color:#000000;&#8221;&gt;2&lt;/span&gt;;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;008&lt;/span&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;009&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;public&lt;/span&gt; &lt;span style=&#8221;color:#0000e6;&#8221;&gt;void&lt;/span&gt; gameloop()&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;010&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;011&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;initialize();&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;012&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;long&lt;/span&gt; nanoTimeDoProximoPulso = System.nanoTime();&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;013&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;while&lt;/span&gt; (&lt;span style=&#8221;color:#0000e6;&#8221;&gt;true&lt;/span&gt;)&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;014&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;015&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Thread.yield();&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;016&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;long&lt;/span&gt; pulsos = &lt;span style=&#8221;color:#000000;&#8221;&gt;0&lt;/span&gt;;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;017&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&#8221;color:#0000e6;&#8221;&gt;while&lt;/span&gt; (System.nanoTime() &amp;gt; nanoTimeDoProximoPulso &amp;amp;&amp;amp; pulsos &amp;lt; MAX_FRAMES_PARA_PULAR)&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;018&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;019&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;update();&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;020&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;nanoTimeDoProximoPulso += NANOS_ESPERADOS_POR_PULSO;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;021&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;pulsos++;&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;022&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;023&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;render();&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;024&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;025&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;span style=&#8221;color:#000000;&#8221;&gt;&lt;br/&gt;&lt;span style=&#8217;color:#666;background-color:#DDD;border-right:1px #999 solid;margin-right:5px;padding:2px&#8217;&gt;026&lt;/span&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;</div>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-%e2%80%93-parte-2-de-2/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>GameLoop com taxa constante de pulsos &#8211; parte 1 de 2</title>
		<link>http://abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-parte-1-de-2</link>
		<comments>http://abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-parte-1-de-2#comments</comments>
		<pubDate>Fri, 25 Sep 2009 03:31:02 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://blog.abrindoojogo.com.br/?p=727</guid>
		<description><![CDATA[O coração de qualquer jogo é o game loop, um laço que fica sendo repetido durante toda execução do jogo. A cada volta desse laço temos um novo frame de jogo. Mas você sabe que a taxa de frames pode variar muito de um hardware para outro. Como manter a lógica do jogo rodando a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop1.png"><img class="alignleft size-full wp-image-729" title="GameLoop" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop1.png" alt="GameLoop" width="200" height="150" /></a></p>
<p>O coração de qualquer jogo é o <em>game loop</em>, um laço que fica sendo repetido durante toda execução do jogo. A cada volta desse laço temos um novo frame de jogo. Mas você sabe que a taxa de frames pode variar muito de um hardware para outro. Como manter a lógica do jogo rodando a uma velocidade fixa, independente da variação nos frames?<br />
<span id="more-727"></span><br />
Quando jogamos, o que vemos na tela é uma sucessão de quadros que nos dá a impressão de movimento. Isso é chamado animação e tenho certeza que você já conhece seus princípios. Em geral somos levados a crer que, a cada quadro novo que vemos, algo mudou no estado do jogo. Se uma nave está se movendo, a cada quadro ela estará, digamos, um pixel para a direita.</p>
<p>É o <em>game loop</em>, o laço principal do jogo, que emite o que podemos chamar de <strong>pulsos </strong>para atualizar o estado do jogo (<em><strong>update</strong></em>) e redesenhar a imagem na tela (<em><strong>render</strong></em>). Em sua forma mais simples, a cada volta do <em>game loop</em> temos um pulso para <em>update </em>e um para <em>render</em>. Mas estas duas tarefas não precisam ser sempre sincronizadas. Na verdade, é melhor que não sejam.</p>
<p>Vamos contruir um programa de exemplo para estudar mais a fundo o <em>game loop</em>. Neste post vamos ver o <em>loop </em>mais simples e entender sua limitação. No próximo veremos como desacoplar o <em>update </em>do <em>render</em>, de forma que o <em>update </em>rode sempre a uma determinada velocidade e o <em>render </em>rode o mais rápido que puder.</p>
<p><strong>Arquivo Main.java</strong></p>
<div style="overflow: scroll; border: 1px solid #cccccc;">
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.gameloop;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Main<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">static</span> <span style="color: #0000e6;">void</span> main(String[] args)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>        </span>JogoLoopSimples jogo = <span style="color: #0000e6;">new</span> JogoLoopSimples();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>        </span>jogo.gameloop();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span></span>}</span></pre>
</div>
<p>Esta classe simplesmente cria um objeto do tipo JogoLoopSimples e chama seu método gameloop() que vai rodar o jogo. A seguir a classe do jogo em sí, que possui o game loop.</p>
<p><strong>Arquivo JogoLoopSimples</strong></p>
<div style="overflow: scroll; border: 1px solid #cccccc;">
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.gameloop;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">import</span> java.awt.Color;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span><span style="color: #0000e6;">import</span> java.awt.Dimension;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span></span><span style="color: #0000e6;">import</span> java.awt.Graphics2D;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span></span><span style="color: #0000e6;">import</span> java.awt.Toolkit;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span></span><span style="color: #0000e6;">import</span> java.awt.event.KeyEvent;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span></span><span style="color: #0000e6;">import</span> java.awt.event.KeyListener;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span></span><span style="color: #0000e6;">import</span> java.awt.image.BufferStrategy;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span></span><span style="color: #0000e6;">import</span> javax.swing.JFrame;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span></span><span style="color: #0000e6;">import</span> javax.swing.WindowConstants;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> JogoLoopSimples <span style="color: #0000e6;">extends</span> JFrame <span style="color: #0000e6;">implements</span> KeyListener<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>    </span>BufferStrategy bs;<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">016</span>    </span></span><span style="color: #ff0000;">Contador contador;</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">017</span>    </span><span style="color: #0000e6;">int</span> nave_x, nave_y, nave_qtd;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">018</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">019</span>    </span><span style="color: #0000e6;">public</span> JogoLoopSimples()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">020</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">021</span>        </span>setUndecorated(<span style="color: #0000e6;">true</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>        </span>setSize(<span style="color: #000000;">800</span>, <span style="color: #000000;">600</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>        </span>Dimension d = Toolkit.getDefaultToolkit().getScreenSize();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span>        </span>setLocation(d.width / <span style="color: #000000;">2</span> - <span style="color: #000000;">400</span>, d.height / <span style="color: #000000;">2</span> - <span style="color: #000000;">300</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">025</span>        </span>setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">026</span>        </span>setIgnoreRepaint(<span style="color: #0000e6;">true</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">027</span>        </span>addKeyListener(<span style="color: #0000e6;">this</span>);<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">028</span>        </span></span><span style="color: #ff0000;">contador = new Contador();</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">029</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">030</span>
<strong><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">031</span>    </strong></span><strong><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> gameloop()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">032</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">033</span>        </span>initialize();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">034</span>        </span><span style="color: #0000e6;">while</span> (<span style="color: #0000e6;">true</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">035</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">036</span>            </span>Thread.yield();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">037</span>            </span>update();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">038</span>            </span>render();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">039</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">040</span>    </span>}</strong><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">041</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">042</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> initialize()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">043</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">044</span>        </span>setVisible(<span style="color: #0000e6;">true</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">045</span>        </span>createBufferStrategy(<span style="color: #000000;">2</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">046</span>        </span>bs = getBufferStrategy();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">047</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">048</span>        </span>nave_x = <span style="color: #000000;">400</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">049</span>        </span>nave_y = <span style="color: #000000;">50</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">050</span>        </span>nave_qtd = <span style="color: #000000;">1</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">051</span>
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">052</span>        </span></span><span style="color: #ff0000;">contador.inicia();</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">053</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">054</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">055</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> update()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">056</span>    </span>{<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">057</span>        </span></span><span style="color: #ff0000;">contador.contaPulso();</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">058</span>        </span>nave_x += <span style="color: #000000;">1</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">059</span>        </span><span style="color: #0000e6;">if</span> (nave_x &gt; getWidth() + <span style="color: #000000;">30</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">060</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">061</span>            </span>nave_x = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">062</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">063</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">064</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">065</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> render()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">066</span>    </span>{<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">067</span>        </span></span><span style="color: #ff0000;">contador.contaFrame();</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">068</span>        </span>Graphics2D g = (Graphics2D) bs.getDrawGraphics();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">069</span>        </span>g.setColor(Color.black);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">070</span>        </span>g.fillRect(<span style="color: #000000;">0</span>, <span style="color: #000000;">0</span>, getWidth(), getHeight());<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">071</span>        </span><span style="color: #0000e6;">int</span> x = nave_x;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">072</span>        </span><span style="color: #0000e6;">int</span> y = nave_y;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">073</span>        </span><span style="color: #0000e6;">for</span> (<span style="color: #0000e6;">int</span> i = <span style="color: #000000;">0</span>; i &lt; nave_qtd; i++)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">074</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">075</span>            </span>g.setColor(Color.yellow);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">076</span>            </span>g.drawLine(x, y, x - <span style="color: #000000;">20</span>, y - <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">077</span>            </span>g.drawLine(x, y, x - <span style="color: #000000;">20</span>, y + <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">078</span>            </span>g.drawLine(x - <span style="color: #000000;">20</span>, y - <span style="color: #000000;">5</span>, x - <span style="color: #000000;">20</span>, y + <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">079</span>            </span>y += <span style="color: #000000;">15</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">080</span>            </span><span style="color: #0000e6;">if</span> (y &gt; <span style="color: #000000;">550</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">081</span>            </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">082</span>                </span>y = nave_y;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">083</span>                </span>x += <span style="color: #000000;">15</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">084</span>            </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">085</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">086</span>        </span>g.setColor(Color.white);<span style="color: #000000;">
<span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">087</span></span>        </span>g.drawString(<span style="color: #ce7b00;">"Pulsos: "</span> + <span style="color: #ff0000;">contador.getPulsosPorSegundo()</span> + <span style="color: #ce7b00;">"  Frames: "</span> + <span style="color: #ff0000;">contador.getFramesPorSegundo()</span> + <span style="color: #ce7b00;">"          naves: "</span> + nave_qtd, <span style="color: #000000;">10</span>, <span style="color: #000000;">20</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">088</span>        </span>g.dispose();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">089</span>        </span>bs.show();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">090</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">091</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">092</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> keyPressed(KeyEvent e)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">093</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">094</span>        </span><span style="color: #0000e6;">if</span> (e.getKeyCode() == KeyEvent.VK_ESCAPE)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">095</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">096</span>            </span>System.exit(<span style="color: #000000;">0</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">097</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">098</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">099</span>        </span><span style="color: #0000e6;">if</span> (e.getKeyCode() == KeyEvent.VK_UP)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">100</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">101</span>            </span>nave_y -= <span style="color: #000000;">1</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">102</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">103</span>        </span><span style="color: #0000e6;">if</span> (e.getKeyCode() == KeyEvent.VK_DOWN)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">104</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">105</span>            </span>nave_y += <span style="color: #000000;">1</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">106</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">107</span>        </span><span style="color: #0000e6;">if</span> (e.getKeyCode() == KeyEvent.VK_RIGHT)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">108</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">109</span>            </span><span style="color: #0000e6;">if</span> (nave_qtd &lt; <span style="color: #000000;">1054</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">110</span>            </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">111</span>                </span>nave_qtd += <span style="color: #000000;">1</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">112</span>            </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">113</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">114</span>        </span><span style="color: #0000e6;">if</span> (e.getKeyCode() == KeyEvent.VK_LEFT)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">115</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">116</span>            </span><span style="color: #0000e6;">if</span> (nave_qtd &gt; <span style="color: #000000;">1</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">117</span>            </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">118</span>                </span>nave_qtd -= <span style="color: #000000;">1</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">119</span>            </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">120</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">121</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">122</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">123</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> keyReleased(KeyEvent e)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">124</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">125</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">126</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">127</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> keyTyped(KeyEvent e)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">128</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">129</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">130</span></span>}</span></pre>
</div>
<p>Vejamos os métodos mais importantes. O contructor faz bastante coisa de configuração, mas tudo com relação à janela do jogo. É tirada a decoração (título, borda, etc) ficando apenas um quadro centralizado no vídeo. É centralizado baseado no tamanho da tela, obtida por meio de Toolkit.getDefaultToolkit().getScreenSize().  Boa parte desse código é parecida com o que foi mostrado no post <a href="http://blog.abrindoojogo.com.br/passive-vs-active-rendering-%E2%80%93-parte-2-de-2/">Passive VS Active Rendering</a>. Note, no entando na criação do objeto &#8220;contador&#8221;. Ele será utilizado para contar quantos pulsos e quantos <em>frames </em>obteremos. Os pontos onde ele é utilizado estão destacados em vermelho.</p>
<p>O jogo é muito simples &#8211; na verdade nem é um jogo. O método update() incrementa a variável nave_x, fazendo ela ir até a direita da tela e então recomeçar da esquerda. Quando uma tecla é pressionada, o método keyPressed modifica a variável nave_y, fazendo a posição subir ou descer, ou aumenta/diminui a variável nave_qtd, que informa quantos sprites teremos na tela.</p>
<p>O método render() limpa a tela, desenha a &#8220;nave&#8221; (um triângulo feito com linhas) dentro de um <em>loop </em>que vai repetir o desenho tantas vezes quanto for o valor de nave_qtd. Depois mostra na tela os valores de pulsos por segundo e <em>frames </em>por segundos do contador.</p>
<p>Note que toda vez que o método update() é executado, dentro dele é chamado o contador.contaPulso(). E no método render() é chamado contador.contaFrame(). Assim estamos contando quantas vezes estes dois métodos são chamados.</p>
<p>Nosso game loop é a versão mais simples possível, reproduzida abaixo.</p>
<div style="overflow: scroll; border: 1px solid #cccccc;">
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">031</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> gameloop()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">032</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">033</span>        </span>initialize();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">034</span>        </span><span style="color: #0000e6;">while</span> (<span style="color: #0000e6;">true</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">035</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">036</span>            </span>Thread.yield();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">037</span>            </span>update();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">038</span>            </span>render();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">039</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">040</span>    </span>}</span></pre>
</div>
<p>É chamado update() e depois render(), um após o outro sem nenhum controle mais elaborado. O método yield() faz o programa interromper rapidamente seu processamento para que o resto do sistema tenha tempo de CPU. Usar ele faz o programa parar um pouco para escutar o teclado. Sem ele, um pressionar de tecla pode ser perdido.</p>
<p>Finalmente vejamos o código do contador.</p>
<p><strong>Arquivo Contador.java</strong></p>
<div style="overflow: scroll; border: 1px solid #cccccc;">
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #0000e6;">package</span> abrindoojogo.exemplos.gameloop;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span></span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">class</span> Contador<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span></span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>    </span><span style="color: #0000e6;">static</span> <span style="color: #0000e6;">public</span> <span style="color: #0000e6;">double</span> NANOS_EM_UM_SEGUNDO = <span style="color: #000000;">1e9</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>    </span><span style="color: #0000e6;">protected</span> <span style="color: #0000e6;">long</span> pulsosPorSegundo;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>    </span><span style="color: #0000e6;">protected</span> <span style="color: #0000e6;">long</span> framesPorSegundo;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>    </span><span style="color: #0000e6;">protected</span> <span style="color: #0000e6;">long</span> nanoTimeAnterior;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>    </span><span style="color: #0000e6;">protected</span> <span style="color: #0000e6;">long</span> pulsosContados;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>    </span><span style="color: #0000e6;">protected</span> <span style="color: #0000e6;">long</span> framesContados;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> inicia()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span>        </span>nanoTimeAnterior = System.nanoTime();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>        </span>pulsosContados = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">016</span>        </span>framesContados = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">017</span>        </span>pulsosPorSegundo = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">018</span>        </span>framesPorSegundo = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">019</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">020</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">021</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> contaPulso()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>        </span>pulsosContados++;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span>        </span>verifica();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">025</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">026</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">027</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> contaFrame()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">028</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">029</span>        </span>framesContados++;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">030</span>        </span>verifica();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">031</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">032</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">033</span>    </span><span style="color: #0000e6;">protected</span> <span style="color: #0000e6;">void</span> verifica()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">034</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">035</span>        </span><span style="color: #0000e6;">if</span> (System.nanoTime() - nanoTimeAnterior &gt; NANOS_EM_UM_SEGUNDO)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">036</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">037</span>            </span>pulsosPorSegundo = pulsosContados;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">038</span>            </span>framesPorSegundo = framesContados;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">039</span>            </span>pulsosContados = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">040</span>            </span>framesContados = <span style="color: #000000;">0</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">041</span>            </span>nanoTimeAnterior = System.nanoTime();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">042</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">043</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">044</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">045</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> sleep(<span style="color: #0000e6;">long</span> miliSecondsToSleep)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">046</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">047</span>        </span><span style="color: #0000e6;">try</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">048</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">049</span>            </span>Thread.sleep(miliSecondsToSleep);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">050</span>        </span>} <span style="color: #0000e6;">catch</span> (Exception e)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">051</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">052</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">053</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">054</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">055</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">long</span> getPulsosPorSegundo()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">056</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">057</span>        </span><span style="color: #0000e6;">return</span> pulsosPorSegundo;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">058</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">059</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">060</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">long</span> getFramesPorSegundo()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">061</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">062</span>        </span><span style="color: #0000e6;">return</span> framesPorSegundo;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">063</span>    </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">064</span></span>}</span></pre>
</div>
<p>O trabalho desta classe é interessante: cada vez que chamamos o método contaPulso(), ela incrementa o contador de pulsos e chama o método verifica() que testa se já passou um segundo desde a última verificação. Se sim, ele atribui a quantidade de pulsos contados para a variável pulsosPorSegundo. Assim, esta variável é atualizada a cada segundo com a quantidade de pulsos que ocorreram. Nesse momento o contador de pulsos é zerado para contar quantos pulsos ocorrerão no próximo segundo. A mesma coisa para a contagem de frames.</p>
<p>O tempo é medido em nanosegundos, que é bem menor que os milisegundos geralmente utilizados nos programas. Um segundo contém 1.000 milisegundos, ou seja, <strong>1e3</strong> (mil). E possui 1.000.000.000 nano segundos, ou seja, <strong>1e9</strong> (um milhão). Esse valor está registrado na constante NANOS_EM_UM_SEGUNDO para ser utilizado nos cálculos.</p>
<p>Essa classe oferece ainda um método utilitário chamado sleep(), que servirá para realizarmos alguns testes. Ele simplifica o uso do método sleep() de Thread, que precisa de um <em>try-catch</em> para ser usado. Ele faz o processamento parar durante os milisegundos informados.</p>
<p>Executando esse programa, obtenho o seguinte resultado (só mostro o canto da tela):</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop01.png"><img class="aligncenter size-full wp-image-732" title="GameLoop01" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop01.png" alt="GameLoop01" width="400" height="100" /></a>Conforme os dados do contador mostrados, tenho 47 pulsos por segundo e também 47 frames. Naturalmente estes números serão sempre iguais, porque dentro do loop chamo uma vez update() e uma vez o render().</p>
<p>Se eu desejasse 60 fps (<em>frames </em>por segundo), não seria possível. 47 é tudo que eu consigo no meu computador e ainda fica variando. Se eu pressiono a seta para direita, aumentando a quantidade de <em>sprites </em>até 1054, a taxa de <em>frames </em>cai mais um pouco.</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop02.png"><img class="aligncenter size-full wp-image-733" title="GameLoop02" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop02.png" alt="GameLoop02" width="400" height="100" /></a>Talvez seu computador seja bem mais rápid e mesmo aumentando os <em>sprites </em>a taxa de frames não apresente muita diferença. Vamos fazer um teste mais exagerado. Chamaremos o método contador.sleep() dentro do método render(), de forma a fazer este método demorar alguns milisegundos a mais.</p>
<div style="overflow: scroll; border: 1px solid #cccccc;">
<pre><span style="font-family: Monospaced,monospace; color: #000000;"><span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">001</span><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">002</span>
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">003</span>    </span><span style="color: #0000e6;">public</span> <span style="color: #0000e6;">void</span> render()<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">004</span>    </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">005</span>        </span>contador.contaFrame();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">006</span>        </span>Graphics2D g = (Graphics2D) bs.getDrawGraphics();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">007</span>        </span>g.setColor(Color.black);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">008</span>        </span>g.fillRect(<span style="color: #000000;">0</span>, <span style="color: #000000;">0</span>, getWidth(), getHeight());<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">009</span>        </span><span style="color: #0000e6;">int</span> x = nave_x;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">010</span>        </span><span style="color: #0000e6;">int</span> y = nave_y;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">011</span>        </span><span style="color: #0000e6;">for</span> (<span style="color: #0000e6;">int</span> i = <span style="color: #000000;">0</span>; i &lt; nave_qtd; i++)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">012</span>        </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">013</span>            </span>g.setColor(Color.yellow);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">014</span>            </span>g.drawLine(x, y, x - <span style="color: #000000;">20</span>, y - <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">015</span>            </span>g.drawLine(x, y, x - <span style="color: #000000;">20</span>, y + <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">016</span>            </span>g.drawLine(x - <span style="color: #000000;">20</span>, y - <span style="color: #000000;">5</span>, x - <span style="color: #000000;">20</span>, y + <span style="color: #000000;">5</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">017</span>            </span>y += <span style="color: #000000;">15</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">018</span>            </span><span style="color: #0000e6;">if</span> (y &gt; <span style="color: #000000;">550</span>)<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">019</span>            </span>{<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">020</span>                </span>y = nave_y;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">021</span>                </span>x += <span style="color: #000000;">15</span>;<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">022</span>            </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">023</span>        </span>}<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">024</span>        </span>g.setColor(Color.white);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">025</span>        </span>g.drawString(<span style="color: #ce7b00;">"Pulsos: "</span> + contador.getPulsosPorSegundo() + <span style="color: #ce7b00;">"  Frames: "</span> + contador.getFramesPorSegundo() + <span style="color: #ce7b00;">"          naves: "</span> + nave_qtd, <span style="color: #000000;">10</span>, <span style="color: #000000;">20</span>);<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">026</span>        </span>g.dispose();<span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">027</span>        </span>bs.show();<span style="color: #000000;">
<strong><span style="color: #ff0000;"><span style="border-right: 1px solid #999999; background-color: #dddddd; margin-right: 5px; padding: 2px;">028</span>        </span></strong></span><strong><span style="color: #ff0000;">contador.sleep(50);</span></strong><span style="color: #000000;">
<span style="color: #666; background-color: #ddd; border-right: 1px #999 solid; margin-right: 5px; padding: 2px;">029</span>    </span>}</span></pre>
</div>
<p>Agora sim. O tempo de atualizar a tela (render) leva absurdos 50 ms (milisegundos). Absolutamente lento demais. A taxa de <strong>frames </strong>cai para 14 na minha máquina.</p>
<p><a href="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop03.png"><img class="aligncenter size-full wp-image-734" title="GameLoop03" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/gameloop03.png" alt="GameLoop03" width="400" height="100" /></a>Agora preste atenção na parte mais importante: <strong>a taxa de pulsos por segundo cai junto com os frames</strong>, embora apenas a rotina render() tenha recebido o tempo a mais. Isso ocorre porque como uma rotina é chamada depois da outra, em sequencia, update() tem que esperar render() executar para ser executada novamente.</p>
<p>Rodando o jogo você percebe que não é apenas a taxa de atualização da tela que fica lenta, <strong>mas o jogo todo</strong>. A nave agora leva uma eternidade para chegar até a extremidade da tela, porque temos apenas 14 pulsos de atualização da sua posição por segundo.</p>
<p>Está comprovado o problema. No próximo post a solução. Até amanhã.</p>
<p><a href="http://blog.abrindoojogo.com.br/como-obter-os-codigos-fonte-dos-artigos/">Baixe o código fonte deste artigo.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/gameloop-com-taxa-constante-de-pulsos-parte-1-de-2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Passive VS Active Rendering – parte 2 de 2</title>
		<link>http://abrindoojogo.com.br/passive-vs-active-rendering-%e2%80%93-parte-2-de-2</link>
		<comments>http://abrindoojogo.com.br/passive-vs-active-rendering-%e2%80%93-parte-2-de-2#comments</comments>
		<pubDate>Fri, 18 Sep 2009 01:59:53 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://blog.abrindoojogo.com.br/?p=680</guid>
		<description><![CDATA[Vimos no post anterior a atualização passiva e suas limitações. Vejamos agora coisa real, criando um programa com maior previsibilidade na atualização da tela, capacidade de rodar em tela-cheia (fullscreen) e de mudar o modo de vídeo.  Para isso aprenderemos a atualização ativa (active rendering). Atualização ativa No artigo anterior vimos a atualização passiva que [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-689" title="FullScreen" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/fullscreen1.png" alt="FullScreen" width="199" height="150" />Vimos no post anterior a atualização passiva e suas limitações. Vejamos agora coisa real, criando um programa com maior previsibilidade na atualização da tela, capacidade de rodar em tela-cheia (<em>fullscreen</em>) e de mudar o modo de vídeo.  Para isso aprenderemos a atualização ativa (<em>active rendering</em>).<span id="more-680"></span></p>
<h2>Atualização ativa</h2>
<p>No artigo anterior vimos a <a href="http://blog.abrindoojogo.com.br/passive-vs-active-rendering-parte-1-de-2/">atualização passiva</a> que pode ser utilizada para a criação de jogos que possuem gráficos simples ou ação lenta. E nestes casos é até recomendada, porque compromete pouco a CPU. Mas em jogos mais animados não podemos depender do S.O. para gerar as atualizações da tela. Nesse caso desligamos o mecanismo de atualização automatica e partimos para o manual, com a atualização ativa.</p>
<p>O Java nos permite controlar a tela de forma deterministica por meio da classe BufferStrategy. Não é um acesso direto à placa de vídeo, porque o Java nos isola da camada de hardware. Mas isso é bom, porque simplifica a coisa e nos oferece uma forma padrão para trabalhar, o mais independente possível da configuração da máquina do usuário.</p>
<p>Abaixo mostro o código de um programa quase idêntico ao do artigo anterior, porém agora usando atualização ativa.</p>
<h3>Arquivo: Main.java</h3>
<pre><span class="line-number"> 1</span> <span class="keyword-directive">package</span> abrindoojogo.exemplos.atualizacaoativa;
<span class="line-number"> 2</span>
<span class="line-number"> 3</span> <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> Main
<span class="line-number"> 4</span> {
<span class="line-number"> 5</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> main(String[] args)
<span class="line-number"> 6</span>     {
<span class="line-number"> 7</span>         MeuJogo mj = <span class="keyword-directive">new</span> MeuJogo();
<span class="line-number"> 8</span>         mj.setVisible(<span class="keyword-directive">true</span>);
<span class="line-number"> 9</span>         mj.initialize();
<span class="line-number">10</span>     }
<span class="line-number">11</span> }
<span class="line-number">12</span>
<span class="line-number">13</span></pre>
<p>Veja que a classe principal é quase igual. A diferença é que a classe MeuJogo agora possui um método initialize que deve ser chamado depois de tornarmos ela visível. Nesse método inicializamos a BufferStrategy (veja abaixo). Destaquei em vermelho as partes que são novidade em relação ao exemplo anterior.</p>
<h3>Arquivo: MeuJogo.java</h3>
<pre><span class="line-number"> 1</span> <span class="keyword-directive">package</span> abrindoojogo.exemplos.atualizacaoativa;
<span class="line-number"> 2</span>
<span class="line-number"> 3</span> <span class="keyword-directive">import</span> java.awt.Color;
<span class="line-number"> 4</span> <span class="keyword-directive">import</span> java.awt.Graphics2D;
<span class="line-number"> 5</span> <span class="keyword-directive">import</span> java.awt.event.KeyEvent;
<span class="line-number"> 6</span> <span class="keyword-directive">import</span> java.awt.event.KeyListener;
<span class="line-number"> 7</span> <span class="keyword-directive">import</span> java.awt.image.BufferStrategy;
<span class="line-number"> 8</span> <span class="keyword-directive">import</span> javax.swing.JFrame;
<span class="line-number"> 9</span> <span class="keyword-directive">import</span> javax.swing.WindowConstants;
<span class="line-number">10</span>
<span class="line-number">11</span> <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> MeuJogo <span class="keyword-directive">extends</span> JFrame <span class="keyword-directive">implements</span> KeyListener
<span class="line-number">12</span> {
<span class="line-number">13</span>     <span class="keyword-directive">in</span><span class="keyword-directive">t</span> tom;
<span style="color: #ff0000;"><span class="line-number">14</span>     BufferStrategy bs;
</span><span class="line-number">15</span>
<span class="line-number">16</span>     <span class="keyword-directive">public</span> MeuJogo()
<span class="line-number">17</span>     {
<span class="line-number">18</span>         setTitle(<span class="character">"</span><span class="character">Atualização Ativa</span><span class="character">"</span>);
<span class="line-number">19</span>         setSize(800, 600);
<span class="line-number">20</span>         setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
<span style="color: #ff0000;"><span class="line-number">21</span>         setIgnoreRepaint(<span class="keyword-directive">true</span>);</span>
<span class="line-number">22</span>         addKeyListener(<span class="keyword-directive">this</span>);
<span class="line-number">23</span>         tom = 0;
<span class="line-number">24</span>     }
<span class="line-number">25</span>
<span style="color: #ff0000;"><span class="line-number">26</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> initialize()
<span class="line-number">27</span>     {
<span class="line-number">28</span>         createBufferStrategy(1);
<span class="line-number">29</span>         bs = getBufferStrategy();
<span class="line-number">30</span>         render();
<span class="line-number">31</span>     }</span>
<span class="line-number">32</span>
<span style="color: #ff0000;"><span class="line-number">33</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> render()</span>
<span class="line-number">34</span>     {
<span style="color: #ff0000;"><span class="line-number">35</span>         Graphics2D g = (Graphics2D) bs.getDrawGraphics();</span>
<span class="line-number">36</span>         g.clearRect(0, 0, getWidth(), getHeight());
<span class="line-number">37</span>         <span class="keyword-directive">for</span> (<span class="keyword-directive">int</span> x = 0; x &lt; 800; x += 10)
<span class="line-number">38</span>         {
<span class="line-number">39</span>             <span class="keyword-directive">for</span> (<span class="keyword-directive">int</span> y = 0; y &lt; 600; y += 10)
<span class="line-number">40</span>             {
<span class="line-number">41</span>                 g.setColor(<span class="keyword-directive">new</span> Color(x % 256, y % 256, (tom * 50)
                   % 256));
<span class="line-number">42</span>                 g.fillRect(x, y, 10, 10);
<span class="line-number">43</span>             }
<span class="line-number">44</span>         }
<span style="color: #ff0000;"><span class="line-number">45</span>         g.dispose();
<span class="line-number">46</span>         bs.show();</span>
<span class="line-number">47</span>     }
<span class="line-number">48</span>
<span class="line-number">49</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> keyPressed(KeyEvent e)
<span class="line-number">50</span>     {
<span class="line-number">51</span>         <span class="keyword-directive">if</span> (e.getKeyCode() == KeyEvent.VK_ENTER)
<span class="line-number">52</span>         {
<span class="line-number">53</span>             tom++;
<span style="color: #ff0000;"><span class="line-number">54</span>             render();</span>
<span class="line-number">55</span>         }
<span class="line-number">56</span>     }
<span class="line-number">57</span>
<span class="line-number">58</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> keyReleased(KeyEvent e)
<span class="line-number">59</span>     {
<span class="line-number">60</span>     }
<span class="line-number">61</span>
<span class="line-number">62</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> keyTyped(KeyEvent e)
<span class="line-number">63</span>     {
<span class="line-number">64</span>     }
<span class="line-number">65</span> }
<span class="line-number">66</span>
<span class="line-number">67</span></pre>
<p>O contructor é muito parecido, mas preste atenção. Ele inclui agora uma chamada ao método <strong>setIgnoreRepaint() </strong>passando o valor true. Isso desliga a atualização automática. O S.O. não vai mais gerar eventos de atualização para nossa janela.</p>
<p>Em seguida temos o método initialize().</p>
<pre>26     public void initialize()
27     {
28         createBufferStrategy(1);
29         bs = getBufferStrategy();
30         render();
31     }</pre>
<p>Nesse método eu chamo <strong>createBufferStrategy()</strong>, que é pertencente à classe JFrame. O parâmetro é a quantidade de buffers de tela que quero usar. Falarei sobre isso adiante. Adquiro uma referência ao BufferStratey e armazeno na variável bs. Através desta variável eu vou ter acesso ao buffer da tela para desenhar meus gráficos. Logo após chamo o método render().</p>
<p>O método render() é o próximo declarado na classe. É nele que se dá o desenho da tela. Veja que é praticamente o mesmo código que estava dentro do método paint() do artigo anterior. Só que agora é um método próprio e não um manipulador de evento. Lembre que desligamos a atualização automática, que chamava o paint(). O método render(), por sua vez, será chamado diretamente por mim, quando eu desejar que a tela seja redesenhada.</p>
<pre>33     public void render()
34     {
35         Graphics2D g = (Graphics2D) bs.getDrawGraphics();
36         g.clearRect(0, 0, getWidth(), getHeight());
37         for (int x = 0; x &lt; 800; x += 10)
38         {
39             for (int y = 0; y &lt; 600; y += 10)
40             {
41                 g.setColor(new Color(x % 256, y % 256, (tom * 50)
                   % 256));
42                 g.fillRect(x, y, 10, 10);
43             }
44         }
45         g.dispose();
46         bs.show();
47     }</pre>
<p>Examinando esse método, vemos que a parte que lida com o objeto &#8220;g&#8221;, do tipo Graphics2D, é idêntica à anterior. A diferença está no modo como obtemos o Graphics. Antes ele era recebido como parâmetro no método paint(). Ou seja, o S.O. nos passava o Graphics ao chamar o método. Agora nós pegamos um Graphics do objeto BufferStrategy. Esse Graphics que ele retorna é uma referência para o buffer da tela, desenhando nele, desenhamos nela. Depois de usar, chamamos o método dispose para liberar &#8211; adquirimos e liberamos um novo Graphics a cada render.</p>
<p>Depois do desenho pronto, chamamos o método show() do BufferStrategy. Embora nesse momento ele fique um pouco perdido, vai fazer mais sentido quando eu falar em mais de um buffer, daqui a pouco.</p>
<p>A modificação final é no método keyPressed(), que é o manipulador para o evento de tecla pressionada. Depois de atualizar a variável &#8220;tom&#8221;, chamamos render(). Aqui reside a grande diferença: enquanto antes chamavamos repaint() para avisar o S.O. que desejávamos uma atualização, e ficava a cargo dele atualizar a tela quando bem entendesse, agora chamamos diretamente nosso método render(), que vai obter um Graphics e desenhar na hora, sem espera.</p>
<p>Execute esse programa e o resultado vai ser parecido com o anterior, na parte visual. Quando você ficar pressionando ENTER a tela vai piscar da mesma forma, porém a atualização da tela consome mais CPU e por isso se você ficar pressionando por muito tempo, os eventos keyPressed não vão ser processados a tempo e vão acumular (ao soltar a tecla continuarão sendo gerados eventos por algum tempo).</p>
<p>Note também que redimensionando a janela ela não é mais redesenhada. Não há mais eventos relacionado a essa ação.</p>
<h2>DoubleBuffer</h2>
<p>Para evitar as piscadas na tela (o efeito chamado de <em>tearing</em> &#8211; rasgo), utilizaremos dois buffers ao invés de um. A lógica é a seguinte: se temos apenas um buffer, ele está sempre sendo mostrado na tela. Quando desenhamos nele, o desenho é feito diretamente nela e podemos ver o desenho sendo contruído e reconstruído repetidamente. Isso causa o efeito indesejado.</p>
<p>Se utilizarmos dois buffers, enquanto um deles é mostrado na tela, desenhamos no outro. Assim, enquanto o desenho está sendo contruído, nós estamos olhando para o desenho anterior, que está estático. Quando o novo desenho está pronto, o método show() do BufferStrategy troca os buffers. Aquele que acabamos de atualizar vai para a tela e o outro passa a ser o de desenho. E ficamos nessa, sempre desenhando no buffer de trás (<em>back buffer</em>) enquanto o outro (<em>front buffer</em> ou buffer primário) fica estático na tela. Como a troca de buffers é muito rápida, centenas de vezes mais rápida do que gerar um desenho na tela, não ocorre nenhum efeito perceptível para o usuário.</p>
<p>Para usar dois buffers, basta mudar o parâmetro do método createBufferStrategy(). Passe o número 2 ao invés de 1 e execute o programa. As piscadas sumirão. Você pode usar mais buffers, mas isso torna o processo mais lento e consome bem mais memória &#8211; veja, cada buffer é uma cópia da tela, seria como ter três telas na memória de vídeo. E memória de vídeo é algo que não podemos desperdiçar. Apenas em casos muito específicos, ou em determinados hardwares, o uso de triplebuffer traz melhorias e pode ser usado. Mais de três buffers, nem pensar &#8211; você pode até passar um número maior, mas provavelmente serão criados apenas 2 ou 3.</p>
<p>Observação: dependendo do seu hardware, a troca de buffers pode ser feita de formas diferentes, o que gera resultados melhores para uns do que para outros. De qualquer forma a diferença deste exemplo para o anterior será gritante.</p>
<h2>Fullscreen e mudança de modo de vídeo</h2>
<p>Que tal rodar o jogo em tela-cheia? Essa é melhor opção porque cria uma imersão muito mais profunda para o usuário, melhorando sua experiência com o jogo. Mas só tela-cheia não basta por causa do tamanho da tela. Se seu jogo foi feito em 800&#215;600 (como é o caso desse exemplo), colocar em tela-cheia vai fazer ele não ocupar toda tela, ficando uma borda preta ao redor. Em um monitor com resolução de 1440, o jogo fica sendo apenas um quadro no meio da tela.</p>
<p>Para usar tela-cheia, o ideal, então, é mudar o modo de vídeo do monitor para ajustar-se à resolução do jogo. Mudando o modo de vídeo para 800&#215;600 o jogo ocupa todo monitor, sem bordas.</p>
<p>Fazer isso é bem fácil. Veja abaixo o método initialize modificado para colocar a janela em tela-cheia e logo após mudar o modo de vídeo para 800&#215;600.</p>
<pre><span class="line-number">28</span>     <span class="keyword-directive">pub</span><span class="keyword-directive">lic</span> <span class="keyword-directive">void</span> initialize()
<span class="line-number">29</span>     {
<span class="line-number">30</span>         createBufferStrategy(1);
<span class="line-number">31</span>         bs = getBufferStrategy();
<span style="color: #ff0000;"><span class="line-number">32</span>         getGraphicsConfiguration().getDevice().
           setFullScreenWindow(<span class="keyword-directive">this</span>);
<span class="line-number">33</span>         getGraphicsConfiguration().getDevice().setDisplayMode(<span class="keyword-directive">
           new</span> DisplayMode(800, 600, 32,
           DisplayMode.REFRESH_RATE_UNKNOWN));</span>
<span class="line-number">34</span>         render();
<span class="line-number">35</span>     }
<span class="line-number"> </span></pre>
<p>Utilizei o método <strong>getGraphicsConfiguration() </strong>herdado da classe JFrame para, através dele, obter acesso ao dispositivo de vídeo (getDevice). A classe GraphicsDevice nos provê um método para entrar em tela-cheia, que é setFullScreenWindow(). Passamos para ele a janela que vai ocupar a tela &#8211; nesse caso, nossa própria classe, que é uma janela. Passando null para esse método saimos da tela-cheia, o que também ocorre, automaticamente, ao fecharmos o programa.</p>
<p>Outro método que temos à disposição é o <strong>setDisplayMode()</strong>. Passamos para ele um objeto do tipo DisplayMode, criado com os dados do modo de vídeo desejado. Os primeiros dois parâmewtros são largura e altura (800&#215;600). Em seguida a profundidade de cor, ou seja, quantos bits por cor. No caso, passei 32 bits &#8211; hoje todos monitores suportam isso. O último parâmetro é a taxa de atualização do monitor (<em>refresh rate</em>). Por exemplo, pode ser 60, 70, 80, etc, onde 60 significa 60Hz e assim por diante. Mas essa taxa não é padronizada e por isso é melhor utilizar a constante <strong>DisplayMode.REFRESH_RATE_UNKNOWN</strong>, que não muda a taxa de atualização do monitor.</p>
<p>Executando o programa assim, ele entra ela tela-cheia. Mas ainda fica com a borda da janela, o que não é desejado nesse caso. Programas em tela-cheia não exibem a borda. Para esconder ela, basta chamar o método <strong>setUndecorated() </strong>passando true. Isso tira a decoração da janela (borda, título, botões). Veja abaixo como chamei esse método no contructor.</p>
<pre>17     public MeuJogo()
18     {
19         setTitle("Atualização Ativa");
20         setSize(800, 600);
<span style="color: #ff0000;">21         setUndecorated(true);</span>
22         setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
23         setIgnoreRepaint(true);
24         addKeyListener(this);
25         tom = 0;
26     }</pre>
<p>Pronto, agora temos um programa que roda em tela-cheia, mudando a resolução do vídeo e sem piscar ao atualizar a tela. Além de termos a garantia de que a tela vai ser atualizada sempre que mandarmos.</p>
<p>Mas para evoluir até um jogo, falta um detalhe importante! Você notou que a coisa só se &#8220;mexe&#8221; quando pressionamos ENTER. Isso porque é dentro do evento do teclado (keyPressed) que modificamos a variável e atualizamos a tela. Um jogo real fica modificando seu estado e atualizando a tela sozinho, sem ninguém pressionar um tecla. Para isso temos que ter um loop em algum lugar &#8211; o fatídico <em>game loop</em>. Assunto para o próximo post.</p>
<p>Até lá, pensem na melhor forma de fazer isso. Que tal fazer esse programa ficar mudando as cores sem estar o ENTER pressionado? Mãos à obra.</p>
<p><a href="http://blog.abrindoojogo.com.br/como-obter-os-codigos-fonte-dos-artigos/">Baixe o código fonte deste artigo.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/passive-vs-active-rendering-%e2%80%93-parte-2-de-2/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Passive VS Active Rendering &#8211; parte 1 de 2</title>
		<link>http://abrindoojogo.com.br/passive-vs-active-rendering-parte-1-de-2</link>
		<comments>http://abrindoojogo.com.br/passive-vs-active-rendering-parte-1-de-2#comments</comments>
		<pubDate>Thu, 17 Sep 2009 02:00:35 +0000</pubDate>
		<dc:creator>Luiz Nörnberg</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Técnico]]></category>

		<guid isPermaLink="false">http://blog.abrindoojogo.com.br/?p=653</guid>
		<description><![CDATA[Existem basicamente duas formas de atualizar a tela quando criamos um programa em Java. Podemos fazer isso de forma passiva ou ativa. Cada uma tem suas vantagens e desvantagens e veremos, nesta dupla de artigos, como implementá-las. Iniciaremos pela atualização passiva (passive rendering). Atualização passiva Esta é forma padrão de atualização de tela para programas [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-687" title="Repaint" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/repaint.png" alt="Repaint" width="200" height="150" />Existem basicamente duas formas de atualizar a tela quando criamos um programa em <strong>Java</strong>. Podemos fazer isso de forma passiva ou ativa. Cada uma tem suas vantagens e desvantagens e veremos, nesta dupla de artigos, como implementá-las. Iniciaremos pela atualização passiva (<em>passive rendering</em>).<span id="more-653"></span></p>
<h2>Atualização passiva</h2>
<p>Esta é forma padrão de atualização de tela para programas em Java, geralmente utilizada por aplicativos. É comum se ouvir falar que esta forma não serve para jogos, mas isto não é inteiramente verdade. Como tudo nessa vida, isso depende.</p>
<p>A atualização passíva consiste em criar uma rotina que é chamada pelo sistema operacional (S.O.) sempre que ele precisar de uma versão atualizada da nossa tela. Em termos técnicos criamos um manipulador de evento (<em>event handler</em>) para o evento Paint.</p>
<p>Veja que é o S.O. que decide quando a atualização é necessária, baseado em dados que ele possui e não baseado em dados do jogo em sí. Esta é sua maior limitação. Por outro lado, é uma forma muito leve em termos de processamento, já que a tela vai ser atualizada apenas quando for necessário e esta é sua vantagem.</p>
<p>Mas baseado em quê o sistema decide se precisa ou não atualizar a tela? Fundamentalmente em mudanças na área da tela como redimensionamento ou ocultamento/reapresentação.</p>
<p>Por exemplo, se nossa tela é uma janela, o sistema vai requerer uma atualização dela sempre que a mesma for redimensionada ou for ocultada e depois mostrada novamente. Nesses eventos é que precisamos desenhar novamente o conteúdo da tela. Veja a ilutração a seguir.</p>
<div id="attachment_703" class="wp-caption aligncenter" style="width: 462px"><a title="Clique para ampliar" href="http://abrindoojogo.com.br/wp-content/uploads/2009/09/interface-021.jpg" target="_blank"><img class="size-full wp-image-703" title="interface 02" src="http://abrindoojogo.com.br/wp-content/uploads/2009/09/interface-021.jpg" alt="interface 02" width="452" height="139" /></a><p class="wp-caption-text">clique para ampliar</p></div>
<p style="text-align: left;">Vejamos como implementar isso em Java, usando uma janela do tipo Swing. Criamos uma classe chamada MeuJogo que é derivada da classe JFrame (um frame &#8211; moldura &#8211; é como chamamos uma janela em Java).</p>
<h3>Arquivo: MeuJogo.java</h3>
<pre><span class="line-number"> 1</span> <span class="keyword-directive">package</span> abrindoojogo.exemplos.atualizacaopassiva;
<span class="line-number"> 2</span>
<span class="line-number"> 3</span> <span class="keyword-directive">import</span> java.awt.Color;
<span class="line-number"> 4</span> <span class="keyword-directive">import</span> java.awt.Graphics;
<span class="line-number"> 5</span> <span class="keyword-directive">import</span> java.awt.event.KeyEvent;
<span class="line-number"> 6</span> <span class="keyword-directive">import</span> java.awt.event.KeyListener;
<span class="line-number"> 7</span> <span class="keyword-directive">import</span> javax.swing.JFrame;
<span class="line-number"> 8</span> <span class="keyword-directive">import</span> javax.swing.WindowConstants;
<span class="line-number"> 9</span>
<span class="line-number">10</span> <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> MeuJogo <span class="keyword-directive">extends</span> JFrame <span class="keyword-directive">implements</span> KeyListener
<span class="line-number">11</span> {
<span class="line-number">12</span>     <span class="keyword-directive">int</span> tom;
<span class="line-number">13</span>
<span class="line-number">14</span>     <span class="keyword-directive">public</span> MeuJogo()
<span class="line-number">15</span>     {
<span class="line-number">16</span>         setTitle(<span class="character">"</span><span class="character">Atualização Passiva</span><span class="character">"</span>);
<span class="line-number">17</span>         setSize(800, 600);
<span class="line-number">18</span>         setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
<span class="line-number">19</span>         addKeyListener(<span class="keyword-directive">this</span>);
<span class="line-number">20</span>         tom = 0;
<span class="line-number">21</span>     }
<span class="line-number">22</span>
<span class="line-number">23</span>     @Override
<span class="line-number">24</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> paint(Graphics g)
<span class="line-number">25</span>     {
<span class="line-number">26</span>         g.clearRect(0, 0, getWidth(), getHeight());
<span class="line-number">27</span>         <span class="keyword-directive">for</span> (<span class="keyword-directive">int</span> x = 0; x &lt; 800; x += 10)
<span class="line-number">28</span>         {
<span class="line-number">29</span>             <span class="keyword-directive">for</span> (<span class="keyword-directive">int</span> y = 0; y &lt; 600; y += 10)
<span class="line-number">30</span>             {
<span class="line-number">31</span>                 g.setColor(<span class="keyword-directive">new</span> Color(x % 256, y % 256, (tom * 50) % 256));
<span class="line-number">32</span>                 g.fillRect(x, y, 10, 10);
<span class="line-number">33</span>             }
<span class="line-number">34</span>         }
<span class="line-number">35</span>     }
<span class="line-number">36</span>
<span class="line-number">37</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> keyPressed(KeyEvent e)
<span class="line-number">38</span>     {
<span class="line-number">39</span>         <span class="keyword-directive">if</span> (e.getKeyCode() == KeyEvent.VK_ENTER)
<span class="line-number">40</span>         {
<span class="line-number">41</span>             tom ++;
<span class="line-number">42</span>         }
<span class="line-number">43</span>     }
<span class="line-number">44</span>
<span class="line-number">45</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> keyReleased(KeyEvent e)
<span class="line-number">46</span>     {
<span class="line-number">47</span>
<span class="line-number">48</span>     }
<span class="line-number">49</span>
<span class="line-number">50</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">void</span> keyTyped(KeyEvent e)
<span class="line-number">51</span>     {
<span class="line-number">52</span>
<span class="line-number">53</span>     }
<span class="line-number">54</span> }</pre>
<p>Abaixo o código da classe principal do programa, onde o processamento inicia. Nela criamos um objeto do tipo da classe MeuJogo e fazemos ele ficar visível. Assim a janela aparece na tela.</p>
<h3>Arquivo: Main.java</h3>
<pre><span class="line-number"> 1</span> <span class="keyword-directive">package</span> abrindoojogo.exemplos.atualizacaopassiva;
<span class="line-number"> 2</span>
<span class="line-number"> 3</span> <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> Main
<span class="line-number"> 4</span> {
<span class="line-number"> 5</span>     <span class="keyword-directive">public</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> main(String[] args)
<span class="line-number"> 6</span>     {
<span class="line-number"> 7</span>         MeuJogo mj = <span class="keyword-directive">new</span> MeuJogo();
<span class="line-number"> 8</span>         mj.setVisible(<span class="keyword-directive">true</span>);
<span class="line-number"> 9</span>     }
<span class="line-number">10</span> }</pre>
<p>Faça o seguinte teste: execute esse exemplo e arraste o canto inferior direito da janela, redimensionando-a. Você vai notar que a imagem pisca: isso é porque está sendo redesenhada a cada alteração de tamanho. Faça isso bem rapidamente e você poderá notar que a imagem deixa de piscar por alguns instantes. Isso ocorre porque o sistema fica sobrecarregado com a mudança de tamanho e, para poupar CPU, deixa de atualziar a imagem, aguardando você parar de mover o mouse para, só então, gerar o evento de redesenho.</p>
<p>Experimente també ficar pressionando a tecla ENTER. Nada ocorre, embora tenhamos um manipulador para o evento KeyPressed que incrementa a variável &#8220;tom&#8221;, que é utilizada para determinar a cor do gráfico. Porque a cor do gráfico não muda?</p>
<p>O que ocorre é que nosso modelo, digamos assim, ou seja, a representação interna do gráfico mudou (a variável foi incrementada), mas como o S.O não sabe disso, ele não enviou o evento para atualziar a tela e por isso a imagem permanece igual. Para contornar isso basta chamar o método repaint() dentro do evento keyPressed. Veja abaixo.</p>
<pre>37     public void keyPressed(KeyEvent e)
38     {
39         if (e.getKeyCode() == KeyEvent.VK_ENTER)
40         {
41             tom ++;
<span style="color: #ff0000;">42             repaint();</span>
43         }
44     }</pre>
<p>Esse método informa ao S.O. que desejamos uma atualização da tela. Rode o programa agora a fique pressionando ENTER. Agora sim, a cor do gráfico muda. Pronto, temos uma máquina simples que serve como base para um jogo de pouca ação. Por exemplo, jogos de tabuleiro como batalha naval.</p>
<p>Porque não serve para jogos de ação intensa e animações constantes? Porque não temos controle sobre quando a tela será atualizada e porque tudo pisca (você notou que o gráfico piscar ao ficar pressionando ENTER?).</p>
<p>Colocar a chamada ao método repaint não faz a tela ser atualizada na hora. Apenas informa ao S.O. que queremos uma atualização, mas o S.O. pode demorar até alguns segundos para atualizar. Se for um jogo de ação, digamos de luta, o modelo interno do jogo vai ser atualizado várias vezes até que a tela seja redesenhada. Ou seja, seu oponente pode lhe dar um chute, você  perder energia e o oponente voltar a posição normal, tudo isso antes da próxima atualização da tela. Quando a tela for redesenhada, você vai ver que sua energia diminuiu, mas não viu o que aconteceu.</p>
<p>E, é claro, tem o problema de piscar. Como estamos atualizando diretamente a tela, ocorre o efeito de <em>tearing</em> (rasgo), onde parece que a imagem fica rasgada. Explicarei porque isso ocorre em um próximo post.</p>
<p>Mas para jogos lentos, quase parando, essa é uma boa opção porque consome muito pouco da CPU. Por exemplo, se for um jogo de damas. Você só precisa chamar o repaint() quando um dos jogadores mover uma peça, o que ocorre com pouca frequência. Não terá o efeito de ficar piscando.</p>
<p>Durante muito tempo isso foi tudo que podia ser feito em Java. Mas já alguns anos que a linguagem permite o que chamamos de <em>active rendering</em>. Esse recurso possibilita atualização instantânea da tela, a cada frame e de quebra nos oferece <em>double buffer</em> (o fim das piscadas), tela-cheia e até mudança de modo de vídeo. Veremos tudo isso amanhã, nesse mesmo site, nesse mesmo horário.</p>
<p><a href="http://blog.abrindoojogo.com.br/como-obter-os-codigos-fonte-dos-artigos/">Baixe o código fonte deste artigo.</a></p>
<address>Ilustrações: Inara Cavichioli</address>
<address><a href="http://blog.abrindoojogo.com.br/passive-vs-active-rendering-%E2%80%93-parte-2-de-2/">Confira a segunda parte&gt;&gt;</a></address>
<address></address>
]]></content:encoded>
			<wfw:commentRss>http://abrindoojogo.com.br/passive-vs-active-rendering-parte-1-de-2/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

