2012-08-01 63 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