站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2ME 专题制作是男人就撑30秒

制作是男人就撑30秒

摘要: 制作是男人就撑30秒
作者:


我们前面已经谈到了,应用程序框架,游戏循环,双缓冲区和按键的处理等内容。如果再加上低级界面处理函数和声音的处理,那么我们的教程也就基本完整了。但是今天我们先不谈后面的两部分内容。为什么呢?对于游戏这样一个以界面、图像来表现得艺术形式怎么能抛开最重要的两项呢?我的回答是,虽然这几项内容都是游戏开发不可缺少的部分,但是前面的内容基本上可以脱离开发环境,并且可以提升到游戏的理论中去的,是一种共性的东西(只是在这里我们以J2ME平台来讲解了)。而界面的处理等内容则对平台依赖性太大,也是所有开发游戏的人都会注意到的内容。所以我将它们分开来讲解了。
我们先来运用前面的知识,和没谈到的低级界面处理函数来完成一个简单的游戏,有了一个较为完整的游戏框架后,我们就可以思考更生层次的内容了,因为我们已经真正的跨入了游戏开发的门槛了,学习和开发会更有的放矢,更有效率。
废话少说,我们还是直接切入正题。为什么要开发这样一个游戏呢?思考一下该游戏的根本:就是移动自己控制的主角,来躲过从四面八方射过来的子弹,看谁撑的时间长。明白的原理,让我们放开自己的思维,想一想他的具体实现吧。

第一步控制主角的移动。

如果你对主角的形象不是要求太高的话,我们可以将逐句换成一个方块,(呵呵,又回到方块了,)这样你是否有印象呢?对了那就是我们前面完成过的《j2mej2me 键盘输入》键盘输入,地址如下:http://www.j2mefans.com/blog/trackback.asp?tbID=61
也就是说我们可以在该文的基础上进行开发了。

第二步添加子弹。

对于子弹,我们当然也可以使用小方块来代表了。所以我们也要使用(X,Y)坐标表示他的位置,用XSPEED,YSPEED分别记录他的方向和移动速度(如果不清楚地话可以复习以下三角函数,或关于直线斜率的问题)。
所以,我们要在代码中添加下面语句:
//控制子弹
private int[] x1,y1;//纪录子弹的位置
private int[] x1speed,y1speed;//纪录子弹的速度和方向
当然还需要控制子弹的数目:
//子弹数目
private static final int zidanshu=25;

