Add project files.
This commit is contained in:
196
AlientAttack.MonoGame/GameLoops/GameLoop.cs
Normal file
196
AlientAttack.MonoGame/GameLoops/GameLoop.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using AlienAttack.MonoGame.Things;
|
||||
using AlienAttack.MonoGame.Things.Enemies;
|
||||
using AlienAttack.MonoGame.Things.Stars;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AlienAttack.MonoGame.GameLoops;
|
||||
|
||||
internal class GameLoop : GameLoopBase
|
||||
{
|
||||
private readonly List<Sprite> _spritesToAdd = [];
|
||||
private readonly Random _random = new();
|
||||
|
||||
private int _spawnNewEnemyThreshold = 100;
|
||||
private float _backgroundYOffset = 0;
|
||||
|
||||
private Starfield _starfield;
|
||||
private Texture2D _pixel;
|
||||
|
||||
protected readonly List<Sprite> Sprites = [];
|
||||
|
||||
public GameLoop(AlienAttackGame game) : base(game)
|
||||
{
|
||||
InitializeStarField(game);
|
||||
Sprites.Add(new Player(game.ViewTransform.ScreenWidth / 2 - 32, game.ViewTransform.ScreenHeight - 64));
|
||||
}
|
||||
|
||||
private void InitializeStarField(AlienAttackGame game)
|
||||
{
|
||||
_starfield = new Starfield(seed: 42);
|
||||
|
||||
//// Far layer: many tiny, slow, faint
|
||||
//_starfield.AddLayer(count: 450, speedPxPerSec: 20f, minSize: 1f, maxSize: 1.5f, minAlpha: 0.15f, maxAlpha: 0.35f);
|
||||
|
||||
//// Mid layer
|
||||
//_starfield.AddLayer(count: 220, speedPxPerSec: 45f, minSize: 1.5f, maxSize: 2.2f, minAlpha: 0.25f, maxAlpha: 0.60f);
|
||||
|
||||
//// Near layer: fewer, bigger, faster, brighter
|
||||
//_starfield.AddLayer(count: 90, speedPxPerSec: 85f, minSize: 2.0f, maxSize: 3.2f, minAlpha: 0.40f, maxAlpha: 0.90f);
|
||||
|
||||
_starfield.AddLayer(count: 450, velocityPxPerSec: new Vector2(+4f, 20f), minSize: 1f, maxSize: 1.5f, minAlpha: 0.15f, maxAlpha: 0.35f);
|
||||
_starfield.AddLayer(count: 220, velocityPxPerSec: new Vector2(-10f, 45f), minSize: 1.5f, maxSize: 2.2f, minAlpha: 0.25f, maxAlpha: 0.60f);
|
||||
_starfield.AddLayer(count: 90, velocityPxPerSec: new Vector2(+20f, 85f), minSize: 2.0f, maxSize: 3.2f, minAlpha: 0.40f, maxAlpha: 0.90f);
|
||||
|
||||
|
||||
_pixel = new Texture2D(game.GraphicsDevice, 1, 1);
|
||||
_pixel.SetData(new[] { Color.White });
|
||||
|
||||
_starfield.Initialize(ViewTransform.ScreenWidth, ViewTransform.ScreenHeight);
|
||||
}
|
||||
|
||||
public override void OnDraw()
|
||||
{
|
||||
_starfield.Draw(SpriteBatch, _pixel);
|
||||
//DrawBackground();
|
||||
DrawSprites();
|
||||
}
|
||||
|
||||
private void DrawBackground()
|
||||
{
|
||||
Texture2D backgroundTexture = Content.Load<Texture2D>($@"Background\PixelBackgroundSeamlessVertically");
|
||||
int blockCountY = (int)Math.Ceiling((decimal)ViewTransform.ScreenHeight / (decimal)backgroundTexture.Height);
|
||||
int blockCountX = (int)Math.Ceiling((decimal)ViewTransform.ScreenWidth / (decimal)backgroundTexture.Width);
|
||||
|
||||
for (int y = 0; y < blockCountY; y++)
|
||||
{
|
||||
float startY = (y * backgroundTexture.Height) + _backgroundYOffset;
|
||||
_backgroundYOffset = _backgroundYOffset + 0.25f;
|
||||
|
||||
if (_backgroundYOffset > ViewTransform.ScreenHeight)
|
||||
{
|
||||
_backgroundYOffset = 0;
|
||||
}
|
||||
|
||||
for (int x = 0; x < blockCountX; x++)
|
||||
{
|
||||
int width = backgroundTexture.Width;
|
||||
|
||||
if (x * backgroundTexture.Width + backgroundTexture.Width > ViewTransform.ScreenWidth)
|
||||
{
|
||||
width = ViewTransform.ScreenWidth - (x * backgroundTexture.Width);
|
||||
}
|
||||
|
||||
Vector2 position = new(x * backgroundTexture.Width, startY);
|
||||
SpriteBatch.Draw(backgroundTexture, position, new Rectangle(new Point(x, y), new Point(width, backgroundTexture.Height)), Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSprites()
|
||||
{
|
||||
SpriteDrawArgs args = new(Game);
|
||||
|
||||
foreach (Sprite sprite in Sprites)
|
||||
{
|
||||
sprite.Draw(args);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUpdate(GameTime gameTime)
|
||||
{
|
||||
_starfield.Update(gameTime);
|
||||
UpdateSprites(gameTime);
|
||||
CheckSpriteCollisions();
|
||||
ClearDeadSprites();
|
||||
AddEnemySprites();
|
||||
AddNewSprites();
|
||||
}
|
||||
|
||||
private void UpdateSprites(GameTime gameTime)
|
||||
{
|
||||
SpriteUpdateContext args = new(Game)
|
||||
{
|
||||
Random = _random,
|
||||
GameTime = gameTime,
|
||||
SpawnSprite = _spritesToAdd.Add
|
||||
};
|
||||
|
||||
foreach (Sprite sprite in Sprites)
|
||||
{
|
||||
sprite.Update(args);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSpriteCollisions()
|
||||
{
|
||||
var collisionSprites = Sprites.Where(x => x.CanCollide).ToList();
|
||||
|
||||
foreach (var sprite in collisionSprites)
|
||||
{
|
||||
foreach (var otherSprite in collisionSprites.Where(x => x != sprite))
|
||||
{
|
||||
SpriteCollisionContext context = new(Game)
|
||||
{
|
||||
Sprite = otherSprite,
|
||||
SpawnSprite = _spritesToAdd.Add
|
||||
};
|
||||
|
||||
// TODO: If perfomed once; do not perform again
|
||||
if (sprite.Intersects(otherSprite))
|
||||
{
|
||||
sprite.OnCollision(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearDeadSprites()
|
||||
{
|
||||
var deadSprites = Sprites.Where(x => x.IsDead).ToList();
|
||||
|
||||
foreach (var sprite in deadSprites)
|
||||
{
|
||||
Sprites.Remove(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNewSprites()
|
||||
{
|
||||
foreach (Sprite sprite in _spritesToAdd)
|
||||
{
|
||||
Sprites.Add(sprite);
|
||||
}
|
||||
|
||||
_spritesToAdd.Clear();
|
||||
}
|
||||
|
||||
private void AddEnemySprites()
|
||||
{
|
||||
if (_spawnNewEnemyThreshold > 0)
|
||||
{
|
||||
_spawnNewEnemyThreshold--;
|
||||
}
|
||||
|
||||
if (_spawnNewEnemyThreshold == 0)
|
||||
{
|
||||
int randomNumber = _random.Next(0, 100);
|
||||
|
||||
if (randomNumber == 0)
|
||||
{
|
||||
Enemy enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64);
|
||||
Sprites.Add(enemy);
|
||||
_spawnNewEnemyThreshold = 100 + _random.Next(0, 100);
|
||||
}
|
||||
else if (randomNumber == 1)
|
||||
{
|
||||
RedEnemy enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64);
|
||||
Sprites.Add(enemy);
|
||||
_spawnNewEnemyThreshold = 100 + _random.Next(0, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user