Introducción BFGT

1. Entidades

public class Dot extends Entity

Para poder comenzar a desarrollar un juego es necesario identificar cada uno de los elementos que lo constituyen y hacer que estos extiendan la clase entidad.


public Dot(int x, int y, Bitmap img, GameState game, List<Mask> mask, SpriteMap animations, String soundName, Point soundOffset) {

super(x, y, img, game, mask, animations, soundName, soundOffset, true);

}

 

A la que se le puede especificar desde la posición hasta una fuente de sonido 3D y su desplazamiento con respecto a la posición indicada por parámetro. (Ver API para más información)

 

@Override

public void onUpdate() {

super.onUpdate();

if(Input.getEvent().getX() > x){

                x++;

} else if(Input.getEvent().getX() < x){

                x--;

} else if(Input.getEvent().getY() > y){

                y++;

} else if(Input.getEvent().getY() < y){

                y--;

}

}

               

@Override

public void onDraw(Canvas canvas){

super.onDraw(canvas);

}

 

Los métodos onDraw y onUpdate son los más importantes. En ellos se harán las acciones necesarias para que se realicen dibujos adicionales a los de la imagen estática o animada especificada por parámetro y se actualice la lógica de la entidad respectivamente. En este caso no es necesario pues

 

@Override

public void onCollision(Entity e) {

if (e instanceof Dot && this.x !=0){

this.remove(e);

}

}


Por otro lado, disponemos de otros métodos  adicionales como onCollision, el cual permite definir qué acción realizar en caso de choque con otra entidad dentro de su ámbito de actuación.

 

@Override

public void onTimer(int timer) {

if(timer == 0)

}


También podemos sobrecargar el método onTimer, que permite definir una acción a realizar por la entidad tras un número determinado de pasos del juego. Para ello se activaría el temporizador con Entity.setTimer(int timer, int steps); y después haríamos la distinción de casos en el método mencionado.

 

@Override

public void onSavedInstance(Bundle outState, int i, int j) {

outState.putFloat("dotPosX", SIZE_DP);

outState.putFloat("dotPosY", SIZE_DP);

super.onSavedInstance(outState, i, j);

}

              

@Override

public void onRestoreInstance(Bundle savedInstanceState, int i, int j) {

x = outState.getFloat("dotPosX", 0);

y = outState.getFloat("dotPosY", 0);

super.onRestoreInstance( savedInstanceState , i, j);

}


Finalmente podemos sobrecargar métodos para el guardado y cargado de información de entidades, para salvar el estado de la aplicación en caso de que el sistema decida realizar su liberación por falta de recursos para la ejecución de otras aplicaciones.


2. GameStates


A continuación, debemos identificar los estados del juego o GameStates, es decir los diferentes estados por los que puede pasar nuestra aplicación. Un conjunto de GameStates válido podría ser el siguiente: Pantalla de inicio, introducción del juego, el juego en sí y fin de partida. Si fuera un juego por niveles cada nivel podría modelarse 

como un GameState, en definitiva, cada GameState delimita el ámbito de actuación de las entidades que hemos creado en el paso anterior.

 

public class Gameplay extends GameState {

               

                private Dot myDot;

               

                public Gameplay (View v, TTS textToSpeech, Context c, Game game) {

                               super(v,c,textToSpeech, game);

                               mask = new ArrayList<Mask>();

                               Bitmap myBitmap = BitmapFactory.decodeResource(R.drawable.myDot);

                               SpriteMap animations = new SpriteMap(2, 2, myBitmap, 0);

                               aux = new ArrayList<Integer>();

                               aux.add(0);

                               aux.add(2);

                               myDot = new Dot (0,0,  null, game, mask, animations, R.sound.run ,new Point(0,0));

               

                               this.addEntity(myDot);

                }

                @Override

                public void onInit() {

                               super.onInit();

                }

                @Override

                public void onDraw(Canvas canvas) {

                               // Todo lo que quieras dibujar en el estado del juego

                               super.onDraw(canvas);

                }

                @Override

                public void onUpdate() {

                                // actualizar la lógica del estado del juego

                               super.onUpdate();

          }

}


3. Panel de la actividad


A continuación necesitamos definir la vista que asociaremos a la actividad y sobre la que se realiza todo el renderizado de cada estado.


public class DotPanel extends DrawablePanel {

    private Game game;

    

    private GestureDetector mGestureDetector;

    

    public DotPanel (Game game, Context context) {

            super(context);

            this.game = game;

            mGestureDetector = new GestureDetector(new MyGestureDetector());

    }

    @Override

    public void onInitalize() {

            game.onInit();

    }

    @Override

    public void onDraw(Canvas canvas) {

            super.onDraw(canvas);

            game.onDraw(canvas);

    }

    @Override

    public void onUpdate() {

            game.onUpdate();

            if (game.isEndGame())

                this.getContext().finish();

    }

    @Override

    public boolean onTouchEvent(MotionEvent event) {

            return mGestureDetector.onTouchEvent(event);

    }

}


4. Crear el juego 


Para finalizar se instancia el juego, especificando los estados de los que se compone y su orden relativo, dentro del método onCreate de una actividad cualquiera en la aplicación Android.


public class DotActivity extends Activity {

                private TTS textToSpeech;

                private Game game;

                

                @Override

                public void onCreate(Bundle savedInstanceState) {

                    super.onCreate(savedInstanceState); 


                    textToSpeech = (TTS) getIntent().getParcelableExtra(MainActivity.KEY_TTS);

                    textToSpeech.setContext(this);


                    createGame(view);

                }


Se instancia la vista especificada previamente, se especifica al motor de síntesis de voz el contexto en el que actúa y una vez hecho esto instanciamos la vista y el juego en sí.


                private void createGame(DrawablePanel zarodnikView) {

                    ArrayList<Integer> order;

                    ArrayList<GameState> gameStates;

                    DrawablePanel  view = new DotGamePanel(this);

                    setContentView(view);


                    order = new ArrayList<Integer>();

                    order.add(0);


                    gameStates = new ArrayList<GameState>();

                    gameStates.add(new Gameplay(v, textToSpeech, this, game));

                    game = new Game();

                    game.initialize(gameStates, order);

                }


Cada entero en orden, es la posición que ocupa dentro del vector de estados el estado que se desea que se ejecute y la posición de ese entero fija el orden de ejecución:

     Order = [0,2,1]

     GameStates = [Inicio,Fin,Gameplay]


Ejecuta Inicio, tras finalizar este realiza Gameplay y en último lugar Fin.


                   @Override

                protected void onDestroy() {

                     super.onDestroy();

                     textToSpeech.stop();

                     Sound3DManager.getSoundManager(this).stopAllSources();

                }


 Si se desea preservar el estado además será necesario implementar lo siguiente en el método onSaveInstanceState de Activity:


                      @Override

                protected void onSaveInstanceState(Bundle outState) {

                     game.onSaveInstance(outState);

                     super.onSaveInstanceState(outState);

                }