2013-06-04 5 views
4

С тех пор я читаю книгу «Начало игр для Android» с последних дней. Но я застрял, чтобы понять код.Мне нужно объяснение для кода «начинающих игр для Android»

Вы можете проверить или загрузить код здесь: http://code.google.com/p/beginnginandroidgames2/downloads/list

Проект Я имею в виду ch06-mr-mom. Активность называется MrNomGame:

public abstract class AndroidGame extends Activity implements Game { 

    AndroidFastRenderView renderView; 
    Graphics graphics; 
    Audio audio; 
    Input input; 
    FileIO fileIO; 
    Screen screen; 
    WakeLock wakeLock; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
       WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; 
     int frameBufferWidth = isLandscape ? 480 : 320; 
     int frameBufferHeight = isLandscape ? 320 : 480; 
     Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth, 
       frameBufferHeight, Config.RGB_565); 

     float scaleX = (float) frameBufferWidth 
       /getWindowManager().getDefaultDisplay().getWidth(); 
     float scaleY = (float) frameBufferHeight 
       /getWindowManager().getDefaultDisplay().getHeight(); 

     renderView = new AndroidFastRenderView(this, frameBuffer); 
     graphics = new AndroidGraphics(getAssets(), frameBuffer); 
     fileIO = new AndroidFileIO(this); 
     audio = new AndroidAudio(this); 
     input = new AndroidInput(this, renderView, scaleX, scaleY); 
     screen = getStartScreen(); 
     setContentView(renderView); 

     PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 
     wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame"); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     wakeLock.acquire(); 
     screen.resume(); 
     renderView.resume(); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     wakeLock.release(); 
     renderView.pause(); 
     screen.pause(); 

     if (isFinishing()) 
      screen.dispose(); 
    } 

    public Input getInput() { 
     return input; 
    } 

    public FileIO getFileIO() { 
     return fileIO; 
    } 

    public Graphics getGraphics() { 
     return graphics; 
    } 

    public Audio getAudio() { 
     return audio; 
    } 

    public void setScreen(Screen screen) { 
     if (screen == null) 
      throw new IllegalArgumentException("Screen must not be null"); 

     this.screen.pause(); 
     this.screen.dispose(); 
     screen.resume(); 
     screen.update(0); 
     this.screen = screen; 
    } 

    public Screen getCurrentScreen() { 
     return screen; 
    } 
} 

класс реализует интерфейс Game:

package com.badlogic.androidgames.framework; 

public interface Game { 
    public Input getInput(); 
    public FileIO getFileIO(); 
    public Graphics getGraphics(); 
    public Audio getAudio(); 
    public void setScreen(Screen screen); 
    public Screen getCurrentScreen(); 
    public Screen getStartScreen(); 
} 

Мой первый вопрос: я пропустил реализацию метода getStartScreen() интерфейса Game. Обычно я должен реализовать все методы интерфейса.

В любом случае, теперь работает onCreate. На этой линии:

screen = getStartScreen(); 

Программа восходит к классу происхождения MrNomGame, где метод getStartScreen() дает объект LoadingScreen к переменным screen. Класс LoadingScreen:

public class LoadingScreen extends Screen { 

    public LoadingScreen(Game game) { 
     super(game); 
    } 

    public void update(float deltaTime) { 
     Graphics g = game.getGraphics(); 
     Assets.background = g.newPixmap("background.png", PixmapFormat.RGB565); 
     Assets.logo = g.newPixmap("logo.png", PixmapFormat.ARGB4444); 
     Assets.mainMenu = g.newPixmap("mainmenu.png", PixmapFormat.ARGB4444); 
     Assets.buttons = g.newPixmap("buttons.png", PixmapFormat.ARGB4444); 
     Assets.help1 = g.newPixmap("help1.png", PixmapFormat.ARGB4444); 
     Assets.help2 = g.newPixmap("help2.png", PixmapFormat.ARGB4444); 
     Assets.help3 = g.newPixmap("help3.png", PixmapFormat.ARGB4444); 
     Assets.numbers = g.newPixmap("numbers.png", PixmapFormat.ARGB4444); 
     Assets.ready = g.newPixmap("ready.png", PixmapFormat.ARGB4444); 
     Assets.pause = g.newPixmap("pausemenu.png", PixmapFormat.ARGB4444); 
     Assets.gameOver = g.newPixmap("gameover.png", PixmapFormat.ARGB4444); 
     Assets.headUp = g.newPixmap("headup.png", PixmapFormat.ARGB4444); 
     Assets.headLeft = g.newPixmap("headleft.png", PixmapFormat.ARGB4444); 
     Assets.headDown = g.newPixmap("headdown.png", PixmapFormat.ARGB4444); 
     Assets.headRight = g.newPixmap("headright.png", PixmapFormat.ARGB4444); 
     Assets.tail = g.newPixmap("tail.png", PixmapFormat.ARGB4444); 
     Assets.stain1 = g.newPixmap("stain1.png", PixmapFormat.ARGB4444); 
     Assets.stain2 = g.newPixmap("stain2.png", PixmapFormat.ARGB4444); 
     Assets.stain3 = g.newPixmap("stain3.png", PixmapFormat.ARGB4444); 
     Assets.click = game.getAudio().newSound("click.ogg"); 
     Assets.eat = game.getAudio().newSound("eat.ogg"); 
     Assets.bitten = game.getAudio().newSound("bitten.ogg"); 
     Settings.load(game.getFileIO()); 
     game.setScreen(new MainMenuScreen(game)); 
    } 

    public void present(float deltaTime) { 

    } 

    public void pause() { 

    } 

    public void resume() { 

    } 

    public void dispose() { 

    } 
} 

Класс Screen:

public abstract class Screen { 
    protected final Game game; 

    public Screen(Game game) { 
     this.game = game; 
    } 

    public abstract void update(float deltaTime); 
    public abstract void present(float deltaTime); 
    public abstract void pause(); 
    public abstract void resume(); 
    public abstract void dispose(); 
} 

После определенного времени, метод onCreate() закончен. Но в режиме Debug экран моего мобильного телефона уже черный и темный. Кажется, программа находится в цикле. Я могу нажать F6 так часто, как я хочу. Но когда я вернусь, появится главное меню. Если вы посмотрите в коде, вы увидите, что Главное меню вызовет метод update()loadingScreen.

Мой большой вопрос: Что происходит после того, как метода onCreate() закончена, и как программа попасть в update() метод loadingScreen?

Я знаю, что много кода. Но мне было бы очень полезно это понять.

+13

Бог благословить храбрый Stackoverflowers, которые читают до конца. – xyz

+1

что-то не так с вашим методом обновления. он вызывает Game.setScreen, а ваша реализация игры вызывает обновление в конце setScreen. Это похоже на бесконечную рекурсию. – njzk2

+0

@ njzk2 сначала 'screen' является экземпляром' LoadingScreen'. «Обновление» этого класса устанавливает «экран» в экземпляр «MainMenuScreen». Следовательно, новое 'update' вызывается в другом классе. –

ответ

4

Для вашего первого вопроса: AndroidGame является аннотация класс. Это означает, что ему не нужно реализовывать все методы Game, если только один из классов, распространяющихся на AndroidGame, делает это.Как вы можете видеть из кода, это делается в MrNomGame:

public class MrNomGame extends AndroidGame { 
    public Screen getStartScreen() { 
     return new LoadingScreen(this); 
    } 
} 

Теперь для большого вопроса:

В onCreate, рендерер создан:

renderView = new AndroidFastRenderView(this, frameBuffer); 

Если у вас есть посмотрите на этот класс, вы увидите, что onResume создает новый поток, который запускает следующий код:

public void run() { 
    Rect dstRect = new Rect(); 
    long startTime = System.nanoTime(); 
    while(running) { 
     if(!holder.getSurface().isValid()) 
      continue;   

     float deltaTime = (System.nanoTime()-startTime)/1000000000.0f; 
     startTime = System.nanoTime(); 

     game.getCurrentScreen().update(deltaTime); 
     game.getCurrentScreen().present(deltaTime); 

     Canvas canvas = holder.lockCanvas(); 
     canvas.getClipBounds(dstRect); 
     canvas.drawBitmap(framebuffer, null, dstRect, null); 
     holder.unlockCanvasAndPost(canvas); 
    } 
} 

Итак, он повторно называет update на текущем экране, который является экземпляром LoadingScreen.

+0

Благодарим за помощь. Другой вопрос: что вызывает методы «onResume» и «run» в «AndroidFastRenderView»? И почему мне нужен этот интерфейс «runnable»? Возможно, я не понимаю цели интерфейса. Я думаю, что он имеет дело с классом «SurfaceView», который расширен «AndroidFastRenderView». –

+0

@PeterPanne Как вы можете видеть в коде, который вы отправили, 'AndroidGame.onResume' вызывает метод' resume' в 'AndroidFastRenderView' (если вы хотите узнать, почему вызывается' onResume', посмотрите [Жизненный цикл активности ] (http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle)). Метод 'run' вызывается' renderThread.start() '. Это связано с тем, что 'AndroidFastRenderView' реализует' Runnable', что означает, что он может запускаться в отдельном потоке, чтобы не замораживать графический интерфейс. –

+0

Большое спасибо. Думаю, теперь я это понимаю. While-Loop в «run» - бесконечный цикл. Таким образом, ему нужен собственный поток, иначе приложение will будет заморожено. Я не знаю достаточно о интерфейсе «runnable», но я знаю, что это необходимо, потому что класс просто способен расширять один класс. Поэтому вам нужен интерфейс. На данный момент я не понимаю всю тему интерфейсов. Я скоро открою новый поток, чтобы спросить об этом. Еще раз спасибо за ответы на мои вопросы. –