Skip to content

Commit

Permalink
Merge pull request #31 from grzegorz-kraszewski/game-ending
Browse files Browse the repository at this point in the history
Game ending
  • Loading branch information
grzegorz-kraszewski authored Oct 19, 2024
2 parents 5118360 + 5b20a40 commit 67deb0f
Show file tree
Hide file tree
Showing 12 changed files with 328 additions and 35 deletions.
Binary file modified StandardSet.iff
100644 → 100755
Binary file not shown.
8 changes: 4 additions & 4 deletions Untangle.guide
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
@DATABASE Untangle.guide
@$VER: Untangle.guide 1.0 (03.09.2024)
@$VER: Untangle.guide 1.1 (19.10.2024)
@AUTHOR: RastPort
@WIDTH 80
@SMARTWRAP
@NODE Main "Untangle"


@{JCENTER}@{B}Untangle 1.0@{UB}
@{JCENTER}@{B}Untangle 1.1@{UB}

@{JLEFT}

Expand Down Expand Up @@ -78,8 +78,8 @@ Level is solved, when there are no intersections. Then the game blinks the
screen, pauses for a second, and loads the next level.


After the last level of a set is completed, a requester with text "no more
levels in set" is displayed.
After the last level of a set is completed, the game ending is displayed with
some statistics.


A level is accessible after all the previous levels of set have been solved.
Expand Down
269 changes: 269 additions & 0 deletions src/endgame.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
//-------------
// game ending
//-------------

#include "main.h"
#include "strutils.h"
#include "selector.h"

#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/dos.h>
#include <proto/layers.h>
#include <proto/timer.h>
#include <proto/intuition.h>
#include <graphics/rpattr.h>

#define SEGMENT_UP 0
#define SEGMENT_LEFT 1
#define SEGMENT_DOWN 2
#define SEGMENT_RIGHT 3

struct EndGameText
{
char *text;
LONG len;
};

unsigned long long FractTime, FractDelta = 1;

//---------------------------------------------------------------------------------------------

static inline short addrot(short rot1, short rot2)
{
return (rot1 + rot2) & 0x3;
}

//---------------------------------------------------------------------------------------------

static void deltaDraw(struct RastPort *rp, Point *p, short dx, short dy)
{
WORD ddx = dx >> 1;
WORD ddy = dy >> 1;

p->x += ddx;
p->y += ddy;
WritePixel(rp, p->x, p->y);
p->x += ddx;
p->y += ddy;
WritePixel(rp, p->x, p->y);
}

//---------------------------------------------------------------------------------------------

void TimerDelay()
{
unsigned long long t;

do
{
ReadEClock((struct EClockVal*)&t);
}
while (t < FractTime);

FractTime += FractDelta;
}

//---------------------------------------------------------------------------------------------

void Segment(struct RastPort *rp, short direction, short size, Point *p)
{
if (size == 0)
{
switch (direction)
{
case SEGMENT_UP: deltaDraw(rp, p, 0, -2); break;
case SEGMENT_LEFT: deltaDraw(rp, p, -2, 0); break;
case SEGMENT_DOWN: deltaDraw(rp, p, 0, 2); break;
case SEGMENT_RIGHT: deltaDraw(rp, p, 2, 0); break;
}

TimerDelay();
}
else
{
size--;
Segment(rp, addrot(direction, SEGMENT_RIGHT), size, p);
Segment(rp, addrot(direction, SEGMENT_UP), size, p);
Segment(rp, addrot(direction, SEGMENT_LEFT), size, p);
Segment(rp, addrot(direction, SEGMENT_UP), size, p);
}
}

//---------------------------------------------------------------------------------------------

void SetWindowCenter(struct Window *win, Point *p)
{
p->x = win->BorderLeft + ((win->Width - win->BorderLeft - win->BorderRight) >> 1);
p->y = win->BorderTop + ((win->Height - win->BorderTop - win->BorderBottom) >> 1);
}

//---------------------------------------------------------------------------------------------

void Fractal(struct App *app)
{
Point p;
struct RastPort *rp = app->Win->RPort;
short startsize = 6;

SetWindowCenter(app->Win, &p);
p.x += 65;
p.y += 65;

SetRPAttrs(rp,
RPTAG_APen, 3,
RPTAG_DrMd, JAM1,
TAG_END);

Move(rp, p.x, p.y);
Segment(rp, SEGMENT_UP, startsize, &p);
Segment(rp, SEGMENT_LEFT, startsize, &p);
Segment(rp, SEGMENT_DOWN, startsize, &p);
Segment(rp, SEGMENT_RIGHT, startsize, &p);
}

//---------------------------------------------------------------------------------------------

void TimedFractal(struct App *app)
{
ULONG efreq;

efreq = ReadEClock((struct EClockVal*)&FractTime);
FractDelta = efreq >> 10;
Fractal(app);
}

//---------------------------------------------------------------------------------------------

void ClipFractal(struct App *app)
{
struct Window *win = app->Win;
struct Region *rg, *org;
struct Rectangle in;

in.MinX = win->BorderLeft;
in.MinY = win->BorderTop;
in.MaxX = win->Width - win->BorderRight - 1;
in.MaxY = win->Height - win->BorderBottom -1;

if (rg = NewRegion())
{
if (OrRectRegion(rg, &in))
{
org = InstallClipRegion(win->WLayer, rg);

if (org != rg)
{
TimedFractal(app);
InstallClipRegion(win->WLayer, org);
}
}

DisposeRegion(rg);
}
}

//---------------------------------------------------------------------------------------------

BOOL PrepareTexts(struct App *app, struct EndGameText *texts)
{
LONG moves = 0, seconds = 0;
WORD hours, minutes;

struct HighScore *hs;

for (hs = (struct HighScore*)app->Selector.HighScores.mlh_Head; hs->Node.mln_Succ;
hs = (struct HighScore*)hs->Node.mln_Succ)
{
if (hs->Seconds != THE_WORST_TIME_POSSIBLE) // skip the last, unfinished level
{
seconds += hs->Seconds;
moves += hs->Moves;
}
}

hours = div16(seconds, 3600);
seconds -= mul16(hours, 3600);
minutes = div16(seconds, 60);
seconds -= mul16(minutes, 60);

texts[0].text = "Congratulations!";
texts[1].text = FmtNew("You have completed all the %ld levels.", app->LevelNumber - 1);
texts[2].text = FmtNew("Your total number of moves: %ld.", moves);
texts[3].text = FmtNew("Your total time: %ld:%02ld:%02ld.", hours, minutes, seconds);

if (texts[1].text && texts[2].text && texts[3].text)
{
WORD i;

for (i = 0; i < 4; i++) texts[i].len = StrLen(texts[i].text);
return TRUE;
}

return FALSE;
}

//---------------------------------------------------------------------------------------------

void PrintTextsCentered(struct App *app, struct EndGameText *texts)
{
Point center;
WORD x, y, i;
struct RastPort *rp = app->Win->RPort;
struct TextFont *tf;

SetWindowCenter(app->Win, &center);
GetRPAttrs(rp, RPTAG_Font, &tf, TAG_END);
y = center.y - tf->tf_YSize - tf->tf_YSize + tf->tf_Baseline;

SetRPAttrs(rp, RPTAG_DrMd, JAM1, TAG_END);

for (i = 0; i < 4; i++)
{
WORD tw;

tw = TextLength(rp, texts[i].text, texts[i].len);
x = center.x - (tw >> 1);
SetRPAttrs(rp, RPTAG_APen, 1, TAG_END);
Move(rp, x + 1, y + 1);
Text(rp, texts[i].text, texts[i].len);
SetRPAttrs(rp, RPTAG_APen, 2, TAG_END);
Move(rp, x, y);
Text(rp, texts[i].text, texts[i].len);
y += tf->tf_YSize;
}
}

//---------------------------------------------------------------------------------------------

void FreeTexts(struct EndGameText *texts)
{
if (texts[1].text) StrFree(texts[1].text);
if (texts[2].text) StrFree(texts[2].text);
if (texts[3].text) StrFree(texts[3].text);
}

//---------------------------------------------------------------------------------------------

void EndGame(struct App *app)
{
struct EndGameText texts[4];
struct Requester req;

InitRequester(&req);

if (Request(&req, app->Win))
{
SetWindowPointer(app->Win, WA_BusyPointer, TRUE, TAG_END);

if (PrepareTexts(app, texts))
{
ClipFractal(app);
PrintTextsCentered(app, texts);
}

FreeTexts(texts);
EndRequest(&req, app->Win);
SetWindowPointer(app->Win, WA_Pointer, NULL, TAG_END);
}
}
7 changes: 7 additions & 0 deletions src/endgame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//-------------
// game ending
//-------------

#include "main.h"

void EndGame(struct App *app);
43 changes: 27 additions & 16 deletions src/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "lscm.h"
#include "strutils.h"
#include "version.h"
#include "endgame.h"

#include <proto/exec.h>
#include <proto/graphics.h>
Expand Down Expand Up @@ -424,7 +425,11 @@ static void PrintLevelInfo(struct App *app)
{
struct RastPort *rp = app->Win->RPort;

if (app->CurrentInfoText) StrFree(app->CurrentInfoText);
if (app->CurrentInfoText)
{
StrFree(app->CurrentInfoText);
app->CurrentInfoText = NULL;
}

if (app->Level)
{
Expand All @@ -449,26 +454,31 @@ void StopTimer(struct App *app)
AbortIO(&app->TimerReq->tr_node);
WaitIO(&app->TimerReq->tr_node);
}

app->TimerStopped = TRUE;
}

/*---------------------------------------------------------------------------*/

void PushNextSecond(struct App *app, BOOL redraw)
{
if (redraw) PrintLevelTime(app);
app->LevelTime.Sec++;

if (app->LevelTime.Sec == 60)
if (!app->TimerStopped)
{
app->LevelTime.Sec = 0;
app->LevelTime.Min++;
}
if (redraw) PrintLevelTime(app);
app->LevelTime.Sec++;

app->NextSecond.tv_secs++;
app->TimerReq->tr_node.io_Command = TR_ADDREQUEST;
app->TimerReq->tr_time = app->NextSecond;
app->TimerUsed = TRUE;
SendIO(&app->TimerReq->tr_node);
if (app->LevelTime.Sec == 60)
{
app->LevelTime.Sec = 0;
app->LevelTime.Min++;
}

app->NextSecond.tv_secs++;
app->TimerReq->tr_node.io_Command = TR_ADDREQUEST;
app->TimerReq->tr_time = app->NextSecond;
app->TimerUsed = TRUE;
SendIO(&app->TimerReq->tr_node);
}
}

/*---------------------------------------------------------------------------*/
Expand All @@ -479,6 +489,7 @@ static void StartTimer(struct App *app)
app->LevelTime.Min = 0;
GetSysTime(&app->LevelStart);
app->NextSecond = app->LevelStart;
app->TimerStopped = FALSE;
PushNextSecond(app, TRUE);
}

Expand All @@ -487,19 +498,19 @@ static void StartTimer(struct App *app)
void NewGame(struct App *app)
{
BPTR olddir = NULL;
BOOL endgame = FALSE;

app->LevelTime.Min = 0;
app->LevelTime.Sec = 0;
if (app->LevelSetFile.wa_Lock) olddir = CurrentDir(app->LevelSetFile.wa_Lock);

if (app->Level = LoadLevel(app->Win, app->LevelNumber, app->LevelSetFile.wa_Name))
if (app->Level = LoadLevel(app->Win, app->LevelNumber, app->LevelSetFile.wa_Name, &endgame))
{
PrecalculateLevel(app->Level);
ScaleGame(app);
UpdateInfosAfterLevelLoad(app);
DrawGame(app);
StartTimer(app);
}
else if (endgame) EndGame(app);

if (app->LevelSetFile.wa_Lock) CurrentDir(olddir);
}
Loading

0 comments on commit 67deb0f

Please sign in to comment.