Pattern/Enemy Script, How To?
10 posts
• Page 1 of 1
Pattern/Enemy Script, How To?
I was wondering how all you guys create your patterns and shooting scripts for enemies?
Im thinking something along the lines of Danmakufu that uses scripts, so a script might contain something like:
ring(20,10,0,false,0) fire ring of 20 shots, 10 times, no angle mod, dont change num, no num mod
arc(10,10,p,0,true,1) fire arc of 10 shots, target player, 0 ang mod, do reduce num each round, reduce num by one
my main question is how do you go about having these in a text file and parsing them to your game? i need lots and lots, each to be chosen randomly(ish) do i store them all as some kind of object?
Thanks guys
Im thinking something along the lines of Danmakufu that uses scripts, so a script might contain something like:
ring(20,10,0,false,0) fire ring of 20 shots, 10 times, no angle mod, dont change num, no num mod
arc(10,10,p,0,true,1) fire arc of 10 shots, target player, 0 ang mod, do reduce num each round, reduce num by one
my main question is how do you go about having these in a text file and parsing them to your game? i need lots and lots, each to be chosen randomly(ish) do i store them all as some kind of object?
Thanks guys

Re: Pattern/Enemy Script, How To?
To answer your initial question, I store everything in XML documents and parse them with TinyXML-2.
You might want to start by doing everything in code instead of trying to parse external data files. You'll need to create game logic and data structures (or classes) anyway so you might as well start there.
You might want to start by doing everything in code instead of trying to parse external data files. You'll need to create game logic and data structures (or classes) anyway so you might as well start there.

Re: Pattern/Enemy Script, How To?
Thanks for the link, you use case statements or something when parsing the XML?
Like
I have got the classes done in various prototypes, im copying them over and recoding them at the moment
Im looking for info on doing this so once ive redone my renderer and mesh generators i can implement some patterns since i have the triggers ready for the AI now
What sort of base types do you have for your patterns/scripts?
Like
- Code: Select all
switch(type) {
case shot.ring:
case shot.spiral;
..etc
}
I have got the classes done in various prototypes, im copying them over and recoding them at the moment
Im looking for info on doing this so once ive redone my renderer and mesh generators i can implement some patterns since i have the triggers ready for the AI now
What sort of base types do you have for your patterns/scripts?
Re: Pattern/Enemy Script, How To?
You can't do it that way in C or C++, unfortunately.
While you can do a bunch of string compares, what I do is compute the hash of the type string and do a switch based on that. I use FNV-1a on my project because it's simple but you can use CRC32 or other hash functions. I made a little program that takes its input and spits out the hash value in hexadecimal with the original string as a comment. I end up with a bunch of stuff that looks like this:
I don't do particularly complex shot patterns or bullet movements, mostly just bursts and spreads with projectiles moving in straight lines. Weapons support action scripting with wait, repeat, recoil, flash, ordnance, cue, and loop commands. Ordnance doesn't support actions yet since I never had a need. Here's the entire XML document for a burst-firing player weapon (with "playerbombbullet" and "playerweaponflash" being separate documents):
While you can do a bunch of string compares, what I do is compute the hash of the type string and do a switch based on that. I use FNV-1a on my project because it's simple but you can use CRC32 or other hash functions. I made a little program that takes its input and spits out the hash value in hexadecimal with the original string as a comment. I end up with a bunch of stuff that looks like this:
- Code: Select all
// process child elements
for (const tinyxml2::XMLElement *child = element->FirstChildElement(); child != NULL; child = child->NextSiblingElement())
{
switch (Hash(child->Value()))
{
case 0x14c8d3ca /* "offset" */:
...
case 0xcab7a341 /* "scatter" */:
...
case 0xca04efe0 /* "inherit" */:
...
case 0x32741c32 /* "velocity" */:
...
case 0x0dd0b0be /* "variance" */:
...
case 0x3a224d98 /* "spawn" */:
...
}
}
I don't do particularly complex shot patterns or bullet movements, mostly just bursts and spreads with projectiles moving in straight lines. Weapons support action scripting with wait, repeat, recoil, flash, ordnance, cue, and loop commands. Ordnance doesn't support actions yet since I never had a need. Here's the entire XML document for a burst-firing player weapon (with "playerbombbullet" and "playerweaponflash" being separate documents):
- Code: Select all
<?xml version="1.0" ?>
<template name="playershipweapon3">
<weapon>
<action>
<ordnance name="playerbombbullet">
<position x="6" y="0" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="6" y="-1"/>
</flash>
<ordnance name="playerbombbullet">
<position x="-6" y="0" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="-6" y="-1"/>
</flash>
<ordnance name="playerbullet">
<position x="2" y="2" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="2" y="2" angle="0"/>
</flash>
<ordnance name="playerbullet">
<position x="-2" y="2" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="-2" y="2" angle="0"/>
</flash>
<cue name="fire"/>
<wait value="0.05"/>
<ordnance name="playerbombbullet">
<position x="6" y="-1" angle="-5"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="6" y="-1"/>
</flash>
<ordnance name="playerbombbullet">
<position x="-6" y="-1" angle="5"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="-6" y="-1"/>
</flash>
<ordnance name="playerbullet">
<position x="2" y="2" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="2" y="2" angle="0"/>
</flash>
<ordnance name="playerbullet">
<position x="-2" y="2" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="-2" y="2" angle="0"/>
</flash>
<cue name="fire"/>
<wait value="0.05"/>
<ordnance name="playerbombbullet">
<position x="6" y="-1" angle="-10"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="6" y="-1"/>
</flash>
<ordnance name="playerbombbullet">
<position x="-6" y="-1" angle="10"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="-6" y="-1"/>
</flash>
<ordnance name="playerbullet">
<position x="2" y="2" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="2" y="2" angle="0"/>
</flash>
<ordnance name="playerbullet">
<position x="-2" y="2" angle="0"/>
<velocity x="0" y="480"/>
</ordnance>
<flash name="playerweaponflash">
<position x="-2" y="2" angle="0"/>
</flash>
<cue name="fire"/>
<wait value="0.05"/>
</action>
</weapon>
<sound volume="0.25">
<file name="robotron-playershot.wav" />
</sound>
<soundcue>
<cue name="fire" sound="playershipweapon3" />
</soundcue>
</template>
Re: Pattern/Enemy Script, How To?
If you want to go the hash route, here's the functions I use. The string one is case-insensitive though you don't have to do it that way.
FNV-1a has the nice property that you can use the hash of a string as the seed for another hash and get the hash of the concatenated strings; Hash(".bar", Hash("foo")) produces the same result as Hash("foo.bar"). That can occasionally be useful.
(It also doesn't need any lookup tables the way most implementations of CRC32 do; it works a lot like a linear congruential random number generator so it's the kind of thing you could write down on a cocktail napkin.)
- Code: Select all
// fnv-1a hash
inline unsigned int Hash(const unsigned char byte, unsigned int hash = 2166136261u)
{
hash ^= byte;
hash *= 16777619u;
return hash;
}
inline unsigned int Hash(const void *data, size_t len, unsigned int hash = 2166136261u)
{
const unsigned char * d = static_cast<const unsigned char *>(data);
const unsigned char * const e = d + len;
while (d < e)
hash = Hash(*d++, hash);
return hash;
}
inline unsigned int Hash(const char *string, unsigned int hash = 2166136261u)
{
if (string == 0)
return 0;
for (const char *s = string; *s != 0; ++s)
hash = Hash(unsigned char(tolower(*s)), hash);
return hash;
}
FNV-1a has the nice property that you can use the hash of a string as the seed for another hash and get the hash of the concatenated strings; Hash(".bar", Hash("foo")) produces the same result as Hash("foo.bar"). That can occasionally be useful.
(It also doesn't need any lookup tables the way most implementations of CRC32 do; it works a lot like a linear congruential random number generator so it's the kind of thing you could write down on a cocktail napkin.)
Re: Pattern/Enemy Script, How To?
thanks for this VERY useful info, i tried looking at converting a string to hex values, i cant seem to get it formatted like yours so i decided to maybe use the string hashcodes instead? (java seems to have a DataType.getHashcode() method that returns an int)
unfortunately im still getting my renderer to work when generating ships, ive just finished the bullet managers classes. This xml stuff is going to link in with that and the 'behaviors' which are up next
unfortunately im still getting my renderer to work when generating ships, ive just finished the bullet managers classes. This xml stuff is going to link in with that and the 'behaviors' which are up next

Re: Pattern/Enemy Script, How To?
I wrote a program to do it since I use those hexcodes everywhere. I set it as an external tool in the IDE that takes the selected text as input, runs the program, dumps result to the Output pane. I can then copy and paste it from there.
- Code: Select all
int main(int argc, const char* argv[])
{
for (int i = 1; i < argc; i++)
{
printf("%s0x%08x /* \"%s\" */", i > 1 ? "\n" : "", Hash(argv[i]), argv[i]);
}
return 0;
}
Re: Pattern/Enemy Script, How To?
we dont have that magic Hash() function in java, ive tried suggestions from here http://stackoverflow.com/questions/4159 ... sh-in-java but they return values like fade44533c5ef08184c96d779853d545 for "enemyshot"
i dont want to add LOTS of code for this, since ideally itd be a nice little class like yours, any suggestions?
edit//
completely missed your hash() function this time round, trying again and ill report back
edit2//
any chance you can post the rough java equivalent to your Hash() methods? no idea what half of it means
edit3//
using the following:
your examples
case 0x14c8d3ca /* "offset" */:
case 0xcab7a341 /* "scatter" */:
case 0xca04efe0 /* "inherit" */:
case 0x32741c32 /* "velocity" */:
case 0x0dd0b0be /* "variance" */:
case 0x3a224d98 /* "spawn" */:
become:
offset - c3376493
scatter - 71e9c6be
inherit - 740c90fb
velocity - 7f363cdd
variance - b584fe71
spawn - 688f37b
might this do for 3 lines of code??
i dont want to add LOTS of code for this, since ideally itd be a nice little class like yours, any suggestions?
edit//
completely missed your hash() function this time round, trying again and ill report back

edit2//
any chance you can post the rough java equivalent to your Hash() methods? no idea what half of it means

edit3//
using the following:
- Code: Select all
String ss = "offset";
int h = ss.hashCode();
System.out.println(ss + " - " + Integer.toHexString(h));
your examples
case 0x14c8d3ca /* "offset" */:
case 0xcab7a341 /* "scatter" */:
case 0xca04efe0 /* "inherit" */:
case 0x32741c32 /* "velocity" */:
case 0x0dd0b0be /* "variance" */:
case 0x3a224d98 /* "spawn" */:
become:
offset - c3376493
scatter - 71e9c6be
inherit - 740c90fb
velocity - 7f363cdd
variance - b584fe71
spawn - 688f37b
might this do for 3 lines of code??
- berilium
-
- Posts: 6
- Joined: Fri Jul 27, 2012 12:30 am
- Location: Blasting off and striking the evil Bydo empire!
Re: Pattern/Enemy Script, How To?
Hi
Wikipedia has an article about fnv-1 hash with some pseudocode. It might help?
http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash
I think Java's hashCode() is enough. You want unique hashes and the function fast enough for your requirements. It doesn't matter if the hashes are different from kdmiller3's ones.
XYX wrote:edit2//
any chance you can post the rough java equivalent to your Hash() methods? no idea what half of it means
Wikipedia has an article about fnv-1 hash with some pseudocode. It might help?
http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash
I think Java's hashCode() is enough. You want unique hashes and the function fast enough for your requirements. It doesn't matter if the hashes are different from kdmiller3's ones.
Re: Pattern/Enemy Script, How To?
I haven't worked with Java enough to provide a working Java implementation, but I can at least explain what it's doing.
Start with a seed hash value (unsigned integer 2166136261 by default)
For each byte of the input:
Java doesn't have unsigned types so FNV-1a is tricky to implement; you'd need to use 64-bit integers (long) and mask off the low 32 bits (& 0xFFFFFFFF) each time. When it comes down to it, the concept is what matters, not the actual hash function you use. Java's string type hashCode function should be perfectly adequate.
Start with a seed hash value (unsigned integer 2166136261 by default)
For each byte of the input:
- exclusive-or the hash value with the input byte
- multiply the hash value by unsigned integer 16777619
Java doesn't have unsigned types so FNV-1a is tricky to implement; you'd need to use 64-bit integers (long) and mask off the low 32 bits (& 0xFFFFFFFF) each time. When it comes down to it, the concept is what matters, not the actual hash function you use. Java's string type hashCode function should be perfectly adequate.
10 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest