principleMinor
Adding features to a strategy game
Viewed 0 times
featuresgameaddingstrategy
Problem
I'm working on a basic strategy game for iOS and I have a question about the overall layout of the code in the program. I added some features to the game today and I had to add code to several different places to get the features to function properly. In general I think I am doing things correctly, but I fear I am falling into common programming pitfalls that I do not yet know about. In this question I will walk through the features I wanted to add to the program, and the way I approached them.
To start with I had basic enemies in the game that were randomly created on floors of the tower given certain conditions. When spawned they just stayed in place and did nothing. So I looked at the class and saw that once the enemies were created, there was no logic present to decide what they would do. So I added some logic to tell the enemies to move to attack the nearest wall if one was present on the floor that they spawned on.
Next I wanted to make the workers react to the presence of enemies on a floor. The floors have an enum that defines their state. After the tower creates an enemy, it immediately sends it to the correct floor. The floor accepts it with this code:
Next I needed to cause the workers on the floor to react to the presence of the enemy. I did so with the following code:
This method also deals with the regular case of when the floor is not under attack, but that is not so important here.
I also needed to add this code:
```
-(void) cancelJobDueToAttack {
[self abandonCurrentJob];
[_jobArray
To start with I had basic enemies in the game that were randomly created on floors of the tower given certain conditions. When spawned they just stayed in place and did nothing. So I looked at the class and saw that once the enemies were created, there was no logic present to decide what they would do. So I added some logic to tell the enemies to move to attack the nearest wall if one was present on the floor that they spawned on.
Next I wanted to make the workers react to the presence of enemies on a floor. The floors have an enum that defines their state. After the tower creates an enemy, it immediately sends it to the correct floor. The floor accepts it with this code:
-(void) acceptEnemy:(DTEnemy *)enemy {
[self.enemyArray addObject:enemy];
if (self.floorState != FloorUnderAttack && self.floorState != FloorDestroyed) {
self.floorState = FloorUnderAttack;
}
}Next I needed to cause the workers on the floor to react to the presence of the enemy. I did so with the following code:
-(void) updateFloor {
switch (self.floorState) {
case FloorUnderAttack:
[self cancelJobDueToAttack];
[self makeDwarvesFlee];
[self handleEnemies];
break;This method also deals with the regular case of when the floor is not under attack, but that is not so important here.
I also needed to add this code:
```
-(void) cancelJobDueToAttack {
[self abandonCurrentJob];
[_jobArray
Solution
I can't offer any specific advice for how better to approach this specific problem, as I don't have my head completely wrapped around all that your project encompasses. Moreover, for this question, I think specific advice isn't particularly helpful. Even if I had a solution that could make the current and near-future situation better, this question is about seeing way beyond that.
There's nothing more frustrating to me as a programmer then to spend several days working on something, only to then realize, "Wow. This will actually never work. The entire structure is flawed to the core so badly that I can only restart from basically scratch." Yet, it happens. You should always be trying to think beyond the current scope of your project and attempt to future proof it as much as possible, but it's not always possible. So when you run into a situation where you have to update a lot of existing code to make new features work, don't feel too down on yourself.
But when you have time, look at that scenario, and try to imagine a way in which it could have been avoided. And by that, I don't mean how your past-self could have avoided it equipped with the knowledge of your current-self. Try to think of how your past-self could have avoided the scenario with the exact amount of knowledge your past-self had.
Thirty minutes of planning could save 3 days of recoding. A day of planning could save months of recoding time. Before you spend too much time coding, sit down, away from a computer and do some planning. Do some formal planning where you're outlining the plan, taking notes, etc., and do some informal note-taking as well while you're actually doing something else. Often times, my best ideas on how to tackle a programming challenge come while I'm pre-occupied with some other activity, sleeping, showering, whatever.
During this planning, the first thing to consider is how best to structure your code so that you will easily be able to include every feature that you currently have planned and will for sure be including at any point in time, as well as try to imagine and future features that you may want to include in the future.
Once you've got a bit of an idea on how to model your code, spend some more time looking for its glass ceilings. In what areas is your model going to limit you from as of yet unforeseen features and is there an way to change your model now so that this is not difficult in the future?
In this case, I'd argue that the changes you had to make only seem big because you're not breaking it down into the group of smaller changes that had to be made.
If the only task were to add enemies, that part seemed relatively painless.
If the only task were to add a single new job, that alone doesn't seem to bad.
The problem is, in order to add enemies to the game (a quite big feature), that required adding 3 new jobs. The total task of adding enemies and 3 new jobs seems like a lot. But if you broke it down into the 4 tasks of adding enemies and 3 new jobs, on balance, each individual task isn't that much.
If you were working for a boss, and your boss said "We want to be able to make the dwarves dance on a floor. Can you have this done in an hour?" What would happen? You'd spend two minutes adding the dance job, and 58 minutes adding the dancing animation.
So perhaps the real lesson here is to remember to look at your own tasks as a collection of smaller tasks, which are in turn, a collection of smaller tasks. Every time you add a job, you'll have to update any switch which switches on jobs. The job-specific methods arguably could all be a single method with a switch also. And so if you already had the necessary jobs in place, all that would've been left is writing the logic for the enemies... which is the feature you were adding, so I can't really see too much complaint about having to put in this effort.
There's nothing more frustrating to me as a programmer then to spend several days working on something, only to then realize, "Wow. This will actually never work. The entire structure is flawed to the core so badly that I can only restart from basically scratch." Yet, it happens. You should always be trying to think beyond the current scope of your project and attempt to future proof it as much as possible, but it's not always possible. So when you run into a situation where you have to update a lot of existing code to make new features work, don't feel too down on yourself.
But when you have time, look at that scenario, and try to imagine a way in which it could have been avoided. And by that, I don't mean how your past-self could have avoided it equipped with the knowledge of your current-self. Try to think of how your past-self could have avoided the scenario with the exact amount of knowledge your past-self had.
Thirty minutes of planning could save 3 days of recoding. A day of planning could save months of recoding time. Before you spend too much time coding, sit down, away from a computer and do some planning. Do some formal planning where you're outlining the plan, taking notes, etc., and do some informal note-taking as well while you're actually doing something else. Often times, my best ideas on how to tackle a programming challenge come while I'm pre-occupied with some other activity, sleeping, showering, whatever.
During this planning, the first thing to consider is how best to structure your code so that you will easily be able to include every feature that you currently have planned and will for sure be including at any point in time, as well as try to imagine and future features that you may want to include in the future.
Once you've got a bit of an idea on how to model your code, spend some more time looking for its glass ceilings. In what areas is your model going to limit you from as of yet unforeseen features and is there an way to change your model now so that this is not difficult in the future?
In this case, I'd argue that the changes you had to make only seem big because you're not breaking it down into the group of smaller changes that had to be made.
If the only task were to add enemies, that part seemed relatively painless.
If the only task were to add a single new job, that alone doesn't seem to bad.
The problem is, in order to add enemies to the game (a quite big feature), that required adding 3 new jobs. The total task of adding enemies and 3 new jobs seems like a lot. But if you broke it down into the 4 tasks of adding enemies and 3 new jobs, on balance, each individual task isn't that much.
If you were working for a boss, and your boss said "We want to be able to make the dwarves dance on a floor. Can you have this done in an hour?" What would happen? You'd spend two minutes adding the dance job, and 58 minutes adding the dancing animation.
So perhaps the real lesson here is to remember to look at your own tasks as a collection of smaller tasks, which are in turn, a collection of smaller tasks. Every time you add a job, you'll have to update any switch which switches on jobs. The job-specific methods arguably could all be a single method with a switch also. And so if you already had the necessary jobs in place, all that would've been left is writing the logic for the enemies... which is the feature you were adding, so I can't really see too much complaint about having to put in this effort.
Context
StackExchange Code Review Q#54584, answer score: 2
Revisions (0)
No revisions yet.