Catalogue

Showing posts with label Scripting. Show all posts
Showing posts with label Scripting. Show all posts

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 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, June 27, 2016

Scripting 2: Script: Shooter_AI

Shooter_AI is a script used by enemies that shoot projectiles.


This is an overview of the Shooter_AI Script.

This script contains 13 public variables and 9 private variables. Every public variable is used to customize the projectile being shot.


VOID Start()  Only used to set the pooler boolean.
bulletshot: The array of projectiles being shot, customizable.
pooler: If true, then all projectiles are created from the start, if false then projectiles are created when they're shot.
if the length of the bulletShot array is larger than 1 projectile, pooler is set to true and RefChecker() is called. Otherwise pooler is set to false.


VOID Update()  Only used to control knockback
Sets the motion of the enemy. Like the HPscript, Shooter_AI has its own special movements. These movements are used only to affect the enemy's knockback after shooting a bullet.
Lerps hspeed and vspeed to 0 by 0.2f;
transform.Translate(hspeed/10,vspeed/10,0);

public VOID ProjectChoose()  This is the function called by other scripts.
if pooling:
  • Checks each projectile saved in the bulletshot array.
  • The fires the first inactive projectile found with StartCoroutine("ProjectileToss", bulletshot[tC];
  • If the checked projectile is active, tC+=1, and the next projectile is checked.
if not pooling:
  • objReffed = Instantiate(bulletshot[0]);
  • The fired projectile's function are reset through the ProjRefSet function.
  • Then the projectile is fired with StartCoroutine("ProjectileToss",objReffed);
IENUMERATOR ProjectileToss(GameObject tRef) Fires the projectile
  • First checks the enemy HP. If HP is lower than 0, all coroutines end immediately.
  • At this point, the object is disabled and enabled to ensure it gets reset.
  • The projectile's position is first set to the object firing it, with a displacement created by the Vector 2 bullDistance.
  • The knockback is set based on shootStrength; Vector2
  • The projectile's hspeed and vspeed are set based on bulletspeed; Vector3
  • The projectile's gravity is set based on bulletslow; Vector3
  • The damage is set based on bulletDamage; Integer
  • The element is set based on bulletElement; String
VOID RefChecker() Only used for pooling, creates all the pooled projectiles.
  • Each prefab in bulletShot is instantiated;
  • Each prefab in the bulletShot array is replaced with the newly created gameObject;
  • ProjRefSet() is called for each projectile;
  • Each projectile is now deactivated.
VOID  ProjRefSet(GameObject bulRef) set the projectile variables.
  • startTime = How long the bullet will remain active before despawning.
  • initialSize = Original size of the bullet.
  • sizing = Active size of the bullet.
  • element = Physical traits of the bullet, given through a string.
  • diesOnHit = whether or not the bullet will be destroyed upon collision.
  • homePoint = whether or not the bullet will home in on the player.
  • After all the variables are set, the bullet is parented to the "Projectile_List" gameObject for the sake of organization. This gameObject is located within the Scene_Prefab object present in all levels in the game.

Monday, June 20, 2016

Scripting 1: Script: Enemy_Health

Enemy_Health is a script required by every enemy character. Its purpose it to control the enemy HP, taking damage, reacting to damage, spawning and despawning, and holding important variables.

This is an overview of the Enemy_Health Script.

Due to the nature of this script, there are 32 public and 6 private variables. Some variables are public for the sake of customization on a per-enemy basis, others are public so that other attached scripts are able to read them.

7 of the public variables are spawner variables, which get passed on to a spawner object created by the Enemy_Health script on startup. This spawner is responsible for respawning the enemy to which the script is attached.

VOID Start()  Creates the permanent variables.
  • maxEnemyHP = enemyHP; sets both variables to be equal.
  • nightlight = gameobject with "NightLight" tag; This light is used to control colorizer.
  • body = attached Rigidbody2D; This is optional, most enemies do not have a Rigidbody2D.

Colorizer Variables

  • alterGlow and savGlow are reset to uniqueGlow's value.
  • appearance = SpriteRenderer; Saves 2D renderer information for colorizing.
  • if there is no SpriteRenderer: appearance3D = Renderer; Saves 3D renderer information.

Spawner Variables

  • enemySpawned: The enemy to spawn, always set to "this.gameObject";
  • distanceToSpawn: Radius of CircleCast around the spawner. Defaults to 30;
  • infiniteSpawner: A countdown to auto respawn the enemy, does not auto respawn if int == 0;
  • respawnLimits: An int that controls exactly how the enemy will spawn.

respawnLimit meaning:
 0= Regains ability to respawn when the player is far away.
 1= Only respawns when the player dies.
 2= Will keep respawning until the enemy is killed. Useful for minibosses.
 3+= Will not spawn or create a spawner. Useful for event-based enemy spawning.

And finally, the enemy gameObject is always set to be inactive after the first frame.

VOID OnEnable()  This acts as a reseter.
  • enemyHP = maxEnemyHP; Resets HP to maximum.
  • Colorizer(); Resets color.
  • focusPoint is set to active. Useful for minibosses that need the camera to stay still.
  • canBeControlled = false; Resets debugging functionality. 
  • deactivates spawnObjects- spawnObjects are meant to spawn after the enemy dies.
  • reactivates killObjects- killObjects are meant to despawn after the enemy dies.
VOID OnDisable
focusPoint is set to inactive. Optional, focusers tell the camera where to go.

VOID Update ()
  • movRef variables are set. movRef references the enemy's Movement, if attached.
  • if there is no movRef, the hSpeed and fSpeed variables are set instead. These variables Lerp towards 0, and are used to tranform.translate the object. These variables control knockback.
  • finally, countdown variables (hurt, para, etc.) are updated by -0.1f; 
After the initial variables are set, the colorizer function is called.
To override the initial colorizer is the Pain Throb feature. When an enemy's HP falls below 25% they will begin to glow and throb red. After these variables are set, the colorizer is called a second time.

Finally, the dying variables are set. This section reads the HP, and if it's below 0 the enemy begins dying. 
At this point spawnObjects are spawned, and killObjects are despawned.

VOID Colorizer() Changes sprite and model color based on the light and atmosphere.
The Enemy_Health Script contains its own version of the Colorizer script, this is to create the throbbing effect. Enemies can also have a unique glow.

VOID OnTriggerEnter2D(Collider2D other)
If the variable "touchdamage" is greater than 0, the enemy will damage the player on contact. This variable is turned off for almost every enemy in the game.