Sign in to follow this  

2D Shooter Weapons/Projectiles

This topic is 2840 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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()?

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by theOcelot
Speaking of Weapon points, do they need to be a different class from your generic point at all?


Well apart from the basic X and Y I have 1 or 2 other variables that seem to make sense being there for what I have planned.

Quote:
Original post by theOcelot
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.


I suppose it probably would be best for the Weapon to deal with it... I'll have to see how to implement it that way though. It'll need some way of associating a point's unique ID with a firing order. I suppose it was always going to need to include some info on the points to use anyway so I'll just add something to that.

Quote:
Original post by Captain P
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.


Yeah... I'll have to look into this. I'd thought of making Weapon an abstract base class but I haven't entirely decided yet. I suppose I could probably use XML to make the differences between the weapons. I might use that Type idea.

Quote:
Original post by Captain P
I think Command & Conquer: Tiberian Sun made it's units manage their projectiles. Destroying a unit would also remove it's projectiles, heh. :)


Yeah, good point. How might you go about managing Projectiles then? A set of static functions in the Projectile class maybe? With 1 vector/list of Projectiles for all projectiles that exist.

However, then I suppose I'd need more data in the Projectile class to say who the Projectile belongs to or at least what team it's on. How would you manage that? You could have different lists maybe but then we're kind of at square one again.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sean_Seanston
I suppose it probably would be best for the Weapon to deal with it... I'll have to see how to implement it that way though. It'll need some way of associating a point's unique ID with a firing order. I suppose it was always going to need to include some info on the points to use anyway so I'll just add something to that.


I'm confused about this firing order thing. Surely you don't plan on having repeated weapon firings cycle through all occupied weapon points, and therefore all installed weapons? I'd think you would just have an active weapon, direct all firing notifications to it, and let it worry about which of its firing points to use.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sean_Seanston
Yeah, good point. How might you go about managing Projectiles then? A set of static functions in the Projectile class maybe? With 1 vector/list of Projectiles for all projectiles that exist.

Nope, no static functions - no need to go for a 'global' approach. If you have an object that manages all bullets, enemies and player(s) - say, an instance of a World class - then give every Weapon a reference/pointer to that object. They can then tell the world that they want to add some bullets. The world provides a function for this, addProjectile(...), and stores the given projectiles in it's player bullet list. The weapons then only need to care about creating projectiles whenever they receive a fire command 'from above' (e.g. the weapon system that contains them, or the plane itself).

Quote:
However, then I suppose I'd need more data in the Projectile class to say who the Projectile belongs to or at least what team it's on. How would you manage that? You could have different lists maybe but then we're kind of at square one again.

For a game like this, with relatively few different groups, I'd just keep a list of player projectiles, a list of enemy projectiles, a list of enemies and a player. It's not very scalable, but this kind of game doesn't really need that - unless you have some specific ideas in mind of course. ;)

