您的位置:首页 > 移动开发 > Android开发

android手机游戏之二线程绘图

2011-04-06 13:04 417 查看
在之前我写了一个简单的手工绘图,现在接下来继续讲解下加了线程绘图使界面更加的丰富多彩..

首先是目录结构



步骤一:建立AFootballactivity主类。二:建立CustomGallery自定义类(这个拿来用就可以了)。三:WelcomeView类.四WelcomeThread类。五:WelcomeDrawThread.

材料图片部分:(将一下图片分别放入drawable-mdpi文件)















图片名称:p1.jpg , p2.jpg ,p3.jpg,welcome.jpg,club_4.png,club_5.png,club_6.png。以上工作全部准备好了就进入代码部分.

1.AFootballActivity类

package com.AFootball;

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class AFootballActivity extends Activity {
View current;
WelcomeView welcome;
int keyState = 0;
boolean wantSound = true; // 是否播放声音标志位
MediaPlayer mpWelcomeMusic; // 游戏开始前的欢迎音乐
Rect rectGallery; // 表示Gallery的矩形框
int[] imageIDs = { // 存放8个俱乐部的图片ID
R.drawable.club_1, R.drawable.club_2, R.drawable.club_3, R.drawable.club_4,
R.drawable.club_5, R.drawable.club_6, R.drawable.club_7,
R.drawable.club_8 };
int clubID = imageIDs[0]; // 记录用户选择的俱乐部的ID

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initWelcomeSound(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
welcome = new WelcomeView(this);// 将屏幕切到欢迎界面
setContentView(welcome);
current = welcome;
if (wantSound && mpWelcomeMusic != null) {
mpWelcomeMusic.start();
}
initRects();// 初始化用于匹配点击事件的矩形框
}

// 方法:初始化欢迎界面的声音
private void initWelcomeSound(Context context) {
mpWelcomeMusic = MediaPlayer.create(context, R.raw.music);

}

// 方法:初始化矩形框
private void initRects() {

rectGallery = new Rect(10, 10, 310, 110);
}

}


2.CustomGallery类

package com.AFootball;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

public class CustomGallery {
Bitmap[] bmpContent; // Gallery要显示的内容图片
int length; // Gallery要显示的图片数组大小
int currIndex; // 当前被显示的图片的索引
int startX; // 绘制Gallery时其左上角在屏幕中的X坐标
int startY; // 绘制Gallery时其左上角在屏幕中的Y坐标
int cellWidth; // 每个图片的宽度
int cellHeight; // 每个图片的高度

// 构造器,初始化主要成员变量
public CustomGallery(int startX, int startY, int cellWidth, int cellHeight) {
this.startX = startX;
this.startY = startY;
this.cellWidth = cellWidth;
this.cellHeight = cellHeight;
}
public void setContent(Bitmap[] bmpContent) { // 方法:为Gallery设置显示内容
this.bmpContent = bmpContent;
this.length = bmpContent.length;
}
public void setCurrent(int index) { // 方法:设置当前显示的图片
if (index >= 0 && index < length) {
this.currIndex = index;
}
}
public void drawGallery(Canvas canvas, Paint paint) {// 方法:绘制自己
// 创建背景的画笔
Paint paintBack = new Paint();
paintBack.setARGB(220, 99, 99, 99);
// 创建边框的画笔
Paint paintBorder = new Paint();
paintBorder.setStyle(Paint.Style.STROKE);
paintBorder.setStrokeWidth(4.5f);
paintBorder.setARGB(255, 150, 150, 150);
// 画左边的图片
if (currIndex > 0) {
canvas.drawRect(startX, startY, startX + cellWidth, startY
+ cellHeight, paintBack); // 背景
canvas.drawBitmap(bmpContent[currIndex - 1], startX, startY, paint); // 贴图片
canvas.drawRect(startX, startY, startX + cellWidth, startY
+ cellHeight, paintBorder); // 画左边图片的边框
}
// 画被选中的图片
canvas.drawRect(startX + cellWidth, startY, startX + cellWidth * 2,
startY + cellHeight, paintBack); // 背景
canvas.drawBitmap(bmpContent[currIndex], startX + cellWidth, startY,
paint); // 贴图片
// 画右边的图片
if (currIndex < length - 1) {
canvas.drawRect(startX + cellWidth * 2, startY, startX + cellWidth
* 3, startY + cellHeight, paintBack); // 背景
canvas.drawBitmap(bmpContent[currIndex + 1],
startX + cellWidth * 2, startY, paint); // 贴图片
paintBorder.setARGB(255, 150, 150, 150); // 画右边图片的边框
canvas.drawRect(startX + cellWidth * 2, startY, startX + cellWidth
* 3, startY + cellHeight, paintBorder);
}
// 画选中的边框
paintBorder.setColor(Color.RED);
canvas.drawRect(startX + cellWidth, startY, startX + cellWidth * 2,
startY + cellHeight, paintBorder);
}
public void galleryTouchEvnet(int x, int y) { // 方法:Gallery的处理点击事件方法
if (x > startX && x < startX + cellWidth) { // 点在了左边那张图片
if (currIndex > 0) { // 判断当前图片的左边还有没有图片
currIndex--; // 设置当前图片为左边的图片
}
} else if (x > startX + cellWidth * 2 && x < startX + cellWidth * 3) { // 点在了右边那张图片
if (currIndex < length - 1) { // 判断当前图片的右边还有没有图片
currIndex++; // 设置当前图片为右边的图片
}
}
}
}


3.WelcomeView类

package com.AFootball;

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.Matrix;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class WelcomeView extends SurfaceView implements SurfaceHolder.Callback {
WelcomeThread wt; // 后台修改数据线程
WelcomeDrawThread wdt; // 后台重绘线程
int index = 0; // 开场3个动画帧的索引
int status = -1; // 0代表足球动画,1代表背景转进来,2代表全部渐显,3代表待命
int alpha = 255; // 透明度,初始为255,即不透明
int[] layout = { 3, 3, 4 }; // 玩家球员的站位数组,3个值分别代表前场、中场、后场
CustomGallery cg; // 自定义的Gallery类,用于选择俱乐部logo
Bitmap[] bmpGallery; // 存储Gallery对象要显示的内容
Bitmap[] bmpAnimaition; // 存储欢迎动画帧的数组
Bitmap bmpBack; // 背景图片
Matrix matrix; // Matrix对象,用来旋转背景图
AFootballActivity father; // Activity的引用

public WelcomeView(AFootballActivity father) {
super(father);
this.father = father;
getHolder().addCallback(this);
initBitmap(father); // 初始化图片
matrix = new Matrix(); // 创建Matrix对象
cg = new CustomGallery(10, 10, 100, 100); // 创建CustomGallery对象
cg.setContent(bmpGallery); // 为CustomGallery对象设置显示内容
cg.setCurrent(2);
wt = new WelcomeThread(this); // 创建WelcomeThread对象
wdt = new WelcomeDrawThread(this, getHolder()); // 创建WelcomeDrawThread对象
status = 0; // 设置初始状态值为0
}
private void initBitmap(Context context) {
Resources r = context.getResources(); // 获取Resources对象
bmpBack = BitmapFactory.decodeResource(r, R.drawable.welcome); // 创建背景图片
bmpAnimaition = new Bitmap[3]; // 创建动画数组
bmpAnimaition[0] = BitmapFactory.decodeResource(r, R.drawable.p1);
bmpAnimaition[1] = BitmapFactory.decodeResource(r, R.drawable.p2);
bmpAnimaition[2] = BitmapFactory.decodeResource(r, R.drawable.p3);
// 初始化Gallery的图片资源
bmpGallery = new Bitmap[8]; // 创建自定义Gallery要显示的内容图片数组
for (int i = 0; i < bmpGallery.length; i++) {
bmpGallery[i] = BitmapFactory.decodeResource(r, father.imageIDs[i]);
}

}

public void doDraw(Canvas canvas) {// 方法:用于根据不同状态绘制屏幕
Paint paint = new Paint(); // 创建画笔
switch (status) {
case 0:// 显示3个动画帧
canvas.drawBitmap(bmpAnimaition[index], 0, 0, null);
break;
case 1:// 背景图片旋转而进
canvas.drawColor(Color.BLACK); // 清屏幕
Bitmap bmpTemp = Bitmap.createBitmap(bmpBack, 0, 0,
bmpBack.getWidth(), bmpBack.getHeight(), matrix, true);// 旋转背景图
canvas.drawBitmap(bmpTemp, 0, 0, null); // 绘制背景图
break;
case 2:// 全场透明
case 3:// 全场待命--------------这两个画法一样,只是透明度不同
canvas.drawColor(Color.BLACK); // 清屏幕
paint.setAlpha(alpha); // 设置透明度
canvas.drawBitmap(bmpBack, 0, 0, paint);// 画背景
cg.drawGallery(canvas, paint); // 画自定义的Gallery

break;
}
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!wt.isAlive()) { // 启动后台修改数据线程
wt.start();
}
if (!wdt.isAlive()) { // 启动后台绘制线程
wdt.start();
}

}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (wt.isAlive()) { // 停止后台修改数据线程
wt.isWelcoming = false;
}
if (wdt.isAlive()) { // 停止后台绘制线程
wdt.flag = false;
}
}

}


4.WelcomeThread类

package com.AFootball;

public class WelcomeThread extends Thread {
WelcomeView father; // WelcomeView对象的引用
boolean isWelcoming = false; // 线程执行标志位
float rotateAngle = 60; // 旋转角度
int rotateCounter = 0; // 旋转计数器
int animationCounter = 0; // 换帧计数器
int sleepSpan = 150; // 休眠时间

// 构造器:初始化主要成员变量
public WelcomeThread(WelcomeView father) {
this.father = father;
isWelcoming = true;
}

public void run() {// 线程的执行方法
while (isWelcoming) {
switch (father.status) {// 获取现在的状态
case 0: // 该状态为3个图片轮流显示
animationCounter++; // 换帧计数器自加
if (animationCounter == 4) { // 计数器达到4时换帧
father.index++; // 开场3个动画帧的索引
if (father.index == 3) { // 判断是否播放完毕所有帧
father.status = 1; // 转入下一状态
}
animationCounter = 0; // 清空计数器
}
break;
case 1:// 该状态为背景图片旋转着进来
father.matrix.postRotate(rotateAngle); // 旋转角度
rotateCounter++; // 计数器自加
if (rotateCounter == 6) {// 旋转计数器到了
father.status = 2;// 设置状态
father.alpha = 0; // 设置alpha值,用于菜单渐显
}
break;
case 2:// 该状态为菜单渐显菜单渐显 , alpha透明度,初始为255,即不透明
father.alpha += 51; // alpha值增加
if (father.alpha >= 255) {
father.status = 3;// 进入待命状态,此状态玩家可以选择菜单选项
}
break;
case 3: // 如果遇到了待命状态,就自己把自己关闭
this.isWelcoming = false;
break;
}
try {
Thread.sleep(sleepSpan); // 休眠一段时间
} catch (Exception e) {
e.printStackTrace(); // 捕获并打印异常
}
}
}
}


5.WelcomeDrawThread

package com.AFootball;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class WelcomeDrawThread extends Thread {
WelcomeView father; // WelcomeView对象的引用
SurfaceHolder surfaceHolder; // WelcomeView对象的SurfaceHolder
int sleepSpan = 100; // 休眠时间
boolean flag; // 线程执行标志位

// 构造器:初始化主要的成员变量
public WelcomeDrawThread(WelcomeView father, SurfaceHolder surfaceHolder) {
this.father = father;
this.surfaceHolder = surfaceHolder;
this.flag = true;
}

// 方法:线程执行方法
public void run() {
Canvas canvas = null; // 创建一个Canvas对象
while (flag) {
try {
canvas = surfaceHolder.lockCanvas(null); // 为画布加锁
synchronized (surfaceHolder) {
father.doDraw(canvas); // 重新绘制屏幕
}
} catch (Exception e) {
e.printStackTrace(); // 捕获异常并打印
} finally {
if (canvas != null) {// 释放画布并将其传回
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
try {
Thread.sleep(sleepSpan); // 休眠一段时间
} catch (Exception e) {
e.printStackTrace(); // 捕获异常并打印
}
}
}
}


最后的效果图:



5个类以建立完成...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: