sobota, 27 lipca 2013

LIBGDX - Grafika - konfiguracja i odczytywanie parametrów.

OpenGL Context
Poniższy kod odpowiada za ustawienie rozmiarów pola widzenia oraz jego wyczyszczenie (wypełnienie jednolitym kolorem).

Gdx.gl20.glViewport( 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() );
Gdx.gl20.glClearColor( 0, 0, 0, 1 );
Gdx.gl20.glClear( GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT );


Frame Time
Jedną z najczęściej wykorzystywanych metod klasy Graphics jest getDeltaTime(), która zwraca czas który upłynął od chwili wyrenderowania poprzedniej ramki.
Przykładowe użycie:
stage.act( Math.min( Gdx.graphics.getDeltaTime(), 1/30 ) );

Kolejną przydatną metodą jest getFramesPerSecond() - zwraca średnią ilość renderowanych ramek w ciągu sekundy. Najczęściej przydatna w celach diagnostycznych.

LIBGDX - klawiatura ekranowa.

Wyświetlenie klawiatury:

Gdx.input.setOnscreenKeyboardVisible(true);


LIBGDX - Obsługa przycisków 'Wstecz' i 'Menu'

Naciśnięcie przycisku 'Wstecz' zazwyczaj powoduje zakończenie bieżącej aktywności. W niektórych sytuacjach wymagane jest wyświetlenie okna dialogowego służącego potwierdzeniu decyzji o zamknięciu np. aktywności. Aby tego dokonać należy przechwycić zdarzenie naciśnięcia przycisku 'Wstecz'.
Gdx.input.setCatchBackKey(true);

Zdarzenie nadal będzie obsługiwane jeśli mamy zarejestrowany odpowiedni InputProcessor, jednak system operacyjny nie zamknie bieżącej aktywności.
Należy mieć na uwadze, że w systemie Android przycisk 'Wstecz' z definicji służy do zamykania bieżącej aktywności i zmiana takiego zachowania nie należy do dobrych praktyk.
Sposób przechwytywania zdarzenia naciśnięcia przycisku 'Menu':
Gdx.input.setCatchMenuKey(true);

LIBGDX - obsługa wibracji (Gdx.input.vibrate).

Obsługa urządzenia wibracji:

Gdx.input.vibrate(2000);

Jako parametr podajemy czas wibracji mierzony w milisekundach.
Sposób wibrowania można określić bardziej precyzyjnie:

Gdx.input.vibrate(new long[] { 0, 200, 200, 200}, -1); 

W tym przypadku wibracje będą włączone przez 200ms, następnie zostaną wyłączone na 200ms poczym ponownie włączone na 200ms. Drugi parametr oznacza, że cykl wibracji nie będzie powtarzany. Więcej szczegółów w Javadocs.

LIBGDX - Obsługa kompasu

Sprawdzenie obecności czujnika pola magnetycznego w urządzeniu:

boolean compassAvail = Gdx.input.isPeripheralAvailable(Peripheral.Compass);

Odczytywanie danych z kompasu:

float azimuth = Gdx.input.getAzimuth();
float pitch = Gdx.input.getPitch(); float roll = Gdx.input.getRoll();

Wartości kątów zwracane przez w/w funkcje mierzone są w stopniach.

  • azimuth - kąt położenia urządzenia względem osi 'z'. Wartości dodatnie osi 'z' skierowane są ku środkowi kuli ziemskiej.
  • pitch - kąt położenia urządzenia względem osi 'x'.
  • roll - kąt położenia urządzenia względem osi 'Y'.

LIBGDX - obsługa akcelerometru

Przyspieszenie mierzone jest w metrach na sekundę do kwadratu (m/s2). Jeśli dana oś wskazuje dokładnie środek kuli ziemskiej, przyspieszenie dla tej osi wynosi 10 m/s2. Jeśli wskazuje przeciwny kierunek wówczas przyspieszenie ma wartość -10 m/s2.
Układ osi współrzędnych obowiązujący dla urządzeń z systemem Android.


Niestety dla urządzeń typu tablet układ osi jest inny. W urządzeniach z systemem Android przyjęto, że telefony domyślnie znajdują się w pozycji 'portrait' a tablety 'landscape'.

Sprawdzenie dostępności akcelerometru w urządzeniu:

boolean available = Gdx.input.isPeripheralAvailable(Peripheral.Accelerometer);


Odczytanie bieżącej orientacji ekranu:
int orientation = Gdx.input.getOrientation();


Funkcja zwraca wartość 0, 90, 180 lub 270. Daje to informację o różnicy między aktualną orientacją a natywną.

Odczytanie natywnej (domyślnej) orientacji ekranu:
Orientation nativeOrientation = Gdx.input.getNativeOrientation();
Funkcja zwraca wartość Orientation.Landscape lub Orientation.Portrait.

Odczytywanie wartości akcelerometru:
 float accelX = Gdx.input.getAccelerometerX();
 float accelY = Gdx.input.getAccelerometerY();
 float accelZ = Gdx.input.getAccelerometerZ();
W urządzeniach nie posiadających akcelerometru funkcje zwrócą wartość 0.
Przykład zastosowania akcelerometru: Super Jumper.


LIBGDX - wprowadzanie tekstu przez użytkownika "Text Input interface".

Jeśli w aplikacji konieczne jest wprowadzenie przez użytkownika tekstu (np. wpisanie hasła), można skorzystać z gotowego interfejsu "Input".
W systemie Android zostanie wyświetlone standardowe okno dialogowe umożliwiające wprowadzenie tekstu.
Obsługa zdarzeń akceptacji lub anulowania wprowadzonych danych za pomocą listener-a:

public class MyTextInputListener implements TextInputListener {
   @Override
   public void input (String text) {
   }

   @Override
   public void canceled () {
   }
}

Aby wywołać okno dialogowe należy skorzystać z metody:

MyTextInputListener listener = new MyTextInputListener();
Gdx.input.getTextInput(listener, "Dialog Title", "Initial Textfield Value");

Metody listenera ("input" lub "canceled") zostaną wywołane standardowo w tym samym wątku, w którym wykonywana jest metoda "render", zaraz przed wywołaniem ApplicationListener.render().

LIBGDX - GestureDetector - obsługa gestów.

LibGdx dostarcza klasę GestureDetector, która umożliwia detekcję następujących gestów:

  • tap: użytkownik dotyka ekran i podnosi palec ponownie. Palec nie może być przesunięty poza określony obszar wokół miejsca początkowego dotknięcia. Wielokrotne dotknięcie zostanie zarejestrowane jeśli użytkownik dotknie ekran kilka razy w określonym przedziale czasowym.
  • pan: użytkownik przesuwa palec po ekranie. Detektor udostępnia współrzędne dotknięcia ekranu jak również odległość (deltę) przesunięcia między aktualnym a poprzednim miejscem dotknięcia. Przydatne np. do implementacji przesuwania kamery w widoku 3D.
  • fling: Użytkownik przesuwa palec po ekranie i podnosi go.
  • zoom: użytkownik kładzie dwa palce na ekranie i przesuwa je względem siebie. Detektor udostępnia początkowy i bieżący dystans między palcami w pixel-ach. Przydatne np. do implementacji powiększania/zmniejszania.
  • pinch: podobne do poprzedniego - detektor udostępnia początkowe i bieżące położenie palców (nie odległość a położenie). Przydatne do implementacji powiększania/zmniejszania a w szczególności obracania
Aby obsłużyć detektor należy zaimplementować odpowiedni GestureListener i przekazać jego interfejs do konstruktora detektora.

public class MyGestureListener implements GestureListener {

   @Override
   public boolean touchDown (int x, int y, int pointer) {
      return false;
   }

   @Override
   public boolean tap (int x, int y, int count) {
      return false;
   }

   @Override
   public boolean longPress (int x, int y) {
      return false;
   }

   @Override
   public boolean fling (float velocityX, float velocityY) {
      return false;
   }

   @Override
   public boolean pan (int x, int y, int deltaX, int deltaY) {
      return false;
   }

   @Override
   public boolean zoom (float originalDistance, float currentDistance) {
      return false;
   }

   @Override
   public boolean pinch (Vector2 initialFirstPointer, Vector2 initialSecondPointer, Vector2 firstPointer, Vector2 secondPointer) {
      return false;
   }
}


Gdx.input.setInputProcessor(new GestureDetector(new MyGestureListener()));

Podobnie jak w przypadku zdarzeń 'normalnego' InputProcessor-a obsługa zdarzeń następuje tuż przed wywołaniem ApplicationListener.render().

GestureDetector posiada również drugi konstruktor umożliwiający przekazanie dodatkowych parametrów - patrz JavaDocs.

LIBGDX - InputProcessor - obsługa zdarzeń wejść.


public class MyInputProcessor implements InputProcessor {
   @Override
   public boolean keyDown (int keycode) {
      return false;
   }

