Browse Source

Most of a second expansion sufficient to make a game done

master
Ludovic 'Archivist' Lagouardette 8 months ago
parent
commit
a3887417a5
14 changed files with 310 additions and 47 deletions
  1. +47
    -24
      Expansion1/CrosshairGizmoComponent.cs
  2. +1
    -1
      Expansion1/RectangleGizmoComponent.cs
  3. +49
    -0
      Expansion2/ArrowComponent.cs
  4. +36
    -0
      Expansion2/ExampleShootingInputComponent.cs
  5. +35
    -0
      Expansion2/RaylibAssetManagerModule.cs
  6. +37
    -0
      Expansion2/SpriteComponent.cs
  7. +25
    -0
      Expansion2/TimeToLiveComponent.cs
  8. +29
    -11
      Program.cs
  9. +18
    -1
      Smoll/Engine.cs
  10. +9
    -3
      Smoll/Entity.cs
  11. +3
    -1
      Smoll/IActionable.cs
  12. +6
    -0
      Smoll/IEngineModule.cs
  13. +13
    -4
      Smoll/Layer.cs
  14. +2
    -2
      Smoll/Transform2D.cs

+ 47
- 24
Expansion1/CrosshairGizmoComponent.cs View File

@ -14,30 +14,53 @@ namespace Smoll.Ex1 {
}
public override void Draw(Smoll.Layer.DrawMode drawMode) {
ownerTransform ??= owner.GetComponent<Transform2DComponent>();
ownerTransform ??= new Transform2DComponent();
var tr = ownerTransform.AbsoluteTransform();
Raylib.DrawCircleLines((int)tr.position.Real, (int)tr.position.Imaginary, 5.5f, Color.Black);
Raylib.DrawLine(
(int)tr.position.Real,
(int)tr.position.Imaginary-10,
(int)tr.position.Real,
(int)tr.position.Imaginary+10,
Color.Lime);
Raylib.DrawLine(
(int)tr.position.Real-10,
(int)tr.position.Imaginary,
(int)tr.position.Real+10,
(int)tr.position.Imaginary,
Color.Red);
Raylib.DrawText(
tr.angle.ToString(),
(int)tr.position.Real+10,
(int)tr.position.Imaginary+10,
14,
Color.Magenta
);
if(drawMode == Layer.DrawMode.Debug) {
ownerTransform ??= owner.GetComponent<Transform2DComponent>();
ownerTransform ??= new Transform2DComponent();
var tr = ownerTransform.AbsoluteTransform();
Raylib.DrawCircleLines((int)tr.position.Real, (int)tr.position.Imaginary, 5.5f, Color.Black);
Raylib.DrawLine(
(int)tr.position.Real,
(int)tr.position.Imaginary-10,
(int)tr.position.Real,
(int)tr.position.Imaginary+10,
Color.Lime);
Raylib.DrawLine(
(int)tr.position.Real-10,
(int)tr.position.Imaginary,
(int)tr.position.Real+10,
(int)tr.position.Imaginary,
Color.Red);
Raylib.DrawText(
tr.angle.ToString(),
(int)tr.position.Real+10,
(int)tr.position.Imaginary+10,
14,
Color.Magenta
);
Raylib.DrawText(
tr.angle.ToString(),
(int)tr.position.Real+10,
(int)tr.position.Imaginary+10,
14,
Color.Magenta
);
Raylib.DrawText(
tr.position.Real.ToString(),
(int)tr.position.Real+10,
(int)tr.position.Imaginary+26,
14,
Color.Red
);
Raylib.DrawText(
tr.position.Imaginary.ToString(),
(int)tr.position.Real+10,
(int)tr.position.Imaginary+42,
14,
Color.Lime
);
}
}
}
}

+ 1
- 1
Expansion1/RectangleGizmoComponent.cs View File

@ -32,7 +32,7 @@ namespace Smoll.Ex1 {
(float)(0),
(float)(0)
),
tr.angle*360f/MathF.PI,
tr.angle*180f/MathF.PI,
color
);
}

+ 49
- 0
Expansion2/ArrowComponent.cs View File