The World then manages all these objects: it updates them and can check for collisions between them (player-projectiles versus enemies, enemy projectiles versus player, enemies versus player and that's it).


As for the term 'weapon', I think there's some confusion going on here. It can be used in the sense of a weapon type: a 'blaster' fires straight forwards with strength 10. It can also be seen as a turret: the 'blaster' weapon at level 3 would fire sidewards too, so it has one turret facing forwards and two facing sidewards. The same goes for 'weapon slot': is a slot a turret position, or a more generic slot that accepts a weapon with the first meaning? So the player would have a primary and secondary slot, but a weapon that occupies that slot can have multiple turrets spread across the fighter?

Let's call them Weapons, Turrets, Slots and TurretSlots - then, a Weapon has a type, a Turret belongs to a Weapon, a Weapon is mounted in a Slot and a Turret is mounted in a TurrestSlot. Here, a Turret has a cooldown timer, it's type determines what that timer should be reset to, and a Weapon keeps track of which of it's Turrets should fire next. Wooh! I just thought that was worth clearing up. ;)

Share this post


Link to post
Share on other sites
this sounds like a great idea. as for the projectiles, oyu should use a method like so:



first you want to know how many bulllets you want on the screen. call this variable anything you like, and set the number.



now, use a for statement.

for (int i = 0; i < bullet_count; i++){




now in the statement, you should have a bool value array for every bullet. i would call it shown.

for (int i = 0; i < bullet_count; i++){
if (!shown[i]){
shown[i] = true;
break;
}


so now you fire a bullet.



next, you should have another for statement or inmplement it somewhere in there.


it should be like this:


for (int i = 0; i < bullet_count; i ++){
if (shown[i]){
bullet(); // call to the projectile
}

Share this post


Link to post
Share on other sites
Quote:
Original post by theOcelotI'm confused about this firing order thing. Surely you don't plan on having repeated weapon firings cycle through all occupied weapon points, and therefore all installed weapons? I'd think you would just have an active weapon, direct all firing notifications to it, and let it worry about which of its firing points to use.


Yeah, I think that's basically what I'm thinking. I must not be explaining it right.

What I mean anyway is:
I need (or would like) the ability to have certain weapons fire their points in some order, e.g. a missile weapon that fires a missile from the left and then from the right like in Desert Strike.
So, if the Plane knows about the Weapon, it can tell the Weapon to fire and the Weapon knows about the WeaponPoints and can use the fireOrder in those to determine where the weapon should fire from.

I think that's basically what you're saying.

Quote:
Original post by Captain P
If you have an object that manages all bullets, enemies and player(s) - say, an instance of a World class - then give every Weapon a reference/pointer to that object. They can then tell the world that they want to add some bullets. The world provides a function for this, addProjectile(...), and stores the given projectiles in it's player bullet list. The weapons then only need to care about creating projectiles whenever they receive a fire command 'from above' (e.g. the weapon system that contains them, or the plane itself).


Right. I think I basically have something like that in my "GameplayState" class. Since it already handles the logic and rendering etc. of the gameplay, I suppose it should manage the Projectiles.

Quote:
Original post by Captain P
For a game like this, with relatively few different groups, I'd just keep a list of player projectiles, a list of enemy projectiles, a list of enemies and a player. It's not very scalable, but this kind of game doesn't really need that - unless you have some specific ideas in mind of course. ;)


Ya, you're probably right. Sometimes I have the tendency to try to take future planning too far.

Quote:
Original post by Captain P
Let's call them Weapons, Turrets, Slots and TurretSlots - then, a Weapon has a type, a Turret belongs to a Weapon, a Weapon is mounted in a Slot and a Turret is mounted in a TurrestSlot. Here, a Turret has a cooldown timer, it's type determines what that timer should be reset to, and a Weapon keeps track of which of it's Turrets should fire next. Wooh! I just thought that was worth clearing up. ;)


Yeah, that sounds about right ^_^

Quote:
Original post by dantheman1337
first you want to know how many bulllets you want on the screen. call this variable anything you like, and set the number.


Well I was figuring on more of a dynamic approach with vectors. That way there can be as many bullets as needed and if they no longer exist they can just be removed.

Actually, which is better for removing an object anywhere in a dynamic container? std::vectors or std::lists? Or is there something even better?

Share this post


Link to post
Share on other sites
Quote:
Original post by Sean_SeanstonActually, which is better for removing an object anywhere in a dynamic container? std::vectors or std::lists? Or is there something even better?


First, if you only have a few hundred projectiles it doesn't matter which you use. It is faster to delete from a list, however, the relative slowness of iterating through the list will offset anything gained from the faster deletion. What is likely to be fastest is doing "array deletion" to the vector by copying the last element to the index being deleted, then deleting the last element. Vectors are contiguous memory like arrays, so if you delete from the middle all the remaining vector elements will be moved forward 1 slot.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sean_Seanston
What I mean anyway is:
I need (or would like) the ability to have certain weapons fire their points in some order, e.g. a missile weapon that fires a missile from the left and then from the right like in Desert Strike.
So, if the Plane knows about the Weapon, it can tell the Weapon to fire and the Weapon knows about the WeaponPoints and can use the fireOrder in those to determine where the weapon should fire from.

I think that's basically what you're saying.


What I'm saying is that Weapon doesn't need any help from the points, or any data attached to them, to decide which one to fire at a given moment. In my view, the Weapon should define its own firing order, not use one handed to it by Plane.

I mean, alternation is as simple as having a bool firingOnRightSide and flipping it every time you fire.

Share this post


Link to post
Share on other sites
For all intents and purposes, a weapon in this kind of game is just a projectile generator. As far as weapon placement goes, here's what I would do:

First off, in your Plane class, I'd put either a pointer to a Weapon object (if a Plane can have only one Weapon at a time) or a pointer to a list of Weapon objects (if otherwise) and a pointer to the currently selected Weapon in that list. Like TheOcelot said, the Weapon class should have a pointer to a "parent" Plane object. But to be honest, I think a better thing to do here is to have a pointer to a Point object instead that is equal to the Plane's Point object. The advantage here is that you don't have to worry about the Plane interface -- you can concentrate on the behavior that you want to use for the Weapon (namely getting x and y coordinates). Finally, the Weapon class should have a pointer to another Point denoting the offset from the "parent" Point, which represents the Plane's center.

While I think firing delays should be stored in Weapon objects, I think the overall firing behavior should be part of the Plane objects. If the Plane is ready to fire its Weapon, it will tell the "World" to spawn a Projectile with the properties denoted by the Weapon. Then that Projectile will be updated and rendered like all other Projectiles.

In the case of multiple gun ports and the like, the Plane would simply have multiple Weapons that can fire at the same time. For missiles that alternate between sides, the location of the Projectile to be spawned (which the Plane gets from the Weapon in order to notify the World) can alternate between two different offsets.

Hope this helps! Let me know if there's anything you'd like me to clarify.

Share this post


Link to post
Share on other sites
I've a question about the Flyweight system:

Should the Flyweights have functions to access their variables or should the instances of a Plane or whatever just copy the values of a Flyweight into their own copies of those variables?

Share this post


Link to post
Share on other sites
One of the points of the Flyweight pattern is that common data is shared between objects. So yeah, accessor functions rather than copying values. I would only copy those values if I had a specific reason to do so.

Share this post


Link to post
Share on other sites

This topic is 2840 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this