This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mdes.j4k.tools; | |
import java.awt.Toolkit; | |
import java.awt.datatransfer.Clipboard; | |
import java.awt.datatransfer.StringSelection; | |
public class ArrayTranslate { | |
/** Max number of entities */ | |
public static final int COUNT = 10; | |
//Our Entity class | |
enum Entity { | |
ACTIVE, //whether our entity is active, TRUE or FALSE | |
TYPE, //type of entity | |
X, Y, //position | |
VX, VY, //velocity | |
HEALTH, //health | |
MAX_HEALTH, //maximum health | |
} | |
// some custom parameters | |
//false = 0, true = 1 | |
enum Bool { | |
FALSE, | |
TRUE; | |
} | |
//Entity type constants | |
enum Entity_types { | |
PLAYER, | |
SKELETON, | |
GOBLIN | |
} | |
public static void main(String[] args) { | |
parse(Entity.values(), "ENTITIES", float.class, | |
//other types | |
Entity_types.values(), | |
Bool.values()); | |
} | |
public static void parse(Enum<?>[] entities, String arrayName, Class<?> dataType, Enum<?>[] ... constants) { | |
String prefix = entities[0].getClass().getSimpleName().toUpperCase() + "_"; | |
String dataTypeStr = dataType.getSimpleName(); | |
String vis = "public final static int "; | |
for (Enum<?>[] en : constants) { | |
System.out.println("//"+en[0].getClass().getSimpleName().replace('_',' ')); | |
for (Enum<?> e : en) { | |
System.out.println("public final static "+dataTypeStr+" "+e.name()+" = "+e.ordinal()+";"); | |
} | |
System.out.println(); | |
} | |
int entitySize = entities.length; | |
String strideStr = prefix + "STRIDE"; | |
String countStr = prefix + "COUNT"; | |
String arrayLenStr = prefix + "ARRAY_LENGTH"; | |
System.out.println("//number of " + dataTypeStr + " elements for one entity"); | |
System.out.println(vis + strideStr + " = " + entitySize + ";"); | |
System.out.println("//total number of entities"); | |
System.out.println(vis + countStr + " = " + COUNT + ";"); | |
System.out.println("//array length"); | |
System.out.println(vis + arrayLenStr + " = " + strideStr +" * "+countStr+";"); | |
System.out.println(); | |
System.out.println("//Entity properties"); | |
for (int i = 0; i < entities.length; i++) { | |
Enum<?> e = entities[i]; | |
if (e.name().equals("STRIDE") || e.name().equals("COUNT") || e.name().equals("ARRAY_LENGTH")) | |
throw new IllegalArgumentException(e.name()+" is a reserved keyword"); | |
System.out.print(vis); | |
String name = e.name(); | |
if(!e.name().startsWith("$")) { | |
System.out.print(prefix); | |
} else | |
name = e.name().substring(1); | |
System.out.println(name + " = " + i+";"); | |
} | |
System.out.println(); | |
System.out.println("//Entity data"); | |
System.out.println("public final static " + dataTypeStr + "[] " + arrayName + " = new " | |
+ dataTypeStr + "[" + countStr + " * " + strideStr + "];"); | |
System.out.println("\n//example of looping through each entity"); | |
System.out.println("for (int i=0; i<"+arrayLenStr+"; i+="+strideStr+") {"); | |
System.out.println("\tint index = i/"+strideStr+";"); | |
System.out.println("\t//do something..."); | |
System.out.println("}"); | |
} | |
static void setClipboard(String contents) { | |
Toolkit toolkit = Toolkit.getDefaultToolkit(); | |
Clipboard clipboard = toolkit.getSystemClipboard(); | |
StringSelection strSel = new StringSelection(contents); | |
clipboard.setContents(strSel, null); | |
} | |
/* | |
* { | |
* | |
* { r, g, b, a nx, ny, nz } | |
*/ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mdes.j4k.tools; | |
import java.awt.Color; | |
import java.awt.Dimension; | |
import java.awt.Graphics; | |
import java.awt.image.BufferedImage; | |
import java.awt.image.DataBufferByte; | |
import java.io.BufferedReader; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.lang.reflect.Field; | |
import java.net.URISyntaxException; | |
import java.net.URL; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import javax.imageio.ImageIO; | |
import javax.xml.bind.DatatypeConverter; | |
/** | |
* Go wild. | |
* @author davedes | |
*/ | |
public class ImageTool { | |
//////////////// COMMON PARAMETERS | |
/** If false, then BufferedImage will be ignored and only the raw pixels will be used. */ | |
public static boolean useBufferedImage = true; | |
/** The format to encode with ImageIO when useBufferedImage is true; default "PNG" */ | |
public static String encodeFormat = "PNG"; | |
//////////////// OTHER PARAMETERS | |
//does not apply to GIF encoding | |
//-1 or NO_MAX will fit all characters into a single line | |
public static final int NO_MAX = -1; | |
/** maximum number of chars to include on a single line for simple encoding */ | |
static int maxStringWidth = NO_MAX; | |
//This is project-specific; the output is useful if you want to add normal mapping | |
static boolean useFloatWithNormals = false; | |
public static void main(String[] args) throws IOException { | |
//////////////// USAGE | |
// PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream("out.txt"))); | |
// System.setOut(out); | |
// create(dir("/res/pirates")); | |
create(dir("/res/pirates")); | |
// out.close(); | |
// BufferedImage[] imgs = parseBMFont(getResource("res/p.fnt").openStream(), getResource("res/pixel_00.png"), new Dimension(5, 5)); | |
// create(imgs); | |
//writeFrames("imgs", "char_", 32, "png", imgs); | |
} | |
///////////////////////////////////////////////////////// | |
// MESSY INTERNAL CODE BELOW ... VIEW AT YOUR OWN RISK // | |
///////////////////////////////////////////////////////// | |
//TODO: support multiple color formats.. not there yet | |
static enum Format { | |
TYPE_INT_ARGB("int", 1), | |
TYPE_INT_RGBA("int", 1), | |
TYPE_INT_RGB("int", 1), | |
TYPE_3BYTE_RGB("byte", 3), | |
TYPE_4BYTE_RGBA("byte", 4); | |
public final String type; | |
public final int numComponents; | |
Format(String type, int numComponents) { | |
this.type = type; | |
this.numComponents = numComponents; | |
} | |
} | |
static Format format = Format.TYPE_INT_ARGB; | |
public static final Color TRANSPARENT = new Color(0,0,0,0); | |
static String[] dir(String p) { | |
URL path = ImageTool.class.getResource(p); | |
File f = null; | |
try { | |
f = new File(path.toURI()); | |
} catch (URISyntaxException e) { | |
// TODO Auto-generated catch block | |
e.printStackTrace(); | |
} | |
File[] files = f.listFiles(); | |
List<String> out = new ArrayList<String>(files.length); | |
for (int i=0; i<files.length; i++) { | |
String o = files[i].getPath(); | |
if (o.toLowerCase().endsWith(".bmp") | |
|| o.toLowerCase().endsWith(".gif") | |
|| o.toLowerCase().endsWith(".jpg") | |
|| o.toLowerCase().endsWith(".jpeg") | |
|| o.toLowerCase().endsWith(".png") | |
|| o.toLowerCase().endsWith(".tga")) | |
out.add(o); | |
} | |
return out.toArray(new String[out.size()]); | |
} | |
static HashMap<Color, String> colorNames = new HashMap<Color, String>(); | |
static { | |
try { | |
Field[] fields = Color.class.getFields(); | |
for (Field f : fields) { | |
if (!Character.isUpperCase(f.getName().charAt(0)) && f.getDeclaringClass().equals(Color.class.getClass())) { | |
try { | |
Color c = (Color)f.get(null); | |
if (c!=null) { | |
int rgb = ((int)(c.getRed()) << 16) | ((int)(c.getGreen()) << 8) | (int)(c.getBlue()); | |
colorNames.put(c, "0x"+Integer.toHexString(rgb)+" - "+f.getName()); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
colorNames.put(TRANSPARENT, "transparent"); | |
} | |
static String nameOfColor(Color c, boolean hex) { | |
String sc = colorNames.get(c); | |
if (sc!=null) | |
return sc; | |
else { | |
if (hex) { | |
int rgb = ((int)(c.getRed()) << 16) | ((int)(c.getGreen()) << 8) | (int)(c.getBlue()); | |
return "0x"+Integer.toHexString(rgb); | |
} else { | |
return "R="+c.getRed()+", G="+c.getGreen()+", B="+c.getBlue()+", A="+c.getAlpha(); | |
} | |
} | |
} | |
static String parse(String line, String tag) { | |
tag += "="; | |
int start = line.indexOf(tag); | |
if (start==-1) | |
return null; | |
int end = line.indexOf(' ', start+tag.length()); | |
if (end==-1) | |
end = line.length(); | |
return line.substring(start+tag.length(), end); | |
} | |
public static void writeFrames(String folder, String namePrefix, int prefixOff, String fmt, BufferedImage ... frames) throws IOException { | |
File dir = new File(folder); | |
if (!dir.exists()) | |
dir.mkdir(); | |
for (int i=0; i<frames.length; i++) { | |
File f = new File(folder+File.separator+namePrefix+(prefixOff+i)+"."+fmt); | |
if (!f.exists()) | |
f.createNewFile(); | |
ImageIO.write(frames[i], fmt, f); | |
} | |
} | |
public static BufferedImage[] parseBMFont(InputStream bmFont, URL fontImage) throws IOException { | |
return parseBMFont(bmFont, fontImage, null); | |
} | |
public static BufferedImage[] parseBMFont(InputStream bmFont, URL fontImage, Dimension packSize) throws IOException { | |
if (bmFont==null || fontImage==null) | |
throw new IllegalArgumentException("font/image files were not found"); | |
BufferedImage[] imgs = new BufferedImage[95]; //standard ASCII characters | |
BufferedImage sheet = ImageIO.read(fontImage); | |
BufferedReader br = new BufferedReader(new InputStreamReader(bmFont)); | |
br.readLine(); //skip first | |
br.readLine(); //skip second | |
br.readLine(); //skip third | |
br.readLine(); //skip fourth | |
String line = ""; | |
while ((line = br.readLine()) != null) { | |
if (line.startsWith("kernings")) | |
break; | |
try { | |
int id = Integer.parseInt(parse(line, "id")); | |
int x = Integer.parseInt(parse(line, "x")); | |
int y = Integer.parseInt(parse(line, "y")); | |
int width = Integer.parseInt(parse(line, "width")); | |
int height = Integer.parseInt(parse(line, "height")); | |
int xoffset = Integer.parseInt(parse(line, "xoffset")); | |
int yoffset = Integer.parseInt(parse(line, "yoffset")); | |
BufferedImage img = sheet.getSubimage(x, y, width, height); | |
if (packSize!=null) { | |
BufferedImage buf = new BufferedImage(packSize.width, packSize.height, BufferedImage.TYPE_4BYTE_ABGR); | |
buf.getGraphics().drawImage(img, 0, 0, null); | |
img = buf; | |
} | |
imgs[id-32] = img; | |
// System.out.println(((char)id)+" x="+id+" y="+x+" "+y+" w="+width+" h="+height+" xoff="+xoffset+" yoff="+yoffset); | |
} catch (Exception e) { | |
System.out.println("err on "+line+" "+e.getMessage()); | |
} | |
} | |
return imgs; | |
} | |
public static void create(String ... frames) throws IOException { | |
create(null, 0, frames); | |
} | |
public static void create(BufferedImage ... frames) throws IOException { | |
create(null, 0, frames, null); | |
} | |
public static void create(List<Color> colorTable, int defaultIndex, String ... frames) throws IOException { | |
BufferedImage[] imgs = new BufferedImage[frames.length]; | |
String[] names = new String[frames.length]; | |
for (int i=0; i<imgs.length; i++) { | |
try { | |
imgs[i] = ImageIO.read(ImageTool.class.getResource(frames[i])); | |
} catch (Exception e) { | |
imgs[i] = ImageIO.read(new File(frames[i])); | |
} | |
names[i] = frames[i].toUpperCase(); | |
int start = frames[i].replace('\\','/').lastIndexOf('/'); | |
if (start==-1) | |
start = 0; | |
int end = frames[i].lastIndexOf('.'); | |
if (end==-1) | |
end = frames[i].length(); | |
names[i] = frames[i].substring(start+1, end).toUpperCase(); | |
} | |
create(colorTable, defaultIndex, imgs, names); | |
} | |
static void printBigString(CharSequence str, int blockSize) { | |
String text = str.toString().replace("\\", "\\\\").replace("\"", "\\\""); | |
if (blockSize==-1) { | |
System.out.print("\""+text+"\""); | |
} else { | |
System.out.println("("); | |
for (int i=0; i<text.length(); i+=blockSize) { | |
System.out.print("\t"); | |
boolean appendPlus = false; | |
if (i+blockSize < text.length()) { | |
CharSequence seq = text.subSequence(i, i+blockSize); | |
System.out.print("\""+seq+"\""); | |
appendPlus = true; | |
} else { | |
System.out.print("\""+text.subSequence(i, text.length())+"\""); | |
} | |
if (appendPlus) { | |
System.out.print(" +"); | |
System.out.println(); | |
} else | |
System.out.print(")"); | |
// System.out.println(buf.substring(i, Math.min(buf.length(), i+maxWidth)).toString()) | |
} | |
} | |
} | |
public static void create(List<Color> colorTable, int defaultIndex, BufferedImage[] frames, String[] names) { | |
//TODO: formats not yet supported | |
if (useFloatWithNormals) { | |
format = Format.TYPE_4BYTE_RGBA; | |
useBufferedImage = false; | |
} else { | |
format = Format.TYPE_INT_ARGB; | |
} | |
if (names==null) { | |
names = new String[frames.length]; | |
for (int i=0; i<names.length; i++) { | |
names[i] = "IMG_"+i; | |
} | |
} | |
byte[][] pixels = new byte[frames.length][]; | |
int firstWidth=0,firstHeight=0; | |
int width=0,height=0; | |
for (int i=0; i<frames.length; i++) { | |
BufferedImage img = frames[i]; | |
width = img.getWidth(); | |
height = img.getHeight(); | |
if (i==0) { | |
firstWidth = width; | |
firstHeight = height; | |
} else if (firstWidth!=width || firstHeight!=height) { | |
throw new IllegalArgumentException("frames must be equal size"); | |
} | |
BufferedImage img2 = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); | |
img2.getGraphics().drawImage(img, 0,0,null); | |
img = img2; | |
pixels[i] = ((DataBufferByte)img.getRaster().getDataBuffer()).getData(); | |
} | |
//loop through once and grab colors | |
if (colorTable==null) { | |
colorTable = new ArrayList<Color>(); | |
for (int f=0; f<frames.length; f++) { | |
byte[] px = pixels[f]; | |
for (int i=0; i<px.length; i+=4) { | |
int a = px[i] & 0xFF; | |
int b = px[i+1] & 0xFF; | |
int g = px[i+2] & 0xFF; | |
int r = px[i+3] & 0xFF; | |
Color clr = new Color(r, g, b, a); | |
int index = colorTable.indexOf(clr); | |
if (index==-1) { | |
colorTable.add(clr); | |
index = colorTable.size()-1; | |
} | |
} | |
} | |
//make transparent, white and black the first colors... | |
Color[] reg = new Color[] { Color.white, Color.black, TRANSPARENT }; | |
for (int i=0; i<reg.length; i++) { | |
if (colorTable.contains(reg[i])) { | |
colorTable.remove(reg[i]); | |
colorTable.add(0, reg[i]); | |
} | |
} | |
} | |
int[] indexed = new int[width*height*frames.length]; | |
for (int f=0, off=0; f<frames.length; f++, off+=width*height) { | |
byte[] px = pixels[f]; | |
for (int i=0; i<px.length; i+=4) { | |
int a = px[i] & 0xFF; | |
int b = px[i+1] & 0xFF; | |
int g = px[i+2] & 0xFF; | |
int r = px[i+3] & 0xFF; | |
int index = colorTable.indexOf(new Color(r, g, b, a)); | |
if (index==-1) | |
index = defaultIndex; | |
indexed[off + i/4] = index; | |
} | |
} | |
System.out.println("//"+format.name()+" color table"); | |
System.out.println("public static final "+format.type+"[] TABLE = new "+format.type+"[] {"); | |
for (int i=0; i<colorTable.size(); i++) { | |
Color c = colorTable.get(i); | |
boolean hexInComment = true; | |
if (format.type.equals("int")) { | |
int value = 0x0; | |
if (format==Format.TYPE_INT_ARGB) { | |
value = ((int)(c.getAlpha()) << 24) | ((int)(c.getRed()) << 16) | (int)(c.getGreen() << 8) | c.getBlue(); | |
} else if (format==Format.TYPE_INT_RGBA){ | |
if (useBufferedImage) | |
throw new IllegalStateException("IntRGBA only works if useBufferedImage=false"); | |
value = ((int)(c.getRed()) << 24) | ((int)(c.getGreen()) << 16) | (int)(c.getBlue() << 8) | c.getAlpha(); | |
} else if (format==Format.TYPE_INT_RGB) { | |
value = ((int)(c.getRed()) << 16) | ((int)(c.getGreen()) << 8) | c.getBlue(); | |
} else { | |
throw new IllegalStateException("invalid format "+format.name()); | |
} | |
//print hex | |
String s = "0x"+Integer.toHexString(value); | |
System.out.print("\t"+s); | |
//use ints in comments | |
hexInComment = false; | |
} else { | |
if (format==Format.TYPE_3BYTE_RGB) { | |
System.out.print("\t"+c.getRed()+",\t"+c.getGreen()+",\t"+c.getBlue()); | |
} else if (format==Format.TYPE_4BYTE_RGBA) { | |
System.out.print("\t"+c.getRed()+",\t"+c.getGreen()+",\t"+c.getBlue()+",\t"+c.getAlpha()); | |
} else { | |
throw new IllegalStateException("invaild format "+format.name()); | |
} | |
} | |
if (i!=colorTable.size()-1) | |
System.out.print(","); | |
System.out.println("\t//"+nameOfColor(c, hexInComment)); | |
} | |
System.out.println("};"); | |
System.out.println(); | |
System.out.println("//sprite array properties"); | |
System.out.println("public static final int SPRITE_WIDTH = "+width+";"); | |
System.out.println("public static final int SPRITE_HEIGHT = "+height+";"); | |
System.out.println("public static final int SPRITE_COUNT = "+frames.length+";"); | |
if (useFloatWithNormals) { | |
System.out.println("public static final int SPRITE_SIZE = SPRITE_WIDTH * SPRITE_HEIGHT;"); | |
System.out.println("public static final int SPRITE_COMPONENTS = "+format.numComponents | |
+" * 3; //Diffuse."+format.name()+", Normal.XYZ"); | |
System.out.println("public static final int SPRITE_STRIDE = SPRITE_SIZE * SPRITE_COMPONENTS;"); | |
} else { | |
System.out.println("public static final int SPRITE_STRIDE = SPRITE_WIDTH * SPRITE_HEIGHT;"); | |
} | |
System.out.println("public static final int SPRITE_ARRAY_LEN = SPRITE_STRIDE * SPRITE_COUNT;"); | |
StringBuilder sb = new StringBuilder(); | |
final int CHR_OFFSET = colorTable.size() <= 10 ? 48 : 32; | |
for (int i=0, chrs=0; i<indexed.length; i++, chrs++) { | |
int b = indexed[i]; | |
sb.append((char)(b+CHR_OFFSET)); | |
} | |
if (useFloatWithNormals) | |
System.out.println("public static final int SPRITE_ENCODING_LENGTH = "+sb.length()+";"); | |
System.out.println(); | |
String dataType = useFloatWithNormals ? "float" : "int"; | |
if (!useBufferedImage) { | |
System.out.println("//the sprite image color data"); | |
System.out.println("public static final "+dataType+"[] SPRITES = new "+dataType+"[SPRITE_ARRAY_LEN];"); | |
System.out.println(); | |
} | |
System.out.println("//offsets to different sprite indices"); | |
for (int i=0; i<names.length; i++) { | |
System.out.print("public static final int SPRITE_"+names[i]+" = "); | |
if (useBufferedImage) | |
System.out.println(i+";"); | |
else | |
System.out.println("SPRITE_STRIDE * "+i+";"); | |
} | |
System.out.println(); | |
if (useFloatWithNormals) { | |
System.out.println("//////// Simple Indexed Color Encoding"); | |
System.out.print("for (int i=0; i<SPRITE_ENCODING_LENGTH; i++) {\n" + | |
"\tint c = (int)("); | |
printBigString(sb.toString(), maxStringWidth); | |
System.out.println(".charAt(i)-"+CHR_OFFSET+");\n" + | |
"\t//Diffuse RGBA\n" + | |
"\tSPRITES[i*SPRITE_COMPONENTS] = TABLE[c*"+format.numComponents+"]/255f;\n" + | |
"\tSPRITES[i*SPRITE_COMPONENTS+1] = TABLE[c*"+format.numComponents+"+1]/255f; \n" + | |
"\tSPRITES[i*SPRITE_COMPONENTS+2] = TABLE[c*"+format.numComponents+"+2]/255f;\n" + | |
"\tSPRITES[i*SPRITE_COMPONENTS+3] = TABLE[c*"+format.numComponents+"+3]/255f; \n" + | |
"\t\n" + | |
"\t//The x/y position of the current pixel\n" + | |
"\tint y = i%SPRITE_SIZE / SPRITE_WIDTH;\n" + | |
"\tint x = i%SPRITE_SIZE - SPRITE_WIDTH * y;\n" + | |
"\t\n" + | |
"\t//Normals XYZ\n" + | |
"\tSPRITES[i*SPRITE_COMPONENTS+4] = ((x/(float)SPRITE_WIDTH)*2-1)*0.5f;\n" + | |
"\tSPRITES[i*SPRITE_COMPONENTS+5] = ((y/(float)SPRITE_HEIGHT)*2-1)*0.5f;\n" + | |
"\tSPRITES[i*SPRITE_COMPONENTS+6] = 1f;\n" + | |
"\t\n" + | |
"\t//INCLUDED FOR REFERENCE:\n" + | |
"\t\n" + | |
"\t//The index of the sprite image\n" + | |
"\t//int spriteIndex = i/SPRITE_SIZE;\n" + | |
"\t\n" + | |
"\t//The index of the current pixel for this sprite image\n" + | |
"\t//int pixelIndex = i % SPRITE_SIZE;\n" + | |
"}"); | |
} else if (useBufferedImage) { | |
System.out.println("//////// ENCODING METHOD: Simple Indexed Color Encoding"); | |
System.out.print( | |
"public static final BufferedImage SPRITE_SHEET = new BufferedImage(SPRITE_WIDTH, SPRITE_HEIGHT * SPRITE_COUNT, BufferedImage.TYPE_INT_ARGB);\n" + | |
"public static final int[] SPRITE_PIXELS = ((DataBufferInt)SPRITE_SHEET.getRaster().getDataBuffer()).getData();\n" + | |
"public static final BufferedImage[] SPRITES = new BufferedImage[SPRITE_COUNT];\n\n"+ | |
"for (int i=0; i<SPRITE_ARRAY_LEN; i++) {\n" + | |
"\tSPRITE_PIXELS[i] = TABLE["); | |
printBigString(sb.toString(), maxStringWidth); | |
System.out.println(".charAt(i)-"+CHR_OFFSET+"];"); | |
if (frames.length>1) { | |
System.out.println( | |
"\tif (i%SPRITE_STRIDE == SPRITE_STRIDE-1) {\n" + | |
"\t\tSPRITES[i/(SPRITE_WIDTH*SPRITE_HEIGHT)] = SPRITE_SHEET.getSubimage(\n" + | |
"\t\t\t0, i/(SPRITE_WIDTH*SPRITE_HEIGHT)*SPRITE_HEIGHT, \n" + | |
"\t\t\tSPRITE_WIDTH, SPRITE_HEIGHT);\n" + | |
"\t}"); | |
} | |
System.out.println("}"); | |
} else { | |
System.out.println("//////// ENCODING METHOD: Simple Indexed Color Encoding"); | |
System.out.print("for (int i=0; i<SPRITE_ARRAY_LEN; i++) {\n" + | |
"\tSPRITES[i] = (byte)("); | |
printBigString(sb.toString(), maxStringWidth); | |
System.out.println(".charAt(i)-"+CHR_OFFSET+");\n" + | |
"}"); | |
} | |
System.out.println(); | |
//pack gifs into new | |
if (useBufferedImage) { | |
BufferedImage sheet; | |
if (frames.length==1) | |
sheet = frames[0]; | |
else { //create sprite sheet from frames | |
sheet = new BufferedImage(width, height*frames.length, BufferedImage.TYPE_INT_ARGB); | |
Graphics g = sheet.createGraphics(); | |
for (int i=0; i<frames.length; i++) { | |
g.drawImage(frames[i], 0, i*height, null); | |
} | |
g.dispose(); | |
} | |
System.out.println("//////// ENCODING METHOD: "+encodeFormat+" Encoding"); | |
System.out.println("// You can remove the color table and some of the constants defined earlier"); | |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
try { | |
ImageIO.write(sheet, encodeFormat, baos); | |
} catch (IOException e) { | |
// TODO Auto-generated catch block | |
e.printStackTrace(); | |
} | |
System.out.println("BufferedImage SPRITE_SHEET = null;"); | |
if (frames.length>1) { | |
System.out.println("BufferedImage[] SPRITES = new BufferedImage[SPRITE_COUNT];"); | |
} | |
String str = DatatypeConverter.printBase64Binary(baos.toByteArray()); | |
System.out.println("try {\n" + | |
"\tSPRITE_SHEET = ImageIO.read(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(\n" + | |
"\t\t\""+str+"\"\n" + | |
"\t\t)));"); | |
if (frames.length>1) { | |
System.out.println("\tfor (int i=0; i<SPRITE_COUNT; i++) \n" + | |
"\t\tSPRITES[i] = SPRITE_SHEET.getSubimage(0, i*SPRITE_HEIGHT, SPRITE_WIDTH, SPRITE_HEIGHT);"); | |
} | |
System.out.println("} catch (Exception e) {\n" + | |
" // TODO Auto-generated catch block\n" + | |
"}"); | |
System.out.println(); | |
} | |
// System.out.println("//Simple block encoding:"); | |
// StringBuilder sbEnc2 = new StringBuilder(); | |
// int last = -1; | |
// int counter = 1; | |
// for (int i=0; i<indexed.length; i++) { | |
// int b = indexed[i]; | |
// if (counter>=94) { //special case.. we need to reset counter | |
// sbEnc2.append((char)(48+last)); | |
// sbEnc2.append((char)(32+counter)); | |
// counter = 1; | |
// } else if (last==-1) { //first run | |
// if (i==indexed.length-1) { //special case -- 1 char long | |
// sbEnc2.append((char)(48+last)); | |
// sbEnc2.append((char)(32+counter)); | |
// } | |
// } else if (last==b) { //same index as last check, increase counter | |
// counter++; | |
// if (i==indexed.length-1) { | |
// sbEnc2.append((char)(48+last)); | |
// sbEnc2.append((char)(32+counter)); | |
// } | |
// } else { //new index, print last one and counter | |
// sbEnc2.append((char)(48+last)); | |
// sbEnc2.append((char)(32+counter)); | |
// counter = 1; | |
// } | |
// last = b; | |
// } | |
// System.out.println(sbEnc2.toString()); | |
// System.out.println(); | |
/* TODO: support binary packed encoding | |
if (!useFloatWithNormals && width * height <= 32 && colorTable.size()==2) { | |
ArrayList<Integer> packedList = new ArrayList<Integer>(); | |
for (int f=0, off=0; f<frames.length; f++) { | |
int packed = 0; | |
for (int i=0; i<width * height; i++) { | |
packed = (packed << 1) | indexed[off + i]; | |
} | |
packedList.add(packed); | |
off += width * height; | |
} | |
System.out.println("//////// ENCODING METHOD: Binary-Packed (2 colors, width*height <= 32)"); | |
System.out.println("final int[] SPRITE_DATA = new int[] {"); | |
System.out.print("\t"); | |
for (int i=0, count=0; i<packedList.size(); i++, count++) { | |
int packed = packedList.get(i); | |
System.out.print("0x"+Integer.toHexString(packed)); | |
// System.out.print(packed); | |
if (i!=packedList.size()-1) { | |
System.out.print(", "); | |
if (count>8) { | |
System.out.print("\n\t"); | |
count = 0; | |
} | |
} | |
} | |
System.out.println("\n};"); | |
System.out.println(); | |
System.out.println("for (int f=0, off=0; f<SPRITE_COUNT; f++, off+=SPRITE_STRIDE) {\n" + | |
" for (int i=0; i<SPRITE_STRIDE; i++)\n" + | |
" SPRITES[off+i] = ((SPRITE_DATA[f]>>(SPRITE_STRIDE-1-i)) & 1);\n" + | |
"}"); | |
System.out.println(); | |
}*/ | |
// if (!useFloatWithNormals && indexed.length < 95 && colorTable.size()<=2) { | |
// int lastIndex = indexed[0]; | |
// int lastPos = 0; | |
// int count = 0; | |
// StringBuilder sbEnc3 = new StringBuilder(); | |
// System.out.println("//Monochromatic (two colors, less than 95 pixels large):"); | |
// for (int i=0; i<indexed.length; i++) { | |
// int b = indexed[i]; | |
// //if this index is different | |
// if (b!=lastIndex) { | |
// if (lastIndex!=0) { | |
// sbEnc3.append( (char)(32 + lastPos) ); //append pixel position | |
// sbEnc3.append( (char)(32 + count) ); //append count | |
// } | |
// count = 1; | |
// lastPos = i; | |
// } else { | |
// count++; | |
// if (i==indexed.length-1 && lastIndex!=0) { | |
// sbEnc3.append( (char)(32 + lastPos) ); //append pixel position | |
// sbEnc3.append( (char)(32 + count) ); //append count | |
// } | |
// } | |
// lastIndex = b; | |
// } | |
// | |
// System.out.println("final int COLOR_MONOCHROME = 1;\n" + | |
// "char[] data = \""+sbEnc3.toString().replace("\\", "\\\\").replace("\"", "\\\"")+"\".toCharArray();\n" + | |
// "for (int i=0; i<data.length; i+=2) {\n" + | |
// " int index = ((int)data[i])-32;\n" + | |
// " int num = ((int)data[i+1])-32;\n" + | |
// " while (num-- > 0) \n" + | |
// " SPRITES[index + num] = COLOR_MONOCHROME;\n" + | |
// "}"); | |
// System.out.println(); | |
// } | |
// String[] s = "".split(' '); | |
// for (int color=0; color<s.length; color++) { | |
// for (int i=1; i<s[color].length(); i++) { | |
// int index = ((int)s[color].charAt(i))-32; | |
// int num = ((int)s[color].charAt(i+1))-32; | |
// while (num-- > 0) | |
// SPRITES[index + num] = color; | |
// } | |
// } | |
// for(int i = 0; i < 8; i++) { | |
// result[i] = (byte) ((val >> (7 - i)) & 1); | |
// } | |
//int value = 1 << ; | |
// for (int i=0; i) | |
// value = (value << 1) | 1; | |
// for (int i=0; i<indexed.length; i++) { | |
// value = value & indexed[i]; | |
// } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mdes.j4k.tools; | |
public class ImageToolTest { | |
public static void main(String[] args) throws Exception { | |
//GIF transparency is a bit wonky with ImageIO | |
ImageTool.encodeFormat = "PNG"; | |
//If true, then we get code that will work with BufferedImage | |
//If false, the code is more tailored toward per-pixel rendering | |
ImageTool.useBufferedImage = true; | |
//You can pass individual images like so: | |
//ImageTool.create("/res/knight1.png", "/res/knight2.png"); | |
//Or you can load an entire directory into a sprite sheet | |
ImageTool.create(ImageTool.dir("/res/pirates/")); | |
//Or you can pass BufferedImages directly | |
//ImageTool.create(arrayOfBufferedImages); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.applet.Applet; | |
import java.awt.AWTEvent; | |
import java.awt.Color; | |
import java.awt.Graphics; | |
import java.awt.Graphics2D; | |
import java.awt.event.KeyEvent; | |
import java.awt.event.MouseEvent; | |
import java.awt.image.BufferedImage; | |
import java.awt.image.DataBufferInt; | |
public class T extends Applet implements Runnable { | |
////////////////////////////////////////////////////////// | |
// image tool output ///////////////////////////////////// | |
////////////////////////////////////////////////////////// | |
//TYPE_INT_ARGB color table | |
public static final int[] TABLE = new int[] { | |
0x0, //transparent | |
0xff1a1a1a, //R=26, G=26, B=26, A=255 | |
0xffbfbfbf, //R=191, G=191, B=191, A=255 | |
0xffa29446, //R=162, G=148, B=70, A=255 | |
0xfff7e26b, //R=247, G=226, B=107, A=255 | |
0xffc20000, //R=194, G=0, B=0, A=255 | |
0xffff0000, //R=255, G=0, B=0, A=255 | |
0xff9d9d9d, //R=157, G=157, B=157, A=255 | |
0xff6f4417, //R=111, G=68, B=23, A=255 | |
0xffa46422 //R=164, G=100, B=34, A=255 | |
}; | |
//sprite array properties | |
public static final int SPRITE_WIDTH = 11; | |
public static final int SPRITE_HEIGHT = 9; | |
public static final int SPRITE_COUNT = 6; | |
public static final int SPRITE_STRIDE = SPRITE_WIDTH * SPRITE_HEIGHT; | |
public static final int SPRITE_ARRAY_LEN = SPRITE_STRIDE * SPRITE_COUNT; | |
//offsets to different sprite indices | |
public static final int SPRITE_PIRATE1_ATTACK = 0; | |
public static final int SPRITE_PIRATE1_WALK1 = 1; | |
public static final int SPRITE_PIRATE1_WALK2 = 2; | |
public static final int SPRITE_PIRATE2_ATTACK = 3; | |
public static final int SPRITE_PIRATE2_WALK1 = 4; | |
public static final int SPRITE_PIRATE2_WALK2 = 5; | |
//////// ENCODING METHOD: Simple Indexed Color Encoding | |
public static final BufferedImage SPRITE_SHEET = new BufferedImage(SPRITE_WIDTH, SPRITE_HEIGHT * SPRITE_COUNT, BufferedImage.TYPE_INT_ARGB); | |
public static final int[] SPRITE_PIXELS = ((DataBufferInt)SPRITE_SHEET.getRaster().getDataBuffer()).getData(); | |
public static final BufferedImage[] SPRITES = new BufferedImage[SPRITE_COUNT]; | |
////////////////////////////////////////////////////////// | |
// end generated code //////////////////////////////////// | |
////////////////////////////////////////////////////////// | |
//TODO: remove these if not needed | |
boolean[] keys = new boolean[32767]; | |
float mouseX, mouseY; | |
public void start() { | |
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); | |
new Thread(this).start(); | |
} | |
public void run() { | |
//Set up graphics | |
final int WIDTH = 240; | |
final int HEIGHT = 160; | |
final int SCALE = 2; | |
setSize(WIDTH*SCALE, HEIGHT*SCALE); // For AppletViewer, remove later. | |
//Set up our screen image | |
final BufferedImage screen = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); | |
final int[] pixels = ((DataBufferInt)screen.getRaster().getDataBuffer()).getData(); | |
final Graphics2D g = (Graphics2D)screen.getGraphics(); | |
final Graphics appletGraphics = getGraphics(); | |
// Some variables to use for the fps. | |
int tick = 0, fps = 0, acc = 0; | |
long lastTime = System.nanoTime(); | |
// ---------------- LOAD IMAGES ---------------- // | |
////////////////////////////////////////////////////////// | |
// image tool output ///////////////////////////////////// | |
////////////////////////////////////////////////////////// | |
for (int i=0; i<SPRITE_ARRAY_LEN; i++) { | |
SPRITE_PIXELS[i] = TABLE["000000000001111212000011111110000034141000000344430000255666502220411171400000888880000008000800000000000000001111212020011111110200034141002000344430200055666540000411171000000888880000008000800000111121202001111111020003414100200034443020005566654000041117100000088888000000888880000008000800000000000000006066600000006666600000634141000000344430000288999802220411171400000888880000008000800000000000000006066600020006666600200634141002000344430200088999840000411171000000888880000008000800000606660002000666660020063414100200034443020008899984000041117100000088888000000888880000008000800000".charAt(i)-48]; | |
if (i%SPRITE_STRIDE == SPRITE_STRIDE-1) { | |
SPRITES[i/(SPRITE_WIDTH*SPRITE_HEIGHT)] = SPRITE_SHEET.getSubimage( | |
0, i/(SPRITE_WIDTH*SPRITE_HEIGHT)*SPRITE_HEIGHT, | |
SPRITE_WIDTH, SPRITE_HEIGHT); | |
} | |
} | |
// ---------------- GAME LOOP ---------------- // | |
while (true) { | |
long now = System.nanoTime(); | |
long delta = now - lastTime; | |
acc += delta; | |
tick++; | |
if (acc >= 1000000000L) { | |
acc -= 1000000000L; | |
fps = tick; | |
tick = 0; | |
} | |
// Update | |
lastTime = now; | |
//TODO: remove later if not needed | |
g.clearRect(0, 0, WIDTH, HEIGHT); | |
// ---------------- DRAW SPRITES ---------------- // | |
g.drawImage(SPRITES[SPRITE_PIRATE2_ATTACK], | |
50, 50, | |
SPRITE_WIDTH*2, SPRITE_HEIGHT*2, | |
null); | |
//TODO: remove later | |
g.setColor(Color.white); | |
g.drawString("FPS " + String.valueOf(fps), 20, 30); | |
// Draw the entire results on the screen. | |
appletGraphics.drawImage(screen, 0, 0, WIDTH*SCALE, HEIGHT*SCALE, null); | |
do { | |
Thread.yield(); | |
} while (System.nanoTime() - lastTime < 1000000000/60); | |
if (!isActive()) { | |
return; | |
} | |
} | |
} | |
public void processEvent(AWTEvent e) | |
{ | |
boolean down = false; | |
switch (e.getID()) | |
{ | |
case KeyEvent.KEY_PRESSED: | |
down = true; | |
case KeyEvent.KEY_RELEASED: | |
keys[((KeyEvent) e).getKeyCode()] = down; | |
break; | |
case MouseEvent.MOUSE_PRESSED: | |
down = true; | |
case MouseEvent.MOUSE_RELEASED: | |
keys[((MouseEvent) e).getButton()] = down; | |
case MouseEvent.MOUSE_MOVED: | |
case MouseEvent.MOUSE_DRAGGED: | |
mouseX = ((MouseEvent) e).getX(); | |
mouseY = ((MouseEvent) e).getY(); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment