开发者

Compile XML into Java

开发者 https://www.devze.com 2023-04-10 18:06 出处:网络
I have a hard task here. I\'m thinking of building a simple game, and in this game I\'m going to apply a buff system (read here for more information).

I have a hard task here. I'm thinking of building a simple game, and in this game I'm going to apply a buff system (read here for more information).

So, let's say I want to create a buff:

<buff name="Life Steal">
  <afterAttack>
    <heal target="attacker">$damage$ * 0.2</heal>`
  </afterAttack>
</buff>

This, in thesis, would generate the following output:

public class Life_Steal extends Buff {

    @Override
    public void afterAttack(Object attacker, Object defender, int damageDone) {
        heal(attacker, damageDone * 0.2);
    }
}

Is this possible? If so, is there any tool out there that enables me to do something like that?


EDIT

I found out that mixing Javascript and XML would be a good way to go for it.

<buff name="Life Steal>
  <onattach>
    <javascript>
      attacker.hp += damage * 0.2;
    </javascript>
 开发者_如何学运维 </onattach>
</buff>

That's the best solution I could think of. Anyone have a better one?


I don't condone this project, but it is along the lines of what you are doing. Jelly - Executable XML. The most painless way to load XML is JAXB.

That said, a real scripting language would be a much better choice.

  1. Javascript is included as a scripting engine language by default ( Rhino )
  2. Lua is a good choice as a dedicated embedded scripting language
  3. Jython is very popular
  4. JRuby is available as well

In any case read Scripting for the Java Platform and Java Scripting Programmers Guide before you go any further.

If you just have to use XML for some bizarre reason, a mixture of JAXB with scripting imbedded in the XML might be another way to go.


I think you could probably get quite a long way with XSLT. The free-form expressions inside, for example, the <heal> element might be tricky.

In general, it's a pretty simple problem. Grab a parser - I'd recommend a SAX or StAX parser rather than a DOM parser - and output appropriate Java code for each element/attribute you encounter. Using something like Javassist you could even compile that code straight into bytecode without having to output the source to disk and invoke the compiler separately.


IMO your best bet is to implement stuff like this using a DSL, or just use a more dynamic language like JRuby or Groovy for these pieces, even if the rest of the system is in Java.


Take a look at Apache Jelly. This is the closest fit I can think of to what you're asking for (which I presume is allowing non coders to create game content).


This seems like you really yearn to program in xml, which is really gonna be a pain (imho) when you have a hundred or thousand of these. However, there is definitely some configuration here, that you could dump into xml so your xml gets processed into a Buff object graph and you have an attack method that takes vararg set of buffs.

Then you can keep the algorithm in java, but do all the nerfing in xml.

update to try and answer the question with code -

If I were going to recommend a technique for this, I would say you can probably leave your xml alone and use a JAXB parser, which I think is packaged with a later jvm.

// java like pseudocode.
JAXBContext.newInstance(Buff.class);
Unmarshaller u = ctx.createUnmarshaller()
List<Buff> buffs = u.unmarshal(loadedXmlFile)

now you can use your buff configurations and read them type safely as configuration.


consider not using xml and maybe something like:

import java.util.*;
enum Stats {
    health, mana
}
class Character {
    EnumMap<Stats, Integer> stats = new EnumMap<Stats, Integer>(Stats.class) {
        {
            for (Stats stat : Stats.values())
                put(stat, 10);
        }
    };
    int getStat(Stats stat) {
        int value = stats.get(stat);
        List<Buff> timedOut = new LinkedList<Buff>();
        for (Buff buff : buffs)
            if (System.currentTimeMillis() - buff.t0 > buff.duration) timedOut.add(buff);
            else if (buff.stat.equals(stat)) value += buff.value;
        buffs.removeAll(timedOut);
        return value;
    }
    List<Buff> buffs = new LinkedList<Buff>();
}
class Buff {
    Buff(Stats stat, int value, int duration) {
        this.stat = stat;
        this.value = value;
        this.duration = duration;
    }
    final Stats stat;
    final int value;
    final int duration;
    final long t0 = System.currentTimeMillis();
}
public class Main {
    public static void main(String[] args) throws Exception {
        Character character = new Character();
        character.buffs.add(new Buff(Stats.health,1,1000));
        System.out.println(character.getStat(Stats.health));
        Thread.sleep(2000);
        System.out.println(character.getStat(Stats.health));
    }
}


If you only want to support limited expressive power in your expressions, using XPath expressions embedded in XML is a good choice and the simplest way to evaluate them is to transform the XML into XSLT.

If you want to support richer algorithmic power, then use a fully-featured programming language instead of inventing your own.


Although XStream may be used to parse XML, you better stick with a language scripting.

0

精彩评论

暂无评论...
验证码 换一张
取 消