Skip to content

Commit

Permalink
Working camera 2
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkSuckerberg committed Oct 6, 2023
1 parent a278a16 commit de4c60c
Show file tree
Hide file tree
Showing 16 changed files with 450 additions and 224 deletions.
3 changes: 2 additions & 1 deletion .run/Blocktest (Local Multiplayer).run.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Blocktest (Local Multiplayer)" type="DotNetProject" factoryName=".NET Project">
<configuration default="false" name="Blocktest (Local Multiplayer)" type="DotNetProject" factoryName=".NET Project"
singleton="false">
<option name="EXE_PATH" value="$PROJECT_DIR$/Blocktest/bin/Debug/net7.0/Blocktest.exe" />
<option name="PROGRAM_PARAMETERS" value="connect 127.0.0.1" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Blocktest/bin/Debug/net7.0" />
Expand Down
6 changes: 5 additions & 1 deletion Blocktest.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Blocktest/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Adjacencies/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Blocktest/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Renderable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=renderables/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Smoothable/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
3 changes: 2 additions & 1 deletion Blocktest/BlocktestGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ public sealed class BlocktestGame : Game {
private IScene? _currentScene;
private GraphicsDeviceManager _graphics;


/// <inheritdoc />
public BlocktestGame() {
_connect = false;
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
TargetElapsedTime = TimeSpan.FromMilliseconds(16);
Window.AllowUserResizing = true;
}

public BlocktestGame(string newIp) {
Expand All @@ -26,6 +26,7 @@ public BlocktestGame(string newIp) {
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
Window.AllowUserResizing = true;
TargetElapsedTime = TimeSpan.FromMilliseconds(16);
}

Expand Down
17 changes: 7 additions & 10 deletions Blocktest/Code/Block System/BlockSprites.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Blocktest.Block_System;
/// </summary>
public sealed class BlockSprites {
/// <summary> Shared block info </summary>
public BlockShared BlockShared;
private readonly BlockShared _blockShared;

/// <summary> The block's sprite. </summary>
public Drawable BlockSprite;
Expand All @@ -18,7 +18,7 @@ public sealed class BlockSprites {
/* METHODS */

public BlockSprites(BlockShared newBlockShared) {
BlockShared = newBlockShared;
_blockShared = newBlockShared;
LoadSprite();
}

Expand All @@ -29,27 +29,24 @@ public BlockSprites(BlockShared newBlockShared) {
/// DO NOT FORGET TO CALL THE BASE METHOD IF YOU OVERRIDE THIS.
/// </remarks>
public void LoadSprite() {
string path = @"Graphics\Blocks\" + BlockShared.BlockName.ToLower().Replace(" ", "");
string path = @"Graphics\Blocks\" + _blockShared.BlockName.ToLower().Replace(" ", "");
try {
BlockSprite =
new Drawable(path,
new Rectangle(1, 1, 10,
10)); //this might need to be expanded in the future in case we decide to make use of the full 12x12 tiles on our spritesheets
if (!BlockShared.BlockSmoothing) {
if (!_blockShared.BlockSmoothing) {
return;
}
SpriteSheet = new SpriteSheet(path, 4, 4, 1);
if (SpriteSheet.OrderedSprites.Length <= 1) {
Console.WriteLine("Block " +
this +
" is marked as smoothable, but a sprite sheet could not be found at " +
path +
"!");
Console.WriteLine(
$"Block {this} is marked as smoothable, but a sprite sheet could not be found at {path}!");
}
}
catch (ContentLoadException) {
BlockSprite = new Drawable(@"Graphics\Blocks\error");
Console.WriteLine("Block " + this + " does not have an icon at " + path + "!");
Console.WriteLine($"Block {this} does not have a sprite at {path}!");
}
}
}
66 changes: 66 additions & 0 deletions Blocktest/Code/Block System/RenderableTile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using Blocktest.Rendering;
using Shared.Code;
using Shared.Code.Block_System;
namespace Blocktest.Block_System;

public class RenderableTile : TileShared {
public readonly Renderable Renderable;

public RenderableTile(TileShared tile, bool background) : base(tile.SourceBlock,
tile.Transform.Position / GlobalsShared.GridSize) {
Renderable = new Renderable(Transform, background ? Layer.BackgroundBlocks : Layer.ForegroundBlocks,
BlockSpritesManager.AllBlocksSprites[tile.SourceBlock.BlockId].BlockSprite, tile.Color);
}

/// <summary>
/// This method is called whenever an adjacent (according to a tilemap's adjacency variable) tile is placed or removed.
/// Used for smoothing.
/// </summary>
/// <param name="position">The position of the current tile.</param>
/// <param name="tilemap">The tilemap the tile is on.</param>
public void UpdateAdjacencies(Vector2Int position, TilemapShared tilemap) {
if (!SourceBlock.BlockSmoothing) {
return;
} // If the tile doesn't smooth, don't even try

int bitmask = 0; // Uses bitmask smoothing, look it up

if (HasSmoothableTile(position + Vector2Int.Up, tilemap)) {
bitmask += 1;
}
if (HasSmoothableTile(position + Vector2Int.Down, tilemap)) {
bitmask += 2;
}
if (HasSmoothableTile(position + Vector2Int.Right, tilemap)) {
bitmask += 4;
}
if (HasSmoothableTile(position + Vector2Int.Left, tilemap)) {
bitmask += 8;
}

Renderable.Appearance = BlockSpritesManager.AllBlocksSprites[SourceBlock.BlockId].SpriteSheet
.OrderedSprites[bitmask];
}

/// <summary>
/// Whether or not the tile at a certain <paramref name="position" /> can smooth with this tile.
/// </summary>
/// <param name="position">The position of the tile to check for smoothing.</param>
/// <param name="tilemap">The tilemap on which the tile you want to check for smoothing is.</param>
/// <returns>Whether or not the tile can smooth with this tile.</returns>
private bool HasSmoothableTile(Vector2Int position, TilemapShared tilemap) {
if (tilemap.TryGetTile(position, out TileShared? tile)) {
return SourceBlock.SmoothSelf
? IsSameTileType(tile)
: tile.SourceBlock.BlockId != 0; // Don't smooth with air, possibly find nicer way to do this later.
}
return false;
}

/// <summary>
/// If the tile provided is the same type (references the same block) as the current tile.
/// </summary>
/// <param name="otherTile">The other tile to check.</param>
/// <returns>Whether or not the other block is the same type as the current tile</returns>
private bool IsSameTileType(TileShared otherTile) => otherTile.SourceBlock == SourceBlock;
}
60 changes: 60 additions & 0 deletions Blocktest/Code/Block System/RenderableTilemap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Blocktest.Rendering;
using Shared.Code;
using Shared.Code.Block_System;
namespace Blocktest.Block_System;

public class RenderableTilemap {
private readonly TilemapShared _tilemap;

private readonly RenderableTile[,] _renderables;
private readonly Camera _camera;

/// <summary>
/// A list of <see cref="Vector2Int" />s that specify which blocks should be refreshed when a tile is placed/destroyed.
/// Defaults to the changed block and all cardinal directions.
/// </summary>
private static readonly List<Vector2Int> Adjacencies = new()
{ Vector2Int.Zero, Vector2Int.Up, Vector2Int.Down, Vector2Int.Left, Vector2Int.Right };


public RenderableTilemap(TilemapShared newTilemap, Camera camera) {
_tilemap = newTilemap;
_camera = camera;
_renderables = new RenderableTile[_tilemap.TilemapSize.X, _tilemap.TilemapSize.Y];
UpdateRenderables();
newTilemap.OnTileChanged += OnTilemapChanged;
}

private void OnTilemapChanged(TileShared tile, Vector2Int location) {
_camera.RenderedComponents.Remove(_renderables[location.X, location.Y].Renderable);

foreach (Vector2Int dir in Adjacencies) {
if (location.X + dir.X < 0 ||
location.X + dir.X >= _tilemap.TilemapSize.X ||
location.Y + dir.Y < 0 ||
location.Y + dir.Y >= _tilemap.TilemapSize.Y) {
continue;
}
_renderables[location.X + dir.X, location.Y + dir.Y].UpdateAdjacencies(location + dir, _tilemap);
}

RenderableTile newTile = new RenderableTile(tile, _tilemap.Background);
_renderables[location.X, location.Y] = newTile;
newTile.UpdateAdjacencies(location, _tilemap);
_camera.RenderedComponents.Add(newTile.Renderable);
}

private void UpdateRenderables() {
_camera.RenderedComponents.Clear();
for (int x = 0; x < _tilemap.TilemapSize.X; x++)
for (int y = 0; y < _tilemap.TilemapSize.Y; y++) {
if (!_tilemap.TryGetTile(new Vector2Int(x, y), out TileShared? tile)) {
continue;
}
RenderableTile newTile = new RenderableTile(tile, _tilemap.Background);
_renderables[x, y] = newTile;
_camera.RenderedComponents.Add(newTile.Renderable);
newTile.UpdateAdjacencies(new Vector2Int(x, y), _tilemap);
}
}
}
49 changes: 0 additions & 49 deletions Blocktest/Code/Block System/TilemapSprites.cs

This file was deleted.

65 changes: 65 additions & 0 deletions Blocktest/Code/Rendering/Camera.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
namespace Blocktest.Rendering;

public sealed class Camera {
private readonly Color _backgroundColor;
private readonly Vector2 _size;

public readonly List<Renderable> RenderedComponents = new();

public Rectangle RenderLocation;
public readonly RenderTarget2D RenderTarget;
public Vector2 Position;

public Camera(Vector2 position, Vector2 size, GraphicsDevice graphicsDevice, Color? backgroundColor = null) {
Position = position;
_size = size;
_backgroundColor = backgroundColor ?? Color.CornflowerBlue;
RenderTarget = new RenderTarget2D(graphicsDevice, (int)size.X, (int)size.Y, false, SurfaceFormat.Color,
DepthFormat.None, 0, RenderTargetUsage.DiscardContents);
}

public void Draw(GraphicsDevice graphics, SpriteBatch spriteBatch) {
graphics.SetRenderTarget(RenderTarget);
graphics.Clear(_backgroundColor);

spriteBatch.Begin();

foreach (Renderable component in RenderedComponents) {
if (component.Appearance == null) {
continue;
}

Vector2 worldPosition = component.Transform.Position;
Vector2 cameraPosition = worldPosition - Position;

if (worldPosition.X + component.Appearance.Bounds.Width < Position.X &&
worldPosition.X > Position.X + _size.X &&
worldPosition.Y + component.Appearance.Bounds.Height < Position.Y &&
worldPosition.Y > Position.Y + _size.Y) {
continue;
}

Vector2 flippedPosition = new(cameraPosition.X,
RenderTarget.Height - cameraPosition.Y - component.Appearance.Bounds.Height);

Rectangle positionBounds = new((int)flippedPosition.X, (int)flippedPosition.Y,
(int)(component.Appearance.Bounds.Width * component.Transform.Scale.X),
(int)(component.Appearance.Bounds.Height * component.Transform.Scale.Y));

spriteBatch.Draw(component.Appearance.Texture, positionBounds, component.Appearance.Bounds,
component.RenderColor, component.Transform.Rotation, component.Transform.Origin, SpriteEffects.None,
(float)component.Layer / EnumCount);
}

spriteBatch.End();

graphics.SetRenderTarget(null);
}

private static readonly int EnumCount = Enum.GetValues(typeof(Layer)).Length;

public Vector2 CameraToWorldPos(Vector2 mouseState) => new(
(mouseState.X - RenderLocation.X) / RenderLocation.Width * RenderTarget.Width + Position.X, Position.Y +
RenderTarget.Height -
(mouseState.Y - RenderLocation.Y) / RenderLocation.Height * RenderTarget.Height);
}
35 changes: 35 additions & 0 deletions Blocktest/Code/Rendering/Renderable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Shared.Code.Components;
namespace Blocktest.Rendering;

public enum Layer {
Top = 0,
Player = 1,
Default = 2,
ForegroundBlocks = 3,
BackgroundBlocks = 4
}

public sealed class Renderable {
public readonly Transform Transform;
public Drawable? Appearance;
public Color RenderColor;
public Layer Layer;

public Renderable(Transform transform, Layer layer = Layer.Default, Drawable? appearance = null,
Color? renderColor = null) {
Transform = transform;
Layer = layer;
Appearance = appearance;
RenderColor = renderColor ?? Color.White;
}

public void Draw(SpriteBatch spriteBatch, Vector2 cameraPosition) {
if (Appearance == null) {
return;
}

spriteBatch.Draw(Appearance.Texture, Transform.Position - cameraPosition, Appearance.Bounds, RenderColor,
Transform.Rotation, Transform.Origin, Transform.Scale,
SpriteEffects.None, 0);
}
}
Loading

0 comments on commit de4c60c

Please sign in to comment.