program project1;
{$mode objfpc}{$H+}
uses
{$IFDEF LINUX} cthreads,{$ENDIF}
Classes, SysUtils, CustApp, raylib, Map2;
type
{ TRayApplication }
TRayApplication = class(TCustomApplication)
protected
procedure DoRun; override;
public
boulderTx, bridgeTx, treeTx, grassTx, waterTx: TTexture;
boulder, hex, hewxWather, bridge, tree, pointer_: TModel;
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
end;
const AppTitle = 'raylib - basic window';
var
camera: TCamera;
pathStart: PMapNode = nil;
pathEnd: PMapNode = nil;
frame: Integer = 0;
_map: array[0..20, 0..15] of Integer = (
(2,2,2,0,2,2,2,2,0,2,2,0,0,2,2,2),
(2,2,0,0,0,2,2,0,0,0,2,0,0,0,0,2),
(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
(0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0),
(0,0,0,0,3,3,3,3,3,3,3,3,0,0,0,0),
(0,0,0,3,3,3,3,3,3,3,3,3,3,0,0,0),
(0,0,3,3,3,3,3,3,3,3,3,3,3,0,0,0),
(3,4,3,3,3,3,3,3,3,3,3,3,3,0,0,0),
(0,0,3,3,3,3,3,3,3,3,3,3,3,0,0,0),
(0,0,0,3,3,3,3,3,3,3,3,3,3,0,0,0),
(0,0,0,0,3,3,3,3,3,3,3,3,0,0,0,0),
(0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0),
(0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0),
(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),
(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
(2,0,0,0,0,2,2,0,0,0,0,0,0,0,0,2),
(2,2,0,0,2,2,2,2,2,2,0,2,0,0,2,2)
);
const
hsize = 1.004;
vsize = 1.008;
function MouseToHex(m: TVector2): TVector2;
var
X, Z: Single;
begin
X := (((1.73205080757 / 3 * m.x) / hsize)) + hsize / 2;
Z := ((2.0 / 3 * m.y) / vsize) + vsize / 2;
if (Trunc(Z) and 1) <> 0 then
X := X - 0.5;
Result.x := Trunc(X);
Result.y := Trunc(Z);
end;
{ TRayApplication }
constructor TRayApplication.Create(TheOwner: TComponent);
var x, y: Integer;
begin
inherited Create(TheOwner);
for y := 0 to MAPHEIGHT - 1 do
begin
for x := 0 to MAPWIDTH - 1 do
begin
mapNodes[x][y].nodeType := THexType(_map[x][y]);
mapNodes[x][y].coords.x := x;
mapNodes[x][y].coords.y := y;
end;
end;
buildMapLinks();
InitWindow(800, 600, AppTitle); // for window settings, look at example - window flags
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
// Инициализация камеры
camera := Default(TCamera); // Обнуляем структуру камеры
camera.position := Vector3Create(16.0, 16.0, -16.0);
camera.target := Vector3Create(16.0, 0.0, 16.0);
camera.up := Vector3Create(0.0, 1.0, 0.0);
camera.fovy := 45.0;
camera.projection := CAMERA_PERSPECTIVE;
boulder := LoadModel('data/mine.gltf.glb');
// the hex model is retextured and repurposed for those terrains
// that are simply hex shaped grass, water and similar flat ones
hex := LoadModel('data/hex.gltf.glb');
hewxWather := LoadModel('data/hex_water.gltf.glb');
bridge := LoadModel('data/hex_bridge.gltf.glb');
tree := LoadModel('data/hex_forest.gltf.glb');
pointer_ := LoadModel('data/pointer.obj');
HideCursor();
end;
procedure TRayApplication.DoRun;
var
r: TRay;
rhi: TRayCollision;
curs: TVector2;
mn: PMapNode;
m: PModel;
x, y , tp: integer;
offset: Single;
tint: TColorB;
begin
while (not WindowShouldClose) do // Detect window close button or ESC key
begin
// Update your variables here
inc(frame);
UpdateCamera(@camera, CAMERA_FREE);
r := GetMouseRay(GetMousePosition(), camera);
rhi := GetRayCollisionQuad(r,
Vector3Create(-1000, 0, -1000),
Vector3Create(1000, 0, -1000),
Vector3Create(1000, 0, 1000),
Vector3Create(-1000, 0, 1000));
// Преобразуем координаты плоскости в координаты гексагональной карты
curs := MouseToHex(Vector2Create(rhi.point.x, rhi.point.z));
if InMap(curs) then
begin
if IsKeyPressed(KEY_S) then
begin
pathStart := @mapNodes[Trunc(curs.x)][Trunc(curs.y)];
if Assigned(pathEnd) then
FindPath(pathStart, pathEnd);
end;
if IsKeyPressed(KEY_E) then
begin
pathEnd := @mapNodes[Trunc(curs.x)][Trunc(curs.y)];
if Assigned(pathStart) then
FindPath(pathStart, pathEnd);
end;
if IsKeyPressed(KEY_T) then
begin
mn := @mapNodes[Trunc(curs.x)][Trunc(curs.y)];
mn^.nodeType := THexType(Ord(mn^.nodeType) + 1);
if mn^.nodeType > HxBridge then
// Превысили максимальный тип местности - сбрасываем
mn^.nodeType := HxGrass;
// Необходимо перестроить связи для измененного гекса и его соседей
BuildMapLinks();
if Assigned(pathStart) and Assigned(pathEnd) then
FindPath(pathStart, pathEnd);
end;
end;
// Draw
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(camera);
for y := 0 to MAPHEIGHT - 1 do
begin
for x := 0 to MAPWIDTH - 1 do
begin
offset := 0;
// Нечетные строки смещены...
if Odd(y) then offset := Map2.OFFSET;
//0 if y/2 <> y/2.0 then offset := Map.OFFSET;
m := nil;
tp := Ord(mapNodes[x][y].nodeType);
// Выбираем подходящую модель для типа местности
case THexType(tp) of
HxGrass:
begin
m := @hex;
//m^.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture := grassTx;
end;
HxBoulder: m := @boulder;
HxTree: m := @tree;
HxWater:
begin
m := @hewxWather;
//m^.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture := waterTx;
end;
HxBridge: m := @bridge;
end;
if Assigned(m) then
begin
// Изменяем цвет в зависимости от пути и выделенных гексов
tint := WHITE;
if (x = Trunc(curs.x)) and (y = Trunc(curs.y)) then
tint := RED;
if mapNodes[x][y].onPath then
tint := ORANGE;
if pathStart = @mapNodes[x][y] then
tint := MAGENTA;
if pathEnd = @mapNodes[x][y] then
tint := GREEN;
DrawModel(m^, Vector3Create(x*HWIDTH + offset, -1, y*HHEIGHT), 1, tint);
// DrawModelEx(m^, Vector3Create(x * HWIDTH + offset, 0, y*HHEIGHT),
// Vector3Create(0,1,0), 180, Vector3Create(1,1,1), tint);
end;
end;
end;
DrawModel(pointer_, rhi.point, 1, WHITE);
EndMode3D();
EndDrawing();
end;
// Stop program loop
Terminate;
end;
destructor TRayApplication.Destroy;
begin
// De-Initialization
CloseWindow(); // Close window and OpenGL context
// Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
TraceLog(LOG_INFO, 'your first window is close and destroy');
inherited Destroy;
end;
var
Application: TRayApplication;
begin
Application:=TRayApplication.Create(nil);
Application.Title:=AppTitle;
Application.Run;
Application.Free;
end.