Galactic Wing

The Code Behind Galactic Wing

Game Designer, Lead Programmer/Developer, Sound Designer, and Music Producer – Nicklas Kenyon

Graphic Designer, Lead Artist,  and Programmer/Developer – Caleb Perry

Galactic Wing and Processing
Galactic Wing was written in Processing (It’s free at https://processing.org/download/).

Click to Download Game

Some of the code you see uses functions built into Processing.
For this review of my project I am going to explain the major parts of code, because the code itself is quite lengthy.

 

How the Code is Organized

Setup looks like this:

void setup(){
  size(1280,720);
  background(0);
  //loads images at the start of the game.
  loadimages();
  //Setup_FileRW creates the file reader, and then loads the save file.
  Setup_FileRW();
  //Assigns default or saved values before the game starts
  Setup_AssignValues();
  //Creates new instances of all lists that are requiered in the game.
  Setup_CreateLists();
  //If a Lists needs objects at the beginning of the game, those objects are added using the Setup_FillLists method
  Setup_FillLists();
  //Runs the initial setup of Music Players
  Setup_MusicPlayers();
}

Setup is composed of several separate setup packages so that the setup does not get cluttered. With all of the separate functions, I can keep better track of where things are, and when they happen. This same idea of organizing the code into several different functions and methods is used throughout the entire code.

Void draw also follows this organization

void draw(){
 //if the console isn't being used, continue running whichever gamemode is selected 
  if (consoleactive==false){ 
    //if the gamemode is 0, run the MainMenu package, which displays the main menu, and checks to see what the user wants to do.
    if (gamemode==0){
      MAINMENU();
    }
    //When campaign mode is made, gamemode 1 will run a campaign mode package.
    if (gamemode==1){
      CAMPAIGNMODE();
    }
    // If the gamemode is 2, the Chaos Mode package is run, which is a survival stlye gamemode
    // in which the player tries to dodge more and more asteroids as time goes on.
    if (gamemode==2){
      CHAOSMODE();
    }
    //if the gamemode is 3, the Hangar package is run, which brings up a view of the hangar, where the user can select and unlock ships.
    if (gamemode==3){
      HANGAR();
    }
    if (gamemode==4){
      //opens tribute mode
     TRIBUTEMODE(); 
    }
    if (gamemode!=3){
      //resets Hangar fade mode
      FadeHangarOff = false;
      //resets Opacity for all images to completely Opaque.
      tint(255,255);
    }
  }
  //runs the console package
  console_package();
  //Plays the music
  PlayMusic();
  //Runs the Character Package
  CHARACTER();
}

Each of the fully capitalized methods in void draw are what I like to call “packages” (i.e. “CAMPAIGNMODE()”).

Going into detail about each function would become monotonous and boring, so I will just touch on some other important aspects of the game.

The Save/Load System

The saving and loading of a save file is a game feature I am very proud of. Thankfully, Processing has some built in functions that make this a bit easier.

The code looks like this:

PrintWriter savefile;
int fivescores = 0;
BufferedReader savefile_reader;
String savefile_string;
PFont filefont;
int count = 0;
boolean FileIsRead = false;
// void Setup_File_RW() is in the "Setup" tab.

void SaveGame(){
  writesavefile();
}

void LoadGame(){
  if(FileIsRead==false){
    readsavefile();
    FileIsRead=true;
  }
  }

void writesavefile(){
  
  savefile = createWriter("savefile.txt");
  savefile.print("Gold="+Gold+"~");
  savefile.print("Rank="+Rank+"~");
  savefile.print("Experience="+Experience+"~");
  savefile.print("End of File~");
  println("Saved");
  savefile.flush();
  savefile.close();
}

void readsavefile(){
      try{
        savefile_string = savefile_reader.readLine();
        
      } catch (IOException e) {
         e.printStackTrace();
         savefile_string = null;
      }
      if (savefile_string == null) {
          //nothings gonna happens
      } 
      else {
        String[] savefile_list = split(savefile_string, "~");
        println("SFList: "+savefile_list.length);
        
        //Gold
        String SaveData_String_Gold = savefile_list[0];
        String[] SaveData_Array_Gold = split(SaveData_String_Gold,"=");
        ;
        Gold = int(SaveData_Array_Gold[1]);
        println("Gold: "+Gold);
        //Rank
        String SaveData_String_Rank = savefile_list[1];
        String[] SaveData_Array_Rank = split(SaveData_String_Rank,"=");
        //Rank = int(SaveData_Array_Rank[1]);
        println("Rank: "+Rank);
        //Experience
        String SaveData_String_Experience = savefile_list[2];
        String[] SaveData_Array_Experience = split(SaveData_String_Experience,"=");
        Experience = int(SaveData_Array_Experience[1]);
        println("Experience: "+Experience);
  }
}

As you can see, the save file takes user variables, such as Gold, and saves them. When the game starts, the save file is loaded.

This is what the save file looks like:

2014-06-01_02h34_57

 

This is a very simple way of storing information, but for the purposes of this game, it is sufficient.

 

The Command Console

The Command Console took forever.

At first, I was just checking an ArrayList of Strings. When I wanted to get more advanced and have the text scroll, and be able to view input history, I decided to make a “Input” class, that had a String variable and a “y” variable for the text’s y position in the history view.

Code:

class CommandInputs{
  //y position of the string in the console view
  int ypos;
  // the text that the user has input into the console.
  String inputtext;
  CommandInputs(int y, String text){
    ypos=y;
    inputtext=text;
  }
  void moveup(){
    //move the line up by the height of the font (i'm using font size 12, so I give a little bit of space by adding 14)
    ypos+= 14;
  } 
}

Here is a demo of the console:

Collision Detection

Currently, the game uses a radius based method of collision detection. Another, “pixel-perfect” method of collision detection is in the making, but is not functional enough to put into the game at this time.

A bit of sample code

//if an asteroid hits another asteroid, it bounces off
void check(Asteroid b){
  float d = dist(xpos, ypos, b.xpos, b.ypos);
    if (d <= ((diam+b.diam)/2)){
      if (diam<=b.diam){
      xspeed *= -1;
      }
    }
}

Loading Maps in Campaign Mode

As is the case in many 2D games, I decided to uses a pixel sheet to design and create my maps. The map reader gets the color information from each pixel in a map sheet, and then decides what object to place in that relative position based on the color.

Examples
Map_1

Map_2
Red pixels are stationary asteroids.
Green pixels are moving asteroids.

What about Gameplay?

There are two game modes in Galactic Wing; Chaos Mode and Campaign Mode.

Chaos mode is a survival style game mode in which you get one ship and try to stay alive, dodging asteroids and shooting gold as more and more asteroids enter your area of space.

Your ammo is replenished with each wave of asteroids.

 

Campaign mode is in early development but features a progression through different asteroid fields of increasing difficulty.

As you play, you will gain experience and be promoted to new ranks. The greater your rank, the more ships you can control.

 

As you play, you will gain gold, experience, and rank. With gold, you can buy new ships in the hangar.

The Controls

The controls for Galactic Wing are a bit unique. Instead of holding down the WASD keys to move, you press them to increase or decrease you x and y speeds.

To fire a laser, press the space bar.

If you manage to go into the hangar, you can press the “f” key to go back. The hangar is in development, so enter at your own risk.

To open the console, press the “/” key. When you are done typing in your command, press enter to submit it and close the console.

To go back to the main menu at any time, press the “m” key.

 

One thought on “Galactic Wing

Leave a Reply

Your email address will not be published. Required fields are marked *