LADXHD/InGame/GameObjects/Things/ObjIslandBackground.cs

184 lines
7.6 KiB
C#
Raw Normal View History

2023-12-14 22:21:22 +00:00
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ProjectZ.InGame.GameObjects.Base;
using ProjectZ.InGame.GameObjects.Base.CObjects;
using ProjectZ.InGame.GameObjects.Base.Components;
using ProjectZ.InGame.Map;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Things;
namespace ProjectZ.InGame.GameObjects.Things
{
internal class ObjIslandBackground : GameObject
{
class Cloud
{
public int Index;
public float LiveCounter;
public float Transparency = 1;
public Vector2 Position;
public Cloud(int index, Vector2 position)
{
Index = index;
Position = position;
LiveCounter = Game1.RandomNumber.Next(5000, 50000);
}
}
private Rectangle[] cloudSourceRectangles = new Rectangle[3];
private Cloud[] _clouds;
private const int GradientHeight = 120;
private readonly Rectangle _waveSource;
private readonly Rectangle _topWaveSource;
private readonly Color _colorSky = new Color(65, 90, 255);
private readonly Color _colorOceanBright = new Color(66, 89, 255);
private readonly DictAtlasEntry _oceanGradient;
private const int LeftCloudPosition = -1300;
private int _topWaveFrame;
private int _topWaveSpeed = 250;
public ObjIslandBackground() : base("water_3") { }
public ObjIslandBackground(Map.Map map, int posX, int posY) : base(map)
{
_waveSource = Resources.SourceRectangle("water_3");
_waveSource.Width = 16;
_topWaveSource = Resources.SourceRectangle("water_12");
_topWaveSource.Width = 16;
cloudSourceRectangles[0] = Resources.SourceRectangle("cloud_0");
cloudSourceRectangles[1] = Resources.SourceRectangle("cloud_1");
cloudSourceRectangles[2] = Resources.SourceRectangle("cloud_2");
_clouds = new Cloud[50];
_oceanGradient = Resources.GetSprite("overworld_gradient");
// spawn the clouds
var positionX = LeftCloudPosition;
for (var i = 0; i < _clouds.Length; i++)
{
var index = Game1.RandomNumber.Next(0, cloudSourceRectangles.Length);
_clouds[i] = new Cloud(index, new Vector2(positionX, 32 - cloudSourceRectangles[index].Height));
positionX += cloudSourceRectangles[index].Width + Game1.RandomNumber.Next(1, 7) * 16;
}
AddComponent(UpdateComponent.Index, new UpdateComponent(Update));
AddComponent(DrawComponent.Index, new DrawComponent(Draw, Values.LayerBackground, new CPosition(posX, posY, 0)));
}
public void Update()
{
// all the animations are in sync
_topWaveFrame = ((int)(Game1.TotalGameTime) % (4 * _topWaveSpeed)) / _topWaveSpeed;
// move the clouds
foreach (var cloud in _clouds)
{
var cloudSpeed = (Math.Sin(cloud.Position.X / 100) * 0.125 + 1) * 0.015 * Game1.TimeMultiplier;
cloud.Position.X -= (float)cloudSpeed;
// set the cloud to the right position
if (cloud.Position.X < LeftCloudPosition)
{
float rightPosition = 0;
foreach (var cloud1 in _clouds)
{
if (cloud1.Position.X > rightPosition)
rightPosition = cloud1.Position.X + cloudSourceRectangles[cloud1.Index].Width;
}
cloud.Position.X = rightPosition + Game1.RandomNumber.Next(1, 7) * 16;
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
if (MapManager.Camera.Scale <= 0)
return;
var cameraRectangle = MapManager.Camera.GetCameraRectangle();
var left = (int)(cameraRectangle.X / _waveSource.Width / MapManager.Camera.Scale) - 1;
var right = (int)(cameraRectangle.Right / _waveSource.Width / MapManager.Camera.Scale) + 1;
var top = (int)(cameraRectangle.Y / _waveSource.Height / MapManager.Camera.Scale);
var bottom = (int)(cameraRectangle.Bottom / _waveSource.Height / MapManager.Camera.Scale) + 1;
if (cameraRectangle.X < 0)
{
left--;
right++;
}
if (cameraRectangle.Y < 0)
{
top--;
bottom++;
}
// draw the top waves
if (top <= 2 && bottom > 2)
for (var x = left; x < right + 1; x++)
{
spriteBatch.Draw(Resources.SprObjects, new Rectangle(
x * _topWaveSource.Width, 2 * _topWaveSource.Height, _topWaveSource.Width, _topWaveSource.Height),
new Rectangle(
_topWaveSource.X + _topWaveSource.Width * _topWaveFrame, _topWaveSource.Y,
_topWaveSource.Width, _topWaveSource.Height), Color.White);
}
// change context to have smooth gradient transition
spriteBatch.End();
ObjectManager.SpriteBatchBeginAnisotropic(spriteBatch, null);
if (top <= 10 && bottom >= 4)
DrawGradient(spriteBatch, left, right, 3, 10);
if (left < 1)
DrawGradient(spriteBatch, left, 2, Math.Max(3, top), Math.Min(bottom, GradientHeight + 3));
if (right > 16 * 10)
DrawGradient(spriteBatch, 16 * 10, right, Math.Max(3, top), Math.Min(bottom, GradientHeight + 3));
spriteBatch.End();
ObjectManager.SpriteBatchBegin(spriteBatch, null);
var oceanBottomTop = Math.Max(3 + GradientHeight, top);
var oceanBottomBottom = Math.Max(3 + GradientHeight, bottom);
spriteBatch.Draw(Resources.SprWhite, new Rectangle(
left * Values.TileSize, oceanBottomTop * Values.TileSize, (right - left + 1) * Values.TileSize, (oceanBottomBottom - oceanBottomTop + 1) * Values.TileSize), _colorOceanBright);
// draw the sky
if (top < 2)
{
spriteBatch.Draw(Resources.SprWhite, new Rectangle(
left * 16, (top - 1) * 16,
(right - left + 1) * 16, (-top + 3) * 16), _colorSky);
}
// draw the clouds
foreach (var cloud in _clouds)
{
DrawHelper.DrawNormalized(spriteBatch, Resources.SprObjects, cloud.Position, cloudSourceRectangles[cloud.Index], Color.White * cloud.Transparency);
}
}
private void DrawGradient(SpriteBatch spriteBatch, int left, int right, int top, int bottom)
{
spriteBatch.Draw(_oceanGradient.Texture, new Rectangle(
left * Values.TileSize, top * Values.TileSize, (right - left) * Values.TileSize, (bottom - top) * Values.TileSize),
new Rectangle(
_oceanGradient.ScaledRectangle.X,
_oceanGradient.ScaledRectangle.Y + (int)(_oceanGradient.ScaledRectangle.Height * ((top + 0) / (float)GradientHeight)),
_oceanGradient.ScaledRectangle.Width,
(int)(_oceanGradient.ScaledRectangle.Height * ((bottom - (top + 3)) / (float)GradientHeight))), Color.White);
}
}
}