public class Core extends Canvas
implements Runnable , RecordFilter {
//////////////////////////////////////////////////////////////////
//Game core
//////////////////////////////////////////////////////////////////
//#ifndef Core.GameCanvas
//define constant to handle game key states
public static final int UP_PRESSED = 1 << UP;
public static final int DOWN_PRESSED = 1 << DOWN;
public static final int LEFT_PRESSED = 1 << LEFT;
public static final int RIGHT_PRESSED = 1 << RIGHT;
public static final int FIRE_PRESSED = 1 << FIRE;
public static final int GAME_A_PRESSED = 1 << GAME_A;
public static final int GAME_B_PRESSED = 1 << GAME_B;
public static final int GAME_C_PRESSED = 1 << GAME_C;
public static final int GAME_D_PRESSED = 1 << GAME_D;
//double buffer
private Image __bufferedImage;
//clip
private boolean __setClip;
private int __clipX, __clipY, __clipWidth, __clipHeight;
public void paint(Graphics g)
{
if (this.__setClip) {
g.clipRect( this.__clipX, this.__clipY, this.__clipWidth, this.__clipHeight);
this.__setClip = false;
}
g.drawImage(this.__bufferedImage, 0, 0, Graphics.TOP | Graphics.LEFT );
}
public void flushGraphics()
{
repaint();
serviceRepaints();
}
public void flushGraphics(int x, int y, int width, int height)
{
this.__setClip = true;
this.__clipX = x;
this.__clipY = y;
this.__clipWidth = width;
this.__clipHeight = height;
repaint();
serviceRepaints();
}
//#endif
//define constant to handle soft key states
public static final int SOFT_FIRST_PRESSED = GAME_A_PRESSED;
public static final int SOFT_LAST_PRESSED = GAME_B_PRESSED;
//MIDlet object
private MIDlet __midlet;
//key states and soft key states
private int __keyStates, __currentKeyStates, __lastKeyStates, __softKeyStates, __currentSoftKeyStates, __lastSoftKeyStates;
//used for sleep
private long __lastSystemTime, __elapsedTime;
//canvas Graphics object
private Graphics g;
//view window
private int viewX, viewY, viewWidth, viewHeight;
//running and pause flags
public boolean running = true;
public boolean pause;
//clock
private boolean clockRunning = true;
public long virtualTime;
//frame delay
private long frameDelay = 120;
//auto flushGraphics
public Core(MIDlet m) {
//#ifndef Core.GameCanvas
super();
//#else
//# super(false);
//# setFullScreenMode(true);
//#endif
//#ifdef Core.GameCanvas
this.viewWidth = getWidth();
this.viewHeight = getHeight();
//#else
//#if polish.FullCanvasSize:defined
//#= this.viewWidth = ${polish.FullCanvasWidth};
//#= this.viewHeight = ${polish.FullCanvasHeight};
//#else
//# this.viewWidth = getWidth();
//# this.viewHeight = getHeight();
//#endif
//#endif
//#ifndef Core.GameCanvas
this.__bufferedImage = Image.createImage(this.viewWidth, this.viewHeight );
this.g = this.__bufferedImage.getGraphics();
//#else
//# this.g = getGraphics();
//#endif
//midlet
this.__midlet = m;
}
protected void keyPressed(int keyCode) {
//#ifndef Core.GameCanvas
this.__keyStates |= 1 << getGameAction(keyCode);
//#endif
switch (keyCode) {
//#ifdef polish.key.LeftSoftKey
//# case ${polish.key.LeftSoftKey}:
//#else
case -6:
//#endif
this.__softKeyStates |= SOFT_FIRST_PRESSED;
break;
//#ifdef polish.key.RightSoftKey
//# case ${polish.key.RightSoftKey}:
//#else
case -7:
//#endif
this.__softKeyStates |= SOFT_LAST_PRESSED;
break;
}
}
protected void keyReleased(int keyCode) {
//#ifndef Core.GameCanvas
this.__keyStates &= ~(1 << getGameAction(keyCode));
//#endif
switch (keyCode) {
//#ifdef polish.key.LeftSoftKey
//# case ${polish.key.LeftSoftKey}:
//#else
case -6:
//#endif
this.__softKeyStates &= ~SOFT_FIRST_PRESSED;
break;
//#ifdef polish.key.RightSoftKey
//# case ${polish.key.RightSoftKey}:
//#else
case -7:
//#endif
this.__softKeyStates &= ~SOFT_LAST_PRESSED;
break;
}
}
/**
* detect user input
*
* @param keyPressedConstant
* XXX_PRESSED constant like FIRE_PRESSED
* @param detectsStroke
* set true to detect stroke action,false to detect key pressed
* state
* @param soft
* set true to detect soft key,false to detect game key.
* @param update
* set true to update key(soft key) state
* @return
*/
private final boolean detectInput(int keyPressedConstant, boolean detectsStroke,boolean soft,boolean update){
if(soft){
if(update){
this.__lastSoftKeyStates = this.__currentSoftKeyStates;
this.__currentSoftKeyStates = this.__softKeyStates;
}
if(detectsStroke){
return ((this.__lastSoftKeyStates & keyPressedConstant) != 0) && ((this.__softKeyStates & keyPressedConstant) == 0);
}else{
return ((this.__softKeyStates & keyPressedConstant) != 0);
}
}else{
if(update){
//#ifdef Core.GameCanvas
//# this.__keyStates = getKeyStates();
//#endif
this.__lastKeyStates = this.__currentKeyStates;
this.__currentKeyStates = this.__keyStates;
}
if(detectsStroke){
return ((this.__lastKeyStates & keyPressedConstant) != 0) && ((this.__keyStates & keyPressedConstant) == 0);
}else{
return ((this.__keyStates & keyPressedConstant) != 0);
}
}
}
//implements interface Runnable
public void run(){
try{
initialize();
while (running) {
this.__lastSystemTime = System.currentTimeMillis();
if(!pause){
//#ifndef Core.GameCanvas
this.g = this.__bufferedImage.getGraphics();
//#else
//# this.g = getGraphics();
//#endif
executeFrameTask();
if(clockRunning){
this.virtualTime += this.frameDelay;
}
}
this.__elapsedTime = System.currentTimeMillis() - this.__lastSystemTime;
if (this.__elapsedTime>0 && this.__elapsedTime < this.frameDelay) {
try{
Thread.sleep(this.frameDelay - this.__elapsedTime);
}catch(InterruptedException ie){}
}
//#mdebug benchmark
//# System.out.println("elapsed time: " + String.valueOf(this.__elapsedTime) +
//# " (" + String.valueOf(this.__elapsedTime*100/this.frameDelay) + "%)");
//#enddebug
}
this.__midlet.notifyDestroyed();
//#mdebug info
//# System.out.println("game stop normally.");
//#enddebug
}catch(Exception e){
//#mdebug fatal
//# System.out.println("a fatal error occured.");
//# e.printStackTrace();
//#enddebug
showSystemHint(Locale.get("Game.SystemError"));
this.__midlet.notifyDestroyed();
}
}
//略……
}
上面的代码在MIDP1.0接口的基础上模拟了MIDP2.0 GameCanvas的功能,并对用户输入作了增强。
paint(Graphics g)实现了父类的抽象方法。
flushGraphics()和flushGraphics(int x, int y, int width, int height)是对GameCanvas相应方法的模拟,方便调用。
keyPressed(int keyCode)和keyReleased(int keyCode)用来捕获用户输入,并记录按键的状态。
detectInput(int keyPressedConstant, boolean detectsStroke,boolean soft,boolean update)用于根据案件状态来判断,用户(玩家)是否将某个键(包括左右系统键)按下一次,或按下没有松开。
run()实现了Runnable接口的方法,其中,游戏初始化在initialize()中进行,游戏循环在executeFrameTask()中实现。每一帧如果不到预定的帧延迟时间就让当前线程睡眠一会。
这只是一小部分,为了阅读方便有些改动。另外,在我的游戏内核里还有
Temporary Memory部分 用于方便的把数据按照数据流DataInputStream和DataOutputStream来操作。
General部分 定义了8个方向,高效产生随机数,对矩形进行碰撞判断,byte[]和int的相互转换。
Device Feature部分 包括设备相关特性的操作:声音、振动和灯光
UI部分 包括在屏幕上书写特效文字,在一个区域内分页显示大段文字(比如人物对话),系统信息提示和进度条。
Map部分 对游戏中地图的解析和显示
Game Menu部分 游戏菜单,绘制菜单和获取用户对菜单项的选择。
Resource and storage部分 用于获取打包资源(为了使压缩比更大)和按文件名方式管理RMS内容,还有从网上下载资源。
Path部分 产生完美的圆弧和直线路径,用于子弹敌人飞行等
上面各部分为了使字节码尽可能少,我没有做类封装,而是写到了一起。另外,如果有哪些部分没有被调用到,那么在作绕码(混淆)时,会被自动去掉,所以不必担心。
我还写了对MIDP2.0 Sprite类的模拟类,以便使用。
内核部分之外,就是具体游戏逻辑的实现了。其实,有了上面工具的帮助,游戏逻辑的实现是就容易多了。
除了j2me的程序,在开发中还需要一些工具,如:资源打包工具,地图编辑器和图像优化工具。
资源打包工具——把多个资源文件(如png图片等)打包为一个文件,这样在jar包中会有更大的压缩比。
地图编辑器——编辑游戏地图,共类似TiledLayer使用。
图像优化工具——将png图片进一步压缩,节约空间。
以上内容我正在使用。
二、商业运作
这方面问题如果没有深入进去,是比较难了解的。在国内,j2me应用是通过sp(Service Provider,开发者是cp content provider之一)来进行发布,通过移动审批后供用户下载使用。通常的商业模式为:预付款+按比例分成。具体数字和比例看CP的名气、东西的品质和谈判的技巧等。
如果东西好,还可以销售到国外。除了通过运营商销售以外,还可以放在独立的销售网站上销售。好东西,价格都很高的。像gameloft的单机游戏几十港元一个。通过运营商的,通常可以买到4-5欧元一个下载。
所以,新兴的手机游戏市场,是个大馅饼,有很多机会。尤其是对于我们这种没有资金的个人或小型团队来说,是淘金千载难逢的机遇。
更详细的以后再谈。
三、demo
这个demo是我目前尚未发布的作品,MIDP2 is required.具体我不多谈了,CSDN不能上传,有兴趣可以给我发邮件,我用附件发送。
四、关于我和我寻求的帮助
先说我个人。我2000年考入国防科技大学,2年后不能忍受压抑的环境要求退学未受批准,于是不告而别被开除。后来研究技术,没有找到合适的市场机会。几个月前和像素点工作室的朋友在四川合作开发手机游戏,现在拥有1个完整产品和完善内核、周边工具。
也许最理智的程序员也会在爱情面前陷入死循环,直到资源耗尽系统崩溃!
我寻求的帮助。去年我和北京一个女孩有个为期5个月的浪漫约定,于是我就走入移动开发领域。可是,时间到了,我的东西还没出来,我失约了。约定又超过了2个月,我不想絮叨情感上的纠缠不清,可的确发生了很多事情。今天我和她聊天,我不能再等了。我不能等到我的游戏谈判完卖出去以后再去找她,因为她要毁了自己,绝无玩笑。
对具体的技术和商业细节感兴趣,可以和我面谈。如果你愿意善意的帮助一个同行,交一个真诚的朋友或者共同开发手机游戏市场,请尽快联系我。
http://topic.csdn.net/t/20050308/05/3832358.html
posted on 2007-02-03 19:15
SIMONE 阅读(363)
评论(0) 编辑 收藏 所属分类:
JAVA