楼主: 熊猫儿

[转载] 【Android开发网上的一些重要知识点[经验分享]。。】

[复制链接]
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
101#
 楼主| 发表于 2013-2-1 09:55 | 只看该作者
本帖最后由 熊猫儿 于 2013-2-1 09:57 编辑

public static BitmapDrawable toRoundCorner(BitmapDrawable bitmapDrawable, int pixels) {   
Bitmap bitmap = bitmapDrawable.getBitmap();   
bitmapDrawable = new BitmapDrawable(toRoundCorner(bitmap, pixels));   
return bitmapDrawable;   
}
   
  
public static void saveBefore(String path) {   
BitmapFactory.Options options = new BitmapFactory.Options();   
options.inJustDecodeBounds = true;   
// 获取这个图片的宽和高   
Bitmap bitmap = BitmapFactory.decodeFile(path, options); // 此时返回bm为空   
options.inJustDecodeBounds = false;   
// 计算缩放比   
int be = (int)(options.outHeight / (float)200);   
if (be <= 0)   
be = 1;   
options.inSampleSize = 2; // 图片长宽各缩小二分之一   
// 重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦   
bitmap = BitmapFactory.decodeFile(path, options);   
int w = bitmap.getWidth();   
int h = bitmap.getHeight();   
System.out.println(w + " " + h);   
// savePNG_After(bitmap,path);   
saveJPGE_After(bitmap, path);   
}
   
  
public static void savePNG_After(Bitmap bitmap, String name) {   
File file = new File(name);   
try {   
FileOutputStream out = new FileOutputStream(file);   
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)) {   
out.flush();   
out.close();   
}   
} catch (FileNotFoundException e) {   
e.printStackTrace();   
} catch (IOException e) {   
e.printStackTrace();   
}   
}
   
  
public static void saveJPGE_After(Bitmap bitmap, String path) {   
File file = new File(path);   
try {   
FileOutputStream out = new FileOutputStream(file);   
if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {   
out.flush();   
out.close();   
}   
} catch (FileNotFoundException e) {   
e.printStackTrace();   
} catch (IOException e) {   
e.printStackTrace();   
}   
}
   

public static Bitmap createBitmapForWatermark(Bitmap src, Bitmap watermark) {   
if (src == null) {   
return null;   
}   
int w = src.getWidth();   
int h = src.getHeight();   
int ww = watermark.getWidth();   
int wh = watermark.getHeight();   
// create the new blank bitmap   
Bitmap newb = Bitmap.createBitmap(w, h, Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图   
Canvas cv = new Canvas(newb);   
// draw src into   
cv.drawBitmap(src, 0, 0, null);// 在 0,0坐标开始画入src   
// draw watermark into   
cv.drawBitmap(watermark, w - ww + 5, h - wh + 5, null);// 在src的右下角画入水印   
// save all clip   
cv.save(Canvas.ALL_SAVE_FLAG);// 保存   
// store   
cv.restore();// 存储   
return newb;   
}
   
  
public static Bitmap potoMix(int direction, Bitmap... bitmaps) {   
if (bitmaps.length <= 0) {   
return null;   
}   
if (bitmaps.length == 1) {   
return bitmaps[0];   
}   
Bitmap newBitmap = bitmaps[0];   
// newBitmap = createBitmapForFotoMix(bitmaps[0],bitmaps[1],direction);   
for (int i = 1; i < bitmaps.length; i++) {   
newBitmap = createBitmapForFotoMix(newBitmap, bitmaps, direction);   
}   
return newBitmap;   
}   
  
private static Bitmap createBitmapForFotoMix(Bitmap first, Bitmap second, int direction) {   
if (first == null) {   
return null;   
}   
if (second == null) {   
return first;   
}   
int fw = first.getWidth();   
int fh = first.getHeight();   
int sw = second.getWidth();   
int sh = second.getHeight();   
Bitmap newBitmap = null;   
if (direction == LEFT) {   
newBitmap = Bitmap.createBitmap(fw + sw, fh > sh ? fh : sh, Config.ARGB_8888);   
Canvas canvas = new Canvas(newBitmap);   
canvas.drawBitmap(first, sw, 0, null);   
canvas.drawBitmap(second, 0, 0, null);   
} else if (direction == RIGHT) {   
newBitmap = Bitmap.createBitmap(fw + sw, fh > sh ? fh : sh, Config.ARGB_8888);   
Canvas canvas = new Canvas(newBitmap);   
canvas.drawBitmap(first, 0, 0, null);   
canvas.drawBitmap(second, fw, 0, null);   
} else if (direction == TOP) {   
newBitmap = Bitmap.createBitmap(sw > fw ? sw : fw, fh + sh, Config.ARGB_8888);   
Canvas canvas = new Canvas(newBitmap);   
canvas.drawBitmap(first, 0, sh, null);   
canvas.drawBitmap(second, 0, 0, null);   
} else if (direction == BOTTOM) {   
newBitmap = Bitmap.createBitmap(sw > fw ? sw : fw, fh + sh, Config.ARGB_8888);   
Canvas canvas = new Canvas(newBitmap);   
canvas.drawBitmap(first, 0, 0, null);   
canvas.drawBitmap(second, 0, fh, null);   
}   
return newBitmap;   
}   
  
public static Bitmap createBitmapBySize(Bitmap bitmap,int width,int height)   
{   
return Bitmap.createScaledBitmap(bitmap, width, height, true);   
}   
  
public static Bitmap drawableToBitmapByBD(Drawable drawable) {   
BitmapDrawable bitmapDrawable = (BitmapDrawable)drawable;   
return bitmapDrawable.getBitmap();   
}   
  
public static Drawable bitmapToDrawableByBD(Bitmap bitmap) {   
Drawable drawable = new BitmapDrawable(bitmap);   
return drawable;   
}   
  
public static Bitmap bytesToBimap(byte[] b) {   
if (b.length != 0) {   
return BitmapFactory.decodeByteArray(b, 0, b.length);   
} else {   
return null;   
}   
}   
  
public static byte[] bitmapToBytes(Bitmap bm) {   
ByteArrayOutputStream baos = new ByteArrayOutputStream();   
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);   
return baos.toByteArray();   
}   
}

文章出处:
本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-11/48110.htm

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
102#
 楼主| 发表于 2013-2-1 09:56 | 只看该作者
Android游戏开发之一】设置全屏以及绘画简单的图形
(2013-01-22 14:16:16)
转载▼
标签:
android
学习笔记
it
分类: Android游戏开发学习笔记

转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/263.html
这一章简单讲述些简单的Android-UI:

直接上代码:
package com.himi;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity {
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        //隐去电池等图标和一切修饰部分(状态栏部分)
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 隐去标题栏(程序的名字)
        setContentView(new MyView(this));
    }
}
注意: 隐去标题(应用的名字) 此设定必须要写在setContentView之前,否则会有异常!

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
103#
 楼主| 发表于 2013-2-1 09:56 | 只看该作者
对于设置全屏,主要就两点:

一点是设置隐去状态栏部分,包括电池等图标,第二点无疑就是把我们应用的名字也隐去不显示,这样一来就全屏了。

package com.himi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;
public class MyView extends View {
    private Paint paint ;
    public MyView(Context context) {
        super(context);
        paint = new Paint();
        paint.setAntiAlias(true);//设置画笔无锯齿(如果不设置可以看到效果很差)
        this.setKeepScreenOn(true);//设置背景常亮
        paint.setColor(Color.RED);
    }
    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);//设置刷屏颜色
        Rect rect = new Rect(30,30,50,50); //这里最后两个参数不是宽高、而是矩形右下角的坐标
        canvas.drawRect(rect, paint);
        RectF rectF = new RectF(70f,30f,90f,90f);//RectF 只是矩形 float形式 只是跟Rect精确度不一样
        canvas.drawArc(rectF, 0, 360, true, paint);
        canvas.drawCircle(150, 30, 20, paint);//这也是画圆第三个参数为半径
        float[] points =new float[]{200f,10f,200f,40f,300f,30f,400f,70f};
        canvas.drawLines(points, paint);
//      canvas.drawLines(points, 1, 4, paint);//选取特定点数组中两点来画出一条直线
        canvas.drawText("Himi", 230, 30, paint);
    }
}
设置横竖屏也可以在AndroidManifest.xml中定义:
android:theme=”@android:style/Theme.NoTitleBar” 隐去标题栏android:theme=”@android:style/Theme.NoTitleBar.Fullscreen” 隐去状态栏

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
104#
 楼主| 发表于 2013-2-1 09:56 | 只看该作者
【Android游戏开发之二】剖析游戏开发用view还是surfaceView ?!
(2013-01-22 14:26:20)
转载▼
标签:
android
学习笔记
游戏
it
分类: Android游戏开发学习笔记

转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/295.html
在Android游戏当中充当主要的除了控制类外就是显示类,在J2ME中我们用Display和Canvas来实现这些,而Google Android中涉及到显示的为view类,Android游戏开发中比较重要和复杂的就是显示和游戏逻辑的处理。

这里我们说下android.view.View和android.view.SurfaceView。SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView,到底有哪些优势呢? SurfaceView可以控制表面的格式,比如大小,显示在屏幕中的位置,最关键是的提供了SurfaceHolder类,使用getHolder方法获取,相关的有Canvas lockCanvas()
Canvas lockCanvas(Rect dirty) 、void removeCallback(SurfaceHolder.Callback callback)、void unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制,而在SurfaceHolder.Callback 接口回调中可以通过重写下面方法实现。

使用的SurfaceView的时候,一般情况下要对其进行创建,销毁,改变时的情况进行监视,这就要用到 SurfaceHolder.Callback.
class XxxView extends SurfaceView implements SurfaceHolder.Callback {

public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//看其名知其义,在surface的大小发生改变时激发
public void surfaceCreated(SurfaceHolder holder){}
//同上,在创建时激发,一般在这里调用画图的线程。
public void surfaceDestroyed(SurfaceHolder holder) {}
//同上,销毁时激发,一般在这里将画图的线程停止、释放。

}

对于Surface相关的,Android底层还提供了GPU加速功能,所以一般实时性很强的应用中主要使用SurfaceView而不是直接从View构建,同时后来做android 3d OpenGL中的GLSurfaceView也是从该类实现。

SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。
那么在UI的主线程中更新画面可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。
当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。

所以基于以上,根据游戏特点,一般分成两类。

1 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

2 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。

3.Android中的SurfaceView类就是双缓冲机制。因此,开发游戏时尽量使用SurfaceView而不要使用View,这样的话效率较高,而且SurfaceView的功能也更加完善。

考虑以上几点,所以我一直都选用 SurfaceView 来进行游戏开发。

那么在以后源码实例中,我都会以继承surfaceView框架来进行演示。下一章将详细剖析surfaceview ,以及附上本人写的游戏开发架构

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
105#
 楼主| 发表于 2013-2-1 09:58 | 只看该作者

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
106#
 楼主| 发表于 2013-2-2 18:10 | 只看该作者
【Android游戏开发之三】详细剖析 SurfaceView ! Callback以及SurfaceHolder!!
(2013-01-22 15:16:37)
转载▼
标签:
android
游戏
学习笔记
it
分类: Android游戏开发学习笔记

转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/296.html
各位童鞋请你们注意:surfaceview中确实有 onDraw这个方法,但是你surfaceview不会自己去调用!!!

  而我代码中的ondraw() 也好 draw() 也好,都是我自己定义的一个方法。。。放在线程中不断调用的,一定要注意!!

之前我们对view和surfaceview 做了比较和取舍,最后我们发现surfaceview更加的适合运作与游戏开发中,那么下面就让我们来看看这个surfaceview的结构吧;

先上一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.himi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
import android.view.animation.Animation;
public class MySurfaceView extends SurfaceView implements Callback, Runnable {// 备注1
    private SurfaceHolder sfh;
    private Thread th;
    private Canvas canvas;
    private Paint paint;
    private int ScreenW, ScreenH;
    public MySurfaceView(Context context) {
        super(context);
        th = new Thread(this);
        sfh = this.getHolder();
        sfh.addCallback(this); // 备注1
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        this.setKeepScreenOn(true);// 保持屏幕常亮
    }

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
107#
 楼主| 发表于 2013-2-2 18:10 | 只看该作者
@Override
    public void startAnimation(Animation animation) {
        super.startAnimation(animation);
    }
    public void surfaceCreated(SurfaceHolder holder) {
        ScreenW = this.getWidth();// 备注2
        ScreenH = this.getHeight();
        th.start();
    }
    private void draw() {
        try {
            canvas = sfh.lockCanvas(); // 得到一个canvas实例
            canvas.drawColor(Color.WHITE);// 刷屏
            canvas.drawText("Himi", 100, 100, paint);// 画文字文本
            canvas.drawText("这就是简单的一个游戏框架", 100, 130, paint);
        } catch (Exception ex) {
        } finally { // 备注3
            if (canvas != null)
                sfh.unlockCanvasAndPost(canvas);  // 将画好的画布提交
        }
    }
    public void run() {
        while (true) {
            draw();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }
}
代码很简单,我们继承继承surfaceview类,并且使用回调callback接口以及线程runnable接口。那么这里我简单的说下Callback接口和SurfaceHolder 类的作用;



//备注1

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
108#
 楼主| 发表于 2013-2-2 18:10 | 只看该作者
callback接口:

只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口:

surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。
surfaceChanged(SurfaceHolder holder, int format, int width,int height):当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。
SurfaceHolder 类:

它是一个用于控制surface的接口,它提供了控制surface 的大小,格式,上面的像素,即监视其改变的。

SurfaceView的getHolder()函数可以获取SurfaceHolder对象,Surface 就在SurfaceHolder对象内。虽然Surface保存了当前窗口的像素数据,但是在使用过程中是不直接和Surface打交道的,由SurfaceHolder的Canvas lockCanvas()或则Canvas lockCanvas()函数来获取Canvas对象,通过在Canvas上绘制内容来修改Surface中的数据。如果Surface不可编辑或则尚未创建调用该函数会返回null,在 unlockCanvas() 和 lockCanvas()中Surface的内容是不缓存的,所以需要完全重绘Surface的内容,为了提高效率只重绘变化的部分则可以调用lockCanvas(Rect rect)函数来指定一个rect区域,这样该区域外的内容会缓存起来。在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、修改)。

// 备注2

我没有在该surfaceview的初始化函数中将其 ScreenW 与 ScreenH 进行赋值,这里要特别注意,如果你在初始化调用ScreenW = this.getWidth();和ScreenH = this.getHeight();那么你将得到很失望的值全部为0;原因是和接口Callback接口机制有关,当我们继承callback接口会重写它的surfaceChanged()、surfaceCreated()、surfaceDestroyed(),这几个函数当surfaceCreated()被执行的时候,真正的view才被创建,也就是说之前得到的值为0 ,是因为初始化会在surfaceCreated()方法执行以前执行,view没有的时候我们去取屏幕宽高肯定是0,所以这里要注意这一点;

//备注3

这里我把draw的代码都try起来,主要是为了当画的内容中一旦抛出异常了,那么我们也能在finally中执行该操作。这样当代码抛出异常的时候不会导致Surface出去不一致的状态。

其实这就是一个简单的游戏架构了,当然还少了按键处理,声音播放等等,这些我后续会写出相关的学习文章。对于surfaceview的介绍差不多就介绍到这里了,其中的理解是看了别人的文章和自己的理解、当然可能理解的会有些偏差,但是我想不会太离谱呵呵。

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
109#
 楼主| 发表于 2013-2-2 18:11 | 只看该作者
Android游戏开发之四】基础的Android 游戏框架(一个游戏角色在屏幕行走的demo)
(2013-01-22 15:17:36)
转载▼
标签:
android
学习笔记
游戏
it
分类: Android游戏开发学习笔记

其实上一篇分析surfaceview的文章就是一个简单的游戏框架了,当然这里再强调一下,简单的游戏框架,以不要高手们不要乱喷哦  ~

这个Demo是给群里一童鞋写的一个对图片操作以及按键处理,游戏简单框架的一个demo,这里放出给大家分享~

package com.himi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
    private Thread th = new Thread(this);
    private SurfaceHolder sfh;
    private int SH, SW;
    private Canvas canvas;
    private Paint p;
    private Paint p2;
    private Resources res;
    private Bitmap bmp;
    private int bmp_x = 100, bmp_y = 100;
    private boolean UP, DOWN, LEFT, RIGHT;
    private int animation_up[] = { 3, 4, 5 };
    private int animation_down[] = { 0, 1, 2 };
    private int animation_left[] = { 6, 7, 8 };
    private int animation_right[] = { 9, 10, 11 };
    private int animation_init[] = animation_down;
    private int frame_count;
    public MySurfaceView(Context context) {
        super(context);
        this.setKeepScreenOn(true);
        res = this.getResources();
        bmp = BitmapFactory.decodeResource(res, R.drawable.enemy1);
        sfh = this.getHolder();
        sfh.addCallback(this);
        p = new Paint();
        p.setColor(Color.YELLOW);
        p2 = new Paint();
        p2.setColor(Color.RED);
        p.setAntiAlias(true);
        setFocusable(true);  //备注1
    }
    public void surfaceCreated(SurfaceHolder holder) {
        SH = this.getHeight();
        SW = this.getWidth();
        th.start();
    }
    public void draw() {
        canvas = sfh.lockCanvas();
        canvas.drawRect(0, 0, SW, SH, p);   //备注2
        canvas.save();   //备注3
        canvas.drawText("Himi", bmp_x-2, bmp_y-10, p2);
        canvas.clipRect(bmp_x, bmp_y, bmp_x + bmp.getWidth() / 13, bmp_y+bmp.getHeight());
        if (animation_init == animation_up) {
            canvas.drawBitmap(bmp, bmp_x - animation_up[frame_count] * (bmp.getWidth() / 13), bmp_y, p);
        } else if (animation_init == animation_down) {
            canvas.drawBitmap(bmp, bmp_x - animation_down[frame_count] * (bmp.getWidth() / 13), bmp_y, p);
        } else if (animation_init == animation_left) {
            canvas.drawBitmap(bmp, bmp_x - animation_left[frame_count] * (bmp.getWidth() / 13), bmp_y, p);
        } else if (animation_init == animation_right) {
            canvas.drawBitmap(bmp, bmp_x - animation_right[frame_count] * (bmp.getWidth() / 13), bmp_y, p);
        }
        canvas.restore();  //备注3
        sfh.unlockCanvasAndPost(canvas);
    }
    public void cycle() {
        if (DOWN) {
            bmp_y += 5;
        } else if (UP) {
            bmp_y -= 5;
        } else if (LEFT) {
            bmp_x -= 5;
        } else if (RIGHT) {
            bmp_x += 5;
        }
        if (DOWN || UP || LEFT || RIGHT) {
            if (frame_count < 2) {
                frame_count++;
            } else {
                frame_count = 0;
            }
        }
        if (DOWN == false && UP == false && LEFT == false && RIGHT == false) {
            frame_count = 0;
        }
    }
    @Override
    public boolean onKeyDown(int key, KeyEvent event) {
        if (key == KeyEvent.KEYCODE_DPAD_UP) {
            if (UP == false) {
                animation_init = animation_up;
            }
            UP = true;
        } else if (key == KeyEvent.KEYCODE_DPAD_DOWN) {
            if (DOWN == false) {
                animation_init = animation_down;
            }
            DOWN = true;
        } else if (key == KeyEvent.KEYCODE_DPAD_LEFT) {
            if (LEFT == false) {
                animation_init = animation_left;
            }
            LEFT = true;
        } else if (key == KeyEvent.KEYCODE_DPAD_RIGHT) {
            if (RIGHT == false) {
                animation_init = animation_right;
            }
            RIGHT = true;
        }
        return super.onKeyDown(key, event);
    }

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
110#
 楼主| 发表于 2013-2-2 18:11 | 只看该作者
@Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (DOWN) {
            DOWN = false;
        } else if (UP) {
            UP = false;
        } else if (LEFT) {
            LEFT = false;
        } else if (RIGHT) {
            RIGHT = false;
        }
        return super.onKeyUp(keyCode, event);
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            draw();
            cycle();
            try {
                Thread.sleep(100);
            } catch (Exception ex) {
            }
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    }
}
备注1

此方法是用来响应按键!如果是自己定义一个继承自View的类,重新实现onKeyDown方法后,只有当该View获得焦点时才会调用onKeyDown方法,Actvity中的onKeyDown方法是当所有控件均没有处理该按键事件时,才会调用.

备注2

   这里也是对屏幕进行刷屏操作,其实这也只是一种,之前文章里我也用到drawRGB的方法同样实现,当然也可以用fillRect等来刷屏。

那么这里我想说下,在继承view中,因为onDraw方法是系统自动调用的,不像在surfaceview这里这样去在run里面自己去不断调用,在view中我们可以抵用 invalidate()/postInvalidate() 这两种方法实现让系统调用onDraw方法,这里也是和surfaceview中的不同之一!

备注3

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表