package com.junerking.skeleton.sdp; import java.util.ArrayList; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Vector2; public class XAnimation extends IAnimation { private HashMap<Integer, AtlasRegion> atlas_region = new HashMap<Integer, AtlasRegion>(); protected int _action_count; protected String[] _action_ids; protected String[] _nextaction_ids; protected XAnimationFrames[] _actions; protected TextureAtlas _texture_atlas; public XAnimation(int frame_count) { _action_count = frame_count; _action_ids = new String[_action_count]; _nextaction_ids = new String[_action_count]; _actions = new XAnimationFrames[_action_count]; } public void addAtlasComponent(int id, AtlasRegion region) { atlas_region.put(id, region); } //=================================================================================== public final class State { int action_index = -1, frame_index, speed = 150, size = 0, last_frame_index; long time = 0; boolean flip_x; public void tick(float time_span) { if (action_index >= 0) { time += time_span; int count = (int) (time / speed); last_frame_index = frame_index; frame_index = count % size; if (count % size == 0 && last_frame_index != frame_index) { boolean action_changed = false; if (!action_changed) { changeAction(_nextaction_ids[action_index]); } } } } public void changeAction(String animation_name) { if (animation_name == null || animation_name.equals("")) { _changeAction(-1); return; } for (int i = _action_ids.length - 1; i >= 0; i--) { if (animation_name.equals(_action_ids[i])) { _changeAction(i); return; } } _changeAction(-1); } protected void _changeAction(int nextaction) { System.out.println("==== " + nextaction); action_index = nextaction; frame_index = 0; time = 0; if (action_index >= 0) { size = _actions[action_index].size; } } public boolean isFlipX() { return flip_x; } public int getFrameId() { return frame_index; } public int getActionIndex() { return action_index; } public String getAction() { if (action_index == -1) return null; return _action_ids[action_index]; } public IAnimation getAnimation() { return XAnimation.this; } } public State createState() { return new State(); } //=================================================================================== //---------------------render------------------------------ private Matrix4 mutable_matrix = new Matrix4(); private Matrix4 temp_matrix = new Matrix4(); public void render(SpriteBatch sprite_batch, float x, float y, float sx, float sy, int action_index, int frame_index, boolean flip_x) { if (action_index >= _action_count || action_index < 0) return; final XAnimationFrames ca = _actions[action_index]; if (frame_index < 0 || frame_index >= ca.size) return; final XSingleFrame frame = ca.frames_array.get(frame_index); if (frame == null) return; temp_matrix.set(sprite_batch.getTransformMatrix().val); mutable_matrix.set(temp_matrix); mutable_matrix.translate(x, y, 0); if (flip_x) { mutable_matrix.scale(-sx, sy, 0); } else { mutable_matrix.scale(sx, sy, 0); } sprite_batch.setTransformMatrix(mutable_matrix); final ArrayList<XPosition> positions_array = frame.getPositionArray(); for (XPosition p : positions_array) { final AtlasRegion r = atlas_region.get(p.type); if (r != null) sprite_batch.draw(r, p.x1, p.y1, p.x2, p.y2, p.x3, p.y3, p.x4, p.y4, r.getU(), r.getV(), r.getU2(), r.getV2()); } sprite_batch.setTransformMatrix(temp_matrix); } //=================================================================================== //----------------------parse----------------------- public static XAnimation createAnimation(String file_name) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); System.out.print("" + Gdx.files.internal("")); Document doc = db.parse(Gdx.files.internal(file_name).file()); doc.normalize(); return getCharData(doc, file_name.substring(0, file_name.lastIndexOf('/') + 1)); } catch (Exception e) { e.printStackTrace(); } return null; } public static XAnimation getCharData(Document doc, String file_name_pre) throws ParserConfigurationException, SAXException { XAnimation data = null; NodeList headers = doc.getElementsByTagName("XAnimation"); data = new XAnimation(getIntValue((Element) (headers.item(0)), "frame_count", 1)); HashMap<Integer, Vector2> component_list = new HashMap<Integer, Vector2>(); //components { NodeList _components = doc.getElementsByTagName("components"); Element components = (Element) _components.item(0); String texture_atlas_name = components.getAttribute("texture_atlas"); TextureAtlas texture_atlas = new TextureAtlas(file_name_pre + texture_atlas_name); NodeList nodes = components.getElementsByTagName("component"); for (int i = 0, n = nodes.getLength(); i < n; i++) { Element element = (Element) (nodes.item(i)); int component_id = getIntValue(element, "type", -1); int w = getIntValue(element, "w", 0); int h = getIntValue(element, "h", 0); Vector2 vc = new Vector2(w, h); component_list.put(component_id, vc); String component_name = element.getAttribute("name"); AtlasRegion region = texture_atlas.findRegion(component_name); if (region != null) { data.addAtlasComponent(component_id, region); } } } { NodeList _frames = doc.getElementsByTagName("Frames"); for (int ii = 0, n = _frames.getLength(); ii < n; ii++) { Element frames = (Element) (_frames.item(ii)); boolean loop = getBooleanValue(frames, "loop", true); data._action_ids[ii] = getStringValue(frames, "id"); if (!loop) { data._nextaction_ids[ii] = getStringValue(frames, "next"); } else { data._nextaction_ids[ii] = null; } XAnimationFrames animation_frames = new XAnimationFrames(); NodeList frame_data = frames.getElementsByTagName("frame"); for (int jj = 0, m = frame_data.getLength(); jj < m; jj++) { Element _single_frame = (Element) (frame_data.item(jj)); XSingleFrame single_frame = new XSingleFrame(); NodeList pos_list = _single_frame.getElementsByTagName("position"); for (int kk = 0, len = pos_list.getLength(); kk < len; kk++) { Element _pos = (Element) (pos_list.item(kk)); int region_id = getIntValue(_pos, "type", 0); float tx = getFloatValue(_pos, "x", 0); float ty = getFloatValue(_pos, "y", 0); float sx = getFloatValue(_pos, "sx", 0); float sy = getFloatValue(_pos, "sy", 0); float rx = getFloatValue(_pos, "rx", 0); float ry = getFloatValue(_pos, "ry", 0); Vector2 com = component_list.get(region_id); AtlasRegion region = data.atlas_region.get(region_id); if (region == null || region.packedWidth == region.originalWidth && region.packedHeight == region.originalHeight) { XXXPosition(com.x, com.y, null, tx, ty, sx, sy, rx, ry, 1.0f); } else { XXXPosition(com.x, com.y, region, tx, ty, sx, sy, rx, ry, 1.0f); } XPosition p = new XPosition(region_id, x1, y1, x2, y2, x3, y3, x4, y4); single_frame.addPosition(p); } animation_frames.addFrame(single_frame); } data._actions[ii] = animation_frames; } } component_list.clear(); component_list = null; return data; } public static int getIntValue(Element element, String key, int defaultValue) { if (element.hasAttribute(key)) { return Integer.parseInt(element.getAttribute(key)); } return defaultValue; } public static float getFloatValue(Element element, String key, float defaultValue) { if (element.hasAttribute(key)) { return Float.parseFloat(element.getAttribute(key)); } return defaultValue; } public static boolean getBooleanValue(Element element, String key, boolean defaultValue) { if (element.hasAttribute(key)) { return Boolean.parseBoolean(element.getAttribute(key)); } return defaultValue; } public static String getStringValue(Element element, String key) { return element.getAttribute(key); } //======================================================================== //------------------------static classes---------------------------------- //======================================================================== public static class XSingleFrame { private ArrayList<XPosition> positions_array; public XSingleFrame() { positions_array = new ArrayList<XPosition>(); } public void addPosition(XPosition position) { positions_array.add(position); } public ArrayList<XPosition> getPositionArray() { return positions_array; } } private static class XPosition { public int type; public float x1, x2, x3, x4; public float y1, y2, y3, y4; public XPosition(int type, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { this.type = type; this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.x3 = x3; this.y3 = y3; this.x4 = x4; this.y4 = y4; } } private static float x1, y1, x2, y2, x3, y3, x4, y4; public static void XXXPosition(float originalWidth, float originalHeight, AtlasRegion region, float x, float y, float sx, float sy, float rs0, float rs1, float scale) { if (region != null) { float scalew = originalWidth * 1.0f / region.originalWidth; float scaleh = originalHeight * 1.0f / region.originalHeight; float ox = region.offsetX * scalew; float oy = (region.originalHeight - region.packedHeight - region.offsetY) * scaleh; float pw = region.packedWidth * scalew; float ph = region.packedHeight * scaleh; x1 = sx * ox + rs1 * (-oy) + x; y1 = rs0 * ox + sy * (-oy) + y; x2 = sx * (ox + pw) + rs1 * (-oy) + x; y2 = rs0 * (ox + pw) + sy * (-oy) + y; x3 = sx * (ox + pw) + rs1 * (-oy - ph) + x; y3 = rs0 * (ox + pw) + sy * (-oy - ph) + y; x4 = sx * ox + rs1 * (-oy - ph) + x; y4 = rs0 * ox + sy * (-oy - ph) + y; } else { x1 = x; y1 = y; x2 = sx * originalWidth + x; y2 = rs0 * originalWidth + y; x3 = sx * originalWidth + rs1 * (-originalHeight) + x; y3 = rs0 * originalWidth + sy * (-originalHeight) + y; x4 = rs1 * (-originalHeight) + x; y4 = sy * (-originalHeight) + y; } x1 *= scale; y1 *= scale; x2 *= scale; y2 *= scale; x3 *= scale; y3 *= scale; x4 *= scale; y4 *= scale; } public static class XAnimationFrames { private ArrayList<XSingleFrame> frames_array = new ArrayList<XSingleFrame>(); private int size; public void addFrame(XSingleFrame singleFrame) { frames_array.add(singleFrame); ++size; } } }