Package it.marteEngine

Source Code of it.marteEngine.XMLResourceLoader

package it.marteEngine;

import org.newdawn.slick.AngelCodeFont;
import org.newdawn.slick.Animation;
import org.newdawn.slick.BigImage;
import org.newdawn.slick.Color;
import org.newdawn.slick.Image;
import org.newdawn.slick.Music;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Sound;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.SpriteSheetFont;
import org.newdawn.slick.UnicodeFont;
import org.newdawn.slick.font.effects.ColorEffect;
import org.newdawn.slick.tiled.TiledMap;
import org.newdawn.slick.util.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.StringTokenizer;
/**
* The XMLResourceLoader parses an xml document and reads the following known
* elements:
* basedir path(req)
* sound key file
* music key file
* image key file transparentColor(opt)
* sheet key file width height transparentColor(opt)
* anim key imgName frameDuration frames(opt) flipVertical(opt) flipHorizontal(opt) loop(default=true)
* angelcodefont key fontFile imageFile
* unicodefont key file fontSize(default=12)
* spritesheetfont key file firstchar
* map key file
* param key value
* <p/>
* A parameter followed by (req) means Required and by (opt) means Optional.
* Some parameters are optional because they have a default value. The file
* parameter is relative to the basedir.
* <p/>
* Examples:
* <sound key="jump" file="jump.wav" />
* <music key="sleepy" file="sleep.wav" />
* <image key="ship" file="ship.png" />
* <sheet key="homer" file="homer.png" width="25" height="25" transparentColor="000000" />
* <anim key="homer" imgName="homer" frameDuration="250" row="0" frames="1,2,3,4,5"
* flipVertical="true" flipHorizontal="true" loop="false"/>
* <unicodefont key="default" file="gbb.ttf" fontSize="20" />
* <angelcodefont key="font" fontFile="font.fnt" imageFile="font.png" />
* <map key="level1" file="level1.tmx" />
* <param key="bossLevel" value="11" />
*/
public class XMLResourceLoader {
  private Element[] NO_ELEMENTS = new Element[0];
  private String baseDir;
  private Element rootElement;

  public void load(InputStream in) throws IOException {
    try {
      DocumentBuilder builder = DocumentBuilderFactory.newInstance()
          .newDocumentBuilder();
      Document document = builder.parse(in);
      rootElement = document.getDocumentElement();
      validateResourceFile();

      Element[] elements = getElementsByTagName("basedir");
      setBaseDirectory(elements[0].getAttribute("path"));

      for (Element element : getElementsByTagName("sound")) {
        loadSound(element);
      }
      for (Element element : getElementsByTagName("music")) {
        loadMusic(element);
      }
      for (Element element : getElementsByTagName("image")) {
        loadImage(element);
      }
      for (Element element : getElementsByTagName("sheet")) {
        loadSpriteSheet(element);
      }
      for (Element element : getElementsByTagName("anim")) {
        loadAnimation(element);
      }
      for (Element element : getElementsByTagName("angelcodefont")) {
        loadAngelCodeFont(element);
      }
      for (Element element : getElementsByTagName("unicodefont")) {
        loadUnicodeFont(element);
      }
      for (Element element : getElementsByTagName("spritesheetfont")) {
        loadSpriteSheetFont(element);
      }
      for (Element element : getElementsByTagName("map")) {
        loadTiledMap(element);
      }
      for (Element element : getElementsByTagName("param")) {
        loadParameter(element);
      }
    } catch (Exception e) {
      Log.error(e);
      throw new IOException(
          "Unable to load resource configuration file", e);
    }
  }

  private void validateResourceFile() throws IOException {
    if (!rootElement.getNodeName().equals("resources")) {
      throw new IOException("Not a resource configuration file");
    }
  }

  private Element[] getElementsByTagName(String elementName) {
    NodeList nodes = rootElement.getElementsByTagName(elementName);
    int nodeCount = nodes.getLength();

    if (nodeCount != 0) {
      Element[] elements = new Element[nodeCount];

      for (int i = 0; i < nodeCount; i++) {
        Element element = (Element) nodes.item(i);
        elements[i] = element;
      }
      return elements;
    } else {
      return NO_ELEMENTS;
    }
  }

  private void setBaseDirectory(String baseDirectory) throws SlickException {
    Log.debug("Setting base directory to " + baseDirectory);
    if (baseDirectory == null || baseDirectory.isEmpty()) {
      throw new SlickException("Could not find required BaseDir element.");
    }
    baseDir = baseDirectory;
    if (!baseDir.endsWith("/")) {
      baseDir += "/";
    }
  }

  private void loadSound(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "file");
    String key = element.getAttribute("key");
    String file = element.getAttribute("file");
    Log.debug(formatLoadMsg("sound", key, file));
    ResourceManager.addSound(key, new Sound(baseDir + file));
  }

  private void loadMusic(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "file");
    String key = element.getAttribute("key");
    String file = element.getAttribute("file");
    Log.debug(formatLoadMsg("music", key, file));
    ResourceManager.addMusic(key, new Music(baseDir + file));
  }

  private void loadImage(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "file");
    String key = element.getAttribute("key");
    String file = element.getAttribute("file");
    Color transparentColor = null;

    if (element.hasAttribute("transparentColor")) {
      transparentColor = decodeColor(element);
    }

    Image image;
    try {
      image = new Image(baseDir + file, transparentColor);
    } catch (SlickException ex) {
      // To support large textures on older graphic cards
      Log.info("Using BigImage.");
      image = new BigImage(baseDir + file);
    }
    Log.debug(formatLoadMsg("image", key, file));
    ResourceManager.addImage(key, image);
  }

  private void loadSpriteSheet(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "file", "width", "height");
    String key = element.getAttribute("key");
    String file = element.getAttribute("file");
    int width = parseIntAttribute(element, "width");
    int height = parseIntAttribute(element, "height");
    Color transparentColor = null;

    if (element.hasAttribute("transparentColor")) {
      transparentColor = decodeColor(element);
    }

    Log.debug(String.format(
        "Loading spritesheet key=%s file=%s width=%s height=%s", key,
        file, width, height));
    ResourceManager.addSpriteSheet(key, new SpriteSheet(baseDir + file,
        width, height, transparentColor));
  }

  private Color decodeColor(Element element) {
    String transparentColorAsText = element
        .getAttribute("transparentColor");
    if (transparentColorAsText != null && !transparentColorAsText.isEmpty()) {
      return Color.decode(transparentColorAsText);
    } else {
      return null;
    }
  }

  private void loadAnimation(Element element) {
    checkRequiredAttributes(element, "key", "imgName", "frameDuration");
    String key = element.getAttribute("key");
    String imgName = element.getAttribute("imgName");
    int frameDuration = parseIntAttribute(element, "frameDuration");
    boolean flipHorizontal = false, flipVertical = false;
    int[] frames;
    int row = 0;
    boolean loop = true;

    if (!ResourceManager.hasSpriteSheet(imgName)) {
      throw new IllegalArgumentException("Animation " + key
          + " needs spritesheet " + imgName
          + " but it has not been loaded.");
    }
    SpriteSheet sheet = ResourceManager.getSpriteSheet(imgName);

    if (element.hasAttribute("frames")) {
      String framesAsText = element.getAttribute("frames");
      frames = readFrameIndexes(framesAsText);
    } else {
      frames = new int[sheet.getHorizontalCount()];
      for (int i = 0; i < sheet.getHorizontalCount(); i++) {
        frames[i] = i;
      }
    }
    if (element.hasAttribute("flipHorizontal")) {
      flipHorizontal = parseBooleanAttribute(element, "flipHorizontal");
    }
    if (element.hasAttribute("flipVertical")) {
      flipVertical = parseBooleanAttribute(element, "flipVertical");
    }
    if (element.hasAttribute("row")) {
      row = parseIntAttribute(element, "row");
    }
    if (element.hasAttribute("loop")) {
      loop = parseBooleanAttribute(element, "loop");
    }

    Animation anim = buildAnimationFromFrames(sheet, row, frames,
        frameDuration, flipHorizontal, flipVertical);
    anim.setLooping(loop);
    Log.debug(formatLoadMsg("animation", key, "spritesheet", imgName));
    ResourceManager.addAnimation(key, anim);
  }

  private int[] readFrameIndexes(String framesAsText) {
    StringTokenizer tokenizer = new StringTokenizer(framesAsText, ",");

    int frames[] = new int[tokenizer.countTokens()];
    for (int i = 0; tokenizer.hasMoreTokens(); i++) {
      frames[i] = Integer.parseInt(tokenizer.nextToken().trim());
    }
    return frames;
  }

  /**
   * Create an animation from a spritesheet row.
   *
   * @param sheet
   *            The spritesheet that contains the individual images.
   * @param row
   *            The vertical index in the spritesheet to read the animation
   *            from, zero based.
   * @param frames
   *            The horizontal indexes of the frames that need to be included
   *            in the animation, zero based.
   * @param frameDuration
   *            The duration of 1 frame in the resulting animation.
   * @param flipHorizontal
   *            If true flips each frame in the animation on the x axis
   * @param flipVertical
   *            If true flips each frame in the animation on the y axis
   * @return An animation parsed from the spritesheet
   */
  private Animation buildAnimationFromFrames(SpriteSheet sheet, int row,
      int[] frames, int frameDuration, boolean flipHorizontal,
      boolean flipVertical) {
    Animation animation = new Animation(false);
    for (int frameIndex : frames) {
      Image img = sheet.getSubImage(frameIndex, row);

      if (flipHorizontal || flipVertical) {
        img = img.getFlippedCopy(flipHorizontal, flipVertical);
      }
      animation.addFrame(img, frameDuration);
    }
    return animation;
  }

  private void loadAngelCodeFont(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "fontFile", "imageFile");
    String key = element.getAttribute("key");
    String fontFile = element.getAttribute("fontFile");
    String imageFile = element.getAttribute("imageFile");

    Log.debug(String.format(
        "Loading Angelcode font key=%s imagefile=%s fontfile=%s", key,
        imageFile, fontFile));
    AngelCodeFont font = new AngelCodeFont(baseDir + fontFile, baseDir
        + imageFile, true);
    ResourceManager.addFont(key, font);
  }

  @SuppressWarnings("unchecked")
  private void loadUnicodeFont(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "file");
    String key = element.getAttribute("key");
    String ttfFile = element.getAttribute("file");
    int fontSize = 12;

    if (element.hasAttribute("fontSize")) {
      fontSize = parseIntAttribute(element, "fontSize");
    }

    Log.debug(formatLoadMsg("Unicode font", key, ttfFile));
    UnicodeFont unicodeFont = new UnicodeFont(baseDir + ttfFile, fontSize,
        false, false);
    unicodeFont.getEffects().add(new ColorEffect());
    unicodeFont.addAsciiGlyphs();
    unicodeFont.loadGlyphs();
    unicodeFont.setDisplayListCaching(true);
    ResourceManager.addFont(key, unicodeFont);
  }

  private void loadSpriteSheetFont(Element element) {
    checkRequiredAttributes(element, "key", "file", "firstchar");
    String key = element.getAttribute("key");
    String imgName = element.getAttribute("file");
    char startingChar = element.getAttribute("firstchar").charAt(0);

    if (!ResourceManager.hasSpriteSheet(imgName)) {
      throw new IllegalArgumentException("Spritesheetfont " + key
          + " needs spritesheet " + imgName
          + " but it has not been loaded.");
    }
    SpriteSheet sheet = ResourceManager.getSpriteSheet(imgName);

    Log.debug(formatLoadMsg("SpriteSheet font", key, imgName));
    SpriteSheetFont font = new SpriteSheetFont(sheet, startingChar);
    ResourceManager.addFont(key, font);
  }

  private void loadTiledMap(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "file");
    String key = element.getAttribute("key");
    String file = element.getAttribute("file");

    Log.debug(formatLoadMsg("Tiled map", key, file));
    TiledMap tiledMap = new TiledMap(baseDir + file);
    ResourceManager.addTiledMap(key, tiledMap);
  }

  private void loadParameter(Element element) throws SlickException {
    checkRequiredAttributes(element, "key", "value");
    String key = element.getAttribute("key");
    String value = element.getAttribute("value");

    Log.debug(formatLoadMsg("Parameter", key, "value", value));
    ResourceManager.setParameter(key, value);
  }

  private void checkRequiredAttributes(Element element, String... attributes) {
    boolean requiredAttributeMissing = false;
    for (String attribute : attributes) {
      if (!element.hasAttribute(attribute)) {
        requiredAttributeMissing = true;
      }
    }

    if (requiredAttributeMissing) {
      StringBuffer missingAttributesMessage = new StringBuffer(
          "Required attribute(s) missing: ");
      for (String attribute : attributes) {
        if (!element.hasAttribute(attribute)) {
          missingAttributesMessage.append(attribute);
          missingAttributesMessage.append(", ");
        }
      }
      // Remove trailing ", "
      int length = missingAttributesMessage.length();
      missingAttributesMessage.delete(length - 2, length);
      missingAttributesMessage.append(" from element ").append(
          element.getNodeName());
      throw new IllegalArgumentException(
          missingAttributesMessage.toString());
    }
  }

  private int parseIntAttribute(Element element, String attributeName) {
    return Integer.parseInt(element.getAttribute(attributeName));
  }

  private boolean parseBooleanAttribute(Element element, String attributeName) {
    return Boolean.parseBoolean(element.getAttribute(attributeName));
  }

  private String formatLoadMsg(String type, String key, String value) {
    return formatLoadMsg(type, key, "file", value);
  }

  private String formatLoadMsg(String type, String key, String valueName,
      String value) {
    StringBuffer buf = new StringBuffer("Loading ");
    buf.append(type).append(" key=").append(key).append(" ")
        .append(valueName).append("=").append(value);
    return buf.toString();
  }
}
TOP

Related Classes of it.marteEngine.XMLResourceLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.