  <?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/"
	>

<channel>
	<title>Athanazio &#187; android</title>
	<atom:link href="http://www.athanazio.com/category/android/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.athanazio.com</link>
	<description>Nada é Simples, Mas Tudo é Possível</description>
	<lastBuildDate>Thu, 01 Dec 2011 03:47:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>e a corrida pelo android começou</title>
		<link>http://www.athanazio.com/2011/03/21/e-a-corrida-pelo-android-comecou/</link>
		<comments>http://www.athanazio.com/2011/03/21/e-a-corrida-pelo-android-comecou/#comments</comments>
		<pubDate>Mon, 21 Mar 2011 11:30:40 +0000</pubDate>
		<dc:creator>athanazio</dc:creator>
				<category><![CDATA[android]]></category>
		<category><![CDATA[soluções]]></category>

		<guid isPermaLink="false">http://www.athanazio.com/?p=2829</guid>
		<description><![CDATA[os desenvolvedores já começaram a sua corrida para desenvolver soluções para o Android, uma tal de vaca vitória software já apresenta algumas soluções &#8230; www.vacavitoria.com/android]]></description>
			<content:encoded><![CDATA[<div id="HOTWordsTxt" name="HOTWordsTxt"><p><img src="http://www.vacavitoria.com/wp-content/uploads/2011/03/aqui_o_android_tambem_pasta.png" alt="android bovino" /><br />
os desenvolvedores já começaram a sua corrida para desenvolver soluções para o Android,<br />
uma tal de <a href="http://www.vacavitoria.com">vaca vitória software</a> já apresenta algumas soluções &#8230;<br />
<a href="http://www.vacavitoria.com/android/">www.vacavitoria.com/android</a></p>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.athanazio.com/2011/03/21/e-a-corrida-pelo-android-comecou/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>android game &#8211; imagem e som</title>
		<link>http://www.athanazio.com/2009/11/21/android-game-imagem-e-som/</link>
		<comments>http://www.athanazio.com/2009/11/21/android-game-imagem-e-som/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 20:17:03 +0000</pubDate>
		<dc:creator>athanazio</dc:creator>
				<category><![CDATA[android]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[programacao]]></category>
		<category><![CDATA[.ogg]]></category>
		<category><![CDATA[.png]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[effect]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[soundtrack]]></category>
		<category><![CDATA[sprite]]></category>

		<guid isPermaLink="false">http://www.athanazio.com/?p=2315</guid>
		<description><![CDATA[Opa ! apos algumas idas e vindas no codigo, as coisas começam a se arrumar hehehehe, nesta versão já esta resolvida a exibição de imagem a partir do nome da imagem, e execução de som no formato ogg, tanto no loop como um som a partir de um evento do usuário. Apesar da recomendação do [...]]]></description>
			<content:encoded><![CDATA[<div id="HOTWordsTxt" name="HOTWordsTxt"><p><a href="http://www.athanazio.com/wp-content/uploads/2009/11/android-show-image.png"><img src="http://www.athanazio.com/wp-content/uploads/2009/11/android-show-image-450x300.png" alt="android show image" title="android show image" width="450" height="300" class="alignnone size-medium wp-image-2316" /></a><br />
Opa ! apos algumas idas e vindas no codigo, as coisas começam a se arrumar hehehehe, nesta versão já esta resolvida a exibição de imagem a partir do nome da imagem, e execução de som no formato ogg, tanto no loop como um som a partir de um evento do usuário.</p>
<p>Apesar da recomendação do SDK seja de acessar os arquivos de midia através do resource ID criado na classe R, eu estou construindo as classes usando o nome do resource para poder expandir a programação do jogo para uma lingaguem de script, e usar o java como uma camada de abstração do jogo.</p>
<p>Vamos ao codigo e alguns comentarios sobre cada um :</p>
<p><strong>GameActivity </strong>- ganhou uma nova chamada para determinar que volume o jogo vai usar, setVolumeControlStream(AudioManager.STREAM_MUSIC) assim o jogo fica com o mesmo volume que estiver acertado para a musica, alem disto o metodo onDestroy() chama o novo metodo release() da view que vai se encarregar de liberar recursos e em especial mandar os audios se calarem <img src='http://www.athanazio.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre class="brush: java; title: ; notranslate">
package com.athanazio.android.showimage;

import android.app.Activity;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.Window;

public class GameActivity extends Activity {
	private GameView view;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setVolumeControlStream(AudioManager.STREAM_MUSIC);

		view = new GameView(this, getResources());
		setContentView(view);
	}

	protected void onDestroy() {
		super.onDestroy();
		view.release();
	}

}
</pre>
<p><strong>GameView</strong> &#8211; usa as classes Sprite e Audio para exibir imagens e tocar audio, poucas mudanças comparando com a versão anterior.</p>
<pre class="brush: java; title: ; notranslate">
package com.athanazio.android.showimage;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

public class GameView extends View implements Runnable {

	private static final String TAG = &quot;GAME VIEW&quot;;

	private static final int INTERVAL = 10;
	private Paint cPaint;

	private boolean running = true;

	FPSCounter fps;

	private Sprite background;
	private Sprite cloud;

	private Audio soundtrack;
	private Audio touch;

	public GameView(Context context, Resources resources) {
		super(context);

		String packageName = getClass().getPackage().getName();

		background = new Sprite(resources, packageName, &quot;background&quot;);
		cloud = new Sprite(resources, packageName, &quot;cloud&quot;);
		cloud.setCenterAtMiddle();

		soundtrack = new Audio(resources, packageName, &quot;soundtrack&quot;);
		touch = new Audio(resources, packageName, &quot;cowbell&quot;);

		soundtrack.setLooping(true);
		soundtrack.play();

		cPaint = new Paint();
		setFocusable(true);
		setClickable(true);
		setLongClickable(true);

		fps = new FPSCounter();

		// Set the background
		this.setBackgroundColor(Color.WHITE);
		Log.i(TAG, &quot;game view created&quot;);

		Thread monitorThread = new Thread(this);
		monitorThread.setPriority(Thread.MIN_PRIORITY);
		monitorThread.start();
	}

	public void draw(Canvas canvas) {
		super.draw(canvas);

		background.draw(canvas);
		cloud.draw(canvas);

		cPaint.setColor(Color.WHITE);
		canvas.drawText(fps.getFPS(), 20, 20, cPaint);
	}

	public boolean onKeyUp(int keyCode, KeyEvent event) {
		return super.onKeyUp(keyCode, event);
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {
		boolean handled = false;
		Log.i(TAG, &quot;key down&quot;);
		float x = cloud.getX();
		float y = cloud.getY();

		if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
			y = y - 5;
			handled = true;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
			y = y + 5;
			handled = true;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
			x = x - 5;
			handled = true;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
			x = x + 5;
			handled = true;
		}

		cloud.move(x, y);
		return handled;
	}

	public boolean onTouchEvent(MotionEvent event) {
		cloud.setX(event.getRawX());
		cloud.setY(event.getRawY());
		Log.i(TAG, &quot;on touch&quot;);

		touch.play();
		return super.onTouchEvent(event);
	}

	public void run() {
		while (running) {
			try {
				Thread.sleep(INTERVAL);
			} catch (InterruptedException e) {
				Log.e(TAG, &quot;main loop finished&quot;);
			}
			update();
			postInvalidate();
		}
	}

	private void update() {
		fps.update();

	}

	public void release() {
		running = false;
		soundtrack.release();
		touch.release();
	}

}
</pre>
<p><strong>Sprite</strong> &#8211; esta eh responsavel por exibir imagens na tela, uma atenção especial deve ser dada ao recurso de determinar o centro da imagem, isto eh muito util para responder eventos de mouse, e por exemplo posicionar a imagem centralizada onde o usuário clicou, o método setCenterAtMiddle() calcula a posição para desenhar baseado na largura e altura da imagem. e por default o centro da imagem eh no 0,0.</p>
<pre class="brush: java; title: ; notranslate">
package com.athanazio.android.showimage;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;

public class Sprite {

	private static final String TAG = &quot;GAME SPRITE&quot;;
	private Bitmap bitmap;
	private float x;
	private float y;
	private float centerX;
	private float centerY;
	private float drawX;
	private float drawY;
	private Paint paint;

	public Sprite(Resources resources, String packageName, String name) {
		String logFileName = packageName + &quot; &quot; + name;
		Log.i(TAG, &quot;loading image : &quot; + logFileName);

		int id = resources.getIdentifier(name, &quot;drawable&quot;, packageName);
		bitmap = BitmapFactory.decodeResource(resources, id);
		centerX = 0;
		centerY = 0;

		setX(0);
		setY(0);

		this.paint = new Paint();
	}

	public void draw(Canvas canvas) {
		canvas.drawBitmap(bitmap, drawX, drawY, paint);
	}

	public void move(float x, float y) {
		setX(this.x + x);
		setY(this.y + y);
	}

	public void setCenterAtMiddle(){
		centerX = bitmap.getWidth() / 2F;
		centerY = bitmap.getHeight() / 2F;
	}

	public float getX() {
		return x;
	}

	public void setX(float x) {
		this.x = x;
		drawX = this.x - centerX;
	}

	public float getY() {
		return y;
	}

	public void setY(float y) {
		this.y = y;
		drawY = this.y - centerY;
	}

}
</pre>
<p><strong>Audio</strong> &#8211; esta classe esconde a criação de um MediaPlayer para cada som que se deseja tocar, imagino que o melhor cenário seria ter uma classe para som em loop que usaria um MediaPlayer, e outra classe para efeitos sonoros que tocaria no maximo N efeitos ao mesmo tempo, mantendo menos objetos MediaPlayer na memória.</p>
<p>Mas a implementação atual mantém um MediaPlayer para cada som, observar que o resource ID é recuperado pelo nome do arquivo usando o metodo resources.getIdentifier(name, &#8220;raw&#8221;, packageName) e a partir do resource ID podemos recuperar o AssetFileDescriptor com a chamada resources.openRawResourceFd(id), of file descriptor é usado para inicializar o MediaPlayer com os detalhes necessários a execução do som.</p>
<pre class="brush: java; title: ; notranslate">
package com.athanazio.android.showimage;

import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaPlayer;
import android.util.Log;

/**
 * Audio resources abstraction
 *
 * @author athanazio
 * @see &quot;http://developer.android.com/intl/fr/guide/topics/media/index.html&quot;
 * @see &quot;http://developer.android.com/intl/fr/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States&quot;
 */
public class Audio {

	private static final String TAG = &quot;GAME AUDIO&quot;;
	private MediaPlayer player;
	private boolean ready;
	private int id;
	private AssetFileDescriptor afd;

	/**
	 *
	 * @param resources
	 * @param context
	 * @param packageName
	 * @param name
	 *
	 */
	public Audio(Resources resources, String packageName, String name) {
		String logFileName = packageName + &quot; &quot; + name;
		Log.i(TAG, &quot;loading audio : &quot; + logFileName);

		ready = false;
		player = new MediaPlayer();

		try {
			this.id = resources.getIdentifier(name, &quot;raw&quot;, packageName);
			this.afd = resources.openRawResourceFd(id);

			Log.i(TAG, &quot;loading audio : &quot; + logFileName + &quot; id:&quot; + id);

			player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
			player.setLooping(false);
			player.prepare();

			// reset the player after completion
			player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
				public void onCompletion(MediaPlayer mp) {
					try {
						player.reset();
						player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
						player.prepare();
					} catch (Exception e) {
						Log.e(TAG, &quot;error resetting the media player&quot;);
						e.printStackTrace();
					}
				}
			});

			ready = true;

		} catch (Exception e) {
			Log.e(TAG, &quot;ERROR loading audio : &quot; + logFileName);
			e.printStackTrace();
		}
	}

	public void play() {
		if (ready) {
			player.start();
		} else {
			Log.i(TAG, &quot;the player is not ready.&quot;);
		}
	}

	public void setLooping(boolean b) {
		player.setLooping(b);
	}

	public void release() {
		player.stop();
		player.release();
	}

}
</pre>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.athanazio.com/2009/11/21/android-game-imagem-e-som/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>android &#8211; mover bolinha</title>
		<link>http://www.athanazio.com/2009/11/21/android-mover-bolinha/</link>
		<comments>http://www.athanazio.com/2009/11/21/android-mover-bolinha/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 14:14:00 +0000</pubDate>
		<dc:creator>athanazio</dc:creator>
				<category><![CDATA[android]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[programacao]]></category>
		<category><![CDATA[90 fps]]></category>
		<category><![CDATA[direction]]></category>
		<category><![CDATA[fps]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[main loop]]></category>
		<category><![CDATA[touch screen]]></category>

		<guid isPermaLink="false">http://www.athanazio.com/?p=2310</guid>
		<description><![CDATA[Na minha opinão o hello world para desenvolver jogos eh mover um desenho primitivo na tela junto com a informação de FPS (frames por segundo) até porque logo logo perguntamos : tah rodando a quantos FPS ? assim sendo já posso dizer que fiz o meu hello world para o android. Alguns links que ajudaram [...]]]></description>
			<content:encoded><![CDATA[<div id="HOTWordsTxt" name="HOTWordsTxt"><p><a href="http://www.athanazio.com/wp-content/uploads/2009/11/android-move-ball.png"><img class="alignnone size-medium wp-image-2311" title="android move ball" src="http://www.athanazio.com/wp-content/uploads/2009/11/android-move-ball-450x300.png" alt="android move ball" width="450" height="300" /></a></p>
<p>Na minha opinão o hello world para desenvolver jogos eh mover um desenho primitivo na tela junto com a informação de FPS (frames por segundo) até porque logo logo perguntamos : tah rodando a quantos FPS ? <img src='http://www.athanazio.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  assim sendo já posso dizer que fiz o meu hello world para o android.</p>
<p>Alguns links que ajudaram bastante foram estes :</p>
<p>Uma apresentação da google sobre o desenvolvimento para de jogos para o Android<br />
<a href="http://www.scribd.com/doc/16917369/Writing-Real-Time-Games-for-Android">Writing-Real-Time-Games-for-Android</a></p>
<p>Os exemplos de cógigo citados na apresentação<br />
<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/CLiCkin2DaBeaT/src/com/google/clickin2dabeat/C2B.java">C2B </a>2 <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/CLiCkin2DaBeaT/src/com/google/clickin2dabeat/GameView.java">GameView</a></p>
<p>Com certeza este exemplo que escrevi eh extremamente simples, mas exemplifica alguns elementos básicos :</p>
<ul>
<li>main loop</li>
<li>chamada de update</li>
<li>atualização da area de vizualização</li>
<li>input do usuário</li>
</ul>
<p>O ambiente que tenho eh o Eclipse com o plugin para desenvolvimento do android instalado, para os testes eu prefiro usar o telefone porque o emulador demora muito para inicializar <img src='http://www.athanazio.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  e este exemplo tem basicamento 3 classes :</p>
<p><strong>GameActivity</strong> &#8211; que eh a entrada da aplicação, nela eu solicito o uso fullscreen para o jogo, e determino que a visualização será realizada por uma instancia da classe GameView.</p>
<pre class="brush: java; title: ; notranslate">
package com.athanazio.android.moveball2;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;

public class GameActivity extends Activity {
	private GameView view;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);

		view = new GameView(this);
		setContentView(view);
	}

	protected void onPause() {
		super.onPause();
		view.pause();
	}
}
</pre>
<p><strong>GameView</strong> &#8211; nesta classe reside o loop principal do jogo que é iniciado no final do construtor, note que na verdade eh criado um Thread com baixa prioridade, que passará a realizar as atividades de atualização e principalmente executar o método postupdate() notficando a interface que pode ser exibida.</p>
<p>além do loop principal o input direcional é tratado pelo método onKeyDown() e o tocar na tela pelo método onTouchEvent()</p>
<pre class="brush: java; title: ; notranslate">
package com.athanazio.android.moveball2;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

public class GameView extends View implements Runnable {

	private static final String TAG = &quot;GAMEVIEW&quot;;

	private static final int INTERVAL = 10;
	private Paint cPaint;

	private float x = 50;

	private float y = 50;

	private boolean running = true;

	FPSCounter fps;

	public GameView(Context context) {
		super(context);
		cPaint = new Paint();
		setFocusable(true);
		setClickable(true);
		setLongClickable(true);

		fps = new FPSCounter();

		// Set the background
		this.setBackgroundColor(Color.WHITE);
		Log.i(TAG, &quot;game view created&quot;);

		Thread monitorThread = new Thread(this);
		monitorThread.setPriority(Thread.MIN_PRIORITY);
		monitorThread.start();
	}

	public boolean onKeyUp(int keyCode, KeyEvent event) {
		return super.onKeyUp(keyCode, event);
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {
		boolean handled = false;
		Log.i(TAG, &quot;key down&quot;);

		if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
			y = y - 5;
			handled = true;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
			y = y + 5;
			handled = true;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
			x = x - 5;
			handled = true;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
			x = x + 5;
			handled = true;
		}
		return handled;
	}

	public boolean onTouchEvent(MotionEvent event) {
		x = event.getRawX();
		y = event.getRawY();
		Log.i(TAG, &quot;on touch&quot;);

		return super.onTouchEvent(event);
	}

	public void draw(Canvas canvas) {
		super.draw(canvas);

		cPaint.setColor(Color.BLUE);
		canvas.drawCircle(x, y, 15, cPaint);

		cPaint.setColor(Color.BLACK);
		canvas.drawText(fps.getFPS(), 20, 20, cPaint);

	}

	public void run() {
		while (running) {
			try {
				Thread.sleep(INTERVAL);
			} catch (InterruptedException e) {
				Log.e(TAG, &quot;main loop finished&quot;);
			}
			update();
			postInvalidate();
		}
	}

	private void update() {
		fps.update();

	}

	public void pause() {
		running = false;
	}

}
</pre>
<p><strong>FPSCounter</strong> &#8211; nesta classe é feita uma contagem de frames que o jogo consegue exibir por segundo, vi algumas implementações interessantes disto, mas acabei fazendo o mais simples e mais econômico, contar frames e ver se jah passou o tempo <img src='http://www.athanazio.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  note que algumas variáveis eu criei fora dos métodos para evitar que o Garbage collector tivesse que trabalhar, querendo ou não isto economiza alguns milisegundos <img src='http://www.athanazio.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre class="brush: java; title: ; notranslate">
package com.athanazio.android.moveball2;

import java.text.DecimalFormat;

import android.os.SystemClock;

public class FPSCounter {

	public static final DecimalFormat format = new DecimalFormat(&quot;###0.00&quot;);

	private float frames;
	private String fps;
	private long start;
	private long current;

	public FPSCounter() {
		start = SystemClock.uptimeMillis();
		frames = 0;
		fps = &quot;???&quot;;
	}

	public void update() {
		frames ++;
		current = SystemClock.uptimeMillis();
		if( current - start &gt; 1000 ){
			fps = format.format(frames);
			frames = 0;
			start = current;
		}
	}

	public String getFPS() {
		return fps;
	}
}
</pre>
<p>a propósito o fps esta em torno de 90 e poucos, vamos ver o que acontece quando tiver de desenhar uma imagem no fundo e varias outras na tela hehehehe.</p>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.athanazio.com/2009/11/21/android-mover-bolinha/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

