WASM examples (+ backports of new official examples) (#344)
* chg: New build system that uses the officially distributed binaries, bumped version to 8.0.0, simplified git workflow, removed deprecated OpenGL 1.1 functionality. * chg: Modernize CI workflow, enable SourceLink - Bump workflow actions to latest majors (Node 24); drop deprecated softprops/action-gh-release@v1 - Trigger push builds on main instead of master - Create local nuget feed dir before pack (fixes NU1301) - Enable Microsoft.SourceLink.GitHub for debugging symbols (ref PR #340) * fix: centralized version data in Directory.build.props, and fixed various interop details that had incorrect function signatures * chore: updated readme * fix: version the native extract marker and chain download via DependsOnTargets The .extracted marker now includes the raylib package name, so bumping TargetRaylibTag re-extracts the new archive instead of silently keeping (and packing/copying) the previous version's files. _PrepareNativeLibrary and _StageWasmNative now depend directly on _DownloadAndExtractInternal instead of CallTarget-ing it; dependency targets run in the same project instance, so the resolved properties (RaylibPackageName etc.) propagate naturally. * fix: let the binding build for browser-wasm on both net8.0 and net10.0 The net8-era wasm workload (Microsoft.NET.Runtime.WebAssembly.Sdk 8.0.x, auto-imported for RID browser-wasm) treats every browser-wasm project as a wasm app: it forces OutputType=Exe after project evaluation (CS5001 for a classlib) and hooks its app-bundle build after Build, which errors because a library has no assemblies to bundle. Opt Raylib-cs out via DisableAutoWasmBuildApp (props time, before the workload defaults its trigger) and pin OutputType back to Library in Directory.Build.targets (evaluated after the workload props, so the assignment wins). net10's wasm SDK needs neither workaround. * chore: readme updated * chg: simplifying build logic - a simple line in the documentation should save us the code here * fix: Wrong signature of FrameBufferComplete * chore: readme update * feat: samples default to local project reference, and can optionally use the nuget package * feat: backporting existing raylib-cs examples and new official raylib examples to WASM, adopting raylib's original code style * chore: readme, gitignore, and targets backport. * fix: Examples.csproj runs the download task when building locally * feat: backporting existing raylib-cs examples and new official raylib examples to WASM, adopting raylib's original code style * chore: readme, gitignore, and targets backport. * chore: clean up linter warnings * feat: html harness focuses the example and allows quick navigation with J/K instead. * chore: readme mentions the property to use nuget vs. the local project reference * feat: replaced the J/K navigation with good old HTML buttons * chore: run dotnet format scoped default (was previously scoped to just 'style')
This commit is contained in:
parent
b207e633ae
commit
8c22e68c2a
236 changed files with 40405 additions and 10896 deletions
419
Examples/Core/AutomationEvents.cs
Normal file
419
Examples/Core/AutomationEvents.cs
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - automation events
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* Example based on 2d_camera_platformer example by arvyy (@arvyy)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2023-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class AutomationEvents : IExample
|
||||
{
|
||||
private const int GRAVITY = 400;
|
||||
private const float PLAYER_JUMP_SPD = 350.0f;
|
||||
private const float PLAYER_HOR_SPD = 200.0f;
|
||||
|
||||
private const int MAX_ENVIRONMENT_ELEMENTS = 5;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Automation Events";
|
||||
|
||||
public string Title => "raylib [core] example - automation events";
|
||||
|
||||
private struct Player
|
||||
{
|
||||
public Vector2 Position;
|
||||
public float Speed;
|
||||
public bool CanJump;
|
||||
}
|
||||
|
||||
private struct EnvElement
|
||||
{
|
||||
public Rectangle Rect;
|
||||
public int Blocking;
|
||||
public Color Color;
|
||||
}
|
||||
|
||||
private Player player;
|
||||
private EnvElement[] envElements;
|
||||
private Camera2D camera;
|
||||
|
||||
private AutomationEventList aelist;
|
||||
private bool eventRecording;
|
||||
private bool eventPlaying;
|
||||
|
||||
private uint frameCounter;
|
||||
private uint playFrameCounter;
|
||||
private uint currentPlayFrame;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Define player
|
||||
player = new Player();
|
||||
player.Position = new Vector2(400, 280);
|
||||
player.Speed = 0;
|
||||
player.CanJump = false;
|
||||
|
||||
// Define environment elements (platforms)
|
||||
envElements = new EnvElement[MAX_ENVIRONMENT_ELEMENTS]
|
||||
{
|
||||
new EnvElement { Rect = new Rectangle(0, 0, 1000, 400), Blocking = 0, Color = Color.LightGray },
|
||||
new EnvElement { Rect = new Rectangle(0, 400, 1000, 200), Blocking = 1, Color = Color.Gray },
|
||||
new EnvElement { Rect = new Rectangle(300, 200, 400, 10), Blocking = 1, Color = Color.Gray },
|
||||
new EnvElement { Rect = new Rectangle(250, 300, 100, 10), Blocking = 1, Color = Color.Gray },
|
||||
new EnvElement { Rect = new Rectangle(650, 300, 100, 10), Blocking = 1, Color = Color.Gray }
|
||||
};
|
||||
|
||||
// Define camera
|
||||
camera = new Camera2D();
|
||||
camera.Target = player.Position;
|
||||
camera.Offset = new Vector2(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
camera.Rotation = 0.0f;
|
||||
camera.Zoom = 1.0f;
|
||||
|
||||
// Automation events
|
||||
aelist = LoadAutomationEventList((sbyte*)null); // Initialize list of automation events to record new events
|
||||
SetAutomationEventList(ref aelist);
|
||||
eventRecording = false;
|
||||
eventPlaying = false;
|
||||
|
||||
frameCounter = 0;
|
||||
playFrameCounter = 0;
|
||||
currentPlayFrame = 0;
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float deltaTime = 0.015f;//GetFrameTime();
|
||||
|
||||
// Dropped files logic
|
||||
//----------------------------------------------------------------------------------
|
||||
#if BROWSER
|
||||
// NOTE: drag-and-drop event-list loading (.txt/.rae) is not supported in the browser host.
|
||||
#else
|
||||
if (IsFileDropped())
|
||||
{
|
||||
FilePathList droppedFiles = LoadDroppedFiles();
|
||||
|
||||
// Supports loading .rgs style files (text or binary) and .png style palette images
|
||||
if (IsFileExtension(droppedFiles[0], ".txt;.rae"))
|
||||
{
|
||||
UnloadAutomationEventList(aelist);
|
||||
aelist = LoadAutomationEventList(droppedFiles[0]);
|
||||
|
||||
eventRecording = false;
|
||||
|
||||
// Reset scene state to play
|
||||
eventPlaying = true;
|
||||
playFrameCounter = 0;
|
||||
currentPlayFrame = 0;
|
||||
|
||||
player.Position = new Vector2(400, 280);
|
||||
player.Speed = 0;
|
||||
player.CanJump = false;
|
||||
|
||||
camera.Target = player.Position;
|
||||
camera.Offset = new Vector2(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
camera.Rotation = 0.0f;
|
||||
camera.Zoom = 1.0f;
|
||||
}
|
||||
|
||||
UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory
|
||||
}
|
||||
#endif
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Update player
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
player.Position.X -= PLAYER_HOR_SPD * deltaTime;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
player.Position.X += PLAYER_HOR_SPD * deltaTime;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Space) && player.CanJump)
|
||||
{
|
||||
player.Speed = -PLAYER_JUMP_SPD;
|
||||
player.CanJump = false;
|
||||
}
|
||||
|
||||
int hitObstacle = 0;
|
||||
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
|
||||
{
|
||||
EnvElement element = envElements[i];
|
||||
if (element.Blocking != 0 &&
|
||||
element.Rect.X <= player.Position.X &&
|
||||
element.Rect.X + element.Rect.Width >= player.Position.X &&
|
||||
element.Rect.Y >= player.Position.Y &&
|
||||
element.Rect.Y <= player.Position.Y + player.Speed * deltaTime)
|
||||
{
|
||||
hitObstacle = 1;
|
||||
player.Speed = 0.0f;
|
||||
player.Position.Y = element.Rect.Y;
|
||||
}
|
||||
}
|
||||
|
||||
if (hitObstacle == 0)
|
||||
{
|
||||
player.Position.Y += player.Speed * deltaTime;
|
||||
player.Speed += GRAVITY * deltaTime;
|
||||
player.CanJump = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.CanJump = true;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
// Reset game state
|
||||
player.Position = new Vector2(400, 280);
|
||||
player.Speed = 0;
|
||||
player.CanJump = false;
|
||||
|
||||
camera.Target = player.Position;
|
||||
camera.Offset = new Vector2(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
camera.Rotation = 0.0f;
|
||||
camera.Zoom = 1.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Events playing
|
||||
// NOTE: Logic must be before Camera update because it depends on mouse-wheel value,
|
||||
// that can be set by the played event... but some other inputs could be affected
|
||||
//----------------------------------------------------------------------------------
|
||||
if (eventPlaying)
|
||||
{
|
||||
// NOTE: Multiple events could be executed in a single frame
|
||||
while (playFrameCounter == aelist.Events[currentPlayFrame].Frame)
|
||||
{
|
||||
PlayAutomationEvent(aelist.Events[currentPlayFrame]);
|
||||
currentPlayFrame++;
|
||||
|
||||
if (currentPlayFrame == aelist.Count)
|
||||
{
|
||||
eventPlaying = false;
|
||||
currentPlayFrame = 0;
|
||||
playFrameCounter = 0;
|
||||
|
||||
TraceLog(TraceLogLevel.Info, "FINISH PLAYING!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
playFrameCounter++;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
camera.Target = player.Position;
|
||||
camera.Offset = new Vector2(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
|
||||
|
||||
// WARNING: On event replay, mouse-wheel internal value is set
|
||||
camera.Zoom += ((float)GetMouseWheelMove() * 0.05f);
|
||||
if (camera.Zoom > 3.0f)
|
||||
{
|
||||
camera.Zoom = 3.0f;
|
||||
}
|
||||
else if (camera.Zoom < 0.25f)
|
||||
{
|
||||
camera.Zoom = 0.25f;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
|
||||
{
|
||||
EnvElement element = envElements[i];
|
||||
minX = MathF.Min(element.Rect.X, minX);
|
||||
maxX = MathF.Max(element.Rect.X + element.Rect.Width, maxX);
|
||||
minY = MathF.Min(element.Rect.Y, minY);
|
||||
maxY = MathF.Max(element.Rect.Y + element.Rect.Height, maxY);
|
||||
}
|
||||
|
||||
Vector2 max = GetWorldToScreen2D(new Vector2(maxX, maxY), camera);
|
||||
Vector2 min = GetWorldToScreen2D(new Vector2(minX, minY), camera);
|
||||
|
||||
if (max.X < screenWidth)
|
||||
{
|
||||
camera.Offset.X = screenWidth - (max.X - (float)screenWidth / 2);
|
||||
}
|
||||
|
||||
if (max.Y < screenHeight)
|
||||
{
|
||||
camera.Offset.Y = screenHeight - (max.Y - (float)screenHeight / 2);
|
||||
}
|
||||
|
||||
if (min.X > 0)
|
||||
{
|
||||
camera.Offset.X = (float)screenWidth / 2 - min.X;
|
||||
}
|
||||
|
||||
if (min.Y > 0)
|
||||
{
|
||||
camera.Offset.Y = (float)screenHeight / 2 - min.Y;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Events management
|
||||
if (IsKeyPressed(KeyboardKey.S)) // Toggle events recording
|
||||
{
|
||||
if (!eventPlaying)
|
||||
{
|
||||
if (eventRecording)
|
||||
{
|
||||
StopAutomationEventRecording();
|
||||
eventRecording = false;
|
||||
|
||||
ExportAutomationEventList(aelist, "automation.rae");
|
||||
|
||||
TraceLog(TraceLogLevel.Info, $"RECORDED FRAMES: {aelist.Count}");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAutomationEventBaseFrame(180);
|
||||
StartAutomationEventRecording();
|
||||
eventRecording = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.A)) // Toggle events playing (WARNING: Starts next frame)
|
||||
{
|
||||
if (!eventRecording && (aelist.Count > 0))
|
||||
{
|
||||
// Reset scene state to play
|
||||
eventPlaying = true;
|
||||
playFrameCounter = 0;
|
||||
currentPlayFrame = 0;
|
||||
|
||||
player.Position = new Vector2(400, 280);
|
||||
player.Speed = 0;
|
||||
player.CanJump = false;
|
||||
|
||||
camera.Target = player.Position;
|
||||
camera.Offset = new Vector2(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
camera.Rotation = 0.0f;
|
||||
camera.Zoom = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventRecording || eventPlaying)
|
||||
{
|
||||
frameCounter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
frameCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.LightGray);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
// Draw environment elements
|
||||
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
|
||||
{
|
||||
DrawRectangleRec(envElements[i].Rect, envElements[i].Color);
|
||||
}
|
||||
|
||||
// Draw player rectangle
|
||||
DrawRectangleRec(new Rectangle(player.Position.X - 20, player.Position.Y - 40, 40, 40), Color.Red);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
// Draw game controls
|
||||
DrawRectangle(10, 10, 290, 145, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(10, 10, 290, 145, Fade(Color.Blue, 0.8f));
|
||||
|
||||
DrawText("Controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- RIGHT | LEFT: Player movement", 30, 40, 10, Color.DarkGray);
|
||||
DrawText("- SPACE: Player jump", 30, 60, 10, Color.DarkGray);
|
||||
DrawText("- R: Reset game state", 30, 80, 10, Color.DarkGray);
|
||||
|
||||
DrawText("- S: START/STOP RECORDING INPUT EVENTS", 30, 110, 10, Color.Black);
|
||||
DrawText("- A: REPLAY LAST RECORDED INPUT EVENTS", 30, 130, 10, Color.Black);
|
||||
|
||||
// Draw automation events recording indicator
|
||||
if (eventRecording)
|
||||
{
|
||||
DrawRectangle(10, 160, 290, 30, Fade(Color.Red, 0.3f));
|
||||
DrawRectangleLines(10, 160, 290, 30, Fade(Color.Maroon, 0.8f));
|
||||
DrawCircle(30, 175, 10, Color.Maroon);
|
||||
|
||||
if (((frameCounter / 15) % 2) == 1)
|
||||
{
|
||||
DrawText($"RECORDING EVENTS... [{aelist.Count}]", 50, 170, 10, Color.Maroon);
|
||||
}
|
||||
}
|
||||
else if (eventPlaying)
|
||||
{
|
||||
DrawRectangle(10, 160, 290, 30, Fade(Color.Lime, 0.3f));
|
||||
DrawRectangleLines(10, 160, 290, 30, Fade(Color.DarkGreen, 0.8f));
|
||||
DrawTriangle(new Vector2(20, 155 + 10), new Vector2(20, 155 + 30), new Vector2(40, 155 + 20), Color.DarkGreen);
|
||||
|
||||
if (((frameCounter / 15) % 2) == 1)
|
||||
{
|
||||
DrawText($"PLAYING RECORDED EVENTS... [{currentPlayFrame}]", 50, 170, 10, Color.DarkGreen);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadAutomationEventList(aelist);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - automation events");
|
||||
|
||||
var game = new AutomationEvents();
|
||||
game.Init();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,23 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Basic window
|
||||
* raylib [core] example - basic screen manager
|
||||
*
|
||||
* Welcome to raylib!
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* To test examples, just press F6 and execute raylib_compile_execute script
|
||||
* Note that compiled executable is placed in the same folder as .c file
|
||||
* NOTE: This example illustrates a very simple screen manager based on a states machines
|
||||
*
|
||||
* You can find all basic examples on C:\raylib\raylib\examples folder or
|
||||
* raylib official webpage: www.raylib.com
|
||||
* Example originally created with raylib 4.0, last time updated with raylib 4.0
|
||||
*
|
||||
* Enjoy using raylib. :)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* This example has been created using raylib 1.0 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
*
|
||||
* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2021-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
enum GameScreen
|
||||
internal enum GameScreen
|
||||
{
|
||||
Logo = 0,
|
||||
Title,
|
||||
|
|
@ -31,143 +25,160 @@ enum GameScreen
|
|||
Ending
|
||||
}
|
||||
|
||||
public class BasicScreenManager
|
||||
public partial class BasicScreenManager : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Basic Screen Manager";
|
||||
|
||||
public string Title => "raylib [core] example - basic screen manager";
|
||||
|
||||
private GameScreen currentScreen;
|
||||
private int framesCounter;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
currentScreen = GameScreen.Logo;
|
||||
|
||||
// TODO: Initialize all required variables and load all required data here!
|
||||
|
||||
framesCounter = 0; // Useful to count frames
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (currentScreen)
|
||||
{
|
||||
case GameScreen.Logo:
|
||||
{
|
||||
// TODO: Update LOGO screen variables here!
|
||||
|
||||
framesCounter++; // Count frames
|
||||
|
||||
// Wait for 2 seconds (120 frames) before jumping to TITLE screen
|
||||
if (framesCounter > 120)
|
||||
{
|
||||
currentScreen = GameScreen.Title;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GameScreen.Title:
|
||||
{
|
||||
// TODO: Update TITLE screen variables here!
|
||||
|
||||
// Press enter to change to GAMEPLAY screen
|
||||
if (IsKeyPressed(KeyboardKey.Enter) || IsGestureDetected(Gesture.Tap))
|
||||
{
|
||||
currentScreen = GameScreen.Gameplay;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GameScreen.Gameplay:
|
||||
{
|
||||
// TODO: Update GAMEPLAY screen variables here!
|
||||
|
||||
// Press enter to change to ENDING screen
|
||||
if (IsKeyPressed(KeyboardKey.Enter) || IsGestureDetected(Gesture.Tap))
|
||||
{
|
||||
currentScreen = GameScreen.Ending;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GameScreen.Ending:
|
||||
{
|
||||
// TODO: Update ENDING screen variables here!
|
||||
|
||||
// Press enter to return to TITLE screen
|
||||
if (IsKeyPressed(KeyboardKey.Enter) || IsGestureDetected(Gesture.Tap))
|
||||
{
|
||||
currentScreen = GameScreen.Title;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
switch (currentScreen)
|
||||
{
|
||||
case GameScreen.Logo:
|
||||
{
|
||||
// TODO: Draw LOGO screen here!
|
||||
DrawText("LOGO SCREEN", 20, 20, 40, Color.LightGray);
|
||||
DrawText("WAIT for 2 SECONDS...", 290, 220, 20, Color.Gray);
|
||||
}
|
||||
break;
|
||||
case GameScreen.Title:
|
||||
{
|
||||
// TODO: Draw TITLE screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.Green);
|
||||
DrawText("TITLE SCREEN", 20, 20, 40, Color.DarkGreen);
|
||||
DrawText("PRESS ENTER or TAP to JUMP to GAMEPLAY SCREEN", 120, 220, 20, Color.DarkGreen);
|
||||
}
|
||||
break;
|
||||
case GameScreen.Gameplay:
|
||||
{
|
||||
// TODO: Draw GAMEPLAY screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.Purple);
|
||||
DrawText("GAMEPLAY SCREEN", 20, 20, 40, Color.Maroon);
|
||||
DrawText("PRESS ENTER or TAP to JUMP to ENDING SCREEN", 130, 220, 20, Color.Maroon);
|
||||
|
||||
}
|
||||
break;
|
||||
case GameScreen.Ending:
|
||||
{
|
||||
// TODO: Draw ENDING screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.Blue);
|
||||
DrawText("ENDING SCREEN", 20, 20, 40, Color.DarkBlue);
|
||||
DrawText("PRESS ENTER or TAP to RETURN to TITLE SCREEN", 120, 220, 20, Color.DarkBlue);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// TODO: Unload all loaded data (textures, fonts, audio) here!
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic screen manager");
|
||||
|
||||
GameScreen currentScreen = GameScreen.Logo;
|
||||
|
||||
// TODO: Initialize all required variables and load all required data here!
|
||||
|
||||
// Useful to count frames
|
||||
int framesCounter = 0;
|
||||
|
||||
SetTargetFPS(60); // Set desired framerate (frames-per-second)
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new BasicScreenManager();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (currentScreen)
|
||||
{
|
||||
case GameScreen.Logo:
|
||||
{
|
||||
// TODO: Update LOGO screen variables here!
|
||||
|
||||
// Count frames
|
||||
framesCounter++;
|
||||
|
||||
// Wait for 2 seconds (120 frames) before jumping to TITLE screen
|
||||
if (framesCounter > 120)
|
||||
{
|
||||
currentScreen = GameScreen.Title;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GameScreen.Title:
|
||||
{
|
||||
// TODO: Update TITLE screen variables here!
|
||||
|
||||
// Press enter to change to GAMEPLAY screen
|
||||
if (IsKeyPressed(KeyboardKey.Enter) || IsGestureDetected(Gesture.Tap))
|
||||
{
|
||||
currentScreen = GameScreen.Gameplay;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GameScreen.Gameplay:
|
||||
{
|
||||
// TODO: Update GAMEPLAY screen variables here!
|
||||
|
||||
// Press enter to change to ENDING screen
|
||||
if (IsKeyPressed(KeyboardKey.Enter) || IsGestureDetected(Gesture.Tap))
|
||||
{
|
||||
currentScreen = GameScreen.Ending;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GameScreen.Ending:
|
||||
{
|
||||
// TODO: Update ENDING screen variables here!
|
||||
|
||||
// Press enter to return to TITLE screen
|
||||
if (IsKeyPressed(KeyboardKey.Enter) || IsGestureDetected(Gesture.Tap))
|
||||
{
|
||||
currentScreen = GameScreen.Title;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
switch (currentScreen)
|
||||
{
|
||||
case GameScreen.Logo:
|
||||
{
|
||||
// TODO: Draw LOGO screen here!
|
||||
DrawText("LOGO SCREEN", 20, 20, 40, Color.LightGray);
|
||||
DrawText("WAIT for 2 SECONDS...", 290, 220, 20, Color.Gray);
|
||||
|
||||
}
|
||||
break;
|
||||
case GameScreen.Title:
|
||||
{
|
||||
// TODO: Draw TITLE screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.Green);
|
||||
DrawText("TITLE SCREEN", 20, 20, 40, Color.DarkGreen);
|
||||
DrawText("PRESS ENTER or TAP to JUMP to GAMEPLAY SCREEN", 120, 220, 20, Color.DarkGreen);
|
||||
|
||||
}
|
||||
break;
|
||||
case GameScreen.Gameplay:
|
||||
{
|
||||
// TODO: Draw GAMEPLAY screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.Purple);
|
||||
DrawText("GAMEPLAY SCREEN", 20, 20, 40, Color.Maroon);
|
||||
DrawText("PRESS ENTER or TAP to JUMP to ENDING SCREEN", 130, 220, 20, Color.Maroon);
|
||||
|
||||
}
|
||||
break;
|
||||
case GameScreen.Ending:
|
||||
{
|
||||
// TODO: Draw ENDING screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Color.Blue);
|
||||
DrawText("ENDING SCREEN", 20, 20, 40, Color.DarkBlue);
|
||||
DrawText("PRESS ENTER or TAP to RETURN to TITLE SCREEN", 120, 220, 20, Color.DarkBlue);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// TODO: Unload all loaded data (textures, fonts, audio) here!
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -26,50 +26,58 @@
|
|||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using System;
|
||||
using System.Text;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class BasicWindow
|
||||
public partial class BasicWindow : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Basic Window";
|
||||
|
||||
public string Title => "raylib [core] example - basic window";
|
||||
|
||||
public void Init()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Congrats! You created your first window!", 190, 200, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
||||
var game = new BasicWindow();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Congrats! You created your first window!", 190, 200, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,31 +13,33 @@
|
|||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class Camera2dDemo
|
||||
public partial class Camera2dDemo : IExample
|
||||
{
|
||||
public const int MaxBuildings = 100;
|
||||
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Camera 2D Demo";
|
||||
|
||||
public string Title => "raylib [core] example - 2d camera";
|
||||
|
||||
private Rectangle player;
|
||||
private Rectangle[] buildings;
|
||||
private Color[] buildColors;
|
||||
private Camera2D camera;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
player = new(400, 280, 40, 40);
|
||||
buildings = new Rectangle[MaxBuildings];
|
||||
buildColors = new Color[MaxBuildings];
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
|
||||
var spacing = 0;
|
||||
|
||||
Rectangle player = new(400, 280, 40, 40);
|
||||
Rectangle[] buildings = new Rectangle[MaxBuildings];
|
||||
Color[] buildColors = new Color[MaxBuildings];
|
||||
|
||||
int spacing = 0;
|
||||
|
||||
for (int i = 0; i < MaxBuildings; i++)
|
||||
for (var i = 0; i < MaxBuildings; i++)
|
||||
{
|
||||
buildings[i].Width = GetRandomValue(50, 200);
|
||||
buildings[i].Height = GetRandomValue(100, 800);
|
||||
|
|
@ -54,124 +56,139 @@ public class Camera2dDemo
|
|||
);
|
||||
}
|
||||
|
||||
Camera2D camera = new();
|
||||
camera = new();
|
||||
camera.Target = new Vector2(player.X + 20, player.Y + 20);
|
||||
camera.Offset = new Vector2(screenWidth / 2, screenHeight / 2);
|
||||
camera.Offset = new Vector2(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
camera.Rotation = 0.0f;
|
||||
camera.Zoom = 1.0f;
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Player movement
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
player.X += 2;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
player.X -= 2;
|
||||
}
|
||||
|
||||
// Camera target follows player
|
||||
camera.Target = new Vector2(player.X + 20, player.Y + 20);
|
||||
|
||||
// Camera rotation controls
|
||||
if (IsKeyDown(KeyboardKey.A))
|
||||
{
|
||||
camera.Rotation--;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.S))
|
||||
{
|
||||
camera.Rotation++;
|
||||
}
|
||||
|
||||
// Limit camera rotation to 80 degrees (-40 to 40)
|
||||
if (camera.Rotation > 40)
|
||||
{
|
||||
camera.Rotation = 40;
|
||||
}
|
||||
else if (camera.Rotation < -40)
|
||||
{
|
||||
camera.Rotation = -40;
|
||||
}
|
||||
|
||||
// Camera zoom controls
|
||||
// Uses log scaling to provide consistent zoom speed
|
||||
camera.Zoom = MathF.Exp(MathF.Log(camera.Zoom) + ((float)GetMouseWheelMove() * 0.1f));
|
||||
|
||||
if (camera.Zoom > 3.0f)
|
||||
{
|
||||
camera.Zoom = 3.0f;
|
||||
}
|
||||
else if (camera.Zoom < 0.1f)
|
||||
{
|
||||
camera.Zoom = 0.1f;
|
||||
}
|
||||
|
||||
// Camera reset (zoom and rotation)
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
camera.Zoom = 1.0f;
|
||||
camera.Rotation = 0.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
DrawRectangle(-6000, 320, 13000, 8000, Color.DarkGray);
|
||||
|
||||
for (var i = 0; i < MaxBuildings; i++)
|
||||
{
|
||||
DrawRectangleRec(buildings[i], buildColors[i]);
|
||||
}
|
||||
|
||||
DrawRectangleRec(player, Color.Red);
|
||||
|
||||
DrawLine((int)camera.Target.X, -screenHeight * 10, (int)camera.Target.X, screenHeight * 10, Color.Green);
|
||||
DrawLine(-screenWidth * 10, (int)camera.Target.Y, screenWidth * 10, (int)camera.Target.Y, Color.Green);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawText("SCREEN AREA", 640, 10, 20, Color.Red);
|
||||
|
||||
DrawRectangle(0, 0, screenWidth, 5, Color.Red);
|
||||
DrawRectangle(0, 5, 5, screenHeight - 10, Color.Red);
|
||||
DrawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, Color.Red);
|
||||
DrawRectangle(0, screenHeight - 5, screenWidth, 5, Color.Red);
|
||||
|
||||
DrawRectangle(10, 10, 250, 113, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(10, 10, 250, 113, Color.Blue);
|
||||
|
||||
DrawText("Free 2D camera controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- Right/Left to move player", 40, 40, 10, Color.DarkGray);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, Color.DarkGray);
|
||||
DrawText("- A / S to Rotate", 40, 80, 10, Color.DarkGray);
|
||||
DrawText("- R to reset Zoom and Rotation", 40, 100, 10, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Camera2dDemo();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Player movement
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
player.X += 2;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
player.X -= 2;
|
||||
}
|
||||
|
||||
// Camera3D target follows player
|
||||
camera.Target = new Vector2(player.X + 20, player.Y + 20);
|
||||
|
||||
// Camera3D rotation controls
|
||||
if (IsKeyDown(KeyboardKey.A))
|
||||
{
|
||||
camera.Rotation--;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.S))
|
||||
{
|
||||
camera.Rotation++;
|
||||
}
|
||||
|
||||
// Limit camera rotation to 80 degrees (-40 to 40)
|
||||
if (camera.Rotation > 40)
|
||||
{
|
||||
camera.Rotation = 40;
|
||||
}
|
||||
else if (camera.Rotation < -40)
|
||||
{
|
||||
camera.Rotation = -40;
|
||||
}
|
||||
|
||||
// Camera3D zoom controls
|
||||
camera.Zoom += ((float)GetMouseWheelMove() * 0.05f);
|
||||
|
||||
if (camera.Zoom > 3.0f)
|
||||
{
|
||||
camera.Zoom = 3.0f;
|
||||
}
|
||||
else if (camera.Zoom < 0.1f)
|
||||
{
|
||||
camera.Zoom = 0.1f;
|
||||
}
|
||||
|
||||
// Camera3D reset (zoom and rotation)
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
camera.Zoom = 1.0f;
|
||||
camera.Rotation = 0.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
DrawRectangle(-6000, 320, 13000, 8000, Color.DarkGray);
|
||||
|
||||
for (int i = 0; i < MaxBuildings; i++)
|
||||
{
|
||||
DrawRectangleRec(buildings[i], buildColors[i]);
|
||||
}
|
||||
|
||||
DrawRectangleRec(player, Color.Red);
|
||||
|
||||
DrawRectangle((int)camera.Target.X, -500, 1, (int)(screenHeight * 4), Color.Green);
|
||||
DrawLine(
|
||||
(int)(-screenWidth * 10),
|
||||
(int)camera.Target.Y,
|
||||
(int)(screenWidth * 10),
|
||||
(int)camera.Target.Y,
|
||||
Color.Green
|
||||
);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawText("SCREEN AREA", 640, 10, 20, Color.Red);
|
||||
|
||||
DrawRectangle(0, 0, (int)screenWidth, 5, Color.Red);
|
||||
DrawRectangle(0, 5, 5, (int)screenHeight - 10, Color.Red);
|
||||
DrawRectangle((int)screenWidth - 5, 5, 5, (int)screenHeight - 10, Color.Red);
|
||||
DrawRectangle(0, (int)screenHeight - 5, (int)screenWidth, 5, Color.Red);
|
||||
|
||||
DrawRectangle(10, 10, 250, 113, ColorAlpha(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(10, 10, 250, 113, Color.Blue);
|
||||
|
||||
DrawText("Free 2d camera controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- Right/Left to move Offset", 40, 40, 10, Color.DarkGray);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, Color.DarkGray);
|
||||
DrawText("- A / S to Rotate", 40, 80, 10, Color.DarkGray);
|
||||
DrawText("- R to reset Zoom and Rotation", 40, 100, 10, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
181
Examples/Core/Camera2dMouseZoom.cs
Normal file
181
Examples/Core/Camera2dMouseZoom.cs
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 2d camera mouse zoom
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
* Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2022-2025 Jeffery Myers (@JeffM2501)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raymath;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class Camera2dMouseZoom : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Camera 2D Mouse Zoom";
|
||||
|
||||
public string Title => "raylib [core] example - 2d camera mouse zoom";
|
||||
|
||||
private Camera2D camera;
|
||||
private int zoomMode; // 0-Mouse Wheel, 1-Mouse Move
|
||||
|
||||
public void Init()
|
||||
{
|
||||
camera = new Camera2D();
|
||||
camera.Zoom = 1.0f;
|
||||
|
||||
zoomMode = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
zoomMode = 0;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
zoomMode = 1;
|
||||
}
|
||||
|
||||
// Translate based on mouse right click
|
||||
if (IsMouseButtonDown(MouseButton.Left))
|
||||
{
|
||||
Vector2 delta = GetMouseDelta();
|
||||
delta = Vector2Scale(delta, -1.0f / camera.Zoom);
|
||||
camera.Target = Vector2Add(camera.Target, delta);
|
||||
}
|
||||
|
||||
if (zoomMode == 0)
|
||||
{
|
||||
// Zoom based on mouse wheel
|
||||
float wheel = GetMouseWheelMove();
|
||||
if (wheel != 0)
|
||||
{
|
||||
// Get the world point that is under the mouse
|
||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||
|
||||
// Set the offset to where the mouse is
|
||||
camera.Offset = GetMousePosition();
|
||||
|
||||
// Set the target to match, so that the camera maps the world space point
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
camera.Target = mouseWorldPos;
|
||||
|
||||
// Zoom increment
|
||||
// Uses log scaling to provide consistent zoom speed
|
||||
float scale = 0.2f * wheel;
|
||||
camera.Zoom = Clamp(MathF.Exp(MathF.Log(camera.Zoom) + scale), 0.125f, 64.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Zoom based on mouse right click
|
||||
if (IsMouseButtonPressed(MouseButton.Right))
|
||||
{
|
||||
// Get the world point that is under the mouse
|
||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||
|
||||
// Set the offset to where the mouse is
|
||||
camera.Offset = GetMousePosition();
|
||||
|
||||
// Set the target to match, so that the camera maps the world space point
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
camera.Target = mouseWorldPos;
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(MouseButton.Right))
|
||||
{
|
||||
// Zoom increment
|
||||
// Uses log scaling to provide consistent zoom speed
|
||||
float deltaX = GetMouseDelta().X;
|
||||
float scale = 0.005f * deltaX;
|
||||
camera.Zoom = Clamp(MathF.Exp(MathF.Log(camera.Zoom) + scale), 0.125f, 64.0f);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(camera);
|
||||
// Draw the 3d grid, rotated 90 degrees and centered around 0,0
|
||||
// just so we have something in the XY plane
|
||||
Rlgl.PushMatrix();
|
||||
Rlgl.Translatef(0, 25 * 50, 0);
|
||||
Rlgl.Rotatef(90, 1, 0, 0);
|
||||
DrawGrid(100, 50);
|
||||
Rlgl.PopMatrix();
|
||||
|
||||
// Draw a reference circle
|
||||
DrawCircle(GetScreenWidth() / 2, GetScreenHeight() / 2, 50, Color.Maroon);
|
||||
EndMode2D();
|
||||
|
||||
// Draw mouse reference
|
||||
//Vector2 mousePos = GetWorldToScreen2D(GetMousePosition(), camera)
|
||||
DrawCircleV(GetMousePosition(), 4, Color.DarkGray);
|
||||
DrawTextEx(GetFontDefault(), $"[{GetMouseX()}, {GetMouseY()}]",
|
||||
Vector2Add(GetMousePosition(), new Vector2(-44, -24)), 20, 2, Color.Black);
|
||||
|
||||
DrawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, Color.DarkGray);
|
||||
if (zoomMode == 0)
|
||||
{
|
||||
DrawText("Mouse left button drag to move, mouse wheel to zoom", 20, 50, 20, Color.DarkGray);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("Mouse left button drag to move, mouse press and move to zoom", 20, 50, 20, Color.DarkGray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera mouse zoom");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Camera2dMouseZoom();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,36 +2,44 @@
|
|||
*
|
||||
* raylib [core] example - 2d camera platformer
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.0
|
||||
*
|
||||
* Example contributed by arvyy (@arvyy) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 arvyy (@arvyy)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2019-2025 arvyy (@arvyy)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Raymath;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class Camera2dPlatformer
|
||||
public partial class Camera2dPlatformer : IExample
|
||||
{
|
||||
const int G = 400;
|
||||
const float PlayerJumpSpeed = 350.0f;
|
||||
const float PlayerHorSpeed = 200.0f;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
struct Player
|
||||
private const int G = 400;
|
||||
private const float PlayerJumpSpeed = 350.0f;
|
||||
private const float PlayerHorSpeed = 200.0f;
|
||||
|
||||
public string Name => "Core / 2D Camera Platformer";
|
||||
|
||||
public string Title => "raylib [core] example - 2d camera platformer";
|
||||
|
||||
private struct Player
|
||||
{
|
||||
public Vector2 Position;
|
||||
public float Speed;
|
||||
public bool CanJump;
|
||||
}
|
||||
|
||||
struct EnvItem
|
||||
private struct EnvItem
|
||||
{
|
||||
public Rectangle Rect;
|
||||
public int Blocking;
|
||||
|
|
@ -45,7 +53,7 @@ public class Camera2dPlatformer
|
|||
}
|
||||
}
|
||||
|
||||
delegate void CameraUpdaterCallback(
|
||||
private delegate void CameraUpdaterCallback(
|
||||
ref Camera2D camera,
|
||||
ref Player player,
|
||||
EnvItem[] envItems,
|
||||
|
|
@ -54,21 +62,22 @@ public class Camera2dPlatformer
|
|||
int height
|
||||
);
|
||||
|
||||
public static int Main()
|
||||
private Player player;
|
||||
private EnvItem[] envItems;
|
||||
private Camera2D camera;
|
||||
private CameraUpdaterCallback[] cameraUpdaters;
|
||||
private int cameraOption;
|
||||
private int cameraUpdatersLength;
|
||||
private string[] cameraDescriptions;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
|
||||
|
||||
Player player = new();
|
||||
player = new();
|
||||
player.Position = new Vector2(400, 280);
|
||||
player.Speed = 0;
|
||||
player.CanJump = false;
|
||||
|
||||
EnvItem[] envItems = new EnvItem[]
|
||||
envItems = new EnvItem[]
|
||||
{
|
||||
new EnvItem(new Rectangle(0, 0, 1000, 400), 0, Color.LightGray),
|
||||
new EnvItem(new Rectangle(0, 400, 1000, 200), 1, Color.Gray),
|
||||
|
|
@ -77,14 +86,14 @@ public class Camera2dPlatformer
|
|||
new EnvItem(new Rectangle(650, 300, 100, 10), 1, Color.Gray)
|
||||
};
|
||||
|
||||
Camera2D camera = new();
|
||||
camera = new();
|
||||
camera.Target = player.Position;
|
||||
camera.Offset = new Vector2(screenWidth / 2, screenHeight / 2);
|
||||
camera.Offset = new Vector2(screenWidth / 2.0f, screenHeight / 2.0f);
|
||||
camera.Rotation = 0.0f;
|
||||
camera.Zoom = 1.0f;
|
||||
|
||||
// Store callbacks to the multiple update camera functions
|
||||
CameraUpdaterCallback[] cameraUpdaters = new CameraUpdaterCallback[]
|
||||
// Store pointers to the multiple update camera functions
|
||||
cameraUpdaters = new CameraUpdaterCallback[]
|
||||
{
|
||||
UpdateCameraCenter,
|
||||
UpdateCameraCenterInsideMap,
|
||||
|
|
@ -93,93 +102,89 @@ public class Camera2dPlatformer
|
|||
UpdateCameraPlayerBoundsPush
|
||||
};
|
||||
|
||||
int cameraOption = 0;
|
||||
int cameraUpdatersLength = cameraUpdaters.Length;
|
||||
cameraOption = 0;
|
||||
cameraUpdatersLength = cameraUpdaters.Length;
|
||||
|
||||
string[] cameraDescriptions = new string[]{
|
||||
cameraDescriptions = new string[]{
|
||||
"Follow player center",
|
||||
"Follow player center, but clamp to map edges",
|
||||
"Follow player center; smoothed",
|
||||
"Follow player center horizontally; update player center vertically after landing",
|
||||
"Player push camera on getting too close to screen edge"
|
||||
};
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float deltaTime = GetFrameTime();
|
||||
|
||||
UpdatePlayer(ref player, envItems, deltaTime);
|
||||
|
||||
camera.Zoom += ((float)GetMouseWheelMove() * 0.05f);
|
||||
|
||||
if (camera.Zoom > 3.0f)
|
||||
{
|
||||
camera.Zoom = 3.0f;
|
||||
}
|
||||
else if (camera.Zoom < 0.25f)
|
||||
{
|
||||
camera.Zoom = 0.25f;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
camera.Zoom = 1.0f;
|
||||
player.Position = new Vector2(400, 280);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.C))
|
||||
{
|
||||
cameraOption = (cameraOption + 1) % cameraUpdatersLength;
|
||||
}
|
||||
|
||||
// Call update camera function by its pointer
|
||||
cameraUpdaters[cameraOption](ref camera, ref player, envItems, deltaTime, screenWidth, screenHeight);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.LightGray);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
for (int i = 0; i < envItems.Length; i++)
|
||||
{
|
||||
DrawRectangleRec(envItems[i].Rect, envItems[i].Color);
|
||||
}
|
||||
|
||||
Rectangle playerRect = new(player.Position.X - 20, player.Position.Y - 40, 40, 40);
|
||||
DrawRectangleRec(playerRect, Color.Red);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawText("Controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- Right/Left to move", 40, 40, 10, Color.DarkGray);
|
||||
DrawText("- Space to jump", 40, 60, 10, Color.DarkGray);
|
||||
DrawText("- Mouse Wheel to Zoom in-out, R to reset zoom", 40, 80, 10, Color.DarkGray);
|
||||
DrawText("- C to change camera mode", 40, 100, 10, Color.DarkGray);
|
||||
DrawText("Current camera mode:", 20, 120, 10, Color.Black);
|
||||
DrawText(cameraDescriptions[cameraOption], 40, 140, 10, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void UpdatePlayer(ref Player player, EnvItem[] envItems, float delta)
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
var deltaTime = GetFrameTime();
|
||||
|
||||
UpdatePlayer(ref player, envItems, deltaTime);
|
||||
|
||||
camera.Zoom += ((float)GetMouseWheelMove() * 0.05f);
|
||||
|
||||
if (camera.Zoom > 3.0f)
|
||||
{
|
||||
camera.Zoom = 3.0f;
|
||||
}
|
||||
else if (camera.Zoom < 0.25f)
|
||||
{
|
||||
camera.Zoom = 0.25f;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
camera.Zoom = 1.0f;
|
||||
player.Position = new Vector2(400, 280);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.C))
|
||||
{
|
||||
cameraOption = (cameraOption + 1) % cameraUpdatersLength;
|
||||
}
|
||||
|
||||
// Call update camera function by its pointer
|
||||
cameraUpdaters[cameraOption](ref camera, ref player, envItems, deltaTime, screenWidth, screenHeight);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.LightGray);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
for (var i = 0; i < envItems.Length; i++)
|
||||
{
|
||||
DrawRectangleRec(envItems[i].Rect, envItems[i].Color);
|
||||
}
|
||||
|
||||
Rectangle playerRect = new(player.Position.X - 20, player.Position.Y - 40, 40.0f, 40.0f);
|
||||
DrawRectangleRec(playerRect, Color.Red);
|
||||
|
||||
DrawCircleV(player.Position, 5.0f, Color.Gold);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawText("Controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- Right/Left to move", 40, 40, 10, Color.DarkGray);
|
||||
DrawText("- Space to jump", 40, 60, 10, Color.DarkGray);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 80, 10, Color.DarkGray);
|
||||
DrawText("- R to reset position + zoom", 40, 100, 10, Color.DarkGray);
|
||||
DrawText("- C to change camera mode", 40, 120, 10, Color.DarkGray);
|
||||
DrawText("Current camera mode:", 20, 140, 10, Color.Black);
|
||||
DrawText(cameraDescriptions[cameraOption], 40, 160, 10, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
private static void UpdatePlayer(ref Player player, EnvItem[] envItems, float delta)
|
||||
{
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
|
|
@ -197,11 +202,11 @@ public class Camera2dPlatformer
|
|||
player.CanJump = false;
|
||||
}
|
||||
|
||||
int hitObstacle = 0;
|
||||
for (int i = 0; i < envItems.Length; i++)
|
||||
var hitObstacle = 0;
|
||||
for (var i = 0; i < envItems.Length; i++)
|
||||
{
|
||||
EnvItem ei = envItems[i];
|
||||
Vector2 p = player.Position;
|
||||
var ei = envItems[i];
|
||||
var p = player.Position;
|
||||
if (ei.Blocking != 0 &&
|
||||
ei.Rect.X <= p.X &&
|
||||
ei.Rect.X + ei.Rect.Width >= p.X &&
|
||||
|
|
@ -211,6 +216,7 @@ public class Camera2dPlatformer
|
|||
hitObstacle = 1;
|
||||
player.Speed = 0.0f;
|
||||
player.Position.Y = ei.Rect.Y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +232,7 @@ public class Camera2dPlatformer
|
|||
}
|
||||
}
|
||||
|
||||
static void UpdateCameraCenter(
|
||||
private static void UpdateCameraCenter(
|
||||
ref Camera2D camera,
|
||||
ref Player player,
|
||||
EnvItem[] envItems,
|
||||
|
|
@ -235,11 +241,11 @@ public class Camera2dPlatformer
|
|||
int height
|
||||
)
|
||||
{
|
||||
camera.Offset = new Vector2(width / 2, height / 2);
|
||||
camera.Offset = new Vector2(width / 2.0f, height / 2.0f);
|
||||
camera.Target = player.Position;
|
||||
}
|
||||
|
||||
static void UpdateCameraCenterInsideMap(
|
||||
private static void UpdateCameraCenterInsideMap(
|
||||
ref Camera2D camera,
|
||||
ref Player player,
|
||||
EnvItem[] envItems,
|
||||
|
|
@ -248,43 +254,43 @@ public class Camera2dPlatformer
|
|||
int height)
|
||||
{
|
||||
camera.Target = player.Position;
|
||||
camera.Offset = new Vector2(width / 2, height / 2);
|
||||
camera.Offset = new Vector2(width / 2.0f, height / 2.0f);
|
||||
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
|
||||
|
||||
for (int i = 0; i < envItems.Length; i++)
|
||||
for (var i = 0; i < envItems.Length; i++)
|
||||
{
|
||||
EnvItem ei = envItems[i];
|
||||
var ei = envItems[i];
|
||||
minX = Math.Min(ei.Rect.X, minX);
|
||||
maxX = Math.Max(ei.Rect.X + ei.Rect.Width, maxX);
|
||||
minY = Math.Min(ei.Rect.Y, minY);
|
||||
maxY = Math.Max(ei.Rect.Y + ei.Rect.Height, maxY);
|
||||
}
|
||||
|
||||
Vector2 max = GetWorldToScreen2D(new Vector2(maxX, maxY), camera);
|
||||
Vector2 min = GetWorldToScreen2D(new Vector2(minX, minY), camera);
|
||||
var max = GetWorldToScreen2D(new Vector2(maxX, maxY), camera);
|
||||
var min = GetWorldToScreen2D(new Vector2(minX, minY), camera);
|
||||
|
||||
if (max.X < width)
|
||||
{
|
||||
camera.Offset.X = width - (max.X - width / 2);
|
||||
camera.Offset.X = width - (max.X - width / 2.0f);
|
||||
}
|
||||
|
||||
if (max.Y < height)
|
||||
{
|
||||
camera.Offset.Y = height - (max.Y - height / 2);
|
||||
camera.Offset.Y = height - (max.Y - height / 2.0f);
|
||||
}
|
||||
|
||||
if (min.X > 0)
|
||||
{
|
||||
camera.Offset.X = width / 2 - min.X;
|
||||
camera.Offset.X = width / 2.0f - min.X;
|
||||
}
|
||||
|
||||
if (min.Y > 0)
|
||||
{
|
||||
camera.Offset.Y = height / 2 - min.Y;
|
||||
camera.Offset.Y = height / 2.0f - min.Y;
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateCameraCenterSmoothFollow(
|
||||
private static void UpdateCameraCenterSmoothFollow(
|
||||
ref Camera2D camera,
|
||||
ref Player player,
|
||||
EnvItem[] envItems,
|
||||
|
|
@ -297,18 +303,18 @@ public class Camera2dPlatformer
|
|||
const float minEffectLength = 10;
|
||||
const float fractionSpeed = 0.8f;
|
||||
|
||||
camera.Offset = new Vector2(width / 2, height / 2);
|
||||
Vector2 diff = Vector2Subtract(player.Position, camera.Target);
|
||||
float length = Vector2Length(diff);
|
||||
camera.Offset = new Vector2(width / 2.0f, height / 2.0f);
|
||||
var diff = Vector2Subtract(player.Position, camera.Target);
|
||||
var length = Vector2Length(diff);
|
||||
|
||||
if (length > minEffectLength)
|
||||
{
|
||||
float speed = Math.Max(fractionSpeed * length, minSpeed);
|
||||
var speed = Math.Max(fractionSpeed * length, minSpeed);
|
||||
camera.Target = Vector2Add(camera.Target, Vector2Scale(diff, speed * delta / length));
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateCameraEvenOutOnLanding(
|
||||
private static void UpdateCameraEvenOutOnLanding(
|
||||
ref Camera2D camera,
|
||||
ref Player player,
|
||||
EnvItem[] envItems,
|
||||
|
|
@ -318,10 +324,10 @@ public class Camera2dPlatformer
|
|||
)
|
||||
{
|
||||
float evenOutSpeed = 700;
|
||||
int eveningOut = 0;
|
||||
float evenOutTarget = 0.0f;
|
||||
var eveningOut = 0;
|
||||
var evenOutTarget = 0.0f;
|
||||
|
||||
camera.Offset = new Vector2(width / 2, height / 2);
|
||||
camera.Offset = new Vector2(width / 2.0f, height / 2.0f);
|
||||
camera.Target.X = player.Position.X;
|
||||
|
||||
if (eveningOut != 0)
|
||||
|
|
@ -357,7 +363,7 @@ public class Camera2dPlatformer
|
|||
}
|
||||
}
|
||||
|
||||
static void UpdateCameraPlayerBoundsPush(
|
||||
private static void UpdateCameraPlayerBoundsPush(
|
||||
ref Camera2D camera,
|
||||
ref Player player,
|
||||
EnvItem[] envItems,
|
||||
|
|
@ -368,11 +374,11 @@ public class Camera2dPlatformer
|
|||
{
|
||||
Vector2 bbox = new(0.2f, 0.2f);
|
||||
|
||||
Vector2 bboxWorldMin = GetScreenToWorld2D(
|
||||
var bboxWorldMin = GetScreenToWorld2D(
|
||||
new Vector2((1 - bbox.X) * 0.5f * width, (1 - bbox.Y) * 0.5f * height),
|
||||
camera
|
||||
);
|
||||
Vector2 bboxWorldMax = GetScreenToWorld2D(
|
||||
var bboxWorldMax = GetScreenToWorld2D(
|
||||
new Vector2((1 + bbox.X) * 0.5f * width,
|
||||
(1 + bbox.Y) * 0.5f * height),
|
||||
camera
|
||||
|
|
@ -399,4 +405,32 @@ public class Camera2dPlatformer
|
|||
camera.Target.Y = bboxWorldMin.Y + (player.Position.Y - bboxWorldMax.Y);
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera platformer");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Camera2dPlatformer();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,183 +2,215 @@
|
|||
*
|
||||
* raylib [core] example - 3d camera first person
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 1.3
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class Camera3dFirstPerson
|
||||
public partial class Camera3dFirstPerson : IExample
|
||||
{
|
||||
public const int MaxColumns = 20;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Camera 3D First Person";
|
||||
|
||||
public string Title => "raylib [core] example - 3d camera first person";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private Camera3D camera;
|
||||
private CameraMode cameraMode;
|
||||
private float[] heights;
|
||||
private Vector3[] positions;
|
||||
private Color[] colors;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world (position, target, up vector)
|
||||
camera = new();
|
||||
camera.Position = new Vector3(0.0f, 2.0f, 4.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 2.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 60.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
cameraMode = CameraMode.FirstPerson;
|
||||
|
||||
// Generates some random columns
|
||||
heights = new float[MaxColumns];
|
||||
positions = new Vector3[MaxColumns];
|
||||
colors = new Color[MaxColumns];
|
||||
|
||||
for (var i = 0; i < MaxColumns; i++)
|
||||
{
|
||||
heights[i] = (float)GetRandomValue(1, 12);
|
||||
positions[i] = new Vector3(GetRandomValue(-15, 15), heights[i] / 2.0f, GetRandomValue(-15, 15));
|
||||
colors[i] = new Color(GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Switch camera mode
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
cameraMode = CameraMode.Free;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
cameraMode = CameraMode.FirstPerson;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
cameraMode = CameraMode.ThirdPerson;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Four))
|
||||
{
|
||||
cameraMode = CameraMode.Orbital;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
// Switch camera projection
|
||||
if (IsKeyPressed(KeyboardKey.P))
|
||||
{
|
||||
if (camera.Projection == CameraProjection.Perspective)
|
||||
{
|
||||
// Create isometric view
|
||||
cameraMode = CameraMode.ThirdPerson;
|
||||
// Note: The target distance is related to the render distance in the orthographic projection
|
||||
camera.Position = new Vector3(0.0f, 2.0f, -100.0f);
|
||||
camera.Target = new Vector3(0.0f, 2.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.Projection = CameraProjection.Orthographic;
|
||||
camera.FovY = 20.0f; // near plane width in CAMERA_ORTHOGRAPHIC
|
||||
// CameraYaw(&camera, -135 * DEG2RAD, true);
|
||||
// CameraPitch(&camera, -45 * DEG2RAD, true, true, false);
|
||||
}
|
||||
else if (camera.Projection == CameraProjection.Orthographic)
|
||||
{
|
||||
// Reset to default view
|
||||
cameraMode = CameraMode.ThirdPerson;
|
||||
camera.Position = new Vector3(0.0f, 2.0f, 10.0f);
|
||||
camera.Target = new Vector3(0.0f, 2.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera.FovY = 60.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera computes movement internally depending on the camera mode
|
||||
// Some default standard keyboard/mouse inputs are hardcoded to simplify use
|
||||
// For advanced camera controls, it's recommended to compute camera movement manually
|
||||
UpdateCamera(ref camera, cameraMode); // Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Draw ground
|
||||
DrawPlane(new Vector3(0.0f, 0.0f, 0.0f), new Vector2(32.0f, 32.0f), Color.LightGray);
|
||||
|
||||
// Draw a blue wall
|
||||
DrawCube(new Vector3(-16.0f, 2.5f, 0.0f), 1.0f, 5.0f, 32.0f, Color.Blue);
|
||||
|
||||
// Draw a green wall
|
||||
DrawCube(new Vector3(16.0f, 2.5f, 0.0f), 1.0f, 5.0f, 32.0f, Color.Lime);
|
||||
|
||||
// Draw a yellow wall
|
||||
DrawCube(new Vector3(0.0f, 2.5f, 16.0f), 32.0f, 5.0f, 1.0f, Color.Gold);
|
||||
|
||||
// Draw some cubes around
|
||||
for (var i = 0; i < MaxColumns; i++)
|
||||
{
|
||||
DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]);
|
||||
DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, Color.Maroon);
|
||||
}
|
||||
|
||||
// Draw player cube
|
||||
if (cameraMode == CameraMode.ThirdPerson)
|
||||
{
|
||||
DrawCube(camera.Target, 0.5f, 0.5f, 0.5f, Color.Purple);
|
||||
DrawCubeWires(camera.Target, 0.5f, 0.5f, 0.5f, Color.DarkPurple);
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// Draw info boxes
|
||||
DrawRectangle(5, 5, 330, 100, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(5, 5, 330, 100, Color.Blue);
|
||||
|
||||
DrawText("Camera controls:", 15, 15, 10, Color.Black);
|
||||
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, Color.Black);
|
||||
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, Color.Black);
|
||||
DrawText("- Camera mode keys: 1, 2, 3, 4", 15, 60, 10, Color.Black);
|
||||
DrawText("- Zoom keys: num-plus, num-minus or mouse scroll", 15, 75, 10, Color.Black);
|
||||
DrawText("- Camera projection key: P", 15, 90, 10, Color.Black);
|
||||
|
||||
DrawRectangle(600, 5, 195, 100, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(600, 5, 195, 100, Color.Blue);
|
||||
|
||||
DrawText("Camera status:", 610, 15, 10, Color.Black);
|
||||
DrawText($"- Mode: {cameraMode}", 610, 30, 10, Color.Black);
|
||||
DrawText($"- Projection: {camera.Projection}", 610, 45, 10, Color.Black);
|
||||
DrawText($"- Position: {camera.Position}", 610, 60, 10, Color.Black);
|
||||
DrawText($"- Target: {camera.Target}", 610, 75, 10, Color.Black);
|
||||
DrawText($"- Up: {camera.Up}", 610, 90, 10, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person");
|
||||
|
||||
// Define the camera to look into our 3d world (position, target, up vector)
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(4.0f, 2.0f, 4.0f);
|
||||
camera.Target = new Vector3(0.0f, 1.8f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 60.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
// Generates some random columns
|
||||
float[] heights = new float[MaxColumns];
|
||||
Vector3[] positions = new Vector3[MaxColumns];
|
||||
Color[] colors = new Color[MaxColumns];
|
||||
|
||||
for (int i = 0; i < MaxColumns; i++)
|
||||
{
|
||||
heights[i] = (float)GetRandomValue(1, 12);
|
||||
positions[i] = new Vector3(GetRandomValue(-15, 15), heights[i] / 2, GetRandomValue(-15, 15));
|
||||
colors[i] = new Color(GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255);
|
||||
}
|
||||
|
||||
CameraMode cameraMode = CameraMode.FirstPerson;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Camera3dFirstPerson();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Switch camera mode
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
cameraMode = CameraMode.Free;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
cameraMode = CameraMode.FirstPerson;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
cameraMode = CameraMode.ThirdPerson;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Four))
|
||||
{
|
||||
cameraMode = CameraMode.Orbital;
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
// Switch camera projection
|
||||
if (IsKeyPressed(KeyboardKey.P))
|
||||
{
|
||||
if (camera.Projection == CameraProjection.Perspective)
|
||||
{
|
||||
// Create isometric view
|
||||
cameraMode = CameraMode.ThirdPerson;
|
||||
// Note: The target distance is related to the render distance in the orthographic projection
|
||||
camera.Position = new Vector3(0.0f, 2.0f, -100.0f);
|
||||
camera.Target = new Vector3(0.0f, 2.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.Projection = CameraProjection.Orthographic;
|
||||
camera.FovY = 20.0f; // near plane width in CAMERA_ORTHOGRAPHIC
|
||||
// CameraYaw(&camera, -135 * DEG2RAD, true);
|
||||
// CameraPitch(&camera, -45 * DEG2RAD, true, true, false);
|
||||
}
|
||||
else if (camera.Projection == CameraProjection.Orthographic)
|
||||
{
|
||||
// Reset to default view
|
||||
cameraMode = CameraMode.ThirdPerson;
|
||||
camera.Position = new Vector3(0.0f, 2.0f, 10.0f);
|
||||
camera.Target = new Vector3(0.0f, 2.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera.FovY = 60.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera computes movement internally depending on the camera mode
|
||||
// Some default standard keyboard/mouse inputs are hardcoded to simplify use
|
||||
// For advance camera controls, it's reecommended to compute camera movement manually
|
||||
UpdateCamera(ref camera, cameraMode);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Draw ground
|
||||
DrawPlane(new Vector3(0.0f, 0.0f, 0.0f), new Vector2(32.0f, 32.0f), Color.LightGray);
|
||||
|
||||
// Draw a blue wall
|
||||
DrawCube(new Vector3(-16.0f, 2.5f, 0.0f), 1.0f, 5.0f, 32.0f, Color.Blue);
|
||||
|
||||
// Draw a green wall
|
||||
DrawCube(new Vector3(16.0f, 2.5f, 0.0f), 1.0f, 5.0f, 32.0f, Color.Lime);
|
||||
|
||||
// Draw a yellow wall
|
||||
DrawCube(new Vector3(0.0f, 2.5f, 16.0f), 32.0f, 5.0f, 1.0f, Color.Gold);
|
||||
|
||||
// Draw some cubes around
|
||||
for (int i = 0; i < MaxColumns; i++)
|
||||
{
|
||||
DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]);
|
||||
DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, Color.Maroon);
|
||||
}
|
||||
|
||||
// Draw player cube
|
||||
if (cameraMode == CameraMode.ThirdPerson)
|
||||
{
|
||||
DrawCube(camera.Target, 0.5f, 0.5f, 0.5f, Color.Purple);
|
||||
DrawCubeWires(camera.Target, 0.5f, 0.5f, 0.5f, Color.DarkPurple);
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// Draw info boxes
|
||||
DrawRectangle(5, 5, 330, 100, ColorAlpha(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(10, 10, 330, 100, Color.Blue);
|
||||
|
||||
DrawText("Camera controls:", 15, 15, 10, Color.Black);
|
||||
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, Color.Black);
|
||||
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, Color.Black);
|
||||
DrawText("- Camera mode keys: 1, 2, 3, 4", 15, 60, 10, Color.Black);
|
||||
DrawText("- Zoom keys: num-plus, num-minus or mouse scroll", 15, 75, 10, Color.Black);
|
||||
DrawText("- Camera projection key: P", 15, 90, 10, Color.Black);
|
||||
|
||||
DrawRectangle(600, 5, 195, 100, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(600, 5, 195, 100, Color.Blue);
|
||||
|
||||
DrawText("Camera status:", 610, 15, 10, Color.Black);
|
||||
DrawText($"- Mode: {cameraMode}", 610, 30, 10, Color.Black);
|
||||
DrawText($"- Projection: {camera.Projection}", 610, 45, 10, Color.Black);
|
||||
DrawText($"- Position: {camera.Position}", 610, 60, 10, Color.Black);
|
||||
DrawText($"- Target: {camera.Target}", 610, 75, 10, Color.Black);
|
||||
DrawText($"- Up: {camera.Up}", 610, 90, 10, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
360
Examples/Core/Camera3dFps.cs
Normal file
360
Examples/Core/Camera3dFps.cs
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 3d camera fps
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Agnis Aldiņš (@nezvers) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Agnis Aldiņš (@nezvers)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raymath;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class Camera3dFps : IExample
|
||||
{
|
||||
// Movement constants
|
||||
private const float GRAVITY = 32.0f;
|
||||
private const float MAX_SPEED = 20.0f;
|
||||
private const float CROUCH_SPEED = 5.0f;
|
||||
private const float JUMP_FORCE = 12.0f;
|
||||
private const float MAX_ACCEL = 150.0f;
|
||||
// Grounded drag
|
||||
private const float FRICTION = 0.86f;
|
||||
// Increasing air drag, increases strafing speed
|
||||
private const float AIR_DRAG = 0.98f;
|
||||
// Responsiveness for turning movement direction to looked direction
|
||||
private const float CONTROL = 15.0f;
|
||||
private const float CROUCH_HEIGHT = 0.0f;
|
||||
private const float STAND_HEIGHT = 1.0f;
|
||||
private const float BOTTOM_HEIGHT = 0.5f;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / 3D Camera FPS";
|
||||
|
||||
public string Title => "raylib [core] example - 3d camera fps";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
// Body structure
|
||||
private struct Body
|
||||
{
|
||||
public Vector3 Position;
|
||||
public Vector3 Velocity;
|
||||
public Vector3 Dir;
|
||||
public bool IsGrounded;
|
||||
}
|
||||
|
||||
// State that was global in the C example
|
||||
private readonly Vector2 sensitivity = new Vector2(0.001f, 0.001f);
|
||||
|
||||
private Body player;
|
||||
private Vector2 lookRotation;
|
||||
private float headTimer;
|
||||
private float walkLerp;
|
||||
private float headLerp;
|
||||
private Vector2 lean;
|
||||
|
||||
private Camera3D camera;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
player = new Body();
|
||||
lookRotation = new Vector2(0, 0);
|
||||
headTimer = 0.0f;
|
||||
walkLerp = 0.0f;
|
||||
headLerp = STAND_HEIGHT;
|
||||
lean = new Vector2(0, 0);
|
||||
|
||||
// Initialize camera variables
|
||||
// NOTE: UpdateCameraFPS() takes care of the rest
|
||||
camera = new Camera3D();
|
||||
camera.FovY = 60.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera.Position = new Vector3(
|
||||
player.Position.X,
|
||||
player.Position.Y + (BOTTOM_HEIGHT + headLerp),
|
||||
player.Position.Z);
|
||||
|
||||
UpdateCameraFPS(ref camera); // Update camera parameters
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mouseDelta = GetMouseDelta();
|
||||
lookRotation.X -= mouseDelta.X * sensitivity.X;
|
||||
lookRotation.Y += mouseDelta.Y * sensitivity.Y;
|
||||
|
||||
int sideway = (IsKeyDown(KeyboardKey.D) ? 1 : 0) - (IsKeyDown(KeyboardKey.A) ? 1 : 0);
|
||||
int forward = (IsKeyDown(KeyboardKey.W) ? 1 : 0) - (IsKeyDown(KeyboardKey.S) ? 1 : 0);
|
||||
bool crouching = IsKeyDown(KeyboardKey.LeftControl);
|
||||
UpdateBody(ref player, lookRotation.X, sideway, forward, IsKeyPressed(KeyboardKey.Space), crouching);
|
||||
|
||||
float delta = GetFrameTime();
|
||||
headLerp = Lerp(headLerp, (crouching ? CROUCH_HEIGHT : STAND_HEIGHT), 20.0f * delta);
|
||||
camera.Position = new Vector3(
|
||||
player.Position.X,
|
||||
player.Position.Y + (BOTTOM_HEIGHT + headLerp),
|
||||
player.Position.Z);
|
||||
|
||||
if (player.IsGrounded && ((forward != 0) || (sideway != 0)))
|
||||
{
|
||||
headTimer += delta * 3.0f;
|
||||
walkLerp = Lerp(walkLerp, 1.0f, 10.0f * delta);
|
||||
camera.FovY = Lerp(camera.FovY, 55.0f, 5.0f * delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
walkLerp = Lerp(walkLerp, 0.0f, 10.0f * delta);
|
||||
camera.FovY = Lerp(camera.FovY, 60.0f, 5.0f * delta);
|
||||
}
|
||||
|
||||
lean.X = Lerp(lean.X, sideway * 0.02f, 10.0f * delta);
|
||||
lean.Y = Lerp(lean.Y, forward * 0.015f, 10.0f * delta);
|
||||
|
||||
UpdateCameraFPS(ref camera);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawLevel();
|
||||
EndMode3D();
|
||||
|
||||
// Draw info box
|
||||
DrawRectangle(5, 5, 330, 75, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(5, 5, 330, 75, Color.Blue);
|
||||
|
||||
DrawText("Camera controls:", 15, 15, 10, Color.Black);
|
||||
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, Color.Black);
|
||||
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, Color.Black);
|
||||
float velLen = Vector2Length(new Vector2(player.Velocity.X, player.Velocity.Z));
|
||||
DrawText($"- Velocity Len: ({velLen:00.000})", 15, 60, 10, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
// Update body considering current world state
|
||||
private void UpdateBody(ref Body body, float rot, int side, int forward, bool jumpPressed, bool crouchHold)
|
||||
{
|
||||
Vector2 input = new Vector2((float)side, (float)-forward);
|
||||
|
||||
// Upstream guards this with `#if defined(NORMALIZE_INPUT)`, which is always true given the
|
||||
// `#define NORMALIZE_INPUT 0` above it (defined() tests definedness, not the value), so the
|
||||
// diagonal-movement normalization is active.
|
||||
// Slow down diagonal movement
|
||||
if ((side != 0) && (forward != 0))
|
||||
{
|
||||
input = Vector2Normalize(input);
|
||||
}
|
||||
|
||||
float delta = GetFrameTime();
|
||||
|
||||
if (!body.IsGrounded)
|
||||
{
|
||||
body.Velocity.Y -= GRAVITY * delta;
|
||||
}
|
||||
|
||||
if (body.IsGrounded && jumpPressed)
|
||||
{
|
||||
body.Velocity.Y = JUMP_FORCE;
|
||||
body.IsGrounded = false;
|
||||
|
||||
// Sound can be played at this moment
|
||||
//SetSoundPitch(fxJump, 1.0f + (GetRandomValue(-100, 100)*0.001));
|
||||
//PlaySound(fxJump);
|
||||
}
|
||||
|
||||
Vector3 front = new Vector3(MathF.Sin(rot), 0.0f, MathF.Cos(rot));
|
||||
Vector3 right = new Vector3(MathF.Cos(-rot), 0.0f, MathF.Sin(-rot));
|
||||
|
||||
Vector3 desiredDir = new Vector3(
|
||||
input.X * right.X + input.Y * front.X,
|
||||
0.0f,
|
||||
input.X * right.Z + input.Y * front.Z);
|
||||
body.Dir = Vector3Lerp(body.Dir, desiredDir, CONTROL * delta);
|
||||
|
||||
float decel = (body.IsGrounded ? FRICTION : AIR_DRAG);
|
||||
Vector3 hvel = new Vector3(body.Velocity.X * decel, 0.0f, body.Velocity.Z * decel);
|
||||
|
||||
float hvelLength = Vector3Length(hvel); // Magnitude
|
||||
if (hvelLength < (MAX_SPEED * 0.01f))
|
||||
{
|
||||
hvel = new Vector3(0, 0, 0);
|
||||
}
|
||||
|
||||
// This is what creates strafing
|
||||
float speed = Vector3DotProduct(hvel, body.Dir);
|
||||
|
||||
// Whenever the amount of acceleration to add is clamped by the maximum acceleration constant,
|
||||
// a Player can make the speed faster by bringing the direction closer to horizontal velocity angle
|
||||
// More info here: https://youtu.be/v3zT3Z5apaM?t=165
|
||||
float maxSpeed = (crouchHold ? CROUCH_SPEED : MAX_SPEED);
|
||||
float accel = Clamp(maxSpeed - speed, 0.0f, MAX_ACCEL * delta);
|
||||
hvel.X += body.Dir.X * accel;
|
||||
hvel.Z += body.Dir.Z * accel;
|
||||
|
||||
body.Velocity.X = hvel.X;
|
||||
body.Velocity.Z = hvel.Z;
|
||||
|
||||
body.Position.X += body.Velocity.X * delta;
|
||||
body.Position.Y += body.Velocity.Y * delta;
|
||||
body.Position.Z += body.Velocity.Z * delta;
|
||||
|
||||
// Fancy collision system against the floor
|
||||
if (body.Position.Y <= 0.0f)
|
||||
{
|
||||
body.Position.Y = 0.0f;
|
||||
body.Velocity.Y = 0.0f;
|
||||
body.IsGrounded = true; // Enable jumping
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera for FPS behaviour
|
||||
private void UpdateCameraFPS(ref Camera3D camera)
|
||||
{
|
||||
Vector3 up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
Vector3 targetOffset = new Vector3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
// Left and right
|
||||
Vector3 yaw = Vector3RotateByAxisAngle(targetOffset, up, lookRotation.X);
|
||||
|
||||
// Clamp view up
|
||||
float maxAngleUp = Vector3Angle(up, yaw);
|
||||
maxAngleUp -= 0.001f; // Avoid numerical errors
|
||||
if (-(lookRotation.Y) > maxAngleUp)
|
||||
{
|
||||
lookRotation.Y = -maxAngleUp;
|
||||
}
|
||||
|
||||
// Clamp view down
|
||||
float maxAngleDown = Vector3Angle(Vector3Negate(up), yaw);
|
||||
maxAngleDown *= -1.0f; // Downwards angle is negative
|
||||
maxAngleDown += 0.001f; // Avoid numerical errors
|
||||
if (-(lookRotation.Y) < maxAngleDown)
|
||||
{
|
||||
lookRotation.Y = -maxAngleDown;
|
||||
}
|
||||
|
||||
// Up and down
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up));
|
||||
|
||||
// Rotate view vector around right axis
|
||||
float pitchAngle = -lookRotation.Y - lean.Y;
|
||||
pitchAngle = Clamp(pitchAngle, -MathF.PI / 2 + 0.0001f, MathF.PI / 2 - 0.0001f); // Clamp angle so it doesn't go past straight up or straight down
|
||||
Vector3 pitch = Vector3RotateByAxisAngle(yaw, right, pitchAngle);
|
||||
|
||||
// Head animation
|
||||
// Rotate up direction around forward axis
|
||||
float headSin = MathF.Sin(headTimer * MathF.PI);
|
||||
float headCos = MathF.Cos(headTimer * MathF.PI);
|
||||
const float stepRotation = 0.01f;
|
||||
camera.Up = Vector3RotateByAxisAngle(up, pitch, headSin * stepRotation + lean.X);
|
||||
|
||||
// Camera BOB
|
||||
const float bobSide = 0.1f;
|
||||
const float bobUp = 0.15f;
|
||||
Vector3 bobbing = Vector3Scale(right, headSin * bobSide);
|
||||
bobbing.Y = MathF.Abs(headCos * bobUp);
|
||||
|
||||
camera.Position = Vector3Add(camera.Position, Vector3Scale(bobbing, walkLerp));
|
||||
camera.Target = Vector3Add(camera.Position, pitch);
|
||||
}
|
||||
|
||||
// Draw game level
|
||||
private void DrawLevel()
|
||||
{
|
||||
const int floorExtent = 25;
|
||||
const float tileSize = 5.0f;
|
||||
Color tileColor1 = new Color(150, 200, 200, 255);
|
||||
|
||||
// Floor tiles
|
||||
for (int y = -floorExtent; y < floorExtent; y++)
|
||||
{
|
||||
for (int x = -floorExtent; x < floorExtent; x++)
|
||||
{
|
||||
if ((y & 1) != 0 && (x & 1) != 0)
|
||||
{
|
||||
DrawPlane(new Vector3(x * tileSize, 0.0f, y * tileSize), new Vector2(tileSize, tileSize), tileColor1);
|
||||
}
|
||||
else if ((y & 1) == 0 && (x & 1) == 0)
|
||||
{
|
||||
DrawPlane(new Vector3(x * tileSize, 0.0f, y * tileSize), new Vector2(tileSize, tileSize), Color.LightGray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 towerSize = new Vector3(16.0f, 32.0f, 16.0f);
|
||||
Color towerColor = new Color(150, 200, 200, 255);
|
||||
|
||||
Vector3 towerPos = new Vector3(16.0f, 16.0f, 16.0f);
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, Color.DarkBlue);
|
||||
|
||||
towerPos.X *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, Color.DarkBlue);
|
||||
|
||||
towerPos.Z *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, Color.DarkBlue);
|
||||
|
||||
towerPos.X *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, Color.DarkBlue);
|
||||
|
||||
// Red sun
|
||||
DrawSphere(new Vector3(300.0f, 300.0f, 0.0f), 100.0f, new Color(255, 0, 0, 255));
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera fps");
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Camera3dFps();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +1,114 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Initialize 3d camera free
|
||||
* raylib [core] example - 3d camera free
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 1.3
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class Camera3dFree
|
||||
public partial class Camera3dFree : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Camera 3D Free";
|
||||
|
||||
public string Title => "raylib [core] example - 3d camera free";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private Camera3D camera;
|
||||
private Vector3 cubePosition;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(10.0f, 10.0f, 10.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Z))
|
||||
{
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawRectangle(10, 10, 320, 93, Fade(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(10, 10, 320, 93, Color.Blue);
|
||||
|
||||
DrawText("Free camera default controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, Color.DarkGray);
|
||||
DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, Color.DarkGray);
|
||||
DrawText("- Z to zoom to (0, 0, 0)", 40, 80, 10, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera;
|
||||
camera.Position = new Vector3(10.0f, 10.0f, 10.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
Vector3 cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Camera3dFree();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Z))
|
||||
{
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawRectangle(10, 10, 320, 133, ColorAlpha(Color.SkyBlue, 0.5f));
|
||||
DrawRectangleLines(10, 10, 320, 133, Color.Blue);
|
||||
|
||||
DrawText("Free camera default controls:", 20, 20, 10, Color.Black);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, Color.DarkGray);
|
||||
DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, Color.DarkGray);
|
||||
DrawText("- Alt + Mouse Wheel Pressed to Rotate", 40, 80, 10, Color.DarkGray);
|
||||
DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 40, 100, 10, Color.DarkGray);
|
||||
DrawText("- Z to zoom to (0, 0, 0)", 40, 120, 10, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,76 +1,96 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Initialize 3d camera mode
|
||||
* raylib [core] example - 3d camera mode
|
||||
*
|
||||
* This example has been created using raylib 1.0 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 1.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class Camera3dMode
|
||||
public partial class Camera3dMode : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private Camera3D camera;
|
||||
private Vector3 cubePosition;
|
||||
|
||||
public string Name => "Core / Camera 3D Mode";
|
||||
|
||||
public string Title => "raylib [core] example - 3d camera mode";
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(0.0f, 10.0f, 10.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera mode type
|
||||
|
||||
cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Welcome to the third dimension!", 10, 40, 20, Color.DarkGray);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera mode");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(0.0f, 10.0f, 10.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
Vector3 cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Camera3dMode();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Welcome to the third dimension!", 10, 40, 20, Color.DarkGray);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
311
Examples/Core/ClipboardText.cs
Normal file
311
Examples/Core/ClipboardText.cs
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - clipboard text
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Ananth S (@Ananth1839) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Ananth S (@Ananth1839)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
// NOTE: The upstream C example uses raygui (GuiTextBox/GuiButton/GuiLabel) for its UI.
|
||||
// raygui is not bound in raylib-cs, so the widgets below are minimal re-implementations
|
||||
// using plain raylib drawing/input. Clipboard behaviour (cut/copy/paste and CTRL+X/C/V
|
||||
// shortcuts) matches the original.
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class ClipboardText : IExample
|
||||
{
|
||||
private const int MaxTextSamples = 5;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Clipboard Text";
|
||||
|
||||
public string Title => "raylib [core] example - clipboard text";
|
||||
|
||||
private string[] sampleTexts;
|
||||
private string clipboardText;
|
||||
private StringBuilder inputBuffer;
|
||||
|
||||
// UI required variables
|
||||
private bool textBoxEditMode;
|
||||
|
||||
private bool btnCutPressed;
|
||||
private bool btnCopyPressed;
|
||||
private bool btnPastePressed;
|
||||
private bool btnClearPressed;
|
||||
private bool btnRandomPressed;
|
||||
|
||||
private int framesCounter;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define some sample texts
|
||||
sampleTexts = new string[]
|
||||
{
|
||||
"Hello from raylib!",
|
||||
"The quick brown fox jumps over the lazy dog",
|
||||
"Clipboard operations are useful!",
|
||||
"raylib is a simple and easy-to-use library",
|
||||
"Copy and paste me!"
|
||||
};
|
||||
|
||||
clipboardText = null;
|
||||
inputBuffer = new StringBuilder("Hello from raylib!"); // Random initial string
|
||||
|
||||
// UI required variables
|
||||
textBoxEditMode = false;
|
||||
|
||||
btnCutPressed = false;
|
||||
btnCopyPressed = false;
|
||||
btnPastePressed = false;
|
||||
btnClearPressed = false;
|
||||
btnRandomPressed = false;
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
framesCounter++;
|
||||
|
||||
// Handle button interactions
|
||||
if (btnCutPressed)
|
||||
{
|
||||
SetClipboardText(inputBuffer.ToString());
|
||||
clipboardText = GetClipboardText_();
|
||||
inputBuffer.Clear(); // Quick solution to clear text
|
||||
}
|
||||
|
||||
if (btnCopyPressed)
|
||||
{
|
||||
SetClipboardText(inputBuffer.ToString()); // Copy text to clipboard
|
||||
clipboardText = GetClipboardText_(); // Get text from clipboard
|
||||
}
|
||||
|
||||
if (btnPastePressed)
|
||||
{
|
||||
// Paste text from clipboard
|
||||
clipboardText = GetClipboardText_();
|
||||
if (clipboardText != null)
|
||||
{
|
||||
SetInputBuffer(clipboardText);
|
||||
}
|
||||
}
|
||||
|
||||
if (btnClearPressed)
|
||||
{
|
||||
inputBuffer.Clear(); // Quick solution to clear text
|
||||
}
|
||||
|
||||
if (btnRandomPressed)
|
||||
{
|
||||
// Get random text from sample list
|
||||
SetInputBuffer(sampleTexts[GetRandomValue(0, MaxTextSamples - 1)]);
|
||||
}
|
||||
|
||||
// Quick cut/copy/paste with keyboard shortcuts
|
||||
if (IsKeyDown(KeyboardKey.LeftControl) || IsKeyDown(KeyboardKey.RightControl))
|
||||
{
|
||||
if (IsKeyPressed(KeyboardKey.X))
|
||||
{
|
||||
SetClipboardText(inputBuffer.ToString());
|
||||
inputBuffer.Clear(); // Quick solution to clear text
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.C))
|
||||
{
|
||||
SetClipboardText(inputBuffer.ToString());
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.V))
|
||||
{
|
||||
clipboardText = GetClipboardText_();
|
||||
if (clipboardText != null)
|
||||
{
|
||||
SetInputBuffer(clipboardText);
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw instructions
|
||||
GuiLabel(new Rectangle(50, 20, 700, 36), "Use the BUTTONS or KEY SHORTCUTS:");
|
||||
DrawText("[CTRL+X] - CUT | [CTRL+C] COPY | [CTRL+V] | PASTE", 50, 60, 20, Color.Maroon);
|
||||
|
||||
// Draw text box
|
||||
if (GuiTextBox(new Rectangle(50, 120, 652, 40), inputBuffer, 256, textBoxEditMode))
|
||||
{
|
||||
textBoxEditMode = !textBoxEditMode;
|
||||
}
|
||||
|
||||
// Random text button
|
||||
btnRandomPressed = GuiButton(new Rectangle(50 + 652 + 8, 120, 40, 40), "RND");
|
||||
|
||||
// Draw buttons
|
||||
btnCutPressed = GuiButton(new Rectangle(50, 180, 158, 40), "CUT");
|
||||
btnCopyPressed = GuiButton(new Rectangle(50 + 165, 180, 158, 40), "COPY");
|
||||
btnPastePressed = GuiButton(new Rectangle(50 + 165 * 2, 180, 158, 40), "PASTE");
|
||||
btnClearPressed = GuiButton(new Rectangle(50 + 165 * 3, 180, 158, 40), "CLEAR");
|
||||
|
||||
// Draw clipboard status
|
||||
GuiLabel(new Rectangle(50, 260, 700, 40), "Clipboard current text data:");
|
||||
GuiTextBoxReadOnly(new Rectangle(50, 300, 700, 40), clipboardText);
|
||||
GuiLabel(new Rectangle(50, 360, 700, 40), "Try copying text from other applications and pasting here!");
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
// Replace input buffer contents (equivalent to raylib TextCopy into a fixed buffer)
|
||||
private void SetInputBuffer(string text)
|
||||
{
|
||||
inputBuffer.Clear();
|
||||
if (text != null)
|
||||
{
|
||||
if (text.Length > 255)
|
||||
{
|
||||
text = text.Substring(0, 255);
|
||||
}
|
||||
|
||||
inputBuffer.Append(text);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Minimal raygui-like widgets (plain raylib re-implementation)
|
||||
//----------------------------------------------------------------------------------
|
||||
private static void GuiLabel(Rectangle bounds, string text)
|
||||
{
|
||||
DrawText(text, (int)bounds.X, (int)(bounds.Y + (bounds.Height - 20) / 2), 20, Color.DarkGray);
|
||||
}
|
||||
|
||||
private static bool GuiButton(Rectangle bounds, string text)
|
||||
{
|
||||
bool pressed = false;
|
||||
Vector2 mouse = GetMousePosition();
|
||||
bool hover = CheckCollisionPointRec(mouse, bounds);
|
||||
|
||||
Color fill = hover ? (IsMouseButtonDown(MouseButton.Left) ? Color.SkyBlue : Color.LightGray) : Color.RayWhite;
|
||||
DrawRectangleRec(bounds, fill);
|
||||
DrawRectangleLinesEx(bounds, 1, hover ? Color.Blue : Color.Gray);
|
||||
|
||||
int textWidth = MeasureText(text, 20);
|
||||
DrawText(text, (int)(bounds.X + (bounds.Width - textWidth) / 2), (int)(bounds.Y + (bounds.Height - 20) / 2), 20, Color.DarkGray);
|
||||
|
||||
if (hover && IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
pressed = true;
|
||||
}
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
private bool GuiTextBox(Rectangle bounds, StringBuilder text, int maxChars, bool editMode)
|
||||
{
|
||||
bool pressed = false;
|
||||
Vector2 mouse = GetMousePosition();
|
||||
bool hover = CheckCollisionPointRec(mouse, bounds);
|
||||
|
||||
if (editMode)
|
||||
{
|
||||
// Get char pressed (unicode character) on the queue
|
||||
int key = GetCharPressed();
|
||||
while (key > 0)
|
||||
{
|
||||
if ((key >= 32) && (key <= 125) && (text.Length < maxChars - 1))
|
||||
{
|
||||
text.Append((char)key);
|
||||
}
|
||||
|
||||
key = GetCharPressed();
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Backspace) && (text.Length > 0))
|
||||
{
|
||||
text.Remove(text.Length - 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleRec(bounds, Color.RayWhite);
|
||||
DrawRectangleLinesEx(bounds, editMode ? 2 : 1, editMode ? Color.Red : (hover ? Color.Blue : Color.Gray));
|
||||
|
||||
string content = text.ToString();
|
||||
DrawText(content, (int)bounds.X + 4, (int)(bounds.Y + (bounds.Height - 20) / 2), 20, Color.DarkGray);
|
||||
|
||||
// Draw blinking cursor while editing
|
||||
if (editMode && ((framesCounter / 20) % 2 == 0))
|
||||
{
|
||||
DrawText("_", (int)bounds.X + 4 + MeasureText(content, 20), (int)(bounds.Y + (bounds.Height - 20) / 2), 20, Color.DarkGray);
|
||||
}
|
||||
|
||||
if (hover && IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
pressed = true;
|
||||
}
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
private static void GuiTextBoxReadOnly(Rectangle bounds, string text)
|
||||
{
|
||||
DrawRectangleRec(bounds, Color.LightGray);
|
||||
DrawRectangleLinesEx(bounds, 1, Color.Gray);
|
||||
if (text != null)
|
||||
{
|
||||
DrawText(text, (int)bounds.X + 4, (int)(bounds.Y + (bounds.Height - 20) / 2), 20, Color.Gray);
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - clipboard text");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new ClipboardText();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
276
Examples/Core/ComputeHash.cs
Normal file
276
Examples/Core/ComputeHash.cs
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - compute hash
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
// NOTE: The upstream C example uses raygui (GuiTextBox/GuiButton/GuiLabel) for its UI.
|
||||
// raygui is not bound in raylib-cs, so the widgets below are minimal re-implementations
|
||||
// using plain raylib drawing/input. The hashing/Base64 logic is a faithful port.
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public unsafe partial class ComputeHash : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Compute Hash";
|
||||
|
||||
public string Title => "raylib [core] example - compute hash";
|
||||
|
||||
// UI controls variables
|
||||
private StringBuilder textInput;
|
||||
private bool textBoxEditMode;
|
||||
private bool btnComputeHashes;
|
||||
|
||||
// Data hash values
|
||||
private uint hashCRC32;
|
||||
private uint[] hashMD5;
|
||||
private uint[] hashSHA1;
|
||||
private uint[] hashSHA256;
|
||||
|
||||
// Base64 encoded data
|
||||
private string base64Text;
|
||||
|
||||
private int framesCounter;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
textInput = new StringBuilder("The quick brown fox jumps over the lazy dog.");
|
||||
textBoxEditMode = false;
|
||||
btnComputeHashes = false;
|
||||
|
||||
hashCRC32 = 0;
|
||||
hashMD5 = null;
|
||||
hashSHA1 = null;
|
||||
hashSHA256 = null;
|
||||
|
||||
base64Text = null;
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
framesCounter++;
|
||||
|
||||
if (btnComputeHashes)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(textInput.ToString());
|
||||
int textInputLen = bytes.Length;
|
||||
|
||||
fixed (byte* textInputPtr = bytes)
|
||||
{
|
||||
int base64TextSize;
|
||||
|
||||
// Encode data to Base64 string (includes NULL terminator), memory must be MemFree()
|
||||
sbyte* base64 = EncodeDataBase64(textInputPtr, textInputLen, &base64TextSize);
|
||||
base64Text = (base64 != null) ? new string(base64) : null;
|
||||
MemFree(base64); // Free Base64 text data (kept managed above)
|
||||
|
||||
hashCRC32 = ComputeCRC32(textInputPtr, textInputLen); // Compute CRC32 hash code (4 bytes)
|
||||
hashMD5 = CopyHash(ComputeMD5(textInputPtr, textInputLen), 4); // Compute MD5 hash code, returns static int[4] (16 bytes)
|
||||
hashSHA1 = CopyHash(ComputeSHA1(textInputPtr, textInputLen), 5); // Compute SHA1 hash code, returns static int[5] (20 bytes)
|
||||
hashSHA256 = CopyHash(ComputeSHA256(textInputPtr, textInputLen), 8); // Compute SHA256 hash code, returns static int[8] (32 bytes)
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
GuiLabel(new Rectangle(40, 26, 720, 32), "INPUT DATA (TEXT):", 20);
|
||||
|
||||
if (GuiTextBox(new Rectangle(40, 64, 720, 32), textInput, 95, textBoxEditMode, 10))
|
||||
{
|
||||
textBoxEditMode = !textBoxEditMode;
|
||||
}
|
||||
|
||||
btnComputeHashes = GuiButton(new Rectangle(40, 64 + 40, 720, 32), "COMPUTE INPUT DATA HASHES", 10);
|
||||
|
||||
GuiLabel(new Rectangle(40, 160, 720, 32), "INPUT DATA HASH VALUES:", 20);
|
||||
|
||||
GuiLabel(new Rectangle(40, 200, 120, 32), "CRC32 [32 bit]:", 10);
|
||||
GuiTextBoxReadOnly(new Rectangle(40 + 120, 200, 720 - 120, 32), GetDataAsHexText(new uint[] { hashCRC32 }, 1), 10);
|
||||
GuiLabel(new Rectangle(40, 200 + 36, 120, 32), "MD5 [128 bit]:", 10);
|
||||
GuiTextBoxReadOnly(new Rectangle(40 + 120, 200 + 36, 720 - 120, 32), GetDataAsHexText(hashMD5, 4), 10);
|
||||
GuiLabel(new Rectangle(40, 200 + 36 * 2, 120, 32), "SHA1 [160 bit]:", 10);
|
||||
GuiTextBoxReadOnly(new Rectangle(40 + 120, 200 + 36 * 2, 720 - 120, 32), GetDataAsHexText(hashSHA1, 5), 10);
|
||||
GuiLabel(new Rectangle(40, 200 + 36 * 3, 120, 32), "SHA256 [256 bit]:", 10);
|
||||
GuiTextBoxReadOnly(new Rectangle(40 + 120, 200 + 36 * 3, 720 - 120, 32), GetDataAsHexText(hashSHA256, 8), 10);
|
||||
|
||||
GuiLabel(new Rectangle(40, 200 + 36 * 5 - 30, 320, 32), "BONUS - BAS64 ENCODED STRING:", 10);
|
||||
GuiLabel(new Rectangle(40, 200 + 36 * 5, 120, 32), "BASE64 ENCODING:", 10);
|
||||
GuiTextBoxReadOnly(new Rectangle(40 + 120, 200 + 36 * 5, 720 - 120, 32), base64Text, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
private static uint[] CopyHash(uint* data, int count)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
uint[] result = new uint[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result[i] = data[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetDataAsHexText(uint[] data, int dataSize)
|
||||
{
|
||||
if ((data != null) && (dataSize > 0) && (dataSize < ((128 / 8) - 1)))
|
||||
{
|
||||
StringBuilder text = new StringBuilder();
|
||||
for (int i = 0; i < dataSize; i++)
|
||||
{
|
||||
text.Append(data[i].ToString("X8"));
|
||||
}
|
||||
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
return "00000000";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Minimal raygui-like widgets (plain raylib re-implementation)
|
||||
//----------------------------------------------------------------------------------
|
||||
private static void GuiLabel(Rectangle bounds, string text, int fontSize)
|
||||
{
|
||||
DrawText(text, (int)bounds.X, (int)(bounds.Y + (bounds.Height - fontSize) / 2), fontSize, Color.DarkGray);
|
||||
}
|
||||
|
||||
private static bool GuiButton(Rectangle bounds, string text, int fontSize)
|
||||
{
|
||||
bool pressed = false;
|
||||
Vector2 mouse = GetMousePosition();
|
||||
bool hover = CheckCollisionPointRec(mouse, bounds);
|
||||
|
||||
Color fill = hover ? (IsMouseButtonDown(MouseButton.Left) ? Color.SkyBlue : Color.LightGray) : Color.RayWhite;
|
||||
DrawRectangleRec(bounds, fill);
|
||||
DrawRectangleLinesEx(bounds, 1, hover ? Color.Blue : Color.Gray);
|
||||
|
||||
int textWidth = MeasureText(text, fontSize);
|
||||
DrawText(text, (int)(bounds.X + (bounds.Width - textWidth) / 2), (int)(bounds.Y + (bounds.Height - fontSize) / 2), fontSize, Color.DarkGray);
|
||||
|
||||
if (hover && IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
pressed = true;
|
||||
}
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
private bool GuiTextBox(Rectangle bounds, StringBuilder text, int maxChars, bool editMode, int fontSize)
|
||||
{
|
||||
bool pressed = false;
|
||||
Vector2 mouse = GetMousePosition();
|
||||
bool hover = CheckCollisionPointRec(mouse, bounds);
|
||||
|
||||
if (editMode)
|
||||
{
|
||||
int key = GetCharPressed();
|
||||
while (key > 0)
|
||||
{
|
||||
if ((key >= 32) && (key <= 125) && (text.Length < maxChars - 1))
|
||||
{
|
||||
text.Append((char)key);
|
||||
}
|
||||
|
||||
key = GetCharPressed();
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Backspace) && (text.Length > 0))
|
||||
{
|
||||
text.Remove(text.Length - 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleRec(bounds, Color.RayWhite);
|
||||
DrawRectangleLinesEx(bounds, editMode ? 2 : 1, editMode ? Color.Red : (hover ? Color.Blue : Color.Gray));
|
||||
|
||||
string content = text.ToString();
|
||||
DrawText(content, (int)bounds.X + 4, (int)(bounds.Y + (bounds.Height - fontSize) / 2), fontSize, Color.DarkGray);
|
||||
|
||||
if (editMode && ((framesCounter / 20) % 2 == 0))
|
||||
{
|
||||
DrawText("_", (int)bounds.X + 4 + MeasureText(content, fontSize), (int)(bounds.Y + (bounds.Height - fontSize) / 2), fontSize, Color.DarkGray);
|
||||
}
|
||||
|
||||
if (hover && IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
pressed = true;
|
||||
}
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
private static void GuiTextBoxReadOnly(Rectangle bounds, string text, int fontSize)
|
||||
{
|
||||
DrawRectangleRec(bounds, Color.LightGray);
|
||||
DrawRectangleLinesEx(bounds, 1, Color.Gray);
|
||||
if (text != null)
|
||||
{
|
||||
DrawText(text, (int)bounds.X + 4, (int)(bounds.Y + (bounds.Height - fontSize) / 2), fontSize, Color.Gray);
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - compute hash");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new ComputeHash();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
208
Examples/Core/CustomFrameControl.cs
Normal file
208
Examples/Core/CustomFrameControl.cs
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - custom frame control
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* NOTE: WARNING: This is an example for advanced users willing to have full control over
|
||||
* the frame processes. By default, EndDrawing() calls the following processes:
|
||||
* 1. Draw remaining batch data: rlDrawRenderBatchActive()
|
||||
* 2. SwapScreenBuffer()
|
||||
* 3. Frame time control: WaitTime()
|
||||
* 4. PollInputEvents()
|
||||
*
|
||||
* To avoid steps 2, 3 and 4, flag SUPPORT_CUSTOM_FRAME_CONTROL can be enabled in
|
||||
* config.h (it requires recompiling raylib). This way those steps are up to the user
|
||||
*
|
||||
* Note that enabling this flag invalidates some functions:
|
||||
* - GetFrameTime()
|
||||
* - SetTargetFPS()
|
||||
* - GetFPS()
|
||||
*
|
||||
* Example originally created with raylib 4.0, last time updated with raylib 4.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2021-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
// NOTE: This example is intended to run against a raylib built with SUPPORT_CUSTOM_FRAME_CONTROL,
|
||||
// where EndDrawing() does NOT swap buffers, wait or poll input, leaving those to the user code
|
||||
// below. The stock raylib-cs native library is built WITHOUT that flag, so EndDrawing() still
|
||||
// performs those steps and the manual SwapScreenBuffer()/WaitTime()/PollInputEvents() calls here
|
||||
// run in addition to them. The port is kept faithful to upstream regardless.
|
||||
[ExcludeFromBrowser("manual PollInputEvents/SwapScreenBuffer/WaitTime clashes with the emscripten main loop")]
|
||||
public partial class CustomFrameControl : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Custom Frame Control";
|
||||
|
||||
public string Title => "raylib [core] example - custom frame control";
|
||||
|
||||
// Custom timming variables
|
||||
private double previousTime; // Previous time measure
|
||||
private double currentTime; // Current time measure
|
||||
private double updateDrawTime; // Update + Draw time
|
||||
private double waitTime; // Wait time (if target fps required)
|
||||
private float deltaTime; // Frame time (Update + Draw + Wait time)
|
||||
|
||||
private float timeCounter; // Accumulative time counter (seconds)
|
||||
private float position; // Circle position
|
||||
private bool pause; // Pause control flag
|
||||
|
||||
private int targetFPS; // Our initial target fps
|
||||
|
||||
public void Init()
|
||||
{
|
||||
previousTime = GetTime();
|
||||
currentTime = 0.0;
|
||||
updateDrawTime = 0.0;
|
||||
waitTime = 0.0;
|
||||
deltaTime = 0.0f;
|
||||
|
||||
timeCounter = 0.0f;
|
||||
position = 0.0f;
|
||||
pause = false;
|
||||
|
||||
targetFPS = 60;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
#if !BROWSER
|
||||
// NOTE: On non web platforms the PollInputEvents just works before the inputs checks
|
||||
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||
#endif
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
pause = !pause;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Up))
|
||||
{
|
||||
targetFPS += 20;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Down))
|
||||
{
|
||||
targetFPS -= 20;
|
||||
}
|
||||
|
||||
if (targetFPS < 0)
|
||||
{
|
||||
targetFPS = 0;
|
||||
}
|
||||
|
||||
if (!pause)
|
||||
{
|
||||
position += 200 * deltaTime; // We move at 200 pixels per second
|
||||
if (position >= GetScreenWidth())
|
||||
{
|
||||
position = 0;
|
||||
}
|
||||
|
||||
timeCounter += deltaTime; // We count time (seconds)
|
||||
}
|
||||
|
||||
#if BROWSER
|
||||
// NOTE: On web platform for some reason the PollInputEvents only works after the inputs
|
||||
// check, so just call it after check all your inputs (on web)
|
||||
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||
#endif
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
for (int i = 0; i < GetScreenWidth() / 200; i++)
|
||||
{
|
||||
DrawRectangle(200 * i, 0, 1, GetScreenHeight(), Color.SkyBlue);
|
||||
}
|
||||
|
||||
DrawCircle((int)position, GetScreenHeight() / 2 - 25, 50, Color.Red);
|
||||
|
||||
DrawText($"{timeCounter * 1000.0f:000} ms", (int)position - 40, GetScreenHeight() / 2 - 100, 20, Color.Maroon);
|
||||
DrawText($"PosX: {position:000}", (int)position - 50, GetScreenHeight() / 2 + 40, 20, Color.Black);
|
||||
|
||||
DrawText("Circle is moving at a constant 200 pixels/sec,\nindependently of the frame rate.", 10, 10, 20, Color.DarkGray);
|
||||
DrawText("PRESS SPACE to PAUSE MOVEMENT", 10, GetScreenHeight() - 60, 20, Color.Gray);
|
||||
DrawText("PRESS UP | DOWN to CHANGE TARGET FPS", 10, GetScreenHeight() - 30, 20, Color.Gray);
|
||||
DrawText($"TARGET FPS: {targetFPS}", GetScreenWidth() - 220, 10, 20, Color.Lime);
|
||||
if (deltaTime != 0)
|
||||
{
|
||||
DrawText($"CURRENT FPS: {(int)(1.0f / deltaTime)}", GetScreenWidth() - 220, 40, 20, Color.Green);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
|
||||
// NOTE: In case raylib is configured to SUPPORT_CUSTOM_FRAME_CONTROL,
|
||||
// Events polling, screen buffer swap and frame time control must be managed by the user
|
||||
|
||||
SwapScreenBuffer(); // Flip the back buffer to screen (front buffer)
|
||||
|
||||
currentTime = GetTime();
|
||||
updateDrawTime = currentTime - previousTime;
|
||||
|
||||
if (targetFPS > 0) // We want a fixed frame rate
|
||||
{
|
||||
waitTime = (1.0f / (float)targetFPS) - updateDrawTime;
|
||||
if (waitTime > 0.0)
|
||||
{
|
||||
WaitTime((float)waitTime);
|
||||
currentTime = GetTime();
|
||||
deltaTime = (float)(currentTime - previousTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
deltaTime = (float)updateDrawTime; // Framerate could be variable
|
||||
}
|
||||
|
||||
previousTime = currentTime;
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom frame control");
|
||||
|
||||
// NOTE: Not calling SetTargetFPS(): this example manages frame timing manually with
|
||||
// WaitTime() (SetTargetFPS/GetFrameTime/GetFPS are invalidated by SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new CustomFrameControl();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +1,41 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Custom logging
|
||||
* raylib [core] example - custom logging
|
||||
*
|
||||
* This example has been created using raylib 2.1 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Pablo Marcos Oltra (@pamarcos) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2018 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2018-2025 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public unsafe class CustomLogging
|
||||
public unsafe partial class CustomLogging : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Custom Logging";
|
||||
|
||||
public string Title => "raylib [core] example - custom logging";
|
||||
|
||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
|
||||
private static void LogCustom(int logLevel, sbyte* text, sbyte* args)
|
||||
{
|
||||
#if BROWSER
|
||||
// WebAssembly can't invoke the C varargs vsprintf/vsnprintf that Logging.GetLogMessage relies on
|
||||
// (the wasm runtime traps with "function signature mismatch"), so log the raw, unformatted text.
|
||||
string message = Marshal.PtrToStringUTF8(new IntPtr(text)) ?? string.Empty;
|
||||
#else
|
||||
var message = Logging.GetLogMessage(new IntPtr(text), new IntPtr(args));
|
||||
|
||||
/*Console.ForegroundColor = (TraceLogLevel)logLevel switch
|
||||
|
|
@ -36,50 +50,64 @@ public unsafe class CustomLogging
|
|||
TraceLogLevel.LOG_NONE => ConsoleColor.White,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null)
|
||||
};*/
|
||||
#endif
|
||||
|
||||
Console.WriteLine($"Custom " + message);
|
||||
// Console.ResetColor();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// First thing we do is setting our custom logger to ensure everything raylib logs
|
||||
// will use our own logger instead of its internal one
|
||||
SetTraceLogCallback(&LogCustom);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
#if !BROWSER
|
||||
// Restore the default formatting logger on desktop. On WebAssembly we leave the (wasm-safe)
|
||||
// custom logger in place — Logging.LogConsole formats via vsprintf, which traps on wasm.
|
||||
SetTraceLogCallback(&Logging.LogConsole);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// First thing we do is setting our custom logger to ensure everything raylib logs
|
||||
// will use our own logger instead of its internal one
|
||||
SetTraceLogCallback(&LogCustom);
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging");
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new CustomLogging();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
SetTraceLogCallback(&Logging.LogConsole);
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -15,114 +15,141 @@
|
|||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
public class DeltaTime
|
||||
public partial class DeltaTime : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// The speed applied to both circles
|
||||
private const float speed = 10.0f;
|
||||
private const float circleRadius = 32.0f;
|
||||
|
||||
private int currentFps;
|
||||
|
||||
// Store the position for the both of the circles
|
||||
private Vector2 deltaCircle;
|
||||
private Vector2 frameCircle;
|
||||
|
||||
public string Name => "Core / Delta Time";
|
||||
|
||||
public string Title => "raylib [core] example - delta time";
|
||||
|
||||
public void Init()
|
||||
{
|
||||
currentFps = 60;
|
||||
|
||||
// Store the position for the both of the circles
|
||||
deltaCircle = new Vector2(0, (float)screenHeight / 3.0f);
|
||||
frameCircle = new Vector2(0, (float)screenHeight * (2.0f / 3.0f));
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Adjust the FPS target based on the mouse wheel
|
||||
var mouseWheel = GetMouseWheelMove();
|
||||
if (mouseWheel != 0)
|
||||
{
|
||||
currentFps += (int)mouseWheel;
|
||||
if (currentFps < 0)
|
||||
{
|
||||
currentFps = 0;
|
||||
}
|
||||
SetTargetFPS(currentFps);
|
||||
}
|
||||
|
||||
// GetFrameTime() returns the time it took to draw the last frame, in seconds (usually called delta time)
|
||||
// Uses the delta time to make the circle look like it's moving at a "consistent" speed regardless of FPS
|
||||
|
||||
// Multiply by 6.0 (an arbitrary value) in order to make the speed
|
||||
// visually closer to the other circle (at 60 fps), for comparison
|
||||
deltaCircle.X += GetFrameTime() * 6.0f * speed;
|
||||
// This circle can move faster or slower visually depending on the FPS
|
||||
frameCircle.X += 0.1f * speed;
|
||||
|
||||
// If either circle is off the screen, reset it back to the start
|
||||
if (deltaCircle.X > screenWidth)
|
||||
{
|
||||
deltaCircle.X = 0;
|
||||
}
|
||||
|
||||
if (frameCircle.X > screenWidth)
|
||||
{
|
||||
frameCircle.X = 0;
|
||||
}
|
||||
|
||||
// Reset both circles positions
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
deltaCircle.X = 0;
|
||||
frameCircle.X = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw both circles to the screen
|
||||
DrawCircleV(deltaCircle, circleRadius, Color.Red);
|
||||
DrawCircleV(frameCircle, circleRadius, Color.Blue);
|
||||
|
||||
// Draw the help text
|
||||
// Determine what help text to show depending on the current FPS target
|
||||
var fpsText = "";
|
||||
if (currentFps <= 0)
|
||||
{
|
||||
fpsText = $"FPS: unlimited ({GetFPS()})";
|
||||
}
|
||||
else
|
||||
{
|
||||
fpsText = $"FPS: {GetFPS()} (target: {currentFps})";
|
||||
}
|
||||
DrawText(fpsText, 10, 10, 20, Color.DarkGray);
|
||||
DrawText($"Frame time: {GetFrameTime():F2} ms", 10, 30, 20, Color.DarkGray);
|
||||
DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, Color.DarkGray);
|
||||
|
||||
// Draw the text above the circles
|
||||
DrawText("FUNC: x += GetFrameTime()*speed", 10, 90, 20, Color.Red);
|
||||
DrawText("FUNC: x += speed", 10, 240, 20, Color.Blue);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - delta time");
|
||||
|
||||
int currentFps = 60;
|
||||
|
||||
Vector2 deltaCircle = new Vector2(0, (float)screenHeight / 3.0f);
|
||||
Vector2 frameCircle = new Vector2(0, (float)screenHeight * (2.0f / 3.0f));
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
const float speed = 10.0f;
|
||||
const float circleRadius = 32.0f;
|
||||
var game = new DeltaTime();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Adjust the FPS target based on the mouse wheel
|
||||
float mouseWheel = GetMouseWheelMove();
|
||||
if (mouseWheel != 0)
|
||||
{
|
||||
currentFps += (int)mouseWheel;
|
||||
if (currentFps < 0)
|
||||
{
|
||||
currentFps = 0;
|
||||
}
|
||||
SetTargetFPS(currentFps);
|
||||
}
|
||||
|
||||
// GetFrameTime() returns the time it took to draw the last frame, in seconds (usually called delta time)
|
||||
// Uses the delta time to make the circle look like it's moving at a "consistent" speed regardless of FPS
|
||||
|
||||
// Multiply by 6.0 (an arbitrary value) in order to make the speed
|
||||
// visually closer to the other circle (at 60 fps), for comparison
|
||||
deltaCircle.X += GetFrameTime() * 6.0f * speed;
|
||||
// This circle can move faster or slower visually depending on the FPS
|
||||
frameCircle.X += 0.1f * speed;
|
||||
|
||||
// If either circle is off the screen, reset it back to the start
|
||||
if (deltaCircle.X > screenWidth)
|
||||
{
|
||||
deltaCircle.X = 0;
|
||||
}
|
||||
|
||||
if (frameCircle.X > screenWidth)
|
||||
{
|
||||
frameCircle.X = 0;
|
||||
}
|
||||
|
||||
// Reset both circles positions
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
deltaCircle.X = 0;
|
||||
frameCircle.X = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw both circles to the screen
|
||||
DrawCircleV(deltaCircle, circleRadius, Color.Red);
|
||||
DrawCircleV(frameCircle, circleRadius, Color.Blue);
|
||||
|
||||
// Draw the help text
|
||||
// Determine what help text to show depending on the current FPS target
|
||||
var fpsText = "";
|
||||
if (currentFps <= 0)
|
||||
{
|
||||
fpsText = $"FPS: unlimited ({GetFPS()})";
|
||||
}
|
||||
else
|
||||
{
|
||||
fpsText = $"FPS: {GetFPS()} (target: {currentFps})";
|
||||
}
|
||||
DrawText(fpsText, 10, 10, 20, Color.DarkGray);
|
||||
DrawText($"Frame time: {GetFrameTime():F2} ms", 10, 30, 20, Color.DarkGray);
|
||||
DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, Color.DarkGray);
|
||||
|
||||
// Draw the text above the circles
|
||||
DrawText("FUNC: x += GetFrameTime()*speed", 10, 90, 20, Color.Red);
|
||||
DrawText("FUNC: x += speed", 10, 240, 20, Color.Blue);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
201
Examples/Core/DirectoryFiles.cs
Normal file
201
Examples/Core/DirectoryFiles.cs
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - directory files
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Hugo ARNAL (@hugoarnal) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Hugo ARNAL (@hugoarnal)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
// NOTE: The original example relies on raygui (GuiButton, GuiLabel, GuiListViewEx) for its UI.
|
||||
// raygui is not part of the raylib-cs bindings, so the back button, directory label and file
|
||||
// list view are reimplemented here with plain raylib primitives. The directory navigation
|
||||
// behaviour (enter directories, go back) is preserved.
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class DirectoryFiles : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private const string FileFilter = "DIRS*;.png;.c";
|
||||
|
||||
public string Name => "Core / Directory Files";
|
||||
|
||||
public string Title => "raylib [core] example - directory files";
|
||||
|
||||
private string directory;
|
||||
private FilePathList files;
|
||||
|
||||
private bool btnBackPressed;
|
||||
|
||||
private int listScrollIndex;
|
||||
private int listItemActive;
|
||||
private int listItemFocused;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
directory = GetWorkingDirectoryAsString();
|
||||
|
||||
// Load file-paths on current working directory
|
||||
// NOTE: LoadDirectoryFiles() loads files and directories by default,
|
||||
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
|
||||
//files = LoadDirectoryFiles(directory);
|
||||
files = LoadDirectoryFilesEx(directory, FileFilter, false);
|
||||
|
||||
btnBackPressed = false;
|
||||
|
||||
listScrollIndex = 0;
|
||||
listItemActive = -1;
|
||||
listItemFocused = -1;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (btnBackPressed)
|
||||
{
|
||||
directory = GetPrevDirectoryPath(directory);
|
||||
UnloadDirectoryFiles(files);
|
||||
files = LoadDirectoryFilesEx(directory, FileFilter, false);
|
||||
|
||||
listScrollIndex = 0;
|
||||
listItemActive = -1;
|
||||
listItemFocused = -1;
|
||||
}
|
||||
|
||||
if ((listItemActive >= 0) && (listItemActive < (int)files.Count))
|
||||
{
|
||||
string selected = files[(uint)listItemActive];
|
||||
bool isDirectory = DirectoryExists(selected);
|
||||
if (isDirectory)
|
||||
{
|
||||
directory = selected;
|
||||
UnloadDirectoryFiles(files);
|
||||
files = LoadDirectoryFilesEx(directory, FileFilter, false);
|
||||
|
||||
listScrollIndex = 0;
|
||||
listItemActive = -1;
|
||||
listItemFocused = -1;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
Vector2 mouse = GetMousePosition();
|
||||
|
||||
// Back button "<"
|
||||
Rectangle backBounds = new Rectangle(40.0f, 10.0f, 48, 28);
|
||||
bool backHover = CheckCollisionPointRec(mouse, backBounds);
|
||||
DrawRectangleRec(backBounds, backHover ? Color.SkyBlue : Color.LightGray);
|
||||
DrawRectangleLinesEx(backBounds, 1, Color.Gray);
|
||||
int backTextWidth = MeasureText("<", 20);
|
||||
DrawText("<", (int)(backBounds.X + (backBounds.Width - backTextWidth) / 2), (int)(backBounds.Y + 4), 20, Color.DarkGray);
|
||||
btnBackPressed = backHover && IsMouseButtonReleased(MouseButton.Left);
|
||||
|
||||
// Current directory label
|
||||
DrawText(directory, 40 + 48 + 10, 16, 20, Color.DarkGray);
|
||||
|
||||
// File list view
|
||||
Rectangle listBounds = new Rectangle(0, 50, GetScreenWidth(), GetScreenHeight() - 50);
|
||||
DrawRectangleRec(listBounds, Color.RayWhite);
|
||||
DrawRectangleLinesEx(listBounds, 1, Color.Gray);
|
||||
|
||||
int count = (int)files.Count;
|
||||
float rowHeight = 28;
|
||||
int visibleRows = (int)(listBounds.Height / rowHeight);
|
||||
|
||||
bool mouseInList = CheckCollisionPointRec(mouse, listBounds);
|
||||
if (mouseInList)
|
||||
{
|
||||
listScrollIndex -= (int)GetMouseWheelMove();
|
||||
}
|
||||
int maxScroll = Math.Max(0, count - visibleRows);
|
||||
listScrollIndex = Math.Clamp(listScrollIndex, 0, maxScroll);
|
||||
|
||||
listItemFocused = -1;
|
||||
for (int i = 0; i < visibleRows; i++)
|
||||
{
|
||||
int itemIndex = listScrollIndex + i;
|
||||
if (itemIndex >= count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Rectangle rowRec = new Rectangle(listBounds.X + 1, listBounds.Y + 1 + i * rowHeight, listBounds.Width - 2, rowHeight);
|
||||
bool rowHover = mouseInList && CheckCollisionPointRec(mouse, rowRec);
|
||||
|
||||
if (itemIndex == listItemActive)
|
||||
{
|
||||
DrawRectangleRec(rowRec, Fade(Color.SkyBlue, 0.7f));
|
||||
}
|
||||
else if (rowHover)
|
||||
{
|
||||
DrawRectangleRec(rowRec, Fade(Color.SkyBlue, 0.3f));
|
||||
}
|
||||
|
||||
if (rowHover)
|
||||
{
|
||||
listItemFocused = itemIndex;
|
||||
if (IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
listItemActive = itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
DrawText(files[(uint)itemIndex], (int)rowRec.X + 40, (int)rowRec.Y + 8, 10, Color.DarkGray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadDirectoryFiles(files);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - directory files");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new DirectoryFiles();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +1,122 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Windows drop files
|
||||
* raylib [core] example - drop files
|
||||
*
|
||||
* This example only works on platforms that support drag ref drop (Windows, Linux, OSX, Html5?)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?)
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.2
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class DropFiles
|
||||
[ExcludeFromBrowser]
|
||||
public partial class DropFiles : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public const int MaxFilepathRecorded = 4096;
|
||||
|
||||
public string Name => "Core / Drop Files";
|
||||
|
||||
public string Title => "raylib [core] example - drop files";
|
||||
|
||||
private List<string> filePaths;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// We will register a maximum of filepaths
|
||||
filePaths = new();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsFileDropped())
|
||||
{
|
||||
var droppedFiles = GetDroppedFiles();
|
||||
|
||||
for (var i = 0; i < droppedFiles.Length; i++)
|
||||
{
|
||||
if (filePaths.Count < (MaxFilepathRecorded - 1))
|
||||
{
|
||||
filePaths.Add(droppedFiles[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (filePaths.Count == 0)
|
||||
{
|
||||
DrawText("Drop your files to this window!", 100, 40, 20, Color.DarkGray);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("Dropped files:", 100, 40, 20, Color.DarkGray);
|
||||
|
||||
for (var i = 0; i < filePaths.Count; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
DrawRectangle(0, 85 + 40 * i, screenWidth, 40, Fade(Color.LightGray, 0.5f));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangle(0, 85 + 40 * i, screenWidth, 40, Fade(Color.LightGray, 0.3f));
|
||||
}
|
||||
|
||||
DrawText(filePaths[i], 120, 100 + 40 * i, 10, Color.Gray);
|
||||
}
|
||||
|
||||
DrawText("Drop new files...", 100, 110 + 40 * filePaths.Count, 20, Color.DarkGray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - drop files");
|
||||
|
||||
string[] files = new string[0];
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new DropFiles();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsFileDropped())
|
||||
{
|
||||
files = Raylib.GetDroppedFiles();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (files.Length == 0)
|
||||
{
|
||||
DrawText("Drop your files to this window!", 100, 40, 20, Color.DarkGray);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("Dropped files:", 100, 40, 20, Color.DarkGray);
|
||||
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
DrawRectangle(0, 85 + 40 * i, screenWidth, 40, ColorAlpha(Color.LightGray, 0.5f));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangle(0, 85 + 40 * i, screenWidth, 40, ColorAlpha(Color.LightGray, 0.3f));
|
||||
}
|
||||
DrawText(files[i], 120, 100 + 40 * i, 10, Color.Gray);
|
||||
}
|
||||
|
||||
DrawText("Drop new files...", 100, 110 + 40 * files.Length, 20, Color.DarkGray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
169
Examples/Core/HighDpiDemo.cs
Normal file
169
Examples/Core/HighDpiDemo.cs
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - highdpi demo
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Jonathan Marler (@marler8997) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Jonathan Marler (@marler8997)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
[ExcludeFromBrowser("monitor/DPI APIs are meaningless on the fixed wasm canvas")]
|
||||
public partial class HighDpiDemo : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / High DPI Demo";
|
||||
|
||||
public string Title => "raylib [core] example - highdpi demo";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.HighDpiWindow | ConfigFlags.ResizableWindow;
|
||||
|
||||
private int logicalGridDescY;
|
||||
private int logicalGridLabelY;
|
||||
private int logicalGridTop;
|
||||
private int logicalGridBottom;
|
||||
private int pixelGridTop;
|
||||
private int pixelGridBottom;
|
||||
private int pixelGridLabelY;
|
||||
private int pixelGridDescY;
|
||||
private int cellSize;
|
||||
private float cellSizePx;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
SetWindowMinSize(450, 450);
|
||||
|
||||
logicalGridDescY = 120;
|
||||
logicalGridLabelY = logicalGridDescY + 30;
|
||||
logicalGridTop = logicalGridLabelY + 30;
|
||||
logicalGridBottom = logicalGridTop + 80;
|
||||
pixelGridTop = logicalGridBottom - 20;
|
||||
pixelGridBottom = pixelGridTop + 80;
|
||||
pixelGridLabelY = pixelGridBottom + 30;
|
||||
pixelGridDescY = pixelGridLabelY + 30;
|
||||
cellSize = 50;
|
||||
cellSizePx = (float)cellSize;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
int monitorCount = GetMonitorCount();
|
||||
|
||||
if ((monitorCount > 1) && IsKeyPressed(KeyboardKey.N))
|
||||
{
|
||||
SetWindowMonitor((GetCurrentMonitor() + 1) % monitorCount);
|
||||
}
|
||||
|
||||
int currentMonitor = GetCurrentMonitor();
|
||||
Vector2 dpiScale = GetWindowScaleDPI();
|
||||
cellSizePx = ((float)cellSize) / dpiScale.X;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
int windowCenter = GetScreenWidth() / 2;
|
||||
DrawTextCenter($"Dpi Scale: {dpiScale.X:F6}", windowCenter, 30, 40, Color.DarkGray);
|
||||
DrawTextCenter($"Monitor: {currentMonitor + 1}/{monitorCount} ([N] next monitor)", windowCenter, 70, 20, Color.LightGray);
|
||||
DrawTextCenter($"Window is {GetScreenWidth()} \"logical points\" wide", windowCenter, logicalGridDescY, 20, Color.Orange);
|
||||
|
||||
bool odd = true;
|
||||
for (int i = cellSize; i < GetScreenWidth(); i += cellSize, odd = !odd)
|
||||
{
|
||||
if (odd)
|
||||
{
|
||||
DrawRectangle(i, logicalGridTop, cellSize, logicalGridBottom - logicalGridTop, Color.Orange);
|
||||
}
|
||||
|
||||
DrawTextCenter($"{i}", i, logicalGridLabelY, 10, Color.LightGray);
|
||||
DrawLine(i, logicalGridLabelY + 10, i, logicalGridBottom, Color.Gray);
|
||||
}
|
||||
|
||||
odd = true;
|
||||
const int minTextSpace = 30;
|
||||
int lastTextX = -minTextSpace;
|
||||
for (int i = cellSize; i < GetRenderWidth(); i += cellSize, odd = !odd)
|
||||
{
|
||||
int x = (int)(((float)i) / dpiScale.X);
|
||||
if (odd)
|
||||
{
|
||||
DrawRectangle(x, pixelGridTop, (int)cellSizePx, pixelGridBottom - pixelGridTop, new Color(0, 121, 241, 100));
|
||||
}
|
||||
|
||||
DrawLine(x, pixelGridTop, (int)(((float)i) / dpiScale.X), pixelGridLabelY - 10, Color.Gray);
|
||||
|
||||
if ((x - lastTextX) >= minTextSpace)
|
||||
{
|
||||
DrawTextCenter($"{i}", x, pixelGridLabelY, 10, Color.LightGray);
|
||||
lastTextX = x;
|
||||
}
|
||||
}
|
||||
|
||||
DrawTextCenter($"Window is {GetRenderWidth()} \"physical pixels\" wide", windowCenter, pixelGridDescY, 20, Color.Blue);
|
||||
|
||||
string text = "Can you see this?";
|
||||
Vector2 size = MeasureTextEx(GetFontDefault(), text, 20, 3);
|
||||
Vector2 pos = new Vector2(GetScreenWidth() - size.X - 5, GetScreenHeight() - size.Y - 5);
|
||||
DrawTextEx(GetFontDefault(), text, pos, 20, 3, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
// Draw text centered on the given position
|
||||
private static void DrawTextCenter(string text, int x, int y, int fontSize, Color color)
|
||||
{
|
||||
Vector2 size = MeasureTextEx(GetFontDefault(), text, (float)fontSize, 3);
|
||||
Vector2 pos = new Vector2(x - size.X / 2, y - size.Y / 2);
|
||||
DrawTextEx(GetFontDefault(), text, pos, (float)fontSize, 3, color);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.HighDpiWindow | ConfigFlags.ResizableWindow);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi demo");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new HighDpiDemo();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
141
Examples/Core/HighDpiTestbed.cs
Normal file
141
Examples/Core/HighDpiTestbed.cs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - highdpi testbed
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Ramon Santamaria (@raysan5) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
[ExcludeFromBrowser("fullscreen/borderless/monitor APIs are meaningless on the fixed wasm canvas")]
|
||||
public partial class HighDpiTestbed : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / High DPI Testbed";
|
||||
|
||||
public string Title => "raylib [core] example - highdpi testbed";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.ResizableWindow | ConfigFlags.HighDpiWindow;
|
||||
|
||||
private Vector2 scaleDpi;
|
||||
private Vector2 mousePos;
|
||||
private int currentMonitor;
|
||||
private Vector2 windowPos;
|
||||
|
||||
private int gridSpacing; // Grid spacing in pixels
|
||||
|
||||
public void Init()
|
||||
{
|
||||
scaleDpi = GetWindowScaleDPI();
|
||||
mousePos = GetMousePosition();
|
||||
currentMonitor = GetCurrentMonitor();
|
||||
windowPos = GetWindowPosition();
|
||||
|
||||
gridSpacing = 40;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
mousePos = GetMousePosition();
|
||||
currentMonitor = GetCurrentMonitor();
|
||||
scaleDpi = GetWindowScaleDPI();
|
||||
windowPos = GetWindowPosition();
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
ToggleBorderlessWindowed();
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.F))
|
||||
{
|
||||
ToggleFullscreen();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw grid
|
||||
for (int h = 0; h < GetScreenHeight() / gridSpacing + 1; h++)
|
||||
{
|
||||
DrawText($"{h * gridSpacing:D2}", 4, h * gridSpacing - 4, 10, Color.Gray);
|
||||
DrawLine(24, h * gridSpacing, GetScreenWidth(), h * gridSpacing, Color.LightGray);
|
||||
}
|
||||
for (int v = 0; v < GetScreenWidth() / gridSpacing + 1; v++)
|
||||
{
|
||||
DrawText($"{v * gridSpacing:D2}", v * gridSpacing - 10, 4, 10, Color.Gray);
|
||||
DrawLine(v * gridSpacing, 20, v * gridSpacing, GetScreenHeight(), Color.LightGray);
|
||||
}
|
||||
|
||||
// Draw UI info
|
||||
DrawText($"CURRENT MONITOR: {currentMonitor + 1}/{GetMonitorCount()} ({GetMonitorWidth(currentMonitor)}x{GetMonitorHeight(currentMonitor)})", 50, 50, 20, Color.DarkGray);
|
||||
DrawText($"WINDOW POSITION: {(int)windowPos.X}x{(int)windowPos.Y}", 50, 90, 20, Color.DarkGray);
|
||||
DrawText($"SCREEN SIZE: {GetScreenWidth()}x{GetScreenHeight()}", 50, 130, 20, Color.DarkGray);
|
||||
DrawText($"RENDER SIZE: {GetRenderWidth()}x{GetRenderHeight()}", 50, 170, 20, Color.DarkGray);
|
||||
DrawText($"SCALE FACTOR: {scaleDpi.X:F2}x{scaleDpi.Y:F2}", 50, 210, 20, Color.Gray);
|
||||
|
||||
// Draw reference rectangles, top-left and bottom-right corners
|
||||
DrawRectangle(0, 0, 30, 60, Color.Red);
|
||||
DrawRectangle(GetScreenWidth() - 30, GetScreenHeight() - 60, 30, 60, Color.Blue);
|
||||
|
||||
// Draw mouse position
|
||||
DrawCircleV(GetMousePosition(), 20, Color.Maroon);
|
||||
DrawRectangleRec(new Rectangle(mousePos.X - 25, mousePos.Y, 50, 2), Color.Black);
|
||||
DrawRectangleRec(new Rectangle(mousePos.X, mousePos.Y - 25, 2, 50), Color.Black);
|
||||
DrawText($"[{GetMouseX()},{GetMouseY()}]", (int)mousePos.X - 44,
|
||||
(mousePos.Y > GetScreenHeight() - 60) ? (int)mousePos.Y - 46 : (int)mousePos.Y + 30, 20, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// TODO: Unload all loaded resources at this point
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.ResizableWindow | ConfigFlags.HighDpiWindow);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new HighDpiTestbed();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
255
Examples/Core/InputActions.cs
Normal file
255
Examples/Core/InputActions.cs
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input actions
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Jett (@JettMonstersGoBoom) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Jett (@JettMonstersGoBoom)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
// Simple example for decoding input as actions, allowing remapping of input to different keys or gamepad buttons
|
||||
// For example instead of using `IsKeyDown(KEY_LEFT)`, you can use `IsActionDown(ACTION_LEFT)`
|
||||
// which can be reassigned to e.g. KEY_A and also assigned to a gamepad button. the action will trigger with either gamepad or keys
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class InputActions : IExample
|
||||
{
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
private enum ActionType
|
||||
{
|
||||
NoAction = 0,
|
||||
ActionUp,
|
||||
ActionDown,
|
||||
ActionLeft,
|
||||
ActionRight,
|
||||
ActionFire,
|
||||
MaxAction
|
||||
}
|
||||
|
||||
// Key and button inputs
|
||||
private struct ActionInput
|
||||
{
|
||||
public KeyboardKey Key;
|
||||
public GamepadButton Button;
|
||||
}
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Input Actions";
|
||||
|
||||
public string Title => "raylib [core] example - input actions";
|
||||
|
||||
private int gamepadIndex; // Gamepad default index
|
||||
private ActionInput[] actionInputs;
|
||||
|
||||
private int actionSet;
|
||||
private bool releaseAction;
|
||||
private Vector2 position;
|
||||
private Vector2 size;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
gamepadIndex = 0;
|
||||
actionInputs = new ActionInput[(int)ActionType.MaxAction];
|
||||
|
||||
// Set default actions
|
||||
actionSet = 0;
|
||||
SetActionsDefault();
|
||||
releaseAction = false;
|
||||
|
||||
position = new Vector2(400.0f, 200.0f);
|
||||
size = new Vector2(40.0f, 40.0f);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
gamepadIndex = 0; // Set gamepad being checked
|
||||
|
||||
if (IsActionDown(ActionType.ActionUp))
|
||||
{
|
||||
position.Y -= 2;
|
||||
}
|
||||
|
||||
if (IsActionDown(ActionType.ActionDown))
|
||||
{
|
||||
position.Y += 2;
|
||||
}
|
||||
|
||||
if (IsActionDown(ActionType.ActionLeft))
|
||||
{
|
||||
position.X -= 2;
|
||||
}
|
||||
|
||||
if (IsActionDown(ActionType.ActionRight))
|
||||
{
|
||||
position.X += 2;
|
||||
}
|
||||
|
||||
if (IsActionPressed(ActionType.ActionFire))
|
||||
{
|
||||
position.X = (screenWidth - size.X) / 2;
|
||||
position.Y = (screenHeight - size.Y) / 2;
|
||||
}
|
||||
|
||||
// Register release action for one frame
|
||||
releaseAction = false;
|
||||
if (IsActionReleased(ActionType.ActionFire))
|
||||
{
|
||||
releaseAction = true;
|
||||
}
|
||||
|
||||
// Switch control scheme by pressing TAB
|
||||
if (IsKeyPressed(KeyboardKey.Tab))
|
||||
{
|
||||
actionSet = (actionSet == 0) ? 1 : 0;
|
||||
if (actionSet == 0)
|
||||
{
|
||||
SetActionsDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActionsCursor();
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.Gray);
|
||||
|
||||
DrawRectangleV(position, size, releaseAction ? Color.Blue : Color.Red);
|
||||
|
||||
DrawText((actionSet == 0) ? "Current input set: WASD (default)" : "Current input set: Arrow keys", 10, 10, 20, Color.White);
|
||||
DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, Color.Green);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Check action key/button pressed
|
||||
// NOTE: Combines key pressed and gamepad button pressed in one action
|
||||
private bool IsActionPressed(ActionType action)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (action < ActionType.MaxAction)
|
||||
{
|
||||
result = (IsKeyPressed(actionInputs[(int)action].Key) || IsGamepadButtonPressed(gamepadIndex, actionInputs[(int)action].Button));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check action key/button released
|
||||
// NOTE: Combines key released and gamepad button released in one action
|
||||
private bool IsActionReleased(ActionType action)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (action < ActionType.MaxAction)
|
||||
{
|
||||
result = (IsKeyReleased(actionInputs[(int)action].Key) || IsGamepadButtonReleased(gamepadIndex, actionInputs[(int)action].Button));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check action key/button down
|
||||
// NOTE: Combines key down and gamepad button down in one action
|
||||
private bool IsActionDown(ActionType action)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (action < ActionType.MaxAction)
|
||||
{
|
||||
result = (IsKeyDown(actionInputs[(int)action].Key) || IsGamepadButtonDown(gamepadIndex, actionInputs[(int)action].Button));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set the "default" keyset
|
||||
// NOTE: Here WASD and gamepad buttons on the left side for movement
|
||||
private void SetActionsDefault()
|
||||
{
|
||||
actionInputs[(int)ActionType.ActionUp].Key = KeyboardKey.W;
|
||||
actionInputs[(int)ActionType.ActionDown].Key = KeyboardKey.S;
|
||||
actionInputs[(int)ActionType.ActionLeft].Key = KeyboardKey.A;
|
||||
actionInputs[(int)ActionType.ActionRight].Key = KeyboardKey.D;
|
||||
actionInputs[(int)ActionType.ActionFire].Key = KeyboardKey.Space;
|
||||
|
||||
actionInputs[(int)ActionType.ActionUp].Button = GamepadButton.LeftFaceUp;
|
||||
actionInputs[(int)ActionType.ActionDown].Button = GamepadButton.LeftFaceDown;
|
||||
actionInputs[(int)ActionType.ActionLeft].Button = GamepadButton.LeftFaceLeft;
|
||||
actionInputs[(int)ActionType.ActionRight].Button = GamepadButton.LeftFaceRight;
|
||||
actionInputs[(int)ActionType.ActionFire].Button = GamepadButton.RightFaceDown;
|
||||
}
|
||||
|
||||
// Set the "alternate" keyset
|
||||
// NOTE: Here cursor keys and gamepad buttons on the right side for movement
|
||||
private void SetActionsCursor()
|
||||
{
|
||||
actionInputs[(int)ActionType.ActionUp].Key = KeyboardKey.Up;
|
||||
actionInputs[(int)ActionType.ActionDown].Key = KeyboardKey.Down;
|
||||
actionInputs[(int)ActionType.ActionLeft].Key = KeyboardKey.Left;
|
||||
actionInputs[(int)ActionType.ActionRight].Key = KeyboardKey.Right;
|
||||
actionInputs[(int)ActionType.ActionFire].Key = KeyboardKey.Space;
|
||||
|
||||
actionInputs[(int)ActionType.ActionUp].Button = GamepadButton.RightFaceUp;
|
||||
actionInputs[(int)ActionType.ActionDown].Button = GamepadButton.RightFaceDown;
|
||||
actionInputs[(int)ActionType.ActionLeft].Button = GamepadButton.RightFaceLeft;
|
||||
actionInputs[(int)ActionType.ActionRight].Button = GamepadButton.RightFaceRight;
|
||||
actionInputs[(int)ActionType.ActionFire].Button = GamepadButton.LeftFaceDown;
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input actions");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputActions();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +1,31 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input gamepad
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* NOTE: This example requires a Gamepad connected to the system
|
||||
* raylib is configured to work with the following gamepads:
|
||||
* - Xbox 360 Controller (Xbox 360, Xbox One)
|
||||
* - PLAYSTATION(R)3 Controller
|
||||
* Check raylib.h for buttons configuration
|
||||
*
|
||||
* Example originally created with raylib 1.1, last time updated with raylib 4.2
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
*
|
||||
* raylib [core] example - input gamepad
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* NOTE: This example requires a Gamepad connected to the system
|
||||
* raylib is configured to work with the following gamepads:
|
||||
* - Xbox 360 Controller (Xbox 360, Xbox One)
|
||||
* - PLAYSTATION(R)3 Controller
|
||||
* Check raylib.h for buttons configuration
|
||||
*
|
||||
* Example originally created with raylib 1.1, last time updated with raylib 4.2
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class InputGamepad
|
||||
public partial class InputGamepad : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// NOTE: Gamepad name ID depends on drivers and OS
|
||||
// These are some possible names the gamepads could have.
|
||||
public const string XBOX_ALIAS_1 = "xbox";
|
||||
|
|
@ -34,320 +33,503 @@ public class InputGamepad
|
|||
public const string PS_ALIAS_1 = "playstation";
|
||||
public const string PS_ALIAS_2 = "sony";
|
||||
|
||||
// Set axis deadzones
|
||||
private const float leftStickDeadzoneX = 0.1f;
|
||||
private const float leftStickDeadzoneY = 0.1f;
|
||||
private const float rightStickDeadzoneX = 0.1f;
|
||||
private const float rightStickDeadzoneY = 0.1f;
|
||||
private const float leftTriggerDeadzone = -0.9f;
|
||||
private const float rightTriggerDeadzone = -0.9f;
|
||||
|
||||
private Texture2D texPs3Pad;
|
||||
private Texture2D texXboxPad;
|
||||
|
||||
private Rectangle vibrateButton;
|
||||
|
||||
private int gamepad; // which gamepad to display
|
||||
|
||||
public string Name => "Core / Input Gamepad";
|
||||
|
||||
public string Title => "raylib [core] example - input gamepad";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
texPs3Pad = LoadTexture("resources/ps3.png");
|
||||
texXboxPad = LoadTexture("resources/xbox.png");
|
||||
|
||||
vibrateButton = new Rectangle();
|
||||
|
||||
gamepad = 0; // which gamepad to display
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Left) && gamepad > 0)
|
||||
{
|
||||
gamepad--;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
gamepad++;
|
||||
}
|
||||
|
||||
var mousePosition = GetMousePosition();
|
||||
|
||||
vibrateButton = new Rectangle(10, 70.0f + 20 * GetGamepadAxisCount(gamepad) + 20, 75, 24);
|
||||
if (IsMouseButtonPressed(MouseButton.Left) && CheckCollisionPointRec(mousePosition, vibrateButton))
|
||||
{
|
||||
SetGamepadVibration(gamepad, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (IsGamepadAvailable(gamepad))
|
||||
{
|
||||
var gamepadName = GetGamepadName_(gamepad);
|
||||
DrawText($"GP{gamepad}: {gamepadName}", 10, 10, 10, Color.Black);
|
||||
|
||||
// Get axis values
|
||||
var leftStickX = GetGamepadAxisMovement(gamepad, GamepadAxis.LeftX);
|
||||
var leftStickY = GetGamepadAxisMovement(gamepad, GamepadAxis.LeftY);
|
||||
var rightStickX = GetGamepadAxisMovement(gamepad, GamepadAxis.RightX);
|
||||
var rightStickY = GetGamepadAxisMovement(gamepad, GamepadAxis.RightY);
|
||||
var leftTrigger = GetGamepadAxisMovement(gamepad, GamepadAxis.LeftTrigger);
|
||||
var rightTrigger = GetGamepadAxisMovement(gamepad, GamepadAxis.RightTrigger);
|
||||
|
||||
// Calculate deadzones
|
||||
if (leftStickX > -leftStickDeadzoneX && leftStickX < leftStickDeadzoneX)
|
||||
{
|
||||
leftStickX = 0.0f;
|
||||
}
|
||||
|
||||
if (leftStickY > -leftStickDeadzoneY && leftStickY < leftStickDeadzoneY)
|
||||
{
|
||||
leftStickY = 0.0f;
|
||||
}
|
||||
|
||||
if (rightStickX > -rightStickDeadzoneX && rightStickX < rightStickDeadzoneX)
|
||||
{
|
||||
rightStickX = 0.0f;
|
||||
}
|
||||
|
||||
if (rightStickY > -rightStickDeadzoneY && rightStickY < rightStickDeadzoneY)
|
||||
{
|
||||
rightStickY = 0.0f;
|
||||
}
|
||||
|
||||
if (leftTrigger < leftTriggerDeadzone)
|
||||
{
|
||||
leftTrigger = -1.0f;
|
||||
}
|
||||
|
||||
if (rightTrigger < rightTriggerDeadzone)
|
||||
{
|
||||
rightTrigger = -1.0f;
|
||||
}
|
||||
|
||||
if (gamepadName.Contains(XBOX_ALIAS_1, StringComparison.OrdinalIgnoreCase) ||
|
||||
gamepadName.Contains(XBOX_ALIAS_2, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DrawTexture(texXboxPad, 0, 0, Color.DarkGray);
|
||||
|
||||
// Draw buttons: xbox home
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.Middle))
|
||||
{
|
||||
DrawCircle(394, 89, 19, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleRight))
|
||||
{
|
||||
DrawCircle(436, 150, 9, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleLeft))
|
||||
{
|
||||
DrawCircle(352, 150, 9, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceLeft))
|
||||
{
|
||||
DrawCircle(501, 151, 15, Color.Blue);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceDown))
|
||||
{
|
||||
DrawCircle(536, 187, 15, Color.Lime);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceRight))
|
||||
{
|
||||
DrawCircle(572, 151, 15, Color.Maroon);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceUp))
|
||||
{
|
||||
DrawCircle(536, 115, 15, Color.Gold);
|
||||
}
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(317, 202, 19, 71, Color.Black);
|
||||
DrawRectangle(293, 228, 69, 19, Color.Black);
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceUp))
|
||||
{
|
||||
DrawRectangle(317, 202, 19, 26, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceDown))
|
||||
{
|
||||
DrawRectangle(317, 202 + 45, 19, 26, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceLeft))
|
||||
{
|
||||
DrawRectangle(292, 228, 25, 19, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceRight))
|
||||
{
|
||||
DrawRectangle(292 + 44, 228, 26, 19, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: left-right back
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftTrigger1))
|
||||
{
|
||||
DrawCircle(259, 61, 20, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightTrigger1))
|
||||
{
|
||||
DrawCircle(536, 61, 20, Color.Red);
|
||||
}
|
||||
|
||||
// Draw axis: left joystick
|
||||
var leftGamepadColor = Color.Black;
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftThumb))
|
||||
{
|
||||
leftGamepadColor = Color.Red;
|
||||
}
|
||||
|
||||
DrawCircle(259, 152, 39, Color.Black);
|
||||
DrawCircle(259, 152, 34, Color.LightGray);
|
||||
DrawCircle(259 + (int)(leftStickX * 20), 152 + (int)(leftStickY * 20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
var rightGamepadColor = Color.Black;
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightThumb))
|
||||
{
|
||||
rightGamepadColor = Color.Red;
|
||||
}
|
||||
|
||||
DrawCircle(461, 237, 38, Color.Black);
|
||||
DrawCircle(461, 237, 33, Color.LightGray);
|
||||
DrawCircle(461 + (int)(rightStickX * 20), 237 + (int)(rightStickY * 20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(170, 30, 15, 70, Color.Gray);
|
||||
DrawRectangle(604, 30, 15, 70, Color.Gray);
|
||||
DrawRectangle(170, 30, 15, (int)(((1 + leftTrigger) / 2) * 70), Color.Red);
|
||||
DrawRectangle(604, 30, 15, (int)(((1 + rightTrigger) / 2) * 70), Color.Red);
|
||||
}
|
||||
else if (gamepadName.Contains(PS_ALIAS_1, StringComparison.OrdinalIgnoreCase) || gamepadName.Contains(PS_ALIAS_2, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DrawTexture(texPs3Pad, 0, 0, Color.DarkGray);
|
||||
|
||||
// Draw buttons: ps
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.Middle))
|
||||
{
|
||||
DrawCircle(396, 222, 13, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleLeft))
|
||||
{
|
||||
DrawRectangle(328, 170, 32, 13, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleRight))
|
||||
{
|
||||
DrawTriangle(
|
||||
new Vector2(436, 168),
|
||||
new Vector2(436, 185),
|
||||
new Vector2(464, 177),
|
||||
Color.Red
|
||||
);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceUp))
|
||||
{
|
||||
DrawCircle(557, 144, 13, Color.Lime);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceRight))
|
||||
{
|
||||
DrawCircle(586, 173, 13, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceDown))
|
||||
{
|
||||
DrawCircle(557, 203, 13, Color.Violet);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceLeft))
|
||||
{
|
||||
DrawCircle(527, 173, 13, Color.Pink);
|
||||
}
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(225, 132, 24, 84, Color.Black);
|
||||
DrawRectangle(195, 161, 84, 25, Color.Black);
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceUp))
|
||||
{
|
||||
DrawRectangle(225, 132, 24, 29, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceDown))
|
||||
{
|
||||
DrawRectangle(225, 132 + 54, 24, 30, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceLeft))
|
||||
{
|
||||
DrawRectangle(195, 161, 30, 25, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceRight))
|
||||
{
|
||||
DrawRectangle(195 + 54, 161, 30, 25, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: left-right back buttons
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftTrigger1))
|
||||
{
|
||||
DrawCircle(239, 82, 20, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightTrigger1))
|
||||
{
|
||||
DrawCircle(557, 82, 20, Color.Red);
|
||||
}
|
||||
|
||||
// Draw axis: left joystick
|
||||
var leftGamepadColor = Color.Black;
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftThumb))
|
||||
{
|
||||
leftGamepadColor = Color.Red;
|
||||
}
|
||||
|
||||
DrawCircle(319, 255, 35, Color.Black);
|
||||
DrawCircle(319, 255, 31, Color.LightGray);
|
||||
DrawCircle(319 + (int)(leftStickX * 20), 255 + (int)(leftStickY * 20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
var rightGamepadColor = Color.Black;
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightThumb))
|
||||
{
|
||||
rightGamepadColor = Color.Red;
|
||||
}
|
||||
|
||||
DrawCircle(475, 255, 35, Color.Black);
|
||||
DrawCircle(475, 255, 31, Color.LightGray);
|
||||
DrawCircle(475 + (int)(rightStickX * 20), 255 + (int)(rightStickY * 20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(169, 48, 15, 70, Color.Gray);
|
||||
DrawRectangle(611, 48, 15, 70, Color.Gray);
|
||||
DrawRectangle(169, 48, 15, (int)(((1 + leftTrigger) / 2) * 70), Color.Red);
|
||||
DrawRectangle(611, 48, 15, (int)(((1 + rightTrigger) / 2) * 70), Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw background: generic
|
||||
DrawRectangleRounded(new Rectangle(175, 110, 460, 220), 0.3f, 16, Color.DarkGray);
|
||||
|
||||
// Draw buttons: basic
|
||||
DrawCircle(365, 170, 12, Color.RayWhite);
|
||||
DrawCircle(405, 170, 12, Color.RayWhite);
|
||||
DrawCircle(445, 170, 12, Color.RayWhite);
|
||||
DrawCircle(516, 191, 17, Color.RayWhite);
|
||||
DrawCircle(551, 227, 17, Color.RayWhite);
|
||||
DrawCircle(587, 191, 17, Color.RayWhite);
|
||||
DrawCircle(551, 155, 17, Color.RayWhite);
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleLeft))
|
||||
{
|
||||
DrawCircle(365, 170, 10, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.Middle))
|
||||
{
|
||||
DrawCircle(405, 170, 10, Color.Green);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleRight))
|
||||
{
|
||||
DrawCircle(445, 170, 10, Color.Blue);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceLeft))
|
||||
{
|
||||
DrawCircle(516, 191, 15, Color.Gold);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceDown))
|
||||
{
|
||||
DrawCircle(551, 227, 15, Color.Blue);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceRight))
|
||||
{
|
||||
DrawCircle(587, 191, 15, Color.Green);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceUp))
|
||||
{
|
||||
DrawCircle(551, 155, 15, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(245, 145, 28, 88, Color.RayWhite);
|
||||
DrawRectangle(215, 174, 88, 29, Color.RayWhite);
|
||||
DrawRectangle(247, 147, 24, 84, Color.Black);
|
||||
DrawRectangle(217, 176, 84, 25, Color.Black);
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceUp))
|
||||
{
|
||||
DrawRectangle(247, 147, 24, 29, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceDown))
|
||||
{
|
||||
DrawRectangle(247, 147 + 54, 24, 30, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceLeft))
|
||||
{
|
||||
DrawRectangle(217, 176, 30, 25, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceRight))
|
||||
{
|
||||
DrawRectangle(217 + 54, 176, 30, 25, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: left-right back
|
||||
DrawRectangleRounded(new Rectangle(215, 98, 100, 10), 0.5f, 16, Color.DarkGray);
|
||||
DrawRectangleRounded(new Rectangle(495, 98, 100, 10), 0.5f, 16, Color.DarkGray);
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftTrigger1))
|
||||
{
|
||||
DrawRectangleRounded(new Rectangle(215, 98, 100, 10), 0.5f, 16, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightTrigger1))
|
||||
{
|
||||
DrawRectangleRounded(new Rectangle(495, 98, 100, 10), 0.5f, 16, Color.Red);
|
||||
}
|
||||
|
||||
// Draw axis: left joystick
|
||||
var leftGamepadColor = Color.Black;
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftThumb))
|
||||
{
|
||||
leftGamepadColor = Color.Red;
|
||||
}
|
||||
|
||||
DrawCircle(345, 260, 40, Color.Black);
|
||||
DrawCircle(345, 260, 35, Color.LightGray);
|
||||
DrawCircle(345 + (int)(leftStickX * 20), 260 + (int)(leftStickY * 20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
var rightGamepadColor = Color.Black;
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightThumb))
|
||||
{
|
||||
rightGamepadColor = Color.Red;
|
||||
}
|
||||
|
||||
DrawCircle(465, 260, 40, Color.Black);
|
||||
DrawCircle(465, 260, 35, Color.LightGray);
|
||||
DrawCircle(465 + (int)(rightStickX * 20), 260 + (int)(rightStickY * 20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(151, 110, 15, 70, Color.Gray);
|
||||
DrawRectangle(644, 110, 15, 70, Color.Gray);
|
||||
DrawRectangle(151, 110, 15, (int)(((1 + leftTrigger) / 2) * 70), Color.Red);
|
||||
DrawRectangle(644, 110, 15, (int)(((1 + rightTrigger) / 2) * 70), Color.Red);
|
||||
}
|
||||
|
||||
DrawText($"DETECTED AXIS [{GetGamepadAxisCount(gamepad)}]:", 10, 50, 10, Color.Maroon);
|
||||
|
||||
for (var i = 0; i < GetGamepadAxisCount(gamepad); i++)
|
||||
{
|
||||
DrawText(
|
||||
$"AXIS {i}: {GetGamepadAxisMovement(gamepad, (GamepadAxis)i):F2}",
|
||||
20,
|
||||
70 + 20 * i,
|
||||
10,
|
||||
Color.DarkGray
|
||||
);
|
||||
}
|
||||
|
||||
// Draw vibrate button
|
||||
DrawRectangleRec(vibrateButton, Color.SkyBlue);
|
||||
DrawText("VIBRATE", (int)(vibrateButton.X + 14), (int)(vibrateButton.Y + 1), 10, Color.DarkGray);
|
||||
|
||||
if (GetGamepadButtonPressed() != (int)GamepadButton.Unknown)
|
||||
{
|
||||
DrawText($"DETECTED BUTTON: {GetGamepadButtonPressed()}", 10, 430, 10, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("DETECTED BUTTON: NONE", 10, 430, 10, Color.Gray);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText($"GP{gamepad}: NOT DETECTED", 10, 10, 10, Color.Gray);
|
||||
DrawTexture(texXboxPad, 0, 0, Color.LightGray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadTexture(texPs3Pad);
|
||||
UnloadTexture(texXboxPad);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint); // Set MSAA 4X hint before windows creation
|
||||
|
||||
// Set MSAA 4X hint before windows creation
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad input");
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gamepad");
|
||||
|
||||
Texture2D texPs3Pad = LoadTexture("resources/ps3.png");
|
||||
Texture2D texXboxPad = LoadTexture("resources/xbox.png");
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
int gamepad = 0;
|
||||
Rectangle vibrateButton = new Rectangle();
|
||||
var game = new InputGamepad();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Left) && gamepad > 0)
|
||||
{
|
||||
gamepad--;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
gamepad++;
|
||||
}
|
||||
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
|
||||
vibrateButton = new Rectangle(10, 70.0f + 20 * GetGamepadAxisCount(gamepad) + 20, 75, 24);
|
||||
if (IsMouseButtonPressed(MouseButton.Left) && CheckCollisionPointRec(mousePosition, vibrateButton))
|
||||
{
|
||||
SetGamepadVibration(gamepad, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (IsGamepadAvailable(gamepad))
|
||||
{
|
||||
string gamepadName = GetGamepadName_(gamepad);
|
||||
DrawText($"GP{gamepad}: {gamepadName}", 10, 10, 10, Color.Black);
|
||||
|
||||
if (gamepadName.Contains(XBOX_ALIAS_1, StringComparison.OrdinalIgnoreCase) ||
|
||||
gamepadName.Contains(XBOX_ALIAS_2, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DrawTexture(texXboxPad, 0, 0, Color.DarkGray);
|
||||
|
||||
// Draw buttons: xbox home
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.Middle))
|
||||
{
|
||||
DrawCircle(394, 89, 19, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleRight))
|
||||
{
|
||||
DrawCircle(436, 150, 9, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleLeft))
|
||||
{
|
||||
DrawCircle(352, 150, 9, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceLeft))
|
||||
{
|
||||
DrawCircle(501, 151, 15, Color.Blue);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceDown))
|
||||
{
|
||||
DrawCircle(536, 187, 15, Color.Lime);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceRight))
|
||||
{
|
||||
DrawCircle(572, 151, 15, Color.Maroon);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceUp))
|
||||
{
|
||||
DrawCircle(536, 115, 15, Color.Gold);
|
||||
}
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(317, 202, 19, 71, Color.Black);
|
||||
DrawRectangle(293, 228, 69, 19, Color.Black);
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceUp))
|
||||
{
|
||||
DrawRectangle(317, 202, 19, 26, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceDown))
|
||||
{
|
||||
DrawRectangle(317, 202 + 45, 19, 26, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceLeft))
|
||||
{
|
||||
DrawRectangle(292, 228, 25, 19, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceRight))
|
||||
{
|
||||
DrawRectangle(292 + 44, 228, 26, 19, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: left-right back
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftTrigger1))
|
||||
{
|
||||
DrawCircle(259, 61, 20, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightTrigger1))
|
||||
{
|
||||
DrawCircle(536, 61, 20, Color.Red);
|
||||
}
|
||||
|
||||
// Draw axis: left joystick
|
||||
DrawCircle(259, 152, 39, Color.Black);
|
||||
DrawCircle(259, 152, 34, Color.LightGray);
|
||||
DrawCircle(
|
||||
259 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftX) * 20),
|
||||
152 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftY) * 20),
|
||||
25,
|
||||
Color.Black
|
||||
);
|
||||
|
||||
// Draw axis: right joystick
|
||||
DrawCircle(461, 237, 38, Color.Black);
|
||||
DrawCircle(461, 237, 33, Color.LightGray);
|
||||
DrawCircle(
|
||||
461 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightX) * 20),
|
||||
237 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightY) * 20),
|
||||
25, Color.Black
|
||||
);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
float leftTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.LeftTrigger);
|
||||
float rightTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.RightTrigger);
|
||||
DrawRectangle(170, 30, 15, 70, Color.Gray);
|
||||
DrawRectangle(604, 30, 15, 70, Color.Gray);
|
||||
DrawRectangle(170, 30, 15, (int)(((1.0f + leftTriggerX) / 2.0f) * 70), Color.Red);
|
||||
DrawRectangle(604, 30, 15, (int)(((1.0f + rightTriggerX) / 2.0f) * 70), Color.Red);
|
||||
}
|
||||
else if (gamepadName.Contains(PS_ALIAS_1, StringComparison.OrdinalIgnoreCase) || gamepadName.Contains(PS_ALIAS_2, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DrawTexture(texPs3Pad, 0, 0, Color.DarkGray);
|
||||
|
||||
// Draw buttons: ps
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.Middle))
|
||||
{
|
||||
DrawCircle(396, 222, 13, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleLeft))
|
||||
{
|
||||
DrawRectangle(328, 170, 32, 13, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.MiddleRight))
|
||||
{
|
||||
DrawTriangle(
|
||||
new Vector2(436, 168),
|
||||
new Vector2(436, 185),
|
||||
new Vector2(464, 177),
|
||||
Color.Red
|
||||
);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceUp))
|
||||
{
|
||||
DrawCircle(557, 144, 13, Color.Lime);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceRight))
|
||||
{
|
||||
DrawCircle(586, 173, 13, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceDown))
|
||||
{
|
||||
DrawCircle(557, 203, 13, Color.Violet);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightFaceLeft))
|
||||
{
|
||||
DrawCircle(527, 173, 13, Color.Pink);
|
||||
}
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(225, 132, 24, 84, Color.Black);
|
||||
DrawRectangle(195, 161, 84, 25, Color.Black);
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceUp))
|
||||
{
|
||||
DrawRectangle(225, 132, 24, 29, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceDown))
|
||||
{
|
||||
DrawRectangle(225, 132 + 54, 24, 30, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceLeft))
|
||||
{
|
||||
DrawRectangle(195, 161, 30, 25, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftFaceRight))
|
||||
{
|
||||
DrawRectangle(195 + 54, 161, 30, 25, Color.Red);
|
||||
}
|
||||
|
||||
// Draw buttons: left-right back buttons
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.LeftTrigger1))
|
||||
{
|
||||
DrawCircle(239, 82, 20, Color.Red);
|
||||
}
|
||||
|
||||
if (IsGamepadButtonDown(gamepad, GamepadButton.RightTrigger1))
|
||||
{
|
||||
DrawCircle(557, 82, 20, Color.Red);
|
||||
}
|
||||
|
||||
// Draw axis: left joystick
|
||||
DrawCircle(319, 255, 35, Color.Black);
|
||||
DrawCircle(319, 255, 31, Color.LightGray);
|
||||
DrawCircle(
|
||||
319 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftX) * 20),
|
||||
255 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.LeftY) * 20),
|
||||
25,
|
||||
Color.Black
|
||||
);
|
||||
|
||||
// Draw axis: right joystick
|
||||
DrawCircle(475, 255, 35, Color.Black);
|
||||
DrawCircle(475, 255, 31, Color.LightGray);
|
||||
DrawCircle(
|
||||
475 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightX) * 20),
|
||||
255 + (int)(GetGamepadAxisMovement(gamepad, GamepadAxis.RightY) * 20),
|
||||
25,
|
||||
Color.Black
|
||||
);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
float leftTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.LeftTrigger);
|
||||
float rightTriggerX = GetGamepadAxisMovement(gamepad, GamepadAxis.RightTrigger);
|
||||
DrawRectangle(169, 48, 15, 70, Color.Gray);
|
||||
DrawRectangle(611, 48, 15, 70, Color.Gray);
|
||||
DrawRectangle(169, 48, 15, (int)(((1.0f - leftTriggerX) / 2.0f) * 70), Color.Red);
|
||||
DrawRectangle(611, 48, 15, (int)(((1.0f - rightTriggerX) / 2.0f) * 70), Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("- GENERIC GAMEPAD -", 280, 180, 20, Color.Gray);
|
||||
// TODO: Draw generic gamepad
|
||||
}
|
||||
|
||||
DrawText($"DETECTED AXIS [{GetGamepadAxisCount(gamepad)}]:", 10, 50, 10, Color.Maroon);
|
||||
|
||||
for (int i = 0; i < GetGamepadAxisCount(gamepad); i++)
|
||||
{
|
||||
DrawText(
|
||||
$"AXIS {i}: {GetGamepadAxisMovement(gamepad, (GamepadAxis)i)}",
|
||||
20,
|
||||
70 + 20 * i,
|
||||
10,
|
||||
Color.DarkGray
|
||||
);
|
||||
}
|
||||
|
||||
DrawRectangleRec(vibrateButton, Color.SkyBlue);
|
||||
DrawText("VIBRATE", (int)(vibrateButton.X + 14), (int)(vibrateButton.Y + 1), 10, Color.DarkGray);
|
||||
|
||||
|
||||
if (GetGamepadButtonPressed() != (int)GamepadButton.Unknown)
|
||||
{
|
||||
DrawText($"DETECTED BUTTON: {GetGamepadButtonPressed()}", 10, 430, 10, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("DETECTED BUTTON: NONE", 10, 430, 10, Color.Gray);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText($"GP{gamepad}: NOT DETECTED", 10, 10, 10, Color.Gray);
|
||||
DrawTexture(texXboxPad, 0, 0, Color.LightGray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(texPs3Pad);
|
||||
UnloadTexture(texXboxPad);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -13,150 +13,178 @@
|
|||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class InputGestures
|
||||
public partial class InputGestures : IExample
|
||||
{
|
||||
public const int MaxGestureStrings = 20;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private Vector2 touchPosition;
|
||||
private Rectangle touchArea;
|
||||
|
||||
private int gesturesCount;
|
||||
private string[] gestureStrings;
|
||||
|
||||
private Gesture currentGesture;
|
||||
private Gesture lastGesture;
|
||||
|
||||
public string Name => "Core / Input Gestures";
|
||||
|
||||
public string Title => "raylib [core] example - input gestures";
|
||||
|
||||
public void Init()
|
||||
{
|
||||
touchPosition = new(0, 0);
|
||||
touchArea = new(220, 10, screenWidth - 230, screenHeight - 20);
|
||||
|
||||
gesturesCount = 0;
|
||||
gestureStrings = new string[MaxGestureStrings];
|
||||
|
||||
currentGesture = Gesture.None;
|
||||
lastGesture = Gesture.None;
|
||||
|
||||
// SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
lastGesture = currentGesture;
|
||||
currentGesture = GetGestureDetected();
|
||||
touchPosition = GetTouchPosition(0);
|
||||
|
||||
if (CheckCollisionPointRec(touchPosition, touchArea) && (currentGesture != Gesture.None))
|
||||
{
|
||||
if (currentGesture != lastGesture)
|
||||
{
|
||||
// Store gesture string
|
||||
switch ((Gesture)currentGesture)
|
||||
{
|
||||
case Gesture.Tap:
|
||||
gestureStrings[gesturesCount] = "GESTURE TAP";
|
||||
break;
|
||||
case Gesture.DoubleTap:
|
||||
gestureStrings[gesturesCount] = "GESTURE DOUBLETAP";
|
||||
break;
|
||||
case Gesture.Hold:
|
||||
gestureStrings[gesturesCount] = "GESTURE HOLD";
|
||||
break;
|
||||
case Gesture.Drag:
|
||||
gestureStrings[gesturesCount] = "GESTURE DRAG";
|
||||
break;
|
||||
case Gesture.SwipeRight:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE RIGHT";
|
||||
break;
|
||||
case Gesture.SwipeLeft:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE LEFT";
|
||||
break;
|
||||
case Gesture.SwipeUp:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE UP";
|
||||
break;
|
||||
case Gesture.SwipeDown:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE DOWN";
|
||||
break;
|
||||
case Gesture.PinchIn:
|
||||
gestureStrings[gesturesCount] = "GESTURE PINCH IN";
|
||||
break;
|
||||
case Gesture.PinchOut:
|
||||
gestureStrings[gesturesCount] = "GESTURE PINCH OUT";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gesturesCount++;
|
||||
|
||||
// Reset gestures strings
|
||||
if (gesturesCount >= MaxGestureStrings)
|
||||
{
|
||||
for (var i = 0; i < MaxGestureStrings; i++)
|
||||
{
|
||||
gestureStrings[i] = " ";
|
||||
}
|
||||
gesturesCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawRectangleRec(touchArea, Color.Gray);
|
||||
DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, Color.RayWhite);
|
||||
|
||||
DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(Color.Gray, 0.5f));
|
||||
|
||||
for (var i = 0; i < gesturesCount; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
DrawRectangle(10, 30 + 20 * i, 200, 20, Fade(Color.LightGray, 0.5f));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangle(10, 30 + 20 * i, 200, 20, Fade(Color.LightGray, 0.3f));
|
||||
}
|
||||
|
||||
if (i < gesturesCount - 1)
|
||||
{
|
||||
DrawText(gestureStrings[i], 35, 36 + 20 * i, 10, Color.DarkGray);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText(gestureStrings[i], 35, 36 + 20 * i, 10, Color.Maroon);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleLines(10, 29, 200, screenHeight - 50, Color.Gray);
|
||||
DrawText("DETECTED GESTURES", 50, 15, 10, Color.Gray);
|
||||
|
||||
if (currentGesture != Gesture.None)
|
||||
{
|
||||
DrawCircleV(touchPosition, 30, Color.Maroon);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures");
|
||||
|
||||
Vector2 touchPosition = new(0, 0);
|
||||
Rectangle touchArea = new(220, 10, screenWidth - 230, screenHeight - 20);
|
||||
|
||||
int gesturesCount = 0;
|
||||
string[] gestureStrings = new string[MaxGestureStrings];
|
||||
|
||||
Gesture currentGesture = Gesture.None;
|
||||
Gesture lastGesture = Gesture.None;
|
||||
|
||||
// SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputGestures();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
lastGesture = currentGesture;
|
||||
currentGesture = GetGestureDetected();
|
||||
touchPosition = GetTouchPosition(0);
|
||||
|
||||
if (CheckCollisionPointRec(touchPosition, touchArea) && (currentGesture != Gesture.None))
|
||||
{
|
||||
if (currentGesture != lastGesture)
|
||||
{
|
||||
// Store gesture string
|
||||
switch ((Gesture)currentGesture)
|
||||
{
|
||||
case Gesture.Tap:
|
||||
gestureStrings[gesturesCount] = "GESTURE TAP";
|
||||
break;
|
||||
case Gesture.DoubleTap:
|
||||
gestureStrings[gesturesCount] = "GESTURE DOUBLETAP";
|
||||
break;
|
||||
case Gesture.Hold:
|
||||
gestureStrings[gesturesCount] = "GESTURE HOLD";
|
||||
break;
|
||||
case Gesture.Drag:
|
||||
gestureStrings[gesturesCount] = "GESTURE DRAG";
|
||||
break;
|
||||
case Gesture.SwipeRight:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE RIGHT";
|
||||
break;
|
||||
case Gesture.SwipeLeft:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE LEFT";
|
||||
break;
|
||||
case Gesture.SwipeUp:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE UP";
|
||||
break;
|
||||
case Gesture.SwipeDown:
|
||||
gestureStrings[gesturesCount] = "GESTURE SWIPE DOWN";
|
||||
break;
|
||||
case Gesture.PinchIn:
|
||||
gestureStrings[gesturesCount] = "GESTURE PINCH IN";
|
||||
break;
|
||||
case Gesture.PinchOut:
|
||||
gestureStrings[gesturesCount] = "GESTURE PINCH OUT";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gesturesCount++;
|
||||
|
||||
// Reset gestures strings
|
||||
if (gesturesCount >= MaxGestureStrings)
|
||||
{
|
||||
for (int i = 0; i < MaxGestureStrings; i++)
|
||||
{
|
||||
gestureStrings[i] = " ";
|
||||
}
|
||||
gesturesCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawRectangleRec(touchArea, Color.Gray);
|
||||
DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, Color.RayWhite);
|
||||
|
||||
DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, ColorAlpha(Color.Gray, 0.5f));
|
||||
|
||||
for (int i = 0; i < gesturesCount; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
DrawRectangle(10, 30 + 20 * i, 200, 20, ColorAlpha(Color.LightGray, 0.5f));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangle(10, 30 + 20 * i, 200, 20, ColorAlpha(Color.LightGray, 0.3f));
|
||||
}
|
||||
|
||||
if (i < gesturesCount - 1)
|
||||
{
|
||||
DrawText(gestureStrings[i], 35, 36 + 20 * i, 10, Color.DarkGray);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText(gestureStrings[i], 35, 36 + 20 * i, 10, Color.Maroon);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleLines(10, 29, 200, screenHeight - 50, Color.Gray);
|
||||
DrawText("DETECTED GESTURES", 50, 15, 10, Color.Gray);
|
||||
|
||||
if (currentGesture != Gesture.None)
|
||||
{
|
||||
DrawCircleV(touchPosition, 30, Color.Maroon);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,406 +1,450 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input gestures testbed
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by ubkp (@ubkp) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2023-2025 ubkp (@ubkp)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
*
|
||||
* raylib [core] example - input gestures testbed
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by ubkp (@ubkp) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2023-2025 ubkp (@ubkp)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
public class InputGesturesTestBed
|
||||
public partial class InputGesturesTestBed : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public const int GESTURE_LOG_SIZE = 20;
|
||||
public const int MAX_TOUCH_COUNT = 32;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
public string Name => "Core / Input Gestures Test Bed";
|
||||
|
||||
public static int Main()
|
||||
public string Title => "raylib [core] example - input gestures testbed";
|
||||
|
||||
private Vector2 messagePosition;
|
||||
|
||||
// Last gesture variables definitions
|
||||
private Gesture lastGesture;
|
||||
private Vector2 lastGesturePosition;
|
||||
|
||||
// Gesture log variables definitions
|
||||
// NOTE: The gesture log uses an array (as an inverted circular queue) to store the performed gestures
|
||||
private string[] gestureLog;
|
||||
|
||||
// NOTE: The index for the inverted circular queue (moving from last to first direction, then looping around)
|
||||
private int gestureLogIndex;
|
||||
private Gesture previousGesture;
|
||||
|
||||
// Log mode values:
|
||||
// - 0 shows repeated events
|
||||
// - 1 hides repeated events
|
||||
// - 2 shows repeated events but hide hold events
|
||||
// - 3 hides repeated events and hide hold events
|
||||
private int logMode;
|
||||
|
||||
private Color gestureColor;
|
||||
private Rectangle logButton1;
|
||||
private Rectangle logButton2;
|
||||
private Vector2 gestureLogPosition;
|
||||
|
||||
// Protractor variables definitions
|
||||
private float angleLength;
|
||||
private float currentAngleDegrees;
|
||||
private Vector2 finalVector;
|
||||
private Vector2 protractorPosition;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures testbed");
|
||||
|
||||
Vector2 messagePosition = new Vector2(160, 7);
|
||||
messagePosition = new Vector2(160, 7);
|
||||
|
||||
// Last gesture variables definitions
|
||||
Gesture lastGesture = 0;
|
||||
Vector2 lastGesturePosition = new Vector2(165, 130);
|
||||
lastGesture = 0;
|
||||
lastGesturePosition = new Vector2(165, 130);
|
||||
|
||||
// Gesture log variables definitions
|
||||
// NOTE: The gesture log uses an array (as an inverted circular queue) to store the performed gestures
|
||||
string[] gestureLog = new string[GESTURE_LOG_SIZE + 1];
|
||||
for (int i = 0; i < GESTURE_LOG_SIZE; i++)
|
||||
gestureLog = new string[GESTURE_LOG_SIZE + 1];
|
||||
for (var i = 0; i < GESTURE_LOG_SIZE; i++)
|
||||
{
|
||||
gestureLog[i] = new string(new char[12]);
|
||||
}
|
||||
;
|
||||
|
||||
// NOTE: The index for the inverted circular queue (moving from last to first direction, then looping around)
|
||||
int gestureLogIndex = GESTURE_LOG_SIZE;
|
||||
Gesture previousGesture = 0;
|
||||
gestureLogIndex = GESTURE_LOG_SIZE;
|
||||
previousGesture = 0;
|
||||
|
||||
// Log mode values:
|
||||
// - 0 shows repeated events
|
||||
// - 1 hides repeated events
|
||||
// - 2 shows repeated events but hide hold events
|
||||
// - 3 hides repeated events and hide hold events
|
||||
int logMode = 1;
|
||||
logMode = 1;
|
||||
|
||||
Color gestureColor = new Color(0, 0, 0, 255);
|
||||
Rectangle logButton1 = new Rectangle(53, 7, 48, 26);
|
||||
Rectangle logButton2 = new Rectangle(108, 7, 36, 26);
|
||||
Vector2 gestureLogPosition = new Vector2(10, 10);
|
||||
gestureColor = new Color(0, 0, 0, 255);
|
||||
logButton1 = new Rectangle(53, 7, 48, 26);
|
||||
logButton2 = new Rectangle(108, 7, 36, 26);
|
||||
gestureLogPosition = new Vector2(10, 10);
|
||||
|
||||
// Protractor variables definitions
|
||||
float angleLength = 90.0f;
|
||||
float currentAngleDegrees = 0.0f;
|
||||
Vector2 finalVector = new Vector2(0.0f, 0.0f);
|
||||
Vector2 protractorPosition = new Vector2(266.0f, 315.0f);
|
||||
angleLength = 90.0f;
|
||||
currentAngleDegrees = 0.0f;
|
||||
finalVector = new Vector2(0.0f, 0.0f);
|
||||
protractorPosition = new Vector2(266.0f, 315.0f);
|
||||
}
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Handle common gestures data
|
||||
int i, ii; // Iterators that will be reused by all for loops
|
||||
var currentGesture = GetGestureDetected();
|
||||
var currentDragDegrees = GetGestureDragAngle();
|
||||
var currentPitchDegrees = GetGesturePinchAngle();
|
||||
var touchCount = GetTouchPointCount();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
// Handle last gesture
|
||||
if ((currentGesture != 0) && ((int)currentGesture != 4) && (currentGesture != previousGesture))
|
||||
{
|
||||
// Update
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Handle common gestures data
|
||||
int i, ii; // Iterators that will be reused by all for loops
|
||||
Gesture currentGesture = GetGestureDetected();
|
||||
float currentDragDegrees = GetGestureDragAngle();
|
||||
float currentPitchDegrees = GetGesturePinchAngle();
|
||||
int touchCount = GetTouchPointCount();
|
||||
lastGesture = currentGesture; // Filter the meaningful gestures (1, 2, 8 to 512) for the display
|
||||
}
|
||||
|
||||
// Handle last gesture
|
||||
if ((currentGesture != 0) && ((int)currentGesture != 4) && (currentGesture != previousGesture))
|
||||
// Handle gesture log
|
||||
if (IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
if (CheckCollisionPointRec(GetMousePosition(), logButton1))
|
||||
{
|
||||
lastGesture = currentGesture; // Filter the meaningful gestures (1, 2, 8 to 512) for the display
|
||||
}
|
||||
|
||||
// Handle gesture log
|
||||
if (IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
if (CheckCollisionPointRec(GetMousePosition(), logButton1))
|
||||
switch (logMode)
|
||||
{
|
||||
switch (logMode)
|
||||
{
|
||||
case 3:
|
||||
logMode = 2;
|
||||
break;
|
||||
case 2:
|
||||
logMode = 3;
|
||||
break;
|
||||
case 1:
|
||||
logMode = 0;
|
||||
break;
|
||||
default:
|
||||
logMode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (CheckCollisionPointRec(GetMousePosition(), logButton2))
|
||||
{
|
||||
switch (logMode)
|
||||
{
|
||||
case 3:
|
||||
logMode = 1;
|
||||
break;
|
||||
case 2:
|
||||
logMode = 0;
|
||||
break;
|
||||
case 1:
|
||||
logMode = 3;
|
||||
break;
|
||||
default:
|
||||
logMode = 2;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
logMode = 2;
|
||||
break;
|
||||
case 2:
|
||||
logMode = 3;
|
||||
break;
|
||||
case 1:
|
||||
logMode = 0;
|
||||
break;
|
||||
default:
|
||||
logMode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int fillLog = 0; // Gate variable to be used to allow or not the gesture log to be filled
|
||||
if (currentGesture != 0)
|
||||
else if (CheckCollisionPointRec(GetMousePosition(), logButton2))
|
||||
{
|
||||
if (logMode == 3) // 3 hides repeated events and hide hold events
|
||||
switch (logMode)
|
||||
{
|
||||
if ((((int)currentGesture != 4) && (currentGesture != previousGesture)) || ((int)currentGesture < 3))
|
||||
{
|
||||
fillLog = 1;
|
||||
}
|
||||
case 3:
|
||||
logMode = 1;
|
||||
break;
|
||||
case 2:
|
||||
logMode = 0;
|
||||
break;
|
||||
case 1:
|
||||
logMode = 3;
|
||||
break;
|
||||
default:
|
||||
logMode = 2;
|
||||
break;
|
||||
}
|
||||
else if (logMode == 2) // 2 shows repeated events but hide hold events
|
||||
{
|
||||
if ((int)currentGesture != 4)
|
||||
{
|
||||
fillLog = 1;
|
||||
}
|
||||
}
|
||||
else if (logMode == 1) // 1 hides repeated events
|
||||
{
|
||||
if (currentGesture != previousGesture)
|
||||
{
|
||||
fillLog = 1;
|
||||
}
|
||||
}
|
||||
else // 0 shows repeated events
|
||||
}
|
||||
}
|
||||
|
||||
var fillLog = 0; // Gate variable to be used to allow or not the gesture log to be filled
|
||||
if (currentGesture != 0)
|
||||
{
|
||||
if (logMode == 3) // 3 hides repeated events and hide hold events
|
||||
{
|
||||
if ((((int)currentGesture != 4) && (currentGesture != previousGesture)) || ((int)currentGesture < 3))
|
||||
{
|
||||
fillLog = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fillLog > 0) // If one of the conditions from logMode was met, fill the gesture log
|
||||
else if (logMode == 2) // 2 shows repeated events but hide hold events
|
||||
{
|
||||
previousGesture = currentGesture;
|
||||
gestureColor = GetGestureColor((int)currentGesture);
|
||||
if (gestureLogIndex <= 0)
|
||||
if ((int)currentGesture != 4)
|
||||
{
|
||||
gestureLogIndex = GESTURE_LOG_SIZE;
|
||||
}
|
||||
gestureLogIndex--;
|
||||
|
||||
// Copy the gesture respective name to the gesture log array
|
||||
gestureLog[gestureLogIndex] = GetGestureName((int)currentGesture);
|
||||
}
|
||||
|
||||
// Handle protractor
|
||||
if ((int)currentGesture > 255)
|
||||
{
|
||||
currentAngleDegrees = currentPitchDegrees; // Pinch In and Pinch Out
|
||||
}
|
||||
else if ((int)currentGesture > 15)
|
||||
{
|
||||
currentAngleDegrees = currentDragDegrees; // Swipe Right, Swipe Left, Swipe Up and Swipe Down
|
||||
}
|
||||
else if (currentGesture > 0)
|
||||
{
|
||||
currentAngleDegrees = 0.0f; // Tap, Doubletap, Hold and Grab
|
||||
}
|
||||
|
||||
float currentAngleRadians =
|
||||
((currentAngleDegrees + 90.0f) * MathF.PI / 180); // Convert the current angle to Radians
|
||||
// Calculate the final vector for display
|
||||
finalVector = new Vector2(
|
||||
(angleLength * MathF.Sin(currentAngleRadians)) + protractorPosition.X,
|
||||
(angleLength * MathF.Cos(currentAngleRadians)) + protractorPosition.Y
|
||||
)
|
||||
;
|
||||
|
||||
// Handle touch and mouse pointer points
|
||||
Vector2[] touchPosition = new Vector2[MAX_TOUCH_COUNT];
|
||||
|
||||
Vector2 mousePosition = Vector2.Zero;
|
||||
if (currentGesture != Gesture.None)
|
||||
{
|
||||
if (touchCount != 0)
|
||||
{
|
||||
for (i = 0; i < touchCount; i++)
|
||||
{
|
||||
touchPosition[i] = GetTouchPosition(i); // Fill the touch positions
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mousePosition = GetMousePosition();
|
||||
fillLog = 1;
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//--------------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw common elements
|
||||
DrawText("*", (int)messagePosition.X + 5, (int)messagePosition.Y + 5, 10, Color.Black);
|
||||
DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", (int)messagePosition.X + 15,
|
||||
(int)messagePosition.Y + 5, 10, Color.Black);
|
||||
DrawText("*", (int)messagePosition.X + 5, (int)messagePosition.Y + 35, 10, Color.Black);
|
||||
DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.",
|
||||
(int)messagePosition.X + 15, (int)messagePosition.Y + 35, 10, Color.Black);
|
||||
|
||||
// Draw last gesture
|
||||
DrawText("Last gesture", (int)lastGesturePosition.X + 33, (int)lastGesturePosition.Y - 47, 20, Color.Black);
|
||||
DrawText("Swipe Tap Pinch Touch", (int)lastGesturePosition.X + 17,
|
||||
(int)lastGesturePosition.Y - 18, 10, Color.Black);
|
||||
DrawRectangle((int)lastGesturePosition.X + 20, (int)lastGesturePosition.Y, 20, 20,
|
||||
lastGesture == Gesture.SwipeUp ? Color.Red : Color.LightGray);
|
||||
DrawRectangle((int)lastGesturePosition.X, (int)lastGesturePosition.Y + 20, 20, 20,
|
||||
lastGesture == Gesture.SwipeLeft ? Color.Red : Color.LightGray);
|
||||
DrawRectangle((int)lastGesturePosition.X + 40, (int)lastGesturePosition.Y + 20, 20, 20,
|
||||
lastGesture == Gesture.SwipeRight ? Color.Red : Color.LightGray);
|
||||
DrawRectangle((int)lastGesturePosition.X + 20, (int)lastGesturePosition.Y + 40, 20, 20,
|
||||
lastGesture == Gesture.SwipeDown ? Color.Red : Color.LightGray);
|
||||
DrawCircle((int)lastGesturePosition.X + 80, (int)lastGesturePosition.Y + 16, 10,
|
||||
lastGesture == Gesture.Tap ? Color.Blue : Color.LightGray);
|
||||
DrawRing(new Vector2(
|
||||
lastGesturePosition.X + 103, lastGesturePosition.Y + 16
|
||||
), 6.0f, 11.0f, 0.0f, 360.0f, 0, lastGesture == Gesture.Drag ? Color.Lime : Color.LightGray);
|
||||
DrawCircle((int)lastGesturePosition.X + 80, (int)lastGesturePosition.Y + 43, 10,
|
||||
lastGesture == Gesture.DoubleTap ? Color.SkyBlue : Color.LightGray);
|
||||
DrawCircle((int)lastGesturePosition.X + 103, (int)lastGesturePosition.Y + 43, 10,
|
||||
lastGesture == Gesture.DoubleTap ? Color.SkyBlue : Color.LightGray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 122, lastGesturePosition.Y + 16
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 137, lastGesturePosition.Y + 26
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 137, lastGesturePosition.Y + 6
|
||||
), lastGesture == Gesture.PinchOut ? Color.Orange : Color.LightGray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 147, lastGesturePosition.Y + 6
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 147, lastGesturePosition.Y + 26
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 162, lastGesturePosition.Y + 16
|
||||
), lastGesture == Gesture.PinchOut ? Color.Orange : Color.Gray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 125, lastGesturePosition.Y + 33
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 125, lastGesturePosition.Y + 53
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 140, lastGesturePosition.Y + 43
|
||||
), lastGesture == Gesture.PinchIn ? Color.Violet : Color.LightGray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 144, lastGesturePosition.Y + 43
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 159, lastGesturePosition.Y + 53
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 159, lastGesturePosition.Y + 33
|
||||
), lastGesture == Gesture.PinchIn ? Color.Violet : Color.LightGray);
|
||||
for (i = 0; i < 4; i++)
|
||||
else if (logMode == 1) // 1 hides repeated events
|
||||
{
|
||||
DrawCircle((int)lastGesturePosition.X + 180, (int)lastGesturePosition.Y + 7 + i * 15, 5,
|
||||
touchCount <= i ? Color.LightGray : gestureColor);
|
||||
}
|
||||
|
||||
// Draw gesture log
|
||||
DrawText("Log", (int)gestureLogPosition.X, (int)gestureLogPosition.Y, 20, Color.Black);
|
||||
|
||||
// Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
|
||||
for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE)
|
||||
{
|
||||
DrawText(gestureLog[ii], (int)gestureLogPosition.X, (int)gestureLogPosition.Y + 410 - i * 20, 20,
|
||||
(i == 0 ? gestureColor : Color.LightGray));
|
||||
}
|
||||
|
||||
Color logButton1Color, logButton2Color;
|
||||
switch (logMode)
|
||||
{
|
||||
case 3:
|
||||
logButton1Color = Color.Maroon;
|
||||
logButton2Color = Color.Maroon;
|
||||
break;
|
||||
case 2:
|
||||
logButton1Color = Color.Gray;
|
||||
logButton2Color = Color.Maroon;
|
||||
break;
|
||||
case 1:
|
||||
logButton1Color = Color.Maroon;
|
||||
logButton2Color = Color.Gray;
|
||||
break;
|
||||
default:
|
||||
logButton1Color = Color.Gray;
|
||||
logButton2Color = Color.Gray;
|
||||
break;
|
||||
}
|
||||
|
||||
DrawRectangleRec(logButton1, logButton1Color);
|
||||
DrawText("Hide", (int)logButton1.X + 7, (int)logButton1.Y + 3, 10, Color.White);
|
||||
DrawText("Repeat", (int)logButton1.X + 7, (int)logButton1.Y + 13, 10, Color.White);
|
||||
DrawRectangleRec(logButton2, logButton2Color);
|
||||
DrawText("Hide", (int)logButton1.X + 62, (int)logButton1.Y + 3, 10, Color.White);
|
||||
DrawText("Hold", (int)logButton1.X + 62, (int)logButton1.Y + 13, 10, Color.White);
|
||||
|
||||
// Draw protractor
|
||||
DrawText("Angle", (int)protractorPosition.X + 55, (int)protractorPosition.Y + 76, 10, Color.Black);
|
||||
|
||||
// Note: Official it's using raylibs functions for string manipulation. But in C# it will end up in an unsafe handling.
|
||||
string angleString = currentAngleDegrees.ToString("F3");
|
||||
int angleStringDot = angleString.IndexOf('.');
|
||||
string angleStringTrim = angleString.Substring(0, angleStringDot + 3);
|
||||
|
||||
DrawText(angleStringTrim, (int)protractorPosition.X + 55, (int)protractorPosition.Y + 92, 20, gestureColor);
|
||||
DrawCircleV(protractorPosition, 80.0f, Color.White);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X - 90, protractorPosition.Y
|
||||
), new Vector2(
|
||||
protractorPosition.X + 90, protractorPosition.Y
|
||||
), 3.0f, Color.LightGray);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X, protractorPosition.Y - 90
|
||||
), new Vector2(
|
||||
protractorPosition.X, protractorPosition.Y + 90
|
||||
), 3.0f, Color.LightGray);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X - 80, protractorPosition.Y - 45
|
||||
), new Vector2(
|
||||
protractorPosition.X + 80, protractorPosition.Y + 45
|
||||
), 3.0f, Color.Green);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X - 80, protractorPosition.Y + 45
|
||||
), new Vector2(
|
||||
protractorPosition.X + 80, protractorPosition.Y - 45
|
||||
), 3.0f, Color.Green);
|
||||
DrawText("0", (int)protractorPosition.X + 96, (int)protractorPosition.Y - 9, 20, Color.Black);
|
||||
DrawText("30", (int)protractorPosition.X + 74, (int)protractorPosition.Y - 68, 20, Color.Black);
|
||||
DrawText("90", (int)protractorPosition.X - 11, (int)protractorPosition.Y - 110, 20, Color.Black);
|
||||
DrawText("150", (int)protractorPosition.X - 100, (int)protractorPosition.Y - 68, 20, Color.Black);
|
||||
DrawText("180", (int)protractorPosition.X - 124, (int)protractorPosition.Y - 9, 20, Color.Black);
|
||||
DrawText("210", (int)protractorPosition.X - 100, (int)protractorPosition.Y + 50, 20, Color.Black);
|
||||
DrawText("270", (int)protractorPosition.X - 18, (int)protractorPosition.Y + 92, 20, Color.Black);
|
||||
DrawText("330", (int)protractorPosition.X + 72, (int)protractorPosition.Y + 50, 20, Color.Black);
|
||||
if (currentAngleDegrees != 0.0f)
|
||||
{
|
||||
DrawLineEx(protractorPosition, finalVector, 3.0f, gestureColor);
|
||||
}
|
||||
|
||||
// Draw touch and mouse pointer points
|
||||
if (currentGesture != Gesture.None)
|
||||
{
|
||||
if (touchCount != 0)
|
||||
if (currentGesture != previousGesture)
|
||||
{
|
||||
for (i = 0; i < touchCount; i++)
|
||||
{
|
||||
DrawCircleV(touchPosition[i], 50.0f, Fade(gestureColor, 0.5f));
|
||||
DrawCircleV(touchPosition[i], 5.0f, gestureColor);
|
||||
}
|
||||
|
||||
if (touchCount == 2)
|
||||
{
|
||||
DrawLineEx(touchPosition[0], touchPosition[1], (((int)currentGesture == 512) ? 8.0f : 12.0f),
|
||||
gestureColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCircleV(mousePosition, 35.0f, Fade(gestureColor, 0.5f));
|
||||
DrawCircleV(mousePosition, 5.0f, gestureColor);
|
||||
fillLog = 1;
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
else // 0 shows repeated events
|
||||
{
|
||||
fillLog = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fillLog > 0) // If one of the conditions from logMode was met, fill the gesture log
|
||||
{
|
||||
previousGesture = currentGesture;
|
||||
gestureColor = GetGestureColor((int)currentGesture);
|
||||
if (gestureLogIndex <= 0)
|
||||
{
|
||||
gestureLogIndex = GESTURE_LOG_SIZE;
|
||||
}
|
||||
gestureLogIndex--;
|
||||
|
||||
// Copy the gesture respective name to the gesture log array
|
||||
gestureLog[gestureLogIndex] = GetGestureName((int)currentGesture);
|
||||
}
|
||||
|
||||
// Handle protractor
|
||||
if ((int)currentGesture > 255)
|
||||
{
|
||||
currentAngleDegrees = currentPitchDegrees; // Pinch In and Pinch Out
|
||||
}
|
||||
else if ((int)currentGesture > 15)
|
||||
{
|
||||
currentAngleDegrees = currentDragDegrees; // Swipe Right, Swipe Left, Swipe Up and Swipe Down
|
||||
}
|
||||
else if (currentGesture > 0)
|
||||
{
|
||||
currentAngleDegrees = 0.0f; // Tap, Doubletap, Hold and Grab
|
||||
}
|
||||
|
||||
var currentAngleRadians =
|
||||
((currentAngleDegrees + 90.0f) * MathF.PI / 180); // Convert the current angle to Radians
|
||||
// Calculate the final vector for display
|
||||
finalVector = new Vector2(
|
||||
(angleLength * MathF.Sin(currentAngleRadians)) + protractorPosition.X,
|
||||
(angleLength * MathF.Cos(currentAngleRadians)) + protractorPosition.Y
|
||||
);
|
||||
|
||||
// Handle touch and mouse pointer points
|
||||
var touchPosition = new Vector2[MAX_TOUCH_COUNT];
|
||||
|
||||
var mousePosition = Vector2.Zero;
|
||||
if (currentGesture != Gesture.None)
|
||||
{
|
||||
if (touchCount != 0)
|
||||
{
|
||||
for (i = 0; i < touchCount; i++)
|
||||
{
|
||||
touchPosition[i] = GetTouchPosition(i); // Fill the touch positions
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mousePosition = GetMousePosition();
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//--------------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw common elements
|
||||
DrawText("*", (int)messagePosition.X + 5, (int)messagePosition.Y + 5, 10, Color.Black);
|
||||
DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", (int)messagePosition.X + 15,
|
||||
(int)messagePosition.Y + 5, 10, Color.Black);
|
||||
DrawText("*", (int)messagePosition.X + 5, (int)messagePosition.Y + 35, 10, Color.Black);
|
||||
DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.",
|
||||
(int)messagePosition.X + 15, (int)messagePosition.Y + 35, 10, Color.Black);
|
||||
|
||||
// Draw last gesture
|
||||
DrawText("Last gesture", (int)lastGesturePosition.X + 33, (int)lastGesturePosition.Y - 47, 20, Color.Black);
|
||||
DrawText("Swipe Tap Pinch Touch", (int)lastGesturePosition.X + 17,
|
||||
(int)lastGesturePosition.Y - 18, 10, Color.Black);
|
||||
DrawRectangle((int)lastGesturePosition.X + 20, (int)lastGesturePosition.Y, 20, 20,
|
||||
lastGesture == Gesture.SwipeUp ? Color.Red : Color.LightGray);
|
||||
DrawRectangle((int)lastGesturePosition.X, (int)lastGesturePosition.Y + 20, 20, 20,
|
||||
lastGesture == Gesture.SwipeLeft ? Color.Red : Color.LightGray);
|
||||
DrawRectangle((int)lastGesturePosition.X + 40, (int)lastGesturePosition.Y + 20, 20, 20,
|
||||
lastGesture == Gesture.SwipeRight ? Color.Red : Color.LightGray);
|
||||
DrawRectangle((int)lastGesturePosition.X + 20, (int)lastGesturePosition.Y + 40, 20, 20,
|
||||
lastGesture == Gesture.SwipeDown ? Color.Red : Color.LightGray);
|
||||
DrawCircle((int)lastGesturePosition.X + 80, (int)lastGesturePosition.Y + 16, 10,
|
||||
lastGesture == Gesture.Tap ? Color.Blue : Color.LightGray);
|
||||
DrawRing(new Vector2(
|
||||
lastGesturePosition.X + 103, lastGesturePosition.Y + 16
|
||||
), 6.0f, 11.0f, 0.0f, 360.0f, 0, lastGesture == Gesture.Drag ? Color.Lime : Color.LightGray);
|
||||
DrawCircle((int)lastGesturePosition.X + 80, (int)lastGesturePosition.Y + 43, 10,
|
||||
lastGesture == Gesture.DoubleTap ? Color.SkyBlue : Color.LightGray);
|
||||
DrawCircle((int)lastGesturePosition.X + 103, (int)lastGesturePosition.Y + 43, 10,
|
||||
lastGesture == Gesture.DoubleTap ? Color.SkyBlue : Color.LightGray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 122, lastGesturePosition.Y + 16
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 137, lastGesturePosition.Y + 26
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 137, lastGesturePosition.Y + 6
|
||||
), lastGesture == Gesture.PinchOut ? Color.Orange : Color.LightGray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 147, lastGesturePosition.Y + 6
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 147, lastGesturePosition.Y + 26
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 162, lastGesturePosition.Y + 16
|
||||
), lastGesture == Gesture.PinchOut ? Color.Orange : Color.Gray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 125, lastGesturePosition.Y + 33
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 125, lastGesturePosition.Y + 53
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 140, lastGesturePosition.Y + 43
|
||||
), lastGesture == Gesture.PinchIn ? Color.Violet : Color.LightGray);
|
||||
DrawTriangle(new Vector2(
|
||||
lastGesturePosition.X + 144, lastGesturePosition.Y + 43
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 159, lastGesturePosition.Y + 53
|
||||
), new Vector2(
|
||||
lastGesturePosition.X + 159, lastGesturePosition.Y + 33
|
||||
), lastGesture == Gesture.PinchIn ? Color.Violet : Color.LightGray);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
DrawCircle((int)lastGesturePosition.X + 180, (int)lastGesturePosition.Y + 7 + i * 15, 5,
|
||||
touchCount <= i ? Color.LightGray : gestureColor);
|
||||
}
|
||||
|
||||
// Draw gesture log
|
||||
DrawText("Log", (int)gestureLogPosition.X, (int)gestureLogPosition.Y, 20, Color.Black);
|
||||
|
||||
// Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
|
||||
for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE)
|
||||
{
|
||||
DrawText(gestureLog[ii], (int)gestureLogPosition.X, (int)gestureLogPosition.Y + 410 - i * 20, 20,
|
||||
(i == 0 ? gestureColor : Color.LightGray));
|
||||
}
|
||||
|
||||
Color logButton1Color, logButton2Color;
|
||||
switch (logMode)
|
||||
{
|
||||
case 3:
|
||||
logButton1Color = Color.Maroon;
|
||||
logButton2Color = Color.Maroon;
|
||||
break;
|
||||
case 2:
|
||||
logButton1Color = Color.Gray;
|
||||
logButton2Color = Color.Maroon;
|
||||
break;
|
||||
case 1:
|
||||
logButton1Color = Color.Maroon;
|
||||
logButton2Color = Color.Gray;
|
||||
break;
|
||||
default:
|
||||
logButton1Color = Color.Gray;
|
||||
logButton2Color = Color.Gray;
|
||||
break;
|
||||
}
|
||||
|
||||
DrawRectangleRec(logButton1, logButton1Color);
|
||||
DrawText("Hide", (int)logButton1.X + 7, (int)logButton1.Y + 3, 10, Color.White);
|
||||
DrawText("Repeat", (int)logButton1.X + 7, (int)logButton1.Y + 13, 10, Color.White);
|
||||
DrawRectangleRec(logButton2, logButton2Color);
|
||||
DrawText("Hide", (int)logButton1.X + 62, (int)logButton1.Y + 3, 10, Color.White);
|
||||
DrawText("Hold", (int)logButton1.X + 62, (int)logButton1.Y + 13, 10, Color.White);
|
||||
|
||||
// Draw protractor
|
||||
DrawText("Angle", (int)protractorPosition.X + 55, (int)protractorPosition.Y + 76, 10, Color.Black);
|
||||
|
||||
// Note: Official it's using raylibs functions for string manipulation. But in C# it will end up in an unsafe handling.
|
||||
var angleString = currentAngleDegrees.ToString("F3");
|
||||
var angleStringDot = angleString.IndexOf('.');
|
||||
var angleStringTrim = angleString[..(angleStringDot + 3)];
|
||||
|
||||
DrawText(angleStringTrim, (int)protractorPosition.X + 55, (int)protractorPosition.Y + 92, 20, gestureColor);
|
||||
DrawCircleV(protractorPosition, 80.0f, Color.White);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X - 90, protractorPosition.Y
|
||||
), new Vector2(
|
||||
protractorPosition.X + 90, protractorPosition.Y
|
||||
), 3.0f, Color.LightGray);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X, protractorPosition.Y - 90
|
||||
), new Vector2(
|
||||
protractorPosition.X, protractorPosition.Y + 90
|
||||
), 3.0f, Color.LightGray);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X - 80, protractorPosition.Y - 45
|
||||
), new Vector2(
|
||||
protractorPosition.X + 80, protractorPosition.Y + 45
|
||||
), 3.0f, Color.Green);
|
||||
DrawLineEx(new Vector2(
|
||||
protractorPosition.X - 80, protractorPosition.Y + 45
|
||||
), new Vector2(
|
||||
protractorPosition.X + 80, protractorPosition.Y - 45
|
||||
), 3.0f, Color.Green);
|
||||
DrawText("0", (int)protractorPosition.X + 96, (int)protractorPosition.Y - 9, 20, Color.Black);
|
||||
DrawText("30", (int)protractorPosition.X + 74, (int)protractorPosition.Y - 68, 20, Color.Black);
|
||||
DrawText("90", (int)protractorPosition.X - 11, (int)protractorPosition.Y - 110, 20, Color.Black);
|
||||
DrawText("150", (int)protractorPosition.X - 100, (int)protractorPosition.Y - 68, 20, Color.Black);
|
||||
DrawText("180", (int)protractorPosition.X - 124, (int)protractorPosition.Y - 9, 20, Color.Black);
|
||||
DrawText("210", (int)protractorPosition.X - 100, (int)protractorPosition.Y + 50, 20, Color.Black);
|
||||
DrawText("270", (int)protractorPosition.X - 18, (int)protractorPosition.Y + 92, 20, Color.Black);
|
||||
DrawText("330", (int)protractorPosition.X + 72, (int)protractorPosition.Y + 50, 20, Color.Black);
|
||||
if (currentAngleDegrees != 0.0f)
|
||||
{
|
||||
DrawLineEx(protractorPosition, finalVector, 3.0f, gestureColor);
|
||||
}
|
||||
|
||||
// Draw touch and mouse pointer points
|
||||
if (currentGesture != Gesture.None)
|
||||
{
|
||||
if (touchCount != 0)
|
||||
{
|
||||
for (i = 0; i < touchCount; i++)
|
||||
{
|
||||
DrawCircleV(touchPosition[i], 50.0f, Fade(gestureColor, 0.5f));
|
||||
DrawCircleV(touchPosition[i], 5.0f, gestureColor);
|
||||
}
|
||||
|
||||
if (touchCount == 2)
|
||||
{
|
||||
DrawLineEx(touchPosition[0], touchPosition[1], (((int)currentGesture == 512) ? 8.0f : 12.0f),
|
||||
gestureColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCircleV(mousePosition, 35.0f, Fade(gestureColor, 0.5f));
|
||||
DrawCircleV(mousePosition, 5.0f, gestureColor);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures testbed");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputGesturesTestBed();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
|
|
@ -409,7 +453,8 @@ public class InputGesturesTestBed
|
|||
return 0;
|
||||
}
|
||||
|
||||
static string GetGestureName(int gesture)
|
||||
// Get text string for gesture value
|
||||
private static string GetGestureName(int gesture)
|
||||
{
|
||||
switch (gesture)
|
||||
{
|
||||
|
|
@ -441,7 +486,7 @@ public class InputGesturesTestBed
|
|||
}
|
||||
|
||||
// Get color for gesture value
|
||||
static Color GetGestureColor(int gesture)
|
||||
private static Color GetGestureColor(int gesture)
|
||||
{
|
||||
switch (gesture)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,69 +13,89 @@
|
|||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class InputKeys
|
||||
public partial class InputKeys : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Input Keys";
|
||||
|
||||
public string Title => "raylib [core] example - input keys";
|
||||
|
||||
private Vector2 ballPosition;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
ballPosition = new((float)screenWidth / 2, (float)screenHeight / 2);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
ballPosition.X += 2.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
ballPosition.X -= 2.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
ballPosition.Y -= 2.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
ballPosition.Y += 2.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("move the ball with arrow keys", 10, 10, 20, Color.DarkGray);
|
||||
|
||||
DrawCircleV(ballPosition, 50, Color.Maroon);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input keys");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard input");
|
||||
|
||||
Vector2 ballPosition = new((float)screenWidth / 2, (float)screenHeight / 2);
|
||||
|
||||
SetTargetFPS(60); // Set target frames-per-second
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputKeys();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
ballPosition.X += 2.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
ballPosition.X -= 2.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
ballPosition.Y -= 2.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
ballPosition.Y += 2.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("move the ball with arrow keys", 10, 10, 20, Color.DarkGray);
|
||||
|
||||
DrawCircleV(ballPosition, 50, Color.Maroon);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -14,100 +14,124 @@
|
|||
********************************************************************************************/
|
||||
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class InputMouse
|
||||
public partial class InputMouse : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Input Mouse";
|
||||
|
||||
public string Title => "raylib [core] example - input mouse";
|
||||
|
||||
private Vector2 ballPosition;
|
||||
private Color ballColor;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
ballPosition = new(-100.0f, -100.0f);
|
||||
ballColor = Color.DarkBlue;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.H))
|
||||
{
|
||||
if (IsCursorHidden())
|
||||
{
|
||||
ShowCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
ballPosition = GetMousePosition();
|
||||
|
||||
if (IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
ballColor = Color.Maroon;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Middle))
|
||||
{
|
||||
ballColor = Color.Lime;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Right))
|
||||
{
|
||||
ballColor = Color.DarkBlue;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Side))
|
||||
{
|
||||
ballColor = Color.Purple;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Extra))
|
||||
{
|
||||
ballColor = Color.Yellow;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Forward))
|
||||
{
|
||||
ballColor = Color.Orange;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Back))
|
||||
{
|
||||
ballColor = Color.Beige;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawCircleV(ballPosition, 40, ballColor);
|
||||
|
||||
DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, Color.DarkGray);
|
||||
DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, Color.DarkGray);
|
||||
|
||||
if (IsCursorHidden())
|
||||
{
|
||||
DrawText("CURSOR HIDDEN", 20, 60, 20, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("CURSOR VISIBLE", 20, 60, 20, Color.Lime);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input mouse");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input");
|
||||
|
||||
Vector2 ballPosition = new(-100.0f, -100.0f);
|
||||
Color ballColor = Color.DarkBlue;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputMouse();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.H))
|
||||
{
|
||||
if (IsCursorHidden())
|
||||
{
|
||||
ShowCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
ballPosition = GetMousePosition();
|
||||
|
||||
if (IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
ballColor = Color.Maroon;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Middle))
|
||||
{
|
||||
ballColor = Color.Lime;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Right))
|
||||
{
|
||||
ballColor = Color.DarkBlue;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Extra))
|
||||
{
|
||||
ballColor = Color.Yellow;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Forward))
|
||||
{
|
||||
ballColor = Color.Orange;
|
||||
}
|
||||
else if (IsMouseButtonPressed(MouseButton.Back))
|
||||
{
|
||||
ballColor = Color.Beige;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawCircleV(ballPosition, 40, ballColor);
|
||||
|
||||
DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, Color.DarkGray);
|
||||
DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, Color.DarkGray);
|
||||
|
||||
if (IsCursorHidden())
|
||||
{
|
||||
DrawText("CURSOR HIDDEN", 20, 60, 20, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("CURSOR VISIBLE", 20, 60, 20, Color.Lime);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -13,52 +13,74 @@
|
|||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class InputMouseWheel
|
||||
public partial class InputMouseWheel : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Mouse Wheel";
|
||||
|
||||
public string Title => "raylib [core] example - input mouse wheel";
|
||||
|
||||
private int boxPositionY;
|
||||
private int scrollSpeed; // Scrolling speed in pixels
|
||||
|
||||
public void Init()
|
||||
{
|
||||
boxPositionY = screenHeight / 2 - 40;
|
||||
scrollSpeed = 4; // Scrolling speed in pixels
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
boxPositionY -= (int)(GetMouseWheelMove() * scrollSpeed);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawRectangle(screenWidth / 2 - 40, boxPositionY, 80, 80, Color.Maroon);
|
||||
|
||||
DrawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, Color.Gray);
|
||||
DrawText($"Box position Y: {boxPositionY:000}", 10, 40, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input mouse wheel");
|
||||
|
||||
int boxPositionY = screenHeight / 2 - 40;
|
||||
int scrollSpeed = 4; // Scrolling speed in pixels
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputMouseWheel();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
boxPositionY -= (int)(GetMouseWheelMove() * scrollSpeed);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawRectangle(screenWidth / 2 - 40, boxPositionY, 80, 80, Color.Maroon);
|
||||
|
||||
DrawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, Color.Gray);
|
||||
DrawText($"Box position Y: {boxPositionY}", 10, 40, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -15,79 +15,100 @@
|
|||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class InputMultitouch
|
||||
public partial class InputMultitouch : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private const int MaxTouchPoints = 10;
|
||||
|
||||
public string Name => "Core / Input Multitouch";
|
||||
|
||||
public string Title => "raylib [core] example - input multitouch";
|
||||
|
||||
private Vector2[] touchPositions;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
touchPositions = new Vector2[MaxTouchPoints];
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Get the touch point count ( how many fingers are touching the screen )
|
||||
var tCount = GetTouchPointCount();
|
||||
|
||||
// Clamp touch points available ( set the maximum touch points allowed )
|
||||
if (tCount > MaxTouchPoints)
|
||||
{
|
||||
tCount = MaxTouchPoints;
|
||||
}
|
||||
|
||||
// Get touch points positions
|
||||
for (var i = 0; i < tCount; i++)
|
||||
{
|
||||
touchPositions[i] = GetTouchPosition(i);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
for (var i = 0; i < tCount; i++)
|
||||
{
|
||||
// Make sure point is not (0, 0) as this means there is no touch for it
|
||||
if ((touchPositions[i].X > 0) && (touchPositions[i].Y > 0))
|
||||
{
|
||||
// Draw circle and touch index number
|
||||
DrawCircleV(touchPositions[i], 34, Color.Orange);
|
||||
DrawText(i.ToString(),
|
||||
(int)touchPositions[i].X - 10,
|
||||
(int)touchPositions[i].Y - 70,
|
||||
40,
|
||||
Color.Black
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DrawText("touch the screen at multiple locations to get multiple balls", 10, 10, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input multitouch");
|
||||
|
||||
const int MaxTouchPoints = 10;
|
||||
Vector2[] touchPositions = new Vector2[MaxTouchPoints];
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputMultitouch();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Get the touch point count (how many fingers are touching the screen )
|
||||
int tCount = GetTouchPointCount();
|
||||
|
||||
// Clamp touch points available (set the maximum touch points allowed )
|
||||
if (tCount > MaxTouchPoints)
|
||||
{
|
||||
tCount = MaxTouchPoints;
|
||||
}
|
||||
|
||||
// Get touch points positions
|
||||
for (int i = 0; i < tCount; i++)
|
||||
{
|
||||
touchPositions[i] = GetTouchPosition(i);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
for (int i = 0; i < tCount; i++)
|
||||
{
|
||||
// Make sure point is not (0, 0) as this means there is no touch for it
|
||||
if ((touchPositions[i].X > 0) && (touchPositions[i].Y > 0))
|
||||
{
|
||||
// Draw circle and touch index number
|
||||
DrawCircleV(touchPositions[i], 34, Color.Orange);
|
||||
DrawText(i.ToString(),
|
||||
(int)touchPositions[i].X - 10,
|
||||
(int)touchPositions[i].Y - 70,
|
||||
40,
|
||||
Color.Black
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DrawText("touch the screen at multiple locations to get multiple balls", 10, 10, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,27 +1,23 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input virtual controls
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* Example contributed by GreenSnakeLinux (@GreenSnakeLinux),
|
||||
* reviewed by Ramon Santamaria (@raysan5), oblerion (@oblerion) and danilwhale (@danilwhale)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2024-2025 GreenSnakeLinux (@GreenSnakeLinux) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
*
|
||||
* raylib [core] example - input virtual controls
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* Example contributed by GreenSnakeLinux (@GreenSnakeLinux),
|
||||
* reviewed by Ramon Santamaria (@raysan5), oblerion (@oblerion) and danilwhale (@danilwhale)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2024-2025 GreenSnakeLinux (@GreenSnakeLinux) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
public enum PadButton
|
||||
{
|
||||
BUTTON_NONE = -1,
|
||||
|
|
@ -32,21 +28,31 @@ public enum PadButton
|
|||
BUTTON_MAX
|
||||
}
|
||||
|
||||
public class InputVirtualControls
|
||||
public partial class InputVirtualControls : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Input Virtual Controls";
|
||||
|
||||
public string Title => "raylib [core] example - input virtual controls";
|
||||
|
||||
private Vector2 padPosition;
|
||||
private float buttonRadius;
|
||||
private Vector2[] buttonPositions;
|
||||
private Vector2[][] arrowTris;
|
||||
private Color[] buttonLabelColors;
|
||||
private int pressedButton;
|
||||
private Vector2 inputPosition;
|
||||
private Vector2 playerPosition;
|
||||
private float playerSpeed;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
padPosition = new Vector2(100, 350);
|
||||
buttonRadius = 30;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls");
|
||||
|
||||
Vector2 padPosition = new Vector2(100, 350);
|
||||
float buttonRadius = 30;
|
||||
|
||||
Vector2[] buttonPositions =
|
||||
buttonPositions =
|
||||
[
|
||||
new Vector2(
|
||||
padPosition.X,padPosition.Y - buttonRadius * 1.5f
|
||||
|
|
@ -62,7 +68,7 @@ public class InputVirtualControls
|
|||
) // Down
|
||||
];
|
||||
|
||||
Vector2[][] arrowTris = [
|
||||
arrowTris = [
|
||||
// Up
|
||||
[
|
||||
new Vector2(
|
||||
|
|
@ -114,107 +120,126 @@ public class InputVirtualControls
|
|||
]
|
||||
;
|
||||
|
||||
Color[] buttonLabelColors = [
|
||||
buttonLabelColors = [
|
||||
Color.Yellow, // Up
|
||||
Color.Blue, // Left
|
||||
Color.Red, // Right
|
||||
Color.Green // Down
|
||||
];
|
||||
|
||||
int pressedButton = (int)PadButton.BUTTON_NONE;
|
||||
Vector2 inputPosition = new Vector2(0, 0);
|
||||
pressedButton = (int)PadButton.BUTTON_NONE;
|
||||
inputPosition = new Vector2(0, 0);
|
||||
|
||||
Vector2 playerPosition = new Vector2((float)screenWidth / 2, (float)screenHeight / 2);
|
||||
float playerSpeed = 75f;
|
||||
playerPosition = new Vector2((float)screenWidth / 2, (float)screenHeight / 2);
|
||||
playerSpeed = 75f;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//--------------------------------------------------------------------------
|
||||
if ((GetTouchPointCount() > 0))
|
||||
{
|
||||
inputPosition = GetTouchPosition(0); // Use touch position
|
||||
}
|
||||
else
|
||||
{
|
||||
inputPosition = GetMousePosition(); // Use mouse position
|
||||
}
|
||||
|
||||
// Reset pressed button to none
|
||||
pressedButton = (int)PadButton.BUTTON_NONE;
|
||||
|
||||
// Make sure user is pressing left mouse button if they're from desktop
|
||||
if ((GetTouchPointCount() > 0) ||
|
||||
((GetTouchPointCount() == 0) && IsMouseButtonDown(MouseButton.Left)))
|
||||
{
|
||||
// Find nearest D-Pad button to the input position
|
||||
for (var i = 0; i < (int)PadButton.BUTTON_MAX; i++)
|
||||
{
|
||||
var distX = MathF.Abs(buttonPositions[i].X - inputPosition.X);
|
||||
var distY = MathF.Abs(buttonPositions[i].Y - inputPosition.Y);
|
||||
|
||||
if ((distX + distY < buttonRadius))
|
||||
{
|
||||
pressedButton = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move player according to pressed button
|
||||
switch ((PadButton)pressedButton)
|
||||
{
|
||||
case PadButton.BUTTON_UP:
|
||||
playerPosition.Y -= playerSpeed * GetFrameTime();
|
||||
break;
|
||||
case PadButton.BUTTON_LEFT:
|
||||
playerPosition.X -= playerSpeed * GetFrameTime();
|
||||
break;
|
||||
case PadButton.BUTTON_RIGHT:
|
||||
playerPosition.X += playerSpeed * GetFrameTime();
|
||||
break;
|
||||
case PadButton.BUTTON_DOWN:
|
||||
playerPosition.Y += playerSpeed * GetFrameTime();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//--------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw world
|
||||
DrawCircleV(playerPosition, 50, Color.Maroon);
|
||||
|
||||
// Draw GUI
|
||||
for (var i = 0; i < (int)PadButton.BUTTON_MAX; i++)
|
||||
{
|
||||
DrawCircleV(buttonPositions[i], buttonRadius, (i == pressedButton) ? Color.DarkGray : Color.Black);
|
||||
|
||||
DrawTriangle(
|
||||
arrowTris[i][0],
|
||||
arrowTris[i][1],
|
||||
arrowTris[i][2],
|
||||
buttonLabelColors[i]
|
||||
);
|
||||
}
|
||||
|
||||
DrawText("move the player with D-Pad buttons", 10, 10, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputVirtualControls();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//--------------------------------------------------------------------------
|
||||
if ((GetTouchPointCount() > 0))
|
||||
{
|
||||
inputPosition = GetTouchPosition(0); // Use touch position
|
||||
}
|
||||
else
|
||||
{
|
||||
inputPosition = GetMousePosition(); // Use mouse position
|
||||
}
|
||||
|
||||
// Reset pressed button to none
|
||||
pressedButton = (int)PadButton.BUTTON_NONE;
|
||||
|
||||
// Make sure user is pressing left mouse button if they're from desktop
|
||||
if ((GetTouchPointCount() > 0) ||
|
||||
((GetTouchPointCount() == 0) && IsMouseButtonDown(MouseButton.Left)))
|
||||
{
|
||||
// Find nearest D-Pad button to the input position
|
||||
for (int i = 0; i < (int)PadButton.BUTTON_MAX; i++)
|
||||
{
|
||||
float distX = MathF.Abs(buttonPositions[i].X - inputPosition.X);
|
||||
float distY = MathF.Abs(buttonPositions[i].Y - inputPosition.Y);
|
||||
|
||||
if ((distX + distY < buttonRadius))
|
||||
{
|
||||
pressedButton = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move player according to pressed button
|
||||
switch ((PadButton)pressedButton)
|
||||
{
|
||||
case PadButton.BUTTON_UP:
|
||||
playerPosition.Y -= playerSpeed * GetFrameTime();
|
||||
break;
|
||||
case PadButton.BUTTON_LEFT:
|
||||
playerPosition.X -= playerSpeed * GetFrameTime();
|
||||
break;
|
||||
case PadButton.BUTTON_RIGHT:
|
||||
playerPosition.X += playerSpeed * GetFrameTime();
|
||||
break;
|
||||
case PadButton.BUTTON_DOWN:
|
||||
playerPosition.Y += playerSpeed * GetFrameTime();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
;
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//--------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw world
|
||||
DrawCircleV(playerPosition, 50, Color.Maroon);
|
||||
|
||||
// Draw GUI
|
||||
for (int i = 0; i < (int)PadButton.BUTTON_MAX; i++)
|
||||
{
|
||||
DrawCircleV(buttonPositions[i], buttonRadius, (i == pressedButton) ? Color.DarkGray : Color.Black);
|
||||
|
||||
DrawTriangle(
|
||||
arrowTris[i][0],
|
||||
arrowTris[i][1],
|
||||
arrowTris[i][2],
|
||||
buttonLabelColors[i]
|
||||
);
|
||||
}
|
||||
|
||||
DrawText("move the player with D-Pad buttons", 10, 10, 20, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
|
|
|
|||
510
Examples/Core/KeyboardTestbed.cs
Normal file
510
Examples/Core/KeyboardTestbed.cs
Normal file
|
|
@ -0,0 +1,510 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - keyboard testbed
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: raylib defined keys refer to ENG-US Keyboard layout,
|
||||
* mapping to other layouts is up to the user
|
||||
*
|
||||
* Example originally created with raylib 5.6, last time updated with raylib 5.6
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2026 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class KeyboardTestbed : IExample
|
||||
{
|
||||
private const int KeyRecSpacing = 4; // Space in pixels between key rectangles
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Keyboard Testbed";
|
||||
|
||||
public string Title => "raylib [core] example - keyboard testbed";
|
||||
|
||||
private int[] line01KeyWidths;
|
||||
private int[] line01Keys;
|
||||
private int[] line02KeyWidths;
|
||||
private int[] line02Keys;
|
||||
private int[] line03KeyWidths;
|
||||
private int[] line03Keys;
|
||||
private int[] line04KeyWidths;
|
||||
private int[] line04Keys;
|
||||
private int[] line05KeyWidths;
|
||||
private int[] line05Keys;
|
||||
private int[] line06KeyWidths;
|
||||
private int[] line06Keys;
|
||||
|
||||
private Vector2 keyboardOffset;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
SetExitKey(KeyboardKey.Null); // Avoid exit on KEY_ESCAPE
|
||||
|
||||
// Keyboard line 01
|
||||
line01KeyWidths = new int[15];
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
line01KeyWidths[i] = 45;
|
||||
}
|
||||
|
||||
line01KeyWidths[13] = 62; // PRINTSCREEN
|
||||
line01Keys = new int[]
|
||||
{
|
||||
(int)KeyboardKey.Escape, (int)KeyboardKey.F1, (int)KeyboardKey.F2, (int)KeyboardKey.F3, (int)KeyboardKey.F4, (int)KeyboardKey.F5,
|
||||
(int)KeyboardKey.F6, (int)KeyboardKey.F7, (int)KeyboardKey.F8, (int)KeyboardKey.F9, (int)KeyboardKey.F10, (int)KeyboardKey.F11,
|
||||
(int)KeyboardKey.F12, (int)KeyboardKey.PrintScreen, (int)KeyboardKey.Pause
|
||||
};
|
||||
|
||||
// Keyboard line 02
|
||||
line02KeyWidths = new int[15];
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
line02KeyWidths[i] = 45;
|
||||
}
|
||||
|
||||
line02KeyWidths[0] = 25; // GRAVE
|
||||
line02KeyWidths[13] = 82; // BACKSPACE
|
||||
line02Keys = new int[]
|
||||
{
|
||||
(int)KeyboardKey.Grave, (int)KeyboardKey.One, (int)KeyboardKey.Two, (int)KeyboardKey.Three, (int)KeyboardKey.Four,
|
||||
(int)KeyboardKey.Five, (int)KeyboardKey.Six, (int)KeyboardKey.Seven, (int)KeyboardKey.Eight, (int)KeyboardKey.Nine,
|
||||
(int)KeyboardKey.Zero, (int)KeyboardKey.Minus, (int)KeyboardKey.Equal, (int)KeyboardKey.Backspace, (int)KeyboardKey.Delete
|
||||
};
|
||||
|
||||
// Keyboard line 03
|
||||
line03KeyWidths = new int[15];
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
line03KeyWidths[i] = 45;
|
||||
}
|
||||
|
||||
line03KeyWidths[0] = 50; // TAB
|
||||
line03KeyWidths[13] = 57; // BACKSLASH
|
||||
line03Keys = new int[]
|
||||
{
|
||||
(int)KeyboardKey.Tab, (int)KeyboardKey.Q, (int)KeyboardKey.W, (int)KeyboardKey.E, (int)KeyboardKey.R, (int)KeyboardKey.T, (int)KeyboardKey.Y,
|
||||
(int)KeyboardKey.U, (int)KeyboardKey.I, (int)KeyboardKey.O, (int)KeyboardKey.P, (int)KeyboardKey.LeftBracket,
|
||||
(int)KeyboardKey.RightBracket, (int)KeyboardKey.Backslash, (int)KeyboardKey.Insert
|
||||
};
|
||||
|
||||
// Keyboard line 04
|
||||
line04KeyWidths = new int[14];
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
line04KeyWidths[i] = 45;
|
||||
}
|
||||
|
||||
line04KeyWidths[0] = 68; // CAPS
|
||||
line04KeyWidths[12] = 88; // ENTER
|
||||
line04Keys = new int[]
|
||||
{
|
||||
(int)KeyboardKey.CapsLock, (int)KeyboardKey.A, (int)KeyboardKey.S, (int)KeyboardKey.D, (int)KeyboardKey.F, (int)KeyboardKey.G,
|
||||
(int)KeyboardKey.H, (int)KeyboardKey.J, (int)KeyboardKey.K, (int)KeyboardKey.L, (int)KeyboardKey.Semicolon,
|
||||
(int)KeyboardKey.Apostrophe, (int)KeyboardKey.Enter, (int)KeyboardKey.PageUp
|
||||
};
|
||||
|
||||
// Keyboard line 05
|
||||
line05KeyWidths = new int[14];
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
line05KeyWidths[i] = 45;
|
||||
}
|
||||
|
||||
line05KeyWidths[0] = 80; // LSHIFT
|
||||
line05KeyWidths[11] = 76; // RSHIFT
|
||||
line05Keys = new int[]
|
||||
{
|
||||
(int)KeyboardKey.LeftShift, (int)KeyboardKey.Z, (int)KeyboardKey.X, (int)KeyboardKey.C, (int)KeyboardKey.V, (int)KeyboardKey.B,
|
||||
(int)KeyboardKey.N, (int)KeyboardKey.M, (int)KeyboardKey.Comma, (int)KeyboardKey.Period, /*KEY_MINUS*/
|
||||
(int)KeyboardKey.Slash, (int)KeyboardKey.RightShift, (int)KeyboardKey.Up, (int)KeyboardKey.PageDown
|
||||
};
|
||||
|
||||
// Keyboard line 06
|
||||
line06KeyWidths = new int[11];
|
||||
for (int i = 0; i < 11; i++)
|
||||
{
|
||||
line06KeyWidths[i] = 45;
|
||||
}
|
||||
|
||||
line06KeyWidths[0] = 80; // LCTRL
|
||||
line06KeyWidths[3] = 208; // SPACE
|
||||
line06KeyWidths[7] = 60; // RCTRL
|
||||
line06Keys = new int[]
|
||||
{
|
||||
(int)KeyboardKey.LeftControl, (int)KeyboardKey.LeftSuper, (int)KeyboardKey.LeftAlt,
|
||||
(int)KeyboardKey.Space, (int)KeyboardKey.RightAlt, 162, (int)KeyboardKey.Null,
|
||||
(int)KeyboardKey.RightControl, (int)KeyboardKey.Left, (int)KeyboardKey.Down, (int)KeyboardKey.Right
|
||||
};
|
||||
|
||||
keyboardOffset = new Vector2(26, 80);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
int key = GetKeyPressed(); // Get pressed keycode
|
||||
if (key > 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Info, $"KEYBOARD TESTBED: KEY PRESSED: {key}");
|
||||
}
|
||||
|
||||
int ch = GetCharPressed(); // Get pressed char for text input, using OS mapping
|
||||
if (ch > 0)
|
||||
{
|
||||
TraceLog(TraceLogLevel.Info, $"KEYBOARD TESTBED: CHAR PRESSED: {(char)ch} ({ch})");
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("KEYBOARD LAYOUT: ENG-US", 26, 38, 20, Color.LightGray);
|
||||
|
||||
// Keyboard line 01 - 15 keys
|
||||
// ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, IMP, CLOSE
|
||||
for (int i = 0, recOffsetX = 0; i < 15; i++)
|
||||
{
|
||||
GuiKeyboardKey(new Rectangle(keyboardOffset.X + recOffsetX, keyboardOffset.Y, (float)line01KeyWidths[i], 30.0f), line01Keys[i]);
|
||||
recOffsetX += line01KeyWidths[i] + KeyRecSpacing;
|
||||
}
|
||||
|
||||
// Keyboard line 02 - 15 keys
|
||||
// `, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -, =, BACKSPACE, DEL
|
||||
for (int i = 0, recOffsetX = 0; i < 15; i++)
|
||||
{
|
||||
GuiKeyboardKey(new Rectangle(keyboardOffset.X + recOffsetX, keyboardOffset.Y + 30 + KeyRecSpacing, (float)line02KeyWidths[i], 38.0f), line02Keys[i]);
|
||||
recOffsetX += line02KeyWidths[i] + KeyRecSpacing;
|
||||
}
|
||||
|
||||
// Keyboard line 03 - 15 keys
|
||||
// TAB, Q, W, E, R, T, Y, U, I, O, P, [, ], \, INS
|
||||
for (int i = 0, recOffsetX = 0; i < 15; i++)
|
||||
{
|
||||
GuiKeyboardKey(new Rectangle(keyboardOffset.X + recOffsetX, keyboardOffset.Y + 30 + 38 + KeyRecSpacing * 2, (float)line03KeyWidths[i], 38.0f), line03Keys[i]);
|
||||
recOffsetX += line03KeyWidths[i] + KeyRecSpacing;
|
||||
}
|
||||
|
||||
// Keyboard line 04 - 14 keys
|
||||
// MAYUS, A, S, D, F, G, H, J, K, L, ;, ', ENTER, REPAG
|
||||
for (int i = 0, recOffsetX = 0; i < 14; i++)
|
||||
{
|
||||
GuiKeyboardKey(new Rectangle(keyboardOffset.X + recOffsetX, keyboardOffset.Y + 30 + 38 * 2 + KeyRecSpacing * 3, (float)line04KeyWidths[i], 38.0f), line04Keys[i]);
|
||||
recOffsetX += line04KeyWidths[i] + KeyRecSpacing;
|
||||
}
|
||||
|
||||
// Keyboard line 05 - 14 keys
|
||||
// LSHIFT, Z, X, C, V, B, N, M, ,, ., /, RSHIFT, UP, AVPAG
|
||||
for (int i = 0, recOffsetX = 0; i < 14; i++)
|
||||
{
|
||||
GuiKeyboardKey(new Rectangle(keyboardOffset.X + recOffsetX, keyboardOffset.Y + 30 + 38 * 3 + KeyRecSpacing * 4, (float)line05KeyWidths[i], 38.0f), line05Keys[i]);
|
||||
recOffsetX += line05KeyWidths[i] + KeyRecSpacing;
|
||||
}
|
||||
|
||||
// Keyboard line 06 - 11 keys
|
||||
// LCTRL, WIN, LALT, SPACE, ALTGR, \, FN, RCTRL, LEFT, DOWN, RIGHT
|
||||
for (int i = 0, recOffsetX = 0; i < 11; i++)
|
||||
{
|
||||
GuiKeyboardKey(new Rectangle(keyboardOffset.X + recOffsetX, keyboardOffset.Y + 30 + 38 * 4 + KeyRecSpacing * 5, (float)line06KeyWidths[i], 38.0f), line06Keys[i]);
|
||||
recOffsetX += line06KeyWidths[i] + KeyRecSpacing;
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
// Get keyboard keycode as text (US keyboard)
|
||||
// NOTE: Mapping for other keyboard layouts can be done here
|
||||
private static string GetKeyText(int key)
|
||||
{
|
||||
switch ((KeyboardKey)key)
|
||||
{
|
||||
case KeyboardKey.Apostrophe:
|
||||
return "'"; // Key: '
|
||||
case KeyboardKey.Comma:
|
||||
return ","; // Key: ,
|
||||
case KeyboardKey.Minus:
|
||||
return "-"; // Key: -
|
||||
case KeyboardKey.Period:
|
||||
return "."; // Key: .
|
||||
case KeyboardKey.Slash:
|
||||
return "/"; // Key: /
|
||||
case KeyboardKey.Zero:
|
||||
return "0"; // Key: 0
|
||||
case KeyboardKey.One:
|
||||
return "1"; // Key: 1
|
||||
case KeyboardKey.Two:
|
||||
return "2"; // Key: 2
|
||||
case KeyboardKey.Three:
|
||||
return "3"; // Key: 3
|
||||
case KeyboardKey.Four:
|
||||
return "4"; // Key: 4
|
||||
case KeyboardKey.Five:
|
||||
return "5"; // Key: 5
|
||||
case KeyboardKey.Six:
|
||||
return "6"; // Key: 6
|
||||
case KeyboardKey.Seven:
|
||||
return "7"; // Key: 7
|
||||
case KeyboardKey.Eight:
|
||||
return "8"; // Key: 8
|
||||
case KeyboardKey.Nine:
|
||||
return "9"; // Key: 9
|
||||
case KeyboardKey.Semicolon:
|
||||
return ";"; // Key: ;
|
||||
case KeyboardKey.Equal:
|
||||
return "="; // Key: =
|
||||
case KeyboardKey.A:
|
||||
return "A"; // Key: A | a
|
||||
case KeyboardKey.B:
|
||||
return "B"; // Key: B | b
|
||||
case KeyboardKey.C:
|
||||
return "C"; // Key: C | c
|
||||
case KeyboardKey.D:
|
||||
return "D"; // Key: D | d
|
||||
case KeyboardKey.E:
|
||||
return "E"; // Key: E | e
|
||||
case KeyboardKey.F:
|
||||
return "F"; // Key: F | f
|
||||
case KeyboardKey.G:
|
||||
return "G"; // Key: G | g
|
||||
case KeyboardKey.H:
|
||||
return "H"; // Key: H | h
|
||||
case KeyboardKey.I:
|
||||
return "I"; // Key: I | i
|
||||
case KeyboardKey.J:
|
||||
return "J"; // Key: J | j
|
||||
case KeyboardKey.K:
|
||||
return "K"; // Key: K | k
|
||||
case KeyboardKey.L:
|
||||
return "L"; // Key: L | l
|
||||
case KeyboardKey.M:
|
||||
return "M"; // Key: M | m
|
||||
case KeyboardKey.N:
|
||||
return "N"; // Key: N | n
|
||||
case KeyboardKey.O:
|
||||
return "O"; // Key: O | o
|
||||
case KeyboardKey.P:
|
||||
return "P"; // Key: P | p
|
||||
case KeyboardKey.Q:
|
||||
return "Q"; // Key: Q | q
|
||||
case KeyboardKey.R:
|
||||
return "R"; // Key: R | r
|
||||
case KeyboardKey.S:
|
||||
return "S"; // Key: S | s
|
||||
case KeyboardKey.T:
|
||||
return "T"; // Key: T | t
|
||||
case KeyboardKey.U:
|
||||
return "U"; // Key: U | u
|
||||
case KeyboardKey.V:
|
||||
return "V"; // Key: V | v
|
||||
case KeyboardKey.W:
|
||||
return "W"; // Key: W | w
|
||||
case KeyboardKey.X:
|
||||
return "X"; // Key: X | x
|
||||
case KeyboardKey.Y:
|
||||
return "Y"; // Key: Y | y
|
||||
case KeyboardKey.Z:
|
||||
return "Z"; // Key: Z | z
|
||||
case KeyboardKey.LeftBracket:
|
||||
return "["; // Key: [
|
||||
case KeyboardKey.Backslash:
|
||||
return "\\"; // Key: '\'
|
||||
case KeyboardKey.RightBracket:
|
||||
return "]"; // Key: ]
|
||||
case KeyboardKey.Grave:
|
||||
return "`"; // Key: `
|
||||
case KeyboardKey.Space:
|
||||
return "SPACE"; // Key: Space
|
||||
case KeyboardKey.Escape:
|
||||
return "ESC"; // Key: Esc
|
||||
case KeyboardKey.Enter:
|
||||
return "ENTER"; // Key: Enter
|
||||
case KeyboardKey.Tab:
|
||||
return "TAB"; // Key: Tab
|
||||
case KeyboardKey.Backspace:
|
||||
return "BACK"; // Key: Backspace
|
||||
case KeyboardKey.Insert:
|
||||
return "INS"; // Key: Ins
|
||||
case KeyboardKey.Delete:
|
||||
return "DEL"; // Key: Del
|
||||
case KeyboardKey.Right:
|
||||
return "RIGHT"; // Key: Cursor right
|
||||
case KeyboardKey.Left:
|
||||
return "LEFT"; // Key: Cursor left
|
||||
case KeyboardKey.Down:
|
||||
return "DOWN"; // Key: Cursor down
|
||||
case KeyboardKey.Up:
|
||||
return "UP"; // Key: Cursor up
|
||||
case KeyboardKey.PageUp:
|
||||
return "PGUP"; // Key: Page up
|
||||
case KeyboardKey.PageDown:
|
||||
return "PGDOWN"; // Key: Page down
|
||||
case KeyboardKey.Home:
|
||||
return "HOME"; // Key: Home
|
||||
case KeyboardKey.End:
|
||||
return "END"; // Key: End
|
||||
case KeyboardKey.CapsLock:
|
||||
return "CAPS"; // Key: Caps lock
|
||||
case KeyboardKey.ScrollLock:
|
||||
return "LOCK"; // Key: Scroll down
|
||||
case KeyboardKey.NumLock:
|
||||
return "NUMLOCK"; // Key: Num lock
|
||||
case KeyboardKey.PrintScreen:
|
||||
return "PRINTSCR"; // Key: Print screen
|
||||
case KeyboardKey.Pause:
|
||||
return "PAUSE"; // Key: Pause
|
||||
case KeyboardKey.F1:
|
||||
return "F1"; // Key: F1
|
||||
case KeyboardKey.F2:
|
||||
return "F2"; // Key: F2
|
||||
case KeyboardKey.F3:
|
||||
return "F3"; // Key: F3
|
||||
case KeyboardKey.F4:
|
||||
return "F4"; // Key: F4
|
||||
case KeyboardKey.F5:
|
||||
return "F5"; // Key: F5
|
||||
case KeyboardKey.F6:
|
||||
return "F6"; // Key: F6
|
||||
case KeyboardKey.F7:
|
||||
return "F7"; // Key: F7
|
||||
case KeyboardKey.F8:
|
||||
return "F8"; // Key: F8
|
||||
case KeyboardKey.F9:
|
||||
return "F9"; // Key: F9
|
||||
case KeyboardKey.F10:
|
||||
return "F10"; // Key: F10
|
||||
case KeyboardKey.F11:
|
||||
return "F11"; // Key: F11
|
||||
case KeyboardKey.F12:
|
||||
return "F12"; // Key: F12
|
||||
case KeyboardKey.LeftShift:
|
||||
return "LSHIFT"; // Key: Shift left
|
||||
case KeyboardKey.LeftControl:
|
||||
return "LCTRL"; // Key: Control left
|
||||
case KeyboardKey.LeftAlt:
|
||||
return "LALT"; // Key: Alt left
|
||||
case KeyboardKey.LeftSuper:
|
||||
return "WIN"; // Key: Super left
|
||||
case KeyboardKey.RightShift:
|
||||
return "RSHIFT"; // Key: Shift right
|
||||
case KeyboardKey.RightControl:
|
||||
return "RCTRL"; // Key: Control right
|
||||
case KeyboardKey.RightAlt:
|
||||
return "ALTGR"; // Key: Alt right
|
||||
case KeyboardKey.RightSuper:
|
||||
return "RSUPER"; // Key: Super right
|
||||
case KeyboardKey.KeyboardMenu:
|
||||
return "KBMENU"; // Key: KB menu
|
||||
case KeyboardKey.Kp0:
|
||||
return "KP0"; // Key: Keypad 0
|
||||
case KeyboardKey.Kp1:
|
||||
return "KP1"; // Key: Keypad 1
|
||||
case KeyboardKey.Kp2:
|
||||
return "KP2"; // Key: Keypad 2
|
||||
case KeyboardKey.Kp3:
|
||||
return "KP3"; // Key: Keypad 3
|
||||
case KeyboardKey.Kp4:
|
||||
return "KP4"; // Key: Keypad 4
|
||||
case KeyboardKey.Kp5:
|
||||
return "KP5"; // Key: Keypad 5
|
||||
case KeyboardKey.Kp6:
|
||||
return "KP6"; // Key: Keypad 6
|
||||
case KeyboardKey.Kp7:
|
||||
return "KP7"; // Key: Keypad 7
|
||||
case KeyboardKey.Kp8:
|
||||
return "KP8"; // Key: Keypad 8
|
||||
case KeyboardKey.Kp9:
|
||||
return "KP9"; // Key: Keypad 9
|
||||
case KeyboardKey.KpDecimal:
|
||||
return "KPDEC"; // Key: Keypad .
|
||||
case KeyboardKey.KpDivide:
|
||||
return "KPDIV"; // Key: Keypad /
|
||||
case KeyboardKey.KpMultiply:
|
||||
return "KPMUL"; // Key: Keypad *
|
||||
case KeyboardKey.KpSubtract:
|
||||
return "KPSUB"; // Key: Keypad -
|
||||
case KeyboardKey.KpAdd:
|
||||
return "KPADD"; // Key: Keypad +
|
||||
case KeyboardKey.KpEnter:
|
||||
return "KPENTER"; // Key: Keypad Enter
|
||||
case KeyboardKey.KpEqual:
|
||||
return "KPEQU"; // Key: Keypad =
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Draw keyboard key
|
||||
private static void GuiKeyboardKey(Rectangle bounds, int key)
|
||||
{
|
||||
if (key == (int)KeyboardKey.Null)
|
||||
{
|
||||
DrawRectangleLinesEx(bounds, 2.0f, Color.LightGray);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsKeyDown((KeyboardKey)key))
|
||||
{
|
||||
DrawRectangleLinesEx(bounds, 2.0f, Color.Maroon);
|
||||
DrawText(GetKeyText(key), (int)(bounds.X + 4), (int)(bounds.Y + 4), 10, Color.Maroon);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangleLinesEx(bounds, 2.0f, Color.DarkGray);
|
||||
DrawText(GetKeyText(key), (int)(bounds.X + 4), (int)(bounds.Y + 4), 10, Color.DarkGray);
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckCollisionPointRec(GetMousePosition(), bounds))
|
||||
{
|
||||
DrawRectangleRec(bounds, Fade(Color.Red, 0.2f));
|
||||
DrawRectangleLinesEx(bounds, 3.0f, Color.Red);
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard testbed");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new KeyboardTestbed();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,153 +1,183 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib example - loading thread
|
||||
* raylib [core] example - loading thread
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* NOTE: raylib is NOT thread-safe: the loading thread only updates plain data
|
||||
* (progress counter and loaded flag); all raylib calls happen on the main thread.
|
||||
*
|
||||
* Example originally created with raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
*
|
||||
* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Threading;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Color;
|
||||
using static Raylib_cs.KeyboardKey;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
enum State
|
||||
[ExcludeFromBrowser("System.Threading.Thread is unsupported on single-threaded wasm")]
|
||||
public partial class LoadingThread : IExample
|
||||
{
|
||||
STATE_WAITING,
|
||||
STATE_LOADING,
|
||||
STATE_FINISHED
|
||||
}
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
public class LoadingThread
|
||||
{
|
||||
// C# bool is atomic. Used for synchronization
|
||||
// https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/variables#atomicity-of-variable-references
|
||||
// Data Loaded completion indicator
|
||||
static bool dataLoaded = false;
|
||||
public string Name => "Core / Loading Thread";
|
||||
|
||||
// Data progress accumulator
|
||||
static int dataProgress = 0;
|
||||
public string Title => "raylib [core] example - loading thread";
|
||||
|
||||
enum State
|
||||
{
|
||||
Waiting,
|
||||
Loading,
|
||||
Finished
|
||||
}
|
||||
|
||||
// Loading data thread; a Thread can only be started once, so a fresh one
|
||||
// is created for every load
|
||||
Thread loadingThread;
|
||||
|
||||
// Data loaded completion indicator; volatile so the main thread sees the
|
||||
// background thread's writes
|
||||
volatile bool dataLoaded;
|
||||
|
||||
// Data progress accumulator (0..500, the progress bar width in pixels)
|
||||
volatile int dataProgress;
|
||||
|
||||
State state;
|
||||
int framesCounter;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
loadingThread = null;
|
||||
dataLoaded = false;
|
||||
dataProgress = 0;
|
||||
|
||||
state = State.Waiting;
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (state)
|
||||
{
|
||||
case State.Waiting:
|
||||
if (IsKeyPressed(KeyboardKey.Enter))
|
||||
{
|
||||
loadingThread = new Thread(LoadDataThread) { IsBackground = true };
|
||||
loadingThread.Start();
|
||||
TraceLog(TraceLogLevel.Info, "Loading thread initialized successfully");
|
||||
|
||||
state = State.Loading;
|
||||
}
|
||||
break;
|
||||
|
||||
case State.Loading:
|
||||
framesCounter++;
|
||||
if (dataLoaded)
|
||||
{
|
||||
framesCounter = 0;
|
||||
loadingThread.Join();
|
||||
TraceLog(TraceLogLevel.Info, "Loading thread terminated");
|
||||
|
||||
state = State.Finished;
|
||||
}
|
||||
break;
|
||||
|
||||
case State.Finished:
|
||||
if (IsKeyPressed(KeyboardKey.Enter))
|
||||
{
|
||||
// Reset everything to launch again
|
||||
dataLoaded = false;
|
||||
dataProgress = 0;
|
||||
|
||||
state = State.Waiting;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case State.Waiting:
|
||||
DrawText("PRESS ENTER to START LOADING DATA", 150, 170, 20, Color.DarkGray);
|
||||
break;
|
||||
|
||||
case State.Loading:
|
||||
DrawRectangle(150, 200, dataProgress, 60, Color.SkyBlue);
|
||||
if ((framesCounter / 15) % 2 == 0)
|
||||
{
|
||||
DrawText("LOADING DATA...", 240, 210, 40, Color.DarkBlue);
|
||||
}
|
||||
break;
|
||||
|
||||
case State.Finished:
|
||||
DrawRectangle(150, 200, 500, 60, Color.Lime);
|
||||
DrawText("DATA LOADED!", 250, 210, 40, Color.Green);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DrawRectangleLines(150, 200, 500, 60, Color.DarkGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - loading thread");
|
||||
|
||||
// Loading data thread id
|
||||
Thread thread = new(new ThreadStart(LoadDataThread));
|
||||
|
||||
State state = State.STATE_WAITING;
|
||||
int framesCounter = 0;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new LoadingThread();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (state)
|
||||
{
|
||||
case State.STATE_WAITING:
|
||||
{
|
||||
if (IsKeyPressed(KEY_ENTER))
|
||||
{
|
||||
thread.Start();
|
||||
//int error = pthread_create(ref, NULL, ref, NULL);
|
||||
//if (error != 0) TraceLog(TraceLogLevel.LOG_ERROR, "Error creating loading thread");
|
||||
//else TraceLog(TraceLogLevel.LOG_INFO, "Loading thread initialized successfully");
|
||||
|
||||
state = State.STATE_LOADING;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case State.STATE_LOADING:
|
||||
{
|
||||
framesCounter++;
|
||||
if (dataLoaded)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = State.STATE_FINISHED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case State.STATE_FINISHED:
|
||||
{
|
||||
if (IsKeyPressed(KEY_ENTER))
|
||||
{
|
||||
// Reset everything to launch again
|
||||
// atomic_store(ref, false);
|
||||
dataProgress = 0;
|
||||
state = State.STATE_WAITING;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case State.STATE_WAITING:
|
||||
DrawText("PRESS ENTER to START LOADING DATA", 150, 170, 20, DARKGRAY);
|
||||
break;
|
||||
case State.STATE_LOADING:
|
||||
{
|
||||
DrawRectangle(150, 200, dataProgress, 60, SKYBLUE);
|
||||
if ((framesCounter / 15) % 2 == 0) DrawText("LOADING DATA...", 240, 210, 40, DARKBLUE);
|
||||
}
|
||||
break;
|
||||
case State.STATE_FINISHED:
|
||||
{
|
||||
DrawRectangle(150, 200, 500, 60, LIME);
|
||||
DrawText("DATA LOADED!", 250, 210, 40, GREEN);
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
DrawRectangleLines(150, 200, 500, 60, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Loading data thread function definition
|
||||
static void LoadDataThread()
|
||||
void LoadDataThread()
|
||||
{
|
||||
int timeCounter = 0; // Time counted in ms
|
||||
// clock_t prevTime = clock(); // Previous time
|
||||
int timeCounter = 0; // Time counted in ms
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
// We simulate data loading with a time counter for 5 seconds
|
||||
while (timeCounter < 5000)
|
||||
{
|
||||
//clock_t currentTime = clock() - prevTime;
|
||||
//timeCounter = currentTime*1000/CLOCKS_PER_SEC;
|
||||
timeCounter += 1;
|
||||
timeCounter = (int)stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// We accumulate time over a global variable to be used in
|
||||
// main thread as a progress bar
|
||||
|
|
@ -158,4 +188,3 @@ public class LoadingThread
|
|||
dataLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
205
Examples/Core/MonitorDetector.cs
Normal file
205
Examples/Core/MonitorDetector.cs
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - monitor detector
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Maicon Santana (@maiconpintoabreu) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Maicon Santana (@maiconpintoabreu)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
[ExcludeFromBrowser("GetMonitorCount() is not implemented on the wasm target")]
|
||||
public partial class MonitorDetector : IExample
|
||||
{
|
||||
private const int MaxMonitors = 10;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Monitor Detector";
|
||||
|
||||
public string Title => "raylib [core] example - monitor detector";
|
||||
|
||||
// Monitor info
|
||||
private struct MonitorInfo
|
||||
{
|
||||
public Vector2 Position;
|
||||
public string Name;
|
||||
public int Width;
|
||||
public int Height;
|
||||
public int PhysicalWidth;
|
||||
public int PhysicalHeight;
|
||||
public int RefreshRate;
|
||||
}
|
||||
|
||||
private MonitorInfo[] monitors;
|
||||
private int currentMonitorIndex;
|
||||
private int monitorCount;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
monitors = new MonitorInfo[MaxMonitors];
|
||||
currentMonitorIndex = GetCurrentMonitor();
|
||||
monitorCount = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Variables to find the max x and Y to calculate the scale
|
||||
int maxWidth = 1;
|
||||
int maxHeight = 1;
|
||||
|
||||
// Monitor offset is to fix when monitor position x is negative
|
||||
int monitorOffsetX = 0;
|
||||
|
||||
// Rebuild monitors array every frame
|
||||
monitorCount = GetMonitorCount();
|
||||
for (int i = 0; i < monitorCount; i++)
|
||||
{
|
||||
monitors[i] = new MonitorInfo
|
||||
{
|
||||
Position = GetMonitorPosition(i),
|
||||
Name = GetMonitorName_(i),
|
||||
Width = GetMonitorWidth(i),
|
||||
Height = GetMonitorHeight(i),
|
||||
PhysicalWidth = GetMonitorPhysicalWidth(i),
|
||||
PhysicalHeight = GetMonitorPhysicalHeight(i),
|
||||
RefreshRate = GetMonitorRefreshRate(i)
|
||||
};
|
||||
|
||||
if (monitors[i].Position.X < monitorOffsetX)
|
||||
{
|
||||
monitorOffsetX = -(int)monitors[i].Position.X;
|
||||
}
|
||||
|
||||
int width = (int)monitors[i].Position.X + monitors[i].Width;
|
||||
int height = (int)monitors[i].Position.Y + monitors[i].Height;
|
||||
|
||||
if (maxWidth < width)
|
||||
{
|
||||
maxWidth = width;
|
||||
}
|
||||
if (maxHeight < height)
|
||||
{
|
||||
maxHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Enter) && (monitorCount > 1))
|
||||
{
|
||||
currentMonitorIndex += 1;
|
||||
|
||||
// Set index to 0 if the last one
|
||||
if (currentMonitorIndex == monitorCount)
|
||||
{
|
||||
currentMonitorIndex = 0;
|
||||
}
|
||||
|
||||
SetWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex
|
||||
}
|
||||
else
|
||||
{
|
||||
currentMonitorIndex = GetCurrentMonitor(); // Get currentMonitorIndex if manually moved
|
||||
}
|
||||
|
||||
float monitorScale = 0.6f;
|
||||
|
||||
if (maxHeight > (maxWidth + monitorOffsetX))
|
||||
{
|
||||
monitorScale *= ((float)screenHeight / (float)maxHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
monitorScale *= ((float)screenWidth / (float)(maxWidth + monitorOffsetX));
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Press [Enter] to move window to next monitor available", 20, 20, 20, Color.DarkGray);
|
||||
|
||||
DrawRectangleLines(20, 60, screenWidth - 40, screenHeight - 100, Color.DarkGray);
|
||||
|
||||
// Draw Monitor Rectangles with information inside
|
||||
for (int i = 0; i < monitorCount; i++)
|
||||
{
|
||||
// Calculate retangle position and size using monitorScale
|
||||
Rectangle rec = new Rectangle(
|
||||
(monitors[i].Position.X + monitorOffsetX) * monitorScale + 140,
|
||||
monitors[i].Position.Y * monitorScale + 80,
|
||||
monitors[i].Width * monitorScale,
|
||||
monitors[i].Height * monitorScale
|
||||
);
|
||||
|
||||
// Draw monitor name and information inside the rectangle
|
||||
DrawText($"[{i}] {monitors[i].Name}", (int)rec.X + 10, (int)rec.Y + (int)(100 * monitorScale), (int)(120 * monitorScale), Color.Blue);
|
||||
DrawText(
|
||||
$"Resolution: [{monitors[i].Width}px x {monitors[i].Height}px]\nRefreshRate: [{monitors[i].RefreshRate}hz]\nPhysical Size: [{monitors[i].PhysicalWidth}mm x {monitors[i].PhysicalHeight}mm]\nPosition: {monitors[i].Position.X,3:F0} x {monitors[i].Position.Y,3:F0}",
|
||||
(int)rec.X + 10, (int)rec.Y + (int)(200 * monitorScale), (int)(120 * monitorScale), Color.DarkGray);
|
||||
|
||||
// Highlight current monitor
|
||||
if (i == currentMonitorIndex)
|
||||
{
|
||||
DrawRectangleLinesEx(rec, 5, Color.Red);
|
||||
Vector2 windowPosition = new Vector2((GetWindowPosition().X + monitorOffsetX) * monitorScale + 140, GetWindowPosition().Y * monitorScale + 80);
|
||||
|
||||
// Draw window position based on monitors
|
||||
DrawRectangleV(windowPosition, new Vector2(screenWidth * monitorScale, screenHeight * monitorScale), Fade(Color.Green, 0.5f));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangleLinesEx(rec, 5, Color.Gray);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor detector");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new MonitorDetector();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,119 +1,162 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Picking in 3d mode
|
||||
* raylib [core] example - 3d picking
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class Picking3d
|
||||
public partial class Picking3d : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Picking 3D";
|
||||
|
||||
public string Title => "raylib [core] example - 3d picking";
|
||||
|
||||
private Camera3D camera;
|
||||
private Vector3 cubePosition;
|
||||
private Vector3 cubeSize;
|
||||
private Ray ray; // Picking line ray
|
||||
private RayCollision collision; // Ray collision hit info
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new Camera3D();
|
||||
camera.Position = new Vector3(10.0f, 10.0f, 10.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
cubePosition = new(0.0f, 1.0f, 0.0f);
|
||||
cubeSize = new(2.0f, 2.0f, 2.0f);
|
||||
|
||||
ray = new(); // Picking line ray
|
||||
collision = new(); // Ray collision hit info
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsCursorHidden())
|
||||
{
|
||||
UpdateCamera(ref camera, CameraMode.FirstPerson);
|
||||
}
|
||||
|
||||
// Toggle camera controls
|
||||
if (IsMouseButtonPressed(MouseButton.Right))
|
||||
{
|
||||
if (IsCursorHidden())
|
||||
{
|
||||
EnableCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
DisableCursor();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
if (!collision.Hit)
|
||||
{
|
||||
ray = GetScreenToWorldRay(GetMousePosition(), camera);
|
||||
|
||||
// Check collision between ray and box
|
||||
BoundingBox box = new(
|
||||
cubePosition - cubeSize / 2,
|
||||
cubePosition + cubeSize / 2
|
||||
);
|
||||
collision = GetRayCollisionBox(ray, box);
|
||||
}
|
||||
else
|
||||
{
|
||||
collision.Hit = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
if (collision.Hit)
|
||||
{
|
||||
DrawCube(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.Red);
|
||||
DrawCubeWires(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.Maroon);
|
||||
|
||||
DrawCubeWires(cubePosition, cubeSize.X + 0.2f, cubeSize.Y + 0.2f, cubeSize.Z + 0.2f, Color.Green);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCube(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.Gray);
|
||||
DrawCubeWires(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.DarkGray);
|
||||
}
|
||||
|
||||
DrawRay(ray, Color.Maroon);
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Try clicking on the box with your mouse!", 240, 10, 20, Color.DarkGray);
|
||||
|
||||
if (collision.Hit)
|
||||
{
|
||||
var posX = (screenWidth - MeasureText("BOX SELECTED", 30)) / 2;
|
||||
DrawText("BOX SELECTED", posX, (int)(screenHeight * 0.1f), 30, Color.Green);
|
||||
}
|
||||
|
||||
DrawText("Right click mouse to toggle camera controls", 10, 430, 10, Color.Gray);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera;
|
||||
camera.Position = new Vector3(10.0f, 10.0f, 10.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
Vector3 cubePosition = new(0.0f, 1.0f, 0.0f);
|
||||
Vector3 cubeSize = new(2.0f, 2.0f, 2.0f);
|
||||
|
||||
// Picking line ray
|
||||
Ray ray = new(new Vector3(0.0f, 0.0f, 0.0f), Vector3.Zero);
|
||||
RayCollision collision = new();
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Picking3d();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
|
||||
if (IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
if (!collision.Hit)
|
||||
{
|
||||
ray = GetScreenToWorldRay(GetMousePosition(), camera);
|
||||
|
||||
// Check collision between ray and box
|
||||
BoundingBox box = new(
|
||||
cubePosition - cubeSize / 2,
|
||||
cubePosition + cubeSize / 2
|
||||
);
|
||||
collision = GetRayCollisionBox(ray, box);
|
||||
}
|
||||
else
|
||||
{
|
||||
collision.Hit = false;
|
||||
}
|
||||
|
||||
ray = GetScreenToWorldRay(GetMousePosition(), camera);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
if (collision.Hit)
|
||||
{
|
||||
DrawCube(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.Red);
|
||||
DrawCubeWires(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.Maroon);
|
||||
|
||||
DrawCubeWires(cubePosition, cubeSize.X + 0.2f, cubeSize.Y + 0.2f, cubeSize.Z + 0.2f, Color.Green);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCube(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.Gray);
|
||||
DrawCubeWires(cubePosition, cubeSize.X, cubeSize.Y, cubeSize.Z, Color.DarkGray);
|
||||
}
|
||||
|
||||
DrawRay(ray, Color.Maroon);
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Try selecting the box with mouse!", 240, 10, 20, Color.DarkGray);
|
||||
|
||||
if (collision.Hit)
|
||||
{
|
||||
int posX = (screenWidth - MeasureText("BOX SELECTED", 30)) / 2;
|
||||
DrawText("BOX SELECTED", posX, (int)(screenHeight * 0.1f), 30, Color.Green);
|
||||
}
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
180
Examples/Core/RandomSequence.cs
Normal file
180
Examples/Core/RandomSequence.cs
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - random sequence
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* Example contributed by Dalton Overmyer (@REDl3east) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2023-2025 Dalton Overmyer (@REDl3east)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raymath;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class RandomSequence : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Random Sequence";
|
||||
|
||||
public string Title => "raylib [core] example - random sequence";
|
||||
|
||||
private struct ColorRect
|
||||
{
|
||||
public Color Color;
|
||||
public Rectangle Rect;
|
||||
}
|
||||
|
||||
private int rectCount;
|
||||
private float rectSize;
|
||||
private ColorRect[] rectangles;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
rectCount = 20;
|
||||
rectSize = (float)screenWidth / rectCount;
|
||||
rectangles = GenerateRandomColorRectSequence(rectCount, rectSize, screenWidth, 0.75f * screenHeight);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
ShuffleColorRectSequence(rectangles, rectCount);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Up))
|
||||
{
|
||||
rectCount++;
|
||||
rectSize = (float)screenWidth / rectCount;
|
||||
|
||||
// Re-generate random sequence with new count
|
||||
rectangles = GenerateRandomColorRectSequence(rectCount, rectSize, screenWidth, 0.75f * screenHeight);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Down))
|
||||
{
|
||||
if (rectCount >= 4)
|
||||
{
|
||||
rectCount--;
|
||||
rectSize = (float)screenWidth / rectCount;
|
||||
|
||||
// Re-generate random sequence with new count
|
||||
rectangles = GenerateRandomColorRectSequence(rectCount, rectSize, screenWidth, 0.75f * screenHeight);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
for (int i = 0; i < rectCount; i++)
|
||||
{
|
||||
DrawRectangleRec(rectangles[i].Rect, rectangles[i].Color);
|
||||
|
||||
DrawText("Press SPACE to shuffle the current sequence", 10, screenHeight - 96, 20, Color.Black);
|
||||
DrawText("Press UP to add a rectangle and generate a new sequence", 10, screenHeight - 64, 20, Color.Black);
|
||||
DrawText("Press DOWN to remove a rectangle and generate a new sequence", 10, screenHeight - 32, 20, Color.Black);
|
||||
}
|
||||
|
||||
DrawText($"Count: {rectCount} rectangles", 10, 10, 20, Color.Maroon);
|
||||
|
||||
DrawFPS(screenWidth - 80, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
private static Color GenerateRandomColor()
|
||||
{
|
||||
return new Color(
|
||||
GetRandomValue(0, 255),
|
||||
GetRandomValue(0, 255),
|
||||
GetRandomValue(0, 255),
|
||||
255
|
||||
);
|
||||
}
|
||||
|
||||
private static ColorRect[] GenerateRandomColorRectSequence(float rectCount, float rectWidth, float screenWidth, float screenHeight)
|
||||
{
|
||||
ColorRect[] rectangles = new ColorRect[(int)rectCount];
|
||||
|
||||
int[] seq = GetRandomSequence((uint)rectCount, 0, (int)rectCount - 1);
|
||||
float rectSeqWidth = rectCount * rectWidth;
|
||||
float startX = (screenWidth - rectSeqWidth) * 0.5f;
|
||||
|
||||
for (int i = 0; i < rectCount; i++)
|
||||
{
|
||||
int rectHeight = (int)Remap(seq[i], 0, rectCount - 1, 0, screenHeight);
|
||||
|
||||
rectangles[i].Color = GenerateRandomColor();
|
||||
rectangles[i].Rect = new Rectangle(startX + i * rectWidth, screenHeight - rectHeight, rectWidth, rectHeight);
|
||||
}
|
||||
|
||||
return rectangles;
|
||||
}
|
||||
|
||||
private static void ShuffleColorRectSequence(ColorRect[] rectangles, int rectCount)
|
||||
{
|
||||
int[] seq = GetRandomSequence((uint)rectCount, 0, rectCount - 1);
|
||||
|
||||
for (int i1 = 0; i1 < rectCount; i1++)
|
||||
{
|
||||
int i2 = seq[i1];
|
||||
|
||||
// Swap only the color and height
|
||||
ColorRect tmp = rectangles[i1];
|
||||
rectangles[i1].Color = rectangles[i2].Color;
|
||||
rectangles[i1].Rect.Height = rectangles[i2].Rect.Height;
|
||||
rectangles[i1].Rect.Y = rectangles[i2].Rect.Y;
|
||||
rectangles[i2].Color = tmp.Color;
|
||||
rectangles[i2].Rect.Height = tmp.Rect.Height;
|
||||
rectangles[i2].Rect.Y = tmp.Rect.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - random sequence");
|
||||
|
||||
SetTargetFPS(60);
|
||||
|
||||
var game = new RandomSequence();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +1,95 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Generate random values
|
||||
* raylib [core] example - random values
|
||||
*
|
||||
* This example has been created using raylib 1.1 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.1, last time updated with raylib 1.1
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class RandomValues
|
||||
public partial class RandomValues : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Random Values";
|
||||
|
||||
public string Title => "raylib [core] example - random values";
|
||||
|
||||
private int randValue; // Get a random integer number between -8 and 5 (both included)
|
||||
private int framesCounter; // Variable used to count frames
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// SetRandomSeed(0xaabbccff); // Set a custom random seed if desired, by default: "time(NULL)"
|
||||
|
||||
randValue = GetRandomValue(-8, 5); // Get a random integer number between -8 and 5 (both included)
|
||||
|
||||
framesCounter = 0; // Variable used to count frames
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
framesCounter++;
|
||||
|
||||
// Every two seconds (120 frames) a new random value is generated
|
||||
if (((framesCounter / 120) % 2) == 1)
|
||||
{
|
||||
randValue = GetRandomValue(-8, 5);
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Every 2 seconds a new random value is generated:", 130, 100, 20, Color.Maroon);
|
||||
|
||||
DrawText($"{randValue}", 360, 180, 80, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - random values");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - generate random values");
|
||||
|
||||
// Variable used to count frames
|
||||
int framesCounter = 0;
|
||||
|
||||
// Get a random integer number between -8 and 5 (both included)
|
||||
int randValue = GetRandomValue(-8, 5);
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new RandomValues();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
framesCounter++;
|
||||
|
||||
// Every two seconds (120 frames) a new random value is generated
|
||||
if (((framesCounter / 120) % 2) == 1)
|
||||
{
|
||||
randValue = GetRandomValue(-8, 5);
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Every 2 seconds a new random value is generated:", 130, 100, 20, Color.Maroon);
|
||||
|
||||
DrawText($"{randValue}", 360, 180, 80, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
135
Examples/Core/RenderTexture.cs
Normal file
135
Examples/Core/RenderTexture.cs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - render texture
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class RenderTextureDemo : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// Define a render texture to render
|
||||
private const int renderTextureWidth = 300;
|
||||
private const int renderTextureHeight = 300;
|
||||
|
||||
public string Name => "Core / Render Texture";
|
||||
|
||||
public string Title => "raylib [core] example - render texture";
|
||||
|
||||
private RenderTexture2D target;
|
||||
private Vector2 ballPosition;
|
||||
private Vector2 ballSpeed;
|
||||
private int ballRadius;
|
||||
private float rotation;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
target = LoadRenderTexture(renderTextureWidth, renderTextureHeight);
|
||||
|
||||
ballPosition = new Vector2(renderTextureWidth / 2.0f, renderTextureHeight / 2.0f);
|
||||
ballSpeed = new Vector2(5.0f, 4.0f);
|
||||
ballRadius = 20;
|
||||
|
||||
rotation = 0.0f;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//-----------------------------------------------------
|
||||
// Ball movement logic
|
||||
ballPosition.X += ballSpeed.X;
|
||||
ballPosition.Y += ballSpeed.Y;
|
||||
|
||||
// Check walls collision for bouncing
|
||||
if ((ballPosition.X >= (renderTextureWidth - ballRadius)) || (ballPosition.X <= ballRadius))
|
||||
{
|
||||
ballSpeed.X *= -1.0f;
|
||||
}
|
||||
if ((ballPosition.Y >= (renderTextureHeight - ballRadius)) || (ballPosition.Y <= ballRadius))
|
||||
{
|
||||
ballSpeed.Y *= -1.0f;
|
||||
}
|
||||
|
||||
// Render texture rotation
|
||||
rotation += 0.5f;
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//-----------------------------------------------------
|
||||
// Draw our scene to the render texture
|
||||
BeginTextureMode(target);
|
||||
|
||||
ClearBackground(Color.SkyBlue);
|
||||
|
||||
DrawRectangle(0, 0, 20, 20, Color.Red);
|
||||
DrawCircleV(ballPosition, ballRadius, Color.Maroon);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw render texture to main framebuffer
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw our render texture with rotation applied
|
||||
// NOTE 1: We set the origin of the texture to the center of the render texture
|
||||
// NOTE 2: We flip vertically the texture setting negative source rectangle height
|
||||
DrawTexturePro(target.Texture,
|
||||
new Rectangle(0, 0, target.Texture.Width, -target.Texture.Height),
|
||||
new Rectangle(screenWidth / 2.0f, screenHeight / 2.0f, target.Texture.Width, target.Texture.Height),
|
||||
new Vector2(target.Texture.Width / 2.0f, target.Texture.Height / 2.0f), rotation, Color.White);
|
||||
|
||||
DrawText("DRAWING BOUNCING BALL INSIDE RENDER TEXTURE!", 10, screenHeight - 40, 20, Color.Black);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//-----------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTexture(target);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//---------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - render texture");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//----------------------------------------------------------
|
||||
|
||||
var game = new RenderTextureDemo();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//---------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//----------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +1,108 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Scissor test
|
||||
* raylib [core] example - scissor test
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.0
|
||||
*
|
||||
* Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 Chris Dill (@MysteriousSpace)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2019-2025 Chris Dill (@MysteriousSpace)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class ScissorTest
|
||||
public partial class ScissorTest : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Scissor Test";
|
||||
|
||||
public string Title => "raylib [core] example - scissor test";
|
||||
|
||||
private Rectangle scissorArea;
|
||||
private bool scissorMode;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
scissorArea = new(0, 0, 300, 300);
|
||||
scissorMode = true;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.S))
|
||||
{
|
||||
scissorMode = !scissorMode;
|
||||
}
|
||||
|
||||
// Centre the scissor area around the mouse position
|
||||
scissorArea.X = GetMouseX() - scissorArea.Width / 2;
|
||||
scissorArea.Y = GetMouseY() - scissorArea.Height / 2;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (scissorMode)
|
||||
{
|
||||
BeginScissorMode((int)scissorArea.X, (int)scissorArea.Y, (int)scissorArea.Width, (int)scissorArea.Height);
|
||||
}
|
||||
|
||||
// Draw full screen rectangle and some text
|
||||
// NOTE: Only part defined by scissor area will be rendered
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Color.Red);
|
||||
DrawText("Move the mouse around to reveal this text!", 190, 200, 20, Color.LightGray);
|
||||
|
||||
if (scissorMode)
|
||||
{
|
||||
EndScissorMode();
|
||||
}
|
||||
|
||||
DrawRectangleLinesEx(scissorArea, 1, Color.Black);
|
||||
DrawText("Press S to toggle scissor test", 10, 10, 20, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - scissor test");
|
||||
|
||||
Rectangle scissorArea = new(0, 0, 300, 300);
|
||||
bool scissorMode = true;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new ScissorTest();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.S))
|
||||
{
|
||||
scissorMode = !scissorMode;
|
||||
}
|
||||
|
||||
// Centre the scissor area around the mouse position
|
||||
scissorArea.X = GetMouseX() - scissorArea.Width / 2;
|
||||
scissorArea.Y = GetMouseY() - scissorArea.Height / 2;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (scissorMode)
|
||||
{
|
||||
BeginScissorMode((int)scissorArea.X, (int)scissorArea.Y, (int)scissorArea.Width, (int)scissorArea.Height);
|
||||
}
|
||||
|
||||
// Draw full screen rectangle and some text
|
||||
// NOTE: Only part defined by scissor area will be rendered
|
||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Color.Red);
|
||||
DrawText("Move the mouse around to reveal this text!", 190, 200, 20, Color.LightGray);
|
||||
|
||||
if (scissorMode)
|
||||
{
|
||||
EndScissorMode();
|
||||
}
|
||||
|
||||
DrawRectangleLinesEx(scissorArea, 1, Color.Black);
|
||||
DrawText("Press S to toggle scissor test", 10, 10, 20, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
394
Examples/Core/ScreenRecording.cs
Normal file
394
Examples/Core/ScreenRecording.cs
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - screen recording
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
// NOTE: The upstream C example records frames into an animated GIF using the bundled msf_gif.h
|
||||
// single-header library. raylib-cs does not bind msf_gif, so this port replaces it with a small,
|
||||
// self-contained GIF89a encoder (GifRecorder, below) that uses a fixed 3-3-2 RGB palette. The
|
||||
// rest of the example (rendering, CTRL+R toggle, saving to <appdir>/screenrecording.gif) mirrors
|
||||
// upstream. Frame capture via LoadImageFromScreen() is slow and can cause stuttering, as noted
|
||||
// upstream.
|
||||
[ExcludeFromBrowser("desktop screen capture + gif file export, no web equivalent")]
|
||||
public partial class ScreenRecording : IExample
|
||||
{
|
||||
private const int GIF_RECORD_FRAMERATE = 5; // Record framerate, we get a frame every N frames
|
||||
|
||||
private const int MAX_SINEWAVE_POINTS = 256;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Screen Recording";
|
||||
|
||||
public string Title => "raylib [core] example - screen recording";
|
||||
|
||||
private bool gifRecording; // GIF recording state
|
||||
private uint gifFrameCounter; // GIF frames counter
|
||||
private GifRecorder gifState; // GIF context state
|
||||
|
||||
private Vector2 circlePosition;
|
||||
private float timeCounter;
|
||||
|
||||
private Vector2[] sinePoints;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
gifRecording = false;
|
||||
gifFrameCounter = 0;
|
||||
gifState = new GifRecorder();
|
||||
|
||||
circlePosition = new Vector2(0.0f, screenHeight / 2.0f);
|
||||
timeCounter = 0.0f;
|
||||
|
||||
// Get sine wave points for line drawing
|
||||
sinePoints = new Vector2[MAX_SINEWAVE_POINTS];
|
||||
for (int i = 0; i < MAX_SINEWAVE_POINTS; i++)
|
||||
{
|
||||
sinePoints[i].X = i * GetScreenWidth() / 180.0f;
|
||||
sinePoints[i].Y = screenHeight / 2.0f + 150 * MathF.Sin((2 * MathF.PI / 1.5f) * (1.0f / 60.0f) * (float)i); // Calculate for 60 fps
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Update circle sinusoidal movement
|
||||
timeCounter += GetFrameTime();
|
||||
circlePosition.X += GetScreenWidth() / 180.0f;
|
||||
circlePosition.Y = screenHeight / 2.0f + 150 * MathF.Sin((2 * MathF.PI / 1.5f) * timeCounter);
|
||||
if (circlePosition.X > screenWidth)
|
||||
{
|
||||
circlePosition.X = 0.0f;
|
||||
circlePosition.Y = screenHeight / 2.0f;
|
||||
timeCounter = 0.0f;
|
||||
}
|
||||
|
||||
// Start-Stop GIF recording on CTRL+R
|
||||
if (IsKeyDown(KeyboardKey.LeftControl) && IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
if (gifRecording)
|
||||
{
|
||||
// Stop current recording and save file
|
||||
gifRecording = false;
|
||||
byte[] result = gifState.End();
|
||||
SaveFileData(result, $"{GetApplicationDirectoryString()}/screenrecording.gif");
|
||||
|
||||
TraceLog(TraceLogLevel.Info, "Finish animated GIF recording");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start a new recording
|
||||
gifRecording = true;
|
||||
gifFrameCounter = 0;
|
||||
gifState.Begin(GetRenderWidth(), GetRenderHeight());
|
||||
|
||||
TraceLog(TraceLogLevel.Info, "Start animated GIF recording");
|
||||
}
|
||||
}
|
||||
|
||||
if (gifRecording)
|
||||
{
|
||||
gifFrameCounter++;
|
||||
|
||||
// NOTE: We record one gif frame depending on the desired gif framerate
|
||||
if (gifFrameCounter > GIF_RECORD_FRAMERATE)
|
||||
{
|
||||
// Get image data for the current frame (from backbuffer)
|
||||
// WARNING: This process is quite slow, it can generate stuttering
|
||||
Image imScreen = LoadImageFromScreen();
|
||||
|
||||
// Add the frame to the gif recording, providing and "estimated" time for display in centiseconds
|
||||
int delayCs = (int)((1.0f / 60.0f) * GIF_RECORD_FRAMERATE) / 10;
|
||||
gifState.AddFrame((byte*)imScreen.Data, imScreen.Width, imScreen.Height, imScreen.Width * 4, delayCs);
|
||||
gifFrameCounter = 0;
|
||||
|
||||
UnloadImage(imScreen); // Free image data
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
for (int i = 0; i < (MAX_SINEWAVE_POINTS - 1); i++)
|
||||
{
|
||||
DrawLineV(sinePoints[i], sinePoints[i + 1], Color.Maroon);
|
||||
DrawCircleV(sinePoints[i], 3, Color.Maroon);
|
||||
}
|
||||
|
||||
DrawCircleV(circlePosition, 30, Color.Red);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
/*
|
||||
// Draw record indicator
|
||||
// WARNING: If drawn here, it will appear in the recorded image,
|
||||
// use a render texture instead for the recording and LoadImageFromTexture(rt.texture)
|
||||
if (gifRecording)
|
||||
{
|
||||
// Display the recording indicator every half-second
|
||||
if ((int)(GetTime()/0.5)%2 == 1)
|
||||
{
|
||||
DrawCircle(30, GetScreenHeight() - 20, 10, Color.Maroon);
|
||||
DrawText("GIF RECORDING", 50, GetScreenHeight() - 25, 10, Color.Red);
|
||||
}
|
||||
}
|
||||
*/
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// If still recording a GIF on close window, just finish
|
||||
if (gifRecording)
|
||||
{
|
||||
gifState.End();
|
||||
gifRecording = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - screen recording");
|
||||
|
||||
var game = new ScreenRecording();
|
||||
game.Init();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Minimal self-contained animated GIF89a encoder (replacement for msf_gif.h)
|
||||
// Uses a fixed 3-3-2 RGB global palette and standard GIF-variant LZW compression.
|
||||
private class GifRecorder
|
||||
{
|
||||
private List<byte> output;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
// LZW bit-packing state (per-frame)
|
||||
private int bitBuffer;
|
||||
private int bitCount;
|
||||
private List<byte> subBlock;
|
||||
|
||||
public void Begin(int w, int h)
|
||||
{
|
||||
width = w;
|
||||
height = h;
|
||||
output = new List<byte>();
|
||||
|
||||
// Header
|
||||
output.AddRange(new byte[] { (byte)'G', (byte)'I', (byte)'F', (byte)'8', (byte)'9', (byte)'a' });
|
||||
|
||||
// Logical Screen Descriptor
|
||||
WriteU16(width);
|
||||
WriteU16(height);
|
||||
output.Add(0xF7); // Global color table present, 8-bit color res, 256-entry table
|
||||
output.Add(0x00); // Background color index
|
||||
output.Add(0x00); // Pixel aspect ratio
|
||||
|
||||
// Global Color Table: 256 entries, 3-3-2 RGB
|
||||
for (int k = 0; k < 256; k++)
|
||||
{
|
||||
int r3 = (k >> 5) & 0x7;
|
||||
int g3 = (k >> 2) & 0x7;
|
||||
int b2 = k & 0x3;
|
||||
output.Add((byte)((r3 << 5) | (r3 << 2) | (r3 >> 1)));
|
||||
output.Add((byte)((g3 << 5) | (g3 << 2) | (g3 >> 1)));
|
||||
output.Add((byte)((b2 << 6) | (b2 << 4) | (b2 << 2) | b2));
|
||||
}
|
||||
|
||||
// NETSCAPE2.0 application extension (loop forever)
|
||||
output.Add(0x21);
|
||||
output.Add(0xFF);
|
||||
output.Add(0x0B);
|
||||
output.AddRange(new byte[] { (byte)'N', (byte)'E', (byte)'T', (byte)'S', (byte)'C', (byte)'A', (byte)'P', (byte)'E', (byte)'2', (byte)'.', (byte)'0' });
|
||||
output.Add(0x03);
|
||||
output.Add(0x01);
|
||||
WriteU16(0); // Loop count (0 = forever)
|
||||
output.Add(0x00);
|
||||
}
|
||||
|
||||
public unsafe void AddFrame(byte* data, int w, int h, int stride, int delayCs)
|
||||
{
|
||||
if (output == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Graphic Control Extension
|
||||
output.Add(0x21);
|
||||
output.Add(0xF9);
|
||||
output.Add(0x04);
|
||||
output.Add(0x00); // No transparency, disposal method 0
|
||||
WriteU16(delayCs);
|
||||
output.Add(0x00); // Transparent color index
|
||||
output.Add(0x00); // Block terminator
|
||||
|
||||
// Image Descriptor
|
||||
output.Add(0x2C);
|
||||
WriteU16(0); // Left
|
||||
WriteU16(0); // Top
|
||||
WriteU16(w);
|
||||
WriteU16(h);
|
||||
output.Add(0x00); // No local color table, not interlaced
|
||||
|
||||
// Map pixels to palette indices (3-3-2)
|
||||
byte[] indices = new byte[w * h];
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
int row = y * stride;
|
||||
int dst = y * w;
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
byte r = data[row + x * 4 + 0];
|
||||
byte g = data[row + x * 4 + 1];
|
||||
byte b = data[row + x * 4 + 2];
|
||||
indices[dst + x] = (byte)((r & 0xE0) | ((g & 0xE0) >> 3) | (b >> 6));
|
||||
}
|
||||
}
|
||||
|
||||
// LZW image data
|
||||
const int minCodeSize = 8;
|
||||
output.Add((byte)minCodeSize);
|
||||
|
||||
bitBuffer = 0;
|
||||
bitCount = 0;
|
||||
subBlock = new List<byte>();
|
||||
|
||||
int clearCode = 1 << minCodeSize; // 256
|
||||
int stopCode = clearCode + 1; // 257
|
||||
int keySize = minCodeSize + 1; // 9
|
||||
int nkeys = clearCode + 2; // 258
|
||||
var dict = new Dictionary<int, int>();
|
||||
|
||||
WriteBits(clearCode, keySize);
|
||||
|
||||
int key = indices[0];
|
||||
for (int i = 1; i < indices.Length; i++)
|
||||
{
|
||||
int p = indices[i];
|
||||
int combined = (key << 8) | p;
|
||||
if (dict.TryGetValue(combined, out int existing))
|
||||
{
|
||||
key = existing;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteBits(key, keySize);
|
||||
dict[combined] = nkeys;
|
||||
nkeys++;
|
||||
if (nkeys == (1 << keySize))
|
||||
{
|
||||
if (keySize < 12)
|
||||
{
|
||||
keySize++;
|
||||
}
|
||||
}
|
||||
if (nkeys == 0x1000)
|
||||
{
|
||||
WriteBits(clearCode, keySize);
|
||||
dict.Clear();
|
||||
keySize = minCodeSize + 1;
|
||||
nkeys = clearCode + 2;
|
||||
}
|
||||
key = p;
|
||||
}
|
||||
}
|
||||
|
||||
WriteBits(key, keySize);
|
||||
WriteBits(stopCode, keySize);
|
||||
|
||||
// Flush remaining bits
|
||||
if (bitCount > 0)
|
||||
{
|
||||
subBlock.Add((byte)(bitBuffer & 0xFF));
|
||||
bitBuffer = 0;
|
||||
bitCount = 0;
|
||||
}
|
||||
if (subBlock.Count > 0)
|
||||
{
|
||||
FlushSubBlock();
|
||||
}
|
||||
|
||||
output.Add(0x00); // Image data block terminator
|
||||
}
|
||||
|
||||
public byte[] End()
|
||||
{
|
||||
if (output == null)
|
||||
{
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
|
||||
output.Add(0x3B); // Trailer
|
||||
byte[] result = output.ToArray();
|
||||
output = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
private void WriteBits(int code, int len)
|
||||
{
|
||||
bitBuffer |= code << bitCount;
|
||||
bitCount += len;
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
subBlock.Add((byte)(bitBuffer & 0xFF));
|
||||
bitBuffer >>= 8;
|
||||
bitCount -= 8;
|
||||
if (subBlock.Count == 255)
|
||||
{
|
||||
FlushSubBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FlushSubBlock()
|
||||
{
|
||||
output.Add((byte)subBlock.Count);
|
||||
output.AddRange(subBlock);
|
||||
subBlock.Clear();
|
||||
}
|
||||
|
||||
private void WriteU16(int value)
|
||||
{
|
||||
output.Add((byte)(value & 0xFF));
|
||||
output.Add((byte)((value >> 8) & 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,134 +1,210 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - smooth pixel-perfect camera
|
||||
* raylib [core] example - smooth pixelperfect
|
||||
*
|
||||
* This example has been created using raylib 3.7 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 3.7, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Giancamillo Alessandroni (@NotManyIdeasDev) and
|
||||
* reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2021 Giancamillo Alessandroni (@NotManyIdeasDev) and Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2021-2025 Giancamillo Alessandroni (@NotManyIdeasDev) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public static class SmoothPixelPerfect
|
||||
public partial class SmoothPixelPerfect : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private const int virtualScreenWidth = 160;
|
||||
private const int virtualScreenHeight = 90;
|
||||
|
||||
private const float virtualRatio = (float)screenWidth / (float)virtualScreenWidth;
|
||||
|
||||
public string Name => "Core / Smooth Pixelperfect";
|
||||
|
||||
public string Title => "raylib [core] example - smooth pixelperfect";
|
||||
|
||||
private Camera2D worldSpaceCamera; // Game world camera
|
||||
private Camera2D screenSpaceCamera; // Smoothing camera
|
||||
private RenderTexture2D target;
|
||||
|
||||
private Rectangle rec01;
|
||||
private Rectangle rec02;
|
||||
private Rectangle rec03;
|
||||
|
||||
private Rectangle sourceRec;
|
||||
private Rectangle destRec;
|
||||
|
||||
private Vector2 origin;
|
||||
private float rotation;
|
||||
private float cameraX;
|
||||
private float cameraY;
|
||||
private bool smoothOn;
|
||||
private bool overscan;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
const int virtualScreenWidth = 160;
|
||||
const int virtualScreenHeight = 90;
|
||||
|
||||
const float virtualRatio = (float)screenWidth / (float)virtualScreenWidth;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - smooth pixel-perfect camera");
|
||||
|
||||
// Game world camera
|
||||
Camera2D worldSpaceCamera = new();
|
||||
worldSpaceCamera = new(); // Game world camera
|
||||
worldSpaceCamera.Zoom = 1.0f;
|
||||
|
||||
// Smoothing camera
|
||||
Camera2D screenSpaceCamera = new();
|
||||
screenSpaceCamera = new(); // Smoothing camera
|
||||
screenSpaceCamera.Zoom = 1.0f;
|
||||
|
||||
// This is where we'll draw all our objects.
|
||||
RenderTexture2D target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight);
|
||||
// Load render texture to draw all our objects
|
||||
target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight);
|
||||
|
||||
Rectangle rec01 = new(70.0f, 35.0f, 20.0f, 20.0f);
|
||||
Rectangle rec02 = new(90.0f, 55.0f, 30.0f, 10.0f);
|
||||
Rectangle rec03 = new(80.0f, 65.0f, 15.0f, 25.0f);
|
||||
rec01 = new(70.0f, 35.0f, 20.0f, 20.0f);
|
||||
rec02 = new(90.0f, 55.0f, 30.0f, 10.0f);
|
||||
rec03 = new(80.0f, 65.0f, 15.0f, 25.0f);
|
||||
|
||||
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
|
||||
Rectangle sourceRec = new(
|
||||
sourceRec = new(
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)target.Texture.Width,
|
||||
-(float)target.Texture.Height
|
||||
);
|
||||
Rectangle destRec = new(
|
||||
-virtualRatio,
|
||||
-virtualRatio,
|
||||
screenWidth + (virtualRatio * 2),
|
||||
screenHeight + (virtualRatio * 2)
|
||||
destRec = new(
|
||||
(screenWidth - screenWidth / 1.25f) / 2.0f,
|
||||
(screenHeight - screenHeight / 1.25f) / 2.0f,
|
||||
screenWidth / 1.25f,
|
||||
screenHeight / 1.25f
|
||||
);
|
||||
|
||||
Vector2 origin = new(0.0f, 0.0f);
|
||||
origin = new(0.0f, 0.0f);
|
||||
|
||||
float rotation = 0.0f;
|
||||
rotation = 0.0f;
|
||||
|
||||
float cameraX = 0.0f;
|
||||
float cameraY = 0.0f;
|
||||
cameraX = 0.0f;
|
||||
cameraY = 0.0f;
|
||||
|
||||
smoothOn = true;
|
||||
overscan = false;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rotation += 60.0f * GetFrameTime(); // Rotate the rectangles, 60 degrees per second
|
||||
|
||||
// Make the camera move to demonstrate the effect
|
||||
cameraX = (MathF.Sin((float)GetTime()) * 50.0f) - 10.0f;
|
||||
cameraY = MathF.Cos((float)GetTime()) * 30.0f;
|
||||
|
||||
// Set the camera's target to the values computed above
|
||||
screenSpaceCamera.Target = new Vector2(cameraX, cameraY);
|
||||
|
||||
// Round worldSpace coordinates, keep decimals into screenSpace coordinates
|
||||
worldSpaceCamera.Target.X = MathF.Truncate(screenSpaceCamera.Target.X);
|
||||
screenSpaceCamera.Target.X -= worldSpaceCamera.Target.X;
|
||||
screenSpaceCamera.Target.X *= virtualRatio;
|
||||
|
||||
worldSpaceCamera.Target.Y = MathF.Truncate(screenSpaceCamera.Target.Y);
|
||||
screenSpaceCamera.Target.Y -= worldSpaceCamera.Target.Y;
|
||||
screenSpaceCamera.Target.Y *= virtualRatio;
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.S))
|
||||
{
|
||||
smoothOn = !smoothOn;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.O))
|
||||
{
|
||||
overscan = !overscan;
|
||||
}
|
||||
|
||||
if (overscan)
|
||||
{
|
||||
destRec = new Rectangle(
|
||||
-virtualRatio,
|
||||
-virtualRatio,
|
||||
screenWidth + (virtualRatio * 2),
|
||||
screenHeight + (virtualRatio * 2)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
destRec = new Rectangle(
|
||||
(screenWidth - screenWidth / 1.25f) / 2.0f,
|
||||
(screenHeight - screenHeight / 1.25f) / 2.0f,
|
||||
screenWidth / 1.25f,
|
||||
screenHeight / 1.25f
|
||||
);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(worldSpaceCamera);
|
||||
DrawRectanglePro(rec01, origin, rotation, Color.Black);
|
||||
DrawRectanglePro(rec02, origin, -rotation, Color.Red);
|
||||
DrawRectanglePro(rec03, origin, rotation + 45.0f, Color.Blue);
|
||||
EndMode2D();
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.LightGray);
|
||||
|
||||
if (smoothOn)
|
||||
{
|
||||
BeginMode2D(screenSpaceCamera);
|
||||
DrawTexturePro(target.Texture, sourceRec, destRec, origin, 0.0f, Color.White);
|
||||
EndMode2D();
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTexturePro(target.Texture, sourceRec, destRec, origin, 0.0f, Color.White);
|
||||
}
|
||||
|
||||
DrawText($"Screen resolution: {screenWidth}x{screenHeight}", 10, 10, 20, Color.DarkBlue);
|
||||
DrawText($"World resolution: {virtualScreenWidth}x{virtualScreenHeight}", 10, 40, 20, Color.DarkGreen);
|
||||
DrawText($"Smooth: {(smoothOn ? "ON" : "OFF")}", 10, screenHeight - 60, 20, Color.Red);
|
||||
DrawText($"Overscan: {(overscan ? "ON" : "OFF")}", 10, screenHeight - 30, 20, Color.Red);
|
||||
DrawFPS(GetScreenWidth() - 95, 10);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTexture(target); // Unload render texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - smooth pixelperfect");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new SmoothPixelPerfect();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rotation += 60.0f * GetFrameTime(); // Rotate the rectangles, 60 degrees per second
|
||||
|
||||
// Make the camera move to demonstrate the effect
|
||||
cameraX = (MathF.Sin((float)GetTime()) * 50.0f) - 10.0f;
|
||||
cameraY = MathF.Cos((float)GetTime()) * 30.0f;
|
||||
|
||||
// Set the camera's target to the values computed above
|
||||
screenSpaceCamera.Target = new Vector2(cameraX, cameraY);
|
||||
|
||||
// Round worldSpace coordinates, keep decimals into screenSpace coordinates
|
||||
worldSpaceCamera.Target.X = (int)screenSpaceCamera.Target.X;
|
||||
screenSpaceCamera.Target.X -= worldSpaceCamera.Target.X;
|
||||
screenSpaceCamera.Target.X *= virtualRatio;
|
||||
|
||||
worldSpaceCamera.Target.Y = (int)screenSpaceCamera.Target.Y;
|
||||
screenSpaceCamera.Target.Y -= worldSpaceCamera.Target.Y;
|
||||
screenSpaceCamera.Target.Y *= virtualRatio;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(worldSpaceCamera);
|
||||
DrawRectanglePro(rec01, origin, rotation, Color.Black);
|
||||
DrawRectanglePro(rec02, origin, -rotation, Color.Red);
|
||||
DrawRectanglePro(rec03, origin, rotation + 45.0f, Color.Blue);
|
||||
EndMode2D();
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Red);
|
||||
|
||||
BeginMode2D(screenSpaceCamera);
|
||||
DrawTexturePro(target.Texture, sourceRec, destRec, origin, 0.0f, Color.White);
|
||||
EndMode2D();
|
||||
|
||||
DrawText($"Screen resolution: {screenWidth}x{screenHeight}", 10, 10, 20, Color.DarkBlue);
|
||||
DrawText($"World resolution: {virtualScreenWidth}x{virtualScreenHeight}", 10, 40, 20, Color.DarkGreen);
|
||||
DrawFPS(GetScreenWidth() - 95, 10);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(target);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,40 +1,50 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - split screen
|
||||
* raylib [core] example - 3d camera split screen
|
||||
*
|
||||
* This example has been created using raylib 3.7 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 3.7, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2021 Jeffery Myers (@JeffM2501)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2021-2025 Jeffery Myers (@JeffM2501)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public unsafe class SplitScreen
|
||||
public partial class SplitScreen : IExample
|
||||
{
|
||||
static Texture2D TextureGrid;
|
||||
static Camera3D CameraPlayer1;
|
||||
static Camera3D CameraPlayer2;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private Camera3D CameraPlayer1;
|
||||
private Camera3D CameraPlayer2;
|
||||
|
||||
private RenderTexture2D screenPlayer1;
|
||||
private RenderTexture2D screenPlayer2;
|
||||
private Rectangle splitScreenRect;
|
||||
|
||||
public string Name => "Core / Split Screen";
|
||||
|
||||
public string Title => "raylib [core] example - 3d camera split screen";
|
||||
|
||||
// Scene drawing
|
||||
static void DrawScene()
|
||||
private void DrawScene()
|
||||
{
|
||||
int count = 5;
|
||||
var count = 5;
|
||||
float spacing = 4;
|
||||
|
||||
// Grid of cube trees on a plane to make a "world"
|
||||
// Simple world plane
|
||||
DrawPlane(new Vector3(0, 0, 0), new Vector2(50, 50), Color.Beige);
|
||||
// Draw scene: grid of cube trees on a plane to make a "world"
|
||||
DrawPlane(new Vector3(0, 0, 0), new Vector2(50, 50), Color.Beige); // Simple world plane
|
||||
|
||||
for (float x = -count * spacing; x <= count * spacing; x += spacing)
|
||||
for (var x = -count * spacing; x <= count * spacing; x += spacing)
|
||||
{
|
||||
for (float z = -count * spacing; z <= count * spacing; z += spacing)
|
||||
for (var z = -count * spacing; z <= count * spacing; z += spacing)
|
||||
{
|
||||
DrawCube(new Vector3(x, 1.5f, z), 1, 1, 1, Color.Lime);
|
||||
DrawCube(new Vector3(x, 0.5f, z), 0.25f, 1, 0.25f, Color.Brown);
|
||||
|
|
@ -46,22 +56,8 @@ public unsafe class SplitScreen
|
|||
DrawCube(CameraPlayer2.Position, 1, 1, 1, Color.Blue);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - split screen");
|
||||
|
||||
// Generate a simple texture to use for trees
|
||||
Image img = GenImageChecked(256, 256, 32, 32, Color.DarkGray, Color.White);
|
||||
TextureGrid = LoadTextureFromImage(img);
|
||||
UnloadImage(img);
|
||||
SetTextureFilter(TextureGrid, TextureFilter.Anisotropic16X);
|
||||
SetTextureWrap(TextureGrid, TextureWrap.Clamp);
|
||||
|
||||
// Setup player 1 camera and screen
|
||||
CameraPlayer1.FovY = 45.0f;
|
||||
CameraPlayer1.Up.Y = 1.0f;
|
||||
|
|
@ -69,7 +65,7 @@ public unsafe class SplitScreen
|
|||
CameraPlayer1.Position.Z = -3.0f;
|
||||
CameraPlayer1.Position.Y = 1.0f;
|
||||
|
||||
RenderTexture2D screenPlayer1 = LoadRenderTexture(screenWidth / 2, screenHeight);
|
||||
screenPlayer1 = LoadRenderTexture(screenWidth / 2, screenHeight);
|
||||
|
||||
// Setup player two camera and screen
|
||||
CameraPlayer2.FovY = 45.0f;
|
||||
|
|
@ -78,97 +74,119 @@ public unsafe class SplitScreen
|
|||
CameraPlayer2.Position.X = -3.0f;
|
||||
CameraPlayer2.Position.Y = 3.0f;
|
||||
|
||||
RenderTexture2D screenPlayer2 = LoadRenderTexture(screenWidth / 2, screenHeight);
|
||||
screenPlayer2 = LoadRenderTexture(screenWidth / 2, screenHeight);
|
||||
|
||||
// Build a flipped rectangle the size of the split view to use for drawing later
|
||||
Rectangle splitScreenRect = new(
|
||||
splitScreenRect = new(
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)screenPlayer1.Texture.Width,
|
||||
(float)-screenPlayer1.Texture.Height
|
||||
);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// If anyone moves this frame, how far will they move based on the time since the last frame
|
||||
// this moves things at 10 world units per second, regardless of the actual FPS
|
||||
var offsetThisFrame = 10.0f * GetFrameTime();
|
||||
|
||||
// Move Player1 forward and backwards (no turning)
|
||||
if (IsKeyDown(KeyboardKey.W))
|
||||
{
|
||||
CameraPlayer1.Position.Z += offsetThisFrame;
|
||||
CameraPlayer1.Target.Z += offsetThisFrame;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.S))
|
||||
{
|
||||
CameraPlayer1.Position.Z -= offsetThisFrame;
|
||||
CameraPlayer1.Target.Z -= offsetThisFrame;
|
||||
}
|
||||
|
||||
// Move Player2 forward and backwards (no turning)
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
CameraPlayer2.Position.X += offsetThisFrame;
|
||||
CameraPlayer2.Target.X += offsetThisFrame;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
CameraPlayer2.Position.X -= offsetThisFrame;
|
||||
CameraPlayer2.Target.X -= offsetThisFrame;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw Player1 view to the render texture
|
||||
BeginTextureMode(screenPlayer1);
|
||||
ClearBackground(Color.SkyBlue);
|
||||
|
||||
BeginMode3D(CameraPlayer1);
|
||||
DrawScene();
|
||||
EndMode3D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth() / 2, 40, Fade(Color.RayWhite, 0.8f));
|
||||
DrawText("PLAYER1: W/S to move", 10, 10, 20, Color.Maroon);
|
||||
EndTextureMode();
|
||||
|
||||
// Draw Player2 view to the render texture
|
||||
BeginTextureMode(screenPlayer2);
|
||||
ClearBackground(Color.SkyBlue);
|
||||
|
||||
BeginMode3D(CameraPlayer2);
|
||||
DrawScene();
|
||||
EndMode3D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth() / 2, 40, Fade(Color.RayWhite, 0.8f));
|
||||
DrawText("PLAYER2: UP/DOWN to move", 10, 10, 20, Color.DarkBlue);
|
||||
EndTextureMode();
|
||||
|
||||
// Draw both views render textures to the screen side by side
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
DrawTextureRec(screenPlayer1.Texture, splitScreenRect, new Vector2(0, 0), Color.White);
|
||||
DrawTextureRec(screenPlayer2.Texture, splitScreenRect, new Vector2(screenWidth / 2.0f, 0), Color.White);
|
||||
|
||||
DrawRectangle(GetScreenWidth() / 2 - 2, 0, 4, GetScreenHeight(), Color.LightGray);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTexture(screenPlayer1); // Unload render texture
|
||||
UnloadRenderTexture(screenPlayer2); // Unload render texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera split screen");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new SplitScreen();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// If anyone moves this frame, how far will they move based on the time since the last frame
|
||||
// this moves thigns at 10 world units per second, regardless of the actual FPS
|
||||
float offsetThisFrame = 10.0f * GetFrameTime();
|
||||
|
||||
// Move Player1 forward and backwards (no turning)
|
||||
if (IsKeyDown(KeyboardKey.W))
|
||||
{
|
||||
CameraPlayer1.Position.Z += offsetThisFrame;
|
||||
CameraPlayer1.Target.Z += offsetThisFrame;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.S))
|
||||
{
|
||||
CameraPlayer1.Position.Z -= offsetThisFrame;
|
||||
CameraPlayer1.Target.Z -= offsetThisFrame;
|
||||
}
|
||||
|
||||
// Move Player2 forward and backwards (no turning)
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
CameraPlayer2.Position.X += offsetThisFrame;
|
||||
CameraPlayer2.Target.X += offsetThisFrame;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
CameraPlayer2.Position.X -= offsetThisFrame;
|
||||
CameraPlayer2.Target.X -= offsetThisFrame;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw Player1 view to the render texture
|
||||
BeginTextureMode(screenPlayer1);
|
||||
ClearBackground(Color.SkyBlue);
|
||||
|
||||
BeginMode3D(CameraPlayer1);
|
||||
DrawScene();
|
||||
EndMode3D();
|
||||
|
||||
DrawText("PLAYER 1 W/S to move", 10, 10, 20, Color.Red);
|
||||
EndTextureMode();
|
||||
|
||||
// Draw Player2 view to the render texture
|
||||
BeginTextureMode(screenPlayer2);
|
||||
ClearBackground(Color.SkyBlue);
|
||||
|
||||
BeginMode3D(CameraPlayer2);
|
||||
DrawScene();
|
||||
EndMode3D();
|
||||
|
||||
DrawText("PLAYER 2 UP/DOWN to move", 10, 10, 20, Color.Blue);
|
||||
EndTextureMode();
|
||||
|
||||
// Draw both views render textures to the screen side by side
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
DrawTextureRec(screenPlayer1.Texture, splitScreenRect, new Vector2(0, 0), Color.White);
|
||||
DrawTextureRec(screenPlayer2.Texture, splitScreenRect, new Vector2(screenWidth / 2.0f, 0), Color.White);
|
||||
|
||||
EndDrawing();
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(screenPlayer1);
|
||||
UnloadRenderTexture(screenPlayer2);
|
||||
UnloadTexture(TextureGrid);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
227
Examples/Core/SplitScreen2D.cs
Normal file
227
Examples/Core/SplitScreen2D.cs
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 2d camera split screen
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Addapted from the core_3d_camera_split_screen example:
|
||||
* https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_camera_split_screen.c
|
||||
*
|
||||
* Example originally created with raylib 4.5, last time updated with raylib 4.5
|
||||
*
|
||||
* Example contributed by Gabriel dos Santos Sanches (@gabrielssanches) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2023-2025 Gabriel dos Santos Sanches (@gabrielssanches)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class SplitScreen2D : IExample
|
||||
{
|
||||
private const int PLAYER_SIZE = 40;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 440;
|
||||
|
||||
public string Name => "Core / 2D Camera Split Screen";
|
||||
|
||||
public string Title => "raylib [core] example - 2d camera split screen";
|
||||
|
||||
public int Width => screenWidth;
|
||||
|
||||
public int Height => screenHeight;
|
||||
|
||||
private Rectangle player1;
|
||||
private Rectangle player2;
|
||||
private Camera2D camera1;
|
||||
private Camera2D camera2;
|
||||
private RenderTexture2D screenCamera1;
|
||||
private RenderTexture2D screenCamera2;
|
||||
private Rectangle splitScreenRect;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
player1 = new Rectangle(200, 200, PLAYER_SIZE, PLAYER_SIZE);
|
||||
player2 = new Rectangle(250, 200, PLAYER_SIZE, PLAYER_SIZE);
|
||||
|
||||
camera1 = new Camera2D();
|
||||
camera1.Target = new Vector2(player1.X, player1.Y);
|
||||
camera1.Offset = new Vector2(200.0f, 200.0f);
|
||||
camera1.Rotation = 0.0f;
|
||||
camera1.Zoom = 1.0f;
|
||||
|
||||
camera2 = new Camera2D();
|
||||
camera2.Target = new Vector2(player2.X, player2.Y);
|
||||
camera2.Offset = new Vector2(200.0f, 200.0f);
|
||||
camera2.Rotation = 0.0f;
|
||||
camera2.Zoom = 1.0f;
|
||||
|
||||
screenCamera1 = LoadRenderTexture(screenWidth / 2, screenHeight);
|
||||
screenCamera2 = LoadRenderTexture(screenWidth / 2, screenHeight);
|
||||
|
||||
// Build a flipped rectangle the size of the split view to use for drawing later
|
||||
splitScreenRect = new Rectangle(0.0f, 0.0f, (float)screenCamera1.Texture.Width, (float)-screenCamera1.Texture.Height);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.S))
|
||||
{
|
||||
player1.Y += 3.0f;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.W))
|
||||
{
|
||||
player1.Y -= 3.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.D))
|
||||
{
|
||||
player1.X += 3.0f;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.A))
|
||||
{
|
||||
player1.X -= 3.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Up))
|
||||
{
|
||||
player2.Y -= 3.0f;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Down))
|
||||
{
|
||||
player2.Y += 3.0f;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
player2.X += 3.0f;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
player2.X -= 3.0f;
|
||||
}
|
||||
|
||||
camera1.Target = new Vector2(player1.X, player1.Y);
|
||||
camera2.Target = new Vector2(player2.X, player2.Y);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(screenCamera1);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(camera1);
|
||||
|
||||
// Draw full scene with first camera
|
||||
for (int i = 0; i < screenWidth / PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV(new Vector2((float)PLAYER_SIZE * i, 0), new Vector2((float)PLAYER_SIZE * i, (float)screenHeight), Color.LightGray);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenHeight / PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV(new Vector2(0, (float)PLAYER_SIZE * i), new Vector2((float)screenWidth, (float)PLAYER_SIZE * i), Color.LightGray);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenWidth / PLAYER_SIZE; i++)
|
||||
{
|
||||
for (int j = 0; j < screenHeight / PLAYER_SIZE; j++)
|
||||
{
|
||||
DrawText($"[{i},{j}]", 10 + PLAYER_SIZE * i, 15 + PLAYER_SIZE * j, 10, Color.LightGray);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleRec(player1, Color.Red);
|
||||
DrawRectangleRec(player2, Color.Blue);
|
||||
EndMode2D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth() / 2, 30, Fade(Color.RayWhite, 0.6f));
|
||||
DrawText("PLAYER1: W/S/A/D to move", 10, 10, 10, Color.Maroon);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
BeginTextureMode(screenCamera2);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(camera2);
|
||||
|
||||
// Draw full scene with second camera
|
||||
for (int i = 0; i < screenWidth / PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV(new Vector2((float)PLAYER_SIZE * i, 0), new Vector2((float)PLAYER_SIZE * i, (float)screenHeight), Color.LightGray);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenHeight / PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV(new Vector2(0, (float)PLAYER_SIZE * i), new Vector2((float)screenWidth, (float)PLAYER_SIZE * i), Color.LightGray);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenWidth / PLAYER_SIZE; i++)
|
||||
{
|
||||
for (int j = 0; j < screenHeight / PLAYER_SIZE; j++)
|
||||
{
|
||||
DrawText($"[{i},{j}]", 10 + PLAYER_SIZE * i, 15 + PLAYER_SIZE * j, 10, Color.LightGray);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleRec(player1, Color.Red);
|
||||
DrawRectangleRec(player2, Color.Blue);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth() / 2, 30, Fade(Color.RayWhite, 0.6f));
|
||||
DrawText("PLAYER2: UP/DOWN/LEFT/RIGHT to move", 10, 10, 10, Color.DarkBlue);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw both views render textures to the screen side by side
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
DrawTextureRec(screenCamera1.Texture, splitScreenRect, new Vector2(0, 0), Color.White);
|
||||
DrawTextureRec(screenCamera2.Texture, splitScreenRect, new Vector2(screenWidth / 2.0f, 0), Color.White);
|
||||
|
||||
DrawRectangle(GetScreenWidth() / 2 - 2, 0, 4, GetScreenHeight(), Color.LightGray);
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTexture(screenCamera1); // Unload render texture
|
||||
UnloadRenderTexture(screenCamera2); // Unload render texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera split screen");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new SplitScreen2D();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +1,118 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - Storage save/load values
|
||||
* raylib [core] example - storage values
|
||||
*
|
||||
* This example has been created using raylib 1.4 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.4, last time updated with raylib 4.2
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class StorageValues
|
||||
public partial class StorageValues : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
private const string storageDataFile = "storage.data";
|
||||
|
||||
// NOTE: Storage positions must start with 0, directly related to file memory layout
|
||||
enum StorageData
|
||||
private enum StorageData
|
||||
{
|
||||
Score,
|
||||
HiScore
|
||||
}
|
||||
|
||||
public string Name => "Core / Storage Values";
|
||||
|
||||
public string Title => "raylib [core] example - storage values";
|
||||
|
||||
private int score = 0;
|
||||
private int hiscore = 0;
|
||||
private int framesCounter = 0;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
score = 0;
|
||||
hiscore = 0;
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
score = GetRandomValue(1000, 2000);
|
||||
hiscore = GetRandomValue(2000, 4000);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Enter))
|
||||
{
|
||||
SaveStorageValue(storageDataFile, (int)StorageData.Score, score);
|
||||
SaveStorageValue(storageDataFile, (int)StorageData.HiScore, hiscore);
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
// NOTE: If requested position could not be found, value 0 is returned
|
||||
score = LoadStorageValue(storageDataFile, (int)StorageData.Score);
|
||||
hiscore = LoadStorageValue(storageDataFile, (int)StorageData.HiScore);
|
||||
}
|
||||
|
||||
framesCounter++;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText($"SCORE: {score}", 280, 130, 40, Color.Maroon);
|
||||
DrawText($"HI-SCORE: {hiscore}", 210, 200, 50, Color.Black);
|
||||
|
||||
DrawText($"frames: {framesCounter}", 10, 10, 20, Color.Lime);
|
||||
|
||||
DrawText("Press R to generate random numbers", 220, 40, 20, Color.LightGray);
|
||||
DrawText("Press ENTER to SAVE values", 250, 310, 20, Color.LightGray);
|
||||
DrawText("Press SPACE to LOAD values", 252, 350, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
const string storageDataFile = "storage.data";
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - storage values");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - storage save/load values");
|
||||
|
||||
int score = 0;
|
||||
int hiscore = 0;
|
||||
int framesCounter = 0;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new StorageValues();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
score = GetRandomValue(1000, 2000);
|
||||
hiscore = GetRandomValue(2000, 4000);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Enter))
|
||||
{
|
||||
SaveStorageValue(storageDataFile, (int)StorageData.Score, score);
|
||||
SaveStorageValue(storageDataFile, (int)StorageData.HiScore, hiscore);
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
// NOTE: If requested position could not be found, value 0 is returned
|
||||
score = LoadStorageValue(storageDataFile, (int)StorageData.Score);
|
||||
hiscore = LoadStorageValue(storageDataFile, (int)StorageData.HiScore);
|
||||
}
|
||||
|
||||
framesCounter++;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText($"SCORE: {score}", 280, 130, 40, Color.Maroon);
|
||||
DrawText($"HI-SCORE: {hiscore}", 210, 200, 50, Color.Black);
|
||||
|
||||
DrawText($"frames: {framesCounter}", 10, 10, 20, Color.Lime);
|
||||
|
||||
DrawText("Press R to generate random numbers", 220, 40, 20, Color.LightGray);
|
||||
DrawText("Press ENTER to SAVE values", 250, 310, 20, Color.LightGray);
|
||||
DrawText("Press SPACE to LOAD values", 252, 350, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
@ -97,11 +124,11 @@ public class StorageValues
|
|||
{
|
||||
using var fileNameBuffer = fileName.ToUtf8Buffer();
|
||||
|
||||
bool success = false;
|
||||
int dataSize = 0;
|
||||
int newDataSize = 0;
|
||||
var success = false;
|
||||
var dataSize = 0;
|
||||
var newDataSize = 0;
|
||||
|
||||
byte* fileData = LoadFileData(fileNameBuffer.AsPointer(), &dataSize);
|
||||
var fileData = LoadFileData(fileNameBuffer.AsPointer(), &dataSize);
|
||||
byte* newFileData = null;
|
||||
|
||||
if (fileData != null)
|
||||
|
|
@ -115,13 +142,13 @@ public class StorageValues
|
|||
if (newFileData != null)
|
||||
{
|
||||
// RL_REALLOC succeded
|
||||
int* dataPtr = (int*)newFileData;
|
||||
var dataPtr = (int*)newFileData;
|
||||
dataPtr[position] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// RL_REALLOC failed
|
||||
int positionInBytes = position * sizeof(int);
|
||||
var positionInBytes = position * sizeof(int);
|
||||
TraceLog(
|
||||
TraceLogLevel.Warning,
|
||||
@$"FILEIO: [{fileName}] Failed to realloc data ({dataSize}),
|
||||
|
|
@ -140,7 +167,7 @@ public class StorageValues
|
|||
newDataSize = dataSize;
|
||||
|
||||
// Replace value on selected position
|
||||
int* dataPtr = (int*)newFileData;
|
||||
var dataPtr = (int*)newFileData;
|
||||
dataPtr[position] = value;
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +182,7 @@ public class StorageValues
|
|||
|
||||
dataSize = (position + 1) * sizeof(int);
|
||||
fileData = (byte*)MemAlloc((uint)dataSize);
|
||||
int* dataPtr = (int*)fileData;
|
||||
var dataPtr = (int*)fileData;
|
||||
dataPtr[position] = value;
|
||||
|
||||
success = SaveFileData(fileNameBuffer.AsPointer(), fileData, dataSize);
|
||||
|
|
@ -173,9 +200,9 @@ public class StorageValues
|
|||
{
|
||||
using var fileNameBuffer = fileName.ToUtf8Buffer();
|
||||
|
||||
int value = 0;
|
||||
int dataSize = 0;
|
||||
byte* fileData = LoadFileData(fileNameBuffer.AsPointer(), &dataSize);
|
||||
var value = 0;
|
||||
var dataSize = 0;
|
||||
var fileData = LoadFileData(fileNameBuffer.AsPointer(), &dataSize);
|
||||
|
||||
if (fileData != null)
|
||||
{
|
||||
|
|
@ -188,7 +215,7 @@ public class StorageValues
|
|||
}
|
||||
else
|
||||
{
|
||||
int* dataPtr = (int*)fileData;
|
||||
var dataPtr = (int*)fileData;
|
||||
value = dataPtr[position];
|
||||
}
|
||||
|
||||
|
|
|
|||
212
Examples/Core/TextFileLoading.cs
Normal file
212
Examples/Core/TextFileLoading.cs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - text file loading
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Aanjishnu Bhattacharyya (@NimComPoo-04) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 0 Aanjishnu Bhattacharyya (@NimComPoo-04)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using static Raylib_cs.Raymath;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
// NOTE: The upstream C code mutates the raw char buffers returned by LoadTextLines() in place,
|
||||
// temporarily null-terminating to reuse MeasureText for word wrapping. This C# port keeps the
|
||||
// same algorithm but works on managed char arrays: LoadFileText + split on '\n' reproduces
|
||||
// raylib's LoadTextLines('\n') behaviour, and '\n' characters are inserted where lines wrap.
|
||||
public partial class TextFileLoading : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Text File Loading";
|
||||
|
||||
public string Title => "raylib [core] example - text file loading";
|
||||
|
||||
private Camera2D cam;
|
||||
private string fileName;
|
||||
private string[] lines;
|
||||
private int lineCount;
|
||||
private int fontSize;
|
||||
private int textTop;
|
||||
private int wrapWidth;
|
||||
private int textHeight;
|
||||
private Rectangle scrollBar;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Setting up the camera
|
||||
cam = new Camera2D();
|
||||
cam.Offset = new Vector2(0, 0);
|
||||
cam.Target = new Vector2(0, 0);
|
||||
cam.Rotation = 0;
|
||||
cam.Zoom = 1;
|
||||
|
||||
// Loading text file from resources/text_file.txt
|
||||
fileName = "resources/text_file.txt";
|
||||
string text = LoadFileText(fileName);
|
||||
|
||||
// Loading all the text lines (raylib's LoadTextLines splits on '\n')
|
||||
lines = text.Split('\n');
|
||||
lineCount = lines.Length;
|
||||
|
||||
// Stylistic choises
|
||||
fontSize = 20;
|
||||
textTop = 25 + fontSize; // Top of the screen from where the text is rendered
|
||||
wrapWidth = screenWidth - 20;
|
||||
|
||||
// Wrap the lines as needed
|
||||
for (int i = 0; i < lineCount; i++)
|
||||
{
|
||||
char[] chars = lines[i].ToCharArray();
|
||||
int len = chars.Length;
|
||||
int j = 0;
|
||||
int lastSpace = 0; // Keeping track of last valid space to insert '\n'
|
||||
int lastWrapStart = 0; // Keeping track of the start of this wrapped line.
|
||||
|
||||
while (j <= len)
|
||||
{
|
||||
char cur = (j < len) ? chars[j] : '\0';
|
||||
if (cur == ' ' || cur == '\0')
|
||||
{
|
||||
// Making a C style string by "cutting" at the required location so that we can use MeasureText
|
||||
string sub = new string(chars, lastWrapStart, j - lastWrapStart);
|
||||
|
||||
// Checking if the text has crossed the wrapWidth, then going back and inserting a newline
|
||||
if (MeasureText(sub, fontSize) > wrapWidth)
|
||||
{
|
||||
chars[lastSpace] = '\n';
|
||||
|
||||
// Since we added a newline the place of wrap changed so we update our lastWrapStart
|
||||
lastWrapStart = lastSpace + 1;
|
||||
}
|
||||
|
||||
lastSpace = j; // Since we encountered a new space we update our last encountered space location
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
lines[i] = new string(chars);
|
||||
}
|
||||
|
||||
// Calculating the total height so that we can show a scrollbar
|
||||
textHeight = 0;
|
||||
|
||||
for (int i = 0; i < lineCount; i++)
|
||||
{
|
||||
Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], (float)fontSize, 2);
|
||||
textHeight += (int)size.Y + 10;
|
||||
}
|
||||
|
||||
// A simple scrollbar on the side to show how far we have read into the file
|
||||
scrollBar = new Rectangle(
|
||||
(float)screenWidth - 5,
|
||||
0,
|
||||
5,
|
||||
screenHeight * 100.0f / (textHeight - screenHeight)); // Scrollbar height is just a percentage
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float scroll = GetMouseWheelMove();
|
||||
cam.Target.Y -= scroll * fontSize * 1.5f; // Choosing an arbitrary speed for scroll
|
||||
|
||||
if (cam.Target.Y < 0)
|
||||
{
|
||||
cam.Target.Y = 0; // Snapping to 0 if we go too far back
|
||||
}
|
||||
|
||||
// Ensuring that the camera does not scroll past all text
|
||||
if (cam.Target.Y > textHeight - screenHeight + textTop)
|
||||
{
|
||||
cam.Target.Y = (float)textHeight - screenHeight + textTop;
|
||||
}
|
||||
|
||||
// Computing the position of the scrollBar depending on the percentage of text covered
|
||||
scrollBar.Y = Lerp((float)textTop, (float)screenHeight - scrollBar.Height, (float)(cam.Target.Y - textTop) / (textHeight - screenHeight));
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode2D(cam);
|
||||
// Going through all the read lines
|
||||
for (int i = 0, t = textTop; i < lineCount; i++)
|
||||
{
|
||||
// Each time we go through and calculate the height of the text to move the cursor appropriately
|
||||
Vector2 size;
|
||||
if (lines[i] != "")
|
||||
{
|
||||
size = MeasureTextEx(GetFontDefault(), lines[i], (float)fontSize, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fix for empty line in the text file
|
||||
size = MeasureTextEx(GetFontDefault(), " ", (float)fontSize, 2);
|
||||
}
|
||||
|
||||
DrawText(lines[i], 10, t, fontSize, Color.Red);
|
||||
|
||||
// Inserting extra space for real newlines,
|
||||
// wrapped lines are rendered closer together
|
||||
t += (int)size.Y + 10;
|
||||
}
|
||||
EndMode2D();
|
||||
|
||||
// Header displaying which file is being read currently
|
||||
DrawRectangle(0, 0, screenWidth, textTop - 10, Color.Beige);
|
||||
DrawText($"File: {fileName}", 10, 10, fontSize, Color.Maroon);
|
||||
|
||||
DrawRectangleRec(scrollBar, Color.Maroon);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - text file loading");
|
||||
|
||||
var game = new TextFileLoading();
|
||||
game.Init();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
389
Examples/Core/UndoRedo.cs
Normal file
389
Examples/Core/UndoRedo.cs
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - undo redo
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class UndoRedo : IExample
|
||||
{
|
||||
private const int MAX_UNDO_STATES = 26; // Maximum undo states supported for the ring buffer
|
||||
|
||||
private const int GRID_CELL_SIZE = 24;
|
||||
private const int MAX_GRID_CELLS_X = 30;
|
||||
private const int MAX_GRID_CELLS_Y = 13;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Undo Redo";
|
||||
|
||||
public string Title => "raylib [core] example - undo redo";
|
||||
|
||||
// Point struct, like Vector2 but using int
|
||||
private struct Point
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
|
||||
// Player state struct
|
||||
// NOTE: Contains all player data that needs to be affected by undo/redo
|
||||
private struct PlayerState
|
||||
{
|
||||
public Point Cell;
|
||||
public Color Color;
|
||||
}
|
||||
|
||||
// Undo/redo system variables
|
||||
private int currentUndoIndex;
|
||||
private int firstUndoIndex;
|
||||
private int lastUndoIndex;
|
||||
private int undoFrameCounter;
|
||||
private Vector2 undoInfoPos;
|
||||
|
||||
private PlayerState player;
|
||||
private PlayerState[] states;
|
||||
|
||||
// Grid variables
|
||||
private Vector2 gridPosition;
|
||||
|
||||
// Compare two player states (replaces memcmp)
|
||||
private static bool SameState(in PlayerState a, in PlayerState b)
|
||||
{
|
||||
return (a.Cell.X == b.Cell.X) && (a.Cell.Y == b.Cell.Y) &&
|
||||
(a.Color.R == b.Color.R) && (a.Color.G == b.Color.G) &&
|
||||
(a.Color.B == b.Color.B) && (a.Color.A == b.Color.A);
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
currentUndoIndex = 0;
|
||||
firstUndoIndex = 0;
|
||||
lastUndoIndex = 0;
|
||||
undoFrameCounter = 0;
|
||||
undoInfoPos = new Vector2(110, 400);
|
||||
|
||||
// Init current player state and undo/redo recorded states array
|
||||
player = new PlayerState();
|
||||
player.Cell = new Point { X = 10, Y = 10 };
|
||||
player.Color = Color.Red;
|
||||
|
||||
// Init undo buffer to store MAX_UNDO_STATES states
|
||||
states = new PlayerState[MAX_UNDO_STATES];
|
||||
// Init all undo states to current state
|
||||
for (int i = 0; i < MAX_UNDO_STATES; i++)
|
||||
{
|
||||
states[i] = player;
|
||||
}
|
||||
|
||||
// Grid variables
|
||||
gridPosition = new Vector2(40, 60);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Player movement logic
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
player.Cell.X++;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
player.Cell.X--;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Up))
|
||||
{
|
||||
player.Cell.Y--;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Down))
|
||||
{
|
||||
player.Cell.Y++;
|
||||
}
|
||||
|
||||
// Make sure player does not go out of bounds
|
||||
if (player.Cell.X < 0)
|
||||
{
|
||||
player.Cell.X = 0;
|
||||
}
|
||||
else if (player.Cell.X >= MAX_GRID_CELLS_X)
|
||||
{
|
||||
player.Cell.X = MAX_GRID_CELLS_X - 1;
|
||||
}
|
||||
|
||||
if (player.Cell.Y < 0)
|
||||
{
|
||||
player.Cell.Y = 0;
|
||||
}
|
||||
else if (player.Cell.Y >= MAX_GRID_CELLS_Y)
|
||||
{
|
||||
player.Cell.Y = MAX_GRID_CELLS_Y - 1;
|
||||
}
|
||||
|
||||
// Player color change logic
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
player.Color.R = (byte)GetRandomValue(20, 255);
|
||||
player.Color.G = (byte)GetRandomValue(20, 220);
|
||||
player.Color.B = (byte)GetRandomValue(20, 240);
|
||||
}
|
||||
|
||||
// Undo state change logic
|
||||
undoFrameCounter++;
|
||||
|
||||
// Waiting a number of frames before checking if we should store a new state snapshot
|
||||
if (undoFrameCounter >= 2) // Checking every 2 frames
|
||||
{
|
||||
if (!SameState(states[currentUndoIndex], player))
|
||||
{
|
||||
// Move cursor to next available position of the undo ring buffer to record state
|
||||
currentUndoIndex++;
|
||||
if (currentUndoIndex >= MAX_UNDO_STATES)
|
||||
{
|
||||
currentUndoIndex = 0;
|
||||
}
|
||||
|
||||
if (currentUndoIndex == firstUndoIndex)
|
||||
{
|
||||
firstUndoIndex++;
|
||||
}
|
||||
|
||||
if (firstUndoIndex >= MAX_UNDO_STATES)
|
||||
{
|
||||
firstUndoIndex = 0;
|
||||
}
|
||||
|
||||
states[currentUndoIndex] = player;
|
||||
lastUndoIndex = currentUndoIndex;
|
||||
}
|
||||
|
||||
undoFrameCounter = 0;
|
||||
}
|
||||
|
||||
// Recover previous state from buffer: CTRL+Z
|
||||
if (IsKeyDown(KeyboardKey.LeftControl) && IsKeyPressed(KeyboardKey.Z))
|
||||
{
|
||||
if (currentUndoIndex != firstUndoIndex)
|
||||
{
|
||||
currentUndoIndex--;
|
||||
if (currentUndoIndex < 0)
|
||||
{
|
||||
currentUndoIndex = MAX_UNDO_STATES - 1;
|
||||
}
|
||||
|
||||
if (!SameState(states[currentUndoIndex], player))
|
||||
{
|
||||
player = states[currentUndoIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recover next state from buffer: CTRL+Y
|
||||
if (IsKeyDown(KeyboardKey.LeftControl) && IsKeyPressed(KeyboardKey.Y))
|
||||
{
|
||||
if (currentUndoIndex != lastUndoIndex)
|
||||
{
|
||||
int nextUndoIndex = currentUndoIndex + 1;
|
||||
if (nextUndoIndex >= MAX_UNDO_STATES)
|
||||
{
|
||||
nextUndoIndex = 0;
|
||||
}
|
||||
|
||||
if (nextUndoIndex != firstUndoIndex)
|
||||
{
|
||||
currentUndoIndex = nextUndoIndex;
|
||||
|
||||
if (!SameState(states[currentUndoIndex], player))
|
||||
{
|
||||
player = states[currentUndoIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw controls info
|
||||
DrawText("[ARROWS] MOVE PLAYER - [SPACE] CHANGE PLAYER COLOR", 40, 20, 20, Color.DarkGray);
|
||||
|
||||
// Draw player visited cells recorded by undo
|
||||
// NOTE: Remember we are using a ring buffer approach so,
|
||||
// some cells info could start at the end of the array and end at the beginning
|
||||
if (lastUndoIndex > firstUndoIndex)
|
||||
{
|
||||
for (int i = firstUndoIndex; i < currentUndoIndex; i++)
|
||||
{
|
||||
DrawRectangleRec(new Rectangle(gridPosition.X + states[i].Cell.X * GRID_CELL_SIZE, gridPosition.Y + states[i].Cell.Y * GRID_CELL_SIZE,
|
||||
GRID_CELL_SIZE, GRID_CELL_SIZE), Color.LightGray);
|
||||
}
|
||||
}
|
||||
else if (firstUndoIndex > lastUndoIndex)
|
||||
{
|
||||
if ((currentUndoIndex < MAX_UNDO_STATES) && (currentUndoIndex > lastUndoIndex))
|
||||
{
|
||||
for (int i = firstUndoIndex; i < currentUndoIndex; i++)
|
||||
{
|
||||
DrawRectangleRec(new Rectangle(gridPosition.X + states[i].Cell.X * GRID_CELL_SIZE, gridPosition.Y + states[i].Cell.Y * GRID_CELL_SIZE,
|
||||
GRID_CELL_SIZE, GRID_CELL_SIZE), Color.LightGray);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++)
|
||||
{
|
||||
DrawRectangle((int)gridPosition.X + states[i].Cell.X * GRID_CELL_SIZE, (int)gridPosition.Y + states[i].Cell.Y * GRID_CELL_SIZE,
|
||||
GRID_CELL_SIZE, GRID_CELL_SIZE, Color.LightGray);
|
||||
}
|
||||
|
||||
for (int i = 0; i < currentUndoIndex; i++)
|
||||
{
|
||||
DrawRectangle((int)gridPosition.X + states[i].Cell.X * GRID_CELL_SIZE, (int)gridPosition.Y + states[i].Cell.Y * GRID_CELL_SIZE,
|
||||
GRID_CELL_SIZE, GRID_CELL_SIZE, Color.LightGray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw game grid
|
||||
for (int y = 0; y <= MAX_GRID_CELLS_Y; y++)
|
||||
{
|
||||
DrawLine((int)gridPosition.X, (int)gridPosition.Y + y * GRID_CELL_SIZE,
|
||||
(int)gridPosition.X + MAX_GRID_CELLS_X * GRID_CELL_SIZE, (int)gridPosition.Y + y * GRID_CELL_SIZE, Color.Gray);
|
||||
}
|
||||
|
||||
for (int x = 0; x <= MAX_GRID_CELLS_X; x++)
|
||||
{
|
||||
DrawLine((int)gridPosition.X + x * GRID_CELL_SIZE, (int)gridPosition.Y,
|
||||
(int)gridPosition.X + x * GRID_CELL_SIZE, (int)gridPosition.Y + MAX_GRID_CELLS_Y * GRID_CELL_SIZE, Color.Gray);
|
||||
}
|
||||
|
||||
// Draw player
|
||||
DrawRectangle((int)gridPosition.X + player.Cell.X * GRID_CELL_SIZE, (int)gridPosition.Y + player.Cell.Y * GRID_CELL_SIZE,
|
||||
GRID_CELL_SIZE + 1, GRID_CELL_SIZE + 1, player.Color);
|
||||
|
||||
// Draw undo system buffer info
|
||||
DrawText("UNDO STATES:", (int)undoInfoPos.X - 85, (int)undoInfoPos.Y + 9, 10, Color.DarkGray);
|
||||
DrawUndoBuffer(undoInfoPos, firstUndoIndex, lastUndoIndex, currentUndoIndex, 24);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
// Draw undo system visualization logic
|
||||
// NOTE: Visualizing the ring buffer array, every square can store a player state
|
||||
private static void DrawUndoBuffer(Vector2 position, int firstUndoIndex, int lastUndoIndex, int currentUndoIndex, int slotSize)
|
||||
{
|
||||
// Draw index marks
|
||||
DrawRectangle((int)position.X + 8 + slotSize * currentUndoIndex, (int)position.Y - 10, 8, 8, Color.Red);
|
||||
DrawRectangleLines((int)position.X + 2 + slotSize * firstUndoIndex, (int)position.Y + 27, 8, 8, Color.Black);
|
||||
DrawRectangle((int)position.X + 14 + slotSize * lastUndoIndex, (int)position.Y + 27, 8, 8, Color.Black);
|
||||
|
||||
// Draw background gray slots
|
||||
for (int i = 0; i < MAX_UNDO_STATES; i++)
|
||||
{
|
||||
DrawRectangle((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.LightGray);
|
||||
DrawRectangleLines((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Gray);
|
||||
}
|
||||
|
||||
// Draw occupied slots: firstUndoIndex --> lastUndoIndex
|
||||
if (firstUndoIndex <= lastUndoIndex)
|
||||
{
|
||||
for (int i = firstUndoIndex; i < lastUndoIndex + 1; i++)
|
||||
{
|
||||
DrawRectangle((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.SkyBlue);
|
||||
DrawRectangleLines((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Blue);
|
||||
}
|
||||
}
|
||||
else if (lastUndoIndex < firstUndoIndex)
|
||||
{
|
||||
for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++)
|
||||
{
|
||||
DrawRectangle((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.SkyBlue);
|
||||
DrawRectangleLines((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Blue);
|
||||
}
|
||||
|
||||
for (int i = 0; i < lastUndoIndex + 1; i++)
|
||||
{
|
||||
DrawRectangle((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.SkyBlue);
|
||||
DrawRectangleLines((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Blue);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw occupied slots: firstUndoIndex --> currentUndoIndex
|
||||
if (firstUndoIndex < currentUndoIndex)
|
||||
{
|
||||
for (int i = firstUndoIndex; i < currentUndoIndex; i++)
|
||||
{
|
||||
DrawRectangle((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Green);
|
||||
DrawRectangleLines((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Lime);
|
||||
}
|
||||
}
|
||||
else if (currentUndoIndex < firstUndoIndex)
|
||||
{
|
||||
for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++)
|
||||
{
|
||||
DrawRectangle((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Green);
|
||||
DrawRectangleLines((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Lime);
|
||||
}
|
||||
|
||||
for (int i = 0; i < currentUndoIndex; i++)
|
||||
{
|
||||
DrawRectangle((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Green);
|
||||
DrawRectangleLines((int)position.X + slotSize * i, (int)position.Y, slotSize, slotSize, Color.Lime);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw current selected UNDO slot
|
||||
DrawRectangle((int)position.X + slotSize * currentUndoIndex, (int)position.Y, slotSize, slotSize, Color.Gold);
|
||||
DrawRectangleLines((int)position.X + slotSize * currentUndoIndex, (int)position.Y, slotSize, slotSize, Color.Orange);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - undo redo");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new UndoRedo();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
380
Examples/Core/ViewportScaling.cs
Normal file
380
Examples/Core/ViewportScaling.cs
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - viewport scaling
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Agnis Aldiņš (@nezvers) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Agnis Aldiņš (@nezvers)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class ViewportScaling : IExample
|
||||
{
|
||||
private const int ResolutionCount = 4; // For iteration purposes and teaching example
|
||||
|
||||
private enum ViewportType
|
||||
{
|
||||
// Only upscale, useful for pixel art
|
||||
KeepAspectInteger,
|
||||
KeepHeightInteger,
|
||||
KeepWidthInteger,
|
||||
// Can also downscale
|
||||
KeepAspect,
|
||||
KeepHeight,
|
||||
KeepWidth,
|
||||
// For itteration purposes and as a teaching example
|
||||
ViewportTypeCount,
|
||||
}
|
||||
|
||||
// For displaying on GUI
|
||||
private static readonly string[] ViewportTypeNames = new string[]
|
||||
{
|
||||
"KEEP_ASPECT_INTEGER",
|
||||
"KEEP_HEIGHT_INTEGER",
|
||||
"KEEP_WIDTH_INTEGER",
|
||||
"KEEP_ASPECT",
|
||||
"KEEP_HEIGHT",
|
||||
"KEEP_WIDTH",
|
||||
};
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Viewport Scaling";
|
||||
|
||||
public string Title => "raylib [core] example - viewport scaling";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.ResizableWindow;
|
||||
|
||||
// Mutable window size (tracked from GetScreenWidth/GetScreenHeight)
|
||||
private int curScreenWidth;
|
||||
private int curScreenHeight;
|
||||
|
||||
private Vector2[] resolutionList;
|
||||
private int resolutionIndex;
|
||||
private int gameWidth;
|
||||
private int gameHeight;
|
||||
|
||||
private RenderTexture2D target;
|
||||
private Rectangle sourceRect;
|
||||
private Rectangle destRect;
|
||||
|
||||
private ViewportType viewportType;
|
||||
|
||||
// Button rectangles
|
||||
private Rectangle decreaseResolutionButton;
|
||||
private Rectangle increaseResolutionButton;
|
||||
private Rectangle decreaseTypeButton;
|
||||
private Rectangle increaseTypeButton;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
curScreenWidth = screenWidth;
|
||||
curScreenHeight = screenHeight;
|
||||
|
||||
// Preset resolutions that could be created by subdividing screen resolution
|
||||
resolutionList = new Vector2[]
|
||||
{
|
||||
new Vector2(64, 64),
|
||||
new Vector2(256, 240),
|
||||
new Vector2(320, 180),
|
||||
// 4K doesn't work with integer scaling but included for example purposes with non-integer scaling
|
||||
new Vector2(3840, 2160),
|
||||
};
|
||||
|
||||
resolutionIndex = 0;
|
||||
gameWidth = 64;
|
||||
gameHeight = 64;
|
||||
|
||||
target = default;
|
||||
sourceRect = default;
|
||||
destRect = default;
|
||||
|
||||
viewportType = ViewportType.KeepAspectInteger;
|
||||
ResizeRenderSize(viewportType, ref curScreenWidth, ref curScreenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect, ref target);
|
||||
|
||||
// Button rectangles
|
||||
decreaseResolutionButton = new Rectangle(200, 30, 10, 10);
|
||||
increaseResolutionButton = new Rectangle(215, 30, 10, 10);
|
||||
decreaseTypeButton = new Rectangle(200, 45, 10, 10);
|
||||
increaseTypeButton = new Rectangle(215, 45, 10, 10);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsWindowResized())
|
||||
{
|
||||
ResizeRenderSize(viewportType, ref curScreenWidth, ref curScreenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect, ref target);
|
||||
}
|
||||
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
bool mousePressed = IsMouseButtonPressed(MouseButton.Left);
|
||||
|
||||
// Check buttons and rescale
|
||||
if (CheckCollisionPointRec(mousePosition, decreaseResolutionButton) && mousePressed)
|
||||
{
|
||||
resolutionIndex = (resolutionIndex + ResolutionCount - 1) % ResolutionCount;
|
||||
gameWidth = (int)resolutionList[resolutionIndex].X;
|
||||
gameHeight = (int)resolutionList[resolutionIndex].Y;
|
||||
ResizeRenderSize(viewportType, ref curScreenWidth, ref curScreenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect, ref target);
|
||||
}
|
||||
|
||||
if (CheckCollisionPointRec(mousePosition, increaseResolutionButton) && mousePressed)
|
||||
{
|
||||
resolutionIndex = (resolutionIndex + 1) % ResolutionCount;
|
||||
gameWidth = (int)resolutionList[resolutionIndex].X;
|
||||
gameHeight = (int)resolutionList[resolutionIndex].Y;
|
||||
ResizeRenderSize(viewportType, ref curScreenWidth, ref curScreenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect, ref target);
|
||||
}
|
||||
|
||||
if (CheckCollisionPointRec(mousePosition, decreaseTypeButton) && mousePressed)
|
||||
{
|
||||
viewportType = (ViewportType)(((int)viewportType + (int)ViewportType.ViewportTypeCount - 1) % (int)ViewportType.ViewportTypeCount);
|
||||
ResizeRenderSize(viewportType, ref curScreenWidth, ref curScreenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect, ref target);
|
||||
}
|
||||
|
||||
if (CheckCollisionPointRec(mousePosition, increaseTypeButton) && mousePressed)
|
||||
{
|
||||
viewportType = (ViewportType)(((int)viewportType + 1) % (int)ViewportType.ViewportTypeCount);
|
||||
ResizeRenderSize(viewportType, ref curScreenWidth, ref curScreenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect, ref target);
|
||||
}
|
||||
|
||||
Vector2 textureMousePosition = Screen2RenderTexturePosition(mousePosition, sourceRect, destRect);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw our scene to the render texture
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.White);
|
||||
DrawCircleV(textureMousePosition, 20.0f, Color.Lime);
|
||||
EndTextureMode();
|
||||
|
||||
// Draw render texture to main framebuffer
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
// Draw our render texture with rotation applied
|
||||
DrawTexturePro(target.Texture, sourceRect, destRect, new Vector2(0.0f, 0.0f), 0.0f, Color.White);
|
||||
|
||||
// Draw Native resolution (GUI or anything)
|
||||
// Draw info box
|
||||
Rectangle infoRect = new Rectangle(5, 5, 330, 105);
|
||||
DrawRectangleRec(infoRect, Fade(Color.LightGray, 0.7f));
|
||||
DrawRectangleLinesEx(infoRect, 1, Color.Blue);
|
||||
|
||||
DrawText($"Window Resolution: {curScreenWidth} x {curScreenHeight}", 15, 15, 10, Color.Black);
|
||||
DrawText($"Game Resolution: {gameWidth} x {gameHeight}", 15, 30, 10, Color.Black);
|
||||
|
||||
DrawText($"Type: {ViewportTypeNames[(int)viewportType]}", 15, 45, 10, Color.Black);
|
||||
Vector2 scaleRatio = new Vector2(destRect.Width / sourceRect.Width, -destRect.Height / sourceRect.Height);
|
||||
if (scaleRatio.X < 0.001f || scaleRatio.Y < 0.001f)
|
||||
{
|
||||
DrawText("Scale ratio: INVALID", 15, 60, 10, Color.Black);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText($"Scale ratio: {scaleRatio.X:F2} x {scaleRatio.Y:F2}", 15, 60, 10, Color.Black);
|
||||
}
|
||||
|
||||
DrawText($"Source size: {sourceRect.Width:F2} x {-sourceRect.Height:F2}", 15, 75, 10, Color.Black);
|
||||
DrawText($"Destination size: {destRect.Width:F2} x {destRect.Height:F2}", 15, 90, 10, Color.Black);
|
||||
|
||||
// Draw buttons
|
||||
DrawRectangleRec(decreaseTypeButton, Color.SkyBlue);
|
||||
DrawRectangleRec(increaseTypeButton, Color.SkyBlue);
|
||||
DrawRectangleRec(decreaseResolutionButton, Color.SkyBlue);
|
||||
DrawRectangleRec(increaseResolutionButton, Color.SkyBlue);
|
||||
DrawText("<", (int)decreaseTypeButton.X + 3, (int)decreaseTypeButton.Y + 1, 10, Color.Black);
|
||||
DrawText(">", (int)increaseTypeButton.X + 3, (int)increaseTypeButton.Y + 1, 10, Color.Black);
|
||||
DrawText("<", (int)decreaseResolutionButton.X + 3, (int)decreaseResolutionButton.Y + 1, 10, Color.Black);
|
||||
DrawText(">", (int)increaseResolutionButton.X + 3, (int)increaseResolutionButton.Y + 1, 10, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTexture(target);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
private static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, ref Rectangle sourceRect, ref Rectangle destRect)
|
||||
{
|
||||
sourceRect.X = 0.0f;
|
||||
sourceRect.Y = (float)gameHeight;
|
||||
sourceRect.Width = (float)gameWidth;
|
||||
sourceRect.Height = (float)-gameHeight;
|
||||
|
||||
int ratioX = (screenWidth / gameWidth);
|
||||
int ratioY = (screenHeight / gameHeight);
|
||||
float resizeRatio = (float)((ratioX < ratioY) ? ratioX : ratioY);
|
||||
|
||||
destRect.X = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5f);
|
||||
destRect.Y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5f);
|
||||
destRect.Width = (float)(int)(gameWidth * resizeRatio);
|
||||
destRect.Height = (float)(int)(gameHeight * resizeRatio);
|
||||
}
|
||||
|
||||
private static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, ref Rectangle sourceRect, ref Rectangle destRect)
|
||||
{
|
||||
float resizeRatio = (float)screenHeight / gameHeight;
|
||||
sourceRect.X = 0.0f;
|
||||
sourceRect.Y = 0.0f;
|
||||
sourceRect.Width = (float)(int)(screenWidth / resizeRatio);
|
||||
sourceRect.Height = (float)-gameHeight;
|
||||
|
||||
destRect.X = (float)(int)((screenWidth - (sourceRect.Width * resizeRatio)) * 0.5f);
|
||||
destRect.Y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5f);
|
||||
destRect.Width = (float)(int)(sourceRect.Width * resizeRatio);
|
||||
destRect.Height = (float)(int)(gameHeight * resizeRatio);
|
||||
}
|
||||
|
||||
private static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, ref Rectangle sourceRect, ref Rectangle destRect)
|
||||
{
|
||||
float resizeRatio = (float)screenWidth / gameWidth;
|
||||
sourceRect.X = 0.0f;
|
||||
sourceRect.Y = 0.0f;
|
||||
sourceRect.Width = (float)gameWidth;
|
||||
sourceRect.Height = (float)(int)(screenHeight / resizeRatio);
|
||||
|
||||
destRect.X = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5f);
|
||||
destRect.Y = (float)(int)((screenHeight - (sourceRect.Height * resizeRatio)) * 0.5f);
|
||||
destRect.Width = (float)(int)(gameWidth * resizeRatio);
|
||||
destRect.Height = (float)(int)(sourceRect.Height * resizeRatio);
|
||||
|
||||
sourceRect.Height *= -1.0f;
|
||||
}
|
||||
|
||||
private static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, ref Rectangle sourceRect, ref Rectangle destRect)
|
||||
{
|
||||
sourceRect.X = 0.0f;
|
||||
sourceRect.Y = (float)gameHeight;
|
||||
sourceRect.Width = (float)gameWidth;
|
||||
sourceRect.Height = (float)-gameHeight;
|
||||
|
||||
float ratioX = ((float)screenWidth / (float)gameWidth);
|
||||
float ratioY = ((float)screenHeight / (float)gameHeight);
|
||||
float resizeRatio = (ratioX < ratioY ? ratioX : ratioY);
|
||||
|
||||
destRect.X = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5f);
|
||||
destRect.Y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5f);
|
||||
destRect.Width = (float)(int)(gameWidth * resizeRatio);
|
||||
destRect.Height = (float)(int)(gameHeight * resizeRatio);
|
||||
}
|
||||
|
||||
private static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, ref Rectangle sourceRect, ref Rectangle destRect)
|
||||
{
|
||||
float resizeRatio = ((float)screenHeight / (float)gameHeight);
|
||||
sourceRect.X = 0.0f;
|
||||
sourceRect.Y = 0.0f;
|
||||
sourceRect.Width = (float)(int)((float)screenWidth / resizeRatio);
|
||||
sourceRect.Height = (float)-gameHeight;
|
||||
|
||||
destRect.X = (float)(int)((screenWidth - (sourceRect.Width * resizeRatio)) * 0.5f);
|
||||
destRect.Y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5f);
|
||||
destRect.Width = (float)(int)(sourceRect.Width * resizeRatio);
|
||||
destRect.Height = (float)(int)(gameHeight * resizeRatio);
|
||||
}
|
||||
|
||||
private static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, ref Rectangle sourceRect, ref Rectangle destRect)
|
||||
{
|
||||
float resizeRatio = ((float)screenWidth / (float)gameWidth);
|
||||
sourceRect.X = 0.0f;
|
||||
sourceRect.Y = 0.0f;
|
||||
sourceRect.Width = (float)gameWidth;
|
||||
sourceRect.Height = (float)(int)((float)screenHeight / resizeRatio);
|
||||
|
||||
destRect.X = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5f);
|
||||
destRect.Y = (float)(int)((screenHeight - (sourceRect.Height * resizeRatio)) * 0.5f);
|
||||
destRect.Width = (float)(int)(gameWidth * resizeRatio);
|
||||
destRect.Height = (float)(int)(sourceRect.Height * resizeRatio);
|
||||
|
||||
sourceRect.Height *= -1.0f;
|
||||
}
|
||||
|
||||
private static void ResizeRenderSize(ViewportType viewportType, ref int screenWidth, ref int screenHeight, int gameWidth, int gameHeight, ref Rectangle sourceRect, ref Rectangle destRect, ref RenderTexture2D target)
|
||||
{
|
||||
screenWidth = GetScreenWidth();
|
||||
screenHeight = GetScreenHeight();
|
||||
|
||||
switch (viewportType)
|
||||
{
|
||||
case ViewportType.KeepAspectInteger:
|
||||
KeepAspectCenteredInteger(screenWidth, screenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect);
|
||||
break;
|
||||
case ViewportType.KeepHeightInteger:
|
||||
KeepHeightCenteredInteger(screenWidth, screenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect);
|
||||
break;
|
||||
case ViewportType.KeepWidthInteger:
|
||||
KeepWidthCenteredInteger(screenWidth, screenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect);
|
||||
break;
|
||||
case ViewportType.KeepAspect:
|
||||
KeepAspectCentered(screenWidth, screenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect);
|
||||
break;
|
||||
case ViewportType.KeepHeight:
|
||||
KeepHeightCentered(screenWidth, screenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect);
|
||||
break;
|
||||
case ViewportType.KeepWidth:
|
||||
KeepWidthCentered(screenWidth, screenHeight, gameWidth, gameHeight, ref sourceRect, ref destRect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
UnloadRenderTexture(target);
|
||||
target = LoadRenderTexture((int)sourceRect.Width, -(int)sourceRect.Height);
|
||||
}
|
||||
|
||||
// Example how to calculate position on RenderTexture
|
||||
private static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle textureRect, Rectangle scaledRect)
|
||||
{
|
||||
Vector2 relativePosition = new Vector2(point.X - scaledRect.X, point.Y - scaledRect.Y);
|
||||
Vector2 ratio = new Vector2(textureRect.Width / scaledRect.Width, -textureRect.Height / scaledRect.Height);
|
||||
|
||||
return new Vector2(relativePosition.X * ratio.X, relativePosition.Y * ratio.X);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//---------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.ResizableWindow);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - viewport scaling");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//----------------------------------------------------------
|
||||
|
||||
var game = new ViewportScaling();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//----------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +1,76 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - VR Simulator (Oculus Rift CV1 parameters)
|
||||
* raylib [core] example - vr simulator
|
||||
*
|
||||
* This example has been created using raylib 1.7 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Copyright (c) 2017 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class VrSimulator
|
||||
public partial class VrSimulator : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Core / VR Simulator";
|
||||
|
||||
public string Title => "raylib [core] example - vr simulator";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private VrStereoConfig config;
|
||||
private Shader distortion;
|
||||
private RenderTexture2D target;
|
||||
private Rectangle sourceRec;
|
||||
private Rectangle destRec;
|
||||
private Camera3D camera;
|
||||
private Vector3 cubePosition;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 1080;
|
||||
const int screenHeight = 600;
|
||||
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator");
|
||||
|
||||
// VR device parameters definition
|
||||
VrDeviceInfo device = new VrDeviceInfo
|
||||
var device = new VrDeviceInfo
|
||||
{
|
||||
// Oculus Rift CV1 parameters for simulator
|
||||
HResolution = 2160,
|
||||
VResolution = 1200,
|
||||
HScreenSize = 0.133793f,
|
||||
VScreenSize = 0.0669f,
|
||||
EyeToScreenDistance = 0.041f,
|
||||
LensSeparationDistance = 0.07f,
|
||||
InterpupillaryDistance = 0.07f,
|
||||
HResolution = 2160, // Horizontal resolution in pixels
|
||||
VResolution = 1200, // Vertical resolution in pixels
|
||||
HScreenSize = 0.133793f, // Horizontal size in meters
|
||||
VScreenSize = 0.0669f, // Vertical size in meters
|
||||
EyeToScreenDistance = 0.041f, // Distance between eye and display in meters
|
||||
LensSeparationDistance = 0.07f, // Lens separation distance in meters
|
||||
InterpupillaryDistance = 0.07f, // IPD (distance between pupils) in meters
|
||||
};
|
||||
|
||||
// NOTE: CV1 uses a Fresnel-hybrid-asymmetric lenses with specific distortion compute shaders.
|
||||
// Following parameters are an approximation to distortion stereo rendering but results differ from actual
|
||||
// device.
|
||||
unsafe
|
||||
{
|
||||
device.LensDistortionValues[0] = 1.0f;
|
||||
device.LensDistortionValues[1] = 0.22f;
|
||||
device.LensDistortionValues[2] = 0.24f;
|
||||
device.LensDistortionValues[3] = 0.0f;
|
||||
device.ChromaAbCorrection[0] = 0.996f;
|
||||
device.ChromaAbCorrection[1] = -0.004f;
|
||||
device.ChromaAbCorrection[2] = 1.014f;
|
||||
device.ChromaAbCorrection[3] = 0.0f;
|
||||
}
|
||||
// NOTE: CV1 uses fresnel-hybrid-asymmetric lenses with specific compute shaders
|
||||
// Following parameters are just an approximation to CV1 distortion stereo rendering
|
||||
device.LensDistortionValues[0] = 1.0f; // Lens distortion constant parameter 0
|
||||
device.LensDistortionValues[1] = 0.22f; // Lens distortion constant parameter 1
|
||||
device.LensDistortionValues[2] = 0.24f; // Lens distortion constant parameter 2
|
||||
device.LensDistortionValues[3] = 0.0f; // Lens distortion constant parameter 3
|
||||
device.ChromaAbCorrection[0] = 0.996f; // Chromatic aberration correction parameter 0
|
||||
device.ChromaAbCorrection[1] = -0.004f; // Chromatic aberration correction parameter 1
|
||||
device.ChromaAbCorrection[2] = 1.014f; // Chromatic aberration correction parameter 2
|
||||
device.ChromaAbCorrection[3] = 0.0f; // Chromatic aberration correction parameter 3
|
||||
|
||||
// Load VR stereo config for VR device parameteres (Oculus Rift CV1 parameters)
|
||||
VrStereoConfig config = LoadVrStereoConfig(device);
|
||||
config = LoadVrStereoConfig(device);
|
||||
|
||||
// Distortion shader (uses device lens distortion and chroma)
|
||||
Shader distortion = LoadShader(null, "resources/distortion330.fs");
|
||||
distortion = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/distortion.fs");
|
||||
|
||||
// Update distortion shader with lens and distortion-scale parameters
|
||||
Raylib.SetShaderValue(
|
||||
|
|
@ -100,88 +111,104 @@ public class VrSimulator
|
|||
ShaderUniformDataType.Vec2
|
||||
);
|
||||
|
||||
unsafe
|
||||
{
|
||||
SetShaderValue(
|
||||
distortion,
|
||||
GetShaderLocation(distortion, "deviceWarpParam"),
|
||||
device.LensDistortionValues,
|
||||
ShaderUniformDataType.Vec4
|
||||
);
|
||||
SetShaderValue(
|
||||
distortion,
|
||||
GetShaderLocation(distortion, "chromaAbParam"),
|
||||
device.ChromaAbCorrection,
|
||||
ShaderUniformDataType.Vec4
|
||||
);
|
||||
}
|
||||
SetShaderValue(
|
||||
distortion,
|
||||
GetShaderLocation(distortion, "deviceWarpParam"),
|
||||
device.LensDistortionValues,
|
||||
ShaderUniformDataType.Vec4
|
||||
);
|
||||
SetShaderValue(
|
||||
distortion,
|
||||
GetShaderLocation(distortion, "chromaAbParam"),
|
||||
device.ChromaAbCorrection,
|
||||
ShaderUniformDataType.Vec4
|
||||
);
|
||||
|
||||
// Initialize framebuffer for stereo rendering
|
||||
// NOTE: Screen size should match HMD aspect ratio
|
||||
RenderTexture2D target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
target = LoadRenderTexture(device.HResolution, device.VResolution);
|
||||
|
||||
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
|
||||
sourceRec = new(0.0f, 0.0f, (float)target.Texture.Width, -(float)target.Texture.Height);
|
||||
destRec = new(0.0f, 0.0f, (float)GetScreenWidth(), (float)GetScreenHeight());
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera;
|
||||
camera.Position = new Vector3(5.0f, 2.0f, 5.0f);
|
||||
camera.Target = new Vector3(0.0f, 2.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 60.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
camera = new();
|
||||
camera.Position = new Vector3(5.0f, 2.0f, 5.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 2.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector
|
||||
camera.FovY = 60.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
Vector3 cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
SetTargetFPS(90); // Set our game to run at 90 frames-per-second
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.FirstPerson);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
BeginVrStereoMode(config);
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
DrawGrid(40, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
EndVrStereoMode();
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
BeginShaderMode(distortion);
|
||||
DrawTexturePro(target.Texture, sourceRec, destRec, new Vector2(0.0f, 0.0f), 0.0f, Color.White);
|
||||
EndShaderMode();
|
||||
DrawFPS(10, 10);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadVrStereoConfig(config); // Unload stereo config
|
||||
|
||||
UnloadRenderTexture(target); // Unload stereo render fbo
|
||||
UnloadShader(distortion); // Unload distortion shader
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
// NOTE: screenWidth/screenHeight should match VR device aspect ratio
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator");
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new VrSimulator();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.FirstPerson);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginVrStereoMode(config);
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
DrawGrid(40, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
EndVrStereoMode();
|
||||
EndTextureMode();
|
||||
|
||||
BeginShaderMode(distortion);
|
||||
DrawTextureRec(
|
||||
target.Texture,
|
||||
new Rectangle(0, 0, (float)target.Texture.Width, (float)-target.Texture.Height),
|
||||
new Vector2(0.0f, 0.0f),
|
||||
Color.White
|
||||
);
|
||||
EndShaderMode();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadVrStereoConfig(config);
|
||||
UnloadRenderTexture(target);
|
||||
UnloadShader(distortion);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -2,28 +2,254 @@
|
|||
*
|
||||
* raylib [core] example - window flags
|
||||
*
|
||||
* This example has been created using raylib 3.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Copyright (c) 2020 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 3.5, last time updated with raylib 3.5
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2020-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.ConfigFlags;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class WindowFlags
|
||||
[ExcludeFromBrowser("runtime window-state flags don't apply to the emscripten canvas")]
|
||||
public partial class WindowFlags : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Window Flags";
|
||||
|
||||
public string Title => "raylib [core] example - window flags";
|
||||
|
||||
private Vector2 ballPosition;
|
||||
private Vector2 ballSpeed;
|
||||
private float ballRadius;
|
||||
|
||||
private int framesCounter = 0;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
ballPosition = new(GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f);
|
||||
ballSpeed = new(5.0f, 4.0f);
|
||||
ballRadius = 20;
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//-----------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.F))
|
||||
{
|
||||
// modifies window size when scaling!
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
if (IsWindowState(ResizableWindow))
|
||||
{
|
||||
ClearWindowState(ResizableWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(ResizableWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.D))
|
||||
{
|
||||
if (IsWindowState(UndecoratedWindow))
|
||||
{
|
||||
ClearWindowState(UndecoratedWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(UndecoratedWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.H))
|
||||
{
|
||||
if (!IsWindowState(HiddenWindow))
|
||||
{
|
||||
SetWindowState(HiddenWindow);
|
||||
}
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
if (IsWindowState(HiddenWindow))
|
||||
{
|
||||
framesCounter++;
|
||||
if (framesCounter >= 240)
|
||||
{
|
||||
// Show window after 3 seconds
|
||||
ClearWindowState(HiddenWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.N))
|
||||
{
|
||||
if (!IsWindowState(MinimizedWindow))
|
||||
{
|
||||
MinimizeWindow();
|
||||
}
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
if (IsWindowState(MinimizedWindow))
|
||||
{
|
||||
framesCounter++;
|
||||
if (framesCounter >= 240)
|
||||
{
|
||||
// Restore window after 3 seconds
|
||||
RestoreWindow();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.M))
|
||||
{
|
||||
// NOTE: Requires FLAG_WINDOW_RESIZABLE enabled!
|
||||
if (IsWindowState(MaximizedWindow))
|
||||
{
|
||||
RestoreWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
MaximizeWindow();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.U))
|
||||
{
|
||||
if (IsWindowState(UnfocusedWindow))
|
||||
{
|
||||
ClearWindowState(UnfocusedWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(UnfocusedWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.T))
|
||||
{
|
||||
if (IsWindowState(TopmostWindow))
|
||||
{
|
||||
ClearWindowState(TopmostWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(TopmostWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.A))
|
||||
{
|
||||
if (IsWindowState(AlwaysRunWindow))
|
||||
{
|
||||
ClearWindowState(AlwaysRunWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(AlwaysRunWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.V))
|
||||
{
|
||||
if (IsWindowState(VSyncHint))
|
||||
{
|
||||
ClearWindowState(VSyncHint);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(VSyncHint);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.B))
|
||||
{
|
||||
ToggleBorderlessWindowed();
|
||||
}
|
||||
|
||||
// Bouncing ball logic
|
||||
ballPosition.X += ballSpeed.X;
|
||||
ballPosition.Y += ballSpeed.Y;
|
||||
if ((ballPosition.X >= (GetScreenWidth() - ballRadius)) || (ballPosition.X <= ballRadius))
|
||||
{
|
||||
ballSpeed.X *= -1.0f;
|
||||
}
|
||||
if ((ballPosition.Y >= (GetScreenHeight() - ballRadius)) || (ballPosition.Y <= ballRadius))
|
||||
{
|
||||
ballSpeed.Y *= -1.0f;
|
||||
}
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//-----------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
if (IsWindowState(TransparentWindow))
|
||||
{
|
||||
ClearBackground(Color.Blank);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearBackground(Color.RayWhite);
|
||||
}
|
||||
|
||||
DrawCircleV(ballPosition, ballRadius, Color.Maroon);
|
||||
DrawRectangleLinesEx(new Rectangle(0, 0, GetScreenWidth(), GetScreenHeight()), 4, Color.RayWhite);
|
||||
|
||||
DrawCircleV(GetMousePosition(), 10, Color.DarkBlue);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
DrawText($"Screen Size: [{GetScreenWidth()}, {GetScreenHeight()}]", 10, 40, 10, Color.Green);
|
||||
|
||||
// Draw window state info
|
||||
DrawText("Following flags can be set after window creation:", 10, 60, 10, Color.Gray);
|
||||
|
||||
DrawWindowState(FullscreenMode, "[F] FLAG_FULLSCREEN_MODE: ", 10, 80, 10);
|
||||
DrawWindowState(ResizableWindow, "[R] FLAG_WINDOW_RESIZABLE: ", 10, 100, 10);
|
||||
DrawWindowState(UndecoratedWindow, "[D] FLAG_WINDOW_UNDECORATED: ", 10, 120, 10);
|
||||
DrawWindowState(HiddenWindow, "[H] FLAG_WINDOW_HIDDEN: ", 10, 140, 10);
|
||||
DrawWindowState(MinimizedWindow, "[N] FLAG_WINDOW_MINIMIZED: ", 10, 160, 10);
|
||||
DrawWindowState(MaximizedWindow, "[M] FLAG_WINDOW_MAXIMIZED: ", 10, 180, 10);
|
||||
DrawWindowState(UnfocusedWindow, "[G] FLAG_WINDOW_UNFOCUSED: ", 10, 200, 10);
|
||||
DrawWindowState(TopmostWindow, "[T] FLAG_WINDOW_TOPMOST: ", 10, 220, 10);
|
||||
DrawWindowState(AlwaysRunWindow, "[A] FLAG_WINDOW_ALWAYS_RUN: ", 10, 240, 10);
|
||||
DrawWindowState(VSyncHint, "[V] FLAG_VSYNC_HINT: ", 10, 260, 10);
|
||||
DrawWindowState(BorderlessWindowMode, "[B] FLAG_BORDERLESS_WINDOWED_MODE: ", 10, 280, 10);
|
||||
|
||||
DrawText("Following flags can only be set before window creation:", 10, 320, 10, Color.Gray);
|
||||
|
||||
DrawWindowState(HighDpiWindow, "FLAG_WINDOW_HIGHDPI: ", 10, 340, 10);
|
||||
DrawWindowState(TransparentWindow, "FLAG_WINDOW_TRANSPARENT: ", 10, 360, 10);
|
||||
DrawWindowState(Msaa4xHint, "FLAG_MSAA_4X_HINT: ", 10, 380, 10);
|
||||
|
||||
EndDrawing();
|
||||
//-----------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//---------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Possible window flags
|
||||
/*
|
||||
FLAG_VSYNC_HINT
|
||||
|
|
@ -42,235 +268,43 @@ public class WindowFlags
|
|||
*/
|
||||
|
||||
// Set configuration flags for window creation
|
||||
SetConfigFlags(VSyncHint | Msaa4xHint);
|
||||
//SetConfigFlags(VSyncHint | Msaa4xHint | HighDpiWindow);// | TransparentWindow);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - window flags");
|
||||
|
||||
Vector2 ballPosition = new(GetScreenWidth() / 2, GetScreenHeight() / 2);
|
||||
Vector2 ballSpeed = new(5.0f, 4.0f);
|
||||
int ballRadius = 20;
|
||||
|
||||
int framesCounter = 0;
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//----------------------------------------------------------
|
||||
|
||||
var game = new WindowFlags();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//-----------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.F))
|
||||
{
|
||||
// modifies window size when scaling!
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.R))
|
||||
{
|
||||
if (IsWindowState(ResizableWindow))
|
||||
{
|
||||
ClearWindowState(ResizableWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(ResizableWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.D))
|
||||
{
|
||||
if (IsWindowState(UndecoratedWindow))
|
||||
{
|
||||
ClearWindowState(UndecoratedWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(UndecoratedWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.H))
|
||||
{
|
||||
if (!IsWindowState(HiddenWindow))
|
||||
{
|
||||
SetWindowState(HiddenWindow);
|
||||
}
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
if (IsWindowState(HiddenWindow))
|
||||
{
|
||||
framesCounter++;
|
||||
if (framesCounter >= 240)
|
||||
{
|
||||
// Show window after 3 seconds
|
||||
ClearWindowState(HiddenWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.N))
|
||||
{
|
||||
if (!IsWindowState(MinimizedWindow))
|
||||
{
|
||||
MinimizeWindow();
|
||||
}
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
if (IsWindowState(MinimizedWindow))
|
||||
{
|
||||
framesCounter++;
|
||||
if (framesCounter >= 240)
|
||||
{
|
||||
// Restore window after 3 seconds
|
||||
RestoreWindow();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.M))
|
||||
{
|
||||
// NOTE: Requires FLAG_WINDOW_RESIZABLE enabled!
|
||||
if (IsWindowState(MaximizedWindow))
|
||||
{
|
||||
RestoreWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
MaximizeWindow();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.U))
|
||||
{
|
||||
if (IsWindowState(UnfocusedWindow))
|
||||
{
|
||||
ClearWindowState(UnfocusedWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(UnfocusedWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.T))
|
||||
{
|
||||
if (IsWindowState(TopmostWindow))
|
||||
{
|
||||
ClearWindowState(TopmostWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(TopmostWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.A))
|
||||
{
|
||||
if (IsWindowState(AlwaysRunWindow))
|
||||
{
|
||||
ClearWindowState(AlwaysRunWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(AlwaysRunWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.V))
|
||||
{
|
||||
if (IsWindowState(VSyncHint))
|
||||
{
|
||||
ClearWindowState(VSyncHint);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowState(VSyncHint);
|
||||
}
|
||||
}
|
||||
|
||||
// Bouncing ball logic
|
||||
ballPosition.X += ballSpeed.X;
|
||||
ballPosition.Y += ballSpeed.Y;
|
||||
if ((ballPosition.X >= (GetScreenWidth() - ballRadius)) || (ballPosition.X <= ballRadius))
|
||||
{
|
||||
ballSpeed.X *= -1.0f;
|
||||
}
|
||||
if ((ballPosition.Y >= (GetScreenHeight() - ballRadius)) || (ballPosition.Y <= ballRadius))
|
||||
{
|
||||
ballSpeed.Y *= -1.0f;
|
||||
}
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//-----------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
if (IsWindowState(TransparentWindow))
|
||||
{
|
||||
ClearBackground(Color.Blank);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearBackground(Color.RayWhite);
|
||||
}
|
||||
|
||||
DrawCircleV(ballPosition, ballRadius, Color.Maroon);
|
||||
DrawRectangleLinesEx(new Rectangle(0, 0, GetScreenWidth(), GetScreenHeight()), 4, Color.RayWhite);
|
||||
|
||||
DrawCircleV(GetMousePosition(), 10, Color.DarkBlue);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
DrawText($"Screen Size: [{GetScreenWidth()}, {GetScreenHeight()}]", 10, 40, 10, Color.Green);
|
||||
|
||||
// Draw window state info
|
||||
Color on = Color.Lime;
|
||||
Color off = Color.Maroon;
|
||||
|
||||
DrawText("Following flags can be set after window creation:", 10, 60, 10, Color.Gray);
|
||||
|
||||
DrawWindowState(FullscreenMode, "[F] FLAG_FULLSCREEN_MODE: ", 10, 80, 10);
|
||||
DrawWindowState(ResizableWindow, "[R] FLAG_WINDOW_RESIZABLE: ", 10, 100, 10);
|
||||
DrawWindowState(UndecoratedWindow, "[D] FLAG_WINDOW_UNDECORATED: ", 10, 120, 10);
|
||||
DrawWindowState(HiddenWindow, "[H] FLAG_WINDOW_HIDDEN: ", 10, 140, 10);
|
||||
DrawWindowState(MinimizedWindow, "[N] FLAG_WINDOW_MINIMIZED: ", 10, 160, 10);
|
||||
DrawWindowState(MaximizedWindow, "[M] FLAG_WINDOW_MAXIMIZED: ", 10, 180, 10);
|
||||
DrawWindowState(UnfocusedWindow, "[G] FLAG_WINDOW_UNFOCUSED: ", 10, 200, 10);
|
||||
DrawWindowState(TopmostWindow, "[T] FLAG_WINDOW_TOPMOST: ", 10, 220, 10);
|
||||
DrawWindowState(AlwaysRunWindow, "[A] FLAG_WINDOW_ALWAYS_RUN: ", 10, 240, 10);
|
||||
DrawWindowState(VSyncHint, "[V] FLAG_VSYNC_HINT: ", 10, 260, 10);
|
||||
|
||||
DrawText("Following flags can only be set before window creation:", 10, 300, 10, Color.Gray);
|
||||
|
||||
DrawWindowState(HighDpiWindow, "[F] FLAG_WINDOW_HIGHDPI: ", 10, 320, 10);
|
||||
DrawWindowState(TransparentWindow, "[F] FLAG_WINDOW_TRANSPARENT: ", 10, 340, 10);
|
||||
DrawWindowState(Msaa4xHint, "[F] FLAG_MSAA_4X_HINT: ", 10, 360, 10);
|
||||
|
||||
EndDrawing();
|
||||
//-----------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//---------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//----------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DrawWindowState(ConfigFlags flag, string text, int posX, int posY, int fontSize)
|
||||
private static void DrawWindowState(ConfigFlags flag, string text, int posX, int posY, int fontSize)
|
||||
{
|
||||
Color onColor = Color.Lime;
|
||||
Color offColor = Color.Maroon;
|
||||
var onColor = Color.Lime;
|
||||
var offColor = Color.Maroon;
|
||||
|
||||
if (Raylib.IsWindowState(flag))
|
||||
{
|
||||
DrawText($"{text} on", posX, posY, fontSize, onColor);
|
||||
DrawText($"{text}on", posX, posY, fontSize, onColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText($"{text} off", posX, posY, fontSize, offColor);
|
||||
DrawText($"{text}off", posX, posY, fontSize, offColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,139 +1,169 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - window scale letterbox
|
||||
* raylib [core] example - window letterbox
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 Anata (@anatagawa) and Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2019-2025 Anata (@anatagawa) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class WindowLetterbox
|
||||
public partial class WindowLetterbox : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int windowWidth = 800;
|
||||
private const int windowHeight = 450;
|
||||
|
||||
private const int gamescreenWidth = 640;
|
||||
private const int gamescreenHeight = 480;
|
||||
|
||||
public string Name => "Core / Window Letterbox";
|
||||
|
||||
public string Title => "raylib [core] example - window letterbox";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.ResizableWindow | ConfigFlags.VSyncHint;
|
||||
|
||||
private RenderTexture2D target;
|
||||
private Color[] colors;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
const int windowWidth = 800;
|
||||
const int windowHeight = 450;
|
||||
|
||||
// Enable config flags for resizable window and vertical synchro
|
||||
SetConfigFlags(ConfigFlags.ResizableWindow | ConfigFlags.VSyncHint);
|
||||
InitWindow(windowWidth, windowHeight, "raylib [core] example - window scale letterbox");
|
||||
SetWindowMinSize(320, 240);
|
||||
|
||||
int gameScreenWidth = 640;
|
||||
int gameScreenHeight = 480;
|
||||
|
||||
// Render texture initialization, used to hold the rendering result so we can easily resize it
|
||||
RenderTexture2D target = LoadRenderTexture(gameScreenWidth, gameScreenHeight);
|
||||
SetTextureFilter(target.Texture, TextureFilter.Bilinear);
|
||||
target = LoadRenderTexture(gamescreenWidth, gamescreenHeight);
|
||||
SetTextureFilter(target.Texture, TextureFilter.Bilinear); // Texture scale filter to use
|
||||
|
||||
Color[] colors = new Color[10];
|
||||
for (int i = 0; i < 10; i++)
|
||||
colors = new Color[10];
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
colors[i] = new Color(GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255);
|
||||
}
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Compute required framebuffer scaling
|
||||
var scale = MathF.Min(
|
||||
(float)GetScreenWidth() / gamescreenWidth,
|
||||
(float)GetScreenHeight() / gamescreenHeight
|
||||
);
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
// Recalculate random colors for the bars
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
colors[i] = new Color(
|
||||
GetRandomValue(100, 250),
|
||||
GetRandomValue(50, 150),
|
||||
GetRandomValue(10, 100),
|
||||
255
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Update virtual mouse (clamped mouse value behind game screen)
|
||||
var mouse = GetMousePosition();
|
||||
var virtualMouse = Vector2.Zero;
|
||||
virtualMouse.X = (mouse.X - (GetScreenWidth() - (gamescreenWidth * scale)) * 0.5f) / scale;
|
||||
virtualMouse.Y = (mouse.Y - (GetScreenHeight() - (gamescreenHeight * scale)) * 0.5f) / scale;
|
||||
|
||||
Vector2 max = new((float)gamescreenWidth, (float)gamescreenHeight);
|
||||
virtualMouse = Vector2.Clamp(virtualMouse, Vector2.Zero, max);
|
||||
|
||||
// Apply the same transformation as the virtual mouse to the real mouse (i.e. to work with raygui)
|
||||
//SetMouseOffset(-(GetScreenWidth() - (gamescreenWidth*scale))*0.5f, -(GetScreenHeight() - (gamescreenHeight*scale))*0.5f);
|
||||
//SetMouseScale(1/scale, 1/scale);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw everything in the render texture, note this will not be rendered on screen, yet
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite); // Clear render texture background color
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
DrawRectangle(0, (gamescreenHeight / 10) * i, gamescreenWidth, gamescreenHeight / 10, colors[i]);
|
||||
}
|
||||
|
||||
DrawText(
|
||||
"If executed inside a window,\nyou can resize the window,\nand see the screen scaling!",
|
||||
10,
|
||||
25,
|
||||
20,
|
||||
Color.White
|
||||
);
|
||||
|
||||
DrawText($"Default Mouse: [{(int)mouse.X} , {(int)mouse.Y}]", 350, 25, 20, Color.Green);
|
||||
DrawText($"Virtual Mouse: [{(int)virtualMouse.X} , {(int)virtualMouse.Y}]", 350, 55, 20, Color.Yellow);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black); // Clear screen background
|
||||
|
||||
// Draw render texture to screen, properly scaled
|
||||
Rectangle sourceRec = new(
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)target.Texture.Width,
|
||||
(float)-target.Texture.Height
|
||||
);
|
||||
Rectangle destRec = new(
|
||||
(GetScreenWidth() - ((float)gamescreenWidth * scale)) * 0.5f,
|
||||
(GetScreenHeight() - ((float)gamescreenHeight * scale)) * 0.5f,
|
||||
(float)gamescreenWidth * scale,
|
||||
(float)gamescreenHeight * scale
|
||||
);
|
||||
DrawTexturePro(target.Texture, sourceRec, destRec, new Vector2(0, 0), 0.0f, Color.White);
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadRenderTexture(target); // Unload render texture
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Enable config flags for resizable window and vertical synchro
|
||||
SetConfigFlags(ConfigFlags.ResizableWindow | ConfigFlags.VSyncHint);
|
||||
InitWindow(windowWidth, windowHeight, "raylib [core] example - window letterbox");
|
||||
SetWindowMinSize(320, 240);
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new WindowLetterbox();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Compute required framebuffer scaling
|
||||
float scale = MathF.Min(
|
||||
(float)GetScreenWidth() / gameScreenWidth,
|
||||
(float)GetScreenHeight() / gameScreenHeight
|
||||
);
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
// Recalculate random colors for the bars
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
colors[i] = new Color(
|
||||
GetRandomValue(100, 250),
|
||||
GetRandomValue(50, 150),
|
||||
GetRandomValue(10, 100),
|
||||
255
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Update virtual mouse (clamped mouse value behind game screen)
|
||||
Vector2 mouse = GetMousePosition();
|
||||
Vector2 virtualMouse = Vector2.Zero;
|
||||
virtualMouse.X = (mouse.X - (GetScreenWidth() - (gameScreenWidth * scale)) * 0.5f) / scale;
|
||||
virtualMouse.Y = (mouse.Y - (GetScreenHeight() - (gameScreenHeight * scale)) * 0.5f) / scale;
|
||||
|
||||
Vector2 max = new((float)gameScreenWidth, (float)gameScreenHeight);
|
||||
virtualMouse = Vector2.Clamp(virtualMouse, Vector2.Zero, max);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.Black);
|
||||
|
||||
// Draw everything in the render texture, note this will not be rendered on screen, yet
|
||||
BeginTextureMode(target);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
DrawRectangle(0, (gameScreenHeight / 10) * i, gameScreenWidth, gameScreenHeight / 10, colors[i]);
|
||||
}
|
||||
|
||||
DrawText(
|
||||
"If executed inside a window,\nyou can resize the window,\nand see the screen scaling!",
|
||||
10,
|
||||
25,
|
||||
20,
|
||||
Color.White
|
||||
);
|
||||
|
||||
DrawText($"Default Mouse: [{(int)mouse.X} {(int)mouse.Y}]", 350, 25, 20, Color.Green);
|
||||
DrawText($"Virtual Mouse: [{(int)virtualMouse.X}, {(int)virtualMouse.Y}]", 350, 55, 20, Color.Yellow);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw RenderTexture2D to window, properly scaled
|
||||
Rectangle sourceRec = new(
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)target.Texture.Width,
|
||||
(float)-target.Texture.Height
|
||||
);
|
||||
Rectangle destRec = new(
|
||||
(GetScreenWidth() - ((float)gameScreenWidth * scale)) * 0.5f,
|
||||
(GetScreenHeight() - ((float)gameScreenHeight * scale)) * 0.5f,
|
||||
(float)gameScreenWidth * scale,
|
||||
(float)gameScreenHeight * scale
|
||||
);
|
||||
DrawTexturePro(target.Texture, sourceRec, destRec, new Vector2(0, 0), 0.0f, Color.White);
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(target);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
126
Examples/Core/WindowShouldClose.cs
Normal file
126
Examples/Core/WindowShouldClose.cs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - window should close
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public partial class WindowShouldClose : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / Window Should Close";
|
||||
|
||||
public string Title => "raylib [core] example - window should close";
|
||||
|
||||
// The runner drives its loop off this instead of WindowShouldClose(), so the exit
|
||||
// confirmation (polled in Update) can intercept both the X-button and KEY_ESCAPE.
|
||||
public bool ShouldClose => exitWindow;
|
||||
|
||||
private bool exitWindowRequested; // Flag to request window to exit
|
||||
private bool exitWindow; // Flag to set window to exit
|
||||
|
||||
public void Init()
|
||||
{
|
||||
SetExitKey(KeyboardKey.Null); // Disable KEY_ESCAPE to close window, X-button still works
|
||||
|
||||
exitWindowRequested = false;
|
||||
exitWindow = false;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Detect if X-button or KEY_ESCAPE have been pressed to close window
|
||||
bool closeRequested = IsKeyPressed(KeyboardKey.Escape);
|
||||
#if !BROWSER
|
||||
// WindowShouldClose() polls the OS window close button, but on the wasm target it calls
|
||||
// emscripten_sleep (ASYNCIFY is not enabled) and the canvas has no window chrome anyway,
|
||||
// so on web the confirmation is triggered by KEY_ESCAPE only.
|
||||
closeRequested |= Raylib.WindowShouldClose();
|
||||
#endif
|
||||
if (closeRequested)
|
||||
{
|
||||
exitWindowRequested = true;
|
||||
}
|
||||
|
||||
if (exitWindowRequested)
|
||||
{
|
||||
// A request for close window has been issued, we can save data before closing
|
||||
// or just show a message asking for confirmation
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Y))
|
||||
{
|
||||
exitWindow = true;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.N))
|
||||
{
|
||||
exitWindowRequested = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (exitWindowRequested)
|
||||
{
|
||||
DrawRectangle(0, 100, screenWidth, 200, Color.Black);
|
||||
DrawText("Are you sure you want to exit program? [Y/N]", 40, 180, 30, Color.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("Try to close the window to get confirmation message!", 120, 200, 20, Color.LightGray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - window should close");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new WindowShouldClose();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!game.exitWindow)
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,97 +1,127 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - World to screen
|
||||
* raylib [core] example - world screen
|
||||
*
|
||||
* This example has been created using raylib 1.3 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 1.4
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Core;
|
||||
|
||||
public class WorldScreen
|
||||
public partial class WorldScreen : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Core / World to Screen";
|
||||
|
||||
public string Title => "raylib [core] example - world screen";
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private Camera3D camera;
|
||||
private Vector3 cubePosition;
|
||||
private Vector2 cubeScreenPosition = new(0.0f, 0.0f);
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(10.0f, 10.0f, 10.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.ThirdPerson);
|
||||
|
||||
// Calculate cube screen space position (with a little offset to be in top)
|
||||
cubeScreenPosition = GetWorldToScreen(
|
||||
new Vector3(cubePosition.X, cubePosition.Y + 2.5f, cubePosition.Z),
|
||||
camera
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText(
|
||||
"Enemy: 100/100",
|
||||
(int)cubeScreenPosition.X - MeasureText("Enemy: 100/100", 20) / 2,
|
||||
(int)cubeScreenPosition.Y,
|
||||
20,
|
||||
Color.Black
|
||||
);
|
||||
|
||||
DrawText(
|
||||
$"Cube position in screen space coordinates: [{(int)cubeScreenPosition.X}, {(int)cubeScreenPosition.Y}]",
|
||||
10,
|
||||
10,
|
||||
20,
|
||||
Color.Lime
|
||||
);
|
||||
DrawText("Text 2d should be always on top of the cube", 10, 40, 20, Color.Gray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - world screen");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free");
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = new();
|
||||
camera.Position = new Vector3(10.0f, 10.0f, 10.0f);
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
camera.FovY = 45.0f;
|
||||
camera.Projection = CameraProjection.Perspective;
|
||||
|
||||
Vector3 cubePosition = new(0.0f, 0.0f, 0.0f);
|
||||
Vector2 cubeScreenPosition;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new WorldScreen();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, CameraMode.Free);
|
||||
|
||||
// Calculate cube screen space position (with a little offset to be in top)
|
||||
cubeScreenPosition = GetWorldToScreen(
|
||||
new Vector3(cubePosition.X, cubePosition.Y + 2.5f, cubePosition.Z),
|
||||
camera
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, Color.Red);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, Color.Maroon);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText(
|
||||
"Enemy: 100 / 100",
|
||||
(int)cubeScreenPosition.X - MeasureText("Enemy: 100 / 100", 20) / 2,
|
||||
(int)cubeScreenPosition.Y,
|
||||
20,
|
||||
Color.Black
|
||||
);
|
||||
DrawText(
|
||||
"Text is always on top of the cube",
|
||||
(screenWidth - MeasureText("Text is always on top of the cube", 20)) / 2,
|
||||
25,
|
||||
20,
|
||||
Color.Gray
|
||||
);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue