Posts Tagged ‘game’

android game – imagem e som

November 21st, 2009

android show image
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 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.

Vamos ao codigo e alguns comentarios sobre cada um :

GameActivity - 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 :)

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();
	}

}

GameView – usa as classes Sprite e Audio para exibir imagens e tocar audio, poucas mudanças comparando com a versão anterior.

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 = "GAME VIEW";

	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, "background");
		cloud = new Sprite(resources, packageName, "cloud");
		cloud.setCenterAtMiddle();

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

		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, "game view created");

		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, "key down");
		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, "on touch");

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

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

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

	}

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

}

Sprite – 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.

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 = "GAME SPRITE";
	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 + " " + name;
		Log.i(TAG, "loading image : " + logFileName);

		int id = resources.getIdentifier(name, "drawable", 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;
	}

}

Audio – 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.

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, “raw”, 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.

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 "http://developer.android.com/intl/fr/guide/topics/media/index.html"
 * @see "http://developer.android.com/intl/fr/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States"
 */
public class Audio {

	private static final String TAG = "GAME AUDIO";
	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 + " " + name;
		Log.i(TAG, "loading audio : " + logFileName);

		ready = false;
		player = new MediaPlayer();

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

			Log.i(TAG, "loading audio : " + logFileName + " id:" + 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, "error resetting the media player");
						e.printStackTrace();
					}
				}
			});

			ready = true;

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

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

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

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

}

batalha de tanques

September 29th, 2009

battle tank
simples e objetivo ! bum bum bum explode tanques :)
www.permadi.com/java/battletank/index.html

vacas lutadoras

September 28th, 2009

riogdug vacaslutadoras screen2

Neste jogo de combate todas as suas habilidades de lutador serao exigidas, encontre seu adversario sente do ladinho no teclado e coloque as vacas para brigar !!

Este jogo foi feito em Love2D e enviado para a competicao de 48h #1 do RioGDUG

riogdug48h_1_vacas_lutadores

sera necessario instalar o love2d para jogar

my brute

June 9th, 2009

my-brute
que jogo bunitinho :P os bonequinhos saem no tapa, e vc não interage soh assiste, e aleatoriamente a pancadaria rola hehehehe olha lah o meu bruto !
http://foo.bar2.mybrute.com

resultados da competicao LD14

May 7th, 2009

Olas saiu o resultado final do LD14 !
http://www.ludumdare.com/compo/category/ld14/?tag=final+final&mythumb_nav=1

nada mal meu resultado para primeira vez hehehe

Critério Classificação (1-123) Nota Média (0-5)
Audio 31 3.33
Humor 55 2.82
Technical 73 2.87
Overall 91 2.81
Fun 99 2.38
Innovation 85 2.81
Theme 118 1.75
Polish 68 3.0
Graphics 15 4.06

game design tour

May 5th, 2009

show de bola os comentarios deste site sobre design de games, vale conferir
http://blog.wolfire.com/category/design-tour/

diodontidae – jogo novo

April 20th, 2009

Neste fim de semana participei de outra competicao de jogos, mais uma maratona de 48 horas !! veja o listao da competicao ! www.ludumdare.com

Eu fiz um jogo onde vc controla um diodontidae,
que é um baiacú e vc come o lixo do fundo do mar e joga latinhas nos porcos que sujam o mar. aqui esta o link para baixar o jogo : http://www.vacavitoria.com/jogos/diodontidae-necandi/

diodontidae-necandi_tela

se vc tiver o LOVE instalado basta executar o arquivo .love diodontidae_necandi_v1

LOVE games – belly

April 16th, 2009

Olas ! estou estudando uma nova game engine que se chama LOVE

separei um jogo em divertido que baixei do forum, que vc compoe uma musica eletronica a medida que clica nas coisas na tela, muito show !!

belly-game

instale o player do game engine e clique ae em baixo para jogar

clique aqui para jogar belly-05-mod

faça um wiimote em casa

March 29th, 2009

wiimotepattern
ingredientes:

  • impressora
  • tinta
  • papel
  • tesoura
  • cola

modo de fazer:

  • imprima o modelo
  • corte
  • monte
  • cole

facinho né ?

fonte : pumpkin petunia

javafx os cabecudinhos preview 2009-03-18

March 19th, 2009

mosquito-killers

Temos grandes novidades neste preview:

  • Uma interface para entrar com nome dos usuarios que estão jogando
  • a tela de como jogar
  • o envio da pontuação para o servidor

Ufa … os novos graficos ainda nao estao lah, mas estao no forno !!

este eh o link para os arquivos do preview
http://svn.vacavitoria.com/cabecudinhos_1/cabecudinhos_1/preview/2009-03-18/

e este eh o video

javafx cabecudinhos preview 2009-03-15

March 16th, 2009

