喜欢玩火焰纹章吗?【这个是我最喜欢的游戏】fc时期放假的时候,可以一次玩一天的游戏,梦幻模拟战,最早接触的电脑游戏《天使帝国》(我这个人比较奇怪,人家都是先玩红警,我最早接触的游戏除了486麻将,殖民计划,就是天使帝国了),加上光荣公司的3款开天辟地的slg大作,《三国英杰传》,《三国孔明传》,《三国曹操传》,还有台湾汉堂的几款游戏(炎龙骑士团,阿玛迪斯战记等等)加上后期的《风色幻想》,共同支撑起了当年Slg的鼎盛时期,不过在快节奏的今天,战棋游戏的滑落非常明显,虽然《火焰纹章》可以全球发售,在全球范围内都维护了大量粉丝,但最新版《觉醒》全球销量却并不是很尽如人意,为什么呢,并不是游戏的人气下落了,或者玩家少了,而是因为一场战斗花费太多的时间令玩家招架不住了,这个在单机游戏市场如此,在网络游戏市场就更是如此,战棋类网游吃螃蟹的日韩企业不是没有,早在03年就有《佣兵传说》这样的网游问世,国内也有盛大推出的《三国豪侠传》,但无一不是失败了,不过既然战棋有自己独特的魅力,又有固定稳定的玩家群体,那么只要想出解决时间开销问题的解决方法,相信赚钱也不是不可能,我们不讨论如何真把战棋搬到网络上。

我们今天只是聊聊战棋怎么做,当然因为市面上没有相关网游代码,单机代码也是很久以前的,所以大家凑合着看看就行了,等如果那一天战棋类网游真的火了,那么我们在加篇幅讨论。先看看这些曾经失败的作品其实盛大的三国豪侠传做的还挺好玩的,但是说实话,战棋游戏因为一次战斗要耗费太多时间,所以真要让玩家在网络上玩,还真要考虑些新的玩法,佣兵传说就不说了,这个游戏做的有问题,无pvp和pve区分,混战,有时候野外杀个怪,最后没血了,有人强制加入你的战斗,把你杀了,结果什么保护都没有,佣兵要花钱去酒馆雇佣,佣兵死亡无法复活(就是个坑钱的玩应),所有战斗都会消耗佣兵,一天赚的钱只够买两个佣兵,最后玩过的人都说,要想在这个游戏生存下去,最主要的就是玩游戏不带一个佣兵(它倒我不奇怪,奇怪的是它在日韩居然比国服多支撑了好几年,真是奇迹,难为日韩的玩家了)说不说,还说了这么多。

我们下面讨论怎么做。我们先抛开通篇代码的枷锁看看SLG寻路,寻路一直是SLG战棋最难的一个部分,因为不同的地形所生成的步数不同,时时更新,需要相当全面的考虑,我们看下这个寻路算法

SLG中搜索某个角色可移动区域的算法可根据地形的不同,以及角色能力的不同来判断可移动区域。例如骑士在平地上可以移动更大的范围。代码如下:
/** * 搜索可走区域 * @param map 当前地图表 * @param row 行 * @param col 列 * @param locomotivity 该角色的默认移动力 * @param direction 方向 */ public void scanMovableArea(byte map[][], int row, int col, int locomotivity, int direction){ if(locomotivity > map[row][col]) map[row][col] = (byte)locomotivity; else return; /** 向上判断 **/ if(direction != 1){ int loco1 = locomotivity - mapExpendLocomotivity(row, col - 1); if(loco1 >=0) scanMovableArea(map, row, col - 1, loco1, 2); } /** 向下判断 **/ if(direction != 2){ int loco2 = locomotivity - mapExpendLocomotivity(row, col + 1); if(loco2 >= 0) scanMovableArea(map, row, col + 1, loco2, 1); } /** 向左判断 **/ if(direction != 4){ int loco3 = locomotivity - mapExpendLocomotivity(row - 1, col); if(loco3 >= 0) scanMovableArea(map, row - 1, col, loco3, 8); } /** 向右判断 **/ if(direction != 8){ int loco4 = locomotivity - mapExpendLocomotivity(row + 1, col); if(loco4 >= 0) scanMovableArea(map, row + 1, col, loco4, 4); } } ---------------------------------------------- /** * 地形对移动力的消耗 * @param row 行 * @param col 列 * @return 移动力消耗值 */ public int mapExpendLocomotivity(int row, int col){ //这里我就不一一实现了,有兴趣的朋友可以自己扩展这个方法。 //下面给个伪代码 //如果是草地 if(gameMap[row][col] == GAME_MAP_GRASS){ //如果是士兵 if(type == SOLIDER){ return 1; } } //超出边界 if(row < 0 || col < 0 || row > gameWidth || col > gameHeight) { return 1000; } //具体的情况各位朋友可以根据自己的游戏来设计。 } 找到可以移动的区域后,就可以确定要移动的具体位置。这时候又要涉及到找路算法了。对于与A*算法(以前有一位同事写过)。不过下次我会用递归算法来实现,速度更快,更简单。 差点忘记说明了以上得到的map数组怎么使用。这时一个记录了剩余移动力的数组。在显示可移动的区域的时候只要判断map里面的值是否为空,不为空就画出一个矩形,代表该区域可走。 /** * 走路 * @param curX 当前位置 (x方向) * @param curY 当前位置 (y方向) * @param destX 目标位置(x方向) * @param destY 目标位置 (y方向) * @return 路径矢量 */ public Vector scanPath(int curX, int curY, int destX, int destY){ Vector vector = null; short dest[] = { (short)destX, (short)destY }; if(curX == destX && curY == destY){ vector = new Vector(); vector.addElement((Object)dest); return vector; } byte byte0 = 0; byte byte1 = 0; byte byte2 = 0; byte byte3 = 0; if(destY > 0) byte0 = _mapped_terrains[destX][destY - 1]; if(destY < _map_height - 1) byte1 = _mapped_terrains[destX][destY + 1]; if(destX > 0) byte2 = _mapped_terrains[destX - 1][destY]; if(destX < _map_width - 1) byte3 = _mapped_terrains[destX + 1][destY]; int max = Math.max(Math.max((int)byte0, (int)byte1), Math.max((int)byte2, (int)byte3)); if(max == byte0) vector = scanPath(curX, curY, destX, destY - 1); else if(max == byte1) vector = scanPath(curX, curY, destX, destY + 1); else if(max == byte2) vector = scanPath(curX, curY, destX - 1, destY); else if(max == byte3) vector = scanPath(curX, curY, destX + 1, destY); vector.addElement((Object)dest); return vector; } 还记得上个帖子上函数中传入的map参数吗,实际上通过那个函数就可以得到一个map,然后应用于现在的找路算法中,也就是上面代码段看到的_mapped_terrains 还有两个陌生的变量就是 _map_height和_map_width ,这个很简单了,就是SLG地图中的长度和宽度。 呵呵,希望这些代码段对SLG的朋友有些帮助

很详细的讲解以及寻路设定,小伙伴完全可以根据这个来改动一下,当然,我们如果考虑通篇的SlG制作,那么我们看下面的j2me源码

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import java.lang.Thread;public class MainMid extends MIDlet
{MainPit myScreen;boolean first=true;public MainMid(){myScreen = new MainPit(this);}protected void destroyApp(boolean unconditional) {}protected void pauseApp() { }protected void startApp() {Display.getDisplay(this).setCurrent(myScreen);if(first){try{Thread myThread = new Thread(myScreen);myThread.start();}catch(Error e){destroyApp(false);notifyDestroyed();}first = false;}}//游戏结束public void exit(){destroyApp(true);notifyDestroyed();}
}       

这个是j2me的启动app类,因为j2me不像正常java程序那样有public static void main(String[] args){}这个方法,需要在MIDlet的子类里面起一个绘图类的线程

/*SLG战略实现
小图模式
1:光标移动OK
2:滚屏OK
3:人物动作OK
4:人物移动OK
5:移动范围限定OK
6:显示菜单OK
7:多人物模式OK
8:移动完成后的攻击判断,并且根据判断绘制菜单.
9:选择菜单攻击指令后,绘制攻击范围
10:选择攻击目标
11:攻击过程
12:带有地图限定的移动模式
13:其它限定移动
14:整理以方便移植,除去攻击血量显示外,其余已调整完成 ,适配其它机型调整参数即可
15:开始菜单,相关其它显示内容的接口,分离光标的参数调整与绘制
16:移动过程人物寻路
17:全局信息读入
18:加入人物参数及其相关参数导入
*/import javax.microedition.lcdui.Image;
import java.lang.Math;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import java.lang.Thread;
import java.lang.Runnable;
import java.io.InputStream;
import javax.microedition.rms.*;
import java.io.DataOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;//import com.nokia.mid.ui.FullCanvas;
//class MainPit extends FullCanvas implements Runnable
class MainPit extends Canvas implements Runnable
{MainMid myMid;private String mainMenuText[] ={"开始游戏","继续游戏","读取进度","帮助信息","结束游戏"};//按键final static byte UP = -1;final static byte DOWN = -2;final static byte LEFT = -3;final static byte RIGHT = -4;final static byte OK = -5;final static byte LCOMMAND = -6;final static byte RCOMMAND = -7;//状态private int STATE = 1;//屏幕大小private int SCREEN_WIDTH = 128;private int SCREEN_HEIGHT = 128;//瓷砖大小private int TILE_WIDTH = 16;private int TILE_HEIGHT =16;private int TILE_SIZE = 16;//屏幕单元数目最大数private int SCREEN_MAX_WIDTH = 7;private int SCREEN_MAX_HEIGHT = 7;//地图单元数目private int MAP_MAX_WIDTH = 15;private int MAP_MAX_HEIGHT = 15;//职业相关参数private byte vocation[][] = {{22,5,5,5,5,4,1},//人剑{22,5,7,4,4,8,2},//人骑{25,6,5,5,4,6,2},//蛮骑{25,5,5,7,3,6,3},//蛮骑射{20,6,2,8,4,7,3},//羽射{20,6,6,4,4,3,1},//河洛{28,7,7,3,3,5,1},//夸父{20,7,2,6,5,3,1},//魅{22,4,4,6,6,3,1}//术};//图片偏移系数//人物图片偏移[人物类型][y偏移][x偏移]private byte actorpos[][] = {//女剑士1//无焦点{0,2},{-1,1},//有焦点{0,1},{2,-8},//正面下移{2,-1},{2,-2},//背面上移{2,0},{2,0},//左移{3,0},{2,0},//右移{-5,0},{-5,0},//骑士//无焦点{1,-3},{0,-6},//有焦点{-4,-6},{0,-9},//正面下移{2,-7},{2,-9},//背面上移{-1,-6},{-1,-8},//左移{-2,-6},{-2,-5},//右移{-5,-6},{-7,-5}};//人物动作图片位置//[人物类型][动作类型]//人物类型0:主角1//动作类型0:无焦点,1:有焦点,2:正面下移,3:背面上移,4:左移,5:右移private byte actpic[][] = {{0,2,4,6,8,10},{12,14,16,18,20,22}};//红方信息//0:类型,1:x坐标,2:y坐标,3:等级,4:五行属性,5:HP,6:ATK,7:DEF,8:DEX,9,AGI,10:MOV,11:攻击范围)private byte redinfo[][] = new byte[9][12];//蓝方信息//0:类型,1:x坐标,2:y坐标,3:等级,4:五行属性,5:HP,6:ATK,7:DEF,8:DEX,9,AGI,10:MOV,11:攻击范围)private byte blueinfo[][] = new byte[9][12];private byte infored[][] = {//类型,坐标,等级,属性{0,0,0,3,0},{1,5,6,4,1},{2,3,9,4,2},{3,1,6,2,3},{4,8,10,5,4},{5,2,7,2,0},{6,12,12,3,1},{7,14,11,3,2},{8,15,15,5,3}};//出场人物信息数组(人物类型,人物地图坐标,人物移动能力,攻击范围最小值,攻击范围最大值)private int infoact[][] = {{0, 0, 0, 6, 0, 1},{1, 6, 5, 4, 0, 1},{1, 8,10, 4, 1, 3},{0, 1, 1, 2, 1, 4},{1, 2, 7, 5, 0, 2}};//出场人物个数private int actnum = 5;//出场人物处理编号private int idact[] = {0,1,2,3,4};//红方数量private byte rednum;//蓝方数量private byte bluenum;/*//蓝方编号private byte redindex[];//红方编号private byte blueindex[];*///计数器private int tally;//光标计数器/**光标计数器*/private int cursortally;//动作类型//0:未得焦点//1:得到焦点//2:正面下移//3:背面上移//4:左面侧移//5:右面侧移//private byte motionkind[]={0,4,8,12,16,20};//人物类型//0:主角//private byte actpickind[]={0,24};//地图/**地图*/private byte map[][] ={{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0},{0,0,0,0,0,0,0,3,3,3,0,3,0,0,0,0},{0,1,0,0,0,0,0,3,0,0,0,3,0,0,0,0},{0,1,1,0,0,0,0,3,0,3,3,3,0,0,0,0},{0,1,1,0,0,0,3,3,0,3,0,0,0,0,0,0},{0,0,0,0,0,3,3,0,0,3,0,0,0,0,0,0},{0,0,0,0,3,3,0,0,3,3,0,0,2,0,0,0},{0,0,0,0,0,0,0,3,3,0,0,2,2,2,0,0},{0,0,0,0,0,0,3,3,0,0,0,2,2,2,2,2},{0,1,1,0,0,0,3,0,0,0,2,2,2,2,2,2},{0,0,1,0,0,0,3,0,0,0,2,2,2,2,2,2},{0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2},{0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};private String mapname[] = {"草","林","沙","山"};//地图能力修正[防御,闪避][修正值]private byte maprevise[][] = {//草地,林地,沙地,建筑{0,1,2,3},//防御{0,20,10,30}//回避};//地图类型对人物移动能力的修正[地图类型][人物类型]private byte mappos[][] = {//剑士,骑士{1,1},//草地{1,2},//林地{2,2},//沙地{10,10}};//移动能力private byte move[][] ={{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}};//菜单内容public String MenuContent[][] = {{"终了","中断","状况","部队"},{"待机","攻击"}};//菜单信息public byte MenuInfo[] = {4, 1};//当前菜单焦点public int MenuFocus;private byte CurrentMenu;//当前菜单private byte CurrentScene;//当前场景private boolean atkrangeshow;//显示攻击范围private byte atktarget[] = {0,0,0,0,0,0,0,0,0,0,0};//攻击目标private byte currentatk;//当前攻击对象//光标在地图中位置private int cursorMX;private int cursorMY;//光标在屏幕中位置private int cursorSX;private int cursorSY;//屏幕左上角瓷砖在地图中位置private byte x;private byte y;//光标式样private int cursorkind;//按键已按标记private boolean hasPressed;//屏幕滚动标记private boolean rollmapflag;//按键记忆private int kCode;//延时private int hangfire;//选中目标标记private int currentact;/****************************************************************************///选中目标参数//选中目标类型private int currentactkind;//选中目标攻击范围下限private int currentactatkmin;//选中目标攻击范围下限private int currentactatkmax;//选中目标位置坐标//屏幕中位置private int currentactSX;private int currentactSY;//地图中位置private int currentactMX;private int currentactMY;//选中目标状态private int currentactstate;//选中目标动作标记private int currentactcg;//选中目标移动偏移private int currentactmovex;private int currentactmovey;//选中目标移动标记private boolean moveaction;//移动对象坐标private int targetSX;private int targetSY;//选中目标状态private int targetstate;//选中目标移动范围private int currentactmovearea;//移动范围显示标记private boolean showmovearea;/********************************************************************************///文字框架颜色方案数组private int frameColor[][] = {{0x00c8c8d0,0x00d8d8a8,0x00003088,0x000050b0},//开始菜单{0x00605838,0x00605838,0x00f8f8c8,0x005858c0},//游戏菜单{0x00605838,0x00f8f8c8},//地形修正{0x00504830,0x00f8f0c8,0x00f87079,0x00f86800},//攻击血量显示蓝方{0x00504830,0x00f8f0c8,0x00404090,0x0010b0f8},//攻击血量显示红方{0x00d0d8f8,0x005858a8,0x00a0a0f8}//人物基本信息蓝方};/************************************///游戏相关//游戏章节private byte gameChapter;Image back_buffer;//缓存Image static_buffer;//静态图形缓存Image picmap[] = new Image[4];//地图Image piccursor[] = new Image[4];//光标Image picact[] = new Image[24];//人物Graphics gb;Graphics gs;private RecordStore myStore = null;public MainPit(MainMid Mid){gameChapter = 0;myMid = Mid;try{back_buffer = Image.createImage(SCREEN_WIDTH,SCREEN_HEIGHT);static_buffer = Image.createImage(SCREEN_WIDTH,SCREEN_HEIGHT);//图片载入,for(int i = 0; i < 24; i++){if(i < 4){piccursor[i] = Image.createImage("/pic/cursor/c" + i + ".png");picact[i] = Image.createImage("/pic/act/m" + i + ".png");picmap[i] = Image.createImage("/pic/map/m" + i + ".png");}else{picact[i] = Image.createImage("/pic/act/m" + i + ".png");}}//readStaticInfo();}catch(Exception e){}gb = back_buffer.getGraphics();gs = static_buffer.getGraphics();System.out.println("11111111111111");//System.out.println("22222222222");newGame();//System.out.println("3333333333333");}public void loadGameItem(byte chaper){}public void newGame(){//菜单焦点MenuFocus = 0;//计数器tally = 0;cursortally = 0;CurrentScene = 1;//当前场景//光标在地图中位置cursorMX = 0;cursorMY = 0;//光标在屏幕中位置cursorSX = 0;cursorSY = 0;//屏幕左上角瓷砖在地图中位置x = 0;y = 0;//光标式样tally = 0;//按键已按标记hasPressed = false;//屏幕滚动标记rollmapflag = false;//按键记忆kCode = 0;//延时hangfire = 0;//选中目标标记currentact = -1;/****************************************************************************///选中目标参数//选中目标位置坐标//屏幕中位置currentactSX = -1;currentactSY = -1;//地图中位置currentactMX = -1;currentactMY = -1;//选中目标状态currentactstate = 0;//选中目标动作标记currentactcg = -1;//选中目标移动偏移currentactmovex = 0;currentactmovey = 0;//选中目标移动标记moveaction = false;//移动对象坐标targetSX = -1;targetSY = -1;//选中目标状态targetstate = 0;//选中目标移动范围currentactmovearea = 0;//移动范围显示标记showmovearea = false;//System.out.println("444444444444444");//readChapterInfo(gameChapter);DrawStaticPic(gs);//System.out.println("end");}public void paint(Graphics g){g.drawImage(back_buffer,0,0,g.LEFT|g.TOP);}//主菜单public void mainMenu(){gb.setColor(0,0,0);gb.fillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);for(int i = 0; i < 5; i++){drawMainMenu(gb, mainMenuText[i], (SCREEN_WIDTH - 72) / 2, ((SCREEN_HEIGHT - 22 * 5)/6 + 22)*i + (SCREEN_HEIGHT - 22 * 5)/6, 72, 22);//, 2, 6);}DealCursor();}//绘制菜单(内容,菜单坐标,宽高,字体位置)/**绘制菜单(内容,菜单坐标,宽高,字体位置)*/public void drawMainMenu(Graphics g, String s,int x,int y, int w, int h)//,int tx,int ty){DrawFrame(g,x,y,w,h,4,frameColor,0);g.setColor(255,255,255);g.drawString(s,x+16,y+3,g.TOP|g.LEFT);}public void DealCursorMove(){if(hasPressed&&!moveaction){switch(kCode){case 2:if(cursorSY > 2)//静止背景时光标移动{cursorSY--;cursorMY--;}else if(cursorSY > 0&&cursorMY > 2)//背景随光标移动{cursorMY--;y--;RollScreen(gs,2);}else if(cursorMY > 0)//边界光标移动情况{cursorMY--;cursorSY--;}break;case 8:if(cursorSY < SCREEN_MAX_HEIGHT - 2){cursorSY++;cursorMY++;}else if(cursorMY < MAP_MAX_HEIGHT - 2&&cursorSY < SCREEN_MAX_HEIGHT){cursorMY++;y++;RollScreen(gs,8);}else if(cursorMY < MAP_MAX_HEIGHT){cursorSY++;cursorMY++;}break;case 4:if(cursorSX > 2){cursorSX--;cursorMX--;}else if(cursorMX > 2&&cursorSX > 0){x--;cursorMX--;RollScreen(gs,4);}else if(cursorMX > 0){cursorSX--;cursorMX--;}break;case 6:if(cursorSX < SCREEN_MAX_WIDTH - 2){cursorSX++;cursorMX++;}else if(cursorMX < MAP_MAX_WIDTH - 2&&cursorSX < SCREEN_MAX_WIDTH){x++;cursorMX++;RollScreen(gs,6);}else if(cursorMX < MAP_MAX_WIDTH){cursorSX++;cursorMX++;}break;}tally = 0;}}
/***移动判定*/public void DealPersonMove(){if(moveaction){hasPressed = true;boolean endmove = true;if(endmove&&targetSY + y + 1 <= MAP_MAX_HEIGHT){if(move[targetSY+y][targetSX+x] ==move[targetSY+y+1][targetSX+x] + mappos[map[targetSY+y+1][targetSX+x]][currentactkind])//下走{currentactstate = 2;currentactmovey++;if(currentactmovey % TILE_HEIGHT == 0){targetSY++;}endmove = false;}}if(endmove&&targetSY+y-1 >= 0){if(move[targetSY+y][targetSX+x] ==move[targetSY+y-1][targetSX+x] + mappos[map[targetSY+y-1][targetSX+x]][currentactkind])//上走{currentactstate = 3;currentactmovey--;if(currentactmovey % TILE_HEIGHT == 0){targetSY--;}endmove = false;}}if(endmove&&targetSX+x+1 <= MAP_MAX_WIDTH){if(move[targetSY+y][targetSX+x] ==move[targetSY+y][targetSX+x+1] + mappos[map[targetSY+y][targetSX+x+1]][currentactkind])//右走{currentactstate = 5;currentactmovex++;if(currentactmovex % TILE_WIDTH == 0){targetSX++;}endmove = false;}}if(endmove&&targetSX+x-1 >= 0){if(move[targetSY+y][targetSX+x] ==move[targetSY+y][targetSX+x-1] + mappos[map[targetSY+y][targetSX+x-1]][currentactkind])//左走{currentactstate = 4;currentactmovex--;if(currentactmovex % TILE_WIDTH == 0){targetSX--;}endmove=false;}}if(endmove){targetstate = 2;moveaction = false;hasPressed = false;CurrentScene = 2;CurrentMenu = 1;MenuFocus = 0;MenuInfo[1] = 1;//没有攻击目标byte s = 1;//移动完成后的可攻击判断for(int j = -currentactatkmax; j <= currentactatkmax; j++){for(int i = targetSX - (currentactatkmax - Math.abs(j)); i <= targetSX + (currentactatkmax - Math.abs(j)); i++){for(int m = 0; m < actnum; m++){if(m == currentact){continue;}if(infoact[idact[m]][1] - x == i&&infoact[idact[m]][2] - y == j + targetSY){MenuInfo[1] = 2;//有攻击目标currentatk = 1;atktarget[s] = (byte)m;s++;break;}}}}}}}public void playGame(){switch(CurrentScene){case 0://章节显示,并载入相关信息break;case 1://游戏大地图状态//光标移动判断DealCursorMove();//游戏中屏幕坐标与地图坐标相关currentactSX = currentactMX - x;currentactSY = currentactMY - y;//人物移动DealPersonMove();DrawBuffer(gb);//绘制静态缓存DrawPerson(gb);//绘制人物DealCursor();//绘制光标DealMapRevise();//地形修正//DealPersonInfo();break;case 2://菜单1(待机,攻击)DrawBuffer(gb);//绘制静态缓存DrawPerson(gb);//绘制人物DrawMenu(gb,CurrentMenu);DealCursor();break;case 3://攻击选定DrawBuffer(gb);//绘制静态缓存if(targetstate == 2)//攻击对象选定{DrawRange(gb, targetSX, targetSY, currentactatkmin, currentactatkmax, 0x00ff0000);DrawPerson(gb);//绘制人物DealCursor();}else if(targetstate == 3)//攻击过程{atkcg(gb);targetstate = 0;currentactstate = 0;CurrentScene = 1;}break;}}public void run(){while(true){tally++;cursortally++;switch(STATE){case 0://logobreak;case 1://开始菜单mainMenu();break;case 2://游戏playGame();break;}//System.out.println("cursorMX="+cursorMX+"   cursorSX="+cursorSX+"    cursorMY="+cursorMY+"    cursorSY="+cursorSY);//System.out.println("currentactSX="+currentactSX+"   currentactSY="+currentactSY+"    currentactMY="+currentactMY+"    currentactMY="+currentactMY);repaint();System.gc();try{Thread.sleep(hangfire);}catch(Exception e){}}}//绘制文字容器框(位置x,y,大小w,h,边框层数n,颜色c,框架类型k)public void DrawFrame(Graphics g, int x, int y, int w, int h, int n, int c[][],int k){for(int i = 0; i < n;i++){g.setColor(c[k][i]);g.fillRect(x + i, y+i, w - 2 * i, h - 2 * i);}}//绘制范围(g,目标位置,范围下限,范围上限颜色)public void DrawRange(Graphics g, int x, int y, int rmin, int rmax, int c){gb.setColor(c);for(int i = 0; i <= rmax; i++){//右下gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y + (rmax - i)) * TILE_SIZE + TILE_SIZE,(x + i) * TILE_SIZE + TILE_SIZE, (y + (rmax - i)) * TILE_SIZE);gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y + (rmax - i)) * TILE_SIZE + TILE_SIZE,(x + i) * TILE_SIZE, (y + (rmax - i)) * TILE_SIZE + TILE_SIZE);//右上gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y - (rmax - i)) * TILE_SIZE,(x + i) * TILE_SIZE, (y - (rmax - i)) * TILE_SIZE);gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y - (rmax - i)) * TILE_SIZE,(x + i) * TILE_SIZE + TILE_SIZE, (y - (rmax - i)) * TILE_SIZE + TILE_SIZE);//左下gb.drawLine((x - i) * TILE_SIZE, (y + (rmax - i)) * TILE_SIZE + TILE_SIZE,(x - i) * TILE_SIZE, (y + (rmax - i)) * TILE_SIZE);gb.drawLine((x - i) * TILE_SIZE, (y + (rmax - i)) * TILE_SIZE + TILE_SIZE,(x - i) * TILE_SIZE + TILE_SIZE, (y + (rmax - i)) * TILE_SIZE + TILE_SIZE);//左上gb.drawLine((x - i) * TILE_SIZE, (y - (rmax - i)) * TILE_SIZE,(x - i) * TILE_SIZE + TILE_SIZE, (y - (rmax - i)) * TILE_SIZE);gb.drawLine((x - i) * TILE_SIZE, (y - (rmax - i)) * TILE_SIZE,(x - i) * TILE_SIZE, (y - (rmax - i)) * TILE_SIZE + TILE_SIZE);if(i <= rmin)//绘制下限{//右下gb.drawLine((x - i) * TILE_SIZE, (y - (rmin - i)) * TILE_SIZE,(x - i) * TILE_SIZE + TILE_SIZE, (y - (rmin - i)) * TILE_SIZE);gb.drawLine((x - i) * TILE_SIZE, (y - (rmin - i)) * TILE_SIZE,(x - i) * TILE_SIZE, (y - (rmin - i)) * TILE_SIZE + TILE_SIZE);//右上gb.drawLine((x - i) * TILE_SIZE, (y + (rmin - i)) * TILE_SIZE + TILE_SIZE,(x - i) * TILE_SIZE, (y + (rmin - i)) * TILE_SIZE);gb.drawLine((x - i) * TILE_SIZE, (y + (rmin - i)) * TILE_SIZE + TILE_SIZE,(x - i) * TILE_SIZE + TILE_SIZE, (y + (rmin - i)) * TILE_SIZE + TILE_SIZE);//左下gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y - (rmin - i)) * TILE_SIZE,(x + i) * TILE_SIZE, (y - (rmin - i)) * TILE_SIZE);gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y - (rmin - i)) * TILE_SIZE,(x + i) * TILE_SIZE + TILE_SIZE, (y - (rmin - i)) * TILE_SIZE + TILE_SIZE);//左上gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y + (rmin - i)) * TILE_SIZE + TILE_SIZE,(x + i) * TILE_SIZE + TILE_SIZE, (y + (rmin - i)) * TILE_SIZE);gb.drawLine((x + i) * TILE_SIZE + TILE_SIZE, (y + (rmin - i)) * TILE_SIZE + TILE_SIZE,(x + i) * TILE_SIZE, (y + (rmin - i)) * TILE_SIZE + TILE_SIZE);}}}//绘制攻击血槽public void DrawLifeShow(Graphics g, int blue, int red){int m;int d;int n;//System.out.println(" blue =  " + blue + "   red = "+red);if(infoact[idact[red]][2] - y < 4){d = 80;}else{d = 0;}//攻击方//血量显示m = 16 - 3;n = d + 16;//框DrawFrame(g,m,n,54,30,4,frameColor,4);//槽g.setColor(232,144,0);g.drawRect(16 + m + 2, 1 + 8 + n + 4 + 3, 25, 6);g.setColor(112,48,0);g.fillRect(16 + m + 3, 2 + 8 + n + 4 + 3, 23, 4);//血g.setColor(248, 248, 0);g.fillRect(16 + m + 4, 3 + 8 + n + 4 + 3, 18, 2);//人物名称显示m = 24-3;n = d + 8;DrawFrame(g,m,n,38,22,4,frameColor,4);//反击方m = 64+3;n = d + 16;DrawFrame(g,m,n,54,30,4,frameColor,3);//人物名称显示m = 72+3;n = d + 8;DrawFrame(g,m,n,38,22,4,frameColor,3);}public void DrawMenu(Graphics g, int k)//绘制菜单,k:菜单类型{int s = MenuInfo[k];int m = SCREEN_WIDTH - 3 * TILE_SIZE;if(cursorSX >=4){m = TILE_SIZE;}else{m = SCREEN_WIDTH - 3 *TILE_SIZE;;}DrawFrame(g, m,    TILE_SIZE, 37, TILE_SIZE * s + 5,4,frameColor,1);g.setColor(255,255,255);for(int i = 0; i < s; i++){g.drawString(MenuContent[k][s - i - 1], m + TILE_SIZE+3, 2+TILE_SIZE + TILE_SIZE * i, g.TOP|g.HCENTER);}}//人物基本信息public void DealPersonInfo(){if(cursorSX > SCREEN_MAX_WIDTH / 2){DrawPersonInfo(gb, 5, 5);}else{DrawPersonInfo(gb, SCREEN_WIDTH - 53, 5);}}public void DrawPersonInfo(Graphics g,int x,int y){DrawFrame(gb,x,y,48,32,3,frameColor,5);}//地图修正信息处理/**地图修正信息处理*/public void DealMapRevise(){if(cursorSX > SCREEN_MAX_WIDTH / 2){DrawMapRevise(gb, 5, SCREEN_HEIGHT - 41, map[cursorMY][cursorMX]);}else{DrawMapRevise(gb, SCREEN_WIDTH - 41, SCREEN_HEIGHT - 41, map[cursorMY][cursorMX]);}}public void DrawMapRevise(Graphics g,int x,int y, int mk){DrawFrame(gb,x,y,36,36,2,frameColor,2);g.setColor(88,88,192);g.fillRect(x+2,y+2,32,16);g.setColor(255,255,255);g.drawString(mapname[mk],x+2+11,y+2,g.TOP|g.LEFT);g.setColor(0,0,0);g.drawString("DEF:" + maprevise[1][mk],x+2,y+2+16,g.TOP|g.LEFT);g.drawString("AVO:" + maprevise[0][mk],x+2,y+2+24,g.TOP|g.LEFT);}
/**将静态缓存绘制到背景缓存中*/public void DrawBuffer(Graphics g)//将静态缓存绘制到背景缓存中{g.drawImage(static_buffer,0,0,g.LEFT|g.TOP);}//攻击动画/***攻击动画*/public void atkcg(Graphics g){int c1 = 0;int c2 = 0;int picnum;for(int i = 0; i < 16;i++){tally++;cursortally++;DrawBuffer(g);//绘制静态缓存c1 = 0;c2 = 0;if(i/2 == 1||i/2 == 2){c1 = 1;}if(i/2 == 5||i/2 == 6){c2 = 1;}if(infoact[atktarget[currentatk]][1] > infoact[currentact][1]){picnum = actpic[infoact[atktarget[currentatk]][0]][4] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[atktarget[currentatk]][1] - x) * 16 - c1 + actorpos[picnum][0],(infoact[atktarget[currentatk]][2] - y) * 16 + actorpos[picnum][1],g.LEFT|g.TOP);picnum = actpic[infoact[currentact][0]][5] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[currentact][1] - x) * 16 + c2 + actorpos[picnum][0],(infoact[currentact][2] - y) * 16 + actorpos[picnum][1],g.LEFT|g.TOP);}else if(infoact[atktarget[currentatk]][1] < infoact[currentact][1]){picnum = actpic[infoact[atktarget[currentatk]][0]][5] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[atktarget[currentatk]][1] - x) * 16  + c1 + actorpos[picnum][0],(infoact[atktarget[currentatk]][2] - y) * 16 + actorpos[picnum][1],g.LEFT|g.TOP);picnum = actpic[infoact[currentact][0]][4] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[currentact][1] - x) * 16  - c2 + actorpos[picnum][0],(infoact[currentact][2] - y) * 16 + actorpos[picnum][1],g.LEFT|g.TOP);}else if(infoact[atktarget[currentatk]][2] > infoact[currentact][2]){picnum = actpic[infoact[atktarget[currentatk]][0]][3] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[atktarget[currentatk]][1] - x) * 16 + actorpos[picnum][0],(infoact[atktarget[currentatk]][2] - y) * 16  - c1 + actorpos[picnum][1],g.LEFT|g.TOP);picnum = actpic[infoact[currentact][0]][2] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[currentact][1] - x) * 16 + actorpos[picnum][0],(infoact[currentact][2] - y) * 16  + c2 + actorpos[picnum][1],g.LEFT|g.TOP);}else{picnum = actpic[infoact[atktarget[currentatk]][0]][2] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[atktarget[currentatk]][1] - x) * 16 + actorpos[picnum][0],(infoact[atktarget[currentatk]][2] - y) * 16 + c1 + actorpos[picnum][1],g.LEFT|g.TOP);picnum = actpic[infoact[currentact][0]][3] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[currentact][1] - x) * 16 + actorpos[picnum][0],(infoact[currentact][2] - y) * 16 - c2 + actorpos[picnum][1],g.LEFT|g.TOP);}DrawPerson(g);DrawLifeShow(g, currentact, atktarget[currentatk]);repaint();try{Thread.sleep(100);}catch(Exception e){}}}public void DrawMoveRange(Graphics g,int c){for(int j = 0;j<= MAP_MAX_HEIGHT;j++){for(int i = 0; i<= MAP_MAX_WIDTH;i++){if(i - x > SCREEN_MAX_WIDTH||i - x < 0||j - y > SCREEN_MAX_HEIGHT||j - y < 0){continue;}if(move[j][i] > -1){g.setColor(c);g.drawRect((i - x) * TILE_SIZE,(j - y) * TILE_SIZE,TILE_SIZE,TILE_SIZE);}}}}public void DrawPerson(Graphics g){int picnum;for(int i = 0; i < actnum; i++)//绘制人物{if(infoact[idact[i]][2] - y < 0||infoact[idact[i]][2] - y > 7||infoact[idact[i]][1] - x < 0||infoact[idact[i]][1] - x > 7||idact[idact[i]] == currentact)//屏幕显示外和获得焦点的人物不绘制{continue;}if(targetstate == 3&&idact[idact[i]] == atktarget[currentatk]){continue;}picnum = actpic[infoact[idact[i]][0]][0] + (tally/10)%2;g.drawImage(picact[picnum],(infoact[idact[i]][1] - x) * TILE_SIZE + actorpos[picnum][0],(infoact[idact[i]][2] - y) * TILE_SIZE + actorpos[picnum][1],g.LEFT|g.TOP);}if(targetstate != 3){if(currentact >= 0)//有人获得焦点的情况下绘制{if(showmovearea)//绘制选中人物移动范围{DrawMoveRange(gb,0x000000ff);}//绘制人物picnum = actpic[currentactkind][currentactstate] + (tally/10)%2;g.drawImage(picact[picnum],currentactSX * TILE_SIZE + actorpos[picnum][0] + currentactmovex,currentactSY * TILE_SIZE + actorpos[picnum][1] + currentactmovey,g.LEFT|g.TOP);}}}
/***处理光标*/public void DealCursor()//处理光标{switch(STATE){case 1:DrawCursor(gb,(SCREEN_WIDTH - 72) / 2, ((SCREEN_HEIGHT - 22 * 5)/6 + 22) * MenuFocus, 56, 6);break;case 2:switch(CurrentScene){case 1://地图移动for(int i = 0; i < actnum; i++){if(targetstate == 0){if(cursorSX == infoact[idact[i]][1] - x&&cursorSY == infoact[idact[i]][2] - y){cursortally = 0;currentact = idact[i];targetSX = cursorSX;targetSY = cursorSY;chooseact(currentact);//选中目标DealPersonInfo();break;}}if(targetstate == 0){currentact = -1;}}if(!moveaction){DrawCursor(gb,cursorSX * TILE_SIZE,cursorSY * TILE_SIZE,0,0);}break;case 2://菜单选择if(cursorSX >=4){DrawCursor(gb,16,TILE_SIZE + MenuFocus * TILE_SIZE,16,0);}else{DrawCursor(gb,80,TILE_SIZE + MenuFocus * TILE_SIZE,16,0);}break;case 3://攻击目标选择DrawCursor(gb,(infoact[idact[atktarget[currentatk]]][1] - x) * TILE_SIZE,(infoact[idact[atktarget[currentatk]]][2] - y) * TILE_SIZE,0,0);break;}break;}}//绘制光标(光标位置,光标框的大小)public void DrawCursor(Graphics g, int x, int y, int w, int h){g.drawImage(piccursor[0], x + 0 + (cursortally/30)%2, y + 0 + (cursortally/30)%2, g.LEFT|g.TOP);g.drawImage(piccursor[1], x + 10 - (cursortally/30)%2 + w, y + 0 + (cursortally/30)%2, g.LEFT|g.TOP);g.drawImage(piccursor[2], x + 0 + (cursortally/30)%2, y + 10 - (cursortally/30)%2 + h, g.LEFT|g.TOP);g.drawImage(piccursor[3], x + 10 - (cursortally/30)%2 + w, y + 10 - (cursortally/30)%2 + h, g.LEFT|g.TOP);}public void DrawStaticPic(Graphics g)//绘制静态图形{DrawMap(g);//绘制显示地图}public void DrawMap(Graphics g)//绘制地图{for(int j = 0; j <= SCREEN_MAX_HEIGHT; j++){for(int i = 0; i <= SCREEN_MAX_WIDTH; i++){g.drawImage(picmap[map[y + j][x + i]], i * TILE_SIZE, j * TILE_SIZE, g.TOP|g.LEFT);}}}//滚屏public void RollScreen(Graphics g, int dir){switch(dir){case 2:gb.drawImage(static_buffer, 0, TILE_SIZE, gb.TOP|gb.LEFT);g.drawImage(back_buffer, 0, 0, g.TOP|g.LEFT);for(int i = 0; i <= SCREEN_MAX_WIDTH; i++){g.drawImage(picmap[map[cursorMY-2][x + i]], i * TILE_SIZE, 0, g.TOP|g.LEFT);}break;case 8:gb.drawImage(static_buffer, 0, -TILE_SIZE, gb.TOP|gb.LEFT);g.drawImage(back_buffer, 0, 0, g.TOP|g.LEFT);for(int i = 0; i <= SCREEN_MAX_WIDTH; i++){g.drawImage(picmap[map[cursorMY+2][x + i]], i * TILE_SIZE, TILE_SIZE * SCREEN_MAX_HEIGHT, g.TOP|g.LEFT);}break;case 4:gb.drawImage(static_buffer, TILE_SIZE, 0, gb.TOP|gb.LEFT);g.drawImage(back_buffer, 0, 0, g.TOP|g.LEFT);for(int j = 0; j <= SCREEN_MAX_HEIGHT; j++){g.drawImage(picmap[map[y + j][cursorMX-2]], 0, j * TILE_SIZE, g.TOP|g.LEFT);}break;case 6:gb.drawImage(static_buffer, -TILE_SIZE, 0, gb.TOP|g.LEFT);g.drawImage(back_buffer, 0, 0, g.TOP|g.LEFT);for(int j = 0; j <= SCREEN_MAX_HEIGHT; j++){g.drawImage(picmap[map[y + j][cursorMX+2]], SCREEN_MAX_WIDTH * TILE_SIZE, j * TILE_SIZE, g.TOP|g.LEFT);}break;}}//移动能力判断public boolean movejudge(int x,int y){if(move[y][x] != -1){return true;}return false;}public void chooseact(int act){currentactkind = infoact[act][0];currentactMX = infoact[act][1];currentactMY = infoact[act][2];currentactmovearea = infoact[act][3];currentactatkmin = infoact[act][4];currentactatkmax = infoact[act][5];currentactSX = currentactMX - x;currentactSY = currentactMY - y;currentactmovex = 0;currentactmovey = 0;}//递规实现可移动范围的设定(地图限定数组,可移动数组(1为可以移动),当前人物位置,当前人物移动能力)void fmove(int mx,int my,int n){if(mx < 0||my < 0||mx > SCREEN_WIDTH||my > SCREEN_HEIGHT){return;}n = n - mappos[map[my][mx]][currentactkind];for(int k = 0; k < actnum; k++)//对于有敌人的位置是不可移动的{if(idact[k] == currentact){continue;}if(infoact[idact[k]][2] == my&&infoact[idact[k]][1] == mx){n = n - 100;break;}}if(n < 0){
//          try{Thread.sleep(20);
//          }
//          catch(Exception e)
//          {}return;}else{if(move[my][mx] == -1){move[my][mx] = (byte)n;}else if(move[my][mx] < n){move[my][mx] = (byte)n;}if(mx+1 <= MAP_MAX_HEIGHT){fmove(mx+1,my,n);}if(mx-1 >= 0){fmove(mx-1,my,n);}if(my+1 <= MAP_MAX_WIDTH){fmove(mx,my+1,n);}if(my-1 >= 0){fmove(mx,my-1,n);}}}//寻路void smove(int x,int y)//寻路算法{if(y+1 <= MAP_MAX_HEIGHT){if(move[y+1][x] == move[y][x] + mappos[map[y][x]][currentactkind]){smove(x,y+1);}}if(y-1 >=0){if(move[y-1][x] == move[y][x] + mappos[map[y][x]][currentactkind]){smove(x,y-1);}}if(x+1 <= MAP_MAX_WIDTH){if(move[y][x+1] == move[y][x] + mappos[map[y][x]][currentactkind]){smove(x+1,y);}}if(x-1 >= 0){if(move[y][x-1] == move[y][x] + mappos[map[y][x]][currentactkind]){smove(x-1,y);}}move[y][x] = (byte)(move[y][x] + 10);}//初始化人物信息public void initializeinfo(){for(int ih = 0; ih < rednum; ih++){for(int iw = 5; iw < 12; iw++){}}}public void keyPressed(int keyCode){if(!hasPressed){switch(keyCode){case UP:keyAction(2);hasPressed = true;break;case DOWN:keyAction(8);hasPressed = true;break;case LEFT:keyAction(4);hasPressed = true;break;case RIGHT:keyAction(6);hasPressed = true;break;case OK:keyAction(5);hasPressed = true;break;case LCOMMAND:keyAction(5);hasPressed = true;break;case RCOMMAND:keyAction(3);hasPressed = true;break;}}}public void keyReleased(int keyCode){hasPressed = false;hangfire = 0;if(targetstate == 0){if(cursorSX == currentactSX&&cursorSY == currentactSY){currentactstate = 1;}else{currentactstate = 0;}}}public void keyAction(int kC){kCode = kC;switch(STATE){case 0:break;case 1:switch(kC){case 2:case 4:MenuFocus--;if(MenuFocus<0){MenuFocus = 4;}break;case 8:case 6:MenuFocus++;if(MenuFocus>4){MenuFocus = 0;}break;case 5:switch(MenuFocus){case 0://开始新游戏STATE = 2;newGame();break;case 1:break;case 2:break;case 3:break;case 4:myMid.exit();break;}break;}break;case 2:switch(CurrentScene){case 1://光标移动状态hangfire = 100;switch(kC){case 5://按中键switch(targetstate){case 0://选择目标if(currentactstate == 1)//目标获得焦点{for(int i = 0; i<= MAP_MAX_HEIGHT; i++){for(int j = 0; j <= MAP_MAX_WIDTH; j++){move[i][j] = -1;}}fmove(currentactMX, currentactMY, currentactmovearea + mappos[map[currentactMY][currentactMX]][currentactkind]);currentactstate = 2;targetstate = 1;showmovearea = true;chooseact(currentact);//选中目标}else if(currentactstate == 0){CurrentMenu = 0;CurrentScene = 2;MenuFocus = 0;}break;case 1:if(movejudge(cursorMX,cursorMY)){smove(cursorMX,cursorMY);//寻路targetSX = currentactSX;targetSY = currentactSY;moveaction = true;showmovearea = false;}break;/*case 2:currentactSX = targetSX;currentactSY = targetSY;currentactMX = currentactSX + x;currentactMY = currentactSY + y;infoact[currentact][1] = currentactMX;infoact[currentact][2] = currentactMY;currentactmovex = 0;currentactmovey = 0;targetstate = 0;currentactstate = 0;break;*/}break;case 3:switch(targetstate){case 1:currentactstate = 0;targetstate = 0;showmovearea = false;cursorSX = currentactSX;cursorSY = currentactSY;break;/*case 2:targetstate = 1;currentactmovex = 0;currentactmovey = 0;targetSX = currentactSX;targetSY = currentactSY;break;*/}break;}break;case 2://菜单选择switch(kC){case 2://上键MenuFocus--;if(MenuFocus < 0){MenuFocus = MenuInfo[CurrentMenu] - 1;}break;case 8://下键MenuFocus++;if(MenuFocus > MenuInfo[CurrentMenu] - 1){MenuFocus = 0;}break;case 5://左软,中,键switch(CurrentMenu){case 0://系统菜单switch(MenuFocus){case 2://中断MenuFocus = 0;STATE = 1;break;}break;case 1://攻击选择菜单if(MenuFocus == MenuInfo[CurrentMenu] - 1)//待机{CurrentScene = 1;currentactSX = targetSX;currentactSY = targetSY;currentactMX = currentactSX + x;currentactMY = currentactSY + y;infoact[currentact][1] = currentactMX;infoact[currentact][2] = currentactMY;currentactmovex = 0;currentactmovey = 0;targetstate = 0;currentactstate = 0;}else if(MenuFocus == MenuInfo[CurrentMenu] - 2)//攻击{CurrentScene = 3;currentactSX = targetSX;currentactSY = targetSY;currentactMX = currentactSX + x;currentactMY = currentactSY + y;infoact[currentact][1] = currentactMX;infoact[currentact][2] = currentactMY;currentactmovex = 0;currentactmovey = 0;}break;}break;case 3://右软键switch(CurrentMenu){case 0:CurrentScene = 1;break;case 1:CurrentScene = 1;targetstate = 1;showmovearea = true;currentactmovex = 0;currentactmovey = 0;targetSX = currentactSX;targetSY = currentactSY;cursorSX = currentactSX;cursorSY = currentactSY;break;}break;}break;case 3://攻击模式switch(kC){case 2:case 4:currentatk--;if(currentatk == 0){currentatk = atktarget[0];}break;case 8:case 6:currentatk++;if(currentatk > atktarget[0]){currentatk = 1;}break;case 5:switch(targetstate){case 1:targetstate = 2;break;case 2:targetstate = 3;break;}break;case 3:CurrentScene = 2;targetstate = 1;break;}System.out.println("  " + currentatk + "  " + atktarget[currentatk]);break;}break;}}/*//小图在图片中的坐标(ix,iy)//绘制在屏幕上的坐标(sx,xy)public void paintImage(Graphics g,Image pic, int ix, int iy, int width, int height,int sx, int sy){g.setClip(sx,sy,width,height);g.drawImage(pic, sx - ix, sy - iy, g.LEFT|g.TOP);g.setClip(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);}*//*//读取静态信息private void readStaticInfo(){java.io.InputStream is = null;try{is = getClass().getResourceAsStream("/info/staticinfo.txt");if (is != null){readstatic(is);is.close();}else{System.out.println("load static wrong");}}catch (Exception e){System.out.println("static ");}}//加载静态信息public void readstatic(InputStream is){try{int c;int actpicnum;//人物图片类型数目int mappicnum;//地图图片类型数目int vocationnum;//职业数目//职业属性//System.out.println("vocation");c = is.read();vocationnum = c;vocation = new byte[vocationnum][6];for(int ih = 0; ih < vocationnum; ih++){for(int iw = 0; iw < 6; iw++){c = is.read();vocation[ih][iw] = (byte)c;}}//System.out.println("0");//图片偏移c = is.read();actpicnum = c;actorpos = new byte[actpicnum * 12][2];for(int ih = 0; ih < actpicnum * 12; ih++){for(int iw = 0; iw < 2; iw++){c = is.read();if(c >= 128){c = 128 - c;}actorpos[ih][iw] = (byte)c;}}//System.out.println("1");//图片位差actpic = new byte[2][6];for(int ih = 0; ih < 2; ih++){for(int iw = 0; iw < 6; iw++){c = is.read();actpic[ih][iw] = (byte)c;//System.out.print(" "+c);}//System.out.println("");}//System.out.println("2");//地形修正c = is.read();mappicnum = c;maprevise = new byte[2][mappicnum];for(int ih = 0; ih < 2; ih++){for(int iw = 0; iw < mappicnum; iw++){c = is.read();maprevise[ih][iw] = (byte)c;//System.out.print(" "+c);}//System.out.println("");}//System.out.println("3");//地形移动力修正mappos = new byte [mappicnum][actpicnum];for(int ih = 0; ih < mappicnum; ih++){for(int iw = 0; iw < actpicnum; iw++){c = is.read();mappos[ih][iw] = (byte)c;//System.out.print(" "+c);}//System.out.println("");}//System.out.println("4");c = is.read();bluenum = (byte)c;//初始蓝方职业,等级,五行属性,for(int ih = 0; ih < bluenum; ih++){c = is.read();blueinfo[ih][0] = (byte)c;//职业c = is.read();blueinfo[ih][3] = (byte)c;//等级c = is.read();blueinfo[ih][4] = (byte)c;//五行属性}}catch(Exception e){System.out.println(e+"读取静态信息失败");}}//按章节读入动态信息private void readChapterInfo(byte chapter){java.io.InputStream is = null;try{is = getClass().getResourceAsStream("/info/Chapter"+gameChapter+".txt");if (is != null){readchapter(is,chapter);is.close();}else{System.out.println("load Chapter wrong");}}catch (Exception e){System.out.println("Chapter ");}}//加载动态信息public void readchapter(InputStream is,byte chapter){try{//System.out.println("6666666666");int c;c = is.read();MAP_MAX_WIDTH = c - 1;//地图宽//System.out.println("MAP_MAX_WIDTH =" + MAP_MAX_WIDTH);c = is.read();MAP_MAX_HEIGHT = c - 1;//地图高//System.out.println("MAP_MAX_HEIGHT =" + MAP_MAX_HEIGHT);map = new byte[MAP_MAX_HEIGHT+1][MAP_MAX_WIDTH+1];//System.out.println("9");for(int ih = 0; ih <= MAP_MAX_HEIGHT; ih++){for(int iw = 0; iw <= MAP_MAX_WIDTH; iw++){c = is.read();map[ih][iw] = (byte)c;//地图信息//System.out.print(" "+map[ih][iw]);}//System.out.println("");}c = is.read();rednum = (byte)c;//红方数量//System.out.println("rednum = "+rednum);redinfo = new byte[rednum][12];for(int ih = 0; ih < rednum; ih++)//红方初始信息(类型,坐标,等级,属性){for(int iw = 0; iw < 5; iw++){c = is.read();redinfo[ih][iw] = (byte)c;//人物信息//System.out.print(""+redinfo[ih][iw]);}//System.out.println();}//System.out.println("888888888888");//蓝方初始信息(角色编号,坐标)for(int ih = 0; ih < bluenum; ih++){for(int iw = 1; iw < 3; iw++){c = is.read();blueinfo[ih][iw] = (byte)c;}}}catch(Exception e){System.out.println("");}}//读取存盘记录private void readStore(int index){try{ByteArrayInputStream bais;DataInputStream      dis;byte                 data[];myStore = RecordStore.openRecordStore("save"+Integer.toString(index),true);try{data = myStore.getRecord(2);bais = new ByteArrayInputStream(data);dis  = new DataInputStream(bais);//  m[1] = dis.readInt();dis.close();}catch (Exception ioe){System.out.println(ioe + "111111");}myStore.closeRecordStore();}catch (RecordStoreException rse){System.out.println(rse + "22222");}}//写入存盘记录private void writeStore(int index){try{ByteArrayOutputStream baos;DataOutputStream      das;byte                 data[];myStore = RecordStore.openRecordStore("save"+Integer.toString(index),true);try{baos = new ByteArrayOutputStream();das = new DataOutputStream(baos);das.writeLong(System.currentTimeMillis());//   das.writeInt(s[1]);data = baos.toByteArray();das.close();}catch (Exception ioe){throw new RecordStoreException();}if (myStore.getNumRecords() == 0){myStore.addRecord(data,0,8);myStore.addRecord(data,8,12);}else{myStore.setRecord(1,data,0,8);myStore.setRecord(2,data,8,12);}myStore.closeRecordStore();}catch (RecordStoreException rse){//System.out.println(rse + "333633");}}*/
}

继承Canvas和Runnable接口,这样这个类就有了画笔和run这个方法,通过run这个死循环,不停的对画布做更新,这个就是j2me的原理,上面的代码写的很简洁基本实现了站起游戏的功能,因为j2me这个项目在10年的时候就停止更新了,jdk需要1.5以下的版本支持,所以想要调试很麻烦(现在想找个老版本的安装真的是不容易),所以我这直接贴出代码,大家自己看看,寻找下思路如果想进一步了解战棋游戏的做法,那么我们往下看,下面我们会几种分析一个java的例子,因为这个不需要上面j2me环境的限制,所以我们那下面这个java例子来分析这个java例子的作者是cping1982大神,做过java小游戏的可能都对他的Lgame引擎都有个耳闻,这里我们看看他写的SLG小例子

代码,惯例从启动开始

package org.loon.simple.slg.ai;import java.applet.Applet;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;/*** Copyright 2008 - 2009* * Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.* * @project loonframework* @author chenpeng* @email:ceponline@yahoo.com.cn* @version 0.1*/
public class Main extends Applet {/*** */private static final long serialVersionUID = 1L;public void init() {this.setBackground(Color.black);this.add(new GameCanvas());}public static void main(String[] args) {java.awt.EventQueue.invokeLater(new Runnable() {public void run() {Frame frame = new Frame();frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});frame.add(new GameCanvas());frame.pack();frame.setResizable(false);frame.setTitle("Java战棋类游戏AI及寻径处理入门示例");frame.setLocationRelativeTo(null);frame.setVisible(true);}});}}

这个类中有一个方法,就是我上面说的public static void main(String[] args){},这个是我们程序要执行的,它里面定义了一个死循环,这个跟j2me很像了,因为Lgame可以j2ee和j2me之间相互移植,所以看上去一样也很正常,真佩服作者,这个类里面没有什么东西,我们接着看GameCanvas,这个是画布,我们需要的东西应该都在这

package org.loon.simple.slg.ai;import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;/*** Copyright 2008 - 2009* * Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.* * @project loonframework* @author chenpeng* @email:ceponline@yahoo.com.cn* @version 0.1*/
public class GameCanvas extends Canvas implements Runnable, KeyListener {/*** */private static final long serialVersionUID = 1L;// 地图private Map map = null;// 菜单private Menu menu = null;// 背景窗体private Image screen;// 地图图片private Image mapImage;private Graphics2D graphics;private String state;private int lastX;private int lastY;private int curX;private int curY;private int turn = 1;private int actionUnit = -1;private int moveCount = 0;private int[][] moveList;private int[][] movingList;private int[][] attackList;private int maxX;private int maxY;private List unitList = Collections.synchronizedList(new ArrayList(10));// 战斗个体图private Image[] unitImages = Utility.getSplitImages("image/unit.png", tile,tile);private Image[] iconImages = Utility.getSplitImages("image/icon.png", tile,tile);private Image[] listImages = Utility.getSplitImages("image/list.png", tile,tile);private Thread gameLoop;private int eventCode = -1;final static int tile = 32;public GameCanvas() {actionUnit = -1;state = "战斗开始";turn = 1;this.setBackground(Color.BLACK);this.map = new Map("map.txt", tile);// 地图this.mapImage = this.map.getMapImage();this.maxX = map.getMaxX();this.maxY = map.getMaxY();this.moveList = new int[maxX][maxY];this.movingList = new int[maxX][maxY];this.attackList = new int[maxX][maxY];int width = maxX * tile;int height = maxY * tile;// 菜单this.menu = new Menu(maxX - 1);// 创建角色:name=空罐少女,team=0(我军),imageindex=3,x=7,y=1,以下雷同createRole("空罐少女", 0, 0, 3, 7, 1);createRole("猫猫1", 0, 1, 6, 1, 2);createRole("猫猫2", 0, 0, 3, 2, 6);// 创建角色:name=躲猫兵团1,team=1(敌军),imageindex=6,x=4,y=5,以下雷同createRole("躲猫兵团1", 1, 2, 4, 4, 5);createRole("躲猫兵团2", 1, 2, 4, 8, 5);createRole("躲猫兵团3", 1, 2, 4, 5, 7);createRole("躲猫兵团4", 1, 2, 4, 7, 2);this.screen = Utility.createImage(width, height, true);this.graphics = (Graphics2D) screen.getGraphics();// 初始化this.initRange();// 绘制图像this.drawBattle();this.setPreferredSize(new Dimension(width - 2, height - 2));this.setFocusable(true);this.addKeyListener(this);// 开始构建游戏this.mainLoop();}public void mainLoop() {gameLoop = new Thread(this);gameLoop.start();}public void run() {for (;;) {long start = System.currentTimeMillis();long end = System.currentTimeMillis();long time = end - start;long sleepTime = 20L - time;if (sleepTime < 0L) {sleepTime = 0L;}this.eventClick();try {Thread.sleep(sleepTime);} catch (InterruptedException e) {}}}/*** 事件触发* */public synchronized void eventClick() {switch (eventCode) {// 按下Enter,开始触发游戏事件case KeyEvent.VK_ENTER:int index = 0;// 当游戏状态为[状态显示]下if (state.equalsIgnoreCase("状态显示")) {// 光标指向我方未行动角色index = getRoleIdx(0, curX, curY);if ((index > -1) && (getRole(index).action == 0)) {state = "角色移动";actionUnit = getRoleIdx(0, curX, curY);// 绘制移动范围setMoveRange();movingList[curX][curY] = moveCount;drawBattle();// 光标指向敌方未行动角色} else if (getRoleIdx(1, curX, curY) > -1) {state = "移动范围";actionUnit = getRoleIdx(1, curX, curY);setMoveRange();drawBattle();// 查看角色情报} else {state = "情报查看";openMenu(0);drawBattle();}}// 选择移动else if (state.equalsIgnoreCase("角色移动")) {// 无法移动的区域if (moveList[curX][curY] < 0) {return;}// 监测移动地点if ((getRoleIdx(0, curX, curY) == -1)|| (moveList[curX][curY] == 0)) {lastX = getRole(actionUnit).x;lastY = getRole(actionUnit).y;moveRole();state = "行动菜单";// 绘制攻击范围setAttackRange(true);// 判定菜单项if (isAttackCheck()) {openMenu(2);} else {openMenu(1);}drawBattle();}}// 当角色移动后else if (state.equalsIgnoreCase("行动菜单")) {if (menu.getMenuItem(menu.cur).equalsIgnoreCase("攻击")) {state = "进行攻击";closeMenu();drawBattle();} else if (menu.getMenuItem(menu.cur).equalsIgnoreCase("待机")) {state = "状态显示";closeMenu();getRole(actionUnit).action = 1;actionUnit = -1;initRange();drawBattle();}}// 攻击时else if (state.equalsIgnoreCase("进行攻击")) {// 无法攻击if (attackList[curX][curY] < 2) {return;}// 当指定地点敌方存在时if ((index = getRoleIdx(1, curX, curY)) > -1) {// 删除List中敌方角色(此处可设定减血规范)unitList.remove(index);state = "状态显示";// 改变行动状态getRole(actionUnit).action = 1;actionUnit = -1;initRange();drawBattle();}}// 查看角色移动范围else if (state.equalsIgnoreCase("移动范围")) {state = "状态显示";Role role = getRole(actionUnit);curX = role.x;curY = role.y;actionUnit = -1;initRange();drawBattle();}// 查看角色情报else if (state.equalsIgnoreCase("情报查看")) {// 本回合战斗结束if (menu.getMenuItem(menu.cur).equalsIgnoreCase("结束")) {closeMenu();curX = 0;curY = 0;setBeforeAction();state = "战斗结束";drawBattle();}}// 我军开始行动else if (state.equalsIgnoreCase("战斗开始")) {state = "状态显示";drawBattle();}// 敌军开始行动else if (state.equalsIgnoreCase("战斗结束")) {state = "敌方行动";enemyAction();setBeforeAction();turn = turn + 1;state = "战斗开始";drawBattle();}break;// 按下ESC,取消已做选择case KeyEvent.VK_ESCAPE:if (state.equalsIgnoreCase("角色移动")) // 移动{state = "状态显示";Role role = (Role) unitList.get(actionUnit);curX = role.x;curY = role.y;actionUnit = -1;initRange();drawBattle();} else if (state.equalsIgnoreCase("行动菜单")) // 移动后{state = "角色移动";closeMenu();setAttackRange(false); // 不显示攻击范围Role role = (Role) unitList.get(actionUnit);role.x = lastX;role.y = lastY;drawBattle();} else if (state.equalsIgnoreCase("进行攻击")) // 攻击状态{state = "行动菜单";Role role = (Role) unitList.get(actionUnit);curX = role.x;curY = role.y;openMenu(menu.menuType);drawBattle();} else if (state.equalsIgnoreCase("移动范围")) { // 移动范围state = "状态显示";Role role = (Role) unitList.get(actionUnit);curX = role.x;curY = role.y;actionUnit = -1;initRange();drawBattle();}else if (state.equalsIgnoreCase("情报查看")) // 角色情报{state = "状态显示";closeMenu();drawBattle();}else if (state.equalsIgnoreCase("战斗开始")) // 我军行动{state = "状态显示";drawBattle();}else if (state.equalsIgnoreCase("战斗结束")) // 敌军行动{state = "敌方行动";enemyAction();setBeforeAction();turn = turn + 1;state = "战斗开始";drawBattle();}break;}if (eventCode > -1) {eventCode = -1;}}/*** 初始化各项范围参数* */public synchronized void initRange() {for (int y = 0; y <= maxY - 1; y++) {for (int x = 0; x <= maxX - 1; x++) {moveCount = 0;moveList[x][y] = -1;movingList[x][y] = -1;attackList[x][y] = 0;}}}/*** 获得移动到指定地点所需步数* * @param x* @param y* @return*/public synchronized int getMoveCount(int x, int y) {if ((x < 0) || (x > maxX - 1) || (y < 0) || (y > maxY - 1)) {// 无法移动返回-1return -1;}return moveList[x][y];}/*** 设定移动步数* * @param x* @param y* @param count*/public synchronized void setMoveCount(int x, int y, int count) {Role role = getRole(actionUnit);// 当为我军时if (role.team == 0) {if (getRoleIdx(1, x, y) > -1) {return;}} else {if (getRoleIdx(0, x, y) > -1) {return;}}int cost = map.getMapCost(x, y);// 指定位置无法进入if (cost < 0) {return;}count = count + cost;// 移动步数超过移动能力if (count > role.move) {return;}// 获得移动所需步数if ((moveList[x][y] == -1) || (count < moveList[x][y])) {moveList[x][y] = count;}}/*** 设定攻击范围* * @param isAttack*/public synchronized void setAttackRange(final boolean isAttack) {try {int x, y, point;if (isAttack == true) {point = 2;} else {point = 1;}Role role = getRole(actionUnit);x = role.x;y = role.y;// 判定攻击点if (x > 0) {attackList[x - 1][y] = point;}if (y > 0) {attackList[x][y - 1] = point;}if (x < maxX - 1) {attackList[x + 1][y] = point;}if (y < maxY - 1) {attackList[x][y + 1] = point;}} catch (Exception e) {}}/*** 判断是否能做出攻击* * @return*/public synchronized boolean isAttackCheck() {for (int i = 0; i < unitList.size(); i++) {Role role = getRole(i);if (role.team != 1) {continue;}if (attackList[role.x][role.y] == 2) {return true;}}return false;}/*** 设定菜单* * @param menuType*/public synchronized void openMenu(int menuType) {menu.visible = true;menu.setMenuType(menuType);menu.cur = 0;}/*** 关闭菜单* */public synchronized void closeMenu() {menu.visible = false;}/*** 设定所有角色参与行动* */public synchronized void setBeforeAction() {for (Iterator it = unitList.iterator(); it.hasNext();) {Role role = (Role) it.next();role.setAction(0);}}/*** 返回指定索引下角色* * @param index* @return*/public synchronized Role getRole(final int index) {if (unitList != null && index > -1) {return (Role) unitList.get(index);}return null;}/*** 设定移动路线* */public synchronized void setMoveCourse() {if (moveList[curX][curY] == -1) {return;}if (movingList[curX][curY] == moveCount) {return;}// 选择可行的最短路径if ((movingList[redressX(curX - 1)][curY] != moveCount)&& (movingList[curX][redressY(curY - 1)] != moveCount)&& (movingList[redressX(curX + 1)][curY] != moveCount)&& (movingList[curX][redressY(curY + 1)] != moveCount)|| (moveCount + map.getMapCost(curX, curY) > getRole(actionUnit).move)) {for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {movingList[i][j] = -1;}}int x = curX;int y = curY;moveCount = moveList[curX][curY];movingList[x][y] = moveCount;// 获得移动路径for (int i = moveCount; i > 0; i--) {switch (setMoveCouse(x, y)) {case 0:x = x - 1;break;case 1:y = y - 1;break;case 2:x = x + 1;break;case 3:y = y + 1;break;case 4:break;}}moveCount = moveList[curX][curY];movingList[x][y] = 0;return;}// 获得矫正的移动步数moveCount = moveCount + map.getMapCost(curX, curY);if (movingList[curX][curY] > -1) {moveCount = movingList[curX][curY];for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {if (movingList[i][j] > movingList[curX][curY]) {movingList[i][j] = -1;}}}}movingList[curX][curY] = moveCount;}/*** 设定最短移动路径* * @param x* @param y* @return*/public synchronized int setMoveCouse(int x, int y) {// 判定左方最短路径if ((x > 0) && (moveList[x - 1][y] > -1)&& (moveList[x - 1][y] < moveList[x][y])&& (moveList[x - 1][y] == moveCount - map.getMapCost(x, y))) {moveCount = moveCount - map.getMapCost(x, y);movingList[x - 1][y] = moveCount;return 0;}// 判定上方最短路径if ((y > 0) && (moveList[x][y - 1] > -1)&& (moveList[x][y - 1] < moveList[x][y])&& (moveList[x][y - 1] == moveCount - map.getMapCost(x, y))) {moveCount = moveCount - map.getMapCost(x, y);movingList[x][y - 1] = moveCount;return 1;}// 判定右方最短路径if ((x < maxX - 1) && (moveList[x + 1][y] > -1)&& (moveList[x + 1][y] < moveList[x][y])&& (moveList[x + 1][y] == moveCount - map.getMapCost(x, y))) {moveCount = moveCount - map.getMapCost(x, y);movingList[x + 1][y] = moveCount;return 2;}// 判定下方最短路径if ((y < maxY - 1) && (moveList[x][y + 1] > -1)&& (moveList[x][y + 1] < moveList[x][y])&& (moveList[x][y + 1] == moveCount - map.getMapCost(x, y))) {moveCount = moveCount - map.getMapCost(x, y);movingList[x][y + 1] = moveCount;return 3;}return 4;}/*** 移动角色* */public synchronized void moveRole() {state = "开始移动";int x = lastX;int y = lastY;int direction;// 移动方向判定for (int i = 0; i <= moveCount; i++) {direction = 4;if ((x > 0)&& (moveList[x - 1][y] > -1)&& (movingList[x - 1][y] - map.getMapCost(x - 1, y) == movingList[x][y]))direction = 0; // 左if ((y > 0)&& (moveList[x][y - 1] > -1)&& (movingList[x][y - 1] - map.getMapCost(x, y - 1) == movingList[x][y]))direction = 1; // 上if ((x < maxX - 1)&& (moveList[x + 1][y] > -1)&& (movingList[x + 1][y] - map.getMapCost(x + 1, y) == movingList[x][y]))direction = 2; // 右if ((y < maxY - 1)&& (moveList[x][y + 1] > -1)&& (movingList[x][y + 1] - map.getMapCost(x, y + 1) == movingList[x][y]))direction = 3; // 下switch (direction) {case 0:x = x - 1;break;case 1:y = y - 1;break;case 2:x = x + 1;break;case 3:y = y + 1;break;case 4:break;}Role role = getRole(actionUnit);role.setX(x);role.setY(y);drawBattle();Utility.wait(10);}getRole(actionUnit).x = curX;getRole(actionUnit).y = curY;Utility.wait(10);}/*** 设定移动范围*/public synchronized void setMoveRange() {Role role = getRole(actionUnit);int x = role.x;int y = role.y;int area = role.move; // 有效范围moveList[x][y] = 0; // 设定现在为移动0步for (int count = 0; count <= area - 1; count++) {for (int j = redressY(y - area); j < redressY(y + area); j++) {for (int i = redressX(x - (area - Math.abs(y - j))); i <= redressX(x+ (area - Math.abs(y - j))); i++) {// 如果能够移动指定步数if ((getMoveCount(i - 1, j) == count)|| (getMoveCount(i, j - 1) == count)|| (getMoveCount(i + 1, j) == count)|| (getMoveCount(i, j + 1) == count)) {setMoveCount(i, j, count);}}}}area = area + 1; // 射程for (int j = redressY(y - area); j <= redressY(y + area); j++) {for (int i = redressX(x - (area - Math.abs(y - j))); i <= redressX(x+ (area - Math.abs(y - j))); i++) {// 远程攻击if ((getMoveCount(i - 1, j) > -1)|| (getMoveCount(i, j - 1) > -1)|| (getMoveCount(i + 1, j) > -1)|| (getMoveCount(i, j + 1) > -1)) {attackList[i][j] = 1;}}}}/*** 获得指定索引及分组下角色* * @param team* @param x* @param y* @return*/public synchronized int getRoleIdx(final int team, final int x, final int y) {int index = 0;for (Iterator it = unitList.iterator(); it.hasNext();) {Role role = (Role) it.next();if (x == role.x && y == role.y && team == role.team) {return index;}index++;}return -1;}/*** 创建角色* * @param name* @param team* @param imageIndex* @param move* @param x* @param y*/private synchronized void createRole(String name, int team, int imageIndex,int move, int x, int y) {unitList.add(new Role(name, team, unitImages[imageIndex], move, x, y));}/*** 绘制画面* */public synchronized void drawBattle() {int count = 0;// 绘制地图graphics.drawImage(mapImage, 0, 0, null);// 移动范围绘制if ((state.equalsIgnoreCase("角色移动"))|| (state.equalsIgnoreCase("移动范围"))) {for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {if (moveList[i][j] > -1) {graphics.drawImage(iconImages[2], i * tile, j * tile,null);} else if (attackList[i][j] > 0) {graphics.drawImage(iconImages[3], i * tile, j * tile,null);}}}}// 角色绘制for (int index = 0; index < unitList.size(); index++) {Role role = (Role) unitList.get(index);if (index == actionUnit) {// 当前控制角色处理(此示例未加入特殊处理)graphics.drawImage(role.getImage(), role.getX() * tile, role.getY()* tile, null);} else {graphics.drawImage(role.getImage(), role.getX() * tile, role.getY()* tile, null);}// 已行动完毕if (role.action == 1) {graphics.drawImage(unitImages[3], role.getX() * tile, role.getY()* tile, null);}}// 攻击范围绘制if (state.equalsIgnoreCase("进行攻击")) {for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {int result = attackList[i][j];if (result == 2) {graphics.drawImage(iconImages[3], i * tile, j * tile,null);}// 标注选中的攻击对象if (result == 2 && getRoleIdx(1, i, j) > -1 && curX == i&& curY == j) {graphics.drawImage(iconImages[4], i * tile, j * tile,null);}}}}// 绘制移动路线if (state.equalsIgnoreCase("角色移动")) {for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {if (movingList[i][j] == -1) {continue;}count = 0;if ((movingList[i][j] == 0)|| (movingList[i][j] == moveCount)) {if ((i > 0)&& (movingList[i - 1][j] > -1)&& ((movingList[i - 1][j]- map.getMapCost(i - 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i - 1][j]))) {count = 1;}if ((j > 0)&& (movingList[i][j - 1] > -1)&& ((movingList[i][j - 1]- map.getMapCost(i, j - 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j - 1]))) {count = 2;}if ((i < maxX-1)&& (movingList[i + 1][j] > -1)&& ((movingList[i + 1][j]- map.getMapCost(i + 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i + 1][j]))) {count = 3;}if ((j < maxY-1)&& (movingList[i][j + 1] > -1)&& ((movingList[i][j + 1]- map.getMapCost(i, j + 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j + 1]))) {count = 4;}if (movingList[i][j] != 0) {count = count + 4;}} else {count = 6;if ((i > 0)&& (movingList[i - 1][j] > -1)&& ((movingList[i - 1][j]- map.getMapCost(i - 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i - 1][j]))) {count = count + 1;}if ((j > 0)&& (movingList[i][j - 1] > -1)&& ((movingList[i][j - 1]- map.getMapCost(i, j - 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j - 1]))) {count = count + 2;}if ((i < maxX-1)&& (movingList[i + 1][j] > -1)&& ((movingList[i + 1][j]- map.getMapCost(i + 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i + 1][j]))) {count = count + 3;}if ((j < maxY-1)&& (movingList[i][j + 1] > -1)&& ((movingList[i][j + 1]- map.getMapCost(i, j + 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j + 1]))) {count = count + 5;}}if (count > 0) {graphics.drawImage(iconImages[count + 4], i * tile, j* tile, null);}}}}// 菜单if (menu.visible) {Utility.setAlpha(graphics, 0.50f);graphics.drawImage(listImages[0], menu.getLeft(curX) * tile, 0,null);for (int i = 1; i <= menu.width; i++) {graphics.drawImage(listImages[1], (menu.getLeft(curX) + i)* tile, 0, null);}graphics.drawImage(listImages[2],(menu.getLeft(curX) + menu.width + 1) * tile, 0, null);for (int j = 1; j <= menu.height; j++) {graphics.drawImage(listImages[3], menu.getLeft(curX) * tile, j* tile, null);for (int i = 1; i <= menu.width; i++) {graphics.drawImage(listImages[4], (menu.getLeft(curX) + i)* tile, j * tile, null);}graphics.drawImage(listImages[5], (menu.getLeft(curX)+ menu.width + 1)* tile, j * tile, null);}graphics.drawImage(listImages[6], menu.getLeft(curX) * tile,(menu.height + 1) * tile, null);for (int i = 1; i <= menu.width; i++) {graphics.drawImage(listImages[7], (menu.getLeft(curX) + i)* tile, (menu.height + 1) * tile, null);}graphics.drawImage(listImages[8],(menu.getLeft(curX) + menu.width + 1) * tile,(menu.height + 1) * tile, null);Utility.setAlpha(graphics, 1.0f);// 写入文字graphics.drawImage(iconImages[1], (menu.getLeft(curX) + 1) * tile,(menu.cur + 1) * tile, null);for (int j = 1; j <= menu.height; j++) {graphics.setColor(Color.white);Utility.drawDefaultString(menu.getMenuItem(j - 1), graphics,(menu.getLeft(curX) + 2) * tile, ((j * tile)) + 24, 0,23);}}// 显示状态if (state.equalsIgnoreCase("状态显示")) {int i = getRoleIdx(0, curX, curY);if (i == -1) {i = getRoleIdx(1, curX, curY);}if (i > -1) {Role role = (Role) unitList.get(i);Utility.setAlpha(graphics, 0.75f);graphics.drawImage(listImages[0], menu.getLeft(curX) * tile, 0,null);graphics.drawImage(listImages[1], (menu.getLeft(curX) + 1)* tile, 0, null);graphics.drawImage(listImages[1], (menu.getLeft(curX) + 2)* tile, 0, null);graphics.drawImage(listImages[2], (menu.getLeft(curX) + 3)* tile, 0, null);graphics.drawImage(listImages[3], (menu.getLeft(curX)) * tile,tile, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 1)* tile, tile, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 2)* tile, tile, null);graphics.drawImage(listImages[5], (menu.getLeft(curX) + 3)* tile, tile, null);graphics.drawImage(listImages[3], menu.getLeft(curX) * tile,64, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 1)* tile, 64, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 2)* tile, 64, null);graphics.drawImage(listImages[5], (menu.getLeft(curX) + 3)* tile, 64, null);graphics.drawImage(listImages[6], (menu.getLeft(curX)) * tile,96, null);graphics.drawImage(listImages[7], (menu.getLeft(curX) + 1)* tile, 96, null);graphics.drawImage(listImages[7], (menu.getLeft(curX) + 2)* tile, 96, null);graphics.drawImage(listImages[8], (menu.getLeft(curX) + 3)* tile, 96, null);Utility.setAlpha(graphics, 1.0f);// 显示角色数据graphics.drawImage(role.getImage(), (menu.getLeft(curX) + 1)* tile + 16, tile, null);Utility.drawDefaultString("HP:" + role.getHp(), graphics, (menu.getLeft(curX) + 1)* tile + 12, 75, 1, 12);Utility.drawDefaultString("MV:" + role.getMove(), graphics,(menu.getLeft(curX) + 1) * tile + 12, 88, 1, 12);}}// 战斗回合if (state.equalsIgnoreCase("战斗开始") || state.equalsIgnoreCase("战斗结束")) {Utility.setAlpha(graphics, 0.5f);graphics.setColor(Color.black);graphics.fillRect(0, 90, 320, 140);graphics.setColor(Color.white);Utility.setAlpha(graphics, 1.0f);Utility.drawDefaultString("第" + turn + "回合", graphics, 120, 160, 0,25);}// 我方移动else if (state.equalsIgnoreCase("开始移动")) {// 未添加处理} else if (state.equalsIgnoreCase("敌方行动")) {for (int i = unitList.size() - 1; i > -1; i--) {Role role = (Role) unitList.get(i);// 敌军,且无法再次移动和攻击if (role.team == 1 && role.action == 1) {int x = role.x;int y = role.y;int index = 0;// 当敌军移动地点附近才能在我方人物时, 直接删除List中我方角色(实际开发中应加入相应判定)if ((index = getRoleIdx(0, x, y + 1)) > -1&& !role.isAttack()) {unitList.remove(index);} else if ((index = getRoleIdx(0, x, y - 1)) > -1&& !role.isAttack()) {unitList.remove(index);} else if ((index = getRoleIdx(0, x + 1, y)) > -1&& !role.isAttack()) {unitList.remove(index);} else if ((index = getRoleIdx(0, x - 1, y)) > -1&& !role.isAttack()) {unitList.remove(index);}role.setAttack(true);}}} else {// 绘制光标graphics.drawImage(iconImages[0], curX * tile, curY * tile, null);}// 刷新画面this.repaint();}public void paint(Graphics g) {g.drawImage(screen, 0, 0, null);g.dispose();}public void update(Graphics g) {paint(g);}/*** 矫正x坐标* * @param x* @return*/public synchronized int redressX(int x) {if (x < 0)x = 0;if (x > maxX - 1)x = maxX - 1;return x;}/*** 矫正y坐标* * @param y* @return*/public synchronized int redressY(int y) {if (y < 0)y = 0;if (y > maxY - 1)y = maxY - 1;return y;}/*** 敌军行动* */public synchronized void enemyAction() {for (int index = 0; index < unitList.size(); index++) {Role role = (Role) unitList.get(index);if (role.team != 1) {continue;}actionUnit = index;setMoveRange();// 随机选择敌方移动地点int x = role.move - new Random().nextInt(role.move * 2 + 1);int y = (role.move - Math.abs(x))- new Random().nextInt((role.move - Math.abs(x)) * 2 + 1);x = redressX(role.x + x);y = redressY(role.y + y);if ((moveList[x][y] > 0) && (getRoleIdx(0, x, y) == -1)&& (getRoleIdx(1, x, y) == -1)) {// 记录角色最后的移动位置lastX = role.x;lastY = role.y;curX = x;curY = y;moveCount = moveList[x][y];movingList[x][y] = moveCount;for (int i = 0; i < moveCount; i++) {switch (setMoveCouse(x, y)) {case 0:x = x - 1;break;case 1:y = y - 1;break;case 2:x = x + 1;break;case 3:y = y + 1;break;default:break;}}moveCount = moveList[curX][curY];movingList[x][y] = 0;moveRole();}state = "敌方行动";curX = 0;curY = 0;role.setAction(1);role.setAttack(false);actionUnit = -1;initRange();drawBattle();Utility.wait(200);}}public void keyReleased(KeyEvent e) {if (state.equalsIgnoreCase("战斗开始"))return;if (state.equalsIgnoreCase("战斗结束"))return;if (state.equalsIgnoreCase("敌方行动"))return;// 菜单可见if (menu.visible) {switch (e.getKeyCode()) {case KeyEvent.VK_UP:if (menu.cur > 0) {menu.cur = menu.cur - 1;}break;case KeyEvent.VK_DOWN:if (menu.cur < menu.height - 1) {menu.cur = menu.cur + 1;}break;}}// 菜单不可见else {switch (e.getKeyCode()) {case KeyEvent.VK_LEFT:curX = redressX(curX - 1);break;case KeyEvent.VK_UP:curY = redressY(curY - 1);break;case KeyEvent.VK_RIGHT:curX = redressX(curX + 1);break;case KeyEvent.VK_DOWN:curY = redressY(curY + 1);break;}}if (state.equalsIgnoreCase("角色移动")) {setMoveCourse();}drawBattle();}public void keyPressed(KeyEvent e) {int code = e.getKeyCode();eventCode = code;}public void keyTyped(KeyEvent e) {}}

这个类里面有很多东西,我们从头开始看,

// 地图this.mapImage = this.map.getMapImage();this.maxX = map.getMaxX();this.maxY = map.getMaxY();this.moveList = new int[maxX][maxY];this.movingList = new int[maxX][maxY];this.attackList = new int[maxX][maxY];int width = maxX * tile;int height = maxY * tile;

构造函数里面的地图解析,地图map类

package org.loon.simple.slg.ai;import java.awt.Graphics;
import java.awt.Image;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;/*** Copyright 2008 - 2009* * Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.* * @project loonframework* @author chenpeng* @email:ceponline@yahoo.com.cn* @version 0.1*/
public class Map {private int[][] mapArray = null;private int size = 0;private int maxX = 0;private int maxY = 0;private int tile = 32;private Image[] mapImages;/*** 加载指定地图文件为list* * @param fileName* @return* @throws IOException*/private static List loadList(final String fileName) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(Utility.getResource(fileName)));List records = new ArrayList(10);String result = null;try {// 分解地图设定点while ((result = reader.readLine()) != null) {char[] charArray = result.toCharArray();int size = charArray.length;int[] intArray = new int[size];for (int i = 0; i < size; i++) {intArray[i] = Character.getNumericValue(charArray[i]);}records.add(intArray);}} finally {if (reader != null) {try {reader.close();} catch (IOException e) {}}}return records;}/*** 加载地图文件为整型二维数组* * @param fileName* @return* @throws IOException*/public static int[][] loadArray(final String fileName) throws IOException {// 取得地图二维数组(此时row,col颠倒)List list = loadList(fileName);int row = list.size();int[][] mapArray = new int[row][];for (int i = 0; i < row; i++) {mapArray[i] = (int[]) list.get(i);}int col = (((int[]) mapArray[row > 0 ? row - 1 : 0]).length);// 颠倒二维数组row,colint[][] result = new int[col][row];for (int j = 0; j < col; j++) {for (int i = 0; i < row; i++) {result[i][j] = mapArray[j][i];}}return result;}/*** 构造地图* * @param size* @param fileName*/public Map(final String fileName, final int tile) {try {this.mapArray = Map.loadArray(fileName);} catch (IOException e) {throw new RuntimeException(e);}this.size = this.mapArray.length;this.tile = tile;this.maxX = this.size;this.maxY = (((int[]) this.mapArray[this.maxX > 0 ? this.maxX - 1 : 0]).length);this.mapImages = Utility.getSplitImages("image/map.png", tile, tile);}/*** 获得地图图像* * @return*/public Image getMapImage() {Image image = Utility.createImage(maxX * tile, maxY * tile, true);Graphics graphics = image.getGraphics();for (int y = 0; y <= maxY - 1; y++) {for (int x = 0; x <= maxX - 1; x++) {int type = getMapType(x, y);graphics.drawImage(mapImages[type], x * tile, y * tile, null);}}graphics.dispose();return image;}public int[][] getMaps() {return mapArray;}public int getMaxX() {return maxX;}public int getMaxY() {return maxY;}/*** 获得地图指定坐标点对象* * @param x* @param y* @return*/public int getMapType(int x, int y) {/*if (x < 0) {x = 0;}if (y < 0) {y = 0;}if (x > maxX - 1) {x = maxX - 1;}if (y > maxY - 1) {y = maxY - 1;}*/return mapArray[x][y];}/*** 返回指定坐标地形* * @param x* @param y* @return*/public int getMapCost(int x, int y) {int type = getMapType(x, y);switch (type) {case 0:type = 1; // 草break;case 1:type = 2; // 树break;case 2:type = 3; // 山地break;case 3:type = -1; // 湖泽(不能进入)break;}return type;}}

map.txt

1122221100
0000012210
1100001100
0001110000
0000111000
0000000000
1100000000
2111102002
2211133202
2222113322

这个是地图的图块信息,getmapcost方法中可见0是草,1是树,2是山地,3是湖泽(不可移动),map.txt被map类解析完,由canvas的构造函数初始化调用,

// 创建角色:name=空罐少女,team=0(我军),imageindex=3,x=7,y=1,以下雷同createRole("空罐少女", 0, 0, 3, 7, 1);createRole("猫猫1", 0, 1, 6, 1, 2);createRole("猫猫2", 0, 0, 3, 2, 6);// 创建角色:name=躲猫兵团1,team=1(敌军),imageindex=6,x=4,y=5,以下雷同createRole("躲猫兵团1", 1, 2, 4, 4, 5);createRole("躲猫兵团2", 1, 2, 4, 8, 5);createRole("躲猫兵团3", 1, 2, 4, 5, 7);createRole("躲猫兵团4", 1, 2, 4, 7, 2);
 /*** 创建角色* * @param name* @param team* @param imageIndex* @param move* @param x* @param y*/private synchronized void createRole(String name, int team, int imageIndex,int move, int x, int y) {unitList.add(new Role(name, team, unitImages[imageIndex], move, x, y));}

创建人物,我们看到创建人物在unitList中加入了角色的信息,包括名称,阵营,图片等等信息

this.screen = Utility.createImage(width, height, true);this.graphics = (Graphics2D) screen.getGraphics();

绘制screen,我们看下Utility类

package org.loon.simple.slg.ai;import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.ImageProducer;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.WeakHashMap;public class Utility {final static private Toolkit toolKit = Toolkit.getDefaultToolkit();final static private MediaTracker mediaTracker = new MediaTracker(new Container());final static private Map cacheImages = new WeakHashMap(100);final static private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();final static String newLine = "\r\n";final static RenderingHints hints;static {// 设定图像显示状态hints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);hints.put(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);hints.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_SPEED);hints.put(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);hints.put(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);hints.put(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY);hints.put(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_DISABLE);}private Utility() {}/*** 分解整图为图片数组* * @param fileName* @param row* @param col* @return*/public static Image[] getSplitImages(String fileName, int row, int col) {Image image = Utility.loadImage(fileName);int index = 0;int wlenght = image.getWidth(null) / row;int hlenght = image.getHeight(null) / col;int l = wlenght * hlenght;Image[] abufferedimage = new Image[l];for (int y = 0; y < hlenght; y++) {for (int x = 0; x < wlenght; x++) {abufferedimage[index] = Utility.createImage(row, col, true);Graphics g = abufferedimage[index].getGraphics();g.drawImage(image, 0, 0, row, col, (x * row), (y * col), row+ (x * row), col + (y * col), null);g.dispose();// 透明化处理PixelGrabber pgr = new PixelGrabber(abufferedimage[index], 0,0, -1, -1, true);try {pgr.grabPixels();} catch (InterruptedException ex) {ex.getStackTrace();}int pixels[] = (int[]) pgr.getPixels();//循环像素for (int i = 0; i < pixels.length; i++) {//去色255,0,255LColor color = LColor.getLColor(pixels[i]);if (color.R == 255 && color.G == 0 && color.B == 255) {//透明化pixels[i] = 0;}}ImageProducer ip = new MemoryImageSource(pgr.getWidth(), pgr.getHeight(), pixels, 0, pgr.getWidth());abufferedimage[index] = toolKit.createImage(ip);index++;}}return abufferedimage;}public static Image drawClipImage(final Image image, int objectWidth,int objectHeight, int x1, int y1, int x2, int y2) throws Exception {BufferedImage buffer = Utility.createImage(objectWidth, objectHeight,true);Graphics g = buffer.getGraphics();Graphics2D graphics2D = (Graphics2D) g;graphics2D.drawImage(image, 0, 0, objectWidth, objectHeight, x1, y1,x2, y2, null);graphics2D.dispose();graphics2D = null;return buffer;}/*** 生成大图的截取图* * @param source* @param src_x* @param src_y* @param desc_width* @param desc_height* @return*/public static BufferedImage drawClip(String source, int src_x, int src_y,int desc_width, int desc_height) {return Utility.drawClip(Utility.getBufferImage(Utility.loadImage(source)), src_x, src_y, desc_width, desc_height);}public static void drawString(String s, final Graphics2D g, int i, int j,int k) {Graphics2D graphics2D = (Graphics2D) g;graphics2D.setRenderingHints(hints);Font font = graphics2D.getFont();int size = graphics2D.getFontMetrics(font).stringWidth(s);Utility.setAlpha(g, 0.9f);graphics2D.drawString(s, i + (k - size) / 2, j);Utility.setAlpha(g, 1.0f);}/*** 在graphics上描绘文字* * @param message* @param fontName* @param g* @param x1* @param y1* @param style* @param size*/public static void drawString(String message, String fontName,final Graphics g, int x1, int y1, int style, int size) {Graphics2D graphics2D = (Graphics2D) g;graphics2D.setRenderingHints(hints);graphics2D.setFont(new Font(fontName, style, size));Utility.setAlpha(g, 0.9f);graphics2D.drawString(message, x1, y1);Utility.setAlpha(g, 1.0f);}/*** 默认的文字输出* * @param message* @param g* @param x1* @param y1* @param font* @param fontSize*/public static void drawDefaultString(String message, final Graphics2D g,int x1, int y1, int font, int fontSize) {g.setRenderingHints(hints);g.setFont(new Font("华文新魏", font, fontSize));g.drawString(message, x1, y1);}public static BufferedImage getBufferImage(final Image image) {int width = image.getWidth(null);int height = image.getHeight(null);BufferedImage bufferedimage = createImage(width, height, true);Graphics g = bufferedimage.getGraphics();g.drawImage(image, 0, 0, null);return bufferedimage;}public Image drawClip(final Image image, int objectWidth, int objectHeight,int x1, int y1, int x2, int y2) throws Exception {BufferedImage buffer = Utility.createImage(objectWidth, objectHeight,true);Graphics g = buffer.getGraphics();Graphics2D graphics2D = (Graphics2D) g;graphics2D.drawImage(image, 0, 0, objectWidth, objectHeight, x1, y1,x2, y2, null);graphics2D.dispose();graphics2D = null;return buffer;}/*** 生成截取图* * @param image* @param src_x* @param src_y* @param desc_width* @param desc_height* @return*/public static BufferedImage drawClip(final Image image, int src_x,int src_y, int desc_width, int desc_height) {BufferedImage thumbImage = new BufferedImage(desc_width, desc_height,BufferedImage.TYPE_INT_RGB);Graphics2D graphics2D = thumbImage.createGraphics();graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);graphics2D.drawImage(image, 0, 0, desc_width, desc_height, src_x,src_y, image.getWidth(null), image.getHeight(null), null);graphics2D.dispose();return thumbImage;}public final static InputStream getResource(final String fileName) {return new BufferedInputStream(classLoader.getResourceAsStream(fileName));}/*** 加载file转为Image* * @param inputstream* @return*/final static public Image loadImage(final String fileName) {String keyName = fileName.trim().toLowerCase();Image cacheImage = (Image) cacheImages.get(keyName);if (cacheImage == null) {InputStream in = new BufferedInputStream(classLoader.getResourceAsStream(fileName));ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();try {byte[] bytes = new byte[8192];int read;while ((read = in.read(bytes)) >= 0) {byteArrayOutputStream.write(bytes, 0, read);}byte[] arrayByte = byteArrayOutputStream.toByteArray();cacheImages.put(keyName, cacheImage = toolKit.createImage(arrayByte));mediaTracker.addImage(cacheImage, 0);mediaTracker.waitForID(0);waitImage(100, cacheImage);} catch (Exception e) {throw new RuntimeException(fileName + " not found!");} finally {try {if (byteArrayOutputStream != null) {byteArrayOutputStream.close();byteArrayOutputStream = null;}if (in != null) {in.close();}} catch (IOException e) {}}}if (cacheImage == null) {throw new RuntimeException(("File not found. ( " + fileName + " )").intern());}return cacheImage;}/*** 延迟加载image,以使其同步。* * @param delay* @param image*/private final static void waitImage(int delay, Image image) {try {for (int i = 0; i < delay; i++) {if (toolKit.prepareImage(image, -1, -1, null)) {return;}Thread.sleep(delay);}} catch (Exception e) {}}/*** 生成一个BufferImage* * @param i* @param j* @param flag* @return*/final static public BufferedImage createImage(int i, int j, boolean flag) {if (flag) {return new BufferedImage(i, j, 2);} else {return new BufferedImage(i, j, 1);}}/*** 延迟指定毫秒* * @param ms*/final static public void wait(final int ms) {try {Thread.sleep(ms);} catch (InterruptedException ex) {}}/*** 字体设定* * @param g* @param size* @param type*/final static public void font(final Graphics2D g, final int size, int type) {if (type == 0) {type = 0;}if (type == 1) {type = 1;}g.setFont(new Font("SansSerif", type, size));}final static public void font(final Graphics2D g, final String fontName,final int size, int type) {if (type == 0) {type = 0;}if (type == 1) {type = 1;}g.setFont(new Font(fontName, type, size));}/*** 颜色设定* * @param gr* @param r* @param g* @param b*/final static public void color(final Graphics2D gr, final int r,final int g, final int b) {gr.setColor(new Color(r, g, b));}/*** 透明度设定* * @param g* @param d*/final static public void setAlpha(Graphics g, double d) {AlphaComposite alphacomposite = AlphaComposite.getInstance(3, (float) d);((Graphics2D) g).setComposite(alphacomposite);}final static public void setAlpha(Graphics2D g2d, double d) {AlphaComposite alphacomposite = AlphaComposite.getInstance(3, (float) d);g2d.setComposite(alphacomposite);}/*** 分解小图* * @param image* @param objectWidth* @param objectHeight* @param x1* @param y1* @param x2* @param y2* @return* @throws Exception*/final static private Image getClipImage(final Image image, int objectWidth,int objectHeight, int x1, int y1, int x2, int y2) throws Exception {BufferedImage buffer = createImage(objectWidth, objectHeight, true);Graphics g = buffer.getGraphics();Graphics2D graphics2D = (Graphics2D) g;graphics2D.drawImage(image, 0, 0, objectWidth, objectHeight, x1, y1,x2, y2, null);graphics2D.dispose();graphics2D = null;return buffer;}/*** 按横行宽度分解图像* * @param img* @param width* @return*/final static public Image[] getImageRows(Image img, int width) {int iWidth = img.getWidth(null);int iHeight = img.getHeight(null);int size = iWidth / width;Image[] imgs = new Image[size];for (int i = 1; i <= size; i++) {try {imgs[i - 1] = transBlackColor(getClipImage(img, width, iHeight,width * (i - 1), 0, width * i, iHeight));} catch (Exception e) {e.printStackTrace();}}return imgs;}/*** 将黑色颜色部分透明化* * @param img* @return*/final static public Image transBlackColor(final Image img) {int width = img.getWidth(null);int height = img.getHeight(null);PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, true);try {pg.grabPixels();} catch (InterruptedException e) {e.printStackTrace();}int pixels[] = (int[]) pg.getPixels();for (int i = 0; i < pixels.length; i++) {if (pixels[i] <= -11500000) {pixels[i] = 16777215;}}return toolKit.createImage(new MemoryImageSource(width, height, pixels,0, width));}/*** 清空image缓存* */final static public void destroyImages() {cacheImages.clear();System.gc();}}

很明显这个类是作为图像处理的,

/*** 初始化各项范围参数* */public synchronized void initRange() {for (int y = 0; y <= maxY - 1; y++) {for (int x = 0; x <= maxX - 1; x++) {moveCount = 0;moveList[x][y] = -1;movingList[x][y] = -1;attackList[x][y] = 0;}}}
/*** 绘制画面* */public synchronized void drawBattle() {int count = 0;// 绘制地图graphics.drawImage(mapImage, 0, 0, null);// 移动范围绘制if ((state.equalsIgnoreCase("角色移动"))|| (state.equalsIgnoreCase("移动范围"))) {for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {if (moveList[i][j] > -1) {graphics.drawImage(iconImages[2], i * tile, j * tile,null);} else if (attackList[i][j] > 0) {graphics.drawImage(iconImages[3], i * tile, j * tile,null);}}}}// 角色绘制for (int index = 0; index < unitList.size(); index++) {Role role = (Role) unitList.get(index);if (index == actionUnit) {// 当前控制角色处理(此示例未加入特殊处理)graphics.drawImage(role.getImage(), role.getX() * tile, role.getY()* tile, null);} else {graphics.drawImage(role.getImage(), role.getX() * tile, role.getY()* tile, null);}// 已行动完毕if (role.action == 1) {graphics.drawImage(unitImages[3], role.getX() * tile, role.getY()* tile, null);}}// 攻击范围绘制if (state.equalsIgnoreCase("进行攻击")) {for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {int result = attackList[i][j];if (result == 2) {graphics.drawImage(iconImages[3], i * tile, j * tile,null);}// 标注选中的攻击对象if (result == 2 && getRoleIdx(1, i, j) > -1 && curX == i&& curY == j) {graphics.drawImage(iconImages[4], i * tile, j * tile,null);}}}}

寻路

 // 绘制移动路线if (state.equalsIgnoreCase("角色移动")) {for (int j = 0; j <= maxY - 1; j++) {for (int i = 0; i <= maxX - 1; i++) {if (movingList[i][j] == -1) {continue;}count = 0;if ((movingList[i][j] == 0)|| (movingList[i][j] == moveCount)) {if ((i > 0)&& (movingList[i - 1][j] > -1)&& ((movingList[i - 1][j]- map.getMapCost(i - 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i - 1][j]))) {count = 1;}if ((j > 0)&& (movingList[i][j - 1] > -1)&& ((movingList[i][j - 1]- map.getMapCost(i, j - 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j - 1]))) {count = 2;}if ((i < maxX-1)&& (movingList[i + 1][j] > -1)&& ((movingList[i + 1][j]- map.getMapCost(i + 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i + 1][j]))) {count = 3;}if ((j < maxY-1)&& (movingList[i][j + 1] > -1)&& ((movingList[i][j + 1]- map.getMapCost(i, j + 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j + 1]))) {count = 4;}if (movingList[i][j] != 0) {count = count + 4;}} else {count = 6;if ((i > 0)&& (movingList[i - 1][j] > -1)&& ((movingList[i - 1][j]- map.getMapCost(i - 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i - 1][j]))) {count = count + 1;}if ((j > 0)&& (movingList[i][j - 1] > -1)&& ((movingList[i][j - 1]- map.getMapCost(i, j - 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j - 1]))) {count = count + 2;}if ((i < maxX-1)&& (movingList[i + 1][j] > -1)&& ((movingList[i + 1][j]- map.getMapCost(i + 1, j) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i + 1][j]))) {count = count + 3;}if ((j < maxY-1)&& (movingList[i][j + 1] > -1)&& ((movingList[i][j + 1]- map.getMapCost(i, j + 1) == movingList[i][j]) || (movingList[i][j]- map.getMapCost(i, j) == movingList[i][j + 1]))) {count = count + 5;}}if (count > 0) {graphics.drawImage(iconImages[count + 4], i * tile, j* tile, null);}}}}

可以说每个地方地很详细

// 菜单if (menu.visible) {Utility.setAlpha(graphics, 0.50f);graphics.drawImage(listImages[0], menu.getLeft(curX) * tile, 0,null);for (int i = 1; i <= menu.width; i++) {graphics.drawImage(listImages[1], (menu.getLeft(curX) + i)* tile, 0, null);}graphics.drawImage(listImages[2],(menu.getLeft(curX) + menu.width + 1) * tile, 0, null);for (int j = 1; j <= menu.height; j++) {graphics.drawImage(listImages[3], menu.getLeft(curX) * tile, j* tile, null);for (int i = 1; i <= menu.width; i++) {graphics.drawImage(listImages[4], (menu.getLeft(curX) + i)* tile, j * tile, null);}graphics.drawImage(listImages[5], (menu.getLeft(curX)+ menu.width + 1)* tile, j * tile, null);}graphics.drawImage(listImages[6], menu.getLeft(curX) * tile,(menu.height + 1) * tile, null);for (int i = 1; i <= menu.width; i++) {graphics.drawImage(listImages[7], (menu.getLeft(curX) + i)* tile, (menu.height + 1) * tile, null);}graphics.drawImage(listImages[8],(menu.getLeft(curX) + menu.width + 1) * tile,(menu.height + 1) * tile, null);Utility.setAlpha(graphics, 1.0f);// 写入文字graphics.drawImage(iconImages[1], (menu.getLeft(curX) + 1) * tile,(menu.cur + 1) * tile, null);for (int j = 1; j <= menu.height; j++) {graphics.setColor(Color.white);Utility.drawDefaultString(menu.getMenuItem(j - 1), graphics,(menu.getLeft(curX) + 2) * tile, ((j * tile)) + 24, 0,23);}}// 显示状态if (state.equalsIgnoreCase("状态显示")) {int i = getRoleIdx(0, curX, curY);if (i == -1) {i = getRoleIdx(1, curX, curY);}if (i > -1) {Role role = (Role) unitList.get(i);Utility.setAlpha(graphics, 0.75f);graphics.drawImage(listImages[0], menu.getLeft(curX) * tile, 0,null);graphics.drawImage(listImages[1], (menu.getLeft(curX) + 1)* tile, 0, null);graphics.drawImage(listImages[1], (menu.getLeft(curX) + 2)* tile, 0, null);graphics.drawImage(listImages[2], (menu.getLeft(curX) + 3)* tile, 0, null);graphics.drawImage(listImages[3], (menu.getLeft(curX)) * tile,tile, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 1)* tile, tile, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 2)* tile, tile, null);graphics.drawImage(listImages[5], (menu.getLeft(curX) + 3)* tile, tile, null);graphics.drawImage(listImages[3], menu.getLeft(curX) * tile,64, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 1)* tile, 64, null);graphics.drawImage(listImages[4], (menu.getLeft(curX) + 2)* tile, 64, null);graphics.drawImage(listImages[5], (menu.getLeft(curX) + 3)* tile, 64, null);graphics.drawImage(listImages[6], (menu.getLeft(curX)) * tile,96, null);graphics.drawImage(listImages[7], (menu.getLeft(curX) + 1)* tile, 96, null);graphics.drawImage(listImages[7], (menu.getLeft(curX) + 2)* tile, 96, null);graphics.drawImage(listImages[8], (menu.getLeft(curX) + 3)* tile, 96, null);Utility.setAlpha(graphics, 1.0f);// 显示角色数据graphics.drawImage(role.getImage(), (menu.getLeft(curX) + 1)* tile + 16, tile, null);Utility.drawDefaultString("HP:" + role.getHp(), graphics, (menu.getLeft(curX) + 1)* tile + 12, 75, 1, 12);Utility.drawDefaultString("MV:" + role.getMove(), graphics,(menu.getLeft(curX) + 1) * tile + 12, 88, 1, 12);}}// 战斗回合if (state.equalsIgnoreCase("战斗开始") || state.equalsIgnoreCase("战斗结束")) {Utility.setAlpha(graphics, 0.5f);graphics.setColor(Color.black);graphics.fillRect(0, 90, 320, 140);graphics.setColor(Color.white);Utility.setAlpha(graphics, 1.0f);Utility.drawDefaultString("第" + turn + "回合", graphics, 120, 160, 0,25);}// 我方移动else if (state.equalsIgnoreCase("开始移动")) {// 未添加处理} else if (state.equalsIgnoreCase("敌方行动")) {for (int i = unitList.size() - 1; i > -1; i--) {Role role = (Role) unitList.get(i);// 敌军,且无法再次移动和攻击if (role.team == 1 && role.action == 1) {int x = role.x;int y = role.y;int index = 0;// 当敌军移动地点附近才能在我方人物时, 直接删除List中我方角色(实际开发中应加入相应判定)if ((index = getRoleIdx(0, x, y + 1)) > -1&& !role.isAttack()) {unitList.remove(index);} else if ((index = getRoleIdx(0, x, y - 1)) > -1&& !role.isAttack()) {unitList.remove(index);} else if ((index = getRoleIdx(0, x + 1, y)) > -1&& !role.isAttack()) {unitList.remove(index);} else if ((index = getRoleIdx(0, x - 1, y)) > -1&& !role.isAttack()) {unitList.remove(index);}role.setAttack(true);}}} else {// 绘制光标graphics.drawImage(iconImages[0], curX * tile, curY * tile, null);}// 刷新画面this.repaint();}

期间用到的另外3个类

package org.loon.simple.slg.ai;import java.awt.Image;/*** Copyright 2008 - 2009* * Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.* * @project loonframework* @author chenpeng* @email:ceponline@yahoo.com.cn* @version 0.1*/
public class Role {//名称String name;//分队(0:我军 1:敌军)int team; //hpint hp;//角色图像Image image; //移动力int move;//行动状态(0:未行动 1:已行动)int action; //x坐标int x; //y坐标int y; //是否已进行攻击boolean isAttack = false;/*** 设定角色参数* * @param name* @param team* @param image* @param move* @param x* @param y*/public Role(String name, int team, Image image, int move, int x, int y) {this.name = name;this.team = team;this.hp = 10;this.image = image;this.move = move;this.x = x;this.y = y;}public int getAction() {return action;}public void setAction(int action) {this.action = action;}public int getHp() {return hp;}public void setHp(int hp) {this.hp = hp;}public Image getImage() {return image;}public void setImage(Image image) {this.image = image;}public int getMove() {return move;}public void setMove(int move) {this.move = move;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getTeam() {return team;}public void setTeam(int team) {this.team = team;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public boolean isAttack() {return isAttack;}public void setAttack(boolean isAttack) {this.isAttack = isAttack;}
}
package org.loon.simple.slg.ai;/*** * Copyright 2008* * Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.* * @project loonframework* @author chenpeng* @email:ceponline@yahoo.com.cn* @version 0.1*/
public class LColor {public int R = 0;public int G = 0;public int B = 0;private LColor() {}/*** 判定两个lcolor是否相等* * @param a* @param b* @return*/public static boolean equals(final LColor a, final LColor b) {return (a.R == b.R) && (a.G == b.G) && (a.B == b.B);}/*** 将颜色Pixel数值返回为LColor* * @param c* @return*/public static LColor getLColor(int pixel) {LColor color = new LColor();color.R = (pixel & 0x00ff0000) >> 16;color.G = (pixel & 0x0000ff00) >> 8;color.B = pixel & 0x000000ff;return color;}/*** 将color返回为像素* * @param color* @return*/public int getPixel(final LColor color) {return (color.R << 16) | (color.G << 8) | color.B;}public int getPixel() {return (R << 16) | (G << 8) | B;}/*** 注入r,g,b数值* * @param r* @param g* @param b*/public LColor(final int r, final int g, final int b) {this.R = r;this.G = g;this.B = b;}public static LColor fromArgb(final int r, final int g, final int b) {return new LColor(r, g, b);}}
package org.loon.simple.slg.ai;import java.util.ArrayList;
import java.util.List;/*** Copyright 2008 - 2009* * Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.* * @project loonframework* @author chenpeng* @email:ceponline@yahoo.com.cn* @version 0.1*/
public class Menu {// 是否可见boolean visible;// 菜单纵幅int height;// 菜单横幅int width;// 光标位置int cur;// 菜单类型int menuType;// 菜单选项List menuItem;int size=0;public Menu(int size) {this.menuItem = new ArrayList(10);this.setVisible(false);this.setMenuType(0);this.setCur(0);this.size=size;}public void free() {this.menuItem.clear();}public int getCur() {return cur;}/*** 设定光标* @param cur*/public void setCur(int cur) {if (cur < 0) {cur = this.height - 1;}if (cur > this.height - 1) {cur = 0;}this.cur = cur;}/*** 获得指定索引位置菜单* * @param index* @return*/public String getMenuItem(int index) {return (String) menuItem.get(index);}/*** 获得在地图上相对位置* * @param size* @param x* @return*/public int getLeft(int x) {int result = -1;// 如果x点位置大于 9 / 2,则在左侧显示菜单if (x > this.size / 2) {result = 0;} else {// 在右侧显示菜单result = this.size - width - 1;}return result;}/*** 设定菜单项**/public void setMenuItem() {switch (this.menuType) {case 0:this.width = 3;this.height = 1;menuItem.add("结束");break;case 1:this.width = 3;this.height = 1;menuItem.add("待机");break;case 2:this.width = 3;this.height = 2;menuItem.add("攻击");menuItem.add("待机");break;}}public int getMenuType() {return menuType;}public void setMenuType(int menuType) {this.free();this.menuType = menuType;this.setMenuItem();}public boolean isVisible() {return visible;}public void setVisible(boolean visible) {this.visible = visible;}public int getHeight() {return height;}public void setHeight(int height) {this.height = height;}public int getWidth() {return width;}public void setWidth(int width) {this.width = width;}}

代码都在这里了,项目源码在这里(这个项目是cping1982的,不过他只提供了jar文件(源码在jar里)我方便大家直接做成了Eclipse项目, 下载)

代码是贴完了,不过一个问题来了,战棋游戏因为玩法的独特性,所以貌似做成网游难度很大,现在放眼网游(手游)市场,类似产品只有《战龙兵团》勉强算,纯的战棋游戏
《三国鼎立》也是刚刚回归国服,归其原因还是因为玩法上面特殊,时间消耗太大,战龙兵团为了规避走格子消耗太多的时间,发明了战役挂机---这个想法不错《我叫Mt》外传也是战役挂机,不过游戏搞得已经不是战棋游戏了,看上去是一款顶视图的《刀塔传奇》,把2d的玩法加了一个z轴,变成了3d玩法而已,战龙兵团怎么还有个pvp模式,可以真正体验战棋的乐趣(虽然一场仗要打10几20个小时,不过随时退出游戏,随时加入游戏都不限制,可以根据自己时间安排休闲),日本去年12月份上线了一款纯战棋手游,国内火焰vs众筹失败,所以近期吃螃蟹的公司可能不会有,毕竟风险很大,不过风险与机遇是并存的,当年火焰纹章的策划案提出的时候,也是被压了2年时间,当时任天堂内部也是很多声音,怀疑这种游戏类型能否被玩家接受,但后来事实证明,火纹被全世界玩家所喜爱(可能说的有点绝对,但火纹的消费群绝不是掌机那小小的一群人),市场其实还是挺大的,或许不久的将来战棋类型网游真的能成功也说不定。

当然策略游戏也可以归为SLG游戏,不过这里不做讨论。

今天开始做战斗,回合制战斗代码实现第三篇,特殊的回合制游戏Slg(策略战棋)相关推荐

  1. C++实现DPM/LatentSVM 完整代码下载 --- 第三篇

    这是我的DPM代码的第三篇博文,最初发表在http://blog.csdn.net/j56754gefge/article/details/40708679,均是我原创文章,他人转载请注明出处! C+ ...

  2. pygame战棋游戏制作之战棋回合切换(五)

    简介 前面我们已经完成了战棋地图的绘制,棋子的设置,光标的设置,接下来我们将要开始实现rpg游戏的灵魂--回合切换. 正文 回合切换主要是通过棋子列表判断,当列表为空时,触发回合切换的函数.因此我们创 ...

  3. matlab实现鬼波信号压制算法  代码实践--第三篇 拉东域鬼波压制

    第三篇 matlab实现 拉东域鬼波压制方法 本篇用来介绍拉东域鬼波压制的实现思路和压制效果 该方法可用于水平拖缆.斜缆数据的鬼波压制 算法实现思路见3.3节,除了文中代码外,需配置鬼波压制算法工具包 ...

  4. 今天开始做战斗,回合制战斗代码实现第四篇 刀塔传奇战斗模式(即时卡牌战斗模式)

    说是即时卡牌战斗,其实在我看来这种玩法也是回合制战斗的一种,差不多算是九宫格战斗的一种变种,在一个回合120秒内,分成了3次小规模的遇怪自动战斗,而这种自动战斗不在是回合而是即时的,但整个战斗过程,都 ...

  5. 回合制html代码,老框架新思路 最新好玩的回合制网页游戏盘点

    回合制网页游戏是指那种在战斗中需要切换场景,本方角色和敌方角色交互攻击,直至一方全灭即可宣告获胜的游戏类型,这一模式从最早的<梦幻西游>到如今各种红火的卡牌手游,都被广泛应用,而回合制网页 ...

  6. 今天开始做战斗,回合制战斗代码实现第二篇,九宫格战斗

    说到九宫格战斗,就不能不提一款游戏<神仙道>,在神仙道之前,九宫格战斗的模式就在几款游戏里面有应用,但神仙道是真真正正把这种战斗模式发扬光大的里程碑,当时无论口碑,还是市场占有率都可以说是 ...

  7. HTML5 canvas 实现回合制战棋游戏(1):加载和绘制图形

    HTML5 canvas 实现回合制战棋游戏(1):加载和绘制图形 游戏介绍 完整代码 代码目录 游戏运行 HTML5 canvas 绘制图形 canvas 介绍 绘制函数 加载图片 生物行走动画绘制 ...

  8. 今天开始做战斗,回合制战斗代码实现第一篇补充,从头开始,简单的2d回合制游戏一些文档方面的知识

    上一篇代码贴完了,总是感觉缺少些东西,因为光看代码用时候不是很直观,我们还是需要些文档来辅助理解.好了,所以补充些内容. 2009 年 8 月,<梦幻西游>同时最高在线人数达到 256 万 ...

  9. ICE Tester method viewer 的安装和使用,和客制化代码配合使用

     安装 找到目录 C:\Epicor\Epicor905\Utilities\BL-Tester 下面有个安装文件ICE2.0.5 BL Tester Setup,双击这个文件安装 需要填入的资料中, ...

最新文章

  1. 2015 AlBaath Collegiate Programming Contest(2月14日训练赛)
  2. (转)WCF光芒下的Web Service
  3. python工作招聘-爬了招聘网站之后,给你几点学习Python的建议
  4. 全网最新 Skywalking 6.1.0部署进k8s 包含springcloud测试用例
  5. SMACH专题(一)----安装与初探
  6. 数字证书格式详细说明【转】
  7. LINUX下载编译libspeex/libspeexdsp
  8. python查找相似图片或重复图片
  9. 凸优化 - 3 - Jensen不等式、共轭函数、Fenchel不等式
  10. python 多元字符多项式的展开问题
  11. 学会放松和享受当下极其重要
  12. TF卡里删掉文件后内存没变大_不用第三方,手机自带软件也能清扫内存!教你4个清理技巧...
  13. 网络安全——传输层安全协议
  14. 学籍管理系统c语言程序设计,c语言学籍信息管理系统设计
  15. 市审计局充分利用大数据助力扶贫和“十个全覆盖”审计工作
  16. 读《反脆弱性》:凹凸性资料搜集
  17. python基础知识点集锦一
  18. 为Python安装第三方模块
  19. js动态修改css样式
  20. 机器学习 非参数估计

热门文章

  1. Android学习——xUtils框架
  2. Scarborough Fair(斯卡布罗集市)歌词赏析
  3. windows 性能监视器图表中各曲线的意义
  4. tp5.0阿里云oss存储Demo
  5. 【ceph】什么是NFS-Ganesha和fuse
  6. 抽象类和接口的特点和异同
  7. 可以设置压缩大小的在线GIF压缩
  8. 成为国产大数据基础软件第一股的星环科技,未来发展空间几何? | 爱分析调研
  9. java replace和replaceAll的区别以及用法
  10. Java中接口的实现