Sunday, May 26, 2013

Learning Challenge, AS3 Style!

Hey guys!

After my last post I began looking at what I would need to do in order to get the visuals for the action queue to work. I decided I wanted it to look similar in style to the example below. In this example the player wants to use a key, move, talk to a person, then move again. The action that is being performed is scaled larger and is in the 'highlighted' slot on the bar.
This seemed pretty easy in theory, just spawn an icon tot he left of the last one. When one action is completed move the remainder to the right and make the 1st action icon larger. Instead of diving in to this I decided to do a little challenge. The challenge was to make an inventory system that could support a dynamic amount of items. I also wanted to make it scrollable. Now this doesn't seem like it would help with the action queue problem, but both involve spawning movieclips in a line and setting parameters from an array. The last will be important because the actions will be stored in an array and that information will be used to spawn the correct icon. I added the scrolling challenge since I plan on using a system very similar to the challenge if I redo my crafting page, or add an inventory system to my menu collection.

The challenge only took me a couple hours of work, though I had a couple days where both of my computers were out of commission. Many thanks to Craig Campbell over at School of Flash, and Ali Qureshi for their tutorials. Between the two I was able to get the bulk of the logic figured out and implemented. I ended up using Craig's custom scrollbar and masking approach rather than the scrollpane as in Ali's example so I could have more control over the look of it. Ali has a very well commented block of code for spawning the desirable amount of movieclips from AS3. I used this primarily to get the inventory items to spawn. Overall I learned a lot about spawning movieclips and setting parameters using a for loop, and what math is needed to get a particular block of content to scroll. Here is the final product of my self-challenge: (Go ahead, click on it! It's interactive!)



Here is the Actionscript3 code that makes it work: Not too different from the tutorials though.

import flash.events.MouseEvent; stop(); //Movieclip vars var desiredMCs:int = 20; var nextYPos:int = 10; var i:int = 0; var invoCont:invoContainer; var invoArray:Array = ["Bread", "Milk", "Juice", "Steak", "Pinapple", "Carrot", "Ginger", "Parsley", "Eggs", "Peppers", "Onions", "Porkchops", "Chicken Nuggets", "Salmon", "Prickly Pear Cactus", "Butter Cup Squash", "Spam", "Red Leaf Lettuce", "Cornbread", "Cheeseburger"]; //Scrollbar vars var rect:Rectangle; var scrollerMinY:Number = slider_mc.handle_mc.y; var containerMaxY:Number; var padding:Number = 20; slider_mc.handle_mc.buttonMode = true; slider_mc.handle_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragHandle); popup_mc.drawInvo_btn.addEventListener(MouseEvent.CLICK, drawInvo); back_btn.addEventListener(MouseEvent.CLICK, removeInvoCont); //Inventory functions function drawInvo(e:MouseEvent) { desiredMCs = popup_mc.inputField_txt.text; if(desiredMCs >= 1 && desiredMCs <= 20) { invoCont = new invoContainer(); invoCont.x = 170; invoCont.y = 30; mainICont_mc.addChild(invoCont); containerMaxY = invoCont.y; popup_mc.visible = false; for (i = 0; i < desiredMCs; i++) { var item:invoItem = new invoItem(); item.x = 10; item.y = nextYPos; item.name = "invoItem" + i; item.itemName_txt.text ="Item Name: " + invoArray[i]; item.itemType_txt.text ="Item Number: Item " + (i +1); item.itemDesc_txt.text =""; invoCont.addChild(item); nextYPos += item.height + 1; } for (i = 0; i < invoCont.numChildren; i++) { trace ("name: " + invoCont.getChildAt(i).name + "\t type:" + invoCont.getChildAt(i)); } //If there is not enough content to scroll, disable it if(desiredMCs <= 3) { slider_mc.visible = false; } else { slider_mc.visible = true; } } else { //Do something to show an invalid number } } function removeInvoCont(e:MouseEvent) { //Removing the existing inventory mainICont_mc.removeChild(invoCont); //Reseting variables for a new test slider_mc.handle_mc.y = 3; nextYPos = 10; popup_mc.inputField_txt.text = ""; popup_mc.visible = true; } //Slider Functionality function dragHandle(e:MouseEvent):void { rect = new Rectangle(0, 3, 0, 345); slider_mc.handle_mc.startDrag(false, rect); stage.addEventListener(MouseEvent.MOUSE_UP, releaseHandle); slider_mc.handle_mc.addEventListener(Event.ENTER_FRAME, scrollInvo); } function scrollInvo(e:Event):void { var scrollerRange:Number = rect.height; var contentRange:Number = invoCont.height - mask_mc.height + padding; var percentage:Number = (slider_mc.handle_mc.y - scrollerMinY) / scrollerRange; var targetY:Number = containerMaxY - percentage * contentRange; invoCont.y = targetY; } function releaseHandle(e:MouseEvent):void { slider_mc.handle_mc.stopDrag(); slider_mc.handle_mc.removeEventListener(Event.ENTER_FRAME, scrollInvo); }

That's about it. It was a nice little challenge that I think will help me with creating the action queue visuals when I get around to them, plus a better inventory management system. For bearing with me here is an point pickup inspired by the 2007 game Monster Madness: Battle for Suburbia!
No texture, sorry!

Sunday, May 19, 2013

Looking For Another Name For A Queue...

Hello everyone,

Over the past several days I've been working on a queue system where the player, or another portion of code, can add an attack, action, or item to a queue and it will play them after a set delay. This could be used to set up attacks during a battle so you can focus your attention on strategies or your allies. It could also be used to receive function calls from code to handle them if more than one is called at once, for instance if two animations are called at the same time. It ended up being pretty easy to set up once I figured out what steps were needed.

When I first attempted this a couple weeks ago I ended up putting it down in frustration because I couldn't figure out how to get it to do what I wanted it to do. Earlier this week I remembered something from an article I read about coding, and it helped my out with this. The article suggested to write down the steps that the code needed to take before you even begin working on the computer. By doing this you are forcing yourself to think about the different components that make up the chunk of code that you are trying to create.   I decided to do this and the breakdown ended up looking like this:


This really helped me get the order down on what needed to happen where. After that I could take each step and write them out, essentially creating three functions reflecting the outline above.

Here's what I came up with in Unrealscript. This is in my custom Pawn class:

//Struct used in the Action Array struct Actions { var string N; //Action Name var float D; //Action Delay }; //Delay playing another action var bool bDelay; //Holds the actions currently queued to run var Array<Actions> ActArray; function AddAction(string Action, float Delay) { local int i; //Set i to the current length i = ActArray.Length; //Add another element in the array ActArray.Length = ActArray.Length + 1; //Set the properties of the new element ActArray[i].N = Action; ActArray[i].D = Delay; PlayAction(); } function PlayAction() { local string TempN; local float TempD; //If an action is already playing if(bDelay == true) { //Place any action to run if an action is currently being ran. } //If not else if(bDelay == false) { bDelay = true; //Set the temporary variables TempN = ActArray[0].N; TempD = ActArray[0].D; //Check which action needs to be played switch(TempN) { case("sAttack"): //Standard Attack Played break; case("hAttack"): //Heavy Attack Played break; default: break; } //Remove the played action ActArray.Remove(0, 1); //Set bDelay = false after a set time SetTimer(TempD, false, 'ResetDelay'); //Output the time to the screen WorldInfo.Game.Broadcast(self, "PlayAction Time:" @ TempD); } } function ResetDelay() { bDelay = false; //If there is another action waiting if(ActArray.Length > 0) { PlayAction(); } } defaultproperties { bDelay = false }
And the functions that call it from my custom GFxMoviePlayer class:

function sAttack() { GP.AddAction("sAttack", 10.0); } function hAttack() { GP.AddAction("hAttack", 20.0); }
I'll go through and break down what is happening in each one starting in the Pawn class. The variables are pretty self explanatory. I chose to use an array consisting of the Actions structs I defined earlier, that way each action could have multiple properties assigned to it. In this case I just have the action name and how long its cooldown should be. 

Next I'll go through the AddAction function. As you can see it takes two parameters when it is called, this was the easiest way I found to set up the different attacks. We'll then create a local int that will store what element number the action need to go into. Arrays use a base-0 numbering system, meaning they start at 0 and end at one less than the number of elements. I.e. if you have 4 elements the last one would be Element3. Since this is the case I set i equal to the current length of the array, then added one more element onto the array. This left i being the last element in the array. I then set the name and delay properties of that element equal to the parameters that were passed from the calling function. Last, I call the PlayAction function which actually calls the function to play the attack.

Onto the PlayAction function! Most of this is pretty easy to follow. Basically, if an action isn't cooling down(if bDelay is false) then check what the name of the action is and play the appropriate function.Then we're going to remove the first element from the array which will move the rest of them up one. I did this because it simulates a real queue, or line. Only one person can be helped at once. When the first person is done they move off and everyone moves forward, thus creating an organized system to handle multiple people. Finally, we set a timer to mark the system as ready to play another action. You might be able to use ActArray[0].N in the switch directly, or ActArray[0].D in the timer, but I ran into some issues previously with using array elements directly. I may give it a whirl later and see if I can, but I'm going to leave it for now.

Our last function in the Pawn class is resetting bDelay and calling PlayAction if there is another action waiting to be played. 

The functions in the GFxMoviePlayer class simply call the AddAction function and declare what action needs to be set. 

Well, there is a basic working queue system to use in a multitude of situations. You could even make a function for when an action is double clicked on your graphical display to remove that specific action. It could look something like this(though I haven't tried it)

RemoveAction(3); function RemoveAction(int ActNum) { ActArray.Remove(ActNum, 1); }
In this example it would remove 1 element at the 3rd slot, or whatever we pass into ActNum.

Anyway, that's all I have for today. Hope this was useful to someone. Once I figure out how I want the graphical display to look/work I'll post the code and such for that as well.

Sunday, May 12, 2013

Back After A Short Respite

Hello Everyone!

Sorry it has been a while, I took some time off after Super Monster Dance Party to relax a little so I can start on new projects with renewed energy. In this down time I've been working on a 3D scene for two of our classes. The project is creating a culture and an environmental issue that it faces. We were allowed to work in groups for this so I teamed up with Andrew Talarico and Ryan Hess. We have two cultures and three environmental issues. Anyway, one of the cultures is called Praxis and the other is Ryatopia. I decided to create some tools that the Praxians might use. It started out with just some rope and a barrel, but I thought that they didn't have any context and wouldn't do the Praxian culture justice. I just kept adding items to the scene until I thought it felt right. Praxis is a colony that is built unto/into the cliff faces of huge a crevice. All of these objects are on a suspended platform on one of the cliffs. I ended up with two variations(Click on them for bigger images):
A still of Praxian life - Pickaxe only

A still of Praxian life - Pickaxe and Shovel

I think I like the one without the shovel better, simply because I couldn't get the shovel head to not look really flat due to the positioning of the lights. I don't want to move the lights since I like the rest of the shadows. I do like the added variety that the shovel provides though. It makes it look like they use more than one tool. 

The texturing isn't anywhere near perfect,but I think it gets the point across fairly well. Still trying to get the texturing thing down... Seems like a lot of times it is harder than actually modeling the object. 

That's what I've been working on for the most part. I've been a little restricted  when it comes to Umbra or other UDK based projects since UDK decided to stop working correctly. I'm in the process of doing a re-install to see if that fixes it. If it does fix it then it back to trying to get level streaming volumes to work and programming a queue system for actions/attacks/events. 

Saturday, May 4, 2013

Post Mortem - SMDP

I figured I might as well do a post mortem, or a development review/critique , of the process of making Super Monster Dance Party. I'll go over several different aspects of the development cycle, namely Team Forming/Brainstorming, Development, and finally Quality Assurance/Publishing. I'll give an overview of what happened in each stage, then give some suggestions on how to possibly improve the step for the next time.


**Warning- This is will be a long post. You have been warned!**

Here is a two sentence summary if you don't want to read it all: We set out to make a pseudo-rhythm game featuring various monsters destroying towns around the world. The development phase went smoothly, but we needed to allow more time for concepting and testing.


Team Forming/BrainStorming:

Overview:  This stage went pretty smoothly. Dave Troyer came up to David Fuson and me and said he had a concept for a game involving a monster destroying city to music. It started out as a very simple, one button game where notes, or rings, would come in from the sides and you tap the button when the notes go through it. Over the course of around 30-70 minutes we had a more fleshed out version that had the possibility of multiple buttons, several monsters, and several different modes. After we had a stronger concept we recruited Corey Farmer to work on the songs for the game. The rest of the team were kind of picked up along the way, I'll go over that more in the development stage.

Suggestions: I don't really have any suggestions for this stage, it went really smoothly. If I really had to pick one thing it would be to establish an art style before work starts on the art assets. I think spending more time doing concepts to lock down a style will help reduce the amount of assets that need to be redone when the art style changes.This would also include concepting out menus, page backgrounds, buttons, and other aspects of a game that often get overlooked.

Development:

Overview: We started off pretty strong on this game. After Dave proposed the idea and we elaborated it a bit, I started prototyping the engine that would spawn the notes and had a working version within a couple hours. By that time, David Fuson had concepted out 5-6 different monsters and presented the art style he had in mind for the game. We spent the next couple weeks refining the art and engine. Due to certain limitations we ended up cutting the infinite mode, due to how Construct2 handles loops. We also decided to reduce the amount of monsters from the 10 we originally had down to five, as well as the amount of songs.

This was where we changed up the team quite a bit. Corey decided he had enough on his plate working on our school project, and withdrew from the group. To fill the sound void, Dan Langford stepped forward and took on the task of making sound effects and music for the game. Since he was still learning some of the digital music software, he only had time to complete one song, as well as some voice acting. Since we were approaching our target release date and were lacking the amount of songs we needed, we resorted to bringing in a third party composer, DJ SynthR, to supplement the missing songs. We also added Ben Mjelde as a backup artist to work on the buildings for the city.

Onto the art style and art assets. As mentioned before, partway through the development cycle we cut back on the amount of monsters the game would feature. We had to go through and pick the monsters we liked the best, and that had the most diversity stylistically, so they wouldn't all look the same. Once we got those decided on David started putting together the sprite sheets for the animations for Dave to set up in Construct2. Dave ended up redoing the monsters since the previous ones had some issues once they were actually put into Construct2. The only problem with that is that Dave and David's art styles are substantially different, where David was leaning towards the pixel art style with rough edges and shading and Dave had made crisp and shiny new ones. To alleviate some of the differences Dave worked some magic in Photoshop and got his pixelated. They still looked different, but not nearly as much.

Since a lot of effort was being put into the monsters to get them squared away, other aspects of the game were being ignored. We were still lacking a cohesive menu/button scheme, and till right up at the end we were running with the placeholder images I had made so I could set the pages up. These took till the day of release to get finalized, which is not the time to be deciding on layout styles for a game. As we got towards the deadline it seemed like trying to get art assets became increasingly difficult. What I mean by this is when an art asset needed to be updated with new information, or just a tweak to make it look better, there was some resistance to actually update them. I realize that they had already been made, but it should be expected that art assets need to be tweaked/updated. It is frustrating as a developer to be met with an exasperated sigh when we need an art asset before a major deadline, and then receive something that is vaguely what you had asked for.We did manage to get everything updated though, so that was good.

Suggestions: The major thing I think of is to diversify what a group is focusing on. For instance, instead of focusing the entire art team on getting monsters animated, have someone start working on the menus, page backgrounds, text, and stuff of that nature. That way we have more time to refine/redo those assets if we're not satisfied with them on the first go around. When it comes to redoing assets/code/sounds we need to remember that things will need to be adjusted, and just do them. This is especially true if the change would take minutes at most. Sure, you already did the work once, but the assets aren't finalized until the game has been released(And sometimes not even then!)

Another thing that would help the team is to don't take on more than you are willing/able to work on. This was a major issue when it came to our songs, we had the game very close to being done, yet we had no music(which is a major part of the game). It wasn't until several weeks into it that we found out Corey wouldn't be able to do the songs. If the team is relying on another team member to get them something, the team member should let the rest of the team know as soon as they can that a different person will have to work on it. This would avoid a lot of frustration for the remaining team. By all means, if it turns out you have less time than you thought you would have or something comes up and you can no longer work on it, then let the team know. We understand that things come up, but  it should be brought up as soon as you know you can no longer work on it.

Quality Assurance and Publishing:

Overview: This portion of the cycle was entirely too short. Since it took so long to get the songs and remaining art assets we had very little time to test the game with all of that stuff in it. During this process we learned that each browser handles HTML5 different, especially when it comes to audio. Audio support for HTML5 is sporadic at best it seems. Part of the time sound would work great on Chrome, then others it would only work on Firefox. We ended up doing a lot of last minute testing right before we started the publishing process. We also should have tested the game on more types of phones, since apparently every Android device handles HTML5 differently just like a browser. We had the best results on the latest version of Android, and very mixed success on older phones. We also found out that there really isn't anything we could/can do to fix a lot of those issues, since the browsers haven't decided on web standards for HTML5 yet. If we knew Javascript we might be able to smooth some things over, but that is beyond our team's capability at the moment.

Publishing was quite a new experience for Dave Troyer and myself. We ended up spending around 4 hours going from exporting the game to actually publishing it to Google Play. We had crash courses on how to sign an .apk which is needed to upload to the marketplace. Now that we have the process down it should be really easy for future games, but it took a little bit to find a tutorial/explanation that was detailed enough for us newbies to figure it out. Thank you to whomever made this tutorial over on Scirra.com, it was easy to follow!

Suggestions: Main thing would be to allow way more time for testing and to have a wider testing base for mobile. I think that would solve many of the problems that arose during this stage.

Project Overview:

Overall I think this project went pretty smoothly. There were a few hiccups here and there, but we did finish it. Main suggestions would be to: Know your limitations, be prepared to redo stuff, and allow a bunch more time for testing. I would also recommend a longer concepting phase, or at least not just focusing on the main aspects of the game. I feel that would help the game as a whole be more cohesive, and provide a clearer goal for the different teams to work towards.

P.S.: On a side note, after the release of the game we have had reports of features(mostly sound) that are not working correctly. These issues appear to be with how Android processes HTML5 and varies between different versions of Android. I apologize for the inconvenience. We recommend trying to get the latest version of Android. If we receive enough sales we might port it to Apple devices, which are supposed to handle HTML5 better, but that is farther down the road. Thank you for all of your support!