Advertisement

Tower Defense - Upgrading Towers

Started by August 24, 2021 05:37 PM
13 comments, last by Monfik 3 years, 3 months ago

Hey guys, Im implementing upgrade system in Tower Defense for towers. Im wanna make different upgrade levels with different behaviour by scriptable objects. I think about those scriptables like about block whose can be swaped when I upgrade → You know, different upgrade level, different behaviour.

I have Tower (Base class) andTower Based classes like Archer Tower, Fire Tower, Stone Tower etc.. Each Tower has own data like armor reduction, fire damage etc…

And here Im stuck, becouse I dont know how to keep those data connected to tower. Where to store it? In tower?

Any ideas?

Keeping it in the tower is an option, you must copy it then to the next tower each time you upgrade.

Another option is to have a separate data object with things you must retain when upgrading, you simply give the data object to the next tower (sort of copy everything from above in one assignment).

A third step is to not have Tower Based classes, but just one Tower class with properties that you can configure. This tower can do everything of all towers that you have, but you can turn some features on and other features off (so it looks and acts as one of the towers you have now). Upgrading is then simply changing the configuration.

Advertisement

You can also separate “properties” from “behavior” by attaching a “behavior” object onto the “tower” (with a pointer back to the tower.)

You could then have a “FireArrowBehavior” that shoots fire arrows with a strength dependent on the tower properties.

And then, if you upgrade it to a LavaTower, you swap out the behavior to a LavaStreamBehavior, which does something else.

In an ECS, this would mean that the “tower” is the data struct that's the entity, and the “behavior” is a component, and you swap the kind of component.

enum Bool { True, False, FileNotFound };

In our city building game, we did it the same w<y as the good old RTS games did it and just placed the upgrade below the original building and simply moved everything up a constant time so that it slowly raised from the ground until it was finished. We had a construction mesh and a final mesh for every building and those were then exchanged when construction was done.

Another approach to have different upgrades on a twoer might be to add modifier components. Whenever the tower is checked for an action, say attack or when an enemy enters a certain debuff zone, all components of a certain type are collected and cumulated into the final result, for example the kind and type of damage

@hplus0603 Ok it sounds, and if I have 7 Towers (FireTower, IceTower, Sand Tower etc…) and they have 3 levels of upgrade I will have 21 behaviours, am I right? Assuming they all have different behaviours. If my Fire Tower has fire damage property then where and how keep fire damage data? In those behaviours and after upgrade assigns data? I mean u know at level 1 I have 10 fire damage, at level 2 - 15, at level 3 - 20.

Thanks for relpy, it really helps

@Monfik Alberth and hplus0603 make a great point: make a classes for the things that are going to change. Perhaps you just need one class : TowerClass. What makes the towers different is their behaviors and appearnces. TowerClass could have a pointer to an abstract base class: AttackBaseClass. This pointer could point to a specific class : FireAttack, IceAttack, SandAttack, etc. They could also have pointers to different graphics.

Think of games like Diablo or Borderlands that have tons of weapons. There's no way they can make a class for each variant. Instead they probably have a few classes (Sword, Axe, spear, etc) and vary damage, type of damage (fire, ice) and change what's visible on the model.

I attached a link to a video where I do this for a weapons system for a game I am making. I have a single machine gun class, but change variables like rate of fire, kick-back, spread of bullets etc. Also the model is composed of different parts that can be drawn separately.

There's only one model, but there are 3 different stocks, 3 different clip sizes, a scope, a silencer, a longer barrel, etc. Depending on the upgrades, I may set Stock1.Visible = false, Stock2.Visible=false, Stock3.Visible = true. When the SMG is drawn, Stock3 is drawn but the others are not. Also, I like to keep all the variables in a struct.

You could do the same thing with your towers: A model could have a lot of features, but not all of them are drawn. You could have a short wall that goes around one of the towers, spikes on some the walls, different flags on top.

Advertisement

@scott8I write all my classes to make sure I show u how my architecture looks like.

I have Tower class

AttackTower class based on Tower

IceTower, FireTower, ArcherTower, CrossbowTower, StoneTower and some others based on Attack Tower.

The thing is almost all of them has different propertys, in FireTower I have int fireDamagePerSecond, in IceTower I have float slowPower etc so I dont see other solution to make each classes for them, or am I missing something?

The next level of this is upgrade. Upgrade can turn on next graphics or change those graphics, rly different operations. So 3 classes (various behaviour) for each tower class but where to keep then those properties. What if 3 upgrad of the level would have another properties for example in IceTower stunPower. Im stucked xD

@monfik using an entity-component-system (ECS) approach that I use in my engine, I should do this…

Monfik said:
I have Tower (Base class) andTower Based classes like Archer Tower, Fire Tower, Stone Tower etc.. Each Tower has own data like armor reduction, fire damage etc…

entity: tower1 (id1)
component: position (x,y,z,wx,wy,wz,… )
component: archer (range, damage points, …)
component: fire (range, damage points, …)
component: image (tiles, 3D mesh, ….)

entity: tower2 (id2)
component: position (x,y,z,wx,wy,wz,… )
component: fire (range, damage points, …)
component: image (tiles, 3D mesh, ….)

Monfik said:
if I have 7 Towers (FireTower, IceTower, Sand Tower etc…) and they have 3 levels of upgrade I will have 21 behaviours,

In order to upgrade a component (behavior data), I see two options:

  • replace the component with a new one
    upgrade("tower1", archerv1, archerv2) → inside this function, you copy the old data from archerv1 to archerv2
  • Include upgrade options inside the component
    archer (level, range[], damage[], points[], …) → and just change level=2, it cold be just the index of the parameters arrays → damage[level]

Pure ECS use only data in the component (struct, POJO). The behavior is in the Systems.
Systems know how to use the component data, they know the structure, and use those data to apply the behavior.
Some systems could be the following:

Archer system
For each component.archer and component.position do … damage enemies in range

Fire system
For each component.fire and component.position do … damage enemies in range

Draw system
For each component.image and component.position do … draw

So if you want a new tower type, just create a new system (behavior) and new data (component). And add the components to the tower (entities) that you want.

None

@Gotanod I have some conclusions about this. Thanks rly for that, could only if u can translate it on OOP like Im using in Unity?

@monfik Sorry but I don't know Unity.
If you are using Unity, it is better that you read ECS for Unity and you follow those guidelines.

https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/index.html

None

This topic is closed to new replies.

Advertisement