Add project files.

This commit is contained in:
2025-12-16 08:51:34 -05:00
parent ed4d50a5bd
commit f7e3fe0a47
140 changed files with 2946 additions and 0 deletions

View 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);
}
}
}
}