artrag Posted September 6, 2014 Share Posted September 6, 2014 (edited) hi unhuman could it be possible to add graphic importing from e.g. gif or png files ? Provided that the png file in input is 16x16 and has up to 4 colors + background it should be easy to map it in sprite data. I would like to have multiple definitions of layered sprites to allow animations... You could just add a frame number and allow to work/import data on each frame By pressing on a button with arrows you can manually change frame and see a simple animation in the preview window... Edited September 6, 2014 by artrag Quote Link to comment Share on other sites More sharing options...
unhuman Posted September 6, 2014 Author Share Posted September 6, 2014 The latest source is in the first post - anything is possible. If people actually want to work with this, I could create a github project. -H Quote Link to comment Share on other sites More sharing options...
Asmusr Posted September 6, 2014 Share Posted September 6, 2014 I use this small Java program I wrote to create sprite assembly data from 16 color indexed PNG files. The background color must be index 0, and each other index used is treated as a separate layer. It can handle multiple files at the same time, and also images larger then 16x16 as long as the width and height are multiples of 16. It can also produce multicolor sprites for the F18A. I use an old version of Paint Shop Pro to create the PNGs. import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.io.File; import java.io.FileOutputStream; import java.util.Map; import java.util.TreeMap; /** * Created with IntelliJ IDEA. * User: Rasmus * Date: 27-05-13 * Time: 20:17 */ public class Main { public static String APPLICATION_NAME = "Img2Sprite v. 1.1"; public static final int F18A_PATTERN_PLANES = 3; public static void main(String[] args) { new Main(); } public Main() { boolean f18ASprites = JOptionPane.showConfirmDialog(null, "Do you want to create F18A ECM sprites?", "Confirm F18A Sprites", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION; JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter( new FileNameExtensionFilter("PNG Files", "png") ); fileChooser.setMultiSelectionEnabled(true); fileChooser.setCurrentDirectory(new File(".")); if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { StringBuilder asmData = new StringBuilder(); StringBuilder[] planeBuilders = new StringBuilder[4]; for (int i = 0; i < 4; i++) { planeBuilders[i] = new StringBuilder(); } File[] files = fileChooser.getSelectedFiles(); for (int f = 0; f < files.length; f++) { File file = files[f]; String name = file.getName().substring(0, file.getName().indexOf(".")).toUpperCase(); try { BufferedImage image = ImageIO.read(file); if (image.getWidth() % 16 == 0 && image.getHeight() % 16 == 0) { ColorModel colorModel = image.getColorModel(); if (colorModel instanceof IndexColorModel) { IndexColorModel indexColorModel = (IndexColorModel) colorModel; if (indexColorModel.getMapSize() == 16) { System.out.println(file.getName()); int xSprites = image.getWidth() / 16; int ySprites = image.getHeight() / 16; for (int sy = 0; sy < ySprites; sy++) { int y0 = sy * 16; for (int sx = 0; sx < xSprites; sx++) { int x0 = sx * 16; Raster raster = image.getRaster(); if (!f18ASprites) { Map<Integer, int[][]> colorLayers = new TreeMap<Integer, int[][]>(); for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { int[] pixel = new int[1]; raster.getPixel(x + x0, y + y0, pixel); int colorIndex = pixel[0]; if (colorIndex != 0) { // 0 is transparent int[][] colorLayer = colorLayers.get(colorIndex); if (colorLayer == null) { colorLayer = new int[16][16]; colorLayers.put(colorIndex, colorLayer); } colorLayer[y][x] = 1; } System.out.print(Integer.toHexString(pixel[0]).toUpperCase()); } System.out.println(); } System.out.println(); int p = 0; for (int colorIndex : colorLayers.keySet()) { boolean first = true; int[][] colorLayer = colorLayers.get(colorIndex); StringBuilder data = planeBuilders[p]; for (int col = 0; col < 2; col++) { for (int y = 0; y < 16; y++) { if (y % 8 == 0) { data.append("\r\n"); if (first) { String thisName = name; if (xSprites > 1 || ySprites > 1) { thisName += sx + ySprites * sy; } if (colorLayers.size() > 1) { thisName += p; } data.append(thisName); for (int n = 0; n < 6 - thisName.length(); n++) { data.append(" "); } first = false; } else { data.append("\t "); } data.append(" DATA "); } int b = 0; for (int x = 0; x < 8; x++) { b |= colorLayer[y][x + col * 8] * (128 >> x); } if (y % 2 == 0) { data.append(">"); } data.append(b < 16 ? "0" : "").append(Integer.toHexString(b).toUpperCase()); if (y % 2 == 1 && y % 8 != 7) { data.append(","); } if (y == 7 && col == 0) { data.append("\t* Color ").append(colorIndex); } } } p++; } } // F18A ECM sprites else { boolean first; for (int patternPlane = 0; patternPlane < F18A_PATTERN_PLANES; patternPlane++) { first = true; StringBuilder data = planeBuilders[patternPlane]; for (int col = 0; col < 2; col++) { for (int y = 0; y < 16; y++) { if (y % 8 == 0) { data.append("\r\n"); if (first) { data.append(name); data.append(patternPlane); for (int n = 0; n < 5 - name.length(); n++) { data.append(" "); } first = false; } else { data.append("\t "); } data.append(" DATA "); } int b = 0; for (int x = 0; x < 8; x++) { int[] pixel = new int[1]; raster.getPixel(x0 + x + col * 8, y0 + y, pixel); int colorIndex = pixel[0]; b |= ((colorIndex & (1 << patternPlane)) >> patternPlane) * (128 >> x); } if (y % 2 == 0) { data.append(">"); } data.append(b < 16 ? "0" : "").append(Integer.toHexString(b).toUpperCase()); if (y % 2 == 1 && y % 8 != 7) { data.append(","); } if (y == 7 && col == 0) { data.append("\t* Plane ").append(patternPlane); } } } } // Palette if (f == files.length - 1) { first = true; for (int i = 0; i < Math.pow(2, F18A_PATTERN_PLANES); i++) { if (i % 4 == 0) { asmData.append("\r\n"); if (first) { asmData.append("\nPAL "); first = false; } else { asmData.append("\t"); } asmData.append(" DATA "); } indexColorModel.getRGB(i); asmData.append(">0"); asmData.append(Integer.toHexString((int) Math.round((double) indexColorModel.getRed(i) / 17)).toUpperCase()); asmData.append(Integer.toHexString((int) Math.round((double) indexColorModel.getGreen(i) / 17)).toUpperCase()); asmData.append(Integer.toHexString((int) Math.round((double) indexColorModel.getBlue(i) / 17)).toUpperCase()); if (i % 4 != 3) { asmData.append(","); } } asmData.append("\r\n"); } } } } } else { throw new Exception("Palette size must be 16 colors."); } } else { throw new Exception("Color model must be indexed."); } } else { throw new Exception("Image size must be 16 x 16 pixels."); } } catch (Exception e) { JOptionPane.showMessageDialog(null, file.getName() + ": " + e.getMessage(), APPLICATION_NAME, JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } for (StringBuilder planeBuilder : planeBuilders) { asmData.append(planeBuilder); } System.out.println(asmData); fileChooser.setSelectedFile(new File("sprites.a99")); fileChooser.setFileFilter( new FileNameExtensionFilter("TMS9900 Assembly Files", "a99") ); fileChooser.setMultiSelectionEnabled(false); if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { File outputFile = fileChooser.getSelectedFile(); try { FileOutputStream fileOutputStream = new FileOutputStream(outputFile); fileOutputStream.write(asmData.toString().getBytes()); fileOutputStream.close(); } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage(), APPLICATION_NAME, JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } } } } Img2Sprite.zip 2 Quote Link to comment Share on other sites More sharing options...
artrag Posted September 7, 2014 Share Posted September 7, 2014 Thanks! Maybe your script can be at the base of an integration for unhuman's tool I would try myself if I were able to code in Java Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted September 7, 2014 Share Posted September 7, 2014 I had totally forgotten about this tool... Has it seen much use in recent projects? Quote Link to comment Share on other sites More sharing options...
artrag Posted September 7, 2014 Share Posted September 7, 2014 I've just used it yesterday just for fun I think it could become a nice tool once added PNG inport and support for animation Quote Link to comment Share on other sites More sharing options...
unhuman Posted September 9, 2014 Author Share Posted September 9, 2014 (edited) I've used it a bit here and there, but I've unfortunately been inactive for > 1 year now (other than lurking). I can't stay up late anymore. If you need help adding stuff to the tool, I can probably help somewhat. I haven't touched that code in a while and I remember adding the layers or something made the code a bit rough... Layers were needed to make my Avatar (and the game that hasn't come to completion). Edited September 9, 2014 by unhuman Quote Link to comment Share on other sites More sharing options...
artrag Posted September 9, 2014 Share Posted September 9, 2014 (edited) I have linked your tool on www.msx.org for developing msx 1 sprites. Maybe this will increase its use in real projects and some java coder could even consider if integrate your editor Edited September 16, 2014 by artrag 1 Quote Link to comment Share on other sites More sharing options...
unhuman Posted October 4, 2014 Author Share Posted October 4, 2014 I'm going to move my source to GitHub. Then anyone can branch and integrate changes and send me pull requests to merge... 1 Quote Link to comment Share on other sites More sharing options...
unhuman Posted November 9, 2014 Author Share Posted November 9, 2014 Just noticed that my tool doesn't render colors properly on a Mac. What a weird bug. Quote Link to comment Share on other sites More sharing options...
unhuman Posted January 9, 2015 Author Share Posted January 9, 2015 Pushed the source to GitHub.... See the first post for the link. Nothing else to see here. Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted January 18, 2015 Share Posted January 18, 2015 I have a feature request. I do not know enough about Java to complete a semester otherwise I would try to code this myself. It would be helpful to be able to place sprites next to each other. For instance, for Arkanoid the Vaus (paddle) is made up of four sprites and background tiles: two sprites overlapping next to two sprites overlapping. This can help me encode the sprites into data but I am unable to see the actual final product. Quote Link to comment Share on other sites More sharing options...
unhuman Posted January 19, 2015 Author Share Posted January 19, 2015 I'll try to take a look. There were a few bugs (which of course I didn't note and don't remember) that I noticed the last time I used the tool. When I added layering, some of the code got messy. This probably would be similar. But, entirely doable. -H Quote Link to comment Share on other sites More sharing options...
unhuman Posted March 4, 2016 Author Share Posted March 4, 2016 I've updated the code on Github to render properly on mac and a few other small things. 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted March 4, 2016 Share Posted March 4, 2016 I've updated the code on Github to render properly on mac and a few other small things. Could you post a jar file, please? Quote Link to comment Share on other sites More sharing options...
unhuman Posted March 5, 2016 Author Share Posted March 5, 2016 (edited) Yep. There you go on top post. It's version 1.0 since I added Maven. Could you post a jar file, please? Edited March 5, 2016 by unhuman Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.