因为准备做世界大战,所以准备了一张360*170的世界地图,但是这张地图实在是太大了,缩放到32%,仍然将近13000*6000
从var3d那里听说sprite挺好用,所以准备重新优化地图.
1.设定比例上限,玩家对多显示60*40的大小,即2400个格子
2.仿照网格,海洋写法,取消构建大地图的制作方式,,使用装饰素材处理为sprite,实时的构建玩家视野范围内的地图
Ps:海洋地图层的写法:为水蓝色,只铺满屏幕大小,显示在最底层,不做移动
网格地图层的写法:创建一个比玩家视野稍微大的网格,当玩家横向移动超过2格则反向移动2格距离,纵向超过1格则反向移动1格
pixmap的drawPixmap方法很坑,因为只能传int值,会导致地图不准
想要实现向世界4的海岸那样,暂时未成功,思路:制作了阴影层,绘制地图时判断阴影层颜色,然后删除对应地区的海洋边界颜色,遇到的问题:地块缩放后阴影层颜色改变,改变颜色需要遍历色素替换很费时间,构建临时存放地图无透明色等等,暂时放弃模仿世界4的海岸.
地图优化具体的实践结果随后会补上 ------记于3/5/17:38
从5号提出到现在的5天里,一直在实验和操作,最后终于觉得坚持不下去了.
出现的问题:1.实时绘制的坐标变换,纵轴横移基本没问题,个别地方会出现晃屏,原因不明
2.横坐标绘制,移动方向力度难以把控,比纵轴还难,在横坐标交汇点,会出现位移
暂时决定封存此设计方案,仍然采用原pixmap方式制作.随后做战略类游戏时再进行试验 ----记于3/10/22:13
---------------------------------------------------------------更新的分割线2019.4.5----------------------------------------------------------
经过无数尝试,终于完成了此算法
此算法的主要难度为:
1.中心点缩放,当陆地与六边形的绘制方位不对应时,会出现偏移 难度3星
2.x轴相对坐标的计算,类似于大陆地的算法相对简单 难度2星
3.y轴相对坐标的计算,因为y的方向是向上递减,所以计算坐标方向与传统思维计算方式会出现矛盾,会让思考方法出现偏转 难度4.5星
首先说明整体的实现思路:
1.计算屏幕高宽,确定显示范围
2.根据当前坐标确定左上坐标应绘制的类型,然后依次绘制,这里y的值需要根据左上的奇偶调整变换
3.陆地与六边形的绘制方位必须对应,如果不对应,改变zoom时,就会出现偏移!
下面为主要实现方法
//大陆块的实现方法
{ // 或根据玩家屏幕大小限制缩放比例 // 绘制循环陆地,如果比例尺大于一定值,则绘制三层 lw = (int) (spriteLand.getWidth() / vw / getZoom() + 2); lh = (int) (spriteLand.getHeight() / vh / getZoom() + 1); lh = lh < 2 ? 2 : lh; for (li = 0; li < lw * lh; li++) { lx = (li % lw) + 1; ly = (li / lw) + 1; lx_px = getX()*zoom % (spriteLand.getWidth() * getZoom()) + spriteLand.getWidth() * getZoom() * (lx - 1); ly_px = getY()*zoom % (spriteLand.getHeight() * getZoom()) + spriteLand.getHeight() * getZoom() * (ly - 1); batch.draw(spriteLand, lx_px, ly_px, getOriginX(), getOriginY(), spriteLand.getWidth(), spriteLand.getHeight(), // getScaleX(), getScaleY(), getZoom(), getZoom(), getRotation()); //bitmapFont.draw(batch, "id:"+li, lx_px-27*zoom, ly_px+48*zoom); } }
//六边形的绘制方法
gw = (int) (((vw / (112 * Config.Map.MAP_SCALE* getZoom())) +2)); gh = (int) (((vh / (128 * Config.Map.MAP_SCALE* getZoom())) +3)); ulcoord = GameMap.getHotCell((getImgX()), getImgY(),zoom); ul_parity_x=(ulcoord.getX()&1); ul_parity_y=(ulcoord.getY()&1); for (gi = 0; gi < gw * gh; gi++) { gx = (gi % gw) + 1; gy = (gi / gw) + 1; dx_px = -getImgX()*zoom+((int)((getImgX()* this.zoom)/ (112 * Config.Map.MAP_SCALE * this.zoom)))*(112 * Config.Map.MAP_SCALE * this.zoom)+( ((gx-1) * 112 * getZoom() * Config.Map.MAP_SCALE))/*+zoom==1?0:(112 * zoom * Config.Map.MAP_SCALE)*/; dy_px = -(vh%(128 * Config.Map.MAP_SCALE *zoom))+((vh)/zoom)*(zoom-1)+getImgY()*zoom+vh/zoom-((((int)((getImgY()*zoom)/ (128 * Config.Map.MAP_SCALE *zoom)))*(128 * Config.Map.MAP_SCALE * zoom))+ (((gy-1) * 128 +( (gx & 1) == 1 ? 0 : ((ul_parity_x&1)==1?-62:62)))* getZoom() * Config.Map.MAP_SCALE)+((ul_parity_x&1)==1?62:0)* Config.Map.MAP_SCALE * zoom); draw_gx = ulcoord.getX() + gx - 2; draw_gy = ulcoord.getY() + gy - gh ; draw_gd = w * draw_gy + draw_gx+1; if (draw_gx < w && draw_gy < h &&draw_gd<mapBinDAO.getMapbin().size()&&draw_gd>=0) { mapBin = mapBinDAO.getMapbin().get(draw_gd); backTile = tilesMap.get(mapBin.getBackTile() + "_" + mapBin.getBackIdx()); if (backTile == null) { backTile = tilesMap.get(mapBin.getBackTile() + "_1"); } if (backTile != null) { batch.draw(spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getSprite(), dx_px+mapBin.getBackRefX()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefx()*zoom*Config.Map.MAP_SCALE, dy_px+mapBin.getBackRefY()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefy()*zoom*Config.Map.MAP_SCALE, getOriginX(), getOriginY(), spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getSprite().getWidth() * Config.Map.MAP_SCALE, spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getSprite().getHeight() * Config.Map.MAP_SCALE, getZoom(), getZoom(), getRotation()); } else { // Gdx.app.log("", "id:"+draw_gd+" // backTile:"+backTile); } foreTile = tilesMap.get(mapBin.getForeTile() + "_" + mapBin.getForeIdx()); if (foreTile == null) { foreTile = tilesMap.get(mapBin.getForeTile() + "_1"); } if (foreTile != null) {//dx_px-spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefx()*zoom*Config.Map.MAP_SCALE, dy_px-spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefy()*zoom*Config.Map.MAP_SCALE batch.draw(spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getSprite(), dx_px+mapBin.getForeRefX()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getRefx()*zoom*Config.Map.MAP_SCALE, dy_px+mapBin.getForeRefY()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getRefy()*zoom*Config.Map.MAP_SCALE, getOriginX(), getOriginY(), spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getSprite().getWidth() * Config.Map.MAP_SCALE, spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getSprite().getHeight() * Config.Map.MAP_SCALE, getZoom(), getZoom(), getRotation()); } else { // Gdx.app.log("", "id:"+draw_gd+" // foreTile:"+foreTile); } }
//获取六边形坐标
// 六边形网格定位 // @param xPos 输入,所需查询的点的x坐标 // @param yPos 输入,所需查询的点的y坐标 // @param cell_x 输出,改点所在网格的x坐标 // @param cell_y 输出,改点所在网格的y坐标 public static Coord getHotCell(float xPos, float yPos,float zoom) { float GRID_WIDTH = 112;// (CELL_BORDER*1.5f) float GRID_HEIGHT =128;// (CELL_BORDER*0.8660254f) float Gride_BORDER=GRID_WIDTH/1.5f; int cell_y; int cell_x; xPos=xPos/Config.Map.MAP_SCALE; yPos=yPos/Config.Map.MAP_SCALE; cell_x = (int) (xPos / GRID_WIDTH); float x = xPos - cell_x * GRID_WIDTH; cell_y = (int) (yPos / GRID_HEIGHT); float y = yPos - cell_y * GRID_HEIGHT; //if(! (Gride_BORDER-Math.abs((x-1/2*GRID_WIDTH))>Math.abs(y-1/2*GRID_HEIGHT)/Math.sqrt(3))) { if(! (Math.abs(GRID_WIDTH/2-x)+Math.abs(GRID_HEIGHT/2-y)/Math.sqrt(3)<=Gride_BORDER*Math.sqrt(3))) { //不在六边形内部 if(x>GRID_WIDTH/2) { //在右边 cell_x++; } } /*if( cell_x % 2==1 && y<64) { cell_y--; } if((cell_x&1)!=1&& y>64) { cell_y=cell_y-1; } if(cell_y<0) { cell_y=0; }*/ Coord coord = new Coord(cell_x, cell_y); return coord; }
//改变中心点
public void setZoom(float zoom,float cx,float cy) { this.xMax= (this.mapW_px * Config.Map.MAP_SCALE * zoom - vw/zoom+(1-zoom)*this.mapW_px * Config.Map.MAP_SCALE); this.yMax= (this.mapH_px * Config.Map.MAP_SCALE * zoom - vh/zoom+(1-zoom)*this.mapH_px * Config.Map.MAP_SCALE); cx=(getX() - cx) ; cy=(getY() - cy) ; // if (zoom * this.mapW_px < vw || zoom * this.mapH_px < vh) { if (zoom < zoomMax) { //Gdx.app.log("阻止缩放", " zoomMax:"+zoomMax+" zoom:"+zoom); // Gdx.app.log("阻止缩放", "w:"+this.mapW_px+" // h:"+this.mapH_px+" vw:"+vw+" vh:"+vh); } else if (zoom > 2.0f) { zoom = 2.0f; } else if (zoom < 0.5f) { zoom = 0.5f; } else { //旧坐标-(鼠标实际坐标-旧坐标)*(新倍率-旧倍率)/旧倍率 //Gdx.app.log("", "x:"+x+" y:"+y+" cx:"+cx+" cy"+cy); x=x+(cx-x)*(zoom-this.zoom)/this.zoom; y=y+(cy-y)*(zoom-this.zoom)/this.zoom; this.zoom = zoom; }
完整代码:
package com.zhfy.game.screen.actor; import java.util.ArrayList; import java.util.HashMap; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.PixmapIO; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; import com.badlogic.gdx.scenes.scene2d.ui.List; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.zhfy.game.config.Config; import com.zhfy.game.config.Config.Map; import com.zhfy.game.framework.GameFramework; import com.zhfy.game.framework.GameMap; import com.zhfy.game.framework.GameUtils; import com.zhfy.game.model.content.MapBin; import com.zhfy.game.model.content.MapBinDAO; import com.zhfy.game.model.content.def.DefMap; import com.zhfy.game.model.content.def.DefPt; import com.zhfy.game.model.content.def.DefTerrainimg; import com.zhfy.game.model.framework.Coord; import com.zhfy.game.model.framework.SpriteDAO; import com.zhfy.game.model.framework.SpriteListDAO; import com.zhfy.game.model.framework.TextureListDAO; public class BgActor extends Actor { //使用左上角为顶点前的备份 // 本类用来存放背景地图,获取地图范围,移动,缩放背景地图,确定点击位置等,以及环状地图 private DefMap defMap; private Pixmap pixmap;// 临时画布 private MapBinDAO mapBinDAO; private MapBin mapBin; private Texture textureLand;// 陆地 // private Texture textureColor;// 颜色 // private Texture textureDecor;// 装饰 // private Texture textureOcean;// 海洋 // private Texture textureGrid;// 网格 private Sprite spriteLand;// 陆地 // private Sprite spriteColor;// 颜色 // private Sprite spriteDecor;// 装饰 // private Sprite spriteOcean;// 海洋 // private Sprite spriteGrid;// 网格 // private GameFramework gameFramework; private int mapW_px; private int mapH_px; private float x; private float y; private float x_vector; private float y_vector; private int w; private int h; private boolean ifGrid;// 是否显示网格 private float zoom; private float zoomMax; private float xMax; private float yMax; // 使用此判断是否需要重新计算绘制坐标 private float mx; private float my; private float mz; private float vw;// 玩家屏幕宽 private float vh;// 玩家屏幕高 // 横向平移2格还原地图 // 纵向平移1格还原地图 // 网格使用 private float vx;// 视口位置x private float vy;// 视口位置y private int gw;// 网格循环横向次数,即宽 private float gw_y; private int gh;// 网格循环纵向次数,即高 private float gh_y; private int gx;// 网格横坐标 private int gy;// 网格纵坐标 private float gx_px;// 网格横坐标 private float gy_px;// 网格纵坐标 private float dx_px;// 装饰横坐标 private float dy_px;// 装饰纵坐标 private float dy_refpx;// 装饰纵坐标偏离 private float dy_yz;//y轴最上方原坐标 public float getDx_px() { return dx_px; } public void setDx_px(float dx_px) { this.dx_px = dx_px; } public float getDy_px() { return dy_px; } public void setDy_px(float dy_px) { this.dy_px = dy_px; } // 绘制陆地使用,大概是1024*1024的大图 int lw; int lh; int li; int lx; int ly; float lx_px = 0; float ly_px = 0; private int gi;// 网格循环次数 // 点击坐标 private Coord coord; // 左下角坐标,即x,y的坐标 private Coord ulcoord; //左上坐标奇偶 private int ul_parity_x; private int ul_parity_y; // 绘制中的坐标以及id private int draw_gx; private int draw_gy; private int draw_gd; // 是否移动时再绘制 private boolean ifDraw = false; // 存放图像素材 private TextureListDAO textureList; // 对图像素材进行操作 private SpriteListDAO spriteList; // 存放spriteList的顺序{m_n,i} private HashMap<String, String> spriteMap; // 存放对应的装饰名与id private HashMap<String, String> tilesMap; DefTerrainimg defTerrainimgTemp; java.util.List<DefTerrainimg> defTerrainimgs; String backTile; String foreTile; // 文字贴图(默认不支持中文)。 BitmapFont bitmapFont; //TODO 测试 随后删除 float qb;float hb; String s2=""; String s1=""; float a0; float a1; float a2; float a3; float a4; float a5; float a6; float a7; float a8; float a9; public float getVx() { return vx; } public void setVx(float vx) { this.vx = vx; } public float getVy() { return vy; } public void setVy(float vy) { this.vy = vy; } public BgActor(GameFramework gameFramework, int mapId, float vw, float vh) { super(); ifGrid = false; // 获取defMap // this.gameFramework=gameFramework; defMap = gameFramework.getDefMapByMapId(mapId); mapBinDAO = gameFramework.getMapDaoByMapId(mapId); { this.x = 0;// TODO 随后设计为玩家起始位置 this.y = 0; this.w = defMap.getWidth(); this.h = defMap.getHeight(); this.vw = vw; this.vh = vh; this.zoom = 1.0f; // 实际宽高 this.mapW_px = GameMap.getWidth(w); this.mapH_px = GameMap.getHeight(h); this.mx = this.x; this.my = this.y; this.mz = this.zoom; this.zoomMax=(vw/(mapW_px)<vh/(mapH_px)?vh/(mapH_px):vw/(mapW_px))/Map.MAP_SCALE; this.xMax= (this.mapW_px * Config.Map.MAP_SCALE * zoom - vw/zoom+(1-zoom)*this.mapW_px * Config.Map.MAP_SCALE); this.yMax= (this.mapH_px * Config.Map.MAP_SCALE * zoom - vh/zoom+(1-zoom)*this.mapH_px * Config.Map.MAP_SCALE); Gdx.app.log("", "w:" + w + " h:" + h + " mapW_px:" + mapW_px + " mapH_px:" + mapH_px+" zoomMax:"+zoomMax); } { // 绘制画布转为陆地 陆地制作一个pixmap大小的地图,实时绘制 // TODO 先默认为这个通用地块色,随后改为加载btl的地图 textureLand = new Texture(Gdx.files.internal("pixmap/pts/pt1.png")); spriteLand = new Sprite(textureLand); } { // 绘制画布转为颜色 // textureColor = new // Texture(Gdx.files.internal("pixmap/tiles/hexagon.png")); // spriteColor= new Sprite(textureColor); } { bitmapFont = new BitmapFont(); bitmapFont.setColor(Color.RED); bitmapFont.getData().setScale(0.8f*zoom); // 绘制画布转为装饰 textureList = new TextureListDAO(); textureList.addPixmapByFileName("pm_tiles"); spriteList = new SpriteListDAO(); spriteMap = spriteList.init(textureList); tilesMap = new HashMap<String, String>(); defTerrainimgTemp = new DefTerrainimg(); defTerrainimgs = new ArrayList<DefTerrainimg>(); try { defTerrainimgs = GameUtils.getDaoListByClass(defTerrainimgTemp, "config/def_terrainimg.xml"); } catch (Exception e) { e.printStackTrace(); } // 将要取得的图片的id和名字放入位置 for (DefTerrainimg defTerrainimg : defTerrainimgs) { tilesMap.put(defTerrainimg.getId() + "_" + defTerrainimg.getIdx(), defTerrainimg.getImage().replace(".png", "")); } } { // 绘制画布转为海洋 } { // 实时绘制网格 // textureGrid = new // Texture(Gdx.files.internal("pixmap/tiles/grid.png")); // spriteGrid = new Sprite(textureGrid); } setSize(this.mapW_px * Config.Map.MAP_SCALE, this.mapH_px * Config.Map.MAP_SCALE); addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { // 点击图片,图片隐藏![这里写图片描述](https://img-blog.csdn.net/20160425220710777) // super.clicked(event, x, y); // Gdx.app.log("点击的精灵位置1", "x:" + (getX()/getZoom()+x)+" y:" // +(getY()/getZoom()+ y)); // 由于要在actor等中使用坐标绘图,所以采用libgdx的actor坐标系 // 左下为0,0,向右上方向负数扩展 //Gdx.app.log("点击背景位置1", "x:" + (getX()-x)+" y:" + (getY()- y)+" zoom:" + zoom); //Gdx.app.log("点击背景位置1", "bgx:" + getX()+" bgy:" + getY()+"zoom:" + zoom+" x:" + x+" y:" + y); // Gdx.app.log("点击背景位置2", "actX:" + (getX()-x)/getZoom()+" // actY:"+ (getY()-y)/getZoom()); // 点击偏移,经过测试x+4 y+20后合适 coord = GameMap.getHotCell(getImgX((getX() - x)/ getZoom()), getImgY((getY()- y)/ getZoom() ),zoom); Gdx.app.log("点击背景位置", "cx:" + (getX() - x)/ getZoom() + " cy:" + (getY()- y)/ getZoom()); //Gdx.app.log("点击背景位置", "imgX:" + getImgX((getX() - x) / getZoom()) + " imgY:" + getImgY((getY() - y) / getZoom())); //Gdx.app.log("点击坐标", "imgX:" + coord.getX() + " imgY:" + coord.getY()); } }); } @Override public void act(float delta) { super.act(delta); } @Override public void draw(Batch batch, float parentAlpha) { super.draw(batch, parentAlpha); { // 实时绘制地图色 // TODO // 实时绘制装饰 // 0.确定每层装饰最大显示格子数 // 0.1增加中间处理,把地图分为n层,可以通过id计算处于某层,或某层包含哪些id // 1.平时绘制2层装饰,缩放超过一定范围,绘制三层装饰 // 2.写一个方法,获取mapbin的每层装饰,然后实时绘制 // 3.测试能否与海洋色一起绘制的效果 { // 实时绘制网格 if (!ifDraw) { mx = 1; } if ((mx != x || my != y || mz != zoom)) { //显示的范围,跨屏显示+3 gw = (int) (((vw / (112 * Config.Map.MAP_SCALE* getZoom())) +2)); gw_y=vw % (112 * Config.Map.MAP_SCALE* zoom); gh = (int) (((vh / (128 * Config.Map.MAP_SCALE* getZoom())) +3)); gh_y=vh % (128 * Config.Map.MAP_SCALE* zoom); ulcoord = GameMap.getHotCell((getImgX()), getImgY(),zoom); //ulcoord = GameMap.getHotCell(getImgX((getX() )/ getZoom()), getImgY((getY())/ getZoom() ),zoom); //Gdx.app.log(""," ulcoord.x:"+ulcoord.getX()+"ulcoord.y:"+(ulcoord.getY()-gh)+ " gw:"+gw+" gh:"+gh); mx = x; my = y; mz = zoom; ul_parity_x=(ulcoord.getX()&1); ul_parity_y=(ulcoord.getY()&1); { // 或根据玩家屏幕大小限制缩放比例 // 绘制循环陆地,如果比例尺大于一定值,则绘制三层 lw = (int) (spriteLand.getWidth() / vw / getZoom() + 2); lh = (int) (spriteLand.getHeight() / vh / getZoom() + 1); lh = lh < 2 ? 2 : lh; for (li = 0; li < lw * lh; li++) { lx = (li % lw) + 1; ly = (li / lw) + 1; //lx_px = getX()*zoom % (spriteLand.getWidth() * getZoom()) + spriteLand.getWidth() * getZoom() * (lx - 1); //ly_px = getY()*zoom % (spriteLand.getHeight() * getZoom()) + spriteLand.getHeight() * getZoom() * (ly - 1); lx_px = getX()*zoom % (spriteLand.getWidth() * getZoom()) + spriteLand.getWidth() * getZoom() * (lx - 1); ly_px = getY()*zoom % (spriteLand.getHeight() * getZoom()) + spriteLand.getHeight() * getZoom() * (ly - 1); //lx_px = -getImgX() % (spriteLand.getWidth() * getZoom()) + spriteLand.getWidth() * getZoom() * (lx - 1); //ly_px = getImgY() % (spriteLand.getHeight() * getZoom()) - spriteLand.getHeight() * getZoom() * (ly - 1); batch.draw(spriteLand, lx_px, ly_px, getOriginX(), getOriginY(), spriteLand.getWidth(), spriteLand.getHeight(), // getScaleX(), getScaleY(), getZoom(), getZoom(), getRotation()); bitmapFont.draw(batch, "id:"+li, lx_px-27*zoom, ly_px+48*zoom); } //Gdx.app.log("1", " lw:" + lw + " lh:" + lh + " size:"+ lw * lh + " zoom:" + zoom + " lx_px:" + lx_px + "ly_px:" + ly_px); } //Gdx.app.log("3"," dx_px:"+dx_px+" dy_px:"+dy_px+" ulcoordx:"+ulcoord.x+" x:"+getX()+" gw:"+gw); for (gi = 0; gi < gw * gh; gi++) { gx = (gi % gw) + 1; gy = (gi / gw) + 1; //gx_px = -getImgX() % (224 * Config.Map.MAP_SCALE * this.zoom) + ((gx - 1) * 112 * getZoom() * Config.Map.MAP_SCALE); //gy_px = (getImgY() % (128 * Config.Map.MAP_SCALE * this.zoom)+(((gx & 1) == 1 ? (gy - 1) * 128 : (gy - 1) * 128 - 62))* getZoom() * Config.Map.MAP_SCALE); //TODO 获取屏幕中点与游戏显示中点,缩放等比例距离保持比例一致 //dx_px = -(((int)((getX())/ (112 * Config.Map.MAP_SCALE * this.zoom)))*(112 * Config.Map.MAP_SCALE * this.zoom))+ (((gx-1) * 112 )* getZoom() * Config.Map.MAP_SCALE)+getX(); //dx_px = -getImgX()+(((int)((getImgX())/ (112 * Config.Map.MAP_SCALE * this.zoom)))*(112 * Config.Map.MAP_SCALE * this.zoom))+ ((gx-1) * 112 * getZoom() * Config.Map.MAP_SCALE)/*+zoom==1?0:(112 * zoom * Config.Map.MAP_SCALE)*/; dx_px = -getImgX()*zoom+((int)((getImgX()* this.zoom)/ (112 * Config.Map.MAP_SCALE * this.zoom)))*(112 * Config.Map.MAP_SCALE * this.zoom)+( ((gx-1) * 112 * getZoom() * Config.Map.MAP_SCALE))/*+zoom==1?0:(112 * zoom * Config.Map.MAP_SCALE)*/; //dx_px = -getImgX()*zoom+((int)((getImgX()* this.zoom)/ (112 * Config.Map.MAP_SCALE * this.zoom)))*(112 * Config.Map.MAP_SCALE * this.zoom)+( ((gx-1) * 112 * getZoom() * Config.Map.MAP_SCALE))/*+zoom==1?0:(112 * zoom * Config.Map.MAP_SCALE)*/; // dx_px = getX()*zoom % (112 * Config.Map.MAP_SCALE * getZoom())+(112 * Config.Map.MAP_SCALE * getZoom())*(gx-1); /*if(gi==0) { a1=(getImgX()); a2=((int)((getImgX())/ (112 * Config.Map.MAP_SCALE * this.zoom))); a3=((112 * Config.Map.MAP_SCALE * this.zoom)); a4=(gx-1) ; a5=-a1+a2*a3+a4*a3; a9=dx_px; }*/ dy_px = -(vh%(128 * Config.Map.MAP_SCALE *zoom))+((vh)/zoom)*(zoom-1)+getImgY()*zoom+vh/zoom-((((int)((getImgY()*zoom)/ (128 * Config.Map.MAP_SCALE *zoom)))*(128 * Config.Map.MAP_SCALE * zoom))+ (((gy-1) * 128 +( (gx & 1) == 1 ? 0 : ((ul_parity_x&1)==1?-62:62)))* getZoom() * Config.Map.MAP_SCALE)+((ul_parity_x&1)==1?62:0)* Config.Map.MAP_SCALE * zoom); //正确 dy_px = ((vh)/zoom)*(zoom-1)+getImgY()*zoom+vh/zoom-((((int)((getImgY()*zoom)/ (128 * Config.Map.MAP_SCALE *zoom)))*(128 * Config.Map.MAP_SCALE * zoom))+ (((gy-1) * 128 +( (gx & 1) == 1 ? 0 : ((ul_parity_x&1)==1?-62:62)))* getZoom() * Config.Map.MAP_SCALE)+((ul_parity_x&1)==1?62:0)* Config.Map.MAP_SCALE * zoom); // dy_px = (h+(int)((getY()*zoom)/ (128 * Config.Map.MAP_SCALE *zoom)))*(128 * Config.Map.MAP_SCALE * zoom)+(y*zoom % (128 * Config.Map.MAP_SCALE * getZoom()))- (((gy-1) * 128 +( (gx & 1) == 1 ? 0 : ((ul_parity_x&1)==1?-62:62)))* getZoom() * Config.Map.MAP_SCALE)+((ul_parity_x&1)==1?0:62)* Config.Map.MAP_SCALE * zoom; s1=" dy_refpx:"+gy+" y:"+zoom; //Gdx.app.log("", " x:"+dy_px); if(draw_gd==1&&!s1.equals(s2)) { //dy_px=dy_px-(mapH_px-dy_px)*zoom; //Gdx.app.log("", " dy_px:"+dy_px+" yMax:"+((yMax+y/zoom)-dy_px)); /* a1=(((vh)/zoom)*(zoom-1)+(mapH_px * Config.Map.MAP_SCALE-yMax)*zoom+vh/zoom); a2=((int)(((mapH_px * Config.Map.MAP_SCALE-yMax)*zoom)/ (128 * Config.Map.MAP_SCALE *zoom))); a3=(128 * Config.Map.MAP_SCALE *zoom); a4=(((-ulcoord.getY()+ gh-1) * 128 +62)* getZoom() * Config.Map.MAP_SCALE); a5=((ul_parity_x&1)==1?62:0)* Config.Map.MAP_SCALE * zoom; a9=(((vh)/zoom)*(zoom-1)+(mapH_px * Config.Map.MAP_SCALE-yMax)*zoom+vh/zoom)-((((int)(((mapH_px * Config.Map.MAP_SCALE-yMax)*zoom)/ (128 * Config.Map.MAP_SCALE *zoom)))*(128 * Config.Map.MAP_SCALE *zoom))+(((-ulcoord.getY()+ gh-1) * 128 +62)* getZoom() * Config.Map.MAP_SCALE)); Gdx.app.log("", " a1:"+a1+" a2:"+a2+" a3:"+a3+" a4:"+a4+" a5:"+a5+" a9:"+a9+" dy_px:"+dy_px); */ Gdx.app.log("", " gi:"+gi+" gw:"+gw+" gw_y:"+gw_y+" gh:"+gh+" gh_y:"+gh_y+" gx:"+gx+" gy:"+gy+" dy_px:"+dy_px+" ulcoord_X:"+ulcoord.getX()+" getImgY:"+getImgY()+" ulcoord_Y:"+ulcoord.getY()+" zoom:"+zoom+" dy_yz:"+dy_yz+" dy_px:"+dy_px); s2=s1; } // 绘制背景色 // TODO 获取背景色,然后根据颜色排序,然后为batch赋值并绘制 // batch.setColor(123,123,123,123); /* * batch.setColor(new Color( * GameUtils.toIntColor(191,200,41,255))); * batch.draw(spriteColor, gx_px, gy_px, getOriginX(), * getOriginY(), spriteGrid.getWidth() * * Config.Map.MAP_SCALE, spriteGrid.getHeight() * * Config.Map.MAP_SCALE, getZoom(), getZoom(), * getRotation()); * * //Gdx.app.log(""," r:"+Color.RED.r+" g:"+Color.RED. * g+" b:"+Color.RED.b+" a:"+Color.RED.a); */ // 绘制装饰 // 1.建立sprite合集存放图片√ // 2.获取左上角坐标,推算显示的数量是哪几个 // 3.再从对应的mapbin中获取显示的id值,然后在sprite合集的图片中取出对应图片放入相应位置 // 要显示的id,以及对应的图片 // 绘制的x坐标 draw_gx = ulcoord.getX() + gx - 2; draw_gy = ulcoord.getY() + gy - gh ; draw_gd = w * draw_gy + draw_gx+1; /* s1="dx_px:"+dx_px+" draw_gy:"+draw_gy+" draw_gd:"+draw_gd+" x:"+getX(); if(draw_gd==7791&&!s1.equals(s2)) { a1=(getImgX()); a2=((int)((getImgX())/ (112 * Config.Map.MAP_SCALE * this.zoom))); a3=((112 * Config.Map.MAP_SCALE * this.zoom)); a4=(gx-1) ; a5=-a1+a2*a3+a4*a3; a9=dx_px; // Gdx.app.log("3", "dx_px:"+dx_px+" a1:"+a1+" a2:"+a2+" a3:"+a3+" a4:"+a4+" a5:"+a5+" a9:"+a9+" gx:"+gx+" gw:"+gw+" zoom:"+zoom); s2=s1; } */ if (draw_gx < w && draw_gy < h &&draw_gd<mapBinDAO.getMapbin().size()&&draw_gd>=0) { //mapBin = mapBinDAO.getMapbin().get((ulcoord.getX() + gx) * ((ulcoord.getY() - 1 + gy)) + ulcoord.getY() + gy); //TODO mapBin = mapBinDAO.getMapbin().get(draw_gd); backTile = tilesMap.get(mapBin.getBackTile() + "_" + mapBin.getBackIdx()); if (backTile == null) { backTile = tilesMap.get(mapBin.getBackTile() + "_1"); } // Gdx.app.log("绘制的坐标为:","x:"+draw_gx+" // y:"+draw_gy+" id:"+draw_gd); if (backTile != null) { batch.draw(spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getSprite(), dx_px+mapBin.getBackRefX()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefx()*zoom*Config.Map.MAP_SCALE, dy_px+mapBin.getBackRefY()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefy()*zoom*Config.Map.MAP_SCALE, getOriginX(), getOriginY(), spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getSprite().getWidth() * Config.Map.MAP_SCALE, spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getSprite().getHeight() * Config.Map.MAP_SCALE, getZoom(), getZoom(), getRotation()); } else { // Gdx.app.log("", "id:"+draw_gd+" // backTile:"+backTile); } foreTile = tilesMap.get(mapBin.getForeTile() + "_" + mapBin.getForeIdx()); if (foreTile == null) { foreTile = tilesMap.get(mapBin.getForeTile() + "_1"); } if (foreTile != null) {//dx_px-spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefx()*zoom*Config.Map.MAP_SCALE, dy_px-spriteList.get(Integer.parseInt(spriteMap.get(backTile))).getRefy()*zoom*Config.Map.MAP_SCALE batch.draw(spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getSprite(), dx_px+mapBin.getForeRefX()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getRefx()*zoom*Config.Map.MAP_SCALE, dy_px+mapBin.getForeRefY()*zoom*Config.Map.MAP_SCALE+spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getRefy()*zoom*Config.Map.MAP_SCALE, getOriginX(), getOriginY(), spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getSprite().getWidth() * Config.Map.MAP_SCALE, spriteList.get(Integer.parseInt(spriteMap.get(foreTile))).getSprite().getHeight() * Config.Map.MAP_SCALE, getZoom(), getZoom(), getRotation()); } else { // Gdx.app.log("", "id:"+draw_gd+" // foreTile:"+foreTile); } /**/ if (ifGrid) { //字体 bitmapFont.draw(batch, "id:"+draw_gd, dx_px-27*zoom, dy_px+50*zoom); bitmapFont.draw(batch, "gi:"+gi, dx_px-27*zoom, dy_px+40*zoom); bitmapFont.draw(batch, " x:"+draw_gx, dx_px-25*zoom, dy_px+61*zoom); bitmapFont.draw(batch, " y:"+draw_gy, dx_px-25*zoom, dy_px+30*zoom); } /* if(gi==0) { bitmapFont.draw(batch, "dy_px:"+dy_px,dx_px-27*zoom, dy_px+48*zoom); }*/ } // 绘制海洋色 // 绘制网格 if (ifGrid) { batch.draw(spriteList.get(Integer.parseInt(spriteMap.get("grid"))).getSprite(), dx_px, dy_px, getOriginX(), getOriginY(), spriteList.get(Integer.parseInt(spriteMap.get("grid"))).getSprite().getWidth() * Config.Map.MAP_SCALE, spriteList.get(Integer.parseInt(spriteMap.get("grid"))).getSprite().getHeight() * Config.Map.MAP_SCALE, getZoom(), getZoom(), getRotation()); // Gdx.app.log("", "12"); } } } } } } public float getX() { if (this.x > 0) { x = 0; } else if (this.x < -(xMax)) { x = -(xMax); //Gdx.app.log("边界修正", x+""); } return x; } public void setX(float x) { this.x_vector=x-this.x; //x_vector=x_vector<0?-x_vector:x_vector; this.x = x; } public float getY() { // Gdx.app.log("边界修正", "yMax:"+(y)); if (this.y > 0) { y = 0; } else if (this.y < -yMax) { y = -yMax; // Gdx.app.log("边界修正", "yMax:"+(y)); } return y; } public void setY(float y) { this.y_vector=y-this.y; //y_vector=y_vector<0?-y_vector:y_vector; this.y = y; } public int getW() { return w; } public void setW(int w) { this.w = w; } public int getH() { return h; } public void setH(int h) { this.h = h; } public float getVw() { return vw; } public void setVw(float vw) { this.vw = vw; } public float getVh() { return vh; } public void setVh(float vh) { this.vh = vh; } public float getZoom() { return zoom; } public void setZoom(float zoom,float cx,float cy) { this.xMax= (this.mapW_px * Config.Map.MAP_SCALE * zoom - vw/zoom+(1-zoom)*this.mapW_px * Config.Map.MAP_SCALE); this.yMax= (this.mapH_px * Config.Map.MAP_SCALE * zoom - vh/zoom+(1-zoom)*this.mapH_px * Config.Map.MAP_SCALE); cx=(getX() - cx) ; cy=(getY() - cy) ; // if (zoom * this.mapW_px < vw || zoom * this.mapH_px < vh) { if (zoom < zoomMax) { //Gdx.app.log("阻止缩放", " zoomMax:"+zoomMax+" zoom:"+zoom); // Gdx.app.log("阻止缩放", "w:"+this.mapW_px+" // h:"+this.mapH_px+" vw:"+vw+" vh:"+vh); } else if (zoom > 2.0f) { zoom = 2.0f; } else if (zoom < 0.5f) { zoom = 0.5f; } else { //Gdx.app.log(""," ulcoord_x:"+ulcoord.getX()+" ulcoord_y:"+ulcoord.getY()); // Gdx.app.log("容许缩放2", "w:"+this.mapW_px+" // h:"+this.mapH_px+" vw:"+vw+" vh:"+vh); /* * //改变前的中心点 float cx=(x-vw/2)/getZoom(); float * cy=(y-vh/2)/getZoom(); //改变后的中心点 float ex=(x-vw/2)/zoom; float * ey=(y-vh/2)/zoom; Gdx.app.log("变化地图1", "x:"+x+" y:"+y); * this.x=x-(ex-cx)*zoom; this.y=y-(ey-cy)*zoom; * Gdx.app.log("变化地图2", "x:"+x+" y:"+y); Gdx.app.log("变化地图", * "cx:"+cx+" cy:"+cy+" ex:"+ex+" ey:"+ey); Gdx.app.log("变化地图", * "中心点x差:"+(ex-cx)+" y差:"+(ey-cy)+" zoom:"+(this.zoom-zoom)); */ //this.x = x - (((x - vw / 2) / zoom) - ((x - vw / 2) / this.zoom)) * zoom -getX()*(zoom-this.zoom)%(vw * getZoom()) ; //this.y = y - (((y - vh / 2) / zoom) - ((y - vh / 2) / this.zoom)) * zoom -getY()*(zoom-this.zoom)%(vh * getZoom()); //this.x=x+(vw)*(this.zoom-zoom); //this.y=; //this.x = x - (((x - vw / 2) / zoom) - ((x - vw / 2) / this.zoom)) * zoom;//x+(x*(zoom-this.zoom));// //this.y = y - (((y - vh / 2) / zoom) - ((y - vh / 2) / this.zoom)) * zoom;//y+(y*(zoom-this.zoom));// //旧坐标-(鼠标实际坐标-旧坐标)*(新倍率-旧倍率)/旧倍率 //Gdx.app.log("", "x:"+x+" y:"+y+" cx:"+cx+" cy"+cy); x=x+(cx-x)*(zoom-this.zoom)/this.zoom; y=y+(cy-y)*(zoom-this.zoom)/this.zoom; //this.x=x; //this.y=y; //this.x = x - (((x - vw / 2) / zoom) - ((x - vw / 2) / this.zoom)) * zoom -getX()*(zoom-this.zoom)%(vw * getZoom()) ; //this.y = y - (((y - vh / 2) / zoom) - ((y - vh / 2) / this.zoom)) * zoom -getY()*(zoom-this.zoom)%(vh * getZoom()); //this.x = x - (((x) / zoom) - ((x - vw / 2) / this.zoom)) * zoom -getX()*(zoom-this.zoom)%(vw * getZoom()) ; //this.x=(x-vw)*; //this.y=(y-vh)*(this.zoom-zoom); this.zoom = zoom; // this.x=x-this.this.mapW_px*(this.zoom-zoom)/2; // this.y=y+vh*(this.zoom-zoom); } //Gdx.app.log("", " a3:"+a3+" dy_refpx:"+dy_refpx+" dy_px:"+dy_px+" zoom:"+zoom+" ul_parity_x&1:"+(ul_parity_x&1)+" "); //dy_px =((vh)/zoom)*(zoom-1)+getImgY()*zoom+vh/zoom-((((int)((getImgY()*zoom)/ (128 * Config.Map.MAP_SCALE *zoom)))*(128 * Config.Map.MAP_SCALE * zoom))+ (((gy-1) * 128 +( (gx & 1) == 1 ? 0 : ((ul_parity_x&1)==1?-62:62)))* getZoom() * Config.Map.MAP_SCALE)+((ul_parity_x&1)==1?62:0)* Config.Map.MAP_SCALE * zoom); /* a1=((vh)/zoom)*(zoom-1)+getImgY()*zoom+vh/zoom; a2=(int)((getImgY()*zoom)/ (128 * Config.Map.MAP_SCALE *zoom)); a3=(128 * Config.Map.MAP_SCALE * zoom); a4=(((gy-1) * 128 +( (gx & 1) == 1 ? 0 : ((ul_parity_x&1)==1?-62:62)))* getZoom() * Config.Map.MAP_SCALE); a5=((ul_parity_x&1)==1?62:0)* Config.Map.MAP_SCALE * zoom; //a6=; //a7=; //a8=; a9=a1-((a2*a3)+a4+a5); Gdx.app.log("", " a1:"+a1+" a2:"+a2+" a3:"+a3+" a4:"+a4+" a5:"+a5+" a9:"+a9+" zoom:"+zoom); */ } // 将↓→坐标(左上角为0,0,越向右下越大)转为←↓act坐标(左下角为0,0,越向右上越小) public float getActXCoordByImgX(float print_x) { return (-print_x); } public float getActYCoordByImgY(float print_y) { return (print_y - this.mapH_px); } // 将←↓act坐标(左下角为0,0,越向右上越小)转化为↓→坐标(左上角为0,0,越向右下越大) // 将↓→坐标(左上角为0,0,越向右下越大)转为←↓act坐标(左下角为0,0,越向右上越小) public float getImgX(float print_x) { if (print_x != 0f) { return (-print_x); } else { return 0f; } } public float getImgY(float print_y) { return (this.mapH_px * Config.Map.MAP_SCALE + print_y); } //获取实际坐标 public float getImgX() { if (this.x != 0f) { return (-this.x); } else { return 0f; } } public float getImgY() { return (this.mapH_px * Config.Map.MAP_SCALE + this.y); } // 清理5张图层 public void dispose() { if (textureLand != null) { textureLand.dispose(); } /* * if (textureGrid != null) { textureGrid.dispose(); } if (textureColor * != null) { textureColor.dispose(); } if (textureDecor != null) { * textureDecor.dispose(); } if (textureOcean != null) { * textureOcean.dispose(); } */ if (textureList != null) { textureList.clearAll(); textureList = null; spriteList = null; } if (defMap != null) { defMap = null; } if (bitmapFont != null) { bitmapFont.dispose(); } } public DefMap getDefMap() { return defMap; } public void setDefMap(DefMap defMap) { this.defMap = defMap; } public Pixmap getPixmap() { return pixmap; } public void setPixmap(Pixmap pixmap) { this.pixmap = pixmap; } public MapBinDAO getMapBinDAO() { return mapBinDAO; } public void setMapBinDAO(MapBinDAO mapBinDAO) { this.mapBinDAO = mapBinDAO; } public Texture getTextureLand() { return textureLand; } public void setTextureLand(Texture textureLand) { this.textureLand = textureLand; } public Sprite getSpriteLand() { return spriteLand; } public void setSpriteLand(Sprite spriteLand) { this.spriteLand = spriteLand; } public boolean isIfGrid() { return ifGrid; } public void setIfGrid(boolean ifGrid) { this.ifGrid = ifGrid; } public float getZoomMax() { return zoomMax; } public void setZoomMax(float zoomMax) { this.zoomMax = zoomMax; } public int getGw() { return gw; } public void setGw(int gw) { this.gw = gw; } public int getGh() { return gh; } public void setGh(int gh) { this.gh = gh; } public int getMapW_px() { return mapW_px; } public void setMapW_px(int mapW_px) { this.mapW_px = mapW_px; } public int getMapH_px() { return mapH_px; } public void setMapH_px(int mapH_px) { this.mapH_px = mapH_px; } public TextureListDAO getTextureList() { return textureList; } public void setTextureList(TextureListDAO textureList) { this.textureList = textureList; } public SpriteListDAO getSpriteList() { return spriteList; } public void setSpriteList(SpriteListDAO spriteList) { this.spriteList = spriteList; } public Coord getUlcoord() { return ulcoord; } public void setUlcoord(Coord ulcoord) { this.ulcoord = ulcoord; } public float getA1() { return a1; } public void setA1(float a1) { this.a1 = a1; } public float getA2() { return a2; } public void setA2(float a2) { this.a2 = a2; } public float getA3() { return a3; } public void setA3(float a3) { this.a3 = a3; } public float getA4() { return a4; } public void setA4(float a4) { this.a4 = a4; } public float getA5() { return a5; } public void setA5(float a5) { this.a5 = a5; } public float getA9() { return a9; } public void setA9(float a9) { this.a9 = a9; } }
感慨下:数学不学好,做游戏空流泪 ----记于2019年4月5日
在随后的测试中,发现这种绘制方法存在一些问题:
drawcell过高,即一秒要在屏幕绘制700多次
这个的原因是因为实时绘制的是动态网格而不是少量的图,所以导致的这个问题,
从大佬们那里得到一种解决思路;把根据当前屏幕把图片动态合为512*512的图来显示
这个等项目完成阶段再做尝试 --记于4.16