A simple .NET Framework to make 2D games quick and easy.
at main 16 kB view raw
1using Fjord.Scenes; 2using System.Numerics; 3using System.Reflection.Metadata.Ecma335; 4using System.Runtime.InteropServices; 5using static SDL2.SDL; 6using static SDL2.SDL_image; 7 8namespace Fjord.Graphics; 9 10public interface IDrawInstruction { 11 public int depth { get; set; } 12} 13 14public struct Rectangle : IDrawInstruction { 15 public Vector4 rect; 16 public Vector4 color; 17 public float? borderRadius = null; 18 public bool fill; 19 public int depth { get; set; } = 0; 20 21 public Rectangle(Vector4 rect) 22 { 23 this.rect = rect; 24 } 25 26 public Rectangle Rect(Vector4 rect) { 27 this.rect = rect; 28 return this; 29 } 30 31 public Rectangle Color(Vector4 color) { 32 this.color = color; 33 return this; 34 } 35 36 public Rectangle Fill(bool fill) 37 { 38 this.fill = fill; 39 return this; 40 } 41 42 public Rectangle BorderRadius(float radius) 43 { 44 this.borderRadius = radius; 45 return this; 46 } 47 48 public Rectangle Depth(int depth) 49 { 50 this.depth = depth; 51 return this; 52 } 53 54 public void Render() 55 { 56 if (Draw.CurrentSceneID is not null) 57 { 58 SceneHandler.Scenes[Draw.CurrentSceneID].drawBuffer.Add(this); 59 } 60 else 61 { 62 Draw.drawBuffer.Add(this); 63 } 64 } 65 66 public Texture ToTexture() 67 { 68 IntPtr oldRender = SDL_GetRenderTarget(Game.SDLRenderer); 69 70 IntPtr tex = SDL_CreateTexture(Game.SDLRenderer, SDL_PIXELFORMAT_RGBA8888, (int)SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, (int)rect.Z, (int)rect.W); 71 SDL_SetTextureBlendMode(tex, SDL_BlendMode.SDL_BLENDMODE_BLEND); 72 SDL_SetRenderTarget(Game.SDLRenderer, tex); 73 var tempRect = this; 74 tempRect.rect.X = 0; 75 tempRect.rect.Y = 0; 76 Draw.RectangleDirect(tempRect); 77 78 SDL_SetRenderTarget(Game.SDLRenderer, oldRender); 79 80 var itex = new Texture(tex).Position(rect.X, rect.Y); 81 82 return itex; 83 } 84} 85 86public struct Circle : IDrawInstruction { 87 public Vector2 position; 88 public float radius; 89 public Vector4 color; 90 public CirlceAnimation? hoverAnimation; 91 public bool fill; 92 93 public Circle(Vector2 position, float radius) 94 { 95 this.position = position; 96 this.radius = radius; 97 } 98 99 public Circle Position(Vector2 position) { 100 this.position = position; 101 return this; 102 } 103 104 public Circle Radius(float radius) { 105 this.radius = radius; 106 return this; 107 } 108 109 public Circle Color(Vector4 color) { 110 this.color = color; 111 return this; 112 } 113 114 public Circle Fill(bool fill) { 115 this.fill = fill; 116 return this; 117 } 118 119 public Circle Depth(int depth) 120 { 121 this.depth = depth; 122 return this; 123 } 124 125 public Circle HoverAnimation(CirlceAnimation anim) 126 { 127 this.hoverAnimation = anim; 128 return this; 129 } 130 131 public void Render() { 132 if (Draw.CurrentSceneID is not null) 133 { 134 SceneHandler.Scenes[Draw.CurrentSceneID].drawBuffer.Add(this); 135 } 136 else 137 { 138 Draw.drawBuffer.Add(this); 139 } 140 } 141 142 public Texture ToTexture() 143 { 144 IntPtr oldRender = SDL_GetRenderTarget(Game.SDLRenderer); 145 146 IntPtr tex = SDL_CreateTexture(Game.SDLRenderer, SDL_PIXELFORMAT_RGBA8888, (int)SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, (int)(radius * 2 + 1), (int)(radius * 2 + 1)); 147 if(color.W != 255) 148 SDL_SetTextureBlendMode(tex, SDL_BlendMode.SDL_BLENDMODE_BLEND); 149 SDL_SetRenderTarget(Game.SDLRenderer, tex); 150 SDL_SetRenderDrawColor(Game.SDLRenderer, 0, 0, 0, 0); 151 SDL_RenderClear(Game.SDLRenderer); 152 153 var tempRect = this; 154 tempRect.position.X = tempRect.radius; 155 tempRect.position.Y = tempRect.radius; 156 Draw.CircleDirect(tempRect); 157 158 SDL_SetRenderTarget(Game.SDLRenderer, oldRender); 159 160 var itex = new Texture(tex).Position(position.X, position.Y); 161 162 return itex; 163 } 164 165 public int depth { get; set; } 166} 167 168public class Texture : IDrawInstruction { 169 public Vector2 position; 170 public IntPtr SDLTexture; 171 public IntPtr SDLSurface; 172 public Vector2 textureSize; 173 public Vector2 sizeMultiplier = new(1, 1); 174 public bool destroy = false; 175 public float angle; 176 public Flip flip; 177 public float alpha = 255; 178 public Center center; 179 public bool isCustomCenter = false; 180 public Vector2 customCenter = new(); 181 public Vector4? srcTextureOffset = null; 182 183 public Texture(string path) 184 { 185 path = path.OSPath(); 186 if(!Draw.textureCache.ContainsKey(path)) { 187 if(File.Exists(path)) { 188 SDLSurface = IMG_Load(path); 189 SDLTexture = SDL_CreateTextureFromSurface(Game.SDLRenderer, SDLSurface); 190 Draw.textureCache.Add(path, SDLTexture); 191 } else { 192 throw new FileNotFoundException($"No image exists to load at path '{path}'"); 193 } 194 } else { 195 SDLTexture = Draw.textureCache[path]; 196 } 197 SDL_QueryTexture(SDLTexture, out uint format, out int access, out int w, out int h); 198 textureSize = new Vector2(w, h); 199 } 200 201 public Texture(IntPtr texture) 202 { 203 this.SDLTexture = texture; 204 SDL_QueryTexture(SDLTexture, out uint format, out int access, out int w, out int h); 205 textureSize = new Vector2(w, h); 206 } 207 208 public Texture SetTexture(IntPtr texture) { 209 this.SDLTexture = texture; 210 return this; 211 } 212 213 public Texture Position(Vector2 position) { 214 this.position = position; 215 return this; 216 } 217 218 public Texture Position(float x, float y) { 219 this.position = new(x, y); 220 return this; 221 } 222 223 public Texture PositionAndDepth(Vector2 position) { 224 this.position = position; 225 this.depth = -(int)position.Y; 226 return this; 227 } 228 229 public Texture PositionAndDepth(float x, float y) { 230 this.position = new(x, y); 231 this.depth = -(int)y; 232 return this; 233 } 234 235 public Texture Size(Vector2 size) { 236 this.textureSize = size; 237 return this; 238 } 239 240 public Texture Size(float w, float h) { 241 this.textureSize = new(w, h); 242 return this; 243 } 244 public Texture SizeMultiplier(Vector2 size) 245 { 246 this.sizeMultiplier = size; 247 return this; 248 } 249 250 public Texture SizeMultiplier(float w, float h) 251 { 252 this.sizeMultiplier = new(w, h); 253 return this; 254 } 255 256 public Texture Depth(int depth) 257 { 258 this.depth = depth; 259 return this; 260 } 261 262 public Texture Depth(float depth) 263 { 264 this.depth = (int)depth; 265 return this; 266 } 267 268 public Texture Depth(double depth) 269 { 270 this.depth = (int)depth; 271 return this; 272 } 273 274 public Texture Angle(float angle) 275 { 276 this.angle = angle; 277 return this; 278 } 279 280 public Texture Flip(Flip flip) 281 { 282 this.flip = flip; 283 return this; 284 } 285 286 public Texture Center(Center drawCenter) 287 { 288 this.center = drawCenter; 289 this.isCustomCenter = false; 290 return this; 291 } 292 293 public Texture Center(Vector2 drawCenter) 294 { 295 this.customCenter = drawCenter; 296 this.isCustomCenter = true; 297 return this; 298 } 299 300 public Texture Alpha(float alpha) 301 { 302 this.alpha = alpha; 303 return this; 304 } 305 306 public Texture Destroy(bool des) 307 { 308 this.destroy = des; 309 return this; 310 } 311 312 public Texture SrcTextureOffset(Vector4 off) 313 { 314 this.srcTextureOffset = off; 315 return this; 316 } 317 318 public Texture GetRect(out Vector4 outRect) 319 { 320 SDL_Rect rect = new() 321 { 322 x = (int)this.position.X, 323 y = (int)this.position.Y, 324 w = (int)(this.textureSize.X * this.sizeMultiplier.X), 325 h = (int)(this.textureSize.Y * this.sizeMultiplier.Y) 326 }; 327 328 SDL_RendererFlip tmpFlip = this.flip == Graphics.Flip.Horizontal ? SDL_RendererFlip.SDL_FLIP_HORIZONTAL : this.flip == Graphics.Flip.Vertical ? SDL_RendererFlip.SDL_FLIP_VERTICAL : this.flip == Graphics.Flip.Both ? SDL_RendererFlip.SDL_FLIP_HORIZONTAL | SDL_RendererFlip.SDL_FLIP_VERTICAL : SDL_RendererFlip.SDL_FLIP_NONE; 329 330 Vector2 center = new(); 331 Vector2 textureSize = this.textureSize; 332 333 if(!isCustomCenter) 334 { 335 switch (this.center) 336 { 337 case Graphics.Center.TopLeft: 338 { 339 center = new(0, 0); 340 } 341 break; 342 case Graphics.Center.TopMiddle: 343 { 344 center = new(rect.w / 2, 0); 345 } 346 break; 347 case Graphics.Center.TopRight: 348 { 349 center = new(rect.h, 0); 350 } 351 break; 352 353 case Graphics.Center.MiddleLeft: 354 { 355 center = new(0, rect.h / 2); 356 } 357 break; 358 case Graphics.Center.Middle: 359 { 360 center = new(rect.w / 2, rect.h / 2); 361 } 362 break; 363 case Graphics.Center.MiddleRight: 364 { 365 center = new(rect.w, rect.h / 2); 366 } 367 break; 368 369 case Graphics.Center.BottomLeft: 370 { 371 center = new(0, rect.h); 372 } 373 break; 374 case Graphics.Center.BottomMiddle: 375 { 376 center = new(rect.w / 2, rect.h); 377 } 378 break; 379 case Graphics.Center.BottomRight: 380 { 381 center = new(rect.w, rect.h); 382 } 383 break; 384 } 385 } else 386 { 387 center = new(customCenter.X, customCenter.Y); 388 } 389 390 SDL_Point sdlcenter = new() 391 { 392 x = (int)center.X, 393 y = (int)center.Y 394 }; 395 rect.x -= sdlcenter.x; 396 rect.y -= sdlcenter.y; 397 398 outRect = new(rect.x, rect.y, rect.w, rect.h); 399 400 return this; 401 } 402 403 public Texture GetTextureAsSolid(Vector4 color) 404 { 405 // color = new(100, 100, 100, 255); 406 // IntPtr surface = SDL_CreateRGBSurface(0,(int)textureSize.X,(int)textureSize.Y,32,0,0,0,0); 407 // SDL_Rect dstRect = new(); 408 // SDL_BlitSurface(SDLSurface, IntPtr.Zero, surface, ref dstRect); 409 410 // IntPtr newTexture = SDL_CreateTextureFromSurface(Game.SDLRenderer, surface); 411 412 IntPtr newTexture = SDL_CreateTexture(Game.SDLRenderer, SDL_PIXELFORMAT_RGBA8888, (int)SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, (int)textureSize.X, (int)textureSize.Y); 413 414 IntPtr oldRenderer = SDL_GetRenderer(Game.SDLRenderer); 415 SDL_SetRenderTarget(Game.SDLRenderer, newTexture); 416 417 SDL_RenderCopy(Game.SDLRenderer, SDLTexture, IntPtr.Zero, IntPtr.Zero); 418 419 SDL_SetRenderTarget(Game.SDLRenderer, oldRenderer); 420 421 SDL_SetTextureBlendMode(newTexture, SDL_BlendMode.SDL_BLENDMODE_BLEND); 422 423 424 SDL_SetTextureColorMod(newTexture, 0, 0, 0); 425 SDL_SetTextureAlphaMod(newTexture, 255); 426 427 SDL_SetTextureColorMod(newTexture, (byte)color.X, (byte)color.Y, (byte)color.Z); 428 429 return SetTexture(newTexture); 430 } 431 432 public void Render() { 433 if (Draw.CurrentSceneID is not null) 434 { 435 SceneHandler.Scenes[Draw.CurrentSceneID].drawBuffer.Add(this); 436 } 437 else 438 { 439 Draw.drawBuffer.Add(this); 440 } 441 } 442 443 public int depth { get; set; } 444} 445 446public struct Geometry : IDrawInstruction 447{ 448 public List<SDL_Vertex> verticies = new List<SDL_Vertex>(); 449 450 public Geometry() 451 { 452 } 453 454 public Geometry AddVertex(SDL_Vertex v) 455 { 456 verticies.Add(v); 457 return this; 458 } 459 460 public Geometry AddVertex(Vector2 position, Vector4 color, Vector2 tex_coord) 461 { 462 verticies.Add(new SDL_Vertex() 463 { 464 position = new SDL_FPoint() { x = position.X, y = position.Y }, 465 color = new SDL_Color() { r = (byte)color.X, g = (byte)color.Y, b = (byte)color.Z, a = (byte)color.W }, 466 tex_coord = new SDL_FPoint() { x = tex_coord.X, y = tex_coord.Y } 467 }); 468 return this; 469 } 470 public Geometry AddVertex(Vector2 position, Vector4 color) 471 { 472 verticies.Add(new SDL_Vertex() 473 { 474 position = new SDL_FPoint() { x = position.X, y = position.Y }, 475 color = new SDL_Color() { r = (byte)color.X, g = (byte)color.Y, b = (byte)color.Z, a = (byte)color.W }, 476 tex_coord = new SDL_FPoint() { x = 0, y = 0 } 477 }); 478 return this; 479 } 480 481 public Geometry Depth(int depth) 482 { 483 this.depth = depth; 484 return this; 485 } 486 487 public void Render() 488 { 489 if (Draw.CurrentSceneID is not null) 490 { 491 SceneHandler.Scenes[Draw.CurrentSceneID].drawBuffer.Add(this); 492 } 493 else 494 { 495 Draw.drawBuffer.Add(this); 496 } 497 } 498 499 public int depth { get; set; } 500} 501 502public struct Text : IDrawInstruction 503{ 504 public string font; 505 public string value; 506 public Vector2 position; 507 public int size; 508 public Vector4 color; 509 510 public Text(string font, string text) 511 { 512 this.font = font; 513 this.value = text; 514 } 515 516 public Text(string text) 517 { 518 this.value = text; 519 this.font = Graphics.Font.DefaultFont; 520 } 521 522 public Text Font(string font) 523 { 524 this.font = font; 525 return this; 526 } 527 528 public Text Position(Vector2 position) 529 { 530 this.position = position; 531 return this; 532 } 533 534 public Text Position(float x, float y) 535 { 536 this.position = new(x, y); 537 return this; 538 } 539 540 public Text Size(int size) 541 { 542 this.size = size; 543 return this; 544 } 545 546 public Text Color(Vector4 color) 547 { 548 this.color = color; 549 return this; 550 } 551 552 public Text Color(SDL_Color color) 553 { 554 this.color = new(color.r, color.g, color.b, color.a); 555 return this; 556 } 557 558 public Text Depth(int depth) 559 { 560 this.depth = depth; 561 return this; 562 } 563 564 public void Render() 565 { 566 if (Draw.CurrentSceneID is not null) 567 { 568 SceneHandler.Scenes[Draw.CurrentSceneID].drawBuffer.Add(this); 569 } 570 else 571 { 572 Draw.drawBuffer.Add(this); 573 } 574 } 575 576 public Texture ToTexture() 577 { 578 IntPtr oldRender = SDL_GetRenderTarget(Game.SDLRenderer); 579 580 Vector2 size = Graphics.Font.DrawSize(font, value, this.size, color); 581 582 IntPtr tex = SDL_CreateTexture(Game.SDLRenderer, SDL_PIXELFORMAT_RGBA8888, (int)SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, (int)(size.X), (int)(size.Y)); 583 SDL_SetTextureBlendMode(tex, SDL_BlendMode.SDL_BLENDMODE_BLEND); 584 SDL_SetRenderTarget(Game.SDLRenderer, tex); 585 SDL_SetRenderDrawColor(Game.SDLRenderer, 0, 0, 0, 0); 586 SDL_RenderClear(Game.SDLRenderer); 587 var tempRect = this; 588 tempRect.position.X = 0; 589 tempRect.position.Y = 0; 590 Draw.TextDirect(tempRect); 591 592 SDL_SetRenderTarget(Game.SDLRenderer, oldRender); 593 594 var itex = new Texture(tex).Position(position.X, position.Y); 595 596 return itex; 597 } 598 599 public int depth { get; set; } 600} 601 602public struct Line : IDrawInstruction 603{ 604 public Vector2 point1 = new(); 605 public Vector2 point2 = new(); 606 public Vector4 color = new(); 607 608 public Line(Vector2 point1, Vector2 point2) 609 { 610 this.point1 = point1; 611 this.point2 = point2; 612 } 613 614 public Line Color(Vector4 color) 615 { 616 this.color = color; 617 return this; 618 } 619 620 public Line Color(SDL_Color color) 621 { 622 this.color = new(color.r, color.g, color.b, color.a); 623 return this; 624 } 625 626 public Line Depth(int depth) 627 { 628 this.depth = depth; 629 return this; 630 } 631 632 public void Render() 633 { 634 if (Draw.CurrentSceneID is not null) 635 { 636 SceneHandler.Scenes[Draw.CurrentSceneID].drawBuffer.Add(this); 637 } 638 else 639 { 640 Draw.drawBuffer.Add(this); 641 } 642 } 643 644 public int depth { get; set; } 645}