Saturday, December 22, 2012

Fallen: Closing Remarks

Well, I finally turned in the "final" version of Fallen (well, last week I was enjoying some rest). Final is in quotations because the version is really nothing more than a demo showing off the mechanics that we wanted to do. I can honestly say that I am satisfied with the product we were able to deliver, but disappointed that we couldn't release the full scale game that we wanted. That is mostly because of time. There just wasn't enough time to complete the full version with the resources we had. If we were to continue on with this project, it would probably take at least another semester of hard work, work I have to allocate elsewhere. As much as I would love to complete this game fully, I'm just too busy with school work and other projects for the next semester. We may pick this project up again during the summer break, but I don't know if we will carry through with these plans.

If we were to carry on the game, there would be a lot of things I would like to change but couldn't to keep consistency and stay on schedule with the completion of this version. The biggest thing I would like to change is the tool we use to build it. I would scrap Game Maker in a heart beat and use another language. I suggested Actionscript 3.0, but that was only to fit within the time I had. I would like to start this game from scratch again and use the lessons I learned making it to better improve the product. If I were to go all out on this game and assuming I had the resources and time to actually do it, I would love to have this game as an open world 3D RPG. This would require 3D artists and animators, the artist we have is an awesome 2D artist, but he will be the first to say that his 3D work is basically non-existent. I would like to recruit some more programmers on this task since the workload will be extremely heavy with a sufficiently large game that would be like any other RPG you've played (like Dragon Age). If we are keeping things to a pipe dream, then this game could be your next AAA game. So if I were able to have all those variable accounted for (some how), then the tool I would most likely use is a combination of C# and C++ most likely using the .NET framework and possibly UDK. If this game is to be scaled back drastically, but able to keep the open world 3D aspect to it, then I would like to use UDK or Unity.

With that, this concludes the series on Fallen. You can download the demo here. I will take a rest for the rest of this year and pick up again, when next semester starts and I start the next Game Development course. The course focuses on Alternative Gaming, so it should be interesting what the result may bring and a chance to do something bearable this time without Game Maker. Who knows, only time will tell.

Monday, December 10, 2012

Beta and the Pit

I just had beta testing for Fallen and what an experience that was. You can test for all anomalies and bugs in your game, but only those who have never played your game will find the bugs. Users found two recurring bugs that I thought couldn't happen. The first bug was during a certain time when Vengeance was swinging his sword and the radius variable wouldn't initialize. I fully don't understand why that occurred, mostly because I couldn't step through the code and see what actually happens, but I was able to fix the bug by simply initializing the variable to just outside the range of a hit then have the code check for the actual range.

The second error was a variant of the sticky wall problem (where the character sticks to wall when the player walks and jumps straight into it). The player wouldn't stick into a wall, but if they were in contact with the wall and continued to press the space bar, then they could climb up the wall. This was a bit harder to fix, but I was able to fix it by creating a boolean to check if the player is jumping and have the player act appropriately when next to a wall based on that boolean.

The major complain that we did receive about the game was that the player didn't have a chance to use all the upgrades and fully traverse a tree since the full game is not complete. So we decided to create the Pit.

Pit mode is like any arena level or game where you start at a base level and waves of enemies come in at you. This does automatic upgrading when a person gets to the next level since the waves are continuous and the player can switch trees instantaneously. Initial responses to the new mode were favourable. The hardest part about creating the mode was random enemy generation and having enemies spawn at a pace that would start out easy, then get harder as the enemy progresses.

My method for enemy generation was to first create a range that would start out large at lower levels then get smaller and smaller as the player progressed. My initial formula to generate this range was Max_Level - Level;. So as the level grew, the range got closer to zero. This is still the formula I am using, but it is not optimal as I will show below. From the range, it would then pick a random number from [0, Range]. Then it will pick a smaller range by choosing a high and low number. It will choose the low number first by choosing a random number from [0, Range], then it will choose the high number by picking a random number from [low, Range]. Then it will check to see if the number is in the smaller range of numbers. If it is, then it will generate an enemy, if not then it will try again.

pseudo-code:

void generate_random_enemy()
{
      if(num_enemies < max_enemies)
      {
             var range = max_level - level;
             var valid_number = random(range);
             var low = random(range);
             var high = random_range(low, range);
             if(valid_number >= low && valid_number <= high)
             {
                   instance_create(obj_imp);

                   num_enemies++;
             }
      }
}


The problem with this algorithm is that even though there are many permutations, the computer can work through them extremely fast and enemies will still be generated at a fast rate. One thing that I do want to try is by playing around with the range and generating a new formula to get a better and larger range. Another thing is to have the algorithm sleep for a certain amount of time. So after it has generated an enemy or not, it will wait for x amount of time before it starts again and x will decrease as the level gets up. For now, I just limit how many enemies are spawned at a time, with the number of maximum enemies grow with the level.

Now that Beta is over, I have to work to get bugs finished and the game polished for it to be turned in by the end of this week. I will post one final time about this game with my final thoughts.

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. 

Thursday, October 11, 2012

Platformer AI: Swarmmers

This past week has been very busy for me. I could get a chance to enjoy my Fall break and play some video games that are sitting on my shelf all alone, but instead I get to spend the week with Game Maker. I'm still developing a tech demo to show off to my professor that must be done by this upcoming Monday, so procrastination isn't an option. All I have up to this point is an angel that can move around and shoot fireballs (just one of many abilities) and the lowest enemy that a player can fight.

I actually did quite enjoy developing this enemy since it required me to do some actual thinking (not just looking at documentation online to make sure I did it right). This enemy is a lot more complicated than your average Goomba who walks back and forth all day. For this enemy, I had to implement basic physics and calculation to estimate trajectory and get from platform to platform. I will be using some advanced physics equations (what you would learn in an intro college physics class that required Calculus).

For clarification, this specific enemy is called an Imp.

The Imp is a not powerful and very weak. It works well in large numbers where it swarms their enemy by strength in numbers. What I needed to do was to create an enemy, that when the angel got into range it would swarm straight towards it. This is not as straight forward in a platformer with multiple platforms at different levels.

The Imps default mode is just to walk back and forth on its platform until the imp spots the angel.

When the Imp spots the angel it determine if the angel is above, below, or on the same level as the angel. The same level argument is easy enough as the Imp just charges by setting the x velocity towards the angel.

When the Imp is above the angel:


The image above shows what should happen in this situation (red denotes Imp, blue denotes Angel). The Imp needs to get from the top platform to the bottom, So either he can run off the edge or jump off. Running off might seem simpler but that does collide with the code that makes the Imp stay on the platform in his default mode. Jumping not only makes it easier for the Imp to get to the target, but it adds a more fluid and natural looks of a demon trying to get to its target in the fastest way possible. 

To find the initial velocity needed to clear the platform, it needs the distance (d) from it to the edge. From there the equation is: 


vi is the initial velocity that is needed, g is gravity and theta is 45 degrees (pi/4) because its the easiest to calculate and x velocity and y velocity are the same. Everything else besides vi is known so we just rearrange the formula to get: 


using vi, just plug in that number into x and y velocity and the imp will jump off the platform and land below where it can swarm the angel.

There are some things to be aware of and it is the negation of the values that are put into x and y. For example, vi can be a positive number but the y velocity needs to be negative because of how the Cartesian coordinate system is arranged by the language. 

When the Imp is below the angel:



This requires some more insight than the previous one. When the Imp was jumping off a platform, it could jump at 45 degree angel making the calculation easier. In this case, X and Y are independent of each each other except time (t). The vector at which the Imp jumps can range from 1 to 89 degrees. The angel at which the imp jumps is irrelevant if the x and y velocities are known. In order to figure out the velocity in which the imp must jump, we must find the minimum velocity to reach the height of the platform (h). 


 Since the y velocity when the Imp reaches its height will be zero, the equation can be rearranged to:


Knowing the initial y velocity, we can now find the initial x velocity. The only thing that x and y velocities share is that it will take the same amount of time to reach their destination. We can use that knowledge to get the x velocity so that the Imp can reach its distance (d). We can start with the most basic of physics equations, the kinematic equation to find position. Since x does not have an outside force on it, acceleration is zero and we get the equation: 


xf and xi subtracted is the difference (delta) x which in turn is distance:


Again using the kinematic equation for the y axis for velocity, we can represent the initial y velocity as:


Again knowing that final y velocity is zero, we can rearrange that equation as:


We can rearrange the x axis formula two above as:


Plugging t into the x axis formula, we get:

Using basic Algebra, we can rearrange this to be:

Now that we have an initial velocity, the Imp can now jump to the next platform. 

There are some problems with this implementation, and that is it does not take into account where the imp is and the dimensions of the platform. The imp can be below the platform and jump straight into it. The other problem is that the imp will always be one step behind. The hero can be jumping up several platforms and the imp will only know when it lands on the previous platforms. There are ways for the imp to follow the angel up the platform and anticipate where the angel will be using more advanced algorithms. For the moment, this algorithm is sufficient for a basic low level enemy and does provide some basic challenge above the walking back and forth goombas. At least the imp is trying. 

That is all while I finish to complete my tech demo and get the first level finished. Game Maker doesn't make it easy as well as I have to forget everything I learned as a CS major to get some things to work also a debugger that doesn't let you step through your code.

Wednesday, October 3, 2012

Game Maker: Physics Engine and Globals

Physics Engines are one of the greatest things that a developer needs when making a game (especially a platformer game). It makes collision detection vastly easier and creates smoother transition and motion that looks more normal. But there are so many engines out there and half of them defunct. Finding a right one, then hooking it up to your project, and making sure it works correctly is no small task.

For Fallen, I have to link up a physics engine to make collision detection easier when the sprite moves and jumps on platforms and slopes. The built in functions to do this are too jagged and sloppy and are just simply horrible and convoluted to do anything useful. Thus I had to hook up a physics engine to my game. That is where the problems started.

When I first started looking I came across an engine called GM Physics. It seemed promising and the initial reviews for it were favorable. I hooked it up and looked at the demos to see what to do with it. The demos has no comments explaining what each function did and when I looked online to find out, there was no documentation of any kind. This proved problematic as I had no idea what to do with a library that didn't tell me what it could and could not do. I spent a good 2 hours trying to find something to help me with the engine, but to no avail. It was when I came upon a forum when I found out that the developer had stopped development some 2 years ago and had many internal bugs that were not going to be fixed any time soon. I had to give up my search with GM Physics and try again.

I started my search again and came upon an engine called Extreme Physics (http://www.maartenbaert.be/extremephysics/). I found out that the developer has not given up on it and is still coming out with updates for bug fixes. This was my first good sign. There were some good reviews on it too, and the fact that there was a page of documentation explaining what the functions were called and what they did. The explanation and the documentation is poor in my opinion, but it was better than nothing and what I've seen from Game Maker, it is the best I'm going to do.

I hooked it up and followed the demo on how it did collision detection for hitting into boxes. I was initially stuck since when I hooked up the bounding boxes to the player and the platform box, the player always started out knee deep into the floor. Upon inspection and a few hours of agony, I was able to figure out that the way I set up the bounding boxes, was wrong. When I made the box, I set the width and height as the right numbers, but the x and y coordinate was wrong. I set is as 0,0 which should make sense if the way it sets it up is like any other language sets up a box. However, this apparently offset the box down and to the right since my player would get stuck down in the ground and get stuck to a wall if he jumped to the right, but not to the left. The way I had to fix it was to set my x and y as half the width and height. This fixed my problem and my player can jump on platforms very smoothly. I really hate when developer don't explain details like this and assume that you should know. Its okay for developers to stray from convention and what other languages do in a similar situation. But you have to explain why you strayed and how the new way works to avoid people spending hours figuring you weird convention out.

Starting to feel that I have this collision detection down, I started to work on the player walking up and down ramps. This requires the use of a bounding triangle. The way that I did it was by creating a polygon and attaching it to the ramp. I created the polygon as the documentation and the demo instructed. I even attached it as the demo showed. However, that was not enough as a error showed that said the polygon was not convex. I thought this impossible, because a triangle only having three sides would only be convex and never have a vertex that defiled the meaning of a convex polygon. Instead of fixing it, I decided to take a break already spending several hours just that day figuring out two different engines and running into many brick walls.

When I had finally came back to the problem, my initial guess was not that it was or was not convex, but that I just built it in the wrong order. Past experience has showed me that when you build a polygon, that if you construct the vertices in a counter-clockwise way, then the side that would be culled would be facing towards the camera and that in order to get the right way showing was to construct the vertices in a clockwise way. I thought that this may be the same reason too, but for some reason didn't pursue it. About 30 minutes passed of playing around with values with no result was when I decided to construct the vertices in a clockwise manner. To my thrill it worked, my player could walk up and down ramps now. However, the motion up the ramp is still jittery and I believe I can fix it, I just need to play with the values a bit.

Hooking up the collision detection took a vast majority of my time, but when I wanted to take a break from it (after I got the platform and ground working), I decided to add two different rooms that were part of the level. In order to do this I needed to keep track of what the previous room was so that the player could end up in the right spot in the next room and facing the right direction.

I created an exit trigger (just a square), that would start the event to transport the player to the next room. If this was regular code,then each instance of the object I created would have a global variable that showed what room it was currently in so it would be easy to set up the player. At this point, my interpretation of how variables worked was based on how other languages did it. There are three ways to set up variables  in Game Maker:

  1. global.varName
  2. var varName
  3. varName
My initial misreading of the documentation was that to var and global.varName was the same way to set up a global variable while varName was a local variable that would only exist for that function (script). I also initially thought that a global variable was only global for the object. Then when I did obj_name.global_var did I figure that that didn't work. So I decided to create a getter method that would return global.varName. Game Maker didn't like that either and would always throw a bug when I did it like that. I spend a good hour online trying to figure out what to do when I came across a youtube video explaining variables in Game Maker. It was the moment that he said that global.varName would create the variable that was global to all objects in a game did I realize that I had it all wrong. 

I went back to the documentation on variables to see what else I got wrong, when I figured out that varName was global to the object and could be called like obj_name.varName and that var varName was only local to the script it was in. After this realization, using variables and being able to pass them around became significantly easier. I will have to go back in my code sometime and change around variables that were initialized under my false presumptions to something that actually fits convention and good programming style. 

I have now figured out that Game Maker has changed the game on many things with programming from what they normally are in more C based languages. I now just wonder how many more surprises I will face.

Friday, September 28, 2012

More Game Maker and GML

Learning a new programming language at this point in my academic career is not that hard. If the language has great documentation (I'll usually just settle for documentation), and a forum  of developer for that language that discuss the language and syntax I can get the language down and making programs beyond that of a Hello World or Linked List within a week. If that language is a scripting language, even faster.

I have however came across some languages that have poor documentation, and the forum that discusses them is lucky to get any traffic. This is usually rare since the languages worth programming in have great support and a great community that helps those in need. Game Maker has neither.

For those of you who don't know, Game Maker is a drag and drop (with a "scripting language" attached to it). It greatly speeds up development since you can get a prototype of a typical flash game that you can find on Kongregate in just a week. This is if you use the drag and drop. Game Maker does have its own language called GML. If I were to compare it to another scripting language, its syntax is similar to Javascript. I decided to play around with GML and get the basics so that I can get into development without too many bumps as possible.

When writing code for GML. you just write a snippet of code (a script) and attach it an object to perform that script. Unity has a very similar design to this (that's where the similarities end) where their scripting language you can choose between C# or Javascript. This is a bit strange to get a grasp of since I'm more use to programming using objects like in C# or C++. Thinking about it, it is very similar to that type of programming. You can make an object (foo.cpp) where you can attach events to that object, i.e. the create event (the constructor) and a destroy event (the destructor), where they will initiate the script that you've written. That's not bad, in fact I could actually learn to use it. It's what happens in the script where the problems lie.

My biggest problem lies with collision detection and general physics. The way to detect a collision detection is place_free(x,y). It will tell if the object collides with another object. It is however really buggy. Half the time, my object goes through half another object (mostly the floor), where the character can move around and still jump. I've checked the hit rectangles and they seem to be fine. I've tried looking online, but an unhelpful community and poor documentation doesn't reveal anything. When my character jumps and goes into a wall, he sticks to the wall and will release if you move away from the wall. This has cost me more unnecessary time on debugging and figuring out what GML is actually saying.

The thing is I've done all of those things successfully without too much error in openGL c++ and actionscript 3.0. With a little math and some built in functions, it is all possible without too much headaches, it just takes a little more time. I've tried doing what I would normally do in actionscript or c++, but GML complains even more when you do what it doesn't want you to do. When I want the character to move horizontally I have to specify hspeed and not x += velocity. When I do use x += velocity, it creates a jigging effect where the character moves forward by 5, stops for a moment then moves forward by 5 again.

One of my teammates, who practiced with Game Maker using the drag and drop commands replacing the script found it easier and did more in the same amount of time. I would use do that except for that of my pride, and there are some things you have to do using GML to make the best game (comparatively) that you can using such a primitive tool from hell that rivals that of Fortran.

I'll get it eventually, fighting a language is like fighting any other language; just give it enough time and the battle with always be won. Then the cycle repeats itself when I have to find a better physics engine for Game Maker. I am looking  at two right now (GMPhysics and Extreme Physics). Both of which require use of GML.

Friday, September 21, 2012

Game Dev 1: Pitch, Fallen, and Game Maker

This post will be catch up to what I am doing in the development process in Game Dev 1... The class Game Dev 1 (Film 3710) is basically making a game in a semester using a pre-existing engine (Unity, Unreal, Game Maker, Game Salad, etc). The game will usually be in the fashion of a flash game-esque and won't be as expansive as I would like. Though a semester to make a game is better than 2 - 4 weeks. This development process will be from pitch, to game design document, to development, to testing, to release. My team is already doing level design and working out game flow and the mechanics of the game, so I will go through of my initial pitch.

Pitch:

About 2 weeks ago from this posting, I gave my pitch for a game I made up on the spot (I was just happy to do someone else's game). The reason for this is because, I do have some great ideas for games that I will present for my capstone project and maybe a person project (If I can become good friends with an artist).

My game idea came for the idea of a Halloween costume. I love steampunk, and I too love Victorian attire (especially an aristocrat with the top hat, cane, and monocle). So I decided to go as Death if he were an English gentleman. This costume is just the Aristocrat attire with a skull face mask and a skull cane. The main character in my game would be death in his attire. A soul was able to escape from the Underworld and escape to the world above and posses many humans. Death must go above and reclaim that which he lost while trying to either kill or save those who are possessed. This game is a 2D side scroller and relies heavily on visual gags. This was a game I would not make (I probably would save the character of Death for a different game), but need to give a pitch for a grade.

For the actual pitch, since I didn't care for my idea I decided to rely on showmanship and dressed up as my Halloween costume. I was the only one to show up and I did receive some positive feedback about the game. Not surprisingly, I didn't go ahead with the idea. When teams of 3 were formed, we decided to make a different game (one for the better).

Fallen:

We formed into teams of three (1 programmer, 1 artist, and 1 producer). This setup does worry me a bit since I am the only programmer and will have to do all that responsibility for the entire game. I was initially thinking that when we got into the teams of 3, we would improve the game idea and present that to the class, and the professor would merge some teams together to have a bigger development team, but as time goes on I doubt it more and more.

When my team met, we decided not to do any of our ideas and form an idea from a genre that we all love (RPG). We decided to center our game around a fallen angel who has fallen to depths of hell and must escape.

Elevator Pitch:
Thrown out of heaven for somewhat trivial reasons, an Angel finds himself at the bottom of the 10 realms of the underworld. Fighting his way back to the surface the angel must choose to seek vengeance or offer mercy to those he believes has wronged/betrayed him. Fallen is a Action RPG 2D Platformer with puzzles to solve, demons to fight, bosses to suppress and a choice between good and evil to make.
I really like this idea, since it allows us to really get into the visuals and atmosphere. It will also allow me to practice my coding experience on platformers. I believe that if this is done correctly, then it will be an awesome game.


The game is an RPG because the player can choose between three trees (Vengeance, Justice, and Mercy) which represent warrior (melee), ranger (ranged), and mage (magic) respectively. The player can level up each tree and will have a certain weapon that goes with each one (sword with Vengeance, bow with Justice, and staff with Mercy). We are still deciding how a player can switch between the trees or if they can select just one tree at the beginning and they are either Vengeance, Justice, or Mercy.

At the start of the game, the player starts in the bottom of Hell where he must climb out. He faces tougher and tougher demons as he levels up. When he escapes the pit, he has a choice if he will join the demons and invade Heaven and exact revenge on the angel who cast him out. Or rejoin the angels after a brief confrontation and go back to the pit and destroy hell. This will most likely leave a cliffhanger for a sequel that will most never happen.

There are some pitfalls that I do forsee and have currently seen my teammates and myself make. That is we make this game too big. The scope of this game is an epic adventure like most other RPG's. If we had the time and resources this game could have been a AAA game that was fully 3D open world RPG (much like Dragon Age). The choices can be more integrated to show a transform into either a fallen (dark) angel or an archangel (good) both equally as powerful. Like with everything, we won't be able to put everything we want in, but with only a semester for a development time that will be even more so.

Game Maker:

Because we have only a Semester to this game I cannot make this game as I have made it in the past using an IDE and a language (C# using XNA or C++ using QT). I am forced to use a pre-existing engine such as Unity, Unreal SDK, Game Maker, or Game Salad.

I really want to use either Unity or Unreal SDK because their tools are just simply awesome and the scripts they use are actually languages (for example javascript and C# are used for Unity). Game maker uses a bastardized language called GML and Game Maker doesn't even have a scripting language you can use. In fact, one person even went as far as saying "Meet the startup that is going to make programming a thing of the past." The Article. The reason I can't use Unity or Unreal is because they are 3D engines and don't do 2D. You can technically do 2D since its just 3D, but the loss of a dimension but it won't have that flash feel to it and would be awkward to program. I tried Game Maker and even though its alright, I really would rather not use it. If I could, I would like to use Flashbuilder to make this game, but I would need another programmer or more time to do that. Therefore, I have to use Game Maker for this semester.

Game Maker is you drag and drop program for those who don't have any programming experience. While it does have a scripting language (GML) which is similar to javascript, its rather clunky and finding documentation for it was the biggest pain in the ass. There are ways to make this game without writing a single line of code, but it would be similar to how Scratch writes code and that you drag a block of code into a window that does a certain command, a conditional, or a loop. It takes all the joy out of programming and the feel of accomplishment when your eternal fight against the OS and compiler has a temporary victory when a block of code starts to work.

That is all for now. I'll write again in the next development phase, when my team has planned out the flow of the game and the layout of each level.

Summer Project: CSV Parser

Welcome to the third and final installation of the Summer Project series. This project, although isn't having me fix bugs 3 months after release, was the biggest project and did require the most knowledge of certain servers (Mostly LDAP and Active Directory LDAP). This application takes in several .csv files (a file that has a list of students and certain attributes) and creates an Engineering account for them. This application has many parts to it that made it possible:

  • CSV Parser
  • Create Account
  • Create Cards and allow to download
  • Setting up the csv files from the user
These were originally a series of perl files that a person would have to do manually in a linux terminal. My task was to take these perl files and port them into php and have the user (my boss) just select which csv files he wants to add and the code does all the rest. Note: porting perl to php can be an excruciating task (especially when translating regular expressions).

Setting up the .csv file:

In order to parse and process the csv files, the user will have needed to provide some. The first thing that needed to be done was to allow the user to open up a file explorer and select the csv file. This can be done using this html tag

<form action="formatfile.php" method="POST" enctype="multipart/form-data">

     <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />

     <input type="file" name="inputFile" />

     <input type="submit" value="Add File" />
</form>

It has to be in the from because when the user does select "Add File", then it will upload that file to the server into a tmp folder. Adding a file to the tmp folder proved to be difficult because all folder have a default mod of 755 with the user as root and the group as apache. Some people online suggested to chmod it to 777 to allow apache to add. This would be disastrous and I was surprised that they would suggest it. With a security setting of 777, anyone can write anything in the tmp folder whether it be javascript files or other scripts. I needed to find a way for apache to write to the folder without anyone else. Since apache belongs to the group apache, a security setting of 775 would allow apache to write to the folder and no one else. 

When the file is uploaded, it is stored in a temporary location in $_FILES, that if left will be deleted. Therefore, I had to create a helper script to move the file from the tmp location to my more permanent tmp folder on the server. The script would also check to see if the file was really a valid csv file before adding it to the folder. 

After the file had been uploaded, the index page then moves on to show all the files that are uploaded where the user can add more files, remove some files, or parse the files which leads me to:

CSV Parser:

The CSV Parser goes through each line of the .csv file and extracts the relevent student information (name, uid, major, class). From there it puts it in the Create Student script (to be covered below). From there it will print the student information out and how much it completed (in percent). When testing, this process can take about 2 - 3 hours just to parse and add some 2000 students. I have no idea why it takes so long (though I do expect it has to do with adding to AD LDAP (connecting to Windows). After it does this for each .csv file, it will then create cards for each class they are in (i.e. CS1410-001) so that the teacher can hand out their account information at the first or second day of class (for those who request it). Part of the information that is pulled out is what engineering class they are taking. This is able to work too since each .csv file is just a department (i.e. MSE, BIOEN, CH EN, CS, ECE, ME EN). (The card generating algorithm will be covered below). 

This was the first script that I made that I had to port from perl. The way the perl script extracted the information from the line was that each information was at a certain point (uid took up the first eight, name had the next 50, etc). The perl script was able to use regular expressions to get it. 


($uuid,                 # (8)

   $fullname,             # (50) LAST, FIRST MIDDLE|M.I.

   $adm_stat,             # (4)  admission stat   (??)

   $major,                # (4)
   $degree,               # (5)  degree
   $enroll,               # (2)  enrollment class (??)
   $flag,                 # (2)  ???
   $colldes,              # (2)  college descriptor
   $coursedept,           # (5)  course department
   $coursenum,            # (4)  course number
   $coursesect,           # (3)  course section
#  $credithrs,            # (3)  credit hours
#  $grade,                # (2)
#  $crnocrf,              # (1)  credit no/credif flag
#  $courseti,             # (8)  course title INDEX (numeric)
#  $coursetitle,          # (30) course title       (descriptive name)
#  $addline1,             # (35) address line 1
#  $addline2,             # (35) address line 2 (seems to be empty)
#  $city,                 # (14) 
#  $state,                # (2)
#  $zip,                  # (5) ) = /^(\d{8})(.{50})(.{4})(.{4})(.{5})(.{2})(.{2})(.{2})  (.{5})  (.{4})(.{3})/;

Since in php, regular expression are a pain to do, I decided to use a substring(currentLine, index of first char, length of string). This took some fine tuning since my reading of regular expressions isn't the best. From the information extracted, the script would then translate some of it into what the Create Student needed. $degree would be used to determine class (bs, bhs => ugrad AND phd, ms, men => grad AND all else => class). All trailing and leading whitespace would be removed. Then their major would be translated into the department they belonged to (CS => cs, ME EN => me, etc). From there, all the information would be put into an array to be processed by the Create Student algorithm. 


        $MAJOR = array(

            'BIOE' => 'be',

            'CECS' => 'ce',

            'CFEN' => 'ch',

            'CHEN' => 'ch',
            'CPSC' => 'cs',
            'CVEN' => 'cv',
            'MEEN' => 'me',
            'ECE' => 'ee',
            'MSE' => 'ma'
        );

        $COE = array(
            'CS   ' => 'cs',
            'ME EN' => 'me',
            'ECE  ' => 'ee',
            'CHFEN' => 'ch',
            'BIOEN' => 'be',
            'CVEEN' => 'cv',
            'MSE  ' => 'ma',
            'CH EN' => 'ch'
        );

        $uid = trim(substr($line, 0, 8));
        $fullname = trim(substr($line, 8, 50));
        $major = trim(substr($line, 63, 4));
        $degree = trim(substr($line, 67, 5));
        $coursedept = substr($line, 79, 5);
        $coursenum = trim(substr($line, 87, 4));
        $coursesect = trim(substr($line, 91, 3));

        $name = explode(',', $fullname);
        $name1 = explode(' ', $name[1]);

        $last = $name[0];
        $first = $name1[0];
        $middle = count($name1) == 2 ? $name1[1] : '';

        $first = ucfirst($first);
        $middle = ucfirst($middle);
        $last = ucfirst($last);

        if(array_key_exists($major, $MAJOR))
        {
            if($degree === "BS" || $degree === "BHS" || $degree === "MIN")
            {
                $rank = 'ugrad';
            }
            else if($degree === "MEN" || $degree === "MS" || $degree === "PHD")
            {
                $rank = 'grad';
            }
            else
            {
                $rank = 'class';
            }
            $dept = $MAJOR[$major];
        }
        else
        {
            $dept = $COE[$coursedept];
            $rank = 'class';
        }
        
        $student = array(
            'First' => $first,
            'Middle' => $middle,
            'Last' => $last,
            'Uid' => $uid,
            'Dept' => $dept,
            'Rank' => $rank,
            'CourseNumber' => $coursenum,
            'CourseSect' => $coursesect,
            'CourseDept' => $coursedept
        );
        
        return $student;

Create Student:

This algorithm was originally created by a coworker who created this so that an oper can create an account for a student who did not get one in this process. While his algorithm was good, I had to do a lot of work to make it work for my code. For instance, he used a framework made by code igniter. I tried to get it to work at first, but there were a lot of errors. I gave up and made the code from scratch. This was a long process, but I was able to get it to work at the end. 

The first thing the code does is to create the attributes for the user to insert on LDAP (Linux side). The attribute is using the information extracted from the CSV Parser and some new information using it such as UID (user id for chmod), GID (group id for chgrp), a username, location of their home directory, and a random password that is encrypted. 

The username is generated by using a combination of the users full name (usually the first name with last initial, or first initial with last name). It will test each try and go on to the next if the suggested username is already taken. It will then see if the user already exists. If the user already exists, then the code will terminate, tell the user, and go on to the next student. 

If the student is valid, then it will connect to ldap and add the student using ldap_add. If at any point, ldap connection or ldap_add should fail, it will tell the user and go on to the next student. 

When the student has been added to LDAP, it will then create the student on Active Directory LDAP on the windows side. This required a third party library (ADLDAP).

AD LDAP:
Author Scott Barnett, Richard Hyland
Copyright (c) 2006-2010 Scott Barnett, Richard Hyland
License http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
Revision $Revision: 91 $
Version 3.3.2
Link http://adldap.sourceforge.net/

In order to create an account on the windows side, this required me to redo the attributes and add a few categories. These changes were to revamp where the home directory was located on the windows server, add a description (their uid), create .win_profile path, and tell which OU the student belonged to. 

After that, AD LDAP was able to add the student to the server and add them to the ENG Student group. Of course if any of that failed, then the code will tell the user and go on to the next student.

After creating the account on both the windows and linux side of LDAP, the script will then create the students home directory where they will have access to all their work. This is a very simple script that calls another unix script that does all the dirty work. 

      if(preg_match('/[^a-z]/', $user))
            {
                throw new Exception("Illegal Username: " . $user);
            }
            $cmd = "$sudo $homedir " . "$user $uid $gid" . ' 2>&1';
            exec($cmd, $output, $returncode);
            //var_dump($output);
            //var_dump($returncode);
            if($returncode != 0)
            {
                throw new Exception("Could nt create homedir: " . implode("\n", $output));
            }
            return true;

That is all the Create Student account needs to do, the student is ready to use his/her account. The scrip then returns the users password and username for the Card Generation algorithm.

Card Generator:

After the student has been created, then the array that was returned by the Create Student algorithm is added to the $student array that was generated by the CSV Parser. The student is added to a 2D array where the row are Class numbers and the column is the Student's uid where the $student array is stored at that location.

$course = $student['CourseNumber'] . "." . $student['CourseSect'];
     
        if(!array_key_exists($course, $courses))
        {
            $courses[$course] = array();
            $courses[$course][$student['Uid']] = $student;
        }
        else
        {
            $courses[$course][$student['Uid']] = $student;
        }

When the parser is finished with each .csv file. The 2D array is then parsed over in a double array where each class and the students in each class is added to a txt file with the class name one it. That file is then temporarily stored in the cards folder in the server.


foreach($courses as $course)
        {
            $tmp = array_values($course);
            $title = $tmp[0]['CourseDept'];
            $courseNum = $tmp[0]['CourseNumber'] . "." . $tmp[0]['CourseSect'];
         
            $ourFileName = "cards/accounts." . $title . "." . $courseNum . ".txt";
            $file = fopen($ourFileName, 'w')
                    or die("Can't open file " . $ourFileName);
         
            foreach($course as $student)
            {
                $fullname = $student['Last'] . ", " . $student['First'] . " " . $student['Middle'];
                $lineBreak = '-----------------------------';
             
                fwrite($file, $lineBreak . "\n" );
                fwrite($file, $fullname . "   CADE Lab Login: ". $student['Username'] . "   Password: " . $student['Password'] . "\n");
                fwrite($file, "\n");
                fwrite($file, $student['Uid'] . "          To change your lab password, type 'passwd' at a UNIX prompt.\n");
                fwrite($file, "                  Use 'remote_passwd' to set your password for remote services,\n");
                fwrite($file, "                  such as POP mail or FTP.\n");
                fwrite($file, $lineBreak . "\n");
                fwrite($file, "\n");
            }
         
            fclose($file);
        }
     
        Zip_And_Download();



function Zip_And_Download()
{
    exec("zip -r cards/cards cards/");     
    echo "<a href='download.php'>Download cards.zip</a><br />";
}


After each file has been made, then the user can download each file in a .zip file; however, if they were to refresh the page or clear it, then the cards folder would be wiped clean and could never be gotten again (excluding .snapshot) because the script won't add the same students twice once they've been created.

Downloading a zip file is a lot simpler than it seems.


    header('Content-Type: application/zip');
    header('Content-Disposition: attachment; filename=cards.zip');
    readfile("/home/kray/public_html/UserCreateTemp/cards/cards.zip");


That is all for the CSV parser. I couldn't post as much of the code as I would have liked to due to security and me liking my job. This concludes the Summer Projects series. I am now in full development in my Game Dev class and I will be focusing on that for this semester.

Monday, September 17, 2012

Summer Project: CoE Network Request

Welcome to part 2 of the Summer Project series. The second project I made was a Network Request form for people to request access of their computer to the College of Engineering. This was the easiest project of the summer. This is quite simple as the there was only two major pages. The form and the database.

The form is a basic form where the user enters in basic information about them (name, email, department, etc), where computer is located at, and basic information about the computer (name, mac address, and port). With this information an email is sent to the opers where one will connect their computer to the Network. Also the mac address is check against the other address on the database to detect a duplicate. If there is a duplicate mac address, then the system asks the user if they still wish to proceed with the conflict. If they do proceed, then the request is sent to the opers and the information is stored in a separate table where the oper can decide if the conflict should override the current entry. If there should be an override, then the current entry will be deleted and replace by the conflict. This is extremely rare because of the uniqueness of mac addresses.

There is a separate page where only authorized people can view all the mac address in the system and potential conflicts in another page. Since a request comes in nearly every day, the number of mac address in the system is numerous. So the page doesn't load every single mac address in a single page, I made it similar to what other large lists do (split it up). Only 10 mac address would show at any one time, with a series of numbers below that the user can use to jump to any set of mac address (<first 1 2 3 ... (n -1) (n) last>).

Also on the page is a search box, where the user can enter in a mac address and when enter is hit, it will pull up the information on the mac address (if it exists). This is the same for the conflicts tables as well.

That is all for this. I know it wasn't too interesting, but the project itself was very small and not like the Reservation system which had an interesting algorithm to show. The final part of the series will be a CSV Parser where it will take in a list of students and create an Engineering account for them. This will be just as interesting as the Reservation system with some good algorithms to show off.

Friday, September 7, 2012

Summer Project: Reservation System

This is the first part of my Summer Project series. My current job is working the help desk at a Linux lab for the College of Engineering at the University of Utah. During the school year, I am expected to help student with problems they incur when using a Linux. During the Summer, I do some actual programming that my boss needs to get done at the time. I know that this isn't games, but it is programming and the experience will help greatly in my endeavors.

Each of these projects that I did were Web Applications written in PHP. I don't like PHP. It is a poorly written language that doesn't know when to die. Half the time is me fighting PHP when it doesn't do what I need it to do and when it doesn't crash when any other language would crash. Its too lenient when the programmer makes a mistake and the array that is an abomination of a hash map. For all the problems I have with PHP, the reason I still choose to program with it instead of JSM or Ruby on Rails is that first, I know PHP; and second, PHP has built in functions to connect to LDAP.

 The first project I did was a Lab Reservation System. The lab I work for (CADE) is one in seven labs, either windows, linux, or mac. Not only are these for students to get work for, but some are teaching labs and used by professors to help teach their engineering class. These labs can also be used for other purposes, such as summer camps or orientation, if they ask permission first. Now enter in the reservation system. When my boss approached me, there was already a reservation system in place. The layout was horrible and the person approving the request would have to enter in the entry into the SQL server by hand. My job was to completely rebuild it.

I started out by turning my computer into a temporary apache server and database for testing purposes. Getting the layout and css was a lot easier than I imagined because the College of Engineering already has a layout ready to use. From there, I set up the index page to list all the reservations that were approved. A page for a forum to submit a request, and a page that only admins could access in order to approve/deny requests.

After all that was set up, I created a separate script that would check to see if the request had any conflicts. If it did, it would let the user know; else, send the request through to be approved. Checking for conflicts proved to be the most nightmarish part of the whole experience and had flaws in it even past release. The last bug report I got about it was three months after the reservation system was released.

The way I did check for conflicts was to start out general and keep shaving off requirements that did conflict until the program was certain that there was a conflict. Here is the overview of it in pseudocode:

$requestorsInfo

foreach(person in the database as $databaseInfo)
{
     //both want same lab
     if($databaseInfo->lab == $requestorInfo->lab)
     {
            //if the range of dates they want for overlaps with the other
            if($databaseInfo->dateRange conflicts with $requestorInfo->dateRange)
            {
                    //Even though the person specifies a range of dates Aug 8, 2012 - Dec 10, 2012
                    //They can only have it on a certain day of the week such as Tuesday, Thursday
                    //Therefore this will check to see if they both want the lab on the same day of the week
                   if($databaseInfo->dayWeek conflicts with $requestorInfo->dayWeek)
                   {
                           //If they both want it at overlapping times, then that seals the deal. There is a conflict
                          if($databaseInfo->timeRange conflicts with $requestorInfo->timeRange)
                          {
                                  return true //there is a conflict
                          }
                   }
            }
     }
}
return false //there isn't a conflict.

Finding a date conflict took a bit of thinking, but after picturing all the different kinds of overlap might look like, I was able to form a boolean expression to determine conflicts in time.

s1: start date for the requester
e1: end date for the requester

s2: start date for database entry
e2: end date for database entry

Conflict 1:
s1                              e1
|--------------------------|
                 |--------------------------|
                s2                                    e2

Conflict 2:
                   s1                          e1
                    |------------------------|
|-------------------------|
s2                                 e2

Conflict 3:
s1                                       e1
|-------------------------------------|
           |--------------------|
          s2                           e2

Conflict 4:
           s1                        e1
            |------------------|
|---------------------------------|
s2                                               e2

Conflict 3 is true if Conflict 1 AND Conflict 2 are true, so we can remove it from the boolean expression since it is enough if Conflict 1 OR Conflict 2 is true.

The boolean expression is:
($s2 <= $e1 && $e1 <= $e2) || ($s2 <= $s1 && $s1 <= $s2) || ($s1 <= $s2 && $e2 <= $e1)

When calculating the date, I make a gaffe early on. The database takes it in the from Month_Day_Year and stores each part in an array. The database also returns it likewise. When the project was "complete" and I was taking it into beta testing, I read about the Date field for SQL and that it could do such comparisons. However, since the project was so complete, I choose to stick with what I had and work out the bugs instead of choosing to rewrite my code and rearrange my database in an attempt to do the least amount of work possible. I still keep it as is after doing more work debugging because it does work and I am really lazy about rewriting code and reworking the database.

Since I choose to stick with what I had, I needed to represent the dates as value in order to compare them. I could have used a lot of conditionals if the months were the same and if the years were the same, but that felt like more work that was needed. I then decided to split the month, day and year. That of course did not work. After some more thought, I decided to represent each date as a unique integer that could be compared a lot easier. By turning the month into how many days until that event (January would be worth 31 and February would be 59 or 60 depending on the year. Then summing each value up (i.e. January 1, 2012 would be 31 + 1 + 2012). This will produce a unique integer that can compare any date of any year.


To check the conflict of the day of the week actually gave me more problems than I had expected and was the last part that was responsible for bugs even three months after release. A conflict happens when there is at least one day of the week that both people want (i.e. a wants Tuesday Thursday and b wants Wednesday Thursday). The day of the week that a person wants is stored in a array of bytes.

$dayWeek = array(
            'Monday' => 0 | 1
            'Tuesday' => 0 | 1
            'Wednesday' => 0 | 1
            'Thursday' => 0 | 1
            'Friday' => 0 | 1
            'Saturday' => 0 | 1
            'Sunday' => 0 | 1
);

1 if they want it, 0 if not.

A conflict should return true if you go through each day of the week for each comparing the two and ANDing them together. If any AND returns true, then there is a conflict. There were two things I tried before I go (I believe) the correct solution.

Try 1:
 return ($requestor->$dayWeek['Monday'] == $database->$dayWeek['Monday']) || ($requestor->$dayWeek['Tuesday'] == $database->$dayWeek['Tuesday']) || ($requestor->$dayWeek['Wednesday'] == $database->$dayWeek['Wednesday']) || ($requestor->$dayWeek['Thursday'] == $database->$dayWeek['Thursday']) || ($requestor->$dayWeek['Friday'] == $database->$dayWeek['Friday']) || ($requestor->$dayWeek['Saturday'] == $database->$dayWeek['Saturday']) || ($requestor->$dayWeek['Sunday'] == $database->$dayWeek['Sunday'])

The reason this didn't work is because I was treating the 1 and 0 as booleans and not integers. False == False is False, but 0 == 0 is true.

Try 2:
return $requestor->$dayWeek === $database->$dayWeek

This would only work if the user and database wanted the same days of the week and were clones of each other. I should have figured this out at first, but I was pretty lazy.

Implementation:

foreach(dayof the week as $i)
{
      if($requestor->dayWeek[$i] == 1 && $requestor->dayWeek[$i] == 1)
             return true;
}
return false;

This was basically the 1st implementation (Try 1) had the compiler treated 1 and 0 as bools and not integers.

The last conflict check was for the time. This works the same way as the Date checker. The only exception is how it compares times. The time that is inputted is in the 12-hour format. The program takes the the time and converts it into the 24-hour format and then converts the hours into minutes and sums the two up. This creates a unique integer that can be compared easily.

That is the algorithm that checks for conflict in a request. I would like to see how a more complicated system would check for it (like hotel reservations). The rest of the code is basically a bunch of calls to the database to either remove entries, add them, or manipulate them to present to the viewer.

That's all for the Reservation System. It was definitely a challenge and really helped my problem solving. Next part int he Summer Project Series will be CoE Network Request which will not be as long as this one.