蒙板压缩对比图:(此方法可大幅减小游戏包的大小)

包大小对比:

在游戏开发中,包的大小总是与图片资源的大小密切相关,而图片资源中,大多为带有透明度信息的png图像。

那么,如何精简png图片资源呢?

1、图像压缩是一种方法,然而随着压缩率的增大、图片品质也越来越差。(舍弃)

2、我们另辟蹊径,采用png图像拆分。(近乎无损,资源精简)

一、原理:将png图像转化为两张jpeg图像进行存储


pngSplit下载

pngSplit使用说明


二、使用方法:

1、LibGdx中,通过Pixmap使用


// 如工程目录assets/texture/0_1.jpeg下:
/** 从工程资源路径下获取图像,如:filePath1 = "texture/0_1.jpeg"、filePath2 = "texture/0_2.jpeg" */
public static Texture getTexture(String filePath1, String filePath2)
{try{Pixmap pic1 = new Pixmap(Gdx.files.internal(filePath1));Pixmap pic2 = new Pixmap(Gdx.files.internal(filePath2));Pixmap pic = Combine(pic1, pic2);   // 合并为png图像return new Texture(pic);         // 创建Texture}catch (Exception ex){return null;}
}/** 从Pic和Mask合成图像 */
public static Pixmap Combine(Pixmap Pic, Pixmap Mask)
{int width = Pic.getWidth(), height = Pic.getHeight();    // 获取图像的尺寸Pixmap image = new Pixmap(closestTwoPower(width), closestTwoPower(height), Format.RGBA8888); // 合成尺寸为2的幂int color1, color2, color, alpha;for (int i = 0; i < width; i++){for (int j = 0; j < height; j++){color1 = Pic.getPixel(i, j);  // 原图像像素信息color2 = Mask.getPixel(i, j);    // 原图像透明度信息alpha = (color2 & 0xff00) >> 8;                           // 透明度color = alpha == 0 ? 0 : (color1 & 0xffffff00) | alpha;    // 合成像素点image.drawPixel(i, j, color);   // 生成图像}}return image;
}/** 获取最接近于n的2的幂 */
public static int closestTwoPower(int n)
{int power = 1;while (power < n)power <<= 1;return power;
}


2、安卓中,通过 Bitmap使用(未调试)


/** 从工程资源路径下获取图像,如:filePath1 = "0_1.jpeg"、filePath2 = "0_2.jpeg" */
public static Bitmap getBitmap(String pathName1, String pathName2)
{try{Bitmap pic1 = BitmapFactory.decodeFile(pathName1);Bitmap pic2 = BitmapFactory.decodeFile(pathName2);Bitmap pic = Combine(pic1, pic2);   // 合并为png图像return pic;}catch (Exception ex){return null;}
}/** 从Pic和Mask创建bitmap图像 */
public static Bitmap Combine(Bitmap Pic, Bitmap Mask)
{int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);int color1, color2, color;for (int i = 0; i < width; i++){for (int j = 0; j < height; j++){color1 = Pic.getPixel(i, j); // 原图像像素信息color2 = Pic.getPixel(i, j); // 原图像透明度信息color = (color1 & 0x00ffffff) | ((color2 & 0x00ff0000) << 8); // 合成像素点image.setPixel(i, j, color); // 生成图像}}return image;
}

附类文件:(测试通过)

Bitmap2.java

/** 2015-5-25上午10:10:15 wangzhongyuan */package com.hlge.lib.base;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Environment;import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.hlge.lib.HlgeActivity;
import com.hlge.lib.tool.Tools;/** Bitmap2,对Bitmap进行相关图像处理、转化Bitmap的尺寸为2的幂,推荐使用函数getPixmapExt获取图像资源 ----- 2015-5-21 下午2:06:43 wangzhongyuan */
public class Bitmap2
{/** 临时记录载入图像的尺寸 */static int sizex, sizey;/** 标识是否保存至缓存文件 */private static boolean SaveTmpFile = false;/** 图片缓存文件拓展名 */private static String tmpExt = ".png";              // 缓存文件的实际类型public static final String ReadSaveExt = ".png"; // 缓存文件读取和写入使用的文件拓展名// -------------------------------------------------------------------------------------------------/** 此hansh表中的图像资源,直接从内部资源进行载入 */public static HashMap<String, String> LoadList = new HashMap<String, String>(); // 以 path + name为索引,拓展名为值/** 此hansh表中的图像资源,从内部资源进行蒙板合成 */public static ArrayList<String> CombineList = new ArrayList<String>();         // 以 path + name为键值/** 对path路径下的所有图像按文件名分类, path = "texture/" */public static void groupPicByName(String path){// 路径有效性判定FileHandle dir = Gdx.files.internal(path);if (!dir.exists() || !dir.isDirectory())Tools.Log(path + "不是有效路径!");else{FileHandle[] files = dir.list();for (FileHandle file : files){String name = file.name();if (name.endsWith("_1.jpeg") || name.endsWith("_2.jpeg")){name = name.substring(0, name.lastIndexOf("_"));if (!CombineList.contains(path + name)) CombineList.add(path + name);                        // 蒙板合并图像}else if (name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg")){name = name.substring(0, name.lastIndexOf("."));if (!LoadList.containsKey(path + name)) LoadList.put(path + name, "." + file.extension());   // 直接载入图像}}}}/** 预加载图像,载入进度 */public static int loadprocess = 0;/** 预加载所有蒙板图像,合成外部png缓存文件,在游戏载入时调用该函数,提前处理图像资源*/public static void loadResources(){// 将文件夹中的图像资源按文件名分类存入LoadList和CombineListgroupPicByName("texture/");groupPicByName("spine/");// // 判定是否已对所有图像资源进行了缓存载入// String value = LocalDB.readData("Bitmap2_loadResources");// if (value.equals("3")) return;// LocalDB.saveData("Bitmap2_loadResources", "3");for (int i = 0; i < CombineList.size(); i++){String pathName = CombineList.get(i);FileHandle file = new FileHandle(getPath() + pathName + ReadSaveExt); // 缓存文件判定if (!file.exists()){Bitmap pic = getBitmap(pathName + "_1.jpeg", pathName + "_2.jpeg"); // 合成图像int end = pathName.lastIndexOf("/") + 1;String path = end != -1 ? pathName.substring(0, end) : "";String name = end != -1 ? pathName.substring(end) : pathName;Bitmap2.save(path, name, pic);  // 保存至文件缓存pic.recycle();                    // 释放资源}loadprocess = (int) ((((float) i) / CombineList.size()) * 100);Tools.Log("蒙板图像载入进度 " + loadprocess + "% ");}loadprocess = 100;}/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */public static Pixmap getPixmapExt(String path, String fileName){Pixmap pic = null;try{pic = Pixmap2.read(path, fileName, ReadSaveExt);   // 从缓存中读取if (pic != null) return pic;String pathName = path + fileName;if (CombineList.contains(pathName))// 直接从蒙板合成图像{Bitmap tmp = getBitmap(pathName + "_1.jpeg", pathName + "_2.jpeg");pic = ToPixmap(tmp);Bitmap2.save(path, fileName, tmp);             // 保存至文件缓存tmp.recycle();                                    // 释放资源}else if (LoadList.containsKey(pathName))// 直接从内部资源载入图像{String Ext = LoadList.get(pathName);pic = new Pixmap(Gdx.files.internal(pathName + Ext));// 载入图像尺寸校验,需为2的次幂int width = pic.getWidth(), height = pic.getHeight();int w = Bitmap2.closestTwoPower(width), h = Bitmap2.closestTwoPower(height);if (w != width || h != height){Bitmap tmp = getBitmap(pathName + Ext);pic = ToPixmap(tmp);Bitmap2.save(path, fileName, tmp);              // 保存至文件缓存tmp.recycle();                                    // 释放资源}}else// 检索所有拓展名载入{Bitmap tmp = getBitmapExtProcess(path, fileName);    // 从工程内部资源文件生成Bitmap2.save(path, fileName, tmp);                    // 保存至文件缓存pic = ToPixmap(tmp);                             // 转化为Pixmaptmp.recycle();}return pic;}catch (Exception ex){Tools.Log("载入图像" + path + fileName + "出错!");return null;}}/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic",获取图像后自动缓存至文件 */public static Bitmap getBitmapExt(String path, String fileName){Bitmap pic = Bitmap2.read(path, fileName);       // 优先从本地文件缓存中读取if (pic != null)return pic;else{pic = getBitmapExtProcess(path, fileName); // 从工程内部资源文件生成Bitmap2.save(path, fileName, pic);            // 保存至文件缓存return pic;}}/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */private static Bitmap getBitmapExtProcess(String path, String fileName){String filePath = path + fileName;   // 工程内部资源路径+文件名(无拓展名)Bitmap pic;// 载入png或jpg图像String[] Exts = { ".png", ".jpg", ".jpeg" };for (String exts : Exts){tmpExt = exts;pic = getAssetsBitmap(path + fileName + exts);if (pic != null) return FormatSize(pic);}// 从pngSplit工具,导出的蒙板图像载入tmpExt = ".png";pic = getBitmap(path + fileName + "_1.jpeg", path + fileName + "_2.jpeg");if (pic != null) return pic;Tools.Log(filePath + " Bitmap载入出错!");return null;}// pic = getImageFromAssetsFile("assets/texture/0.png");/** 从Assets目录中读取图片, fileName = "texture/0_1.jpeg" */@SuppressWarnings("unused")public static Bitmap getAssetsBitmap(String fileName){// 判断文件是否存在FileHandle handle = Gdx.files.internal(fileName);if (!handle.exists()) return null;Bitmap image = null;AssetManager manager = HlgeActivity.$this.getResources().getAssets();try{InputStream is = manager.open(fileName);image = BitmapFactory.decodeStream(is);is.close();}catch (IOException e){e.printStackTrace();}return image;}// 如工程目录assets/texture/0_1.jpeg下:/** 获取工程目录下的图像,如:filePath = "texture/0_1.jpeg" */public static Bitmap getBitmap(String filePath){Bitmap pic = getAssetsBitmap(filePath);   // 从assets获取图像pic = FormatSize(pic);                   // 转化为2的n次幂return pic;}// 如工程目录assets/texture/0_1.jpeg下:/** 从pngSplit工具,导出的两张蒙板图像创建,如:filePath1 = "texture/0_1.jpeg"、filePath2 = "texture/0_2.jpeg" */public static Bitmap getBitmap(String filePath1, String filePath2){try{Bitmap pic1 = getAssetsBitmap(filePath1);Bitmap pic2 = getAssetsBitmap(filePath2);Bitmap pic = Bitmap2.Combine(pic1, pic2);pic1.recycle();pic2.recycle();return pic;}catch (Exception ex){Tools.Log("从蒙板资源创建Bitmap出错!(" + filePath1 + "、" + filePath2 + ")");return null;}}/** 从两张蒙板图像Pic和Mask,合成图像 */public static Bitmap Combine(Bitmap Pic, Bitmap Mask){try{int width = Pic.getWidth(), height = Pic.getHeight();   // 获取图像的尺寸Bitmap2.sizex = width;                                   // 记录图像原尺寸Bitmap2.sizey = height;int w = Bitmap2.closestTwoPower(width), h = Bitmap2.closestTwoPower(height);Bitmap image = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); // 合成尺寸为2的幂// image.eraseColor(0xffffffff);int color1, color2, color;for (int i = 0; i < width; i++){for (int j = 0; j < height; j++){color1 = Pic.getPixel(i, j);     // 原图像像素信息color2 = Mask.getPixel(i, j);    // 原图像透明度信息color = (color1 & 0x00ffffff) | ((color2 & 0x00ff0000) << 8); // 合成像素点image.setPixel(i, j, color);    // 生成图像}}SaveTmpFile = true;       // 可保存当前图像至缓存return image;}catch (Exception ex){Tools.Log("从蒙板合成图像出错!");return null;}}/** 将Pic转化为尺寸为2的幂的图像 */public static Bitmap FormatSize(Bitmap Pic){try{int width = Pic.getWidth(), height = Pic.getHeight();   // 获取图像的尺寸Bitmap2.sizex = width;                                   // 记录图像原尺寸Bitmap2.sizey = height;int w = Bitmap2.closestTwoPower(width), h = Bitmap2.closestTwoPower(height);if (w == width && h == height) return Pic;              // 若原图像尺寸为2的幂,则直接返回原图像// 构建2的n次幂图像Bitmap image = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas g2d = new Canvas(image);g2d.drawBitmap(Pic, 0, 0, new Paint());// Paint p = new Paint();// p.setColor(Color.WHITE);// p.setAntiAlias(true);// p.setFilterBitmap(true);// int color;// for (int i = 0; i < width; i++)// {// for (int j = 0; j < height; j++)// {// color = Pic.getPixel(i, j); // 原图像像素信息// image.setPixel(i, j, color); // 生成图像// }// }SaveTmpFile = true;  // 可保存当前图像至缓存return image;}catch (Exception ex){Tools.Log("Bitmap尺寸转化为2的幂出错!");return null;}}/** 获取最接近于n的2的幂 */public static int closestTwoPower(int n){int power = 1;while (power < n)power <<= 1;return power;}/** 获取SD卡或内部存储路径,优先选择SD卡 , "/tmp/" */public static String getPath(){if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))return Environment.getExternalStorageDirectory().getPath() + "/tmp/";elsereturn "/tmp/";}/** 从本地缓存文件载入Pixmap, subPath为子文件夹,如:"sub/" */public static Bitmap read(String subPath, String fileName){try{// 从指定路径获取文件String path = getPath() + subPath, name = fileName + ReadSaveExt;File file = new File(path, name);// 创建Bitmapif (file.exists())return BitmapFactory.decodeFile(path + name);elsereturn null;}catch (Exception e){Tools.Log("Bitmap文件读取出错(" + fileName + tmpExt + ") " + e.toString());return null;}}// /** 保存pixmap到缓存文件fileName, subPath为子文件夹,如:"sub/", 不进行条件判断存储 */// public static void saveOne(String subPath, String fileName, Bitmap bitmap)// {// if (bitmap == null) return;//// SaveTmpFile = true;// save(subPath, fileName, bitmap);//// bitmap = null;// }/** 保存pixmap到缓存文件fileName, subPath为子文件夹,如:"sub/" */public static void save(String subPath, String fileName, Bitmap bitmap){if (bitmap == null) return;    // 图像为nullif (SaveTmpFile)SaveTmpFile = false; // 可保存当前图像至缓存elsereturn;try{// 确保路径文件存在String path = getPath() + subPath, name = fileName + ReadSaveExt;File dir = new File(path);if (!dir.exists()) dir.mkdirs();File file = new File(path, name);if (!file.exists()) file.delete();file.createNewFile();// 压缩格式设置CompressFormat format = CompressFormat.PNG;if (tmpExt.equalsIgnoreCase(".jpg") || tmpExt.equalsIgnoreCase(".jpeg")) format = CompressFormat.JPEG;// 保存图像到文件Bitmap2.save(bitmap, file, format);}catch (Exception e){Tools.Log("Bitmap写入文件出错(" + fileName + ") " + e.toString());}}/** 保存bitmap到file中,按格式format进行压缩 */public static void save(Bitmap bitmap, File file, CompressFormat format) // CompressFormat.PNG{try{// 将bitmap,压缩到字节输出流ByteArrayOutputStream stream = new ByteArrayOutputStream();bitmap.compress(format, format == CompressFormat.JPEG ? 100 : 1, stream); // jpg图像最高质量存储,png图像最低质量存储// 从文件输出流,写入文件FileOutputStream fout = new FileOutputStream(file);fout.write(stream.toByteArray());fout.flush();fout.close();}catch (Exception e){Tools.Log("保存bitmap到file中出错" + e.toString());}}/** Bitmap向Pixmap的转化 */public static Pixmap ToPixmap(Bitmap bitmap){if (bitmap == null) return null;// 从Bitmap创建输出流int size = bitmap.getWidth() * bitmap.getHeight();ByteArrayOutputStream outStream = new ByteArrayOutputStream(size);bitmap.compress(Bitmap.CompressFormat.PNG, 0, outStream);// 从输出流创建Pixmapbyte[] img = outStream.toByteArray();return new Pixmap(img, 0, img.length);}
}

Pixmap2.java

package com.hlge.lib.base;import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;import android.graphics.Bitmap;
import android.os.Environment;import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.PixmapIO;
import com.hlge.lib.tool.LocalDB;
import com.hlge.lib.tool.Tools;/** Pixmap2,对Pixmap进行相关图像处理、转化Pixmap的尺寸为2的幂, 内部功能实现基于Bitmap2 ----- 2015-5-21 下午2:06:43 wangzhongyuan */
public class Pixmap2
{/** 临时记录载入图像的尺寸 */static int sizex, sizey;/** 临时记录用于存储的Bitmap */static Bitmap tmpSaveBitmap = null;// -------------------------------------------------------------------------------------------------/** 载入路径下path所有图像资源, path = "texture/" */public static void loadPixmapAll(String path){// 判定是否已对所有图像资源进行了缓存载入String value = LocalDB.readData("loadPixmapAll");if (value.equals("2")) return;LocalDB.saveData("loadPixmapAll", "2");// FileHandle handle = new FileHandle(getPath() + path);// if(handle.exists()) return;// 获取路径下所有文件FileHandle dir = Gdx.files.internal(path);if (!dir.exists() || !dir.isDirectory()) return;// 提取文件名ArrayList<String> pathNames = new ArrayList<String>();FileHandle[] files = dir.list();String tmp;       // 获取文件名,不含路径for (FileHandle file : files){tmp = path.equals("") ? file.path() : file.path().substring(path.length());pathNames.add(tmp);}try{String name, name2;while (pathNames.size() > 0){name = pathNames.remove(0);boolean b_1 = name.endsWith("_1.jpeg"), b_2 = name.endsWith("_2.jpeg");if (b_1 || b_2) // 为蒙板导出的图像 "_1.jpeg", "_2.jpeg"合并为一个文件{name2 = b_1 ? name.replace("_1.jpeg", "_2.jpeg") : name.replace("_2.jpeg", "_1.jpeg");if (pathNames.contains(name2)){pathNames.remove(name2);name = name.substring(0, name.lastIndexOf("_"));}elsename = name.substring(0, name.lastIndexOf("."));}else if (name.contains(".")) name = name.substring(0, name.lastIndexOf("."));Pixmap pic = getPixmapExt(path, name); // 从工程资源目录下载入所有资源,生成资源缓存文件pic.dispose();                         // 释放纹理Tools.Log("缓存文件" + path + name + " 剩余未载入个数:" + pathNames.size());}}catch (Exception ex){Tools.Log("载入路径" + path + "下的图像出错,剩余未载入个数:" + pathNames.size());}}/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */public static Pixmap getPixmapExt(String path, String fileName, String tmpExt){String tmp = Pixmap2.tmpExt;Pixmap2.tmpExt = tmpExt;Pixmap pic = getPixmapExt(path, fileName);Pixmap2.tmpExt = tmp;return pic;}/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic",获取图像后自动缓存至文件 */public static Pixmap getPixmapExt(String path, String fileName){// Pixmap pic = Pixmap2.read(path, fileName); // 优先从本地文件缓存中读取Pixmap pic = Pixmap2.read(path, fileName, Bitmap2.ReadSaveExt);       // 优先从本地文件缓存中读取if (pic != null)return pic;else{pic = getPixmapExtProcess(path, fileName); // 工程内部资源文件生成// Pixmap2.save(path, fileName, pic); // 保存至文件缓存Bitmap2.save(path, fileName, tmpSaveBitmap);// 保存至文件缓存resetSize(pic);tmpSaveBitmap.recycle();  // 释放资源tmpSaveBitmap = null;return pic;}}/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */private static Pixmap getPixmapExtProcess(String path, String fileName){String filePath = path + fileName;    // 工程内部资源路径+文件名(无拓展名)FileHandle handle, handle2;// 从png图像载入handle = Gdx.files.internal(filePath + ".png");if (handle.exists()) return getPixmap(handle);// 从jpg图像载入handle = Gdx.files.internal(filePath + ".jpg");if (handle.exists()) return getPixmap(handle);handle = Gdx.files.internal(filePath + ".jpeg");if (handle.exists()) return getPixmap(handle);// 从pngSplit工具,导出的蒙板图像载入handle = Gdx.files.internal(filePath + "_1.jpeg");handle2 = Gdx.files.internal(filePath + "_2.jpeg");// if (handle.exists() && handle2.exists()) return Combine(getPixmap(handle), getPixmap(handle2));if (handle.exists() && handle2.exists()) return getPixmap(filePath + "_1.jpeg", filePath + "_2.jpeg");Tools.Log(filePath + "Pixmap载入出错!");return null;}/** 设置当前pic的尺寸信息 */private static void resetSize(Pixmap pic){if (Bitmap2.sizex == 0 || Bitmap2.sizey == 0){if (pic == null)sizex = sizey = 0;else{sizex = pic.getWidth();sizey = pic.getHeight();}}else{sizex = Bitmap2.sizex;sizey = Bitmap2.sizey;}}/** 获取工程路径下的图像为Pixmap,如:filePath = "texture/0.png" */public static Pixmap getPixmap(String filePath){FileHandle handle = Gdx.files.internal(filePath);if (handle.exists())            // 从给定的路径载入{// 从缓存读取String path = handle.parent().path() + "/", name = handle.nameWithoutExtension();Pixmap pic = Pixmap2.read(path, name, Bitmap2.ReadSaveExt);// 从文件载入if (pic == null) pic = getPixmap(handle);Bitmap2.save(path, name, tmpSaveBitmap);// 保存至文件缓存resetSize(pic);tmpSaveBitmap.recycle(); // 释放资源tmpSaveBitmap = null;return pic;}else if (filePath.contains("."))// 给定路径文件不存在,尝试其他后缀名载入{// 剔除后缀名int index = filePath.lastIndexOf(".");String name = filePath.substring(0, index);// 分割子路径和文件名index = filePath.lastIndexOf("/");if (index == -1)filePath = "";else{filePath = name.substring(0, index + 1);   // 子路径name = name.substring(index + 1);           // 文件名}return getPixmapExt(filePath, name);}elseTools.Log("从( " + filePath + " )创建Pixmap出错!");return null;}/** 获取handle对应的Pixmap,并转化其尺寸为2的幂 */public static Pixmap getPixmap(FileHandle handle){try{// Pixmap pic = new Pixmap(handle); // 获取对应的图像// pic = Pixmap2.FormatSize(pic); // 图像尺寸转化为2的幂Bitmap tmp = Bitmap2.getBitmap(handle.path());    // 从Bitmap载入图像tmpSaveBitmap = tmp;                         // 记录该Bitmap,待存储Pixmap pic = Bitmap2.ToPixmap(tmp);                // 转化为Pixmapreturn pic;}catch (Exception ex){Tools.Log("从FileHandle=" + handle.toString() + "创建Pixmap出错!");return null;}}// 如工程目录assets/texture/0_1.jpeg下:/** 从pngSplit工具,导出的两张蒙板图像创建,如:filePath1 = "texture/0_1.jpeg"、filePath2 = "texture/0_2.jpeg" */public static Pixmap getPixmap(String filePath1, String filePath2){try{// 从Pixmap载入像素有差异(舍弃)// Pixmap pic1 = new Pixmap(Gdx.files.internal(filePath1));// Pixmap pic2 = new Pixmap(Gdx.files.internal(filePath2));// return Pixmap2.Combine(pic1, pic2);// 以Bitmap方式载入,合成为Pixmap// Bitmap pic1 = Bitmap2.getAssetsBitmap(filePath1);// Bitmap pic2 = Bitmap2.getAssetsBitmap(filePath2);//// return Pixmap2.Combine(pic1, pic2);// 以Bitmap方式载入,转化为PixmapBitmap pic = Bitmap2.getBitmap(filePath1, filePath2);tmpSaveBitmap = pic;     // 记录该Bitmap,待存储return Bitmap2.ToPixmap(pic);}catch (Exception ex){Tools.Log("从蒙板资源创建Pixmap出错!(" + filePath1 + "、" + filePath2 + ")");return null;}}/** 从两张蒙板图像Pic和Mask,合成图像 —— 从Pixmap载入图像,获取的像素值与工具导出像素有差异 */public static Pixmap Combine(Pixmap Pic, Pixmap Mask){// Log.i("Format", Pic.getFormat().name() + " " + Mask.getFormat().name());// Format f1 = Pic.getFormat(), f2 = Mask.getFormat();try{int width = Pic.getWidth(), height = Pic.getHeight();    // 获取图像的尺寸Pixmap2.sizex = width;                                   // 记录图像原尺寸Pixmap2.sizey = height;Pixmap image = new Pixmap(Pixmap2.closestTwoPower(width), Pixmap2.closestTwoPower(height), Format.RGBA8888); // 合成尺寸为2的幂int color1, color2, color, alpha = 0;for (int i = 0; i < width; i++){for (int j = 0; j < height; j++){color1 = Pic.getPixel(i, j); // 原图像像素信息color2 = Mask.getPixel(i, j);    // 原图像透明度信息color1 &= 0xffffff00;           // 获取RGB0alpha = ((color2 & 0x0000ff00) >>> 8);       // 获取Acolor = alpha == 0 ? 0 : (color1 | alpha); // 合成RGBAimage.drawPixel(i, j, color);  // 生成图像}}return image;}catch (Exception ex){Tools.Log("从蒙板合成图像出错!");return null;}}/** 从两张Bitmap蒙板图像Pic和Mask,合成Pixmap */public static Pixmap Combine(Bitmap Pic, Bitmap Mask){try{int width = Pic.getWidth(), height = Pic.getHeight();    // 获取图像的尺寸Pixmap2.sizex = width;                                   // 记录图像原尺寸Pixmap2.sizey = height;int w = Pixmap2.closestTwoPower(width), h = Pixmap2.closestTwoPower(height);Pixmap image = new Pixmap(w, h, Format.RGBA8888);      // 合成尺寸为2的幂int color1, color2, color;for (int i = 0; i < width; i++){for (int j = 0; j < height; j++){color1 = Pic.getPixel(i, j);     // 原图像像素信息, ARGB_8888color2 = Mask.getPixel(i, j);     // 原图像透明度信息, ARGB_8888color = (color1 << 8) | (color2 & 0x000000ff); // 合成像素点, RGBA8888image.drawPixel(i, j, color); // 生成图像}}return image;}catch (Exception ex){Tools.Log("从蒙板合成图像出错!");return null;}}/** 从两张蒙板图像Pic和Mask,合成图像 */public static Pixmap CombineT(Pixmap Pic, Pixmap Mask){// Log.i("Format", Pic.getFormat().name() + " " + Mask.getFormat().name());// Format f1 = Pic.getFormat(), f2 = Mask.getFormat();StringBuffer str1 = new StringBuffer(), str2 = new StringBuffer(), str3 = new StringBuffer();try{int width = Pic.getWidth(), height = Pic.getHeight();    // 获取图像的尺寸Pixmap2.sizex = width;                                   // 记录图像原尺寸Pixmap2.sizey = height;Pixmap image = new Pixmap(Pixmap2.closestTwoPower(width), Pixmap2.closestTwoPower(height), Format.RGBA8888); // 合成尺寸为2的幂int color1, color2, color, alpha = 0;for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){color1 = Pic.getPixel(j, i); // 原图像像素信息color2 = Mask.getPixel(j, i);    // 原图像透明度信息str1.append(Integer.toHexString(color1) + (j < width - 1 ? "," : ""));str2.append(Integer.toHexString(color2) + (j < width - 1 ? "," : ""));color1 &= 0xffffff00;                       // 获取RGB0alpha = ((color2 & 0x0000ff00) >>> 8);       // 获取Acolor = alpha == 0 ? 0 : (color1 | alpha); // 合成RGBAstr3.append(Integer.toHexString(color) + (j < width - 1 ? "," : ""));image.drawPixel(j, i, color); // 生成图像}str1.append(i < height - 1 ? "\r\n" : "");str2.append(i < height - 1 ? "\r\n" : "");str3.append(i < height - 1 ? "\r\n" : "");}FileHandle handle = Gdx.files.internal(getPath() + "color.txt");if (!handle.exists()) handle.file().createNewFile();FileOutputStream fout = new FileOutputStream(new File(getPath(), "color.txt"));PrintStream ps = new PrintStream(fout);ps.println("\r\n\r\n\r\n" + str1.toString());ps.append("\r\n\r\n\r\n" + str2.toString());ps.append("\r\n\r\n\r\n" + str3.toString());ps.close();return image;}catch (Exception ex){Tools.Log("从蒙板合成图像出错!");return null;}}/** 将Pic转化为尺寸为2的幂的图像 */public static Pixmap FormatSize(Pixmap Pic){// Log.i("Format", Pic.getFormat().name());try{int width = Pic.getWidth(), height = Pic.getHeight();    // 获取图像的尺寸Pixmap2.sizex = width;                                   // 记录图像原尺寸Pixmap2.sizey = height;Pixmap image = new Pixmap(Pixmap2.closestTwoPower(width), Pixmap2.closestTwoPower(height), Pic.getFormat());if (image.getWidth() == width && image.getHeight() == height) return Pic; // 若原图像尺寸为2的幂,则直接返回原图像image.drawPixmap(Pic, 0, 0);// int color;// for (int i = 0; i < width; i++)// {// for (int j = 0; j < height; j++)// {// color = Pic.getPixel(i, j); // 原图像像素信息// image.drawPixel(i, j, color); // 生成图像// }// }return image;}catch (Exception ex){Tools.Log("Pixmap尺寸转化为2的幂出错!");return null;}}/** 获取最接近于n的2的幂 */public static int closestTwoPower(int n){int power = 1;while (power < n)power <<= 1;return power;}/** 获取SD卡或内部存储路径,优先选择SD卡 , "/tmp/" */public static String getPath(){if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))return Environment.getExternalStorageDirectory().getPath() + "/tmp/";elsereturn "/tmp/";}/** 图片缓存文件拓展名 */private static String tmpExt = ".byte";/** 保存pixmap到缓存文件fileName, subPath为子文件夹,如:"sub/" */public static void save(String subPath, String fileName, Pixmap pixmap){try{pixmap.setColor(0);FileHandle file = new FileHandle(getPath() + subPath + fileName + tmpExt);if (file.exists()) file.delete();        // 若文件已存在,则删除if (tmpExt.equals(".byte"))PixmapIO.writeCIM(file, pixmap);elsePixmapIO.writePNG(file, pixmap);   // 将pixmap写入文件中缓存}catch (Exception e){Tools.Log("Pixmap写入文件出错(" + fileName + ") " + e.toString());}}/** 从本地缓存文件载入Pixmap, subPath为子文件夹,如:"sub/" */public static Pixmap read(String subPath, String fileName){return read(subPath, fileName, tmpExt);}/** 从本地缓存文件载入Pixmap,拓展名为tmpExt, subPath为子文件夹,如:"sub/" */public static Pixmap read(String subPath, String fileName, String tmpExt){try{FileHandle file = new FileHandle(getPath() + subPath + fileName + tmpExt);if (tmpExt.equals(".byte"))return !file.exists() ? null : PixmapIO.readCIM(file);elsereturn !file.exists() ? null : new Pixmap(file);}catch (Exception e){Tools.Log("Pixmap文件读取出错(" + fileName + tmpExt + ") " + e.toString());return null;}}
}


Tools.java

package com.hlge.lib.tool;import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Random;import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.ScreenUtils;
import com.hlge.lib.HlgeActivity;
import com.hlge.lib.HlgeConfig;
import com.hlge.lib.HlgeHelper;
import com.hlge.lib.HlgeLauncher;/** Tools 工具类,封装一些常用功能函数 ----- 2015-5-16 下午3:55:16 wangzhongyuan */
public class Tools
{// ------------------------------------------------功能函数-----------------------------------------------/** 控制手机震动 */public static void shakePhone(short milliseconds){Gdx.input.vibrate(milliseconds);}/** 打开url地址页 */public static void loadUrl(String url){Intent it = new Intent(Intent.ACTION_VIEW, Uri.parse(url));HlgeActivity.$this.startActivity(it);}/** 将字符串转化为数值,默认值为0 */public static int parseInt(String strNum){int num = 0;try{num = Integer.parseInt(strNum.trim());}catch (Exception ex){};return num;}/** 将字符串转化为数值,默认值为0 */public static float parseFloat(String strNum){float num = 0;try{num = Float.parseFloat(strNum.trim());}catch (Exception ex){};return num;}// --------------------------------------------------随机数、序列数生成、数组排序------------------------------------------------// 随机数发生器public static final Random random = new Random();/** 生成[0, n)范围的随机整数 */public static int random(int n){return random.nextInt(n);}/** 生成[lower, upper]范围的随机整数 */public static int random(int lower, int upper){if (lower > upper)return random(upper, lower);elsereturn random.nextInt(upper - lower + 1) + lower;}/** 序列数生成算法,生成1到n的随机序列数组,每个数值出现且仅出现一次 */public static int[] getSerial(int n){Random Rnd = new Random();int[] tmp = new int[n];int[] num1 = new int[n];for (int i0 = 1; i0 <= n; i0++)num1[i0 - 1] = i0;for (int i = num1.length; i > 0; i--){Rnd.setSeed(Rnd.nextLong());int index = Rnd.nextInt(i);// 随机选中一个数tmp[i - 1] = num1[index];// 剔除选中的数值int[] num2 = new int[i - 1];for (int j = 0; j < i; j++)if (j < index)num2[j] = num1[j];else if (j > index) num2[j - 1] = num1[j];num1 = num2;}return tmp;}/** 数组排序函数 */public static int[] sort(int[] data){int tmp;for (int i = 0; i < data.length - 1; i++){for (int j = i + 1; j < data.length; j++)if (data[i] > data[j]){tmp = data[i];data[i] = data[j];data[j] = tmp;}}return data.clone();}// ------------------------------------------------区域颜色填充-----------------------------------------------/** 用颜色color填充整个界面,Rect为坐标为左下坐标系 */public static void filledRect(Color color){filledRect(HlgeLauncher.batch, HlgeLauncher.render, color, null);}/** 在Rect区域用颜色color进行填充,Rect为坐标为左下坐标系 */public static void filledRect(Color color, Rectangle Rect){filledRect(HlgeLauncher.batch, HlgeLauncher.render, color, Rect);}/** 在Rect区域用颜色color进行填充,Rect为坐标为左下坐标系 */public static void filledRect(SpriteBatch batch, Color color, Rectangle Rect){filledRect(batch, HlgeLauncher.render, color, Rect);}/** 在Rect区域用颜色color进行填充,Rect为坐标为左下坐标系 */public static void filledRect(SpriteBatch batch, ShapeRenderer render, Color color, Rectangle Rect){if (Rect == null) Rect = new Rectangle(0, 0, HlgeConfig.CONF_SCREEN_WIDTH, HlgeConfig.CONF_SCREEN_HEIGHT);batch.end();Gdx.gl.glEnable(GL20.GL_BLEND);Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);render.begin(ShapeRenderer.ShapeType.FilledRectangle);render.setColor(color);render.filledRect(Rect.x / HlgeHelper.scalex, Rect.y / HlgeHelper.scaley, Rect.width / HlgeHelper.scalex, Rect.height / HlgeHelper.scaley);render.end();batch.begin();}// ------------------------------------------------半透阴影的绘制-----------------------------------------------/** 绘制半透阴影,不透明度alpha */public static void drawShadow(float alpha){// drawShadow(0, 0, HlgeConfig.CONF_SCREEN_WIDTH, HlgeConfig.CONF_SCREEN_HEIGHT, 0, 0, 0, 0, alpha, 1);filledRect(new Color(0, 0, 0, alpha));}/** 绘制半透阴影, 区域(x,y,w,h)高亮,不透明度alpha */public static void drawShadow(float x, float y, float w, float h, float alpha){drawShadow(0, 0, HlgeConfig.CONF_SCREEN_WIDTH, HlgeConfig.CONF_SCREEN_HEIGHT, x, y, x + w, y + h, alpha, 20);}// 绘制半透阴影,在区域(x1,y1)-(x2,y2)中,除区域范围(x3,y3)-(x4,y4)外绘制阴影,阴影不透明度为alpha,分fade次进行渲染private static void drawShadow(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float alpha, int fade){HlgeLauncher.batch.end();Gdx.gl.glEnable(GL20.GL_BLEND);Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);HlgeLauncher.render.begin(ShapeRenderer.ShapeType.FilledRectangle);if (fade < 1) fade = 1;alpha = alpha / fade;HlgeLauncher.render.setColor(0, 0, 0, alpha);if (x4 == x3 || y4 == y3)drawShadow(HlgeLauncher.render, x1, y1, x2, y2, x3, y3, x4, y4);else{float boder = 15f / fade;fade += 10;while (fade-- > 10){x3 += boder;y3 += boder;x4 -= boder;y4 -= boder;drawShadow(HlgeLauncher.render, x1, y1, x2, y2, x3, y3, x4, y4);}}HlgeLauncher.render.end();HlgeLauncher.batch.begin();}// 绘制半透阴影,在区域(x1,y1)-(x2,y2)中,除区域范围(x3,y3)-(x4,y4)外绘制阴影private static void drawShadow(ShapeRenderer renderer, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4){// 转化为badlogic.gdx坐标系y3 = HlgeConfig.CONF_SCREEN_HEIGHT - y3;y4 = HlgeConfig.CONF_SCREEN_HEIGHT - y4;y1 = HlgeConfig.CONF_SCREEN_HEIGHT - y1;y2 = HlgeConfig.CONF_SCREEN_HEIGHT - y2;// 屏幕尺寸缩放,位置变换x1 /= HlgeHelper.scalex;y1 /= HlgeHelper.scaley;x2 /= HlgeHelper.scalex;y2 /= HlgeHelper.scaley;x3 /= HlgeHelper.scalex;y3 /= HlgeHelper.scaley;x4 /= HlgeHelper.scalex;y4 /= HlgeHelper.scaley;if (x4 == x3 || y4 == y3)renderer.filledRect(x1, y2, x2 - x1, y1 - y2);else{renderer.filledRect(x1, y2, x2 - x1, y4 - y2);renderer.filledRect(x1, y4, x3 - x1, y3 - y4);renderer.filledRect(x4, y4, x2 - x4, y3 - y4);renderer.filledRect(x1, y3, x2 - x1, y1 - y3);}}// --------------------------------------------------文件数据读取,保存------------------------------------------------/** 从输入流读取数据 */public static String ReadString(DataInputStream dis){try{ArrayList<Byte> stringByte = new ArrayList<Byte>();while (true){byte data;data = dis.readByte();if (data != 0)stringByte.add(data);elsebreak;}byte datas[] = new byte[stringByte.size()];for (int i = 0; i < datas.length; i++)datas[i] = stringByte.get(i);return new String(datas, "GBK");}catch (IOException e){e.printStackTrace();}return null;}/** 从字节数组的offset处开始读取len个字节,形成一个int返回 */public static final int readFromByteArray(byte[] data, int offset, int length){int param = 0;int mbit = 0;for (int i = length - 1; i >= 0; i--){mbit = (length - i - 1) << 3;param |= ((data[offset + i] << mbit) & (0xff << mbit));}switch (length){case 1:param = (byte) param;break;case 2:param = (short) param;break;case 4:param = (int) param;break;}return param;}/** 读取乐堂工具导出资源file,读取类型mode */public static String getTextFile(String file, byte mode){InputStream is = read(file, mode).read();byte[] buffer;try{buffer = new byte[is.available()];is.read(buffer);return new String(buffer);}catch (IOException e){e.printStackTrace();}return "";}/** 文件类型 */public static final byte FILE_TYPE_ACTOR = 1, FILE_TYPE_RAW = 2, FILE_TYPE_MAP = 3, FILE_TYPE_SCENE = 4, FILE_TYPE_XML = 5, FILE_TYPE_FONT = 6,FILE_TYPE_PIC = 7, FILE_TYPE_SOUND = 8, FILE_TYPE_CG = 9, FILE_TYPE_QUESTVAR = 10, FILE_TYPE_SCRIPT = 11, FILE_TYPE_ABSOLUTE = 12;/** 乐堂工具导出资源的路径读取 */public static FileHandle read(String filename, byte mode){switch (mode){case FILE_TYPE_ACTOR:FileHandle fh = Gdx.files.internal("actor/" + filename);return fh.exists() ? fh : Gdx.files.internal("actor/" + LangManager.lang() + "/" + filename);case FILE_TYPE_QUESTVAR:return Gdx.files.internal("scene/" + filename);case FILE_TYPE_MAP:return Gdx.files.internal("map/" + filename);case FILE_TYPE_RAW:return Gdx.files.internal("raw/" + filename);case FILE_TYPE_SCENE:return Gdx.files.internal("scene/" + filename);case FILE_TYPE_XML:return Gdx.files.internal("xml/" + filename);case FILE_TYPE_FONT:return Gdx.files.internal("font/" + filename);case FILE_TYPE_PIC:return Gdx.files.internal("texture/" + filename);case FILE_TYPE_SOUND:return Gdx.files.internal("snd/" + filename);case FILE_TYPE_CG:return Gdx.files.internal("cg/" + filename);case FILE_TYPE_SCRIPT:return Gdx.files.internal("scene/sd/" + filename);case FILE_TYPE_ABSOLUTE:return new FileHandle(new File(filename));default:throw new RuntimeException("文件类型有误,位置read()");}}/** 获取当前屏幕截图 */public static Bitmap captureScreen(int x, int y, int w, int h, boolean flipy){byte[] arr = ScreenUtils.getFrameBufferPixels(x, y, w, h, flipy);int[] bitArr = new int[w * h];for (int i = 0; i < arr.length; i += 4){bitArr[i / 4] = (int) (((arr[i + 3] & 0xFF) << 24) | ((arr[i] & 0xFF) << 16) | ((arr[i + 1] & 0xFF) << 8) | (arr[i + 2] & 0xFF));}return Bitmap.createBitmap(bitArr, w, h, Bitmap.Config.ARGB_8888);}/** 保存图片filename到路径savePath */public static void saveImage(Bitmap bitmap, String savePath, String filename){if (getSDCardPath() != null) savePath += getSDCardPath();try{File path = new File(savePath);String filePath = savePath + "/" + filename;File file = new File(filePath);if (!path.exists()) path.mkdirs();if (!file.exists()) file.createNewFile();FileOutputStream fos = null;fos = new FileOutputStream(file);if (null != fos){if (filename.endsWith(".png"))bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);else{Log.e("Utils.saveImage()", "filename must be end with .png!!!");fos.close();}fos.flush();fos.close();Log.v("tag", filename + "save to" + savePath + "successful!");}}catch (Exception e){e.printStackTrace();}}/** 获取SDCard的路径 */private static String getSDCardPath(){File sdcardDir = null;boolean sdcardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);if (sdcardExist) sdcardDir = Environment.getExternalStorageDirectory(); // 判断SDCard是否存在return sdcardDir.toString();}/** 获取SD卡或内部存储路径,优先选择SD卡 , "/tmp/" */public static String getTmpPath(){if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))return Environment.getExternalStorageDirectory().getPath() + "/tmp/";elsereturn "/tmp/";}/** 将数据data保存至文件file中, Dir = "texture/", fileName = "color.txt" */public static void WriteStringToFile(String data){WriteStringToFile(data, getTmpPath(), "tmp.txt");}/** 将数据data保存至文件file中, Dir = "texture/", fileName = "color.txt" */public static void WriteStringToFile(String data, String Dir, String fileName){try{// 确保文件路径 Dir + fileName 存在,不存在则创建File dir = new File(Dir);if (!dir.exists()) dir.mkdirs();File file = new File((Dir.endsWith("/") ? Dir : Dir + "/") + fileName);if (!file.exists()) file.createNewFile();// 将字符串data写入文件FileOutputStream fout = new FileOutputStream(file);PrintStream ps = new PrintStream(fout);ps.println(data);ps.close();}catch (Exception e){Tools.Log("字符串写入文件出错!");}}// --------------------------------------------------坐标变换、点、矩形碰撞检测------------------------------------------------/** 坐标系变换:左上、左下坐标系,y坐标变换 */public static float coordinateTrans(float y, float height){return HlgeConfig.CONF_SCREEN_HEIGHT - y - height;}/** 二维坐标转化为一维坐标 */public static int point2indexInArray(int i, int j, int columns){i = i * columns + j;return i < 0 ? 0 : i;}/** 点与矩形碰状,判断点(x,y)是否在矩形区域内 */public static boolean isPointInRect(float x, float y, Rectangle Rect){if (Rect == null) return false;return Tools.isPointInRect(x, y, Rect.x, Rect.y, Rect.x + Rect.width, Rect.y + Rect.height);}/** 点与矩形碰状,判断点(x,y)是否在矩形区域内 */public static boolean isPointInRect(float x, float y, float x1, float y1, float x2, float y2){if (x2 > x1){if (x > x2 || x < x1) return false;}else{if (x < x2 || x > x1) return false;}if (y2 > y1){if (y > y2 || y < y1) return false;}else{if (y < y2 || y > y1) return false;}return true;}/** 判断点(x,y)是否在矩形rect 范围内 */public static boolean isPointInRect(int X, int Y, short[] rect){int w = rect[2];int h = rect[3];if ((w | h) < 0) return false;int x = rect[0];int y = rect[1];if (X < x || Y < y) return false;w += x;h += y;return ((w < x || w > X) && (h < y || h > Y));}/** 2个矩形是否相交 */public static boolean isRectIntersect(int[] rect0, int[] rect1){if (rect0 == null || rect1 == null) return false;return !(rect0[0] > rect1[2] || rect1[0] > rect0[2] || rect0[1] > rect1[3] || rect1[1] > rect0[3]);}/** 2个矩形是否相交 */public static boolean isRectIntersect(short[] rect0, short[] rect1){if (rect0 == null || rect1 == null) return false;return !(rect0[0] > rect1[2] || rect1[0] > rect0[2] || rect0[1] > rect1[3] || rect1[1] > rect0[3]);}/** 左下原点坐标系中,获取坐标(x, y)逆时针针旋转degree角度后的坐标 */public static float[] rotate(float x, float y, float scalex, float scaley, float degree){// 尺寸变化后的相对坐标x *= scalex;y *= scaley;// 逆时针旋转degree角度后的相对坐标degree %= 360;if ((x != 0 || y != 0) && degree != 0){float x2 = x, y2 = y;double degree2 = -Math.PI * degree / 180;x2 = (float) (x * Math.cos(degree2) + y * Math.sin(degree2));y2 = (float) (y * Math.cos(degree2) - x * Math.sin(degree2));return new float[] { x2, y2 };}elsereturn new float[] { x, y };// Log.e(degree + "度,坐标值:", ""+ x + "," + y);}// -------------------------------------------------完整调用树、异常代码位置信息输出------------------------------------------------/** 在LogCat中输出提示信息info,并给出输出该信息在代码中的完整调用树 */public static void StackTrace(String info){StackTraceElement[] elem = Thread.currentThread().getStackTrace();   // 从当前位置,获取代码调用堆栈for (StackTraceElement e : elem){String str = info + " 位置:" + e.getClassName() + " -> " + e.getMethodName() + "() 行:" + e.getLineNumber();Gdx.app.error(e.getFileName(), str);                                // 输出调用位置信息和提示信息// Log.e(info, str);// System.out.println(info + "  " + str);}}// 当try块出错时,给出当前代码位置的,出错提示信息// try{}catch(Exception e){ Tools.Log("释放资源出错!"); }/** 在LogCat中输出提示信息info,并给出输出该信息在代码中的调用位置 */public static void Log(String info){StackTraceElement[] elem = Thread.currentThread().getStackTrace(); // 从当前位置,获取代码的堆栈追踪信息StackTraceElement e = elem[3];                                      // 仅获取调用该函数的代码位置,不获取完整调用树String str = info + " 位置:" + e.getClassName() + " -> " + e.getMethodName() + "() 行:" + e.getLineNumber();Gdx.app.error(e.getFileName(), str);                             // 输出调用位置信息和提示信息// Log.e(info, str);// System.out.println(info + "  " + str);}/** 在LogCat中输出提示信息info,并给出输出该信息在代码中的调用位置 */public static String getClassName(){StackTraceElement[] elem = Thread.currentThread().getStackTrace();    // 从当前位置,获取代码的堆栈追踪信息StackTraceElement e = elem[3];                                      // 仅获取调用该函数的代码位置,不获取完整调用树String str = e.getClassName();Gdx.app.error(e.getFileName(), str);                             // 输出调用位置信息和提示信息return str;// Log.e(info, str);// System.out.println(info + "  " + str);}// -------------------------------------------------------------------------------------------------/** 获取对象e所在类名 */public static void getClassName(Object e){Log.i("类名:", e.getClass().toString());// int i = 0;// Log.i("类型:", ((Object)i).getClass().toString()); ;// Log.i("类型:", e.getClass().getDeclaredFields()[0].getName());}public static void setAllComponentsName(Object e){// 获取f对象对应类中的所有属性域Field[] fields = e.getClass().getDeclaredFields();for (int i = 0, len = fields.length; i < len; i++){// 对于每个属性,获取属性名String varName = fields[i].getName();try{// 获取原来的访问控制权限boolean accessFlag = fields[i].isAccessible();// 修改访问控制权限fields[i].setAccessible(true);// 获取在对象f中属性fields[i]对应的对象中的变量 .get(e)Object o = fields[i].get(e);System.out.println("传入的对象中包含一个如下的变量: " + varName + " = " + o);// 恢复访问控制权限fields[i].setAccessible(accessFlag);}catch (Exception ex){ex.printStackTrace();}}}
}



游戏开发中,图片资源的精简相关推荐

  1. 游戏开发中的数学、向量的应用

    点 数学中的坐标系统(笛卡尔坐标系统) 这里A(0,0), B(1,2), C(4,3), D(–1,2), E(–2,–1), F(3,–2). 计算机中的坐标系统(屏幕坐标系统) 注意这里的y轴在 ...

  2. 一些语法在游戏开发中的应用

    一些语法在游戏开发中的应用 一.减少不必要的全局变量 二.动态二维数组 三.整数转换为字符串输出 四.播放音乐模板 一.减少不必要的全局变量 游戏开发中有些变量只需要在少数函数中传递,修改数值.如果不 ...

  3. J2ME游戏开发中时钟的简单实现

    在java.util包中有一个TimerTask类,你可以扩展这个类并且实现他的run()方法,在run()方法中编写我们的逻辑代码.如果我们想制作一个游戏时钟,那么非常简单我们编写一个GameClo ...

  4. Java ME游戏开发中,碰撞检测算法在Java?ME中的实现(

    2019独角兽企业重金招聘Python工程师标准>>> 在Java ME游戏开发中,碰撞检测算法在Java?ME中的实现(百搜技术) 在Java ME游戏开发中,经常需要进行碰撞检测 ...

  5. 机器学习将在游戏开发中的6种应用

    机器学习正在改变几乎每个行业,从农业中的作物规划到医疗保健中的癌症诊断.这些主题通常会得到更广泛的讨论,因为它们已经产生了切实的,对人类有益的影响.对于游戏行业而言,不幸的是,游戏开发中的机器学习仍处 ...

  6. Android游戏开发中绘制游戏触摸轨迹的曲线图

    本篇文章主要来讲解怎样绘制游戏触摸轨迹的曲线图. 我们在onTouchEvent方法中,可以获取到触摸屏幕时手指触摸点的x.y坐标,如何用这些点形成一条无规则轨迹并把这条无规则轨迹曲线显示在屏幕上就是 ...

  7. [C++基金会]位计算 游戏开发中的应用

    定义的位操作:通俗点说,,位计算是计算机操作二进制整数. 无论整数可以用二的方式来表示进度,不同类型的其长度的整数位的是不一样的.INT8要么char靠8个月2 位表示,INT16或者short是由1 ...

  8. 游戏开发中的数据表示

    声明:本文内容源自腾讯游戏学院程序公开课_服务端 一.数据表示的基础 什么是数据表示? 数据是信息的载体. 数据表示是一组操作,可以描述.显示.操作信息. 数据表示的要素 IDL - 接口描述语言 I ...

  9. 手把手教你架构3d游戏引擎pdf_游戏开发中的算法

    游戏技术这条路,可深可浅.你可以满足于完成GamePlay玩法层面的东西,你也可以满足于架构和框架设计层面的东西,你也可以醉心于了解某一游戏引擎带来的掌控感.但是,我们不该止步于此,止步与目前所见或所 ...

最新文章

  1. 二.Springboot 常用注解
  2. 一文看懂5G和AI融合的5个要点
  3. 人类、动物和人工智能意识的新理论
  4. 计算机表格最高分,excel表格里怎样算最高分 excel各个班的最高分
  5. Spanning-tree Potocol(整理)
  6. UIScrollview 技巧
  7. 为什么不能用速度与时间的关系去实现动画
  8. OpenShift 4 - 应急响应Demo应用(AMQ+Knative+Quay+BPM+BDM+SSO)
  9. 华硕固件,梅林固件,高恪固件等等有什么区别?
  10. 解决VMWare虚拟机IP变成127.0.0.1和选择固定IP段
  11. BIO、NIO、AIO差别
  12. SVN客户端安装与使用
  13. 开源OA协同办公平台搭建教程丨模糊人员匹配功能配置说明
  14. win10任务栏太宽而且调不了_win10系统任务栏变宽了的修复方法
  15. 【洋桃电子】STM32入门100步-01
  16. 语音合成 TTS 相关的一些总结
  17. 微信app支付php案例分析,PHP实现APP微信支付的实例讲解
  18. Windows-Exploit-Suggester
  19. 程序员薪资:2022年腾讯校招薪资接近40W?我惊呆了
  20. MFC 预处理器相关知识

热门文章

  1. # MAC备份/导出IDEA配置
  2. 应用8255A控制LED小灯开闭(附代码注释)
  3. Android展示PDF文件(文字,签章,签名)
  4. 读书笔记 - 《史蒂夫·乔布斯传》
  5. Postman中认证CAS
  6. 通过PC获取Tello无人机视频图像和发送控制命令
  7. replication factor: 3 larger than available brokers: 1
  8. 研究生英语期末考试复习
  9. Altera FPGA程序固化(软件+硬件)
  10. 『 论文阅读』LightGBM原理-LightGBM: A Highly Efficient Gradient Boosting Decision Tree