cabecudinhos-preview-2009-03-15
Olas ! estamos quase terminando o jogo dos cabecudinhos, episodio I o ataque dos mosquitos ! as partes graficas estao saindo do forno, valeu Mariana !! as coisas estao se encaixando, e em breve vai rolar o envio de pontuacao para o servidor.

Coisas novas bem legais estao neste preview :

  • feedback do tempo para a criacao do novo mosquito e tempo que o item vai ficar sem gerar mosquito
  • efeito quando os personagens sao atingidos pelo mosquito
  • contagem dos pontos

baixe o arquivo de webstart da implementacao atual
cabecudinhos_episodio_um.jnlp

curta o video do preview

e aproveite a moleza do codigo fonte disponivel no subversion :P

javafx beta 2009-03-08 dos cabecudinhos

March 8th, 2009

Opa esta eh uma versao parcial do jogo dos cabecudinhos !!

executar

para os catucadores de plantão, aqui ficam os arquivos desta versão
http://www.vacavitoria.com/preview/cabecudinhos_1/2009-03-08/

javafx personagem que salta nas plataformas

March 8th, 2009

Uia ! implementei meus rabiscos de gravidade e não eh q funcionou !! hehehe

como tinha dito em javafx-planejando-gravidade são 3 classes envolvidas:

  • GravityManager – fazo update() a cada tick do jogo
  • Force – aplica mudança de posição aos nodes
  • GNode – associa Node a Force.

Para os catucadores de plantão segue o endereço do subversion
http://svn.vacavitoria.com/cabecudinhos_1/cabecudinhos_1/

E alguns fragmentos do codigo
esta eh a Scene em que usei a GravityManager

public class GameScene extends Scene, Updatable{
    ...
    public var gravityManager: GravityManager;

    // set the need info for the Scene work
    public function setup(){
        gameSoundtrack.play();

        background =
        lookup(BACKGROUND_ID) as NodeFromFXZ;
        player1 =
        lookup(PLAYER1_ID) as MovableChar;
        player1.background = background;
        player1.requestFocus();

        gravityManager = GravityManager{
            gravity: 5
            content: [
                GNode{
                    node: bind player1
                }
            ]
        }

    }

    public override function update(){
        gravityManager.update();
    }

    override var content = [
        NodeFromFXZ{
            id: bind BACKGROUND_ID
            source: "{__DIR__}media/background.fxz"
        }

        MovableChar{
            id : bind PLAYER1_ID
            source: "{__DIR__}media/boy.fxz"
            x: 50
            y: 450
            speed: 3
            colision: ["casa1", "casa2", "casa3","casa4", "casa5", "casa6", "casa7", "casa8",
             "caixa1", "caixa2", "caixa3","caixa4", "caixa5", "caixa6",
            "caixa7", "caixa7b", "caixa8", "caixa8b",
            "left", "right", "bottom","top", "plataforma1"]

            onMouseClicked: function(e){
            }

            onKeyReleasedDelegate: function(current:MovableChar, key: KeyCode){
               if( key == KeyCode.VK_SPACE and current.hasColision){
                   fire.play();
                   gravityManager.addForce( current.id, Force {
                        y: -22;
                   });
                }
            }

            onUpdate: function(current:MovableChar){
                current.checkIfScrollBackground();

            }
        }
    ]
}

Segue o codigo das classes para o controle da gravidade

GravityManager

public class GravityManager extends Updatable{

    public var gravity: Integer;
    public var content: GNode[];

    public function addForce(id:String, force: Force){
        for( gNode in content){
            if( gNode.node.id.equals(id) )  {
                insert force into gNode.forces;
            }
        }
    }

    public override function update(){

        // iterate over all gnodes
        for( gNode in content){
            var x: Integer = 0;
            var y: Integer = gravity;

            // iterate over all Force from the GNode
            for( force in gNode.forces){
                x = x + force.x as Integer;
                y = y + force.y as Integer;

                force.applyGravity(gravity);
                if( force.isDisposable()){
                    delete force from gNode.forces;
                }
            }

            // try to move the Node with the increase of x and y
            gNode.node.moveX(x);
            gNode.node.moveY(y);
        }
    }
}

Force.fx

public class Force {

    public var x: Number;
    public var y: Number;
    public var percentGravity: Number = 0.15;

    // reduce the x and y value with the gravity
    public function applyGravity(gravity:Integer){
        if( x < 0 ){
            x = x + (gravity * percentGravity);

            if( x > 0 ){
                x = 0;
            }
        }

        if( y < 0 ){
            y = y + (gravity * percentGravity);
            if( y > 0 ){
                y = 0;
            }
        }
    }

    public function isDisposable():Boolean{
        return x == 0 and y == 0;
    }

}

GNode

public class GNode {

    public var node: MovableChar;
    public var forces: Force[];

}

E finalmente o video com o resultado saltitante :)

javafx quadrado na tela v2

February 15th, 2009

