游戏开发中,图片资源的精简
2015-05-19 17:48
260 查看
蒙板压缩对比图:(此方法可大幅减小游戏包的大小)
包大小对比:
在游戏开发中,包的大小总是与图片资源的大小密切相关,而图片资源中,大多为带有透明度信息的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和CombineList groupPicByName("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); // 转化为Pixmap tmp.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/"; else return "/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); // 创建Bitmap if (file.exists()) return BitmapFactory.decodeFile(path + name); else return 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; // 图像为null if (SaveTmpFile) SaveTmpFile = false; // 可保存当前图像至缓存 else return; 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); // 从输出流创建Pixmap byte[] 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("_")); } else name = 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); } else Tools.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); // 转化为Pixmap return 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方式载入,转化为Pixmap Bitmap 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; // 获取RGB0 alpha = ((color2 & 0x0000ff00) >>> 8); // 获取A color = alpha == 0 ? 0 : (color1 | alpha); // 合成RGBA image.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_8888 color2 = Mask.getPixel(i, j); // 原图像透明度信息, ARGB_8888 color = (color1 << 8) | (color2 & 0x000000ff); // 合成像素点, RGBA8888 image.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; // 获取RGB0 alpha = ((color2 & 0x0000ff00) >>> 8); // 获取A color = alpha == 0 ? 0 : (color1 | alpha); // 合成RGBA str3.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/"; else return "/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); else PixmapIO.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); else return !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); else return random.nextInt(upper - lower + 1) + lower; } /** 序列数生成算法,生成1到n的随机序列数组,每个数值出现且仅出现一次 */ public static int[] getSerial(int n) { Random Rnd = new Random(); int[] tmp = new int ; int[] num1 = new int ; 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); else break; } 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/"; else return "/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 }; } else return 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(); } } } }
相关文章推荐
- android游戏开发的框架设计!(已更新资源图片)
- 程序员开发游戏使用的背景图片素材资源合辑
- 一、创建Assetbundle 在unity3d开发的游戏中,无论模型,音频,还是图片等,我们都做成Prefab,然后打包成Assetbundle,方便我们后面的使用,来达到资源的更新。
- android游戏开发初学之SurfaceView绘制图片
- 在Android开发中替换资源图片不起作用的解决方法
- 游戏开发资源收集
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- Diyal Cocos2d-x 游戏开发系列 从一个图片灰态需求开始
- HTML5游戏开发必备资源
- Windows8 游戏开发教程-二、关于资源和工具(转)
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- 【iOS-Cocos2d游戏开发之八】开启高清(960*640)模式问题与解答、图片适配以及设置iphone横竖屏 推荐
- Android开发用到的图片图表资源
- Unity3D之如何将包大小减少到极致 发表于2014年6月6日由陆泽西 Unity3D之如何将包大小减少到极致,图片是游戏app里最最占空间的资源,所以请各位还没有理解u3d对图片文件存储方式理解
- 《游戏脚本的设计与开发》-1.4 图片的读取显示
- 关于开发兼容android 1.5项目时找不到资源图片问题
- VC++游戏开发1------利用图片拼接实现内存中构建游戏地图,许多游戏编辑器的原理。
- 【COCOS2DX-LUA 脚本开发之十二】Hybrid模式-利用AssetsManager实现在线更新脚本文件lua、js、图片等资源(免去平台审核周期)
- 【图片处理工具】Android游戏开发的好帮手
- 【Unity3D游戏开发】性能优化之Texture图片空间和内存占用分析(三七)