Added gameover state. Cleaned up other things.

This commit is contained in:
Harrison Deng 2020-07-11 23:19:50 -05:00
parent dce1c03ba9
commit 0139832d19
10 changed files with 234 additions and 69 deletions

View File

@ -1,5 +1,5 @@
using System.Drawing;
using SkinnerBox.Utilities.Gameplay;
using SkinnerBox.Utilities;
using SlatedGameToolkit.Framework.Graphics.Render;
using SlatedGameToolkit.Framework.Graphics.Textures;
using SlatedGameToolkit.Framework.Utilities.Collections.Pooling;

View File

@ -33,21 +33,21 @@ namespace SkinnerBox.Entities
public struct PacketSpawnInfo
{
public float timeElapsed;
public int period;
public float interval;
public int perSpawn;
public float batchLocation;
public float distanceBetween;
public float range;
public float jumpDistance;
public float speed;
public float lastSpawnLocation;
public PacketSpawnInfo(int period, int perSpawn, float location, float speed, float distance, float jump) {
public PacketSpawnInfo(float period, int perSpawn, float location, float speed, float distance, float jump) {
timeElapsed = 0;
lastSpawnLocation = 0;
this.period = period;
this.interval = period;
this.perSpawn = perSpawn;
this.batchLocation = location;
this.distanceBetween = distance;
this.range = distance;
this.speed = speed;
this.jumpDistance = jump;
}

View File

@ -1,4 +1,4 @@
using SkinnerBox.Utilities.Gameplay;
using SkinnerBox.Utilities;
using SlatedGameToolkit.Framework.Graphics.Textures;
using SlatedGameToolkit.Framework.Utilities.Collections.Pooling;
using System;

View File

@ -1,4 +1,4 @@
using SkinnerBox.States.Main;
using SkinnerBox.States;
using SkinnerBox.Utilities;
using SlatedGameToolkit.Framework;
using SlatedGameToolkit.Framework.Logging;
@ -12,7 +12,7 @@ namespace SkinnerBox
static void Main(string[] args)
{
GameEngine.targetFPS = 0;
GameEngine.UpdatesPerSecond = 20;
GameEngine.UpdatesPerSecond = 40;
Logger.AddLogListener(new ConsoleLogger());
GameEngine.Ignite(new MenuState());
}

86
States/GameOverState.cs Normal file
View File

@ -0,0 +1,86 @@
using System;
using System.Drawing;
using System.Numerics;
using SlatedGameToolkit.Framework.AssetSystem;
using SlatedGameToolkit.Framework.Graphics.Render;
using SlatedGameToolkit.Framework.Graphics.Text;
using SlatedGameToolkit.Framework.StateSystem;
using SlatedGameToolkit.Framework.StateSystem.States;
namespace SkinnerBox.States
{
public class GameOverState : IState
{
private MeshBatchRenderer renderer;
private AssetManager assets;
BitmapFont font;
BitmapFont titleFont;
private StateManager manager;
private int score;
private TimeSpan timeElapsed;
private int downloadsServed;
private int totalDownloads;
private int packetsReceived;
private int totalPackets;
public GameOverState(BitmapFont font, BitmapFont titleFont, MeshBatchRenderer renderer, AssetManager assets) {
this.font = font;
this.assets = assets;
this.titleFont = titleFont;
this.renderer = renderer;
}
public bool Activate()
{
titleFont.PixelHeight = 120;
titleFont.PrepareCharacterGroup("GameOvr!".ToCharArray());
this.font.PixelHeight = 48;
font.PrepareCharacterGroup("01234567890.Your Stats: Score,ServerUp-timedownloadservedpacketssentWebsitePDRLN%que".ToCharArray());
return true;
}
public bool Deactivate()
{
return true;
}
public void Deinitialize()
{
}
public string getName()
{
return "GameOver";
}
public void Initialize(StateManager manager)
{
this.manager = manager;
}
public void Render(double delta)
{
renderer.Begin(Matrix4x4.Identity, delta);
titleFont.WriteLine(renderer, 1.95f, Game.HEIGHT_UNITS * 0.75f, "Game Over!", Color.Purple);
font.WriteLine(renderer, 1.95f, Game.HEIGHT_UNITS * 0.6f, "Score: " + score, Color.Black);
font.WriteLine(renderer, 1.95f, Game.HEIGHT_UNITS * 0.53f, "Website Uptime: " + timeElapsed.ToString("h\\:mm\\:ss"), Color.Black);
font.WriteLine(renderer, 1.95f, Game.HEIGHT_UNITS * 0.46f, "Packets Received: " + totalPackets + " Packet Loss: " + Math.Round((100f * (1f - ((float) packetsReceived / totalPackets))), 1) + "%", Color.Black);
font.WriteLine(renderer, 1.95f, Game.HEIGHT_UNITS * 0.39f, "Downloads Served: " + downloadsServed, Color.Black);
font.WriteLine(renderer, 1.95f, Game.HEIGHT_UNITS * 0.32f, "Downloads Requested: " + totalDownloads, Color.Black);
renderer.End();
}
public void SetStats(int score, float secondsElapsed, int downloads, int totalDownloads, int packetsReceived, int totalPackets) {
this.score = score;
this.timeElapsed = TimeSpan.FromSeconds(secondsElapsed);
this.downloadsServed = downloads;
this.totalPackets = totalPackets;
this.packetsReceived = packetsReceived;
this.totalDownloads = totalDownloads;
}
public void Update(double timeStep)
{
}
}
}

View File

@ -14,8 +14,9 @@ using SlatedGameToolkit.Framework.StateSystem.States;
using SlatedGameToolkit.Framework.Utilities.Collections.Pooling;
using SlatedGameToolkit.Framework.Utilities;
using SlatedGameToolkit.Framework.Graphics.Text;
using SkinnerBox.Utilities;
namespace SkinnerBox.States.Gameplay
namespace SkinnerBox.States
{
public class GamePlayState : IState
{
@ -23,6 +24,7 @@ namespace SkinnerBox.States.Gameplay
private AssetManager assets;
private StateManager stateManager;
private BitmapFont font;
private GameOverState gameOverState;
private Random random;
#region CursorVars
@ -52,14 +54,22 @@ namespace SkinnerBox.States.Gameplay
#endregion
#region PlayerStats
private readonly int totalUsage = 3;
private int usedUsage = 0;
private RectangleMesh usageMesh;
private int score;
private float timeElapsed;
private int speedBoost = 0;
private int bandwithBoost = 0;
private RectangleMesh bandwithMesh;
private RectangleMesh speedMesh;
private float score;
private TransitionValue timeElapsed;
private int downloadsServed;
private int totalDownloads;
private int packetsReceived;
private int totalPackets;
private readonly float totalStability = 5;
private float stability;
private RectangleMesh stabilityMesh;
#endregion
public GamePlayState(MeshBatchRenderer renderer, AssetManager asset, BitmapFont font)
public GamePlayState(MeshBatchRenderer renderer, AssetManager asset, BitmapFont font, GameOverState gameOverState)
{
this.assets = asset;
this.renderer = renderer;
@ -67,7 +77,7 @@ namespace SkinnerBox.States.Gameplay
warningPool = new ObjectPool<WarningEntity>(createWarning);
downloadPool = new ObjectPool<DownloadEntity>(createDownload);
this.font = font;
font.PrepareCharacterGroup("score:0123456789timlapsd".ToCharArray());
this.gameOverState = gameOverState;
}
public bool Activate()
@ -76,11 +86,26 @@ namespace SkinnerBox.States.Gameplay
Mouse.mouseUpdateEvent += MouseInput;
serverTargetPos = 0.5f * Game.WIDTH_UNITS;
server = new ServerEntity((Texture)assets["serverunit.png"], serverTargetPos, 0.1f);
usageMesh = new RectangleMesh(new RectangleF(0, Game.HEIGHT_UNITS - 0.75f, 0.5f, 0.5f), (ITexture)assets["usage.png"], Color.White);
bandwithMesh = new RectangleMesh(new RectangleF(0, Game.HEIGHT_UNITS - 0.75f, 0.5f, 0.5f), (ITexture)assets["serverunit.png"], Color.White);
stabilityMesh = new RectangleMesh(new RectangleF(0.05f, Game.HEIGHT_UNITS - 3.2f, 0.5f, 0.5f), (ITexture)assets["health.png"], Color.White);
speedMesh = new RectangleMesh(bandwithMesh.Bounds, (ITexture)assets["ram.png"], Color.White);
random = new Random();
packetSpawnInfo = new PacketSpawnInfo(2, 1, (float)(random.NextDouble() * Game.WIDTH_UNITS), 1f, 0.2f, 3f);
packetSpawnInfo = new PacketSpawnInfo(2, 1, (float)(random.NextDouble() * Game.WIDTH_UNITS), 1f, 0.2f, 2f);
downloadSpawnInfo = new DownloadSpawnInfo(4, 6, 3, 1, 4, 2);
score = 0;
timeElapsed.HardSet(0);
server.Size = 4;
bandwithBoost = server.Size;
speedBoost = 0;
stability = totalStability;
packetsReceived = 0;
totalPackets = 0;
downloadsServed = 0;
totalDownloads = 0;
this.font.PixelHeight = 32;
font.PrepareCharacterGroup("Score:0123456789Uptim.%".ToCharArray());
return true;
}
@ -145,24 +170,33 @@ namespace SkinnerBox.States.Gameplay
renderer.Draw(server);
#region StatusRender
for (int i = 0; i < totalUsage; i++)
for (int i = 0; i < bandwithBoost + speedBoost; i++)
{
usageMesh.X = 0.25f + (i * (usageMesh.Width + 0.2f));
if (i >= usedUsage) {
usageMesh.Color = Color.Yellow;
if (i < bandwithBoost) {
bandwithMesh.X = 0.25f + (i * (bandwithMesh.Width + 0.2f));
renderer.Draw(bandwithMesh);
} else {
usageMesh.Color = Color.White;
speedMesh.X = 0.25f + (i * (speedMesh.Width + 0.2f));
renderer.Draw(speedMesh);
}
renderer.Draw(usageMesh);
}
float normalizedHealth = stability / totalStability;
int red = (int) (byte.MaxValue * normalizedHealth);
stabilityMesh.Color = Color.FromArgb(red, 0, 0);
renderer.Draw(stabilityMesh);
font.WriteLine(renderer, stabilityMesh.Width + 0.1f, stabilityMesh.Y, Math.Round(100 * normalizedHealth, 1) + "%", Color.Red);
font.WriteLine(renderer, 0.05f, Game.HEIGHT_UNITS - 2f, "score: " + score, Color.Black);
timeElapsed.InterpolatePosition((float)delta);
font.WriteLine(renderer, 0.05f, Game.HEIGHT_UNITS - 1.75f, "Score: " + Math.Round(score, 0), Color.Black);
font.WriteLine(renderer, 0.05f, Game.HEIGHT_UNITS - 2.5f, "Uptime: " + Math.Round(timeElapsed.Value), Color.Black);
#endregion
renderer.End();
}
public void Update(double timeStep)
{
timeElapsed.Value = (float)timeStep + timeElapsed.DesignatedValue;
score += (float) timeStep * 0.5f;
#region ServerUpdate
if (Mouse.LeftButtonPressed) {
serverTargetPos = cursorWidthScale * Mouse.X;
@ -180,30 +214,33 @@ namespace SkinnerBox.States.Gameplay
#endregion
#region PacketUpdate
packetSpawnInfo.timeElapsed += (float) timeStep;
if (packetSpawnInfo.timeElapsed >= packetSpawnInfo.period) {
if (packetSpawnInfo.timeElapsed >= packetSpawnInfo.interval) {
packetSpawnInfo.timeElapsed = 0;
//do spawning
for(int i = 0; i < packetSpawnInfo.perSpawn; i++) {
PacketEntity packet = packetPool.Retrieve();
packet.CenterX = packetSpawnInfo.batchLocation;
packet.Y = i * packet.Height + packetSpawnInfo.distanceBetween + Game.HEIGHT_UNITS + packetSpawnInfo.speed * (2/3f);
packet.Y = i * packet.Height + packetSpawnInfo.range + Game.HEIGHT_UNITS + packetSpawnInfo.speed * (2/3f);
packet.velocity = packetSpawnInfo.speed;
packet.Color = Color.Blue;
totalPackets++;
activePackets.Add(packet);
}
//Spawn Warning
WarningEntity warning = warningPool.Retrieve();
warning.CenterX = packetSpawnInfo.batchLocation;
warning.LifeTime = packetSpawnInfo.period * (2/3f);
warning.LifeTime = packetSpawnInfo.interval * (2/3f);
warning.Y = Game.HEIGHT_UNITS - warning.Height;
activeWarnings.Add(warning);
//Prepare next batch
packetSpawnInfo.batchLocation = (float)(packetSpawnInfo.batchLocation + (random.NextDouble() - 1/2f) * packetSpawnInfo.jumpDistance * 2);
if (packetSpawnInfo.batchLocation > Game.WIDTH_UNITS - packetSafeMargin) {
packetSpawnInfo.batchLocation = Game.WIDTH_UNITS - packetSafeMargin;
} else if (packetSpawnInfo.batchLocation < packetSafeMargin) packetSpawnInfo.batchLocation = packetSafeMargin;
float change = (float)((float)(random.NextDouble() - 1/2f) * packetSpawnInfo.jumpDistance * 2);
if (packetSpawnInfo.batchLocation + change > Game.WIDTH_UNITS - packetSafeMargin || packetSpawnInfo.batchLocation + change < packetSafeMargin) {
packetSpawnInfo.batchLocation -= change;
} else {
packetSpawnInfo.batchLocation += change;
}
}
for (int i = 0; i < activePackets.Count; i++)
@ -215,15 +252,20 @@ namespace SkinnerBox.States.Gameplay
packet.Color = Color.Cyan;
}
if (packet.Y <= 0 - packet.Height) {
stability -= 0.5f;
packetPool.Release(packet);
activePackets.RemoveAt(i);
i--;
continue;
}
if (packet.Y >= Game.HEIGHT_UNITS && packet.velocity < 0) {
score += -2 * packet.velocity;
packetsReceived++;
stability += 0.05f;
packetPool.Release(packet);
activePackets.RemoveAt(i);
i--;
continue;
}
}
#endregion
@ -238,6 +280,7 @@ namespace SkinnerBox.States.Gameplay
download.Y = (float)(downloadSafeMargin + random.NextDouble() * (Game.HEIGHT_UNITS - 2 * downloadSafeMargin));
download.stepSize = downloadSpawnInfo.stepSize;
download.upTime = downloadSpawnInfo.upTime;
totalDownloads++;
activeDownloads.Add(download);
WarningEntity warning = warningPool.Retrieve();
@ -266,6 +309,8 @@ namespace SkinnerBox.States.Gameplay
if (download.progressValue.Value >= download.Width)
{
score += downloadSpawnInfo.maximumAmount * 2 + downloadSpawnInfo.sizeRange + 1f / downloadSpawnInfo.period + 2 * downloadSpawnInfo.stepSize;
downloadsServed++;
downloadPool.Release(download);
activeDownloads.RemoveAt(i);
i--;
@ -273,6 +318,7 @@ namespace SkinnerBox.States.Gameplay
}
if (download.timeElapsed.Value >= download.upTime)
{
stability -= 1.5f;
downloadPool.Release(download);
activeDownloads.RemoveAt(i);
i--;
@ -292,34 +338,65 @@ namespace SkinnerBox.States.Gameplay
}
}
#endregion
#region DifficultyUpdate
//packet curve
packetSpawnInfo.perSpawn = (int)(0.5f * (Math.Pow(timeElapsed.Value, 0.5f) + 1));
packetSpawnInfo.speed = (float)((0.025f * Math.Pow(timeElapsed.Value, 1.1f)) + 1f);
if (packetSpawnInfo.range < 4) {
packetSpawnInfo.range = (float)(0.1f * (Math.Pow(timeElapsed.Value, 1.15f)) + 2f);
if (packetSpawnInfo.range > 4) packetSpawnInfo.range = 4;
}
if (packetSpawnInfo.interval > 0.3f) {
packetSpawnInfo.interval = (float) (-0.0055 * timeElapsed.Value) + 2f;
if (packetSpawnInfo.interval < 0.3f) packetSpawnInfo.interval = 0.3f;
}
//download curve
if (downloadSpawnInfo.maximumAmount < 4) {
downloadSpawnInfo.maximumAmount = (int)(0.02f * timeElapsed.Value + 1);
}
if (downloadSpawnInfo.upTime > 3) {
downloadSpawnInfo.upTime = (float)(8 + (-0.1f * Math.Pow(timeElapsed.Value, 0.8f)));
if (downloadSpawnInfo.upTime < 3) downloadSpawnInfo.upTime = 3;
}
if (downloadSpawnInfo.period > 1.5f) {
downloadSpawnInfo.period = (float) (-0.006 * timeElapsed.Value) + 4;
if (packetSpawnInfo.interval < 1.5f) packetSpawnInfo.interval = 1.5f;
}
#endregion
#region BoundaryChecking
if (stability > totalStability) {
stability = totalStability;
} else if (stability <= 0)
{
stability = 0;
gameOverState.SetStats((int)Math.Round(this.score), this.timeElapsed.Value, downloadsServed, totalDownloads, packetsReceived, totalPackets);
stateManager.ChangeState("GameOver");
}
#endregion
}
public void KeyInputListener(SDL.SDL_Keycode keycode, bool down) {
if (!down) return;
if (keycode == SDL.SDL_Keycode.SDLK_a) {
if (usedUsage > 0 && server.Size > 1) {
usedUsage--;
int currentUsage = bandwithBoost + speedBoost;
if (keycode == SDL.SDL_Keycode.SDLK_SPACE) {
if (server.Size > 1) {
server.Size--;
}
}
if (keycode == SDL.SDL_Keycode.SDLK_d) {
if (usedUsage < totalUsage) {
usedUsage++;
server.Size++;
}
}
if (keycode == SDL.SDL_Keycode.SDLK_s) {
if (usedUsage > 0 && server.Speed > ServerEntity.MIN_SPEED) {
usedUsage--;
server.Speed -= ServerEntity.SPEED_STEP;
}
}
if (keycode == SDL.SDL_Keycode.SDLK_w) {
if (usedUsage < totalUsage) {
usedUsage++;
bandwithBoost--;
speedBoost++;
server.Speed += ServerEntity.SPEED_STEP;
}
}
if (keycode == SDL.SDL_Keycode.SDLK_LSHIFT) {
if (server.Speed > ServerEntity.MIN_SPEED) {
server.Speed -= ServerEntity.SPEED_STEP;
speedBoost--;
server.Size++;
bandwithBoost++;
}
}
}
public void MouseInput(bool leftDown, bool rightDown, bool middle, int x, int y, int scrollX, int scrollY) {

View File

@ -2,7 +2,6 @@ using System;
using System.Drawing;
using System.Numerics;
using SDL2;
using SkinnerBox.States.Gameplay;
using SlatedGameToolkit.Framework.AssetSystem;
using SlatedGameToolkit.Framework.Graphics;
using SlatedGameToolkit.Framework.Graphics.Render;
@ -14,7 +13,7 @@ using SlatedGameToolkit.Framework.Loaders;
using SlatedGameToolkit.Framework.StateSystem;
using SlatedGameToolkit.Framework.StateSystem.States;
namespace SkinnerBox.States.Main
namespace SkinnerBox.States
{
public class MenuState : IState
{
@ -29,6 +28,12 @@ namespace SkinnerBox.States.Main
public bool Activate()
{
Keyboard.keyboardUpdateEvent += KeyInput;
this.titleFont.PixelHeight = 120;
this.titleFont.PrepareCharacterGroup("You Are the Website.".ToCharArray());
this.titleFont.PixelHeight = 40;
this.titleFont.PrepareCharacterGroup("By: Reslate".ToCharArray());
boldFont.PixelHeight = 60;
boldFont.PrepareCharacterGroup("Press any key to start...".ToCharArray());
return true;
}
@ -62,12 +67,17 @@ namespace SkinnerBox.States.Main
this.camera.MoveTo = this.camera.Position;
this.renderer = new MeshBatchRenderer(camera);
//Add additional states
//Set up title TTF
this.titleFont = new BitmapFont("resources/BigShouldersDisplay-Regular.ttf", textureSizes: 512);
this.titleFont.PixelsPerUnitHeight = 80;
this.titleFont.PixelsPerUnitWidth = 80;
BitmapFont genericFont = new BitmapFont("resources/BigShouldersDisplay-Light.ttf");
genericFont.PixelsPerUnitHeight = 80;
genericFont.PixelsPerUnitWidth = 80;
genericFont.PixelHeight = 32;
manager.AddState(new GamePlayState(renderer, this.assets, genericFont));
//Add additional states
GameOverState gameOverState = new GameOverState(genericFont, titleFont, renderer, assets);
manager.AddState(gameOverState);
manager.AddState(new GamePlayState(renderer, this.assets, genericFont, gameOverState));
//Load assets
assets.Load("serverunit.png");
@ -76,22 +86,14 @@ namespace SkinnerBox.States.Main
assets.Load("downloadbar.png");
assets.Load("drag.png");
assets.Load("usage.png");
assets.Load("health.png");
assets.Load("ram.png");
//Set up title TTF
this.titleFont = new BitmapFont("resources/BigShouldersDisplay-Regular.ttf", textureSizes: 512);
this.titleFont.PixelHeight = 120;
this.titleFont.PixelsPerUnitHeight = 80;
this.titleFont.PixelsPerUnitWidth = 80;
this.titleFont.PrepareCharacterGroup("You Are the Website.".ToCharArray());
this.titleFont.PixelHeight = 40;
this.titleFont.PrepareCharacterGroup("By: Reslate".ToCharArray());
//Set up bold TTF
boldFont = new BitmapFont("resources/BigShouldersDisplay-Black.ttf", textureSizes: 512);
boldFont.PixelHeight = 60;
boldFont.PixelsPerUnitWidth = 80;
boldFont.PixelsPerUnitHeight = 80;
boldFont.PrepareCharacterGroup("Press any key to start...".ToCharArray());
//Set up icon
Texture serverUnitTex = (Texture)assets["serverunit.png"];

View File

@ -1,6 +1,6 @@
using SlatedGameToolkit.Framework.Graphics.Render;
namespace SkinnerBox.Utilities.Gameplay
namespace SkinnerBox.Utilities
{
public struct TransitionValue : IPositionInterpolable
{

BIN
resources/health.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

BIN
resources/ram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B