然后,我们在游戏开始运行处的Start函数中添加初始化代码:
Random r = new Random();
//为前面的数组变量分配内存
x1=new int[zidanshu];
y1=new int[zidanshu];
x1speed= new int[zidanshu];
y1speed=new int[zidanshu];
//为子弹随机分配初始位置和速度,这里为了简单我们只是简单的设置子弹从左上角出现
for(int i=0;i{
x1[i]= r.nextInt()%5+1;
y1[i]= 0;
x1speed[i]=r.nextInt()%3+2;
y1speed[i]=r.nextInt()%3+3;
}

在游戏循环中不断的更新子弹的位置:
public void run() {
// 动画线程开始后运行

// 主游戏循环
while (!sleeping) {
//更新游戏中的数据变量
update();
//更新屏幕显示
repaint();
//线程休眠
try {
Thread.sleep(frameDelay);
}
catch (InterruptedException ie) {}
}
}
现在的重点就转移到了update函数中了。我们要在其中使用每一个子弹的位置加上速度,进而得到他的新位置。下面是代码:
//在这里更新游戏中的数据变量
private void update()
{
for(int i=0;i {
x1[i]+=x1speed[i];
y1[i]+=y1speed[i];

if (x1[i] < 0)
x1[i]=getWidth();
if(x1[i]>getWidth())
x1[i]=0;
if (y1[i] < 0)
y1[i]=getHeight();
if(y1[i]>getHeight())
y1[i]=0;
}

}

别着急,还差最后一步。就是根据新位置显示子弹了:
private void renderWorld()
{
Graphics osg = offScreenBuffer.getGraphics();

//绘制黑色背景
osg.setColor(0);
osg.fillRect(0,0,getWidth(),getHeight());

//绘制方块
osg.setColor(255,0,0);
osg.fillRect(x,y,4,4);

//绘制子弹
for(int i=0;i {
osg.setColor(255,255,255);
osg.fillRect(x1[i],y1[i],2,2);
}
}
这回运行以下程序,子弹移动了吧!只是子弹打不到主角,这就需要下面我们讲到的游戏碰撞:(这里只是简单的注释一下,我们将在以后的文章里详细的谈到这一部分内容)
//这里检查主角和子弹的碰撞
private void pengzhuang()
{
for(int i=0;i {
if((x1[i]>x && x1[i]<(x+4))&&(y1[i]>y && y1[i]<(y+4)))
{

startime= System.currentTimeMillis()-startime;
isend=true;
}
}
}
将这段代码添加到游戏循环中的更新数据和显示界面之间。
最后就是游戏结局的现实。在碰撞函数中我们看到了。
if((x1[i]>x && x1[i]<(x+4))&&(y1[i]>y && y1[i]<(y+4)))
{

startime= System.currentTimeMillis()-startime;
isend=true;
}
其中,isend=true;表示游戏结束。在renderWorld函数中根据isend的值来显示相应的内容:
private void renderWorld()
{
Graphics osg = offScreenBuffer.getGraphics();
if(!isend)
{


//绘制黑色背景
osg.setColor(0);
osg.fillRect(0,0,getWidth(),getHeight());

//绘制方块
osg.setColor(255,0,0);
osg.fillRect(x,y,4,4);


for(int i=0;i {
osg.setColor(255,255,255);
osg.fillRect(x1[i],y1[i],2,2);
}
}else{
osg.setColor(255,255,255);
osg.drawString("GAME OVER" ,getWidth()/2-10,getHeight()/2,Graphics.BOTTOM|Graphics.HCENTER);
osg.drawString("用时:"+long.toString(startime) ,getWidth()/2-10,getHeight()/2,Graphics.BOTTOM|Graphics.HCENTER);
sleeping=true;
}
}

这样我们就游戏就完成了,很简单但是去容纳了很多基础的而又必须的知识。有兴趣的话,在修改吧。努力一定能出精品的!

下面是完整的canvas类的代码:

/**
* 文件名:Ocanvas.java
* 画布类
*/

import javax.microedition.lcdui.*;
import java.io.*;
import java.util.Random;
import java.lang.Thread;
import java.util.*;
public class OCanvas extends Canvas implements Runnable
{
//定义变量
private Display display;
private boolean sleeping;
private long frameDelay;
private Random r;

//双缓冲区
private Image offScreenBuffer;

//控制主角的变量
private int XSpeed,YSpeed;
private int x,y;

//控制15个子弹
private int[] x1,y1;
private int[] x1speed,y1speed;

//子弹数目
private static final int zidanshu=25;

//记录时间
long startime;
private boolean isend;



public OCanvas(Display d)
{
//类构造函数,初始化类变量
super();
display = d;

// 设置帧频 (30 fps)
frameDelay = 33;


}

void start()
{

// 设置这个画布为当前屏幕
display.setCurrent(this);

// 初始化一些游戏中的变量,载入相关图片
isend=false;

r = new Random();
x=getWidth()/2-10;
y=getHeight()/2-10;
// Initialize the UFO sprite
XSpeed = YSpeed = 3;

x1=new int[zidanshu];
y1=new int[zidanshu];
x1speed= new int[zidanshu];
y1speed=new int[zidanshu];
for(int i=0;i {
x1[i]= r.nextInt()%5+1;
y1[i]= 0;

x1speed[i]=r.nextInt()%3+2;
y1speed[i]=r.nextInt()%3+3;
}

//建立双缓冲区
initResources();

// 开始动画线程
sleeping = false;
Thread t = new Thread(this);
t.start();
startime = System.currentTimeMillis();
}

private void initResources()
{
offScreenBuffer = Image.createImage(getWidth(), getHeight());


}

public void stop() {
// 停止动画线程
sleeping = true;
}

public void run() {
// 动画线程开始后运行

// 主游戏循环
while (!sleeping) {
//更新游戏中的数据变量

update();
//检查碰撞
pengzhuang();
//更新屏幕显示
repaint();
//线程休眠
try {
Thread.sleep(frameDelay);
}
catch (InterruptedException ie) {}
}
}
//翟这里检查主角和子弹的碰撞
private void pengzhuang()
{
for(int i=0;i {
if((x1[i]>x && x1[i]<(x+4))&&(y1[i]>y && y1[i]<(y+4)))
{

startime= System.currentTimeMillis()-startime;
isend=true;
}
}
}
//在这里更新游戏中的数据变量
private void update()
{
for(int i=0;i {
x1[i]+=x1speed[i];


y1[i]+=y1speed[i];

if (x1[i] < 0)
//oXSpeed=-oXSpeed;
x1[i]=getWidth();
if(x1[i]>getWidth())
//oXSpeed=-oXSpeed;
x1[i]=0;
if (y1[i] < 0)
//oYSpeed=-oYSpeed;
y1[i]=getHeight();
if(y1[i]>getHeight())
//oYSpeed=-oYSpeed;
y1[i]=0;
}

}

//这里添加对屏幕的绘制
public void paint(Graphics g)
{
// 清除屏幕
g.setColor(0xffffffff);
g.fillRect(0, 0, getWidth(), getHeight());

renderWorld();
g.drawImage(offScreenBuffer,0,0,Graphics.LEFT | Graphics.TOP);

}

private void renderWorld()
{
Graphics osg = offScreenBuffer.getGraphics();
if(!isend)
{


//绘制黑色背景
osg.setColor(0);
osg.fillRect(0,0,getWidth(),getHeight());

//绘制方块
osg.setColor(255,0,0);
osg.fillRect(x,y,4,4);


for(int i=0;i {
osg.setColor(255,255,255);
osg.fillRect(x1[i],y1[i],2,2);
}
}else{
osg.setColor(255,255,255);
osg.drawString("GAME OVER" ,getWidth()/2-10,getHeight()/2,Graphics.BOTTOM|Graphics.HCENTER);
osg.drawString("用时:"+Long.toString(startime-1000) ,getWidth()/2-10,getHeight()/2+15,Graphics.BOTTOM|Graphics.HCENTER);
sleeping=true;
}
}

//处理按键信息
public void keyPressed(int keyCode)
{
int keystates = getGameAction(keyCode);
switch(keystates)
{
case UP:
y = Math.max(0, y - 2);
break;
case DOWN:
y = Math.min(getHeight()-20, y + 2);
break;
case LEFT:
x = Math.max(0, x - 2);
break;
case RIGHT:
x = Math.min(getWidth(), x + 2);
break;
}
}

}





2006-11-20 09:11 PM

↑返回目录
前一篇: 从Flash到Kjava技术转换中的商机(转贴)
后一篇: TilePuzzle剖析(4)