2D Shooter Weapons/Projectiles

Started by
19 comments, last by Sean_Seanston 14 years, 1 month ago
Right, so I'm making a vertical shooter like SWIV or Xevious and I'm currently trying to implement the shooting system. I figured I'd have a Projectile class to represent the individual projectiles with their speed/collision boxes etc. and a Weapon class to cover firing rate, damage and management of Projectiles. It's my first time doing something like this but it seems like that system should work for my purposes for now. What I'm wondering is, let's say I assign a Weapon to a Plane or some such. The Weapon will need to spawn Projectiles at some point on the Plane and in order to look right it'll need to spawn at a point (or points) appropriate to that specific Plane. Now it's probably not too important, I could probably just make each Weapon intended for a specific Plane and cause it to appear at an appropriate position for that Plane and things would work fine. But if I wanted to make it so assigning any Weapon to any Plane causes it to appear right, how should I go about that? Clearly, it would require the Plane to have some sort of... weapon attachment point data but what might be a good way to do that? Let's assume we have 2 different kinds of weapon, Missiles and Guns. Maybe the Gun shoots from the front by default and then later if receiving some form of upgrade it might shoot from points at each side also. Then Missiles then might alternate between points at each side. So the Gun spawns from a point and later has 2 extra points added to the points it's using. Missiles stick to 2 specific points but alternate between them. So, would a logical means of implementing this be to give each Plane a vector/list/whatever of WeaponPoints and then each Weapon would be assigned to a number of these as part of some kind of initialization procedure with each Weapon also having a list of pointers to the Plane's WeaponPoints. In addition, there has to be a means of deciding what set of assigned points are used at any particular time in order to implement an alternating system as described where maybe there are even 2 points on each side and each firing causes 1 side's points to fire. I suppose that could be done with some form of logic inside the Weapon class. Thoughts? Does that system sound like it makes sense or am I going in the wrong direction?
Advertisement
Sounds like a perfectly reasonable idea, certainly the use of atatchment points is probably the way to go. How complicated you make them is entirly up to you. I'm probably just rephrasing what you said now but:

Give each weapon type (such as missiles/blasters) an identifier (enumes). Give each attachment point a list of weapon types it can accept. The order can show its preference (if missiles comes before blasters then first it should try to fit missiles there). If the weapon type is not int he list then it cannot accept it.

If you have 2 pairs of attachment points, one on the wing tips that has priority blasters, missiles and another pair on close to the ships hull with priority missiles, blasters then when you come to add a weapon it should do somehting like:

Add weapon (type missile).
check all open atachment points, priority 1 types. If any match the current weapon type (missile) then attach it and your finished.
Otherwise, check priority 2 weapon types, then 3 then 4 (untill you run out)

That way adding a blaster and missile launcher will always go in the right slot regardless of the order they are added but your still free to add multiple launchers or blasters or any other type.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Quote:Original post by Sean_Seanston
Does that system sound like it makes sense

Yes, but the devil is in the details. Just give it a try. What do you have to lose?
That sounds like it should work. Just be sure to account for the changing position of the plane. Will the attachment points' coordinates be relative to the location of the plane? If so, the location will have to be turned into global coordinates when projectiles are fired, probably by the weapon class, which would have to have access to its parent Plane. Otherwise, the Weapon will have to hold its attachment/spawning points by pointer or reference, and rely on the Plane or whatever to update them every time it moves.
Yeah, I'll give it a go, thanks all.

Quote:Original post by Nanoha
Give each weapon type (such as missiles/blasters) an identifier (enumes). Give each attachment point a list of weapon types it can accept.
...
If you have 2 pairs of attachment points, one on the wing tips that has priority blasters, missiles and another pair on close to the ships hull with priority missiles, blasters then when you come to add a weapon it should do somehting like:

Add weapon (type missile).
check all open atachment points, priority 1 types. If any match the current weapon type (missile) then attach it and your finished.
Otherwise, check priority 2 weapon types, then 3 then 4 (untill you run out)


I'd thought about this briefly. I was thinking would it be better to have attachment types for different weapons or just have 1 type of attachment and then trust that I would just put them on correctly. I figured probably just that. However, now that you mention it, you may have a good idea there... one thing to consider would be starting off with a single gun shooting out the nose of the plane and then upgrading that with 1 more on each side. I suppose I could just specify what nodes the gun upgrades to but yours might be a more automated and efficient system if you get it working.

Maybe just specify what weapon is the only 1 that can fill a slot would be best for my purposes. I'll see.

Quote:Original post by theOcelot
Will the attachment points' coordinates be relative to the location of the plane?


Yeah, that was the idea. Have them relative to the centre of the plane.

Quote:Original post by theOcelot
If so, the location will have to be turned into global coordinates when projectiles are fired, probably by the weapon class, which would have to have access to its parent Plane.


I was thinking along the lines of, every time the Plane moves it lets the Weapon know it moved. Although, what about a simple pointer to the parent and then getX() and getY()?
One other factor I'm thinking of is alternating fire. What I mean is, having something like a missile firing from the left and then the next one firing from the right and having it loop like that.

Should I perhaps just have an "alternating" flag loaded from the XML description of the weapon, or is there a better way? Some sort of scripting language would probably be ideal but that's not happening right now.

Maybe it would be good to have some "order of fire" system? Indeed maybe I could do it so each point had an order number meaning something like firing from 2 points and then another 2 points would be easy by giving each pair a different shared number.

Does that sound overly specific? Maybe I'm trying to push standalone XML too far.

EDIT: Also, I'll only need to use the WeaponPoint class to store info that the Weapon will need to query so should I just use getter functions to return those values or is there a less long-winded way? Should they even really be private? They seem like they should, the positions certainly wouldn't want to be changed by accident but I've often seen people seem to prefer making small classes like this into structs with no private specifier.

[Edited by - Sean_Seanston on March 1, 2010 8:01:34 AM]
What exactly is that 'Plane' that you're talking about? Is it a plane in the sense of parallax scrolling? So all bullets are drawn on the foreground plane?


Either way, here's some ideas for you to think about: a projectile has a type (bullet, missile, etc.), a position, a velocity - possibly a target object or position. Each type has a damage value, a collision range/size, perhaps a damage type. How about modeling this as two classes: a ProjectileType and a Projectile class?

The same can be done for weapons: a WeaponType class has a reference/pointer to a ProjectileType object (that's what it initializes it's Projectiles with) and perhaps some other data such as weapon price, weight, rate of fire, etc. Each Weapon object then gets a reference/pointer to the WeaponType object that represents it's type. A Weapon also contains a position, direction, cooldown timer, and so on.


Then, on top of that, you have an upgrade system. This is simply a list of weapon objects tied to a weapon level. For example, the blaster fires straight forwards at level 1, but at level 2, also fires shots sidewards. So, for level 1, you store one Weapon object with it's direction straight forwards, and a reference to the blaster WeaponType object. For level 2, you store 3 Weapon objects: one firing straight forwards, the others sidewards. You could encapsulate this into a WeaponSystem class - which could keep track of what Weapon needs to fire next. For example, it could cycle through it's list of Weapons based on their cooldown timers divided by the number of weapons.

As for weapon slots, they can store a list of accepted WeaponType references. As for weapon types, you could store them in a dictionary, linking them to strings. This allows easy name/type lookup. As for firing projectiles, a Weapon will need a reference/pointer to the object that manages the bullets, so it can push Projectiles into it whenever it fires.


Of course, you can create all these type objects based on a xml file (or any other kind of input source). These classes themselves don't need to know about that though - you simply write some xml-parsing code that creates these objects based on the xml content.
Create-ivity - a game development blog Mouseover for more information.
Quote:Original post by Captain P
What exactly is that 'Plane' that you're talking about? Is it a plane in the sense of parallax scrolling? So all bullets are drawn on the foreground plane?


Just a fighter plane used by the player or AI etc.

Quote:Original post by Captain PEither way, here's some ideas for you to think about: a projectile has a type (bullet, missile, etc.), a position, a velocity - possibly a target object or position. Each type has a damage value, a collision range/size, perhaps a damage type. How about modeling this as two classes: a ProjectileType and a Projectile class?


Yes, what I've planned so far is to make a Projectile class and implement something like the ProjectileType you've suggested by using XML. So I'll have different types of Projectile with some unique identifiers that have different damage values etc. and read them into the Projectile class. Hopefully it'll all work ok.

Quote:Original post by Captain PThe same can be done for weapons: a WeaponType class has a reference/pointer to a ProjectileType object (that's what it initializes it's Projectiles with) and perhaps some other data such as weapon price, weight, rate of fire, etc. Each Weapon object then gets a reference/pointer to the WeaponType object that represents it's type. A Weapon also contains a position, direction, cooldown timer, and so on.


Now that you mention it though, you've brought up something I hadn't exactly thought of. Obviously I can't load from XML for each Projectile that's spawned by the Weapon so then I'm going to need somewhere to store the info that's been read in once. That'll need something along the lines of the ProjectileType class you're talking about. Or I could just give the Weapon a static Projectile object called ProjectileBase or something and use that to copy values into every spawned Projectile. That would work too I suppose.

Quote:Original post by Captain P
As for firing projectiles, a Weapon will need a reference/pointer to the object that manages the bullets, so it can push Projectiles into it whenever it fires.


Speaking of that, I'd intended the Weapon class to manage its associated projectiles itself. Is that particularly bad? Should be a passable solution anyway, right?
Quote:Original post by Sean_Seanston
I was thinking along the lines of, every time the Plane moves it lets the Weapon know it moved. Although, what about a simple pointer to the parent and then getX() and getY()?

I like the idea of a pointer to the parent better. That way, the Plane doesn't have to keep track of which weapons are attached to it, or at least it doesn't have to mess with them a lot. And grabbing the coords of attachment points shouldn't be too hard for Weapon.

Maybe weapon points could be referred to by indices into an array/vector of attachment points in the Plane. Then, in Weapon, they could be gotten like this: plane->WeaponPoint(point_index).GetX/Y(). As long as the accessor returns by const reference, there should be little danger of either performance or other issues. I digress...

Speaking of Weapon points, do they need to be a different class from your generic point at all?
Quote:One other factor I'm thinking of is alternating fire. What I mean is, having something like a missile firing from the left and then the next one firing from the right and having it loop like that.

All your ideas on this one sound fine, but isn't that a separate concern that only Weapon needs to worry about? Of course weapons will have a lot of variety in how multiple attachment points are treated or even supported. But if you've already got it loading from XML, that's probably not too hard.
Quote:I'd intended the Weapon class to manage its associated projectiles itself. Is that particularly bad? Should be a passable solution anyway, right?

As long as Weapons are prepared to store and process an arbitrarily large number of projectiles, collide them against all other Planes, and manage their lifetimes. To do everything they need to, they'll still need access to the game world, but maybe sectioning off the projectiles from each Weapon will have some other benefit.
Quote:Original post by Sean_Seanston
Just a fighter plane used by the player or AI etc.

Ah, of course. I was thinking more towards planes in the mathematical sense. :)

Quote:Or I could just give the Weapon a static Projectile object called ProjectileBase or something and use that to copy values into every spawned Projectile. That would work too I suppose.

It'll work too, yes, but it'll make Projectile objects a bit bulkier. What I proposed is sometimes called the flyweight pattern - common data that's shared between multiple objects is put in another object that's being referenced. In fact, some languages do this for classes: the class definition is an object itself, which is used as a blueprint to create actual instances. :)

Using a static object means that there's only one that's shared between all Weapon instances. Doesn't sound like a good idea, since you want multiple weapon and projectile types.

Quote:Speaking of that, I'd intended the Weapon class to manage its associated projectiles itself. Is that particularly bad? Should be a passable solution anyway, right?

Could work, but that will result in a number of different bullet lists that all need to be checked. I'd keep it in a central place, considering that you need to check bullets against enemies and such. I find it cleaner: weapons are projectile generators, while the world manages them. I think Command & Conquer: Tiberian Sun made it's units manage their projectiles. Destroying a unit would also remove it's projectiles, heh. :)


As for attaching weapons to a plane, I'd keep weapon positions relative to their parent (plane). When you update a plane, make it update the weapons it has. Giving them a pointer to their plane for position checks would be fine for that purpose. It's a hierarchy of objects.
Create-ivity - a game development blog Mouseover for more information.

This topic is closed to new replies.

Advertisement