Saturday, June 21, 2014

Dev Blog #2

Saturday, June 21 2014

Well, here we are, the end of Senior Project and the end of my career at DeVry. I am really excited to be done and to get on with my career, wherever that may take me. I am grateful for all of the friends I have made and for the professors who made the program fun and interactive.

Anyways, onto the project details. Since we are in the final few days of the session, we are all scrambling to fix little bugs and mistakes and get things ready for the final build and presentation. We have a trailer to put together, websites to make (for ourselves) and a host of bugs to fix. I FINALLY GOT THE PHYSICS TO WORK. I feel really dumb about it, as I was using a few wrong formulas, not to mention that the actual temperature of the atmosphere is not linear in terms of height, but more of a piece-wise function. So, it works really well now, and that model I found at the beginning of the project really helped me out. Since fixing the physics, I have been working on getting the 3 cinematics for the game ready to be implemented. I finished the final one earlier today, and used the same process as in one of my earlier blogs from the previous half of Senior Project. However, I used a different conversion software this time around, as the last time I converted the video files, they did not work at all in Android. They work now, we are just trying to iron out some resolution issues we are having. Android devices come in all shapes and sizes, and with different sized screens. Finding a resolution for the videos that will look nice on all of them is a real pain. But, I did learn a lot more about 3DS Max and animation than I knew before. So, at least I learned something.

I do not know if/when the game will be released, as it is a client based project and our client just so happens to be our professor. The entire game was his idea, our group was just the vehicle for bringing it to life. He has some plans for after we graduate, which I will not detail here. It may or may not come out, and I may or may not announce that on this blog. So, keep your eyes peeled on the Google Play Store and here to see if it gets released or not. We are all very proud of how far it has come in a short 16 weeks. We took an entirely code approach to this project, and I couldn't be happier with the results. Even though none of us are professional artists, the game looks really nice. We plan on entering it in the DeVry Senior Project Showdown. Google it and vote when voting opens. Take us to the top!

Since this is my final blog of my DeVry career, I do not know when/if I will be back here. I hope to keep on making games in my spare time, and might detail them here. Or I might make this into a place of learning for the code newbies who scour Google and blogs for hints and tips on programming. Who knows? Right now I am focused on my job search, as is to be expected of someone who is graduating in 8 days.

As always, thanks for reading and staying with me through all of these years. I enjoyed blogging about my projects, and I hope you enjoyed reading about them. Maybe you even learned a thing or two.

Monday, June 9, 2014

Dev Blog #1

Monday, June 9 2014

