Get the Flash Player to see this player.

time2online Joomla Extensions: Simple Video Flash Player Module
Pierwsza gra z Akcelerometrem

Wszystkie przedstawione wcześniej artykuły miały na celu zbudowanie własnej aplikacji w której wykorzystamy jakiś z czujników. W naszym przypadku wykorzystamy akcelerometr, który opisałem we wcześniejszych artykułach. Oczywiście w tym artykule nie mam zamiaru krok po kroku omawiać całej aplikacji, ale za to udostępnię cały kod i opiszę ogólny sposób działania.

Aplikacja jest bardzo prosta. Na ekranie jest mucha, którą sterujemy akcelerometrem. Czyli jak nachylimy komórkę w prawo, to mucha przesunie się w prawo itd. Do gry umieściłem kilka swoich obrazków, które zmieniają się w zależności od tego gdzie znajduje się mucha. Gra wygląda tak:

Zacznijmy od pliku MainActivity.java:

package pl.nstrefa.avrkwiat.gra1;

import android.os.Bundle;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.hardware.SensorManager;
import android.view.Menu;

public class MainActivity extends Activity {
 private SensorManager menedzer;
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); 
 menedzer = (SensorManager) getSystemService(SENSOR_SERVICE);
 setContentView(new GameView(this,menedzer));
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.main, menu);
 return true;
 }

}

Najważniejszym elementem w tym pliku jest zadeklarowanie akcelerometru i ustawienie ekranu w pozycji pionowej. Przy grach z akcelerometrem najlepiej od razu ustalić górę i dół, bo podczas kręcenia telefonem, będzie nam się zmieniała orientacja, a tego nie chcemy.

Jak widzimy nie ma tu dużo kodu jest za to wywołanie klasy GameView. Czyli głównego wyglądu gry. Dosyć dawno pokazywałem wam gameBuilder w JavieME i tam pokazywałem, że warstwa graficzna jest zawsze odseparowana od logiki gry. Dzięki takiemu rozwiązaniu było można nakładać animację na naszego ludzika. Odsyłam do artykułu, jeśli ktoś ma ochotę programować w JavaME

(http://avrkwiat.nstrefa.pl/omnie/index.php?option=com_content&view=article&id=38&Itemid=44)

Tu chcielibyśmy zrobić tak samo, dlatego program jest podzielony na różne klasy.

Klasa GameView jest głównym ekranem gry, to w tej klasie łączymy wszystkie inne klasy odpowiedzialne za grafikę (Sprity) poprzez metody Update. Także w tej klasie odbieramy dane z akcelerometru i przekazujemy dalej do Spritów.

package pl.nstrefa.avrkwiat.gra1;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.lang.*;


public class GameView extends SurfaceView implements SurfaceHolder.Callback {

 private SpriteObject sprite;
 private SpriteTlo spriteTlo;
 private GameLogic mGameLogic;
 private Akcelerometr daneZczujnika; 
 private Bitmap[] bitmapTab=new Bitmap[5];

 public GameView(Context context, SensorManager menedzer) { 
 super(context);
 getHolder().addCallback(this); 
 daneZczujnika = new Akcelerometr(menedzer);
 sprite = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.star), 50, 50);
 
 bitmapTab[0]=BitmapFactory.decodeResource(getResources(), R.drawable.fk);
 bitmapTab[1]=BitmapFactory.decodeResource(getResources(), R.drawable.fl);
 bitmapTab[2]=BitmapFactory.decodeResource(getResources(), R.drawable.fp);
 bitmapTab[3]=BitmapFactory.decodeResource(getResources(), R.drawable.fg);
 bitmapTab[4]=BitmapFactory.decodeResource(getResources(), R.drawable.fd);
 spriteTlo = new SpriteTlo(bitmapTab);
 mGameLogic = new GameLogic(getHolder(), this);

 setFocusable(true);
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,    int height) {
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 mGameLogic.setGameState(mGameLogic.RUNNING);
 mGameLogic.start();
 }
 
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 }
 
 
 
 public void onDraw(Canvas canvas) {
 
 //canvas.drawColor(Color.WHITE);
 spriteTlo.draw(canvas);
 sprite.draw(canvas);
 }

 public void update() {
 if (sprite.getX() >= getWidth()){ 
 sprite.setMoveX(0);
 sprite.setX(getWidth());
 }
 if (sprite.getX() <= 0){
 sprite.setMoveX(0);
 sprite.setX(0);
 }
 if (sprite.getY() >= getHeight()){ 
 sprite.setMoveY(0);
 sprite.setY(getHeight());
 }
 if (sprite.getY() <= 0){
 sprite.setMoveY(0);
 sprite.setY(0);
 }
 sprite.setMoveX(daneZczujnika.getX());
 sprite.setMoveY(daneZczujnika.getY());
 spriteTlo.update(sprite.getX(), sprite.getY());
 sprite.update();

 }

 
}


Klasy takie jak SpriteObject i SpriteTlo odpowiedzialne są za wyświetlanie grafiki poszczególnych elementów. W naszym przypadku klasa SpriteObject wyświetla grafikę muchy i poprzez metodę update aktualizuję jej położenie. A klasa SpriteTlo posiada 5 obrazków, które służą za tło. Tło zmienia się w zależności od tego gdzie znajduje się mucha.

package pl.nstrefa.avrkwiat.gra1;

import android.graphics.Bitmap;
import android.graphics.Canvas;

public class SpriteTlo {
 private Bitmap[] bitmap=new Bitmap[5];;
 private int wartoscSprawdzajaca=0;

 
 public SpriteTlo(Bitmap[] bitmap) {
 this.bitmap = bitmap;

 }
 public void draw(Canvas canvas) {
 
 switch (wartoscSprawdzajaca) {
 case 1:  canvas.drawBitmap(bitmap[1],0, 0, null);//lewo;
 
 break;
 case 2:  canvas.drawBitmap(bitmap[2],0, 0, null);//prawo
 
 break;
 case 3:  canvas.drawBitmap(bitmap[3],0, 0, null);//gora
 
 break;
 case 4:  canvas.drawBitmap(bitmap[4],0, 0, null);//dol
 
 break;

 default:// canvas.drawBitmap(bitmap[0],0, 0, null);
 
 break;
 }
 
 }
 public void update(int xG, int yG) {
 if(yG<300){
 wartoscSprawdzajaca=3;//patrzy gora
 }else 
 if(xG<=200){
 wartoscSprawdzajaca=1;//patrzy lewo
 }else 
 if (xG>200){
 wartoscSprawdzajaca=2;//patrzy prawo
 }  
 if (yG>500){
 wartoscSprawdzajaca=4; // patrzy dol
 }
 }
}


W klasie Akcelerometr są deklarację związane z naszym czujnikiem. Odbiór współrzędnych odbywa się dzięki metodzie getX() i getY().

package pl.nstrefa.avrkwiat.gra1;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;


public class Akcelerometr  implements SensorEventListener{
 
 private Sensor czujnik;
 private int x=0;        
 private int y=0;
 
 public Akcelerometr(SensorManager menedzer){
 //Wybieramy Akcelerometr
 czujnik = menedzer.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
 menedzer.registerListener(this, czujnik,SensorManager.SENSOR_DELAY_UI);
 }
 
 public void onAccuracyChanged(Sensor czujnik, int dokladnosc) {
 // Do zrobienia: automatycznie wygenerowany zalążek metody
 }
 public int getX() {
 
 return -x;
 }
 
 public int getY() {
 
 return y;
 }
 public void onSensorChanged(SensorEvent zdarzenie) {

 
 for (int i = 0; i < zdarzenie.values.length; i++) {             

 
 if(i==0){

 x = (int)zdarzenie.values[i];
 }
 if(i==1){
 
 y = (int)zdarzenie.values[i];
 }
 if(i==2){}//os z
 
 }
 
 }
}

Najważniejszą klasą jest klasa GameLogic. Jak można było się spodziewać, to w tej klasie deklarujemy wielowątkowości i synchronizujemy cały program.

package pl.nstrefa.avrkwiat.gra1;


import android.graphics.Canvas;
import android.view.SurfaceHolder;
import java.lang.Thread;


public class GameLogic extends Thread {
 
 private SurfaceHolder surfaceHolder;
 private GameView mGameView;
 private int game_state;
 public static final int PAUSE = 0;
 public static final int READY = 1;
 public static final int RUNNING = 2;
 
 
 public GameLogic(SurfaceHolder surfaceHolder, GameView mGameView) {
 super();
 this.surfaceHolder = surfaceHolder;
 this.mGameView = mGameView;
 }
 
 
 public void setGameState(int gamestate) {
 this.game_state = gamestate;
 }
 public int getGameState(){
 return game_state;
 }



 @Override
 public void run() {
 Canvas canvas;
 
 
 while (game_state == RUNNING) {
 canvas = null;
 try {
 
 canvas = this.surfaceHolder.lockCanvas();
 
 synchronized (surfaceHolder) {
 try {
 Thread.sleep(30);
 } catch (InterruptedException e1) {
 }

 
 mGameView.update(); 
 this.mGameView.onDraw(canvas);                
 }
 } 
 finally {
 if (canvas != null) {
 surfaceHolder.unlockCanvasAndPost(canvas);
 }
 }
 }
 }
 
}

Teraz możecie podłożyć własne zdjęcia i rozszerzać ten program jak tylko chcecie.

Kliknij tu, aby pobrać cały projekt