Wednesday, July 28, 2010
Tuesday, July 20, 2010
Monday, July 19, 2010
Crimson Crisis Acrobat Zbrush Sculpt
Challenges:
Knife Belt - I had to decide wheter or not I wanted to give the knife belts actual geometry, or use normals and textures to make them. While giving the belt geometry would have made it standout, rigging the movement of the extra polygons would have been troublesome. I decided to use both techniques. I used normals/textures for the belt part, and gave the knives and belt strap geometry. The deformation of the legs would take care of the belt's movement, and the adding rigging the knife to the Knee Bone Joint would take care of its movement.
Pants Texture - I had to decide whether or not I wanted to use masks to make the pant's pinstripe texture or to do it by hand. I decided to do it by hand to give the pants are more imperfect and homemade feel.
Hair Sculpt - This was the first character I've made so far with long hair. I decided to keep with my simple aesthetic and just make it one whole piece of geometry. I then used stylized sculpting to add a layered feel.
Monday, July 12, 2010
Sunday, July 11, 2010
Rising Sun/Danny Boes Zbrush Sculpt
Challenges:
Proportions - The stylized proportions was a challenge. Using an imagine plane guide with a character sheet in Zbrush was helpful. The head and face was the biggest challenge. It took a lot of tweaking and iterations to get the right feel. The forearms and calves took a few passes to get the right look. The chest and shoulders were actually pretty easy to get right.
Texture - The Dragon texture was really specific so it required a lot of tweaking. I will still look at the texture in photoshop.
Saturday, July 10, 2010
Crimson Crisis Brute Zbrush Sculpt
Challenges:
Body Type- This was the first time I have sculpted an overweight character. While muscular figures give you a definite form to map out your proportions, overweight figures have distorted proportions and lack muscular definition. This makes it more difficult to sculpt the flow of one surface form into another.
Friday, July 9, 2010
Some Coding Changes
A smaller update than the previous ones. This is mainly about programming than anything else. No videos on this one, but some explanations and basic coding layout notes.
Character Attributes
There is now a CharacterAttributes class that is attached to the character's model. This has the values for health, attack, defense, speed, block, and parry that are found in the design document. There are also functions in there that does the calculations for determining the maximum damage an attack can do. An ApplyDamage function is in the class that takes in that calculated damage, and then alters it based on the defense of that character. Other functions are in place to calculate the total block time and recharge time based on the block attribute. These are currently not in use. There is also a Die function that takes care of basic death things, but will probably change later on.
Base Attributes
There is also a BaseAttributes class now which has public constant values that store all the base attributes. This way they can be accessed from anywhere in code and are not allowed to be altered at any point.
Character Collision
Some changes have occurred in the CharacterCollision class. This is placed on any colliders that will be used as attack regions. Inside this class is a few important functions:
AttackStarted: Called via a BroadcastMessage call from the PlayerController class (and most likely an EnemyController class later on). This turns on the trigger aspect of the collision field when an attack has started.
AttackEnded: Called via a BroadcastMessage call from the PlayerController class (and most likely an EnemyController class later on). This turns off the triggers when attacking has completed.
QueueAttack: There is a new class called AttackVals, which stores the duration of an attack and it's power. Every time an attack occurs this is queued up. This way, when an attack collision occurs, the duration is used to keep the trigger from applying damage each frame, and the attack power value is passed into the ApplyDamage call of the enemy. This allows for varying damages based on the attack.
Gate Attributes
Though we never talked about this, the current gate that is shown in the last programming post video could actually be a gameplay element. In slight preparation of this possibility, there is a GateAttributes class that has some basic similarities to the CharacterAttributes class. It has health and defense values, which are calculated the same way with the ApplyDamage function.
Fixed Camera
Lastly, there is a FixedCamera class. This has been around since the last post, but thought I'd post it here too. The class uses the LateUpdate call in order to reposition itself back to where it should be, and allows for left-right scrolling like in old games.
Next Up…
The next major thing that will probably be worked on in programming is the beginnings of AI. Not sure when this will be started, but it will hopefully be soon.
Monday, July 5, 2010
Flux/Cory Stone Zbrush Sculpt
Challenges:
Symmetry- When sculpting in Zbrush, It immensely speeds up your work flow when you have perfect symmetry on your base model. Since Flux has two different arms, this posed a problem. The Solution was to Import a base body model that WAS symmetrical, and then import just the robot arm into a separate subtool. I later sculpted down the left arm to hide inside the robot arm.
Hexagon Texture- I knew this was going to be tedious so I tried a few different ways to streamline the process. I first tried using a repeating Stencil pattern of a hexagon alpha. I could not get the stencils to have a crisp edge so that didn't work. I then tried just creating a repeated hexagon pattern alpha to use as a mask. This didn't work because some of the hexagon alphas would stretch when applied to the model. I just settled on individually placing the hexagon alphas one by one.
Old Design:
The original Concept Art had the legs being pure Dark Navy Blue. I wanted to balance the character's color scheme and add some light blue to the boots. The concept artist and I compromised and settled on the above light blue rim and sole design for the boots. Also, the Visor goggles were missing a black binocular rim around the bug eye lens in this sculpt.
Collisions and New Gameplay Goodness
Differences In the Videos
The last video demo just showed the character attacking, moving, and idling based on player input (or the lack thereof). What wasn't shown is that the player could move anywhere they wanted as well as through solid objects. In this video, you see that the player is actually bounded by walls and objects, can attack, and actually has something react due to the attacks.
Changes Since Last Post
The last post was mostly about player's character control and how it changed the character's state and animation. All of these things were within one class. Now, there is a class called CharacterAnimationController which handles all the animation calls. The PlayerController class has a variable which does the appropriate function calls to make animations occur. This allows for a clear separation of concerns and should allow for player control logic to be in PlayerController and animation control logic to be placed in CharacterAnimationController, to help alleviate any possible confusion. It also allows this to be very flexible, since the CharacterAnimationController class can be placed into any character model and an external controller can access it.
The New Stuff
The new stuff is mainly about collision detection. I will detail what the current logic is, but as for classes and variables, those will probably be left out until the next major post on this subject. The reason behind this is that there will probably be a major code organization change sometime soon based around this stuff and the character attributes of attack, blocking, etc. Also, a small but good change is that the camera has been updated to act like the old games in this genre. It moves only left and right with the character, but not up and down.
First Attempt and What Was Learned
The first attempt at collision detection was a lot of Capsules (a primitive object in which I later had their mesh renderer removed to use their Capsule Collider component) that closely fit to the body of the character. Each one was placed as child to the model's bone's GameObject. This allowed it to automatically rotate and move to the model's animation. This was great since we could have near perfect accuracy. However, it was decided that such accuracy could actually be bad for the type of gameplay we are aiming for since it could make some characters' attacks more effective than others. Though the Capsules were scrapped, we did confirm that we could place other things, such as particle effects, onto the bone of a model and have it act according to the mode's animations. This should allow us to easily have cool effects in certain areas.
The Thing We're Using Now… And What We Learned
Through other attempts and research, the CharacterController component was found. This component, when using it's own Move function, would allow the character to not walk through solid objects. This is now being used to prevent that, but to also be the basis of the collision region of the character (the region that will say when the player is hit). In front of the player is now an invisible BoxCollider, which is the attack region. If the player is attacking and something is in that region, it will be hit by the attack.
A problem that occurred during this is that the CharacterController and the BoxCollider would be colliding during attacks and triggering the colliding functions. This is an issue, since no matter when the player attacks, the trigger would go off, which is a waste and could cause other collision problems. To solve this, I luckily came across the function Physics.IgnoreCollision, which does exactly what it's name implies. It has to be called at runtime though; it will not carry over or save. This did solve the issue, and knowing about this function will most likely help in the future.
When a collision occurs, a message is sent upwards in the collided object with the SendMessageUpwards. Thus if the player hit's an enemy, the enemy has a message sent upwards to apply the damage. At this time, a preset number is sent from player to enemy on the amount of damage to be done. This will later be changed so the calculated maximum damage of the attack is sent, and then the enemy can apply any defenses and changes before actually applying the damage.
What's Next
Things coming up are refinement of this collision detection system, character attributes, and AI. Particle systems will be added somewhere along the way too.
Friday, July 2, 2010
Programming Animations and Attacks - Beginning of Gameplay
The first of many posts! Hopefully this will be detailed and useful to all that read.
One obstacle that had me going for awhile was how to determine when an attack animation was fully completed, without using the isPlaying member. Though this would tell me if an attack animation was done, it would not work well if you have more than 1 attack going in a row and wanted to do something special with each attack. Furthermore, it would always return true since another animation (usually walk or idle) would follow the set of attack animations. So this solution wouldn't work, and no other values were all that useful in knowing when a player was attacking, and when he was idling/walking.
On top of the goal of knowing when a player is attacking and when they are done, I wanted to be able to string attacks together in a combo. These go hand-in-hand, since we want combos, and we'll need to know when a combo is done so the state of the character can change.
So the problem is 2-fold: know when attacks are done, no matter how many occur in the set (though we are currently capped at 3 in a combo), and stringing the attacks together visually.
Attacking State Change Problem
I tossed around a random set of solutions, most of which I can't think of right now (if I remember any I'll post them in a comment). The solution I did settle on, and has been working well, is timestamps. Each AnimationState object has a member called length, a floating point value that is how long the animation is in seconds. So if the field returns 1.73, then the animation lasts for 1.73 seconds. When a combo occurs, the length of each attack animation is added to a single variable called attackTime. This is the total amount of time that the player will be in the attack state. So if combo1 last 0.5 seconds, combo2 last 0.25 seconds, and combo3 lasts for 0.75 seconds, the total amount of time the player will be attacking is 1.5 seconds.
When the player first performs an attack, a timestamp is taken and stored in a variable called timeOfAttack. This variable, in conjunction with the value returned by Time.time, is used to determine how much time, in seconds, has passed since the first attack. This is checked each update call. When the time that has passed is greater than or equal to attackTime, then the attack has completed, and various state related values are reset, including attackTime, the attacking state, and the comboNum (more on this variable below).
This has worked very well so far, with no noticeable issues. The states change when I expect them to, and there hasn't been any major performance hits for this approach that I've seen.
Stringing Attacks Together
Every time the player hits the attack button, the function Attack is called. This function updates the value comboNum each time it is called. This can be seen as the number of Attack function calls that has occurred so far. The function checks to see if the value is less than or equal to 3. If so, the value is passed into a switch statement. This switch statement will then add the length of that combo's animation to the attackTime value, and queue up it's animation for playback.
That's pretty much all there is to that one. Any additional logic for specific animations can go into the switch statement, but so far isn't needed. The code for the Attack function can be seen here.
Final Thoughts
I think this gives a pretty solid core for animations, attacks, and the state changes for moving, attacking, and idling. In the simple demo (embedded above) there's basic changes from idle to walking to attacking. A full combo has a smooth transition back to idle, but if you only do 1 or 2 attacks it pops back to idle. Currently thinking of ways to fix that.
One of the final things I'll probably do next for this is separate player input and movement into one class, and the animations all in another class. This way I can simply drag the animation class into any character type and use it seamlessly.