It is now Week 6 of the second portion of Senior Project, and I probably should have done this blog awhile ago. However, things have been moving quickly with the project. We have an animation system in place to animate the space jumper as he does his tasks in Phase 1, a media player for cinematics (which was supposed to be done in the first half of this class, but I won't go into details), acclerometer controls, improved models and ones that didn't make it into the first half of this class, and a bunch of other things that I am probably forgetting. Anyways, onto my problems with the project.

I was told by one of our other members that my physics was off. I knew things needed to be tweaked and worked on, but what I did not realize is that the way I am calculating temperature as a function of height was completely wrong. Take a look at the picture at the following link:

Click here to see picture

As you can see, the temperature in the Earth's atmosphere is more or less a piece-wise function. It is rather strange, as you would think that going higher in the atmosphere would make you colder. Well, it does, for the most part. But between 10-20 Km above sea level, the temperature doesn't change at all, and there are some other weird things going on as you go higher. So, using some linear algebra, I was able to come up with some formulas for how to solve for temperature given some height. The way I was doing the calculations was strictly linear. As you can see by the graph, its not linear. For example, the temperature that was calculated in the first update call came out as 40 degrees Kelvin... yea not right at all. At that height, temperature is more like 248 degrees Kelvin (or around there). My temperature calculations still rely on height, but the formulas are different for different ranges of height. There are 4 different ranges, with heights between 10000-20000 meters not changing at all (as per the graph).

It seems to work better now. I should probably get going on the other 2 cinematics that I have to do for the game, as our professor wants us done by Wednesday.

Tuesday, April 22, 2014

Dev Blog #3

Tuesday April 22, 2014

Here we are, last day before our Alpha build is due and our presentation. The project has come a long way since the beginning. I would estimate that we are about 50-60% done, with most of the important features implemented but in need of bug fixing/more tweaks. I will talk about my physics tweaks that I did last night in a little bit. Everyone, save for a couple, did their work and contributed to the project. I applaud my team members for their hard work and dedication. Now, on to the good stuff.

So, yesterday August informed me that his text drawing for our HUD (that displays time, velocity and height) was crashing because the jumper would accelerate so fast that his speed became NaN almost instantaneously. I pounded my head against the code for awhile, then decided to comment out all of the physics I had put in and just simply make the jumper fall under the force of gravity. This allowed August to make sure his text was working fine, which it did. After that was done, I was not happy with having to scrap all of that nice physics code. So, I went back and looked over everything. I took out the gravity changes I made and put back in the original physics. I went through it line by line, and even did the calculations by hand for a couple of height values to make sure my calculations were correct. Turns out they weren't. Oops. Sign issues everywhere. I guess that's what happens when you are tired and coding at 2 AM, but I digress as there is no excuse for sign errors in the simple physics I used. I went back through it again, line by line, doing calculations by hand. I finally got all of my pre-calculated values correct (those not directly affected by height that needed to only be calculated once, and not on a per update basis. Saved us so many clock cycles and memory.) Then it was time to re-test my physics equations. Again, sign issues everywhere. I even had an arithmetic mistake (put something in the Java function Math.pow() that needed to be outside that function). Hehe, oops again. After re-writing that equation and doing hours of research to make sure that I was doing the physics correctly, I tested it one last time and HUZZAH it worked. But, with one major bug. The jumper accelerates just fine now and his terminal velocity (the real max velocity Felix hit, ~372 m/s or ~834 mph) but never slows back down. Don't know why or how. It will take a little while longer and some testing with our delta time value to see if it is a delta time issue (I think it is). But, for the alpha, it is fine as it shows that the physics model works.

Here is what the code looks like for our physics: (Keep in mind, its still a work in progress. Also, excuse formatting. Blogger doesn't have <code> tags...)

public void update(float dt)
{

//deltaT += dt;

//update the jumper's height based on the y component of position (since we are falling in the y direction)
height = position.y;

//updating our falling physics data
temperatureAtHeight = seaLevelTemp - (tempLapseRate * height);
pressureAtHeight = 1000.0f * (seaLevelPressure * (float)(Math.pow((1.0f - (height * preCalcPressureFraction)), preCalcPressureExponent)));
//pressure has to be in Pa, not kPa. so we multiply by 1000

densityAtHeight = (pressureAtHeight * molarMassOfAir) / (gasConstant * temperatureAtHeight);

//calculate air resistance
airResistance = new Vector3D(0.0f, 0.5f * densityAtHeight * (float)Math.pow(-velocity.y, 2.0f) * 0.579f , 0.0f);

//calculate net force
airResistance.add(new Vector3D(0.0f, -gravity, 0.0f));
//Vector3D netForce = new Vector3D(0.0f, airResistance.y, 0.0f);

Vector3D weight = new Vector3D(0.0f, mass * gravity, 0.0f);

acceleration = weight.subtract(airResistance).scale(1.0f / mass);
//from the formula a = (W-D)/m where W is weight, D in our case is the netForce and m is mass

//v = v0 + at
velocity = velocity.add(acceleration.scale(dt));

//check to see if we are at terminal velocity or not
if(-velocity.y > maxSpeed)
{
//if we are, we have to use -maxSpeed because we are falling in the downward direction, not up
//changing the sign below will cause the height to go back up after you hit maxSpeed
velocity.y = -maxSpeed;
}

//position = p0 + vt + (at^2)/2
position = position.add(velocity.scale(dt)).add(acceleration.scale((float) Math.pow(dt, 2)).scale(0.5f));
}

I was also able to complete the spacepod model and get it into the game. It looks really nice, especially after Matt L fixed some tessellation issues with the models themselves. I was also able to complete the cinematic for Phase 1 which I detailed and documented in my last blog post.

Until next session, thanks for reading.

Thursday, April 17, 2014

Dev Blog #2

Thursday April 17, 2014

For the second blog that is required for my class, I am going to talk about how I made the cinematic for Phase 1 of our game. The cinematic consists simply of the spacepod moving upwards, to signify that it is starting its ascent to the jump altitude. This is a very, very simple animation as it just consists of a vertical translation of the spacepod over 100 frames. I chose to make the animation take 100 frames as it would slow down the speed of the animation. So, on with the details.

I first imported our spacepod model and its door into 3DS Max. In the same scene, I made a sphere object and converted it to an editable poly. I then scaled the sphere up uniformly to the size I thought would look good in the cinematic. I moved the sphere above the spacepod and focused my attention on the bottom set of faces. I highlighted those faces and extruded them down towards the spacepod. After I made the balloon and the spacepod "touch", I went ahead and attached the balloon to the spacepod using Max's Attach feature. This turns all of the different components into one model allowing you to do things to the model as a whole and not having to select each individual component. You would only do this after you were done working on each individual component and only if you wanted the model to be one component and not many components.

After I attached the balloon to the spacepod, it was time to start the animation process. I selected my model, changed to the Motion tab in the right hand side of 3DS Max and selected the Auto Key option. The Auto Key option allows you to just move the frame slider and adjust your model. It will mark the key frame automatically. So, the first frame is simply the spacepod on the ground. I moved the frame slider to the last key frame (100 in this case) and moved the spacepod up into the air. This caused the second key to be placed. Once this process was done, I went to the Render Setup menu to render out the animation. The easiest way to do this, if you want a video file of your animation, is to open the Render Setup menu, select the radio button that allows you to select a range of frames (0-100 in my case), scroll down until you see the Render Output section, click the Files button, change the output file type to a movie file (in my case, I used .avi), give your file a name and hit save. This will pop open a new window that will allow you to select a compressor for your file. I used the MJPEG compression, which cut my frames down to around 80 (this is ok, as it did not affect the speed of the animation. Just its file size). Hit the OK button and then click the Render button on the Render Setup window. Wait a few seconds/minutes depending on the complexity and frame count of your animation(s) and... Voila! You now have a rendered movie of your animation. You can then use the .avi file if your engine/framework supports it or convert it to some other file type. I converted mine to a .mp4 and a .3gp in order to test out the Android Media Player with different file types.

I followed a tutorial on this process at this link. Everything I described above can be seen in that video.

Monday, March 24, 2014

Senior Project Blog #1

Monday, March 24 2014

We are entering Week 4 now of our Senior Project, and this is my first post. Whoops. Really should have started this sooner, but I did not have anything to talk about. Over the past few weeks, my team and I have been breaking the project up into teams and tasks, and we finally got everyone put into something. My job, as it stands right now, is to write the Physics system and make a model of the Earth for our game. Since modeling is really self-explanatory, let's talk about the physics.

The Stratos Jump, as it is formally called, was a remarkable feat of human engineering and endurance. From 120,000 feet, Felix Baumgartner jumped, broke the speed of sound, and landed safely on the ground. The physics involved with this jump are fairly straightforward, but it will take some explaining and extra research to get the formulas correct to model the behavior correctly.

So, what do we know about the physics of this jump? First of all, the atmosphere at the height of the jump has a much lower density than the atmosphere does at ground level (or sea level, for that matter). This density also changes with the temperature, and we all know that it gets colder the higher you go. There is a great post by Rhett Allain over at scienceblogs.com (link here) that explains the physics behind this jump. I will try and explain it in my own words here, but if something does not make sense, I would suggest going and reading that article and looking at the formulas.

LATER THAT SAME DAY...

Well, it appears this is going to be harder than I expected. Our client wants this to be as realistic as possible, which means my physics simulation will have to be as realistic as possible. After looking over a ton of reports and articles written about the subject, I have come to the conclusion that I will probably use the model put together by Allain in his initial article and a followup he wrote after data was released from one of Felix's test jumps (link here). Sure it isnt the actual data from the real jump, but I can modify the model to include the real data. I am merely going to use the formulas he used to calculate his model. Here is how I see it as of right now:

Physics update loop:

1) Calculate temperature as a function of height using this formula: 
T = T_0 - L h \,
Where T is temperature, T0 is the standard sea-level temperature in Kelvin, L is the temperature lapse rate in Kelvin/meter and h is height in meters.
2) Calculate air pressure as a function of height using this formula: p = p_0 \left(1 - \frac{L h}{T_0} \right)^\frac{g M}{R L}
Where p is pressure, p0 is standard air pressure at sea level in kPa, L is the temperature lapse rate, h is height, T0 is standard sea-level temperature, g is the gravitational constant (can probably get away with 9.8 m/s^2 here), M is the molar mass of dry air and R is the universal gas constant.

3) Calculate air density as a function of pressure using this formula: 
\rho = \frac{p M}{R T} \,
The variables are all explained in the above steps. There is one caveat, though. The p on the right side of the equation has to be in Pa, not kPa as above.

4) Calculate force of air resistance using this formula: i-d7d39adb0a4fb7df70381ce1c496c258-2010-02-19_la_te_xi_t_1_9.jpg

Where p is air density, A is the cross sectional area of the thing falling (our skydiver in this case), C is the drag coefficient, and v is the velocity of the diver. Allain was nice enough to have already calculated an average AC value that should work for our purposes in his most recent article that I linked above. The AC value I will use is .579m^2.

5) Calculate net force on skydiver, which will be air resistance plus gravity.
6) Calculate the new velocity and update it
7) Calculate the new position and update it

This seems really inefficient. I might have to find some way of pre-computing some of these values. Maybe do it upon initialization of the physics object that the skydiver object will have inside it to access its physics properties. I could probably get away with pre-computing all of the values that don't deal directly with the height, which will be passed into the update function every update tick. That way I am only computing a few values that change every tick and not every value. Might save some clock cycles, we are on mobile after all. And if we are targeting Android 2.3.3, which is the most common Android install on the market currently, then there are going to be some very, very slow devices that will try and run this. That could get ugly. I think the pre-computing idea is the best way to handle this.

Monday, October 21, 2013

Blog #2: Flash-UDK Workflow

Monday, October 21, 2013

Hello again. It has been a few weeks since my last blog posting, and I am back again to do another. This time around, I am going to explain the Flash-UDK Workflow and take you through something I created for my most recent project. I will be showing you how I made a custom HUD in Flash, with a checkpoint counter on it, and how I got it to work in UDK. Let's begin.

First off, I will show you the final product:


As you can see, the HUD does not really do anything except display the number of checkpoints the player has left to use in the lower right hand corner. This differs drastically from the normal UDK HUD which has things like health, ammo and what weapon is currently equipped. For our custom game, all we needed was this very simple HUD. Getting this working in UDK, however, is another challenge.

There are two ways to get a HUD in UDK. The first way, and not the recommended way, is to create your HUD, import it into UDK and use Kismet to open a GFxMovie to display your HUD. It works, but it can be very buggy and unpredictable. Especially if you need to use other Flash elements in your game. The way I did it, and the recommended way to do it, is to create your HUD, import it into UDK and make a custom gametype script that will tell UDK to use your HUD and not the default one. 

I am going to start by showing you the Flash first. Below is a picture of the HUD from the above picture open in Adobe Flash:


You cannot see anything as the text is colored white, but it is contained within those two blue boxes in the lower right. The left box holds text that is static, meaning it does not change. The right bow contains a dynamic text field, which means it can change at some point. Now, I have named the dynamic field CPLeft. Let's see the actual ActionScript that controls this HUD:

stop();

var checkpointsLeft:Number;

var keyListener = {};


function setCheckPointsLeft()
{
checkPointsLeft = 5;
_root.CPLeft.text = checkPointsLeft.toString();
}

function useCheckPoint()
{
if(checkPointsLeft > 0)
{
checkPointsLeft--;
}
else
{
checkPointsLeft = 0;
}
_root.CPLeft.text = checkPointsLeft.toString();
}

setCheckPointsLeft();

keyListener.onKeyDown = function()
{
    var theKey = Key.getCode();
if(theKey == 88)
{
useCheckPoint();
}
};

Key.addListener( keyListener );

NOTE: This code is attached to the stage itself, not the text fields. If you are unfamiliar with Flash, I suggest you look up how to add code to things in Flash.

Don't worry, I will go through this code line by line to show you how it works. First of all, the stop() call just makes sure that Flash will not advance to another frame. The next two lines are variable declarations, one being a Number (like int in most other languages) and the other being just another variable. In Flash, you do not need to give your variable types if you don't have to, which is why the keylistener variable has no type. 

The next two functions are purely declarations and implementations. They do nothing on their own. They are put in that spot to make sure they are declared before use. The function setCheckPointsLeft does a very simple job. It sets the global variable checkPointsLeft to 5, then assigns the number 5 to be written in the dynamic text field I described earlier. The call to the dynamic text field is quite simple, _root tells the code we are accessing the root of the stage (where the text fields are located), CPLeft is that name of the dynamic text field (can be thought of as an object) and text is the name of the variable that holds the text that will be written in the dynamic text field. The toString() function call turns the data in the variable checkPointsLeft into a string so it can be displayed by the text field. So, in simple terms, it sets the field to display the number 5.

The function useCheckPoint does what its name implies, it uses a checkpoint and subtracts it from the number left. The if-else statement is a bit of error checking to make sure the number displayed in the text field does not go below 0. Then the line _root.CPLeft.text = checkPointsLeft.toString() uses the same idea as the above description.

Then we call the setCheckPoints() function so it is run when the Flash is started (i.e. when UDK draws it on the screen). The next line is another function declaration. However, it is a little different from the other two. In this case, we are telling the keyListener variable to use its onKeyDown function in a certain way, which we define below that line. We create a variable to hold the key code that is returned from the keyListener. We then check it against whichever key we want that will serve as the button to decrease the amount of checkpoints we have left (meaning the key we setup in UDK as the set checkpoint key). 88 is the ActionScript keycode for the letter x, without having the shift button pressed. Then, after that function declaration, we tell Flash to add our custom keyListener and use it to determine if we have pressed the x button or not.

Now, that wasn't so bad. Let's move on to the UDK stuff. First of all, you would need to save your Flash file in this path (assuming you installed UDk to your C drive, otherwise change that letter to the drive letter where UDK is installed): C://UDK/UDKGame/Flash and put it into a folder with a different name. In my case, the file path of my Flash files was C://UDK/UDKGame/Flash/CPFlash. Now that it is saved, you will need to publish the Flash using FlashPlayer 8 and ActionScript 2.

Now, inside UDK, you would open the Content Browser and click the Import button on the lower left. Navigate to the place where your Flash is stored, and double click the file you want to import. UDK will create a package for you with the name being the same as the folder where the Flash is stored, then click OK. Now, we step into UnrealScript.

This part is not very hard. If you are familiar with how to write a custom gametype and get it to work in UDK, you can skip this step.

What we are going to do is create a custom gametype that will use our HUD instead of the default UDK HUD. 

Navigate to your UDK install folder, and go to Development/Src/MyMod/Classes. Create a new text file and name it NewGame.uc. Open that file and paste in this code:

class NewGame extends UTDeathMatch;


DefaultProperties
{
    HUDType = class'MyMod.NewHUD'
    bUseClassicHUD = true            
}

The first line tells us the name of the class (MUST BE THE SAME AS THE FILE NAME) and what it extends from. In our case, NewGame is extending from UTDeathmatch. DefaultProperties can be found in all UDK scripts, and is the place where variables can be set. So, we are telling UDK that our HUDType is of a class we are going to create soon called NewHUD. Then, the bUseClassicHUD = true tells UDK that we are using a classic HUD. Save this file.

Next, make two new text files in the MyMod folder and name them NewHUD.uc and NewGFxHUD.uc. Open NewGFxHUD and paste in this code:

class CPGFxHUD extends GFxMoviePlayer;

function Init(optional LocalPlayer PC)
{
  Start();
  Advance(0.0f);

}

function UpdateHUD()
{
}

DefaultProperties
{
 MovieInfo = SwfMovie'<insert name of package where your Flash is stored in UDK>.<name of Flash file>'
}

Again, we are first defining the class and what it extends from. Then, our Init function tells UDK to start the Flash file with Start() (this MUST be called) and to keep executing the function with Advance(0.0f). Putting something larger than 0 in the parameter list of Advance() will make UDK sleep for that duration before continuing.

UpdateHUD does nothing, but if we wanted to have dynamic health bars or ammo counters, we would put code in that function to update those specific HUD elements when needed. The DefaultProperties is where we tell UDK what Flash file to use for the HUD. We are setting it to the Flash file you imported into UDK earlier. Save this file.

Open NewHUD.uc and paste in this code:

class NewHUD extends UTHUDBase;

var NewGFxHUD HUDGFx;

simulated function PostBeginPlay()
{
  super.PostBeginPlay();

  HUDGFx = new class 'NewGFxHUD';

  HUDGFx.setTimingMode(TM_Real);

  HUDGFx.Init(LocalPlayer(PlayerOwner.Player));
}

event PostRender()
{
 HUDGFx.UpdateHUD();
}

DefaultProperties
{

}

We are declaring our class and what it extends from, and then creating a variable named HUDGFx that is of type NewGFxHUD. Remember the class we created earlier with the same name? We are using an object of that class to tell UDK to draw our HUD. The function PostBeginPlay is defined next. The first line super.PostBeginPlay() tells UDK to call the PostBeginPlay function and continue from that point. Then, we set the variable to a new object of type NewGFxHUD. Then, we set the timing mode of the HUD to Real, which tells UDK to keep updating the Flash, no matter what. We then call the Init function from our previous class and tell it to set the HUD to the Player so that they can see the HUD.

The next function is not really a function, but an event. This even calls the UpdateHUD function from the previous class. DefaultProperties can be left blank in this class, but it has to be present or UDK will error out.

Now, save that file and close it. You will now have to navigate to UDK/UDKGame/Config and open DefaultEngineUDK.ini. Navigate to the line that says ;ModEditPackages=MyMod and remove the semi-colon. This tells UDK to include scripts you wrote in the MyMod folder, as it does not do this by default. Then save that file.

Open UDK and you will be prompted to rebuild the scripts. Click yes and let it run. If we did everything right, it will have no errors or warnings. Now, open UDK again and it will load the editor. Under the View menu, click World Properties. Then, expand the Game Type field and change both dropdowns to NewGame. Then start the game by clicking the green arrow in the upper right corner. I would suggest testing this on a pre-built level. If everything worked, you should see your HUD on screen. Press the X button to make sure our HUD updates the number of checkpoints left.

I hope you enjoyed this tutorial. The above example can be applied to anything that has to be counted down (or up, by changing the Flash) on key press. We used it to keep track of the number of checkpoints left, but you can edit it to be anything you want.

Monday, September 30, 2013

Blog #1: Grayboxing

Monday September 30, 2013

Hey all, this is my first blog in a long time. As of right now I am in GSP 340, which is Level Design and Modification. This blog is going to focus on one portion of this huge topic, which is grayboxing.

What is grayboxing? Grayboxing is a technique used by level designers in order to map out in rough detail the shape and design of the level they are working on. With a graybox level, there are no textures, particles effects and minimal lighting. The object of building a graybox level is to see how the level flows from its different areas and if the proportions you planned out are either too big or small. It can also help you determine if your initial design is going to work or not. In our group project, our graybox level was a real pain to build, but that is because the shape of our towers is octagonal and not very easy to line the brush up with. Since UDK has weird snapping when you change the rotation of an object, some of the geometry isnt flush with the walls. Just something to keep in mind if you decide to build octagonal towers.

In our graybox, which I will post a picture of below, you can see that we have no textures whatsoever. The only texture/lighting is the skydome and the sun that allows us to see everything we need to.


After you are satisfied with the design and function of your graybox level, you can begin adding textures and static meshes into your level. If you built geometry that is serving as a placeholder for a static mesh or other actor, you can delete those and put in the correct object. It really is a simple concept, but it helps tremendously in the planning and initial building of your level. It keeps you from having to constantly delete textures/meshes/lighting that would mess up your level if you had those things placed in there. Not having textures/meshes/lighting allows you to work with the simplest form of your level.

That's all for today, keep an eye out for my next blog in a few more weeks.

Tuesday, June 25, 2013

Dev Blog #7

Tuesday June 25, 2013

Here we are, at the end of our journey. Matt and I have worked tirelessly on this project for the past 16 weeks, and we are very proud of the things we accomplished. We both learned a ton from making this game from the ground up and we have become better programmers for doing so. You can find the website for the game at LINK where you can see some information about the game, Matt and myself and view the trailer we made for the game. There is also a download link on the website so you can try the game for yourself and let us know how you like it and what we could have done to make it better. I will admit that the game is very short, but the point of this class was to take an idea from concept to code and make it work. We did that and our game came out really good.

I hope you enjoyed reading about the game and, at least, my ideas behind the game. You got to see some code that no one else got to see. I also hope you learned something or got a different view on something you already knew. Thanks for reading. Until next time.

Wednesday, June 19, 2013

Dev Blog #6

Wednesday June 19, 2013

Here we are, down to the final week of development. Matt and I had our weekly meeting with our professor on Monday and he seemed really happy with what we had. He only had a few requirements of us. The two major ones are animations during battle and a gear system. The battle animations are an easy fix. All we need to do is create either another sprite sheet for each monster or make more cells in their existing sprite sheet that has a few frames in it. The frames would alternate between the entity being drawn and not drawn, and when played would give a flickering effect. The gear is a little bit trickier. Matt has to create a new menu that will show equipped gear and I have to make sure that the items draw in the correct slots. That shouldn't be too bad. Then I have to make sure the gear affects the stats correctly, which won't be too bad either.

Matt also has to send me his information for the website and has to create the trailer for the game, as I am handling the website. We also have to make posts to our Career Web Portfolios with information about this project, as DeVry is making that a bigger part of our curriculum. We shall see how this week plays out. Until next week.

Thursday, June 13, 2013

Dev Blog #5

Thursday June 13, 2013

Sorry for this blog being late. I totally forgot last night to write one. This week I will have a code snippet to show you guys in illustrate one of the issues with OOP that can be somewhat frustrating to fix if you don't know where to look.

The problem stemmed from a bug Matt and I were having with items. You could use items just fine and buy items, but that is where the problem reared its nasty head. When you would go to buy potions from the merchant, the game would show you buying 1 potion and then get stuck at 2 potions left in the shop. If you left the shop interface and opened your inventory, there were 2 potions there, even though the game only showed you buying 1. If you used 1 potion or both, the amount in the shop would go down to 1. It frustrated me for days. Finally, I had a breakthrough two days ago.

I saw that we weren't giving the player a brand new version of the item he was trying to buy. We were essentially copying the exact item the merchant had, which is not a good idea in languages like Java. Java passes everything by reference by default, so if you gave the player an item directly from the merchant, those two items were tied together in memory. So, my idea was to set a bunch of variables to hold the data from the item you were trying to buy and then pass those to the constructor for the Pickups class. Then, that Pickups constructor was used as a parameter for the giveItem() function that is part of the InventoryManager class. I will show you in the code snippet below:

This is only a partial code snippet, but it illustrates my point:

if(tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getStackable())
{
int i = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getItemID();
int d = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getDefence();
int a = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getAttack();
int h = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getHealth();
double s = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getSpeed();
String n = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getItemName();
boolean b = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getStackable();
int m = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getMaxStack();
String type = tempNPC.getItems().get(ShopInventory.getMerchantSlot()).getItemType();
EntityManager.getInstance().getDaniel().getInvManager().giveItem(new Pickups(i,d,a,h,s,n,b,m,1, type));
}

Blogger isn't the best on HTML tags, so I just pasted in the code. If it is difficult to read, I apologize. The initial if-statement checks to see if the item you are trying to buy is stackable. Why, you ask? Because stackable and non-stackable items are handled differently by the engine. Above this initial if-statement there is another one that check to see if the item you are trying to buy is already in your inventory. If it is, there is a different part of the code that just adds 1 whenever you buy that item. If it isn't in your inventory, the engine creates a brand new object (you can see this happening in the last line of the code) and places it into an arraylist.

Moral of the story: Be careful about how you pass object around. It could have some nasty consequences that will leave you with a ton of headaches over such a simple coding error.

Wednesday, June 5, 2013

Dev Blog #4

Wednesday June 5, 2013

This past week Matt and I submitted our QA build for testing. We spent a lot of hours the day and night before fixing bugs and implementing features that needed to be tested. When we were done, we submitted the build to our professor. Monday rolled around and our game was there, up and running for people to test out. It really is an amazing feeling seeing something you worked so hard on being tested and critiqued by others. All of the people that I watched test the game seemed to like it a lot, although there were a few bugs that were unintended. First off, the area boss was unbeatable. No matter what you did, you couldn't beat him. That was my bad. I overestimated the amount of stats the player would get by killing all of the other enemies in the area when I set up that feature. Although, the battle system worked beautifully. There was a funny bug that was discovered through testing.

The bug stems from me not range checking the damage done during battle. In this build, it is possible to do negative damage, which would add health to your enemy. The lower level enemies were also able to do negative damage to you, which would heal you. Another bug came from almost the same thing. When trying to select the Use option on an empty inventory slot, the game would crash. This came from the game trying to check an element in an array that simply wasn't there. I fixed that bug earlier, and it was a simple fix.

Matt and I have a lot of work to do over the next few weeks. We have a lot of features to fine tweak, balance to do on monsters and levels to create. It is going to be a hectic next few weeks trying to get everything done in time for our presentation in Week 8.

Wednesday, May 29, 2013

Dev Blog #3

Wednesday May 29, 2013

This past week was an exciting one. Matt and I revised the game code to allow it to read in levels the same way the level editor reads in levels. We also got the game to display multiple monsters on the screen at the same time. We were also able to interact with both of those entities separately, which is a major stride. Matt began creating the QA level in the level editor and it will be finished by the end of the week. We are going to work on implementing code that would randomly disperse the monsters around the QA level and spawn more over time. We want people to be able to level up at least once or twice in order to test balance with the experience ratios and the stat upgrades when people do level up.

I may end up tweaking the experience per level before testing begins. I think it is going to be really high if I leave it the way it is, but I have not tested it yet. Friday will be interesting as that will be our first glance at how the testing level will work out. We should have everything we need for the level to work correctly. Matt just has to take care of allowing the player to see their stats and experience in a menu. He designed the menu system, so I do not like messing with it. It is a rather complex framework, but it works really well.

Wednesday, May 22, 2013

Dev Blog #2

Wednesday May 22, 2013

This past week Matt and I finalized the level editor for our game. It was a major triumph seeing the output from the editor in the correct format, after coding the save function once. The only change I had to make to that function was making it output the actual number, not the data stored in memory at that location. Minor flaw, but nonetheless it was practically a one shot success. In programming, nothing feels better than getting something right the first time.

I ended up rewriting the whole battle system, which included moving the damage calculations out of the battle state and putting them into the player and monster base classes. This gives direct access to the stats of each entity, instead of having to access them in long strings of function calls in the battle state. I also had to rewrite some other functions inside the player and monster classes, which meant moving some of them into the base Entity class, of which monster and player are extended. Simple ones that every class needed to have, so the move was inevitable and I am glad I did it now.

For next week, Matt and I are going to finalize the text parser we have for reading in data, creating an area for the QA testing portion of the class that will include enemies and an area boss and creating some assets. The player will be able to level up in this testing area so we can tweak the leveling process.

The leveling process was written by me haphazardly. I found some formulas online for experience gain and experience needed for the next level, and I adjusted one of them to output much less experience. Basically, I cut it in half.

More next week after we get the testing level set up and ready to go.

Wednesday, May 15, 2013

Dev Blog #1

Wednesday May 15, 2013

Matt and I are off to a great start. Over the spring break Matt began working on a level editor that we can use to quickly and accurately create maps that have the correct data we need for the game to run. It is almost done, he just needs to implement the export function that will write the data to a text file and will allow us to read in that text file into game data.

I worked this week on adding in functionality to the player and monster classes that allow for leveling up and experience gaining. This is really not as hard as it sounds. It was merely adding in a few variables in both classes, their respective setters and getters and some other functions that are either for debug purposes or that give us added features that may or may not stay in the final build. I have to focus next on re-writing the entire battle system to move the damage calculations into the monster and player classes. This will allow us direct access to the stats of each entity without needing multiple functions calls if we keep it in the battle state. I also need to implement the experience gaining system for when the player defeats an enemy. Matt is going to work on getting items to randomly drop from defeated enemies. A message box will pop up saying something like "Entity dropped an item! Would you like to take it with you?" and the player will be able to select yes or no. That statement is generic and will contain specific elements like the enemy's name and the name of the item that was dropped. We figured that this way was much easier to accomplish than actually having an item drop on the ground and be visible to the player. It is less coding and a lot of games do it this way.

Tuesday, April 23, 2013

Development Blog #7

Tuesday April 23, 2013

This is going to be a very short blog. I worked on fixing what I could in the GDD, and sent it off to Matt for approval and for him to add a couple screenshots of certain menus that we did not have programmed the first time we submitted the GDD.

We also worked over Skype on implementing the shop feature and sounds. Matt walked me through how to use the code he wrote for our menu system, as I have yet to really touch it. He has been handling all of the menu stuff, and it is about time that I learn. We got the shop feature working and were able to see the bought item in the player's inventory.

That is all for this session and GSP 361. I will be writing again on the development of Project: DImension (still a working title) when GSP 362 starts up in a few weeks. Until then, happy coding.

Saturday, April 20, 2013

Development Blog #6

Saturday, April 20, 2013

So here we are, down to the wire on this project. The Alpha build presentation is coming up on Wednesday and the game is shaping up to be something really neat. Matt and I are both very proud of the fact that we wrote an entire game engine from scratch that is mostly non-game specific. It could be applied to any other game we wanted to write, with minor changes.

The final things we are taking care of are implementing the shop feature for the city level (we already have the merchant drawn on the screen, just need the functionality), drawing the enemy on the battle screen (we already have the player drawn), allowing the player to move between the city and the forest level and implementing interaction between the bear enemy and the player in the forest level that will initiate a battle. These are all very easy to implement and will take minimal code to accomplish. I want to take this time to thank Matt for all of the work he did with the heavy graphics portion of this project. I am not a graphics genius by any means, and he made something so simple and easy to use. I look forward to completing this project next session with him.

Looking forward, Matt is going to write a level editor over our spring break which will allow us to quickly create levels for the game (as for now the are hard coded into the game itself). This will spit out a text file with symbols in it, which will then be read in by the file i/o system we have in place. The symbols will correspond to a specific tile, and that tile will then be drawn on screen. We also want to add in small touches to different aspects of the game, like animations during battle so you can see both the player and enemy attacking. We also want to implement the team feature we designed in the early stages of development which would allow the player to have a team of animals and people to help them fight their way to the end of the game. I may or may not post something here for download that you would be able to test out and see what we have. That might come at the end of next session, when the game is fully developed.

Friday, April 12, 2013

Development Blog #5

Friday, April 12 2013

Today was a long, laborious day. Matt and I worked on a lot of bug fixes and polishing of the framework that we know works. I had to re-write the entire Sound engine today, as something was going on with Lightweight Java Game Library and OpenAL. Something about corrupted files inside the LWJGL libraries. I have no idea. So, Matt did some research and found that the Slick util libraries handle OpenAL on their own as well (as, I guess, Java supports .wav files out of the box on its own). It turns out, there was about half as much code needed in order to write the Sound engine using the Slick utils.

So we tested the Sound engine, and lo and behold, it worked flawlessly. We tested it with playing two sounds at once, and it handled that beautifully as well.

I also spent a lot of time re-writing the way we are reading in data from text files. Originally, there was an outer While loop and an inner For loop that handled the saving of data from a text file into actual objects. The problem was that the loop seemed to both reset itself and would never exit the loop (that one was purely my fault, as I never closed the BufferedReader after I was done using it). I ended up redoing the loops and using two While loops to get the job done. It is ugly and hacky, but hey, it works. I just now have to figure out how to exit a try-catch without throwing an exception (because the try portion completes successfully  but it still goes on to the catch due to a bug that I am trying to fix).

Saturday, April 6, 2013

Development Blog #4

Saturday, April 6 2013

I apologize for this being late, as I totally dropped the ball on posting yesterday.

So, this week Matt and I wanted to focus heavily on getting our battling system up and running with some dummy data. And lo and behold, we succeeded. Below you will find a code snippet from the battle system we are using:


do{
if(playerTurn == true)
{
while(playerTurn == true){

KeyListener();
Display.update();
Display.sync(60);

if(chosenAttack != null)
{
enemies.get(0).setHealth(enemies.get(0).getHealth() - calcDamage(chosenAttack));
//check to see if enemy is dead
if(enemies.get(0).getHealth() <= 0)
{
enemies.remove(0);
}

playerTurn = false;
}
/*if(chosenItem != null)
{

playerTurn = false;
}*/
}

enemyTurn = true;
}

if(enemyTurn == true)
{
Attack a = enemies.get(0).getAttack(Vector.random(0, 3));

player.setHealth(player.getHealth() - calcDamage(a));

System.out.println("The enemy did "+ calcDamage(a) + " points of damage.");

playerTurn = true;
enemyTurn = false;
}

Display.update();
Display.sync(60);

}
while(player.getHealth() > 0 || enemies.size() != 0);

If that looks a little ugly, both the Blogger formatting and the actual code, I know. I tried for hours to get something onto Blogger that would look like a scrolling code box, but nothing wanted to work (and I am not a web programmer).

So, what you see there is the meat of our battle system. There are a few portions missing, as I worked on it on Matt's laptop towards the end of our meeting yesterday and forgot to grab a copy of it, but you get the gist. The first portion of the code, which you cannot see here, checks to see which attacks the player has enabled out of their repertoire of attacks. This forces the player to only have 4 attacks available to them during any battle. They can change these attacks outside of battle, but not inside. The other part you do not see is the code where we determine who goes first, the player or the enemy, based on their speeds. That part is fairly straightforward, so I will not go into detail about it.

What you see above is how the actual battle system works. It is encased in a do, while loop in order to keep the battle going until either the player dies or the enemy dies. The chosenAttack variable you see stores the attack the player chose from the menu that shows up during battle. We needed a way for the UI to interact with the game, and that was the solution we came up with. The piece of code you may not understand is this portion:

Attack a = enemies.get(0).getAttack(Vector.random(0, 3));

This piece of code sets an Attack object a to a random attack pulled from the attack ArrayList that every monster has. The Vector.random is a function Matt built in order for us to be able to generate a random number between a minimum and maximum value. The enemies.get(0) is a hacky piece of code we are using at the moment until we get actual data to work with. It pulls the first object from the enemies ArrayList that is local to the battle system. When we have actual data to work with (which means, more enemies to fight at any given time in a single battle), this portion of the code will change to reflect whose turn it is in the battle.

Hope you all enjoyed a look into the code of our project in its current stage, and if you have any questions, leave a comment below.

Friday, March 29, 2013

Development Blog #3

Friday, March 29 2013

Well, I guess I can announce the working title of our game. We have decided to call it Project: Dimension for the time being. Hopefully next week I will have some code snippets to share, as that is when the real development work will begin.

This week Matt and I worked on our file I/O system that is going to help us keep the processing time of the game down. What we are doing is storing all of the NPC, monster and item data in separate text files. At game initialization, the game reads in these files and creates objects with the data that is stored in the text files. These objects are the stored in different array lists that are a part of the InventoryManager class and the EntityManager class. We feel that this way is best as it allows us to create more items/monsters/npcs on the fly, without having to hard code anything in. We did, however, run into one major problem.

The problem is still persistent as I have not figured out how to fix it yet. The issue arises when I try to test this file I/O system with some dummy data. The data is read in fine and stored into the array before being passed the the portion where the object is created. Once it hits the creation step, the program crashes and gives me a "No OpenGL data in the current thread". I know that this means I am trying to use something from the OpenGL library before OpenGL is initialized in the program, but I cannot for the life of me figure out where the error stems from. I think it has something to do with the way we are handling textures in the code, but we are in the process of changing over to sprite sheets. Sprite sheets may help avoid this issue as there will not be a separate texture file for each object. The data passed from the text file will have to contain some data on where on the sprite sheet the texture for the object is located. I have a feeling the sprite sheets are going to make this a heck of a lot easier. I am not a graphics guy, so it is somewhat of a foreign language to me. However, I am confident that Matt will be able to walk me through it the next time we meet.

Thursday, March 21, 2013

Development Blog #2

March 21, 2013

Earlier this week I finished up coding the Inventory system and the Entity system. The inventory system handles all of the inventories, including the hidden ones that allow monsters to drop items when they die, if we choose the implement this feature in the future. The entity system has 3 classes derived from it, being the Player, the NPCs and the Monsters. There is also an entity manager and an entity generator that control the generation of all of the characters and monsters in the game at initialization. The manager does not, however, control the player. The player is going to be its own object outside of the entity manager. 

In our meeting today we talked about some ideas for how we are going to implement maps into our game. My idea was to make a giant image of the entire game world, and then create some sort of coordinate system in order to determine the player's position and what portion of the game world is visible to them. This turned out to be a bad idea, as it would take a lot of extra coding in order to get this to work. The idea that Matt and I settled on is to create a text file with symbols inside of it. The symbols will be arranged in the order that we would like the tiles that they represent to be in. This is how we are going to create our playable areas, for now. We are going to have to create tiny (32x32 or 64x64) tiles for this to work, which should not be that hard. 

I have to begin creating some artwork for the game. I am going to create some item sprites and weapon sprites for us to test our File I/O system with, so we know that it works. We also need to test drawing the objects to the screen, to see if we need to adjust our code or rethink the way we are handling textures.