Catalogue

Monday, August 15, 2016

Art 1: HD Spriting method

Summer classes are over, so here's something I hadn't done before to celebrate.
My method for creating the HD sprites is pretty simple. My tool of choice is Manga Studio 5/ Clip Studio Paint. 
Here are 3 character sprites as an example.

The first phase is the "rough." The amount of how finished it turns out can vary a lot. 
I'll use a "messy" rough when I don't have a good idea of how the character's sprite will look, and just want to get the pose down so I can have at least a solid enough foundation to design on top of.
The "nude" rough comes out when I have a really good idea of the character and pose, but haven't fully finished their design or haven't decided on what they should be wearing. I use this one the most often, especially with finished pieces. Sometimes the nude rough won't even have hair.
The "polished" rough comes out when I know exactly what I want from the sprite. Usually there's still a messy and nude phase, but after a certain point I've cleaned the rough so much that I just ended up erasing them.
I just use a basic pen brush for this. Feel free to choose any thin brush with minimal aliasing.
The "outline" phase can go by very fast or very slow depending on how developed the rough phase is.  If the rough is "messy", the outline might as well be a second roughing. Regardless, the outline is always faster than the rough as even a very incorrect rough gives a good foundation. On the other end, if the rough turns into a "full outline" I can just skip this phase and copy the rough over.
For the initial idle sprite I do the roughing and outline using Manga Studio 5. But when I'm animating I use TvPaint instead, and then export the outline to MS5 for coloring and rendering. I'll go over my animating and TvPaint techniques some other time.


The "color" phase has multiple steps to it. First I select the area that's going to be colored. I do this by placing a selection block around the outline, and deselecting everything outside the character. After that I color everything inside the selection with the character's most prominent color. 
Each character gets a block. This is used to compare the colors without an outline getting in the way.
Then I just color the character with the fill bucket.
The following step of the "color" phase is one of the most important. I create color blocks representing the character in a minimalist form. I've mentioned this before (thank you, Mark), the best way to test if your colors are effective is to compare them in a simplified format. 
In the picture above: the right block is the character's original colors, and the left block with a circle over it is the re-colored version. You want to keep each color from clashing with anything it's touching. You also don't want two colors to fight for attention regardless of how far they are from each other. Lily(right) has red as the most saturated and dominant color. Originally the blues would clash with the red because they were just as bright, so I desaturated them in the second version.

The final phase is the "render," where the lights and shadows are applied.
When I'm working on a full piece, I have a dozen or so different layers full of colors and fx. However when I'm making a sprite I want to keep things simple as I have to move the sprites around a lot, so in total there are only 3 layers used for each sprite (rough layers are not counted): the outline, the color, and the shade layers.

You generally want the lighting to come from just above the camera, but it's not a bad idea to put it at a slight angle. The Crown sprites are designed to have the lighting come from just behind the character.

The first step of rendering is to just draw the shadows. My tool of choice is a custom brush I call "Watercolor Sketch," the settings of which are in the image above. 
The second step is drawing the highlights. I also use the Watercolor Sketch for this, but combined with the "Flat Brush" also shown above.
Overall this phase doesn't take very long. It's usually the shortest as it's the phase that requires the least design work, you're really just improving on the color phase. Keep in mind though that you do at least have to choose colors that look good. Beyond that, rendering is about technique.

Monday, August 8, 2016

Scripting 5: Script: Camera_Control

Camera_Control speaks for itself. It's the camera script.


This is an overview of the Camera_Control Script.
VOID Start()  Only used to set certain variables that can't be set earlier.
VOID Update()  Does everything.
  • First InputCheck is called and player data is read.
    • playerspeed = player's.hspeed*3+player's.endlessrun.
      • hspeed records horizontal speed.
      • endlessrun is automatic movement, used in some bossfights.
    • playerfall = player's.rigidbody2D.velocity.y;
  • holding right adds +1 to the variable "aboutFaceLag." If it's value becomes 100, the camera will now stand to the right side of the player. The opposite is done when holding left.
    • This allows you to see ahead of the character, and adds a delay to camera movement when the player is changing directions.
  • If playerfall<15(player is not jumping), the camera stands in the default location.
  • If playerfall>15(player is jumping), the camera tries to stay still.
  • If playerfall<-10(player is falling), the camera attempts to keep you in sight.
  • If playerfall<-24(player is in a long fall), the camera tries to get below you.
  • Wall climbing
    • Reads the player's fspeed, and adjusts to look over or under the player depending which way they're going.
  • If you tap left or right, threatTest is called. If an enemy is found within the aimed vicinity, the camera moves slightly to get them into view.
  • goingLow is one of many variables used to control the y offset of the camera from the player. If you hold down, goingLow decreases to move the camera lower.
  • At this point, custom movements are taken into account. If the camera is moving automatically, most of the above is ignored, and the camera instead moves based on a value.
    • The player is not allowed to exit the camera's field of view while it's moving automatically.
    • If the camera is moving horizontally, it will attempt to keep a strict y position.
  • Rotations are set through a Quaternion.Lerp by 0.01f;
  • The field of view and z offset are both set through Mathf.Lerp by 0.02f;
  • Earthquaking moves the camera around rapidly for a set amount of time. 
  • The camera tests for walls and water.
    • If there's a wall overhead, the camera will avoid rising.
    • If there's water underneath, the camera will try to stay above it.
  • Colorizer: Reads the main light's script and changes the background color accordingly.
At this point the final camera movements are being calculated.
  • First the camera's movement is smoothened. 
    • playerposSmoother = Vector3.Lerp(location, target, 0.98f);
  • startx and starty = playerposSmoother;
    • startz = playerposSmoother + zoffset(the default distance the camera should keep);
  • The final variable "Target" is now calculated.
    • target.x = startx + playerspeed/3(player's running speed) + xoffset(default distance to keep);
    • If y can move freely then target.y = starty + yoffset;
    • If the camera is too close to the bottom of the level, target.y won't fall below 10;
    • If the z position of the camera can move freely, target.z = startz;
Between the first and last calculations, the overrides are set.
  • The camera uses a raycast to stay away from walls in order to prevent clipping or xraying.
  • A circlecast checks for focusers. 
    • If any is found, focusCheck = true; and FindFocus() is called.
    • If none is found then focusCheck = false, and the rotation and field of view are reset;
And now the final movements are set.
  • moving.x = Mathf.Lerp(current x position,target.x,cameraspd*50*Time.deltatime);
  • moving.y = Mathf.Lerp(current y position, target.y, cameraspd*mathf.Abs(currentpos.y-target.y)(changes speed based on distance) * 2.5f * Time.deltaTime);
  • moving.z changes similarly to movingx, just slightly slower (30 instead of 50);
  • transform.position = moving;
  • If the distance is too great or the player dies, the camera snaps to the target via SetCamFast();
 IEnumerator Camflix(float shiftSpeed)  Turns the camera on and off, used after the player dies and during the level's start while things are still loading.
VOID SetCamFast() Quickly resets the camera. 
VOID setFields(int settingT) Changes the field of view between presets. 
VOID ThreatTest() Checks for surrounding enemies. If there is an enemy within a certain location, the camera will move towards it when changing directions. 
VOID FindFocus()  Focuses tell the camera where to go while the player is within its field. Focusers can affect field of view, rotation, and location. 
VOID InputCheck(int whatCheck = 0)  This is a basic input checking function that reads the arrow keys, WASD, joypad, and joystick all at once.

Monday, August 1, 2016

Blog 2: Summer Game Ideas Part 2

Two weeks ago I talked about the inspiration I drew from watching SGDQ. Now I want to talk about the android games I've been trying out, and the new ideas I've had thanks to them. I was mainly inspired by Pokemon Go to do this, since I'm not usually interested in phone games. I'll also rate them out of 5 at the same time.

Monster Sweeperz 5/5 (side scrolling shooter): This has been my favorite game from the Google Play store. Like almost every other android game, it features an autoplay button. But unlike other games, the autoplay is treated like a gameplay feature rather than just an anti-grinding mechanic. The most useful aspect of it is that automatic movement is better at avoiding projectiles than the player, which works even better due to the fact that not every projectile is meant to be avoided and must be destroyed or you take damage anyway. This turns knowing when to take your fingers off the screen into a strategic element. I'm not sure if I got a lot of design ideas from it though, as it is a really solid game but doesn't do anything all that different from other android games, just improves on already popular gameplay features.

Pokemon Go 3/5 (I don't know): It's a barebones game, whose mechanic isn't as unique as everyone seems to think. The best thing I guess would be the explorative element, which I would probably enjoy more if I didn't live in such an empty town. And of course the reason it's so popular is because of the fact that it's Pokemon, the most popular video game series in history. I wonder if parents out there recognize Mario, Mickey Mouse, or Pikachu faster.

Hit 5/5 (Top-down Action Game): My second favorite game. I don't normally like top-down beat-em-ups, but Hit's gameplay, graphics, and abundant features make it very worth playing. I'd like to try making a game like this one some time using Evanlily characters. It'd be relatively quick and easy compared to making a metroidvania, 3D platformer, or platform fighter. Another idea I like is the "instant complete pass" that lets you immediately complete a level you've already beaten. It helps save on the grinding, and they're not too rare or too common.

Delight Games Full Library (Pick your own adventure story) 4/5: Ironic that my three favorite games from the android store are from genres that I normally hate playing. The stories are pretty good, though I've only played 4 chapters total of the Wizard, Witch, Dragon stories, and haven't finished any of them fully. I'm enjoying it though, so I wanted to recommend them anyway.
I also felt a bit of inspiration from them, but not really game design inspiration. I don't plan to make any choose your own adventure games, but I have been writing Evanlily's story lately. I hope to be able to share that story in novel format during future blog posts. Years ago I had planned the story out as a comic series, but when I started learning how to script for games I decided to concentrate on this instead.

Soul Seeker (Top-down Action Game) 3/5: This is the kind of game I would like to make myself. The character designs are pretty good, the graphics are nice, and there's a crapload of content. The biggest drawback is how repetitive it is, as the levels are just the exact same thing over and over again regardless of how far you get into the game. There's also a risk of getting a lot of lag due to all the monsters that can appear on screen at once. What's more the gameplay is not very involving, you might as well just always have auto on. It could have been fixed easily just by including any sort of defensive option, like the dodge button that every other game in this genre has. One thing I do really like though is the fact that you get rewarded every time you fully level up one of your characters. Playing it has pushed me away from wanting to make a top-down action game with a "crew," and instead makes me to want to make something more like Hit that focuses on one character at a time. Not that I have any current plans to do either, I'm trying to focus on Crown.

Minimon (Top-down Action Game) 2/5: Minimon is very similar to Soul Seeker but with worse graphics, less playable characters, and slightly better gameplay. Like Soul Seeker, I really wanted to like this game. The graphics and repetitiveness are the only things pushing me back. The character designs were my main draw, they're all pretty attractive and the girls are thick as fuck which I love. The gameplay also doesn't lag like Soul Seeker, but it's still repetitive. There are a lot of levels in each world, but they all look the same. And the game only ever gives you baby monsters, expecting you to put in hours of work to evolve them into the better ones. I just got bored, but at least there's a dodge button.

Digimon Heroes (Matching Card Game) 4/5: This game has the exact opposite problem as Minimon. While Minimon gives you utter shit, and expects you to work like a bitch to evolve it into good shit, Digimon gives you great shit early game. But that's still a problem. Why should I be expected to evolve the Guilmon I just unlocked through lottery, when I already have a Gallatmon Crimson mode? There's no balance to the Digimon you can get. In the early levels you can unlock a Patamon, and in the next world you'll be unlocking MagnaAngemon before you ever get to gather the evolution materials to get regular Angemon (Which you already unlocked from another level). Evolution is worthless and difficult, but I still enjoyed the gameplay. Once you get the hang of it, it's a very easy but very fun game to play. I'd like to try making a card game some time, but it's not a high priority and probably wouldn't be a matching game.

Honorable mentions: I don't care enough to write full reviews about these games.
Pocket Mortys: It's good, but I'm not a fan of RPGs.
Sonic Boom Dash: It's just a boring runner. I don't have a real opinion on the genre, I've enjoyed runners before. There's nothing special about it, it's really just a time waster.
Sonic Runners: Just like the game above, but better and more fun. Unfortunately all support for this game will have ended by the time I publish this review. Hopefully there's a sequel, and they fix the lag.
Plague Inc: It's alright. It can be fun, but I don't think I will be playing it very much. Maybe the fact that I only played the free version just left a sour taste.
Traffic Rider: It's fun at first, but I hate how much it makes you grind.

Monday, July 25, 2016

Scripting 4: AI: VeluciDrake

Speeddrake_AI is the script used to control VeluciDrake.


This is an overview of the Speeddrake_AI Script.


The string "personality" greatly controls the velocidrake's actions, colored orange.

Coward: Will run away when the player is standing too close.
Savage: Will attack the player from any distance.
Guard: Will not leave past a specific zone.
Persist: Will follow the player relentlessly.
Agile: Will jump over and avoid projectiles.
VOID Start()  Reads and stores component variables.
VOID OnEnable()  Resets AI states
VOID Update()  Controls the meat of the AI.
  • Sets basic variables
  • Checks distance from player.
    • Most vDrakes become inactive if too far away.
    • Persist vDrakes will instead chase after the player.
    • Guard vDrakes will check the distance from the guardzone instead of itself.
  • Agile vDrakes check around themselves for incoming projectiles, and will jump into the air if there are any incoming threats. If the threat is too high, they will instead attempt to drop lower to the ground.
  • Basic functions are then called. There are 4 wall checking variables, to test whether or not the vDrake is on a wall.
    • The wallhitx variables check for standing on walls.
    • The wallcheckx variables check the distance to the hit wall, and positions the vDrake appropriately.
  • The floor underneath the vDrake is then checked. If in the air, and not on a wall, the vDrake will be affected by gravity.
  • Now the script checks to ensure the player is within the vDrake's attack field, and their position. 
  • Guard vDrakes at this point check their distance to their guard point, and Retreat if too far away.
  • The following action is randomized by a variable between 0 and 5.
    • Climb will jump backwards to go up a wall.
    • Fall will jump down from the wall, or move closer to the player.
    • Attack will tackle the player, landing on the other side.
  • Debugging variables are checked last.
VOID wallChecknFace()  Checks for walls, and quickly sets the vDrake's position and facing direction based on the results.
 VOID circleCheck(LayerMask layerFloor, Vector2 chaseSpotT, LayerMask layerWall, Vector2 chaseMove) Creates a circle that moves and grows.
 VOID jumpToPoint(Vector2 jumpPoint, int jumpspd, float xspd, bool attackDash) rapidly moves the vDrake towards the desired point, found by circleCheck().
  VOID projectCheck() If the vDrake is agile, constantly checks for nearby projectiles through a circlecast.
  VOID actionMove (string currAct) Performs the desired action. 
 The string "currAct" controls the vDrake's action, colored red.
  • Attack: Will find a location behind the player, and tackle towards that spot.
    • If Savage the distance to be checked increases.
    • If Safe and Guard the vDrake instead retreats.
    • If Safe and isn't guard the vDrake instead attempt to Attack Safe.
  • Attack Safe: Will find a location between the vDrake and player, just to get closer.
  • Climb: Looks behind itself to find a wall that can be jumped on. This action happens quickly, and there is no prepping animation.
  • Fall: Similar to Climb, but looks instead to the front for a floor to land on.
  • RunAway: Finds any location behind the vDrake, and falls back.
    • If running away Fast, will increase the bubble's speed and decrease the prep time.
  • Retreat: Will jump back towards their guard location, used by Guarders.
  • After everything is checked, the variable curruentAction is reset to be blank.
  VOID OnTriggerStay2D(Collider2D other) Checks if colliding with the player.
If colliding with the player and tackling, the player will be damaged.

Monday, July 18, 2016

Blog 1: Summer Game Design Ideas Part 1

Summer classes have slowed down progress a bit, so most of the updates for the next few weeks will be scripts. I'm working on the game's graphics in the meantime.

Two events happened last week. The first is SGDQ, and the second is that I got my hands on an android. Both events have been inspiring some new game design ideas, though most of them are not very pertinent to Crown. I'll start with SGDQ, and talk about the Android games in my post 2 weeks from now. I've had SGDQ running in the background while I work on my school and project stuff, here are some of my thoughts.

My favorite run this year was Momodora 4: the commentary was great, the skill displayed was really impressive, the game itself is very high quality, and I got the most from it overall.  I'd love to make a metroidvania game at some point in my life, but I'll need to make sure I have the necessary resources when I try it.
Something more immediate though is a gameplay mechanic the runner described as "last hit forgivance. This means that losing all of your HP won't immediately kill you, but instead grants you one more hit. It hasn't been programmed in yet, but I plan to use it for Crown. I'm a bit wary about adding too many features that make the game easy, but I don't think I've crossed the line yet and games should support the player before the difficulty.
The Dark Souls-esque rolling ability also made me rethink one of Lily's powers in the game. But I'll explain more about that later on.

My favorite type of runs are the races and my favorite genre is platformers, so my most rewatched runs were the DKC Tropical Freeze and Super Mario Maker races. Both games showed off pretty good auto scrolling levels, something that will likely be very abundant in Crown as even the first major bossfight in the game is a running boss. The important thing is to keep the gameplay active and fast, something DKC and the Mario Maker speedrun level designers accomplish well.

Ape Escape is one of my all time favorite games, so I'm happy to see it speedran at a gdq event. The floating ability with Spike's slingback shooter reminds me of Razputin from Psychonaut's floating ability, almost tempts me to add dumb little tricks like that in my own games. That's probably not a great idea, but it reminds me how I love messing with cheat codes in games. Though I've already programmed a debug menu in Crown that I plan to make an unlockable feature for the player, so I think I at least have the fun factor that comes with cheating down.

Honorable Mentions: I just don't have much to say about these.
Ty the Tasmanian Tiger: Fun commentary.
New Super Mario Bros 1 and 2: I keep forgetting these games exist.
Kirby & the Amazing Mirror: I've been wanting to see a co-op run of this game.
Ed, Edd, 'n Eddy The Mis-Edventures: Love the show, never seen gameplay of this before.


If you're interested in what I do, here are my other social media pages:
Twitter @Maakole: I tweet whenever I update something here or on my Tumblr.
Tumblr: I made it recently, and don't really plan to use it all that often. But it will showcase art work from my Evanlily game projects, or whatever else I happen to be doing.

Monday, July 11, 2016

Scripting 3: AI: Fansher_AI

Fansher_AI is the script used to control Fanshers.
This is an overview of the Fansher_AI Script.
VOID Start()  Meant to be used only once to mark initial variables.
guardlock: records the initial position. Used for guardian fanshers who only patrol the area around their spawn point.
body: The rigidbody2D attached to the fansher, there isn't one by default.
truemaxspeed: Records the initial maxspeed.
shotref: Provides a link to the Shooter_AI script.
anim: Links to the object's animator component.
zpos: The z position, used to decide the enemy's depth.
sizer: The enemy's scale. Is set to the enemy's initial x scale
VOID Update() The meat of the script. 
  • Basic info is first retrieved. Para and hpRef are set to read the para, enemyHP, hurt, and canBeControlled are set based on the counterpart variables within the Enemy_Health script.
  • Acceleration is set to (1+Mathf.Abs(hspeed)*baseaccel)/3. So the fansher's speed increases at a slower rate the faster it moves.
After this, the four wants(direction) variables are read, and movement is decided based on their values. Fspeed (vertical) always adds double acceleration. Hspeed (horizontal) adds x1, or x3 if the Fansher is flying towards the opposite direction at the time.
Fspeed and Hspeed are stopped separately through lerping to 0 by 0.95f.
Final movements are set through:

transform.Translate(Vector2.right * truemaxspeed/2 * 0.01f * 100 * Time.deltaTime);
transform.Translate(Vector3.up * fspeed * truemaxspeed/2 * Time.deltaTime);
  • A circlecast is used to check the distance between the enemy and player. If the player exits the circle's radius, the enemy object becomes inactive.
  • Another circlecast is used to check if the player is within the Fansher's line of sight. 
  • A raycast is used to ensure the Fansher avoids being too close to water.
  • If the player is within the Fansher's line of site, the Fansher will call ProjectChoose() randomly based on Random.Range(0, bulletchance).
  • Finally, the debugging variable "wantsToMove" is checked, and the AI variables are set according to the debug commands.
IEnumerator ProjectChoose() The meat of the script. 
  • The shot prepping animation is set to let the player know the fansher is about to fire. 
  • hspeed and fspeed are both multiplied by 0.5f to slow down the fansher.
  • body.velocity is set to vector2.zero.
  • Waits for a customizable amount of time "bulletTossWait." 
  • Activates shotRef.ProjectChoose(); on the Shooter_AI script.

Monday, July 4, 2016

Enemy Design 2: VeluciDrake


VeluciDrake


Classification: Monster, drake.
Appearance: Lucent yellow bodies, dark stomach and feet, irisless eyes.
Diet: Carnivorous.
Location: Caves, Mountains, Forests.
Attacks: Lightning tackle.
Threat Level: 2. Very fast, but left vulnerable during attacks.

Adapt at general mobility, VeluciDrake are speedy monsters known for their running and jumping capabilities. When in full speed, the vein on the side of their body can release built up electricity.


Their feet have microscopic hairs underneath, which allow them to stick to almost any surface. To take full advantage of this ability, VeluciDrake mainly inhabit arching habitats, and due to their lucent scales are most commonly found in caves.



Like most Drakes, they hunt for larger creatures in packs. VeluciDrake attack by moving at high speeds toward their prey, this causes their bodies to naturally release electricity which can slice through other creatures like a blade.