   @Override
   public boolean keyUp (int keycode) {
      return false;
   }

   @Override
   public boolean keyTyped (char character) {
      return false;
   }

   @Override
   public boolean touchDown (int x, int y, int pointer, int button) {
      return false;
   }

   @Override
   public boolean touchUp (int x, int y, int pointer, int button) {
      return false;
   }

   @Override
   public boolean touchDragged (int x, int y, int pointer) {
      return false;
   }

   @Override
   public boolean touchMoved (int x, int y) {
      return false;
   }

   @Override
   public boolean scrolled (int amount) {
      return false;
   }
}


  • keyDown(), keyUp(), keyTyped() : zdarzenia klawiatury
  • touchDown(), touchUp(), touchDragged(), touchMoved(), scrolled() : zdarzenia dotyku/myszy
Po zaimplementowaniu metod klasy InputProcessor należy 'zarejestrować' procesor w LibGdx:
MyInputProcessor inputProcessor = new MyInputProcessor();
Gdx.input.setInputProcessor(inputProcessor);
Od tego momentu wszystkie zdarzenia wejściowe będą  przekazywane do instancji MyInputProcessor. Obsługa zdarzeń następuje tuż przed wywołaniem ApplicationListener.render().

piątek, 26 lipca 2013

LIBGDX - reakcja na dotyk ekranu.

Sprawdzenie, czy ekran aktualnie jest 'dotknięty':

boolean isTouched = Gdx.input.isTouched();


Multidotyk - równie prosto...:

boolean firstFingerTouching = Gdx.input.isTouched(0);
boolean secondFingerTouching = Gdx.input.isTouched(1);
boolean thirdFingerTouching = Gdx.input.isTouched(2);


Sprawdzenie, czy użytkownik dotknął i 'zabrał' ( :-) ) palec:

boolean justTouched = Gdx.input.justTouched();


Odczytanie współrzędnych dotkniętego miejsca (jako parametr podajemy numer dotkniętego miejsca):

int firstX = Gdx.input.getX();
int firstY = Gdx.input.getY();
int secondX = Gdx.input.getX(1);
int secondY = Gdx.input.getY(1);


LIBGDX - Klasa Preferences - zapisywanie parametrów (ustawień) programu.

Tworzenie obiektu:

Preferences prefs = Gdx.app.getPreferences("My Preferences");


Ustawianie i odczytywanie własności (np. ustawień programu):

prefs.putString("name", "Donald Duck");
String name = prefs.getString("name", "No name stored");

prefs.putBoolean("soundOn", true);
prefs.putInteger("highscore", 10);


Zapisanie danych:

// bulk update your preferences
prefs.flush();


W systemie Android dane aplikacji zapisywane są za pomocą systemowego mechanizmu SharedPreferences.

Interfejs aplikacji w LIBGDX - przykładowe zastosowania.


Sprawdzenie rodzaju platformy:
switch(Gdx.app.getApplicationType()) {
   case ApplicationType.Android:
       // android specific code
   case ApplicationType.Desktop:
       // desktop specific code
   case ApplicationType.WebGl:
       /// HTML5 specific code
}


Odczytanie obsługiwanej wersji Android SDK:
int androidVersion = Gdx.app.getVersion();


Logowanie:
Gdx.app.log("MyTag", "my informative message");
Gdx.app.error("MyTag", "my error message", exception);
Gdx.app.debug("MyTag", "my error message");

Ustawienie poziomu logowania:
Gdx.app.setLogLevel(logLevel);


Dostępne poziomy logowania:
  • Application.LOG_NONE: mutes all logging.
  • Application.LOG_DEBUG: logs all messages.
  • Application.LOG_ERROR: logs only error messages.
  • Application.LOG_INFO: logs error and normal messages.

LIBGDX - podstawowe informacje o framework-u.

Framework LIBGDX składa się z pięciu podstawowych modułów:

  • Application: uruchamia aplikację i informuje API o zdarzeniach aplikacji takich jak np. zmiana rozmianu ekranu.
  • Files: obsługa systemu plików.
  • Input: API obsługi urządzeń wejściowych (np. mysz, klawiatura, ekran dotykowy, akcelerometr itp.).
  • Audio: obsługa urządzeń audio (wejście / wyjście).
  • Graphics: obsługa OpenGL ES 1.x and 2.0 (jeśli dostępne).
Dostęp do w/w możliwy jest poprzez Application.getApplicationType().




LIBGDX - Klasa startowa i konfiguracja aplikacji.

