Lighting for Health Revision

During the development of Four Days Before School I worked on using lighting to represent the amount of health the player had. The decision to use lighting for health was made because we had one programmer and two artists, so since we would have more man hours for graphics work, we wanted to focus on the aesthetic and atmosphere of the game and chose a concept based on that. Since the game depicted a child dreaming, the idea of using light fading as you took damage in the game felt appropriate, so we decided on the idea.

The implementation simply uses a ___ light in Unity and has a script that linearly interpolates (”lerps”) the intensity and range towards a target value. That target value is modified whenever the player takes damage. This creates an effect where the light fades whenever the player takes damage, and fades faster the more damage is taken.

teddy-hp-light-test

Lighting levels at high health (from early build).

This system was developed early on, but needed a lot of revising, due to player feedback that it was difficult to tell how much health the player had. The early revisions focused on changing how drastic the change in lighting was, but after never getting any positive playtesting feedback on the lighting-as-health system, and the game entering beta stage, we needed to do more drastic reworks. The revision I worked on was one of changing the mathematical function from health to lighting intensity and range.

teddy-hp-light-test-2

Lighting levels at low health (revised system, from alpha build).

Originally the function used was just a linear one. When you lost x health, the intensity dropped by that much. However, after receiving feedback that towards lower health levels, the change in lighting felt more dramatic than at higher health levels, I decided to more closely analyze the change in lighting as intensity changes. I identified that the difference between intensity 2 and intensity 1 felt a lot stronger than intensity 4 to intensity 3, despite that the loss of hit points would be the same (the intensity difference being 1 in both cases) which was in line with playtesting feedback.

After further testing, I concluded that the perceived intensity difference between intensity 4 and intensity 2 felt about the same as that from intensity 2 to intensity 1 and that from intensity 1 to intensity 0.5. From that I concluded that it would be best to use an exponential function. That the target value that the lighting intensity tends towards should be 2^x, where x is health, divided by some number.

Boss Design and Implementation

Design

Because I only worked on fixing bugs this week, I decided to write about some design and coding work I had done the week before which is a lot more interesting to write about. Namely how me and our lead designer worked on the design of the boss and how I implemented it in the game.

When we designed the boss we had the following goals for it:

  1. The boss needs to test the player’s understanding of the core mechanics of the game.
  2. Since we had 2 levels, but didn’t have time to make 2 separate bosses, the boss design needs to have room for abilities that can be added for the second boss to make it more difficult.
  3. The boss needs to offer challenges that are new but still familiar to the ones the player has already encountered.

Based on those goals we came up with the following design:

1. The boss has 4 shields that surround it, and every few seconds they change to either be a full shield, half shield or no shield. When the boss is hit on one side, it takes 1x damage if it is a full shield, 2x damage if it is a half shield and 3x damage if it has no shield.

When the boss switches shields, it also switches weapons, unless it gets no shield in which case it gets no weapon.

The boss also spawns enemies after a few seconds (longer than the shield switch time).

This tests the player in their ability to maneuver both their avatars so neither take damage based on how the boss switches shields and what weapons it has. The boss spawning enemies allows the player to get powerups (which are dropped by enemies) and adds another challenge based on awareness.

2. The bosses in later levels have more weapons, and the final one has a laser state, where it spins around and shoots a ”laser” which the player needs to avoid. The later bosses also spawn more enemies and have more health.

3. The shields are an entirely new concept that the player hasn’t encountered, but we think they are untuitive to understand. The bigger the shield the less damage it takes. Even if the shields are a new concept to the player, they test the same skills the player has required before: maneuvering two avatars at once based on where enemies are on the screen and how the behave at that moment.

Implementation

The boss was simple to implement. The laser state, spawning enemies state and normal state are handled by a state machine, where each shield is a child object which handles switching shields after a few seconds and fires projectiles based on its own state machine that handles which weapon it has equipped.

Movement is simple: It randomly picks a position within a boundary, and then moves towards that position. When it reaches the position it chooses a new position. When it enters a new state it stands still until the state is finished.

Boss

(Screencap of the boss firing projectiles)

Ricochet Projectile

This week I worked on, among other things, a power up which, when activated, launches a projectile which ricochets off of the sceen boundary and all enemies. It damages all enemies it collides with and stops bouncing around after a set period of time.

The design thought behind the projectile is to add power ups that encourage skillful usage of them. When an enemy drops a powerup, it drops three which all go in separate directions.power-up-example

(The image above shows the three powerups moving apart. The green line of particles is a link between the player and a teddy bear)

The player then has to choose which one to go for. Since there are different enemies on different places on the screen, the choice both comes down to how useful the powerups are and how easy they are to pick up in the player’s given situation.

The actual implementation of the projectile is rather short and easy, but the amount of trial and error made it take 8 hours to complete. All that is needed is for the projectile to have a physics material with 0 friction and 1 bounciness (so it keeps bouncing without slowing down) as well as some boundaries outside the screen to bounce it back. I decided to add the following code:


void Update () {
Rigidbody2D rb = GetComponent<Rigidbody2D>();
Vector2 v = rb.velocity.normalized * projectileSpeed;
rb.velocity = v;
}

Vector3.normalized (used on the velocity of the rigidbody) takes a Vector3 and makes it’s length 1, but keeps the direcion the same. This way I make sure that the speed of the projectile is constant, but that the direction changes. Before I added this, the speed of the bouncing projectile would vary depending on the speed of objects it collided with, which wasn’t intended and could produce some bugs because unity’s physics engine doesn’t like really fast moving objects.

The complications I faced during development were mostly due to how we implemented collision previously. We used OnTriggerEnter2D() which requires one of the two objects to have a collider with isTrigger == true. An isTrigger collider cannot be used for physics collision which meant I had to rewrite and retest a bunch of code for all enemies and projectiles in the game. However, in the end, the projectile looks good and works very well.

The particle effect is done using a particle system with a sphere shape which produces particles with no velocity, that way it leaves a trail of particles behind it. It creates a nice effect that I’m sure will look even better when we add some custom particle materials to it.

ricochet

(Image shows a ricochet projectile that just bounced off the top edge of the screen)

Spinning Enemy

This week I worked on adding more enemies to the game, as we previously only had a single one. I made 4 new enemies but the one I want to focus on for this blog post is an enemy that in the concept document was called ”Squirt.” Squirt is an enemy that circles around while spinning around shooting bubbles to the left and right. Here’s what he was depicted as in the concept document:

concept-squirt

Spinning and shooting quickly creates waves of bullets that the player has to dodge. In order to balance this I needed to make another prefab in unity for the projectile, since the one we used for the other enemies is pretty fast moving, it would make it incredibly hard to dodge his projectiles if they were the same speed. Also, since he shoots bubbles, one would expect them to be slower than rocks shot from slingshots, which the normal enemy projectile is modeled from.

The behaviour script for him is fairly straight forward. I created two empty game objects as children of squirt, one to the left and one to the right, which work as spawn points for the bubble projectiles. Every update, the script instantiates the projectile in both those spawn points, as well as moving and rotating squirt. Rotation is easily done using unity’s built in Transform.Rotate() function. The concept document describes squirt’s movement as circular, but we currently have him move in an ellipse (which is easily changed if we want to change it). The reason for that is that the screen is 16:9, not 1:1, so we stretched the circle out to an ellipse with width:height ratio 16:9. This movement is done by increasing a float angle every update and making his x position equal to (16/9) * cos(angle) (this is done using unity’s Mathf.Cos() function) and his y position to sin(angle).

The only complication that arose was in squirt’s ”falling state.” We decided for every enemy to have a falling state, where it can’t take damage but also can’t deal damage. The state is used to warn the player of what enemies will appear soon. Most enemies fall towards a random target on the other side of the screen. After they reach that target they will begin their normal movement pattern and start shooting. For squirt, however, we thought this would look strange. He would ”fall” to a position, move towards a target position and then start circling. We felt the transition from moving in a straight line to moving in a circle would look clunky so we decided that while in the falling state it should move like normal in the falling state and just transition to shooting and being able to take damage. I needed to rewrite some code for the falling state script but in the end it worked out well.

 

Tether System

This week I worked on a ”tether system” between a teddy bear that is controlled with the mouse and a girl that is controlled with the WASD keys. The goal of the tether system is to render a tether between the two characters to visualize their connection to each other.

The reason why we decided on having a tether between them is because of feedback from the playtest. Our testers didn’t understand why the teddy bear is shooting a projectile towards the girl, so we wanted to make it more clear that they are linked and that the player is supposed to position the girl and teddy so that there are enemies in between them that the projectiles hit.

Our lead artist wanted a tether that bended when you moved the characters, so it looked less like a steel bar between them. I tried doing this using a particle system that shot a constant stream of particles towards the player. The problem was it didn’t look at all like a tether since when you moved the teddy quickly the particle would spread out. Unfortunately I deleted the script and didn’t capture any footage of it but rest assured it looked awful.

After going to the coding session with Håkan, he told us that he had no idea how one would implement that and adviced us to scrap the idea of a bendy tether. So we did and I instead used the LineRenderer tool to draw a line between the teddy and the player.

teddy-tether-image

It doesn’t look great right now but we are probably going to add a material that isn’t monocolor and some particle effects in the future. For now it communicates the link to the player and that’s what it need to do right now.

The only problem I had was that Unity’s Line Renderer tool is a for 3d development. While it’s usable in 2d, it isn’t designed for this. This became apparent when the line at first was rendered behind the background. This was solved by the following code lines:

lineRenderer.sortingLayerID = LayerMask.NameToLayer(”Default”);
lineRenderer.sortingOrder = 6;

This sets the line in a ”sorting layer” in the 2d system, which makes it render at layer 6, which is above the background.

 

Revenge of Teddy – Group Troll – HP Light Test

Today I worked on a system which should use light in the level to show the player’s HP. For now I’m using a point light in unity which changes in intensity and range as the player’s health changes. This first image shows what the screen looks like when the player has full HP:

teddy-hp-light-test

(The white box is a placeholder for a teddy bear that the player controls in addition to the main character. Th grey box is a placeholder for a pickup.)

Every update, the HPLightController modifies the light’s range . The change in light range per second is the difference between the current light level and the current hp level multiplied by a given integer switchTime. This makes the light range follow a converging geometric series.

The light intensity follows a similar series, but only half of the intensity changes. The range ranges from 0-50, whereas the intensity ranges from 2-4, so there is at least a level 2 intensity light at all times. This is what the same level looks like at very low HP:

teddy-hp-light-test-2

(The white big white boxes are enemies and the small ones are projectiles.)

Currently it looks like a blue sun in the background, which is a result of my using a point light in unity, which concentrates the light in the middle of it. The decision to use a point light was just that it was what the tutorial I watched on sprite lighting used, so to be safe I used the same type of light. I will most likely change it later, since the light is supposed to be more of an ambient, unobtrusive light rather than strong flashlight-esque light. However, for now, a working light system is good enough since the game has just reached the pre-alpha phase.

I intentionally make the light system only affect the background. The idea of the light system is to be a more aesthetically pleasing way to show HP, rather than a bar. If the enemies and pickups were affected, it would mean that the game becomes harder as you get lower HP, which intrudes on gameplay design.

Designa en webbplats som denna med WordPress.com
Kom igång