Sunday, November 25, 2012

Trees and Captain Crunch

This is a screenshot of your starting position when starting the game. 

Basically for the past week I was working on implementing the other two trees and finishing up their abilities. Mercy is 100% complete. Vengeance is 90% (I just have to wait on Cory, the artist, to send me the artwork for the final ability). I'm 50% done with Justice (a few more abilities and his artwork). With the final trees finished, the game will be feature complete. Then we can focus on enemies and levels.

Implementing the trees was a lot easier than I thought. It's just mostly copy and paste and replace certain values to the correct ones. In fact, it was when I was copying and pasting when I remembered the wise words of my Intro to CS professor. "If you find yourself copying and pasting over and over again. Just put it into a method."

This is the code to check if a certain ability is activated and set up and update the HUD to show that it is disables and display a circular timer to count down when the player can next use it.

var is_active;
is_active = ability_is_active("I_Crush");

if(is_active)
{
    draw_sprite_ext(spr_hud_keys_mercy_2, -1, 102, view_yview[0] + 12, 1, 1, 0, -1, alpha);
 
    origin_x = view_xview[0] + 50 + 76;
    origin_y = view_yview[0] + 36;
    radius = 25;
 
    if(instance_exists(obj_angel) and !obj_angel.canUseCrush)
    {
        per = obj_angel.alarm[3]/global.crush_cooldown;
     
        for(i = 0; i < 360 * per; i += 1)
        {
            radian = degtorad(i - 90);
            dst_x = origin_x + radius * cos(radian);
            dst_y = origin_y + radius * sin(radian);
     
            draw_set_alpha(.35);
            draw_set_color(c_black);
            draw_line(origin_x, origin_y, dst_x, dst_y);
        }
        draw_set_alpha(1);
    }
}


this can be changed to:

var is_active;
is_active = ability_is_active("I_Crush");

if(is_active)
{
         activate_ability(spr_hud_keys_mercy_2, view_xview[0] + 50 + 76, view_yview[0] + 36, obj_angel.canUseCrush, obj_angel.alarm[3], global.crush_cooldown);
}

activate_ability(player_sprite, origin_x, origin_y, ability_bool, angel_alarm, cooldown_timer, )
{

    draw_sprite_ext(player_sprite, -1, 102, view_yview[0] + 12, 1, 1, 0, -1, alpha);

    radius = 25;
 
    if(instance_exists(obj_angel) and !ability_bool)
    {
        per = angel_alarm/cooldown_timer;
     
        for(i = 0; i < 360 * per; i += 1)
        {
            radian = degtorad(i - 90);
            dst_x = origin_x + radius * cos(radian);
            dst_y = origin_y + radius * sin(radian);
     
            draw_set_alpha(.35);
            draw_set_color(c_black);
            draw_line(origin_x, origin_y, dst_x, dst_y);
        }
        draw_set_alpha(1);
    }
}


This greatly simplifies things and it was perhaps the first time that I actually got to use an actual programming paradigm to help me out and that Game Maker would actually allow. However, I still got to the problem of the actual timer. Game Maker only allows you to have 12 timer events per object. I need 15 for each tree. The first thing I tried was to simply have 5 and if the timer event was activated, it would reset the current tree's ability that it was associated with to true. Of course the problem with that is obvious. You can activate an ability in one tree that has a slower cooldown rate and then go to another tree and activate an ability that was associated with the same timer. The timer would reset and whichever tree you were on when the timer would go off would be reset and not the other (you could even be on the third and have neither reset). This is where Game Makers decision baffles me to limit the number of timers an object could have. Right now I am thinking of different approach that would only use single timer (kind of). The step event (an enter_frame for those who know actionscript 3.0) is sort of like that timer that goes on until it is disabled. After each step, the independent timers would count down and activate if their timer reached zero. All my timers do is if they reached zero is set a boolean to true.

The way Game Maker handles booleans is that 0 and NULL are false, everything else is true (whether it be ints, doubles, strings, and even objects). So have a timer variable that would keep track the time it had to cooldown. It would count down 1 every step (unless it was already zero). Only a single variable would therefore be needed to determine if an ability can be used or not. Take the timer variable and NOT it. 0 would be true and all other numbers would be false. This would greatly simplify things and free up excess timer events to be used elsewhere where more complex algorithms can use it.


This is a screen shot of the upgrade menu (made by me not a competent artist). This will list each ability both passive and active that you can get for each tree. 


That should be simple enough, then I realized that Beta is due in a week (December 3) and the finished title the week after that (December 10). Then the semester will finish out. All I can say is that this semester went quick. One of the big things that everyone says when a deadline is approaching is that they didn't have enough time to get the product they want. I can honestly say is that this game will not be the game we were hoping for at the beginning of the semester. I will have a more complete recap when the project is complete, but we seriously went over our heads thinking we could make an RPG platformer in a single semester. At the beginning of the semester, I knew we wouldn't be able to do everything but what we weren't able to accomplished astounded me.

There were several factors that led me to believe this could be done. The first is I thought Game Maker would be a simple tool to use and even though I wouldn't be able to achieve the depth I wanted I would at least be able to speed things up. I was wrong. The first problem is that I didn't learn the in's and out's of Game Maker and GML in the time that I thought and even when I did, past experience wasn't as helpful as I thought too because I had to abandon almost every programming paradigm since I started the program. The second is that the art took longer than expected (Cory even admitted to that). I needed some assets to play around with (I'm not that good of an artist so I couldn't have made any placeholders). This delayed production a bit as I struggled with GML to get even some simpler things working.

My biggest problem with GML is that the debugger is absolutely horrible. With event driven programming, using strings to detect problems can only do so much. I needed to step through the program to figure out what variables were at what time when I do certain events. The step that I couldn't step through was simply horrible.

That's all the gripe I have today. I'll probably post again after Beta.

Wednesday, November 7, 2012

Fallen: Artwork, Upgrade menu, and linked lists

Its been awhile since I last posted, but I've been really busy with school work and midterms. I haven't been able to focus as much as I wanted on Fallen for that reason and the fact that I have to wait for the artist to finish some assets. The artwork is going great and Cory Stivers is an awesome artist who can get some quality work done in a quick amount of time.


This is the concept for the angel.


These are the sprites of the angel for mercy. 
(Left: The attacking animation, Center: This is for walking, but the animation doesn't seem to be working, Right: the idle animation)



These three are the backgrounds for the first level. These don't include the Statue which acts as the platforms. 

Now that some good stuff is out of the way. What I did this past week and a half when I did have the time was create the Upgrade menu, pause ability, and a upper HUD to show which ability the player can use and what key it is mapped to. The upgrade menu was the hardest of it not because it was a challenge, but because game maker and GML is not like any normal programming language. 

The way the upgrade menu works is that there are three trees of abilities (Justice, Vengeance, and Mercy). Each point you get by leveling up, you can spend on an ability. You can purchase any ability on the tree, but you must have purchases the previous ability. So in order to get Justice level 2 ability, you must purchase the Justice level 1 ability. This should be easy to do, but the first thing that bugged me was laying out each button. Normally what I would do is utilize object-oriented programming by creating a master button that each subsequent button extends off of. Game Maker kind of does that, but it really is weird and doesn't act like a true super class, especially when it comes to overrides. What I decided to do is to create one button and to have parameters specify where it will be and what ability it would activate. Again this should be easy, but GML doesn't have a new Button() call. Instead what it does require when you want to create a new object is to call instance_create(x, y, obj). Parameters can't be used to customize it. What I had to do is the following code.

button = instance_create(x, y, obj);

with(button)
{
    //initialize button here
}

In GML, with acts like a for each loop. If you put in an object name, then it will loop through each object on the stage. If you put in an instance id, then it will just do the instance. This is very annoying because and code inside the with loop is called as if its inside the actual button. So a call of instance_destroy() inside the with loop is like button.instance_destroy(). However, you can't call button.instance_destroy() or any other methods to apply to an object. The only thing you can call from an object is a global variable. 

I was able to lay down the buttons and set them so that any ability that could be activated could be selected. Now came the second part. If the player decided to accumulate more than one point, then they could purchase multiple abilities down a tree. This required me to set up a system that would check to see if the previous button was selected so that if it was selected, then the current button could be selectable. This caused the problems. Each button has no knowledge of any other button, so I had to create a data structure that would host each button in sequential order so that the previous entry was the previous button. The obvious choice for me was a linked list. GML has no linked list. What it does have is a list that is similar to the ArrayList in java or a list in C# or a dynamic array (vector). So I create this list hoping that it would function the same as a linked list. To my surprise not only does GML list have no iterator. But when I did find a way to get the previous entry, the code to check to see if the previous was selected didn't work. No matter what I tried, I couldn't get the code the let the next selectable button to be selectable. 

Normally I would debug by stepping through the code, but GML doesn't have a step in functionality in its debugger and prints didn't tell me anything useful. I couldn't think of anything else to do, and I had to continue on the game and get it ready for the Alpha, so I dumped the functionality and just had to have the user select one upgrade at a time. I really hate game maker. Its reasons like this that I wished I had used actionscript 3.0 and flash to create the game. But I'm stuck with my decision and will have to trudge through the finish.