package com.me.mygdxgame;
import android.os.Bundle;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
public class MainActivity extends AndroidApplication {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
        cfg.useGL20 = false;
        
        initialize(new MyGdxGame(), cfg);
    }
}

Klasa startowa (dla aplikacji tworzonej dla systemu Android) dziedziczy z klasy AndroidApplication (która z kolei dziedziczy z klasy Activity).
Podczas uruchamiania aplikacji tworzona jest instancja konfiguracji (AndroidApplicationConfiguration). Następnie wywoływana jest metoda AndroidApplication.initialize(), do której jako parametry przekazywany jest obiekt ApplicationListener(MyGdxGame) oraz utworzona konfiguracja.

Mimo, że aplikacje w systemie Android mogą składać się z wielu aktywności, tworząc grę 'Libgdx' należy tworzyć tylko jedną aktywność. Kolejne ekrany są kreowane za pomocą mechanizmów Libgdx a nie jako oddzielne aktywności. Przyczyną tego rozwiązania jest prosta - tworzenie nowej aktywności implikuje utworzenie nowego kontekstu OpenGL co jest czasochłonne.

LIBGDX - cykl życia aplikacji...



MetodaOpis
create ()Wywoływana tylko jeden raz podczas uruchamiania aplikacji.
resize(int width, int height)Wywoływana za każdym razem gdy następuje zmiana rozmiaru ekranu gry i gra nie jest w trybie pauzy.
Dodatkowo jest jednokrotnie wywołana zaraz po metodzie create ().
Parametrami są nowa szerokość i wysokość ekranu określona w pikselach.
render ()Metoda wywoływana w pętli gry za każdym razem gdy należy 'przegenerować' zawartość ekranu. W tej metodzie również następuje aktualizacja logiki gry.
pause ()W systemie Android ta metoda jest wywoływana kiedy 'naciśnięto' przycisk 'Home', lub wystąpiło telefoniczne połączenie przychodzące.
W środowisku 'desktop' metoda jest wywołana tuż przed wywołaniem metody dispose () - podczas zamykania aplikacji.

Jest to odpowiednie miejsce na zapisanie stanu gry.
resume ()Medoda wywoływana jedynie w środowisku Android - podczas ponownego uaktywnienia gry (powrót z 'trybu pauzy').
dispose ()Wywoływana kiedy aplikacja jest zamykana. Poprzedzona wywołaniem pause().

wtorek, 23 lipca 2013

Samsung Galaxy S II czy może Sony XPERIA L?

Zbliża się czas wymiany telefonu na nowy i co za tym idzie pojawił się dylemat. Jaki telefon wybrać? Aktualnie pod uwagę brane są: Samsung Galaxy S II i Sony XPERIA L.
Co wybrać?

poniedziałek, 15 lipca 2013

Endomondo - skuteczna mobilizacja.

Ostatnio bardzo reklamowany w mediach... I słusznie. Program w sam raz dla każdego kto chce się zmobilizować do aktywności fizycznej.
Uwaga praktyczna - skuteczność programu wzrasta jeśli mamy znajomych, którzy również korzystają z Endomondo.

sobota, 13 lipca 2013

Astrid do kasacji -> przesiadka na 'DGT GTD & To-do List'

Astrid za chwilę przestanie funkcjonować więc czas przestawić się na inny program typu "GTD". Polecam "DGT GTD & To-do List". Rozbudowany program, który synchronizuje dane z serwisem http://www.toodledo.com.

Informacja 'o ciasteczkach' w blogger...

Zgodnie z obecnie obowiązującymi przepisami strony korzystające z ciasteczek muszą o tym fakcie informować… W przypadku blogu na blogger aby dodać taki mechanizm wystarczy skorzystać z poradnika dostępnego pod tym adresem: LINK.

Stało się…. Astrid.com kończy swoją działalność…

Od niedawna krążyły po sieci pogłoski o zbliżającym się końcu istnienia portalu Astrid.com. Kilka dni temu na oficjalnym blogu Astrid pojawił się wpis informujący, że 5 sierpnia 2013r. serwis Astrid.com zostanie zamknięty. Co to oznacza? Użytkownicy programu Astrid będą musieli poszukać dla siebie innego programu – przypominacza. Na chwilę obecną nie ma godnego odpowiednika… przynajmniej na platformę Android. Aktualnie szukam – jeśli znajdę – napiszę… Link do wpisu na blogu: http://blog.astrid.com/blog/2013/07/08/astrid-winding-down/