Jump to content
IGNORED

My Sprite Editor - Try it out - Updated layering


unhuman

Recommended Posts

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 by artrag
Link to comment
Share on other sites

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

  • Like 2
Link to comment
Share on other sites

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 by unhuman
Link to comment
Share on other sites

  • 4 weeks later...
  • 1 month later...
  • 1 month later...
  • 2 weeks later...

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.

Link to comment
Share on other sites

  • 1 year later...

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...