Android游戏之屏幕类TestScreen和游戏类AndroidGame设计

Android游戏之屏幕类TestScreen和游戏类AndroidGame设计

1、基础知识:

A. WakeLock

http://developer.android.com/reference/android/os/PowerManager.WakeLock.html
B. requestWindowFeature
http://developer.android.com/reference/android/app/Activity.html#requestWindowFeature(int)
C. getWindow().setFlags
http://developer.android.com/reference/android/app/Activity.html#getWindow()
http://developer.android.com/reference/android/view/Window.html#setFlags(int, int)
D. getResources().getConfiguration()
http://developer.android.com/reference/android/content/res/Configuration.html
E. Bitmap.createBitmap
http://developer.android.com/reference/android/graphics/Bitmap.html
F. getWindowManager().getDefaultDisplay()
http://developer.android.com/reference/android/view/WindowManager.html
http://developer.android.com/reference/android/view/Display.html
G. powerManager.newWakeLock
http://developer.android.com/reference/android/os/PowerManager.html#newWakeLock(int, java.lang.String)
H.BufferedReader
http://developer.android.com/reference/java/io/BufferedReader.html
I.BufferedWriter
http://developer.android.com/reference/java/io/BufferedWriter.html
J.Thread
http://developer.android.com/reference/java/lang/Thread.html

2、设计屏幕接口Screen和游戏接口Game

package com.badlogic.androidgames.framework;

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();
}
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();
}

3. 实现屏幕类TestScreen和游戏类AndroidGame

package com.badlogic.androidgames.framework;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.List;

import android.graphics.Color;
import android.util.Log;

import com.badlogic.androidgames.framework.Graphics.PixmapFormat;
import com.badlogic.androidgames.framework.Input.KeyEvent;
import com.badlogic.androidgames.framework.Input.TouchEvent;

class TestScreen extends Screen {
    long startTime = System.nanoTime();
    int frames;
    Pixmap bob;
    Pixmap bobAlpha;
    Sound sound;
    Music music;

    public TestScreen(Game game) {
        super(game);
        bob = game.getGraphics().newPixmap("bobrgb888.png", PixmapFormat.RGB565);
        bobAlpha = game.getGraphics().newPixmap("bobargb8888.png", PixmapFormat.ARGB4444);
        music = game.getAudio().newMusic("music.ogg");
        music.setLooping(true);
        music.setVolume(0.5f);
        music.play();
        sound = game.getAudio().newSound("music.ogg");

        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(game.getFileIO().readAsset("test.txt")));
            String text = in.readLine();
            in.close();

            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(game.getFileIO().writeFile("test.txt")));
            out.write("This is a freaking test");
            out.close();

            in = new BufferedReader(new InputStreamReader(game.getFileIO().readFile("test.txt")));
            String text2 = in.readLine();
            in.close();

            Log.d("MrNom", text + ", " + text2 );
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void update(float deltaTime) {
    }

    @Override
    public void present(float deltaTime) {
        Graphics g = game.getGraphics();
        Input inp = game.getInput();
        g.clear(Color.RED);
        g.drawLine(0,0,320, 480, Color.BLUE);
        g.drawRect(20,20,100,100, Color.GREEN);
        g.drawPixmap(bob, 100, 100);
        g.drawPixmap(bobAlpha, 100, 200);
        g.drawPixmap(bob, 200, 200, 0, 0, 64, 64);
        for(int i=0; i < 2; i++) {
            if(inp.isTouchDown(i)) {
                g.drawPixmap(bob, inp.getTouchX(i), inp.getTouchY(i), 0, 0, 64, 64);
            }
        }

        g.drawPixmap(bob, (int)(inp.getAccelX() * 10) + 160 - 16, (int)(inp.getAccelY() * 10) + 240 - 16, 0, 0, 32, 32 );

        List<KeyEvent> keyEvents = inp.getKeyEvents();
        int len = keyEvents.size();
        for(int i = 0; i < len; i++) {
            Log.d("MrNom", keyEvents.get(i).toString());
        }

        List<TouchEvent> touchEvents = inp.getTouchEvents();
        len = touchEvents.size();
        for(int i = 0; i < len; i++) {
            Log.d("MrNom", touchEvents.get(i).toString());
            if(touchEvents.get(i).type == TouchEvent.TOUCH_UP)
                sound.play(1);
        }

        frames++;
        if(System.nanoTime() - startTime > 1000000000l) {
            Log.d("MrNom", "fps: " + frames + ", delta: " + deltaTime);
            frames = 0;
            startTime = System.nanoTime();
        }
    }

    @Override
    public void pause() {
        Log.d("MrNom", "pause");
    }

    @Override
    public void resume() {
        Log.d("MrNom", "resume");
    }

    @Override
    public void dispose() {
        Log.d("MrNom", "dispose");
        music.dispose();
    }
}
package com.badlogic.androidgames.framework.impl;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Window;
import android.view.WindowManager;

import com.badlogic.androidgames.framework.Audio;
import com.badlogic.androidgames.framework.FileIO;
import com.badlogic.androidgames.framework.Game;
import com.badlogic.androidgames.framework.Graphics;
import com.badlogic.androidgames.framework.Input;
import com.badlogic.androidgames.framework.Screen;

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(getAssets());
        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();
    }

    @Override
    public Input getInput() {
        return input;
    }

    @Override
    public FileIO getFileIO() {
        return fileIO;
    }

    @Override
    public Graphics getGraphics() {
        return graphics;
    }

    @Override
    public Audio getAudio() {
        return audio;
    }

    @Override
    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;
    }
}

4.游戏类AndroidGame用到了快速重绘视图类AndroidFastRenderView

package com.badlogic.androidgames.framework.impl;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class AndroidFastRenderView extends SurfaceView implements Runnable {
    AndroidGame game;
    Bitmap framebuffer;
    Thread renderThread = null;
    SurfaceHolder holder;
    volatile boolean running = false;

    public AndroidFastRenderView(AndroidGame game, Bitmap framebuffer) {
        super(game);
        this.game = game;
        this.framebuffer = framebuffer;
        this.holder = getHolder();
    }

    public void resume() {
        running = true;
        renderThread = new Thread(this);
        renderThread.start();
    }      

    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);
        }
    }

    public void pause() {
        running = false;
        while(true) {
            try {
                renderThread.join();
                break;
            } catch (InterruptedException e) {
                // retry
            }
        }
    }
}

5. 另外基于openGL ES的游戏类GLGame(之前的游戏类AndroidGame是基于普通绘图类Graphics)

package com.badlogic.androidgames.framework.impl;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Window;
import android.view.WindowManager;

import com.badlogic.androidgames.framework.Audio;
import com.badlogic.androidgames.framework.FileIO;
import com.badlogic.androidgames.framework.Game;
import com.badlogic.androidgames.framework.Graphics;
import com.badlogic.androidgames.framework.Input;
import com.badlogic.androidgames.framework.Screen;

public abstract class GLGame extends Activity implements Game, Renderer {
    enum GLGameState {
        Initialized,
        Running,
        Paused,
        Finished,
        Idle
    }

    GLSurfaceView glView;
    GLGraphics glGraphics;
    Audio audio;
    Input input;
    FileIO fileIO;
    Screen screen;
    GLGameState state = GLGameState.Initialized;
    Object stateChanged = new Object();
    long startTime = System.nanoTime();
    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);
        glView = new GLSurfaceView(this);
        glView.setRenderer(this);
        setContentView(glView);

        glGraphics = new GLGraphics(glView);
        fileIO = new AndroidFileIO(getAssets());
        audio = new AndroidAudio(this);
        input = new AndroidInput(this, glView, 1, 1);
        PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
    }

    public void onResume() {
        super.onResume();
        glView.onResume();
        wakeLock.acquire();
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        glGraphics.setGL(gl);

        synchronized(stateChanged) {
            if(state == GLGameState.Initialized)
                screen = getStartScreen();
            state = GLGameState.Running;
            screen.resume();
            startTime = System.nanoTime();
        }
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLGameState state = null;

        synchronized(stateChanged) {
            state = this.state;
        }

        if(state == GLGameState.Running) {
            float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
            startTime = System.nanoTime();

            screen.update(deltaTime);
            screen.present(deltaTime);
        }

        if(state == GLGameState.Paused) {
            screen.pause();
            synchronized(stateChanged) {
                this.state = GLGameState.Idle;
                stateChanged.notifyAll();
            }
        }

        if(state == GLGameState.Finished) {
            screen.pause();
            screen.dispose();
            synchronized(stateChanged) {
                this.state = GLGameState.Idle;
                stateChanged.notifyAll();
            }
        }
    }   

    @Override
    public void onPause() {
        synchronized(stateChanged) {
            if(isFinishing())
                state = GLGameState.Finished;
            else
                state = GLGameState.Paused;
            while(true) {
                try {
                    stateChanged.wait();
                    break;
                } catch(InterruptedException e) {
                }
            }
        }
        wakeLock.release();
        glView.onPause();
        super.onPause();
    }    

    public GLGraphics getGLGraphics() {
        return glGraphics;
    }  

    @Override
    public Input getInput() {
        return input;
    }

    @Override
    public FileIO getFileIO() {
        return fileIO;
    }

    @Override
    public Graphics getGraphics() {
        throw new IllegalStateException("We are using OpenGL!");
    }

    @Override
    public Audio getAudio() {
        return audio;
    }

    @Override
    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;
    }

    @Override
    public Screen getCurrentScreen() {
        return screen;
    }
}

本文浅述了“beginning-android-games”书本的相关基础知识和相关类的设计分析,
书本和源码:http://download.csdn.net/detail/yangzhenping/8420261
本篇中的类实现来自“beginning-android-games\ch07-gl-basics”

时间: 2024-08-07 00:13:49

Android游戏之屏幕类TestScreen和游戏类AndroidGame设计的相关文章

cocos2d-x ios游戏开发初认识(五) CCsprite精灵类

这次写一下精灵创建的几种类型: 一.通过文件创建: 在原有的基础上添加如下代码: //一.通过文件创建精灵 CCSprite *bg =CCSprite::create("map.png"); CCSize winSize  =CCDirector::sharedDirector()->getWinSize(); //得到屏幕的尺寸 bg->setPosition(ccp(winSize.width/2, winSize.height/2)); this->addCh

cocos2d-x 如何制作一个类马里奥的横版平台动作游戏 1 献给所有对动作游戏有爱的朋友

本文翻译自国外著名IOS源码教学商业网站raywenderlich 的IOS Game Start Kits三件套之一的Platformer Game/平台动作游戏的前奏曲,另一个是Beat'Em up Game/横版格斗游戏,作者是国外著名游戏开发专家Jake Gundersen,曾参与开发过SFC时代的洛克人X系列. 原文网址: http://www.raywenderlich.com/15230/how-to-make-a-platform-game-like-super-mario-br

android开发学习之路——连连看之游戏逻辑(五)

GameService组件则是整个游戏逻辑实现的核心,而且GameService是一个可以复用的业务逻辑类. (一)定义GameService组件接口 根据前面程序对GameService组件的依赖,程序需要GameService组件包含如下方法.   ·start():初始化游戏状态,开始游戏的方法.     ·Piece[][] getPieces():返回表示游戏状态的Piece[][]数组.     ·boolean hasPieces():判断Pieces[][]数组中是否还剩Piec

游戏中常用到的碰撞检测帮助类

游戏中咱们经常用到碰撞检测,一般的游戏引擎也会自带有自身的检测碰撞类,但有时候不过灵活,这时候我们希望自己可以自定义一些碰撞检测类.tong顶一些啊... import android.graphics.Rect; public class CollisionUtil { /** * 矩形碰撞检测 参数为x,y,width,height * * @param x1 *            第一个矩形的x * @param y1 *            第一个矩形的y * @param w1

【Android】自己动手做个扫雷游戏

1. 游戏规则 扫雷是玩法极其简单的小游戏,点击玩家认为不存在雷的区域,标记出全部地雷所在的区域,即可获得胜利.当点击不包含雷的块的时候,可能它底下存在一个数,也可能是一个空白块.当点击中有数字的块时,游戏会展现当前点击块所包含的数字.当点击空白块时,地图会展开,形成一个大小和形状不规则的图形,该图形的边界是数字块,也可以想成展开的是一个被数字包围着的不规则图形. 1.1 数字生成规则 扫雷游戏中是通过数字来判断雷的位置的,那么,数字的生成规则是什么呢?假设游戏中只有一个雷,那么,他的将被1这个

用cocos2d-html5做的消除类游戏《英雄爱消除》(3)——游戏主界面

游戏主界面,同时也是主程序,包括sprite的生成加入以及游戏状态的控制. 下面同样贴下源码再讲解; /** * Power by html5中文网(html5china.com) * author: jackyWHJ */ var STATE_PLAYING = 0; var STATE_GAMEOVER = 1; var g_sharedGameLayer; var GameLayer = cc.Layer.extend({ _time:0, _timeLabel:null, _timeSt

用cocos2d-html5做的消除类游戏《英雄爱消除》(4)——游戏结束

游戏结束界面: 在前面几个教程中,这个界面的创作所需要的知识点基本我们都讲过了,这里就说下用户数据的缓存吧,也是先来看下源码 /** * Power by html5中文网(html5china.com) * author: jackyWHJ */ var GameOver = cc.Layer.extend({ init:function () { var bRet = false; if (this._super()) { var sp = cc.Sprite.create(s_b05);

即时动作类网络卡牌游戏开发真的很难

我的<凤舞三国>--即时动作策略类网络手机戏从策划到实施如今已经过了16个月了,终于到今年4月(2016年4月)有望出一个内测包给众多期望代理偶家产品的发行们.蓦然回首才发现,偶从2011年3月进入手游开发行业如今已经过去5年了- 不由发出一声感叹:"光阴如梭.人生苦短啊." 我们也像其他众多小游戏公司,在2014年确定了开发三代即时动作类网络卡牌游戏的目标,因为先找到了一个非常好的美术外包合作伙伴,所以当时我们非常有信心8个月能够定搞定该游戏.我们当时认为:就游戏产品开发

Swift游戏实战-跑酷熊猫 02 创建熊猫类

原文:Swift游戏实战-跑酷熊猫 02 创建熊猫类 要点: 如何继承SKSpriteNode :子类必须调用SKSpriteNode的一个指定构造器 init(){ super.init(texture:texture,color:UIColor.whiteColor(),size:size) } 设置场景的背景颜色: self.backgroundColor = SKColor(red:113/255,green:197/255,blue:207,alpha:1) 熊猫类实例化以及定位 @l