2012-08-01 62 views
2

搜索谷歌,各種Android博客,各種遊戲開發人員博客和其他教程網站的android中的surfaceviews後,我期待着對曲面瀏覽的完整理解。我已經閱讀了關於android和表面視圖的Safaribooks的幾本書,但是它們提供的信息太少,或者使用其他SDK(如AndEngine)。我希望嚴格學習表面視圖。我玩過Lunar Lander示例項目以及我找到的其他項目,並創建了一些骨架表面視圖代碼。它由3個類組成,僅用於骨架。Surfaceview骨架教程問題

MainActivity類別:

package com.learning.svlearning; 

import android.os.Bundle; 
import android.app.Activity; 
import android.view.Menu; 
import android.view.Window; 
import android.view.WindowManager; 

public class MainActivity extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

    //Set FullScreen Mode - No title bars!! 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     // Screen created with pure java - Say no to xml (atleast for this demo) 
     setContentView(new MainGamePanel(this)); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.layout_game_window, menu); 
     return true; 
    } 
} 

這個類是非常簡單的。主遊戲活動窗口,請求全屏幕,沒有標題欄。一個真實的遊戲應該如何:)這個類通過傳遞「this」(MainActivity)類的上下文來調用我們的下一個視圖類。

MainGamePanel類:

package com.learning.svlearning; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class MainGamePanel extends SurfaceView { 
final static public String tag = "Tracer"; 

private GameThread gameThread; // For our thread needed to do logical processing without holding up the UI thread 
private SurfaceHolder holder; // For our CallBacks.. (One of the areas I don't understand!) 

public MainGamePanel(Context context) { 
    super(context); 
    Log.d(tag, "Inside MainGamePanel"); 
    gameThread = new GameThread(this); //Create the GameThread instance for our logical processing 
    holder = getHolder(); 


    holder.addCallback(new SurfaceHolder.Callback() { 


// Since we are using the SurfaceView, we need to use, at very least, the surfaceDestroyed and surfaceCreated methods. 
     @Override 
     public void surfaceDestroyed(SurfaceHolder holder) { 
      boolean retry = true; 
      Log.d(tag, "Inside SurfaceHolder Callback - surfaceDestroyed"); 
      gameThread.setRunning(false); // Stop the Thread from running because the surface was destroyed. Can't play a game with no surface!! 

      while (retry) { 
       try { 
        Log.d(tag, "Inside SurfaceHolder Callback - surfaceDestroyed - while statement"); 
        gameThread.join(); 
        retry = false; //Loop until game thread is done, making sure the thread is taken care of. 
       } catch (InterruptedException e) { 
        // In case of catastrophic failure catch error!!! 
       } 
      } 

     } 

     @Override 
     public void surfaceCreated(SurfaceHolder holder) { 
      // let there be Surface! 
      Log.d(tag, "Inside SurfaceHolder Callback - surfaceCreated"); 
      gameThread.setRunning(true); // Now we start the thread 
      gameThread.start(); // and begin our game's logical processing 

     } 

     @Override 
     public void surfaceChanged(SurfaceHolder holder, int format, 
       int width, int height) { 
      // The code to resize the screen ratio when it flips from landscape to portrait and vice versa 

     } 
    }); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
//This is where we draw stuff.. since this is just a skeleton demo, we only draw the color Dark Grey so we can visibly see that we actually accomplished something with the surfaceview drawing 
    Log.d(tag, "Inside onDraw"); 
    canvas.drawColor(Color.DKGRAY); // You can change the Color to whatever color you want, for this demo I just used Color.DKGRAY 

    } 

} 

該類主要涉及我們的資源/使用的onDraw方法圖像處理的繪製什麼是創建和銷燬(屏幕變化也當我們的面時發生,但我現在沒有編寫任何代碼來處理它),並且調用我們的GameThread類來處理我們的遊戲邏輯。

GameThread類:

package com.learning.svlearning; 

import android.graphics.Canvas; 
import android.util.Log; 



public class GameThread extends Thread{ 
final static public String tag = "Tracer"; 


private MainGamePanel view; 
private boolean running = false; 

static final long FPS = 30; // To help limit the FPS when we draw, otherwise we would kill the CPU and increase the Battery Consumption. 

public GameThread(MainGamePanel view){ 
    Log.d(tag, "inside GameThread"); 
    this.view = view; 
} 

public void setRunning(boolean run){ 
    Log.d(tag, "inside GameThread - setRunning"); 
    running = run; // For starting/stoping our game thread 
} 


@Override 
public void run() { 
    long ticksPS = 1000/FPS; // Limit the frames per second 
    long startTime; 
    long sleepTime; 
    Log.d(tag, "inside GameThread - run"); 

    while(running){ // Our Main Game Loop is right here 
     Canvas c = null; // build our canvas to draw on 
     Log.d(tag, "inside GameThread - run - while loop"); 
     startTime = System.currentTimeMillis(); //get the current time in milliseconds - this is for helping us limit the FPS 
     try{ 
      c = view.getHolder().lockCanvas(); //Before we can draw, we always have to lock the canvas, otherwise goblins will invade your app and destroy everything! 
      synchronized (view.getHolder()){ // we have to synchronize this because we need to make sure that the method runs when at the proper time. 
       view.onDraw(c); // this is where we pass our drawing information. The canvas gets passed to the onDraw method in our MainGamePanel class. 
      } 
     }finally{ 
      if(c != null) { 
       view.getHolder().unlockCanvasAndPost(c); // Once we are done drawing, we unlock our canvas and post. which means we drew on the canvas, and now the devices screen will display our drawing. 
      } 
     } 
     sleepTime = ticksPS-(System.currentTimeMillis() - startTime); // this is where we calculace how long we need this thread to sleep (again with the FPS) we want it limited to 30 FPS as defined in our FPS variable. 
     try { 
      if (sleepTime > 0){ 
        sleep(sleepTime); // night night, sleep to limit the fps and save our batteries! 
      } 
      else{ 
        sleep(10); // Incase something goes crazy, we still want to sleep the thread to save the battery. 
      } 
     }catch(Exception e){ 

     } 

    } 

} 


} 

與處理遊戲邏輯和發送任何信息繪製到我們的MainGamePanel類draw方法該類交易。例如,如果我們有一個角色在移動,我們可以將x和y座標發送到我們的繪製方法,以便在不同的位置繪製我們的角色。

現在這些類的某些部分我不完全理解。就像回調一樣,當閱讀谷歌Android開發者頁面上的信息時,我只是更加困惑它是什麼以及我們爲什麼使用它。此外,如果任何人有更多的東西需要加入,或看到任何我可能誤解的東西,請隨時糾正我。我喜歡和android一起工作,雖然這很困難,但是當你開始瞭解事情的時候,這是非常有益的!

+3

而你的問題是? – san 2012-08-01 03:32:31

+0

水邊回調的目的是什麼? – 2012-08-02 01:40:54

+0

這是我見過這麼短的問題中最長的帖子。爲什麼不在沒有解釋你的背景的情況下發布問題? – 2012-10-24 18:52:56

回答

1

SurfaceHolder回調的目的是處理這3個事件。 surfaceCreated(),surfaceDestroyed()和surfaceChanged()。

如果你讀的代碼,你可以看到,surfaceCreated()處理事情需要在創建表面時發生,等等...

是回答您的問題或在那裏嗎?

1

使用SurfaceView時,應該將繪圖方法更改爲除onDraw()之外的其他名稱。這樣主線程永遠不會意外失效()它!

+0

它將如何意外失效? – RichieHH 2014-07-29 11:55:17