gh-scrum/src/graphics_m.pas

278 lines
6.7 KiB
ObjectPascal
Raw Normal View History

2026-02-28 10:57:08 +00:00
unit graphics_m;
interface
uses arena_m, creature_m, hamster_m, trace_m;
procedure DrawAfterStep(var hamster: creature; var t: tracePtr; var a: arena);
procedure DrawAfterStep(var cr: creature; var a: arena);
procedure DrawArenaBorders(var a: arena);
procedure DrawArenaCell(arenaX, arenaY: integer; symbol: char);
procedure DrawArenaEdges;
procedure DrawCreature(var cr: creature);
procedure DrawLevel;
procedure EraseTrace(var hamster: creature; t: tracePtr);
function IsTerminalValid: boolean;
procedure PrintTerminalHelp;
implementation
uses crt, math_m;
const
InterfaceH = 6;
CellSize = 2;
BorderSize = 1;
ScreenW = (ArenaW - 1) * CellSize + BorderSize * 2; { 79 }
ScreenH = (ArenaH + InterfaceH) * CellSize + BorderSize;
WidthCoefficient = 2;
InterfaceBarH = ScreenW - ArenaH * CellSize - BorderSize * 2; { 14 }
function IsTerminalValid: boolean;
begin
IsTerminalValid := (ScreenWidth >= ScreenW) and (ScreenHeight >= ScreenH)
end;
procedure PrintTerminalHelp;
begin
writeln('Increase your terminal size and try again.');
if ScreenWidth < ScreenW then
begin
writeln('Your terminal width: ', ScreenWidth,
'. Required: ', ScreenW, '.')
end;
if ScreenHeight < ScreenH then
begin
writeln('Your terminal height: ', ScreenHeight,
'. Required: ', ScreenH, '.')
end
end;
procedure DrawLineX(x, y, len: integer);
var
i: integer;
begin
GotoXY(x, y);
for i := 1 to len do
write(BorderSymbol);
GotoXY(1, 1)
end;
procedure DrawLineY(x, y, len: integer);
var
i: integer;
begin
for i := 1 to len do
begin
GotoXY(x, y + i - 1);
write(BorderSymbol)
end;
GotoXY(1, 1)
end;
procedure DrawRectangle(x0, y0, h, w: integer);
var
i: integer;
begin
DrawLineX(x0, y0, w);
for i := 1 to h - 2 do
begin
GotoXY(x0, y0 + i);
write(BorderSymbol);
GotoXY(x0 + w - 1, y0 + i);
write(BorderSymbol)
end;
DrawLineX(x0, y0 + h - 1, w);
GotoXY(1, 1)
end;
procedure DrawInterface;
var
cellW: integer = ScreenW div 3;
begin
DrawLineX(1, InterfaceBarH, ScreenW * WidthCoefficient);
DrawLineY(cellW * WidthCoefficient, 1, InterfaceBarH);
DrawLineY(cellW * 2 * WidthCoefficient + 1, 1, InterfaceBarH)
end;
procedure DrawLevel;
begin
DrawRectangle(1, 1, ScreenH, ScreenW * WidthCoefficient);
DrawInterface
end;
procedure DrawArenaCell(arenaX, arenaY: integer; symbol: char);
var
i, screenX, screenY: integer;
begin
screenX := BorderSize + (arenaX - 1) * CellSize * WidthCoefficient;
screenY := InterfaceBarH + (arenaY - 1) * CellSize;
GotoXY(screenX, screenY);
for i := 1 to CellSize * WidthCoefficient do
write(symbol);
GotoXY(screenX, screenY + 1); { later change to nested for }
for i := 1 to CellSize * WidthCoefficient do
write(symbol);
GotoXY(1, 1)
end;
procedure DrawArenaEdges;
begin
DrawRectangle(1, InterfaceBarH,
ScreenH - InterfaceBarH + 1, ScreenW * WidthCoefficient)
end;
procedure DrawLeftEdge(y: integer);
var
terminalY: integer;
begin
y := Clamp(y, 1, ArenaH);
terminalY := InterfaceBarH + (y - 1) * CellSize;
DrawLineY(1, terminalY, CellSize)
end;
procedure DrawRightEdge(y: integer);
var
terminalY: integer;
begin
y := Clamp(y, 1, ArenaH);
terminalY := InterfaceBarH + (y - 1) * CellSize;
DrawLineY(ScreenW * WidthCoefficient, terminalY, CellSize)
end;
procedure DrawUpperEdge(x: integer);
var
terminalX, sizeX: integer;
begin
x := Clamp(x, 1, ArenaW);
terminalX := (x - 1) * CellSize * WidthCoefficient + 1;
sizeX := CellSize * WidthCoefficient;
DrawLineX(terminalX, InterfaceBarH, sizeX)
end;
procedure DrawLowerEdge(x: integer);
var
terminalX, sizeX: integer;
begin
x := Clamp(x, 1, ArenaW);
terminalX := (x - 1) * CellSize * WidthCoefficient + 1;
sizeX := CellSize * WidthCoefficient;
DrawLineX(terminalX, InterfaceBarH + ArenaH * CellSize - 1, sizeX)
end;
procedure DrawArenaBorders(var a: arena);
var
i, j: integer;
begin
for i := 1 to ArenaH do
for j := 1 to ArenaW do
if a.borders[j][i] then
DrawArenaCell(j, i, BorderSymbol)
end;
procedure EraseTrace(var hamster: creature; t: tracePtr);
var
i: integer;
begin
for i := 1 to HamsterDelta do
begin
DrawArenaCell(t^.x, t^.y, ArenaSymbol);
t := t^.prev
end;
if GetLength(t) = 1 then
begin
if IsOnEdge(hamster) then
DrawArenaCell(t^.x, t^.y, ArenaSymbol)
else
DrawArenaCell(t^.x, t^.y, BorderSymbol)
end
end;
procedure EraseCell(x, y: integer);
begin
DrawArenaCell(x, y, ArenaSymbol)
end;
procedure DrawEdge(x, y: integer; var a: arena);
begin
if a.captured[x][y] then
DrawArenaCell(x, y, CaptureSymbol)
else
DrawArenaCell(x, y, ArenaSymbol);
if x = 1 then
DrawLeftEdge(y);
if x = ArenaW then
DrawRightEdge(y);
if y = 1 then
DrawUpperEdge(x);
if y = ArenaH then
DrawLowerEdge(x)
end;
procedure DrawCreature(var cr: creature);
begin
DrawArenaCell(cr.curX, cr.curY, cr.symbol)
end;
procedure
DrawPreviousCell(var hamster: creature; var t: tracePtr; var a: arena);
var
prevX, prevY: integer;
begin
prevX := hamster.curX - hamster.dX;
prevY := hamster.curY - hamster.dY;
if t = nil then
DrawEdge(prevX, prevY, a);
if (a.borders[prevX][prevY]) and (t = nil) then
DrawArenaCell(prevX, prevY, BorderSymbol)
end;
procedure DrawStepTrace(t: tracePtr);
var
i: integer;
begin
for i := 1 to HamsterDelta do
begin
t := t^.prev;
DrawArenaCell(t^.x, t^.y, TraceSymbol)
end
end;
procedure DrawAfterStep(var hamster: creature; var t: tracePtr; var a: arena);
var
prevX, prevY: integer;
begin
prevX := hamster.curX - hamster.dX;
prevY := hamster.curY - hamster.dY;
if IsOnEdge(prevX, prevY) and a.captured[prevX][prevY] then
DrawArenaCell(prevX, prevY, CaptureSymbol)
else
if IsOnBorder(prevX, prevY, a) then
DrawArenaCell(prevX, prevY, BorderSymbol)
else
DrawArenaCell(prevX, prevY, ArenaSymbol);
if t <> nil then
DrawStepTrace(t);
DrawCreature(hamster);
DrawPreviousCell(hamster, t, a)
end;
procedure DrawAfterStep(var cr: creature; var a: arena);
var
prevX, prevY: integer;
begin
prevX := cr.curX - cr.dX;
prevY := cr.curY - cr.dY;
if IsOnEdge(prevX, prevY) and a.captured[prevX][prevY] then
DrawArenaCell(prevX, prevY, CaptureSymbol)
else
if IsOnBorder(prevX, prevY, a) then
DrawArenaCell(prevX, prevY, BorderSymbol)
else
DrawArenaCell(prevX, prevY, ArenaSymbol);
DrawCreature(cr)
end;
end.