hi there!
One thing that took me a lot of time to understand about programming is this: there's almost never a "objective best" way to do things. This is because *you* will be the person doing it, and that's a very important factor.
I will tell you what *I* would do but you need a "subjective best": the best option for *you*, considering your current knowledge, state of mind, previous experiences and personal preference.
If I were doing your game, I would use middleclass, because it's my library, so it's the one I know best
. I would use a two-level hierarchy: A base "Tank" class and one subtank class per "tank model"- ShermanTank, MerkavaTank, etc. The tanks would be instances of these classes. So when you do MerkavaTank:new(x,y) you create a new tank in position x,y. I would probably use one extra class for each "variation" too - a class would represent "how a tank is right when it's fresh out of the factory".
How the rest would be done depends a bit on the kind of game you want to do: namely, how much complexity you want to add to your tanks. If you are ok with all the tanks "behaving the same way" (i.e. all of them can move, all of them can fire from their main turret, etc) so that some "common attributes" (like speed, armor, etc) govern all of them, then I would make the Tank class set them to default values on the constructor. It would also implement all the "common" methods (move, fire, etc).
Code: Select all
-- tank.lua
local class = require 'middleclass'
local Tank = class('Tank')
function Tank:initialize(x,y)
self.x, self.y = x,y
self.turretAngle = 0
self.bodyAngle = 0
self.health = 100
self.firePower = 25
self.speed = 100
...
end
function Tank:fire()
... -- create a projectile at self.x,self.y with self.firePower going towards the angle self.bodyAngle + self.turretAngle
-- maybe play self.fireSound ?
end
function Tank:draw()
... -- draw the body and turret using self.bodyImage and self.turretImage
end
... -- (other methods like rotating the body, advancing, rotating the turret, etc)
return Tank
And then each tank model would just override the default ones on its constructor - and maybe do visual stuff like setting the images and sounds for each model, if you are considering doing that
Code: Select all
-- sherman_tank.lua
local class = require 'middleclass'
local Tank = require 'tank'
local ShermanTank = class('ShermanTank', Tank)
function ShermanTank:initialize(x,y)
Tank.initialize(self, x,y)
self.firePower = 40 -- overrides default firePower
self.turretImage = ...
self.bodyImage = ...
self.fireSound = ...
end
return ShermanTank
Since ShermanTank is a subclass of Tank, it would inherit all the tank methods. So it would be able to fire, move, etc.
If you wanted to model more complex things than an abstract hp option (like "this tank's roadwheels have been destroyed" or "the turret has been impacted and its accuracy won't be optimal") then I would use a different approach: each tank would have an "inventory of parts", each one with its own capacities (hp, armor, capacity to fire, capacity to move) so they would be modelled independently. But this would be quite complex, and require lots of settings. You probably want to start with the version I told you above.