Make my own "Scripting language"

Hello, i'm working on a pretty simple game where you are a space ship at the left of the screen and there are enemies incoming from the right. Looks like this

* * * * * * * * 
* * * * * * Enemy
you * * * * * * 
* * * * * * Enemy
* * * * Enemy *


And i need to control when enemies come in and which kinds of enemies that come. And my idea was to make some kind of script language that have only one command and the syntax would look like this

Enemy_Type Time YPos '\n'

So the first thing im asking. Is this a good way to do it? cause i found out that random generated levels are very bad and boring if you dont make an algoritm that is way over my knowledge.

Any other suggestions on how to solve this maybe?
Your scripting approach is very good. It's a very simple to parse and simple to write format.

One idea....

The way vertical shooters (or I guess in your case, horizontal shooters) often work is they have enemies approach in "waves". A wave can be defined by a few things:

1) A placement position
2) An enemy type
3) Time between each enemy's appearance
4) Number of enemies.


Then instead of defining your levels in terms of individual enemy spawns, you could define them in waves:

1
2
3
enemy_type   num_of_enemies   Y_pos   time_between_enemies
'wait' time_to_wait
enemy_type   etc etc etc  (next wave)


This makes it easier to design levels, but is a bit trickier to implement because you now have to keep track of individual waves. There's also the possibility of multiple waves happening at once, (ie, a 2nd or 3rd wave starts while the 1st one is still spawning enemies).



cause i found out that random generated levels are very bad and boring if you dont make an algoritm that is way over my knowledge.


Randomly generating levels is a HUGE plus. It adds so much to the replay value of a game!

With the above "waves" approach, it isn't very hard to do, either. I would approach it something like this:

1) keep track of how many waves have passed to get an idea of how far along in the game the player has gotten.
2) randomly generate a wave (randomly choose enemy type, Y position, time between spawns, etc)
3) wait for a randomly chosen time.
4) repeat from #2


To make it reasonable, you have to give constraints. For example... when generating the time between individual enemy spawns for a wave, you will want to say it has to be between 15 and 25 frames... or something to that effect.

And when determining the time between waves, you'll want to say it has to be between 100-150 frames, or something. Play around with the numbers until you get it to feel right.


Now to keep the game challenging... you'll want it to get more difficult as time goes on. This is where #1 above comes in.

You'll want the number of waves to give 'bias' to your random numbers. Really, this just means changing the restraints.

For example... if the player has cleared 0-5 waves... you can use restraints like...
- 15-25 frames between individual enemy spawnings
- 3-6 enemies per wave
- 100-150 frames between waves

Once the player gets to 6-10 waves... make the restraints different... like....
- 10-15 frames between individual spawnings
- 5-8 enemies per wave
- 75-100 frames between waves


I'm betting the "time between waves" restraint is really going to be what makes the game difficult. When that number gets really low, the player is just going to get hammered with endless streams of enemies.


To prevent an impossible situation, you might want to give the player the occasional "breather". This is common in many games in this genre. Like say... every 20 or so waves... don't spawn any more waves until all on-screen enemies are gone. This gives the player a chance to catch up.



You might also want to add bias for certain enemy types based on how many waves have passed. For example, you might want to have some easier enemy types more frequent in the first few waves... and introduce harder enemy types later. All that can be done by altering the restraints based on waves passed.
Last edited on
Okay i love the idea, but i dont know if i can implement it. Could you just give me a hint on how to do. I want to solve as much as i can on my own but i feel that i need a hint on this.

I could make 2 mods. Survival and Campaign. Survival should be random generated because im seeing hope in it with your idea, campaign is more story and bosses thingy.

But. How should i implement the script. im thinking of, i need to make a vector that can store both wait and wave commands. I have no idea on how to do that. Maybe a interface.

1
2
3
4
class scriptWord
{
 virtual void doAction();
}


I have actually no clue
There are 3 fundamental object types.

1) Enemy
2) Wave (spawns enemies)
3) WaveSpawner (spawns waves)

For campaign mode, you can load your WaveSpawner from a file. For survival, your WaveSpawner randomly generates the waves. But the way your program will interact with them is the same, so you can use inheritance here.

1
2
3
4
5
6
7
class WaveSpawner
{
  virtual void Update() = 0;  // called once per frame by main game logic
};

class CampaignSpawner : public WaveSpawner { ... };
class SurvivalSpawner : public WaveSpawner { ... };


These classes can keep a counter of the number of frames until the next wave is spawned. Every time Update is called, just decrease that counter, and if it's zero, launch a new wave and reset the counter.

Your wave class can work similarly, but since all waves behave the same, there's no need for inheritance.


As for how you load the scripts... there are many ways to do it. My first instinct was to load the entire file into a vector and then step through the vector in your update function.

But now I'm thinking you can just read data from the file on the fly, and that might be easier.


Either way it'll end up looking something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// pseudo-code
void CampaignSpawner::Update()
{
  if( counter > 0 )
    --counter;

  while(counter <= 0)
  {
    action = ReadNewLine___FromScriptFile_or_FromVector();
    if( action == wave_details )
      SpawnNewWave( action );
    else if( action == wait )
      counter = action;
  }
}
Last edited on
I am not quite sure what you meant with the counter. Otherwise i get your idea and it seems great. Tho i will still load the info into the vector because i like working with vectors and im not the best on working with files so i think i will load the map into a vector before the game starts.

But can you please try to explain where you wanted to go with the counter again? The code with the counter confused me most
Last edited on
A counter is just an integer variable that counts down.

Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int counter;

counter = 5;  // 5 frames until next action


// every frame...
if( counter > 0 )
  --counter;  // count down 1 frame

if( counter <= 0 ) // no more frames to wait.  
{
   // do your action here

  counter = 10;  // reset counter so it will be 10 more frames until the next action happens
}
oh so counter is holding the delay between waves! i get it now. Thank you!
Topic archived. No new replies allowed.