当前页面: 开发资料首页 → 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;
}
}
}