gh-scrum/src/graphics_m.pas

396 lines
10 KiB
ObjectPascal
Raw Normal View History

2026-02-28 10:57:08 +00:00
unit graphics_m;
interface
2026-02-28 11:14:58 +00:00
uses arena_graphics_m, arena_m, creature_m, hamster_m, trace_m, game_m;
2026-02-28 10:57:08 +00:00
procedure DrawAfterStep(var cr: creature; var a: arena);
2026-02-28 11:05:48 +00:00
procedure DrawAfterStep(var hamster: creature; var t: tracePtr; var a: arena);
2026-02-28 10:57:08 +00:00
procedure DrawCreature(var cr: creature);
2026-02-28 11:25:06 +00:00
procedure DrawExitState(s: exitState);
procedure DrawExit(var g: gameState);
2026-02-28 11:28:22 +00:00
procedure DrawPause(var g: gameState);
procedure DrawInfo;
2026-02-28 11:25:06 +00:00
procedure DrawLifes(var g: GameState);
procedure DrawMenuState(s: menuState);
procedure DrawMenu(var g: gameState);
procedure DrawScore(var g: GameState);
2026-02-28 11:28:22 +00:00
procedure EraseAll;
2026-02-28 11:25:06 +00:00
procedure EraseExit;
procedure EraseExitState(s: exitState);
procedure EraseMenu;
procedure EraseMenuState(s: menuState);
2026-02-28 11:14:58 +00:00
procedure EraseStepTrace(var hamster: creature; t: tracePtr);
procedure EraseTrace(t: tracePtr; var a: arena);
2026-02-28 10:57:08 +00:00
implementation
2026-02-28 11:25:06 +00:00
uses crt, math_m, ascii_arts_m;
2026-02-28 10:57:08 +00:00
const
2026-02-28 11:25:06 +00:00
BigLetterWidth = 8;
DigitWidth = 6;
GameNameX = ScreenW * WidthCoefficient div 3 + 4;
GameNameY = 12;
NameHeightPadding = 8;
MenuHeightPadding = 2;
MenuWidthPadding = 4;
MenuHamsterX = GameNameX - HamsterWidth - MenuWidthPadding;
NewGameY = GameNameY + GameNameHeight + NameHeightPadding;
HighScoreY = NewGameY + NewGameHeight + MenuHeightPadding;
KeyInfoY = HighScoreY + HighScoreHeight;
ContinueY = KeyInfoY + KeyInfoHeight;
2026-02-28 11:14:58 +00:00
InterfaceMarginX = InterfaceCellW div 4;
2026-02-28 11:25:06 +00:00
InterfaceMarginY = InterfaceBarH div 4 + BorderSize + 1;
LetterWidth = 5;
Notation = 10;
PunctuationWidth = 3;
SpaceWidth = 3;
ExitGameY = ScreenH div 2 - ExitHeight - MenuHeightPadding;
ExitYesX = MenuHamsterX;
ExitYesY = ExitGameY + ExitHeight + MenuHeightPadding;
ExitNoX = ScreenW * WidthCoefficient - ExitYesX - NoWidth;
ExitHamsterY = ExitYesY;
HamsterYesX = ExitYesX - HamsterWidth - MenuWidthPadding;
HamsterNoX = ExitNoX - HamsterWidth - MenuWidthPadding;
2026-02-28 11:28:22 +00:00
PauseXMargin = 3 * WidthCoefficient;
PauseYMargin = 1;
2026-02-28 11:25:06 +00:00
var
firstMenuDraw: boolean = true;
2026-02-28 10:57:08 +00:00
2026-02-28 11:14:58 +00:00
procedure EraseTrace(t: tracePtr; var a: arena);
2026-02-28 10:57:08 +00:00
begin
2026-02-28 11:14:58 +00:00
while t <> nil do
2026-02-28 10:57:08 +00:00
begin
2026-02-28 11:14:58 +00:00
if t^.prev = nil then
DrawEdge(t^.x, t^.y, a)
else
DrawArenaCell(t^.x, t^.y, ArenaSymbol);
t := t^.prev
end
2026-02-28 10:57:08 +00:00
end;
2026-02-28 11:14:58 +00:00
procedure EraseStepTrace(var hamster: creature; t: tracePtr);
2026-02-28 10:57:08 +00:00
var
i: integer;
begin
2026-02-28 11:14:58 +00:00
for i := 1 to hamster.movespeed do
2026-02-28 10:57:08 +00:00
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 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;
2026-02-28 11:14:58 +00:00
procedure DrawStepTrace(t: tracePtr; hamsterDelta: integer);
2026-02-28 10:57:08 +00:00
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
2026-02-28 11:14:58 +00:00
DrawStepTrace(t, hamster.movespeed);
2026-02-28 10:57:08 +00:00
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;
2026-02-28 11:05:48 +00:00
procedure FillRectangle(x, y, w, h: integer; ch: char);
var
i, j: integer;
begin
2026-02-28 11:25:06 +00:00
for i := 0 to h - 1 do
2026-02-28 11:05:48 +00:00
begin
GotoXY(x, y + i);
for j := 0 to w do
write(ch)
end;
GotoXY(1, 1)
end;
type
stackIntPtr = ^stackIntItem;
stackIntItem = record
val: integer;
next: stackIntPtr
end;
StackInt = record
top: stackIntPtr
end;
procedure StackIntInit(var s: StackInt);
begin
s.top := nil
end;
procedure StackPush(var st: StackInt; val: integer);
var
tmp: stackIntPtr;
begin
new(tmp);
tmp^.val := val;
tmp^.next := st.top;
st.top := tmp
end;
procedure StackPop(var st: StackInt);
var
tmp: stackIntPtr;
begin
tmp := st.top;
st.top := st.top^.next;
dispose(tmp)
end;
2026-02-28 11:25:06 +00:00
procedure DrawAscii(x, y, h: integer; var a: array of string);
var
i: integer;
begin
for i := 1 to h do
begin
GotoXY(x, y + i - 1);
write(a[i - 1])
end;
GotoXY(1, 1)
end;
procedure EraseRectangle(x, y, w, h: integer);
begin
FillRectangle(x, y, w, h, ' ')
end;
2026-02-28 11:05:48 +00:00
procedure DrawDigit(x, y, digit: integer);
begin
2026-02-28 11:25:06 +00:00
DrawAscii(x, y, DigitHeight, DigitsAscii[digit])
2026-02-28 11:05:48 +00:00
end;
2026-02-28 11:14:58 +00:00
procedure DrawNumber(interfaceX: integer; s: longint);
2026-02-28 11:05:48 +00:00
var
x, y: integer;
i: integer = 0;
st: StackInt;
begin
StackIntInit(st);
if s = 0 then
StackPush(st, 0);
while s <> 0 do
begin
2026-02-28 11:14:58 +00:00
StackPush(st, s mod Notation);
s := s div Notation
2026-02-28 11:05:48 +00:00
end;
2026-02-28 11:14:58 +00:00
x := interfaceX + InterfaceMarginX;
y := InterfaceMarginY;
2026-02-28 11:05:48 +00:00
while st.top <> nil do
begin
2026-02-28 11:25:06 +00:00
DrawDigit(x + (DigitWidth + SpaceWidth) * i, y, st.top^.val);
2026-02-28 11:05:48 +00:00
StackPop(st);
i := i + 1
end
end;
2026-02-28 11:25:06 +00:00
procedure DrawLifes(var g: GameState);
2026-02-28 11:14:58 +00:00
begin
2026-02-28 11:25:06 +00:00
DrawNumber(LifeBarX, g.life)
2026-02-28 11:14:58 +00:00
end;
2026-02-28 11:25:06 +00:00
procedure DrawScore(var g: GameState);
2026-02-28 11:14:58 +00:00
var
killBarX: integer = InterfaceCellW * 2 * WidthCoefficient + BorderSize;
begin
2026-02-28 11:25:06 +00:00
DrawNumber(killBarX, g.score)
end;
procedure DrawMenuState(s: menuState);
begin
case s of
menuNewGame:
DrawAscii(MenuHamsterX, NewGameY + 1,
HamsterHeight, HamsterStayAscii);
menuHighScore:
DrawAscii(MenuHamsterX, HighScoreY + 1,
HamsterHeight, HamsterStayAscii);
menuKeyInfo:
DrawAscii(MenuHamsterX, KeyInfoY + 1,
HamsterHeight, HamsterStayAscii);
menuContinue:
DrawAscii(MenuHamsterX, ContinueY + 1,
HamsterHeight, HamsterStayAscii)
end
end;
procedure DrawMenu(var g: gameState);
var
y: integer = GameNameY;
begin
if firstMenuDraw then
begin
DrawRectangle(1, 1, ScreenH, ScreenW * WidthCoefficient);
firstMenuDraw := not firstMenuDraw
end;
DrawAscii(GameNameX, y, GameNameHeight, GameNameAscii);
DrawAscii(GameNameX, NewGameY, NewGameHeight, NewGameAscii);
DrawAscii(GameNameX, HighScoreY, HighScoreHeight, HighScoreAscii);
DrawAscii(GameNameX, KeyInfoY, KeyInfoHeight, KeyInfoAscii);
DrawAscii(GameNameX, ContinueY, ContinueHeight, ContinueAscii);
2026-02-28 11:28:22 +00:00
if not g.continueAllowed then
FillRectangle(GameNameX, ContinueY + ContinueHeight div 2,
ContinueWidth, 1, '-');
2026-02-28 11:25:06 +00:00
DrawMenuState(g.curMenu)
end;
procedure EraseMenuState(s: menuState);
begin
case s of
menuNewGame:
EraseRectangle(MenuHamsterX, NewGameY + 1,
HamsterWidth, HamsterHeight);
menuHighScore:
EraseRectangle(MenuHamsterX, HighScoreY + 1,
HamsterWidth, HamsterHeight);
menuKeyInfo:
EraseRectangle(MenuHamsterX, KeyInfoY + 1,
HamsterWidth, HamsterHeight);
menuContinue:
EraseRectangle(MenuHamsterX, ContinueY + 1,
HamsterWidth, HamsterHeight)
end
end;
2026-02-28 11:28:22 +00:00
procedure EraseAll;
begin
EraseRectangle(1, 1, ScreenW * WidthCoefficient, ScreenH)
end;
2026-02-28 11:25:06 +00:00
procedure EraseMenu;
begin
EraseRectangle(MenuHamsterX, GameNameY,
GameNameWidth + HamsterWidth + MenuWidthPadding,
ScreenH - GameNameY * 2)
end;
procedure DrawExitState(s: exitState);
begin
case s of
exitYes:
DrawAscii(HamsterYesX, ExitHamsterY,
2026-02-28 11:28:22 +00:00
HamsterHeight, HamsterGGAscii);
2026-02-28 11:25:06 +00:00
exitNo:
DrawAscii(HamsterNoX, ExitHamsterY,
HamsterHeight, HamsterStayAscii)
end
end;
2026-02-28 11:28:22 +00:00
procedure DrawPause(var g: gameState);
var
pauseX: integer = (ScreenW * WidthCoefficient - PauseWidth) div 2;
pauseY: integer = (ScreenH - PauseHeight) div 2;
begin
EraseRectangle(pauseX - PauseXMargin,
pauseY - PauseYMargin,
PauseWidth + PauseXMargin * 2 - 1,
PauseHeight + PauseYMargin * 2 + 1);
DrawRectangle(pauseX - PauseXMargin,
pauseY - PauseYMargin,
PauseHeight + PauseYMargin * 2 + 1,
PauseWidth + PauseXMargin * 2);
DrawAscii(pauseX, pauseY, PauseHeight, PauseAscii)
end;
procedure ErasePause(var g: gameState);
begin
end;
2026-02-28 11:25:06 +00:00
procedure DrawExit(var g: gameState);
var
realX: integer = ScreenW * WidthCoefficient;
begin
DrawAscii((realX - ExitWidth) div 2, ExitGameY, ExitHeight, ExitAscii);
DrawAscii(ExitYesX, ExitYesY, YesHeight, YesAscii);
DrawAscii(ExitNoX, ExitYesY, NoHeight, NoAscii);
DrawExitState(g.curExit)
end;
2026-02-28 11:28:22 +00:00
procedure DrawInfo;
begin
end;
2026-02-28 11:25:06 +00:00
procedure EraseExitState(s: exitState);
begin
case s of
exitYes:
EraseRectangle(HamsterYesX, ExitHamsterY,
HamsterWidth, HamsterHeight);
exitNo:
EraseRectangle(HamsterNoX, ExitHamsterY,
HamsterWidth, HamsterHeight)
end
end;
procedure EraseExit;
begin
EraseRectangle(HamsterYesX, ExitGameY,
ExitWidth + HamsterWidth + MenuWidthPadding,
ExitHeight + MenuHeightPadding + YesHeight)
2026-02-28 11:14:58 +00:00
end;
2026-02-28 10:57:08 +00:00
end.