Presentation.java :  » Graphics-3D-2D-OpenGL » racertc » com » games » racertc » gameplay » graphics » Android Open Source

Android Open Source » Graphics 3D 2D OpenGL » racertc 
racertc » com » games » racertc » gameplay » graphics » Presentation.java
package com.games.racertc.gameplay.graphics;

import java.util.ListIterator;

import com.games.racertc.objects.Car;
import com.games.racertc.objects.GameObject;
import com.games.racertc.other.Vec2D;
import com.games.racertc.tracks.Track;
import com.games.racertc.ui.UIManager;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.view.SurfaceHolder;

/**
 * Klasa odpowiadajaca za rysowanie gry.
 * @author Piotr Balut
 */
public class Presentation {

  /** Uchwyt do SurfaceHolder. */
  protected final SurfaceHolder surfaceHolder;
  
  /** Uchwyt do zasobow. */
  protected final Resources resources;
  
  protected UIManager uiManager;
  
  Vec2D camPos = new Vec2D();
  
  /** Szerokosc ekranu. */
  protected int width = 1024;
  /** Wysokosc ekranu. */
  protected int height = 768;
  
  /** Polowa szerokosci ekranu (zaokraglana w dol). */
  protected int halfWidth;
  /** Polowa wysokosci ekranu (zaokraglana w dol). */
  protected int halfHeight;
  
  /** Aktualnie aktywna trasa. */
  protected Track track;
  
  //private Bitmap trackBitmap;
  
  public Presentation( SurfaceHolder surfaceHolder, Resources resources ) {
    this.surfaceHolder = surfaceHolder;
    this.resources = resources;
  }
  
  /**
   * Przygotowuje Presentation do pracy. Powinno byc wolane kazdorazowo przed rozpoczeciem
   * nowej rozgrywki.
   * @param track Trasa na ktorej odbywac sie bedzie rozgrywka.
   */
  public void initialise( Track track ) {
    this.track = track;
  }

  /**
   * Ustawia menadzera interface'u uzytkownika wykorzystywanego do rysowania UI.
   * @param uiManager Menadzer UI, ktory bedzie od teraz uzywany.
   */
  public void setUIManager( UIManager uiManager ) {
    this.uiManager = uiManager;
  }
  
  public UIManager getUIManager() {
    return uiManager;
  }
  
  public void setResolution( int width, int height ) {
    this.width = width;
    this.height = height;
    //oblicza polowy wysokosci i szerokosci - aby zaoszczedzic
    //obliczen pozniej
    halfWidth = ( width >> 1 );
    halfHeight = ( height >> 1 );
  }  
  
/*-----------------------------------------*/
/*-             Obliczenia:               -*/
/*-----------------------------------------*/    
  
  /**
   * Metoda pozwalajaca obliczyc pozycje kamery zawieszonej nad zadanym obiektem. Jezeli
   * obiekt znajduje sie na krawedzi trasy, zwrocone zostanie taka wartosc pozycji kamery,
   * aby nie wysuwala sie ona poza trase.
   * @param stickToObject Obiekt do ktorego "przyczepiona" jest kamera.
   * @return Wspolrzedne piksela trasy nad ktorym zawieszona jest kamera.
   */
  protected void calculateCameraPosition( GameObject stickToObject ) {
    camPos = stickToObject.getPosition().toPx();
    int x = (int) camPos.getX();
    int y = (int) camPos.getY();
    
    //jesli kamera zbyt blisko lewej krawedzi
    if( x < halfWidth )
      camPos.setX( (float) halfWidth );
    
    //jesli kamera zbyt blisko prawej krawedzi
    else if( x > track.getWidth() - halfWidth )
      camPos.setX( (float) (track.getWidth() - halfWidth) );
    
    //jesli kamera zbyt blisko gornej krawedzi
    if( y < halfHeight )
      camPos.setY( (float) halfHeight );
    
    //jesli kamera zbyt blisko dolnej krawedzi
    else if( y > track.getHeight() - halfHeight )
      camPos.setY( (float) (track.getHeight() - halfHeight) );
    
  }
  
  /**
   * Podaje pozycje srodka obiektu na wyswietlaczu.<br>
   * <br>
   * <strong>UWAGA!</strong> Nie sprawdza, czy obiekt
   * faktycznie jest widoczny - ta metoda sluzy _tylko_ do obliczenia wspolrzednych,
   * ktore to moga byc mniejsze od zera, lub przekraczac rozdzielczosc ekranu (co
   * moze tez oznaczac, ze obiekt widoczny jest czesciowo). Testowanie widocznosci
   * mozna przeprowadzic za pomoca funkcji isOnScreen.
   * @param obj Obiekt, ktorego wspolrzedne zostana obliczone.
   * @param camPos Punkt trasy, ktory obserwuje kamera.
   * @return Wspolrzedne srodka obiektu na wyswietlaczu.
   */
  protected Vec2D getOnScreenPosition( GameObject obj, Vec2D camPos ) {
    //pobiera pozycje obiektu:
    Vec2D obj_pos = obj.getPosition().toPx();
    //oblicza przesuniecie obiektu od srodka ekranu:
    obj_pos.set(
        obj_pos.getX() - camPos.getX(),
        obj_pos.getY() - camPos.getY()
    ); //TODO: a jakby tak zrobic Vec2I.substract( Vec2I )?
    //ale tak naprawde teraz mamy przesuniecie wzgledem punktu (0,0)
    //totez przesuwamy obiekt tak, aby faktycznie znalazl sie tam
    //gdzie trzeba na ekranie
    obj_pos.add( halfWidth, halfHeight );
    return obj_pos;
  }
  
  /**
   * Sprawdza, czy zadany obiekt jest przynajmniej czesciowo widoczny na ekranie.
   * @param obj Sprawdzany obiekt.
   * @param onScreenPosition wspolrzedne obiektu na ekranie.
   * @return <strong>true</strong>, jezeli obiekt jest widoczny; <strong>false</strong>
   * w przeciwnym wypadku.
   */
  protected boolean isOnScreen( GameObject obj, Vec2D onScreenPosition ) {
    final float obj_radius = obj.getImageRadius();
    //sprawdzenie na osi X
    float tmp_var = onScreenPosition.getX();
    if( ((tmp_var + obj_radius) < 0) || ((tmp_var - obj_radius) > width) )
      return false;
    //sprawdzenie na osi Y
    tmp_var = onScreenPosition.getY();
    if( ((tmp_var + obj_radius) < 0) || ((tmp_var - obj_radius) > height) )
      return false;    
    return true;
  }
  
/*-----------------------------------------*/
/*       Rysowanie - f. publiczne:        -*/
/*-----------------------------------------*/  
  
  /**
   * Rysuje rozgrywke oraz UI.
   */
  public void drawGame( Canvas canvas ) {
    //rysuje rozgrywke
    internalDrawGame( canvas );
    
    //na koniec rysuje UI:
    uiManager.drawUI( canvas );
    
  }
  
/*-----------------------------------------*/
/*-              Rysowanie:               -*/
/*-----------------------------------------*/
  
  /**
   * Rysuje rozgrywke.
   */
  protected void internalDrawGame( Canvas canvas ) {
    ListIterator< GameObject > iter = track.getGameObjectIterator();
    
    //pobieramy pojazd gracza
    GameObject obj = iter.next();
    
    //obliczamy nad jakim punktem mapy bedzie znajdowac sie kamera:
    calculateCameraPosition( obj );
    
    //rysujemy wycinek mapy (tlo):
    drawTrackFragment( canvas, camPos );
    
    //rysujemy samochod gracza:
    obj.acceptPresentation( this, canvas, getOnScreenPosition( obj, camPos ) );
    
    //rysujemy pozostale obiekty:
    while( iter.hasNext() ) {
      obj = iter.next();
      Vec2D screen_pos = getOnScreenPosition( obj, camPos );
      if( isOnScreen( obj, screen_pos ) ) //czy jest na ekranie?
        obj.acceptPresentation( this, canvas, screen_pos ); //jezeli tak, to rysujemy
    }
  }
  
  /**
   * Wypelnia ekran fragmentem trasy obserwowanym przez kamere znajdujaca sie
   * nad zadanymi wspolrzednymi trasy.
   * @param canvas Obiekt Canvas na ktorym bedzie wykonywane rysowanie
   * @param camPos Wspolrzedne trasy, nad ktorymi zawieszona jest kamera
   */
  protected void drawTrackFragment( Canvas canvas, Vec2D camPos ) {
    //XXX: co to znaczy "immutable bitmap"?! Prawdopodobnie kod nizej jest wysoce nieefektywny
    //poniewaz tworzone sa kopie bitmapy. Jezeli tak jest w istocie, trzeba by napisac funkcje
    //blit() kopiujaca bezposrednio piksele z bitmapy planszy na canvas (albo cos podobnego i wydajnego).
    //Bitmap fragment = Bitmap.createBitmap(
    //  track.getTrackGraphics(),
    //  200,200,//((int) camPos.getX()) - halfWidth,
      //((int) camPos.getY()) - halfHeight,
    //  250,250//width,
      //height
    //);
    Rect r = new Rect(
        ((int) camPos.getX()) - halfWidth,
        ((int) camPos.getY()) - halfHeight,
        ((int) camPos.getX()) - halfWidth + width,
        ((int) camPos.getY()) - halfHeight + height
      );
    //canvas.drawBitmap( fragment, 0, 0, null );
    try {
    canvas.drawBitmap(track.getTrackGraphics(), r, new Rect(0,0,width,height), null);
    } catch( Exception e ) {
      e.printStackTrace();
    }
  }  
  
  /**
   * Rysowanie obiektow - wersja przeciazana dla typu Car.<br><br>
   * Oprocz rysowania samochodu dokonywana jest takze jego animacja.
   * @param car Rysowany obiekt samochodu.
   * @param canvas Canvas na ktorym rysowany jest obiekt.
   * @param screenPos Wspolrzedne piksela w ktorych znajduje sie srodek samochodu.
   */
  public void drawGameObject( Car car, Canvas canvas, Vec2D screenPos ) {
    //zapisuje macierz przekrztalcen
    canvas.save();
    //przygotowuje Canvas do rysowania samochodu:
      //krok II: przesuwa samochod na wlasciwa pozycje na ekranie
    canvas.translate( screenPos.getX(), screenPos.getY() );
      //krok I: obraca samochod
    canvas.rotate( (float) Math.toDegrees( car.getRotation() ) );
    
    //rysuje samochod
    car.getDrawable().draw( canvas );
    
    //przywraca macierz przekrztalcen
    canvas.restore();
    
  }
  
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.