/** * Copyright (c) 2001-2017 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/epl-v10.html */ package net.sf.robocode.battle.snapshot; import net.sf.robocode.battle.peer.BulletPeer; import net.sf.robocode.battle.peer.ExplosionPeer; import net.sf.robocode.battle.peer.RobotPeer; import net.sf.robocode.peer.ExecCommands; import net.sf.robocode.serialization.IXmlSerializable; import net.sf.robocode.serialization.XmlReader; import net.sf.robocode.serialization.SerializableOptions; import net.sf.robocode.serialization.XmlWriter; import robocode.control.snapshot.BulletState; import robocode.control.snapshot.IBulletSnapshot; import java.io.IOException; /** * A snapshot of a bullet at a specific time instant in a battle. * The snapshot contains a snapshot of the bullet data at that specific time. * * @author Flemming N. Larsen (original) * @author Pavel Savara (contributor) * * @since 1.6.1 */ final class BulletSnapshot implements java.io.Serializable, IXmlSerializable, IBulletSnapshot { private static final long serialVersionUID = 2L; /** The bullet state */ private BulletState state; /** The bullet power */ private double power; /** The x position */ private double x; /** The y position */ private double y; /** The x painting position (due to offset on robot when bullet hits a robot) */ private double paintX; /** The y painting position (due to offset on robot when bullet hits a robot) */ private double paintY; /** The ARGB color of the bullet */ private int color = ExecCommands.defaultBulletColor; /** The current frame number to display, i.e. when the bullet explodes */ private int frame; /** Flag specifying if this bullet has turned into an explosion */ private boolean isExplosion; /** Index to which explosion image that must be rendered */ private int explosionImageIndex; private int bulletId; private int victimIndex = -1; private int ownerIndex; private double heading; /** * Creates a snapshot of a bullet that must be filled out with data later. */ public BulletSnapshot() { state = BulletState.INACTIVE; ownerIndex = -1; victimIndex = -1; explosionImageIndex = -1; heading = Double.NaN; power = Double.NaN; } /** * Creates a snapshot of a bullet. * * @param bullet the bullet to make a snapshot of. */ BulletSnapshot(BulletPeer bullet) { state = bullet.getState(); power = bullet.getPower(); x = bullet.getX(); y = bullet.getY(); paintX = bullet.getPaintX(); paintY = bullet.getPaintY(); color = bullet.getColor(); frame = bullet.getFrame(); isExplosion = (bullet instanceof ExplosionPeer); explosionImageIndex = bullet.getExplosionImageIndex(); bulletId = bullet.getBulletId(); final RobotPeer victim = bullet.getVictim(); if (victim != null) { victimIndex = victim.getRobotIndex(); } ownerIndex = bullet.getOwner().getRobotIndex(); heading = bullet.getHeading(); } @Override public String toString() { return ownerIndex + "-" + bulletId + " (" + (int) power + ") X" + (int) x + " Y" + (int) y + " " + state.toString(); } /** * {@inheritDoc} */ public int getBulletId() { return bulletId; } /** * {@inheritDoc} */ public BulletState getState() { return state; } /** * {@inheritDoc} */ public double getPower() { return power; } /** * {@inheritDoc} */ public double getX() { return x; } /** * {@inheritDoc} */ public double getY() { return y; } /** * {@inheritDoc} */ public double getPaintX() { return paintX; } /** * {@inheritDoc} */ public double getPaintY() { return paintY; } /** * {@inheritDoc} */ public int getColor() { return color; } /** * {@inheritDoc} */ public int getFrame() { return frame; } /** * {@inheritDoc} */ public boolean isExplosion() { return isExplosion; } /** * {@inheritDoc} */ public int getExplosionImageIndex() { return explosionImageIndex; } /** * {@inheritDoc} */ public double getHeading() { return heading; } /** * {@inheritDoc} */ public int getVictimIndex() { return victimIndex; } /** * {@inheritDoc} */ public int getOwnerIndex() { return ownerIndex; } /** * {@inheritDoc} */ public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { writer.startElement(options.shortAttributes ? "b" : "bullet"); { writer.writeAttribute("id", ownerIndex + "-" + bulletId); if (!options.skipExploded || state != BulletState.MOVING) { writer.writeAttribute(options.shortAttributes ? "s" : "state", state.toString()); writer.writeAttribute(options.shortAttributes ? "p" : "power", power, options.trimPrecision); } if (state == BulletState.HIT_VICTIM) { writer.writeAttribute(options.shortAttributes ? "v" : "victim", victimIndex); } if (state == BulletState.FIRED) { writer.writeAttribute(options.shortAttributes ? "o" : "owner", ownerIndex); writer.writeAttribute(options.shortAttributes ? "h" : "heading", heading, options.trimPrecision); } writer.writeAttribute("x", paintX, options.trimPrecision); writer.writeAttribute("y", paintY, options.trimPrecision); if (!options.skipNames) { if (color != ExecCommands.defaultBulletColor) { writer.writeAttribute(options.shortAttributes ? "c" : "color", Integer.toHexString(color).toUpperCase()); } } if (!options.skipExploded) { if (frame != 0) { writer.writeAttribute("frame", frame); } if (isExplosion) { writer.writeAttribute("isExplosion", true); writer.writeAttribute("explosion", explosionImageIndex); } } if (!options.skipVersion) { writer.writeAttribute("ver", serialVersionUID); } } writer.endElement(); } /** * {@inheritDoc} */ public XmlReader.Element readXml(XmlReader reader) { return reader.expect("bullet", "b", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final BulletSnapshot snapshot = new BulletSnapshot(); reader.expect("id", new XmlReader.Attribute() { public void read(String value) { String[] parts = value.split("-"); snapshot.ownerIndex = Integer.parseInt(parts[0]); snapshot.bulletId = Integer.parseInt(parts[1]); } }); reader.expect("state", "s", new XmlReader.Attribute() { public void read(String value) { snapshot.state = BulletState.valueOf(value); } }); reader.expect("power", "p", new XmlReader.Attribute() { public void read(String value) { snapshot.power = Double.parseDouble(value); } }); reader.expect("heading", "h", new XmlReader.Attribute() { public void read(String value) { snapshot.heading = Double.parseDouble(value); } }); reader.expect("victim", "v", new XmlReader.Attribute() { public void read(String value) { snapshot.victimIndex = Integer.parseInt(value); } }); reader.expect("owner", "o", new XmlReader.Attribute() { public void read(String value) { snapshot.ownerIndex = Integer.parseInt(value); } }); reader.expect("x", new XmlReader.Attribute() { public void read(String value) { snapshot.x = Double.parseDouble(value); snapshot.paintX = snapshot.x; } }); reader.expect("y", new XmlReader.Attribute() { public void read(String value) { snapshot.y = Double.parseDouble(value); snapshot.paintY = snapshot.y; } }); reader.expect("color", "c", new XmlReader.Attribute() { public void read(String value) { snapshot.color = Long.valueOf(value.toUpperCase(), 16).intValue(); } }); reader.expect("isExplosion", new XmlReader.Attribute() { public void read(String value) { snapshot.isExplosion = Boolean.parseBoolean(value); if (snapshot.isExplosion && snapshot.state == null) { snapshot.state = BulletState.EXPLODED; } } }); reader.expect("explosion", new XmlReader.Attribute() { public void read(String value) { snapshot.explosionImageIndex = Integer.parseInt(value); } }); reader.expect("frame", new XmlReader.Attribute() { public void read(String value) { snapshot.frame = Integer.parseInt(value); } }); return snapshot; } }); } }