Basic principles of the Shuman map format

This commit is contained in:
Safariminer 2025-06-03 23:08:12 -04:00
parent 3686bb3447
commit 651fbd18dc
11 changed files with 224 additions and 15 deletions

View File

@ -0,0 +1,13 @@
#include "Morault_Map.h"
Morault::Maps::Map::Map()
{
}
Morault::Maps::Map::Map(std::string path)
{
}
Morault::Maps::Map::~Map()
{
}

View File

@ -1,9 +1,30 @@
#pragma once #pragma once
#include <iostream>
#include <raylib.h>
#include <vector>
namespace Morault { namespace Morault {
namespace Maps { namespace Maps {
class Map { struct MapTriangle {
Vector2 a, b, c;
std::string wallAB = "pms:none", wallBC = "pms:none", wallCA = "pms:none"; // if empty, no wall
bool hasCeiling; std::string ceilingTexture = "pms:SKY"; // sky is special texture
bool hasFloor; std::string floorTexture = "pms:SKY"; // sky is special texture
int heightFloor, heightCeiling;
};
class Map { // Map element for Shuman 1
public:
std::vector<MapTriangle> MapTriangles;
Map();
Map(std::string path);
~Map();
}; };
} }
} }

View File

@ -5,6 +5,8 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
std::map<std::string, ::Model> __models_map; std::map<std::string, ::Model> __models_map;
std::map<std::string, ::Texture2D> __textures_map;
Morault::Resources::_ResourceRequest Morault::Resources::load(std::string modelName) Morault::Resources::_ResourceRequest Morault::Resources::load(std::string modelName)
{ {
_ResourceRequest retval; _ResourceRequest retval;
@ -59,6 +61,28 @@ std::variant<Model, bool> Morault::Resources::Models(_ResourceRequest request)
} }
} }
std::variant<Texture2D, bool> Morault::Resources::Textures(_ResourceRequest request)
{
switch (request.type) {
case LOAD:
__textures_map[request.req] = LoadTexture(request.req.c_str());
return true;
break;
case GET:
return __textures_map[request.req];
break;
case UNLOAD:
UnloadTexture(__textures_map[request.req]);
return true;
break;
case RELOAD:
UnloadTexture(__textures_map[request.req]);
__textures_map[request.req] = LoadTexture(request.req.c_str());
return true;
break;
}
}
Image Morault::Resources::GenTestImage() Image Morault::Resources::GenTestImage()
{ {
Image retval = GenImageColor(256, 256, BLANK); Image retval = GenImageColor(256, 256, BLANK);

View File

@ -21,13 +21,14 @@ namespace Morault {
std::string req; std::string req;
}; };
_ResourceRequest load(std::string modelName); _ResourceRequest load(std::string resourceName);
_ResourceRequest get(std::string modelName); _ResourceRequest get(std::string resourceName);
_ResourceRequest unload(std::string modelName); _ResourceRequest unload(std::string resourceName);
_ResourceRequest reload(std::string modelName); _ResourceRequest reload(std::string resourceName);
std::variant<Model, bool> Models(_ResourceRequest request); std::variant<Model, bool> Models(_ResourceRequest request);
std::variant<Texture2D, bool> Textures(_ResourceRequest request);
typedef enum { typedef enum {

View File

@ -136,6 +136,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Morault_Map.cpp" />
<ClCompile Include="Morault_Player.cpp" /> <ClCompile Include="Morault_Player.cpp" />
<ClCompile Include="Morault_Resources.cpp" /> <ClCompile Include="Morault_Resources.cpp" />
<ClCompile Include="Morault_UDMF.cpp" /> <ClCompile Include="Morault_UDMF.cpp" />

View File

@ -30,6 +30,9 @@
<ClCompile Include="Morault_UDMF.cpp"> <ClCompile Include="Morault_UDMF.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Morault_Map.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Morault_Resources.h"> <ClInclude Include="Morault_Resources.h">

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -2,11 +2,26 @@
#include <raylib.h> #include <raylib.h>
#include "Morault_Resources.h" #include "Morault_Resources.h"
#include "Morault_Player.h" #include "Morault_Player.h"
#include "Morault_UDMF.h" #include "Morault_Map.h"
#include <raymath.h> #include <raymath.h>
#include <rlgl.h> #include <rlgl.h>
#define MORAULT_MAP_RENDER_SCALE 0.1f #define MORAULT_MAP_RENDER_SCALE 0.1f
typedef enum {
NONE,
GAME,
EDITOR
} EngineState;
typedef enum {
NA, A, B, C
} SectorTriangleSelection;
struct EditorSelection {
int sector;
SectorTriangleSelection point;
};
int main(int argc, char** argv) { int main(int argc, char** argv) {
InitWindow(1280, 720, "ProjectMorault"); InitWindow(1280, 720, "ProjectMorault");
SetTargetFPS(60); SetTargetFPS(60);
@ -15,24 +30,151 @@ int main(int argc, char** argv) {
DisableCursor(); DisableCursor();
Morault::Gameplay::Player player; Morault::Gameplay::Player player;
player.data.playerName = "TestPlayer0001"; player.data.playerName = "TestPlayer0001";
player.data.hp = 100; player.data.hp = 100;
player.data.xp = 0; player.data.xp = 0;
bool gamePaused = false; bool gamePaused = false;
EngineState eState = GAME;
EditorSelection selection = { -1, NA };
bool inSelection = false;
Morault::Maps::Map* map = new Morault::Maps::Map();
{
using namespace Morault::Resources;
Textures(load("data/textures/test.png"));
}
Vector2 editorOffset = { 0,0 };
while (!WindowShouldClose()) { while (!WindowShouldClose()) {
player.controller.UpdatePlayerController(!gamePaused);
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(player.controller.camera);
DrawGrid(100, 10);
EndMode3D();
DrawFPS(0, 0); switch(eState){
EndDrawing(); case GAME: {
if (IsKeyPressed(KEY_E)) {
eState = EDITOR;
EnableCursor();
}
player.controller.UpdatePlayerController(!gamePaused);
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(player.controller.camera);
DrawGrid(100, 10);
for (int i = 0; i < map->MapTriangles.size(); i++) {
DrawTriangle3D(
{
map->MapTriangles[i].a.x * MORAULT_MAP_RENDER_SCALE,
map->MapTriangles[i].heightFloor * MORAULT_MAP_RENDER_SCALE,
map->MapTriangles[i].a.y * MORAULT_MAP_RENDER_SCALE
},
{
map->MapTriangles[i].b.x * MORAULT_MAP_RENDER_SCALE,
map->MapTriangles[i].heightFloor * MORAULT_MAP_RENDER_SCALE,
map->MapTriangles[i].b.y * MORAULT_MAP_RENDER_SCALE
},
{
map->MapTriangles[i].c.x * MORAULT_MAP_RENDER_SCALE,
map->MapTriangles[i].heightFloor * MORAULT_MAP_RENDER_SCALE,
map->MapTriangles[i].c.y * MORAULT_MAP_RENDER_SCALE
},
RED
);
}
EndMode3D();
DrawFPS(0, 0);
EndDrawing();
} break;
case EDITOR: {
if (IsKeyPressed(KEY_E)) {
eState = GAME;
DisableCursor();
}
if (IsKeyPressed(KEY_ESCAPE)) {
inSelection = false;
}
if (IsKeyDown(KEY_LEFT_SHIFT)) {
if (IsKeyPressed(KEY_N)) {
Morault::Maps::MapTriangle tri;
tri.a = { -128, -128 };
tri.b = { 128,128 };
tri.c = { 128,-128 };
tri.floorTexture = "data/textures/test.png";
tri.heightFloor = 0;
tri.heightCeiling = 128;
tri.hasFloor = true;
tri.hasCeiling = false;
tri.wallAB = "data/textures/test.png";
tri.wallBC = "data/textures/test.png";
tri.wallCA = "data/textures/test.png";
map->MapTriangles.push_back(tri);
}
}
if (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)) editorOffset += GetMouseDelta();
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
for (int i = 0; i < map->MapTriangles.size(); i++) {
if (CheckCollisionPointCircle(GetMousePosition() - editorOffset, map->MapTriangles[i].a, 7)) {
inSelection = true;
selection = { i,A };
}
if (CheckCollisionPointCircle(GetMousePosition() - editorOffset, map->MapTriangles[i].b, 7)) {
inSelection = true;
selection = { i,B };
}
if (CheckCollisionPointCircle(GetMousePosition() - editorOffset, map->MapTriangles[i].c, 7)) {
inSelection = true;
selection = { i,C };
}
}
}
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) {
if (inSelection) {
switch (selection.point) {
case A:
map->MapTriangles[selection.sector].a += GetMouseDelta();
break;
case B:
map->MapTriangles[selection.sector].b += GetMouseDelta();
break;
case C:
map->MapTriangles[selection.sector].c += GetMouseDelta();
break;
}
}
}
BeginDrawing();
ClearBackground(BLACK);
for (int i = 0; i < map->MapTriangles.size(); i++) {
DrawTriangleLines(map->MapTriangles[i].a + editorOffset, map->MapTriangles[i].b + editorOffset, map->MapTriangles[i].c + editorOffset, YELLOW);
DrawCircle((map->MapTriangles[i].a + editorOffset).x, (map->MapTriangles[i].a + editorOffset).y, 3, RED);
DrawCircle((map->MapTriangles[i].b + editorOffset).x, (map->MapTriangles[i].b + editorOffset).y, 3, RED);
DrawCircle((map->MapTriangles[i].c + editorOffset).x, (map->MapTriangles[i].c + editorOffset).y, 3, RED);
if(inSelection){
if (selection.sector == i && selection.point == A) DrawCircle((map->MapTriangles[i].a + editorOffset).x, (map->MapTriangles[i].a + editorOffset).y, 5, GREEN);
if (selection.sector == i && selection.point == B) DrawCircle((map->MapTriangles[i].b + editorOffset).x, (map->MapTriangles[i].b + editorOffset).y, 5, GREEN);
if (selection.sector == i && selection.point == C) DrawCircle((map->MapTriangles[i].c + editorOffset).x, (map->MapTriangles[i].c + editorOffset).y, 5, GREEN);
}
}
EndDrawing();
}break;
default:
throw std::runtime_error("what the fuck?");
}
} }

View File

@ -3,6 +3,9 @@
Project Morault is a source-available attempt at a humanist and persistent live-service game. Project Morault is a source-available attempt at a humanist and persistent live-service game.
## Naming
Project Morault is named after Arthur Morault, french mechanic specialized in vintage, sportive and luxury automobiles. He owns a garage, [La Fabrique Auto](https://www.lafabriqueauto.com), with his friend and colleague Joseph Shuman, after whom Project Morault's Shuman map format is named. This naming is a follow-up to the Jossec engine, named after Yann Le Jossec, french drift instructor, powered with the [Levy](https://tilde.town/~safariminer/levy) collision engine, named after Sylvain Levy, french automotive YouTuber.
## Goals ## Goals
### Ideological ### Ideological
- Establish open standards for items, trading, markets, and user interaction - Establish open standards for items, trading, markets, and user interaction

1
shuman.md Normal file
View File

@ -0,0 +1 @@
# Shuman Map Format