@ -0,0 +1,49 @@
using System.Numerics;
using Raylib_cs;
namespace Smoll.Ex2 {
class ArrowComponent : Smoll.Component {
Complex offset;
public Complex rawValue;
Transform2DComponent? ownerTransform;
public ArrowComponent(int offset_x = 0, int offset_y = 0)
{
this.offset = offset_x + Complex.ImaginaryOne*offset_y;
}
public override void OnAttached() {
ownerTransform = owner.GetComponent<Transform2DComponent>();
}
public Complex Origin() {
ownerTransform ??= owner.GetComponent<Transform2DComponent>();
ownerTransform ??= new Transform2DComponent();
var tr = ownerTransform.AbsoluteTransform();
return tr.position + offset*Complex.Exp(Complex.ImaginaryOne * tr.angle) * tr.scale;
}
public Complex Vector() {
ownerTransform ??= owner.GetComponent<Transform2DComponent>();
ownerTransform ??= new Transform2DComponent();
var tr = ownerTransform.AbsoluteTransform();
return rawValue*Complex.Exp(Complex.ImaginaryOne * tr.angle) * tr.scale;
}
public Tuple<Complex, Complex> OriginAndVector() {
ownerTransform ??= owner.GetComponent<Transform2DComponent>();
ownerTransform ??= new Transform2DComponent();
var tr = ownerTransform.AbsoluteTransform();
return Tuple.Create(tr.position + offset*Complex.Exp(Complex.ImaginaryOne * tr.angle) * tr.scale, rawValue*Complex.Exp(Complex.ImaginaryOne * tr.angle) * tr.scale);
}
public override void Draw(Smoll.Layer.DrawMode drawMode) {
if(drawMode == Layer.DrawMode.Debug) {
var data = OriginAndVector();
Complex start = data.Item1;
Complex end = data.Item1 + data.Item2;
Raylib.DrawLineEx(new Vector2((float)start.Real, (float)start.Imaginary),new Vector2((float)end.Real, (float)end.Imaginary),2f, Color.Red);
}
}
}
}

+ 36
- 0
Expansion2/ExampleShootingInputComponent.cs View File

@ -0,0 +1,36 @@
using Smoll;
using Raylib_cs;
using System.Numerics;
namespace Smoll.Ex2
{
class ExampleShootingInputComponent : Component {
Transform2DComponent? transform;
ArrowComponent? arrow;
public ExampleShootingInputComponent() {
}
public override void OnAttached()
{
base.OnAttached();
transform = owner.GetComponent<Transform2DComponent>();
arrow = owner.GetComponent<ArrowComponent>();
}
public override void Update(float deltaTimeSeconds)
{
transform ??= owner.GetComponent<Transform2DComponent>();
if(transform == null) throw new Exception("Example Input used on immovable object");
arrow ??= owner.GetComponent<ArrowComponent>();
if(arrow == null) throw new Exception("Example Shooter used on arrowless object");
if(Raylib.IsKeyPressed(KeyboardKey.Space)) {
var shoot = new Entity(owner.layers.First());
var details = arrow.OriginAndVector();
shoot.Attach(new Transform2DComponent((float)details.Item1.Real,(float)details.Item1.Imaginary,transform.transform.angle, transform.transform.scale));
shoot.Attach(new TimeToLiveComponent(4f));
shoot.Attach(new SpriteComponent("Beam.png"));
}
}
}
}

+ 35
- 0
Expansion2/RaylibAssetManagerModule.cs View File

@ -0,0 +1,35 @@
using Raylib_cs;
namespace Smoll.Ex2
{
class RaylibAssetManagerModule : IEngineModule {
string path;
Dictionary<string, Image> images;
Dictionary<string, Sound> sounds;
public RaylibAssetManagerModule(string path = "./assets") {
this.path = path;
images = new Dictionary<string, Image>();
sounds = new Dictionary<string, Sound>();
}
public Image GetImage(string name) {
Image image;
if(! images.TryGetValue(name, out image)) {
image = Raylib.LoadImage(path+"/"+name);
images.Add(name, image);
}
return image;
}
public Sound GetSound(string name) {
Sound sound;
if(! sounds.TryGetValue(name, out sound)) {
sound = Raylib.LoadSound(path+"/"+name);
sounds.Add(name, sound);
}
return sound;
}
}
}

+ 37
- 0
Expansion2/SpriteComponent.cs View File

@ -0,0 +1,37 @@
using System.Numerics;
using Raylib_cs;
namespace Smoll.Ex2 {
class SpriteComponent : Smoll.Component , IDisposable{
Complex offset;
string asset_name;
Transform2DComponent? ownerTransform;
Texture2D texture;
public SpriteComponent(string asset_name, int offset_x = 0, int offset_y = 0)
{
this.offset = offset_x + Complex.ImaginaryOne*offset_y;
this.asset_name = asset_name;
}
public override void OnAttached() {
ownerTransform = owner.GetComponent<Transform2DComponent>();
Image image = owner.layers.First().attachedEngine.GetModule<RaylibAssetManagerModule>().GetImage(asset_name);
texture = Raylib.LoadTextureFromImage(image);
}
public override void Draw(Smoll.Layer.DrawMode drawMode) {
if(drawMode == Layer.DrawMode.Normal) {
ownerTransform ??= owner.GetComponent<Transform2DComponent>();
ownerTransform ??= new Transform2DComponent();
var tr = ownerTransform.AbsoluteTransform();
Raylib.DrawTextureEx(texture, new Vector2((float)tr.position.Real, (float)tr.position.Imaginary), tr.angle*180f/MathF.PI, tr.scale, Color.White);
}
}
public void Dispose()
{
Raylib.UnloadTexture(texture);
}
}
}

+ 25
- 0
Expansion2/TimeToLiveComponent.cs View File

@ -0,0 +1,25 @@
using System.Numerics;
using Raylib_cs;
namespace Smoll.Ex2 {
class TimeToLiveComponent : Smoll.Component {
float secondsToLive;
float lived = 0f;
public TimeToLiveComponent(float secondsToLive)
{
this.secondsToLive = secondsToLive;
}
public override void Update(float deltaTimeSeconds)
{
lived += deltaTimeSeconds;
if(lived > secondsToLive) owner.mustDelete = true;
}
public override void Draw(Smoll.Layer.DrawMode drawMode) {
if(drawMode == Layer.DrawMode.Debug) {
}
}
}
}

+ 29
- 11
Program.cs View File

@ -1,24 +1,42 @@
using Raylib_cs;
using Smoll;
using Smoll.Ex1;
using Smoll.Ex2;
Raylib.InitWindow(800, 600, "Smoll");
Layer layer = new Layer();
Layer debugLayer = new Layer(Layer.DrawMode.Debug);
Engine engine = new Engine();
engine.AttachModule(new Smoll.Ex2.RaylibAssetManagerModule());
engine.AttachLayer(layer);
engine.AttachLayer(debugLayer);
var entity = new Entity(layer);
entity.Attach(new Transform2DComponent(128, 128, 0));
entity.Attach(new RectangleGizmoComponent(128, 64, Color.Blue));
entity.Attach(new ExampleInputComponent(100f, 0.25f));
entity.Attach(new CrosshairGizmoComponent());
/* */
var player = new Entity(layer);
debugLayer.Attach(player);
player.Attach(new Transform2DComponent(128, 128, 0, 1));
player.Attach(new CrosshairGizmoComponent());
player.Attach(new ExampleInputComponent(100f, 0.25f));
var entity = new Entity(player);
entity.Attach(new Transform2DComponent(-16, -16, 0, 4));
var ship = new SpriteComponent("Ship.png");
ship.zOrder = 1;
entity.Attach(ship);
var entity2 = new Entity(entity);
entity2.Attach(new Transform2DComponent(128, 128, 0));
entity2.Attach(new RectangleGizmoComponent(64, 64, Color.Red));
entity2.Attach(new CrosshairGizmoComponent());
entity2.Attach(new Transform2DComponent(5, -10, 0));
entity2.Attach(new SpriteComponent("Laser.png"));
var arrow = new ArrowComponent(4, 4);
arrow.rawValue = new System.Numerics.Complex(0, -12);
entity2.Attach(arrow);
entity2.Attach(new ExampleShootingInputComponent());
Engine engine = new Engine();
engine.layers.Add(layer);
/* */
Raylib.InitWindow(800, 600, "Smoll");
while(!Raylib.WindowShouldClose()) {
engine.Update();
Raylib.BeginDrawing();

+ 18
- 1
Smoll/Engine.cs View File

@ -4,10 +4,20 @@ using System.Collections.Generic;
namespace Smoll {
public class Engine {
public Engine() {
modules = new List<IEngineModule>();
layers = new List<Layer>();
}
public List<Layer> layers;
List<Layer> layers;
public List<IEngineModule> modules;
public void AttachLayer(Layer layer) {
layers.Add(layer);
layer.attachedEngine = this;
}
public void AttachModule(IEngineModule module) {
modules.Add(module);
}
public void Update() {
foreach (var layer in layers)
@ -22,5 +32,12 @@ namespace Smoll {
layer.Draw();
}
}
public T? GetModule<T>() where T : class {
// TODO: Fix this *where* clause
var module = modules.Find((IEngineModule a) => a is T);
if(module == null) return null;
return module as T;
}
}
}

+ 9
- 3
Smoll/Entity.cs View File

@ -25,6 +25,7 @@ namespace Smoll {
public string name{get;}
public bool isEnabled = true;
public bool isVisible = true;
public bool mustDelete = false;
public Entity(Entity parent) {
this.parent = parent;
components = new List<Component>();
@ -60,11 +61,12 @@ namespace Smoll {
public virtual void Update(float deltaTimeSeconds)
{
actionables.RemoveAll(x => x.ScheduledForRemoval());
if(!isEnabled) return;
foreach (var elem in actionables)
for (int i = 0; i < actionables.Count; i++)
{
elem.Update(deltaTimeSeconds);
}
actionables[i].Update(deltaTimeSeconds);
}
}
public virtual void Draw(Layer.DrawMode drawMode)
@ -81,5 +83,9 @@ namespace Smoll {
if(component == null) return null;
return component as T;
}
public virtual bool ScheduledForRemoval() {
return mustDelete;
}
}
}

+ 3
- 1
Smoll/IActionable.cs View File

@ -8,7 +8,9 @@ namespace Smoll {
int IComparable<IActionable>.CompareTo(IActionable? other)
{
return other.zOrder - zOrder;
return zOrder - other.zOrder;
}
public virtual bool ScheduledForRemoval() { return false; }
}
}

+ 6
- 0
Smoll/IEngineModule.cs View File

@ -0,0 +1,6 @@
namespace Smoll
{
public interface IEngineModule {
}
}

+ 13
- 4
Smoll/Layer.cs View File

@ -3,11 +3,14 @@ using System.Diagnostics;
namespace Smoll {
public class Layer
{
public Layer() {
public Layer(DrawMode drawMode = DrawMode.Normal) {
this.drawMode = drawMode;
actionables = new List<IActionable>();
watch = new Stopwatch();
}
internal Engine attachedEngine;
internal List<IActionable> actionables;
public enum DrawMode {
@ -20,6 +23,11 @@ namespace Smoll {
Stopwatch watch;
public void Attach(Entity entity) {
entity.layers.Add(this);
actionables.Add(entity);
}
public float Update() {
float deltaTime;
if(! watch.IsRunning) {
@ -30,10 +38,11 @@ namespace Smoll {
watch.Reset();
watch.Start();
}
foreach (var elem in actionables)
actionables.RemoveAll(x => x.ScheduledForRemoval());
for (int i = 0; i < actionables.Count; i++)
{
elem.Update(deltaTime);
}
actionables[i].Update(deltaTime);
}
actionables.Sort();
return deltaTime;
}

+ 2
- 2
Smoll/Transform2D.cs View File

@ -43,9 +43,9 @@ sealed class Transform2DComponent : Component {
var component = up.GetComponent<Transform2DComponent>();
if(component != null) {
Transform2D combined = component.AbsoluteTransform();
var unscaled_pos = (transform.position)*Complex.Exp(Complex.ImaginaryOne * combined.angle);
combined.position = unscaled_pos + combined.position;
combined.scale *= transform.scale;
var scaled_pos = combined.scale*(transform.position)*Complex.Exp(Complex.ImaginaryOne * combined.angle);
combined.position = scaled_pos + combined.position;
combined.angle += transform.angle;
combined.ForceInvariant();
return combined;

Loading…
Cancel
Save