Esta e a segunda versão do quadrado na tela, agora com o efeito de manter a tecla pressionada e o movimento acontecer ! para isto acabei definindo uma classe Game que fica com loop principal e todos os Nodes da Scene atual são verificados para execução de um método update(), não sei ainda se dava para fazer com alguma estrutura do próprio JavaFx, mas assim funcionou.

Olha como ficou o movimento

esta é a classe Game, que cria um Timer que executa continuamente, e chama o método update() para todos os Nodes que sao filhos da classe Updatable, no método update() o nosso quadrado muda a sua posicao de acordo com as teclas que estão pressionadas

package javafxmeuquadradinho2;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 * @author athanazio
 */
public class Game extends Stage {

    public var tick: Timeline = Timeline {
        repeatCount: Timeline.INDEFINITE
        keyFrames: [
            KeyFrame {
                time: 0.05s
                action: function() {
                    mainLoop();
                }
        }]
    };

    // main game loop
    public function mainLoop(){
        for (node in scene.content) {
            if( node instanceof Updatable){
                (node as Updatable).update();
            }
        }
    }

    public function play(){
        tick.play();
    }

}

A classe KeyState é usada para manter as informações de que teclas estão pressionadas ou não, Esta solução não permite uma fácil expansão para suportar outras teclas, outra forma seria armazenar uma lista das teclas atualmente pressionadas, e possuir um método para verificar se a tecla X esta pressionada.

package javafxmeuquadradinho2;

/**
 * @author athanazio
 */
public class KeyState {
    public var keyUp = false;
    public var keyLeft = false;
    public var keyRight = false;
    public var keyDown = false;
}

A classe Updatable define o metodo update() a ser executado no loop principal do jogo.

package javafxmeuquadradinho2;

/**
 * @author athanazio
 */
public class Updatable{
    public function update(){

    }
}

A classe MovableChar cria neste exemplo um Retangulo associado com as propriedades da classe, e gera os event handlers baseados neste retangulo, melhor seria usar um ImageView para exibir uma imagem, mas isto jah é outra estória … além disto mantém controle da tecla pressionada, através de uma instância de KeyState, e quando a tecla é liberada desmarca, fazendo com q no próximo update() o movimento naquela direção não ocorra.


/*
 * MovableChar.fx
 *
 * Created on Feb 15, 2009, 3:47:31 PM
 */

package javafxmeuquadradinho2;

import javafx.scene.CustomNode;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;

/**
 * @author athanazio
 */
public class MovableChar extends CustomNode, Updatable{
    public var speed = 10;
    public var x = 0;
    public var y = 0;
    public var width = 60;
    public var height = 60;
    public var fill: Color;

    var keyState: KeyState = KeyState{
        keyUp: false;
        keyLeft: false;
        keyRight: false;
        keyDown: false;
     };

    public override function create():Node {
        return Rectangle {
            x: bind this.x;
            y: bind this.y;
            width: bind this.width;
            height: bind this.height;
            fill: bind this.fill;

            onKeyPressed: function (e: KeyEvent){
                if( e.code == KeyCode.VK_LEFT ){
                    keyState.keyLeft = true;
                }
                if( e.code == KeyCode.VK_RIGHT ){
                    keyState.keyRight = true;
                }
                if( e.code == KeyCode.VK_UP ){
                    keyState.keyUp = true;
                }
                if( e.code == KeyCode.VK_DOWN ){
                    keyState.keyDown = true;
                }
            }
            onKeyReleased: function(e: KeyEvent){
                if( e.code == KeyCode.VK_LEFT ){
                    keyState.keyLeft = false;
                }
                if( e.code == KeyCode.VK_RIGHT ){
                    keyState.keyRight = false;
                }
                if( e.code == KeyCode.VK_UP ){
                    keyState.keyUp = false;
                }
                if( e.code == KeyCode.VK_DOWN ){
                    keyState.keyDown = false;
                }
            }
        };
    }

    public override function update(){

        if( keyState.keyLeft){
            x = x - speed;
        }

        if( keyState.keyRight){
            x = x + speed;
        }

        if( keyState.keyDown){
            y = y + speed;
        }

        if( keyState.keyUp){
            y = y - speed;
        }
    }

}

E finalmente a classe Main que instancia MovableChar e Game e chama o método start de Game.

package javafxmeuquadradinho2;

import java.lang.Object;
import javafx.scene.paint.Color;
import javafx.scene.Scene;

/**
 * @author athanazio
 */
var littleBox: MovableChar = MovableChar{
    x: 20,
    y: 20
    width: 60,
    height: 60
    fill: Color.RED
}

var game: Game = Game {
        title: "Movendo um quadrado pela tela"
        width: 640
        height: 480
        scene: Scene {
            content: [
                littleBox
            ]
        }
    }

function run(__ARGS__ : String[]) {
    game.play();
}