PaintMaze:
PUBLIC
ENTRY ViewerClasses.PaintProc
--PROC [self: Viewer, context: Graphics.Context, whatChanged: REF ANY, clear: BOOL]-- =
BEGIN ENABLE UNWIND => {}; --not strictly right, but it helps debugging
Decisions:
PROC =
BEGIN
crow, ccol, d, me, di: INTEGER;
mes: Square;
row ← p.row;
col ← p.col;
angle ← p.angle;
peek ← p.peek;
[prow, pcol, pdrow, pdcol, pangle] ← Peek[peek, row, col, angle];
IF fromScratch ← whatChanged = NIL THEN NULL
ELSE
IF notMe ← whatChanged # p
THEN
BEGIN
q ← NARROW[whatChanged];
shot ← q.shot;
wasShown ← q.sdistance > 0;
q.shot ← FALSE;
row ← q.row;
col ← q.col;
angle ← q.angle;
[prow, pcol, pdrow, pdcol, pangle] ← Peek[p.speek, p.srow, p.scol, p.sangle];
oDistance ← q.sdistance;
oAngle ← (q.sangle + 4 - pangle) MOD 4;
IF nowShown ← (q.sdistance ← Visible[p.mv, prow, pcol, pdrow, pdcol, row, col]) > 0
THEN
BEGIN
q.srow ← row;
q.scol ← col;
q.sangle ← angle;
nowShown ← TRUE;
END;
IF wasShown = nowShown THEN NULL
ELSE IF wasShown THEN shownPlayers ← Filter[shownPlayers, q]
ELSE shownPlayers ← CONS[q, shownPlayers];
RETURN;
END
ELSE
BEGIN
oRow ← p.srow; oCol ← p.scol; oAngle ← p.sangle;
END;
IF shot ← p.shot THEN p.shot ← FALSE;
FOR sp: PlayerList ← shownPlayers, sp.rest
WHILE sp #
NIL
DO
sp.first.sdistance ← -1;
ENDLOOP;
shownPlayers ← NIL;
crow ← prow;
ccol ← pcol;
mes ← p.mv.squares[me ← Index[p.mv, prow, pcol]];
d ← 0;
di ← Direction[p.mv, pdrow, pdcol];
WHILE mes.open
DO
nu: INTEGER ← me + di;
IF d>0
AND mes.occupants #
NIL
THEN
BEGIN
FOR pl: PlayerList ← mes.occupants, pl.rest
WHILE pl #
NIL
DO
pa: Angle ← pl.first.angle;
pl.first.srow ← crow;
pl.first.scol ← ccol;
pl.first.sangle ← pa;
pl.first.sdistance ← d;
shownPlayers ← CONS[pl.first, shownPlayers];
ENDLOOP;
END;
d ← d + 1;
mes ← p.mv.squares[me ← nu];
crow ← crow + pdrow;
ccol ← ccol + pdcol;
ENDLOOP;
p.srow ← row;
p.scol ← col;
p.sangle ← angle;
p.speek ← peek;
END;
p: Player ← NARROW[self.data];
q: Player ← NIL;
fromScratch, notMe, wasShown, nowShown, shot: BOOLEAN;
oRow, oCol, oDistance, oAngle: INTEGER;
row, col, peek, prow, pcol, pdrow, pdcol: INTEGER;
angle, pangle: Angle;
CallUnderMonitor1[Decisions];
Graphics.Translate[context, p.mv.topX, p.mv.topY];
IF fromScratch
THEN
BEGIN
DrawTopview[context, p.mv];
DrawPlayerTop[context, row, col, angle];
END
ELSE
IF notMe
THEN
BEGIN
Graphics.Translate[context, p.mv.inX, p.mv.inY];
[] ← Graphics.SetPaintMode[context, invert];
Graphics.SetCP[context, 0, 0];
IF wasShown THEN DrawHallPlayer[context, q, oDistance, oAngle, shot, FALSE];
IF nowShown THEN DrawHallPlayer[context, q, q.sdistance, (angle + 4 - pangle) MOD 4, shot, TRUE];
RETURN;
END
ELSE
BEGIN
IF clear THEN ERROR;
[] ← Graphics.SetPaintMode[context, invert];
DrawPlayerTop[context, oRow, oCol, oAngle];
DrawPlayerTop[context, p.srow, p.scol, p.sangle];
END;
Graphics.Translate[context, p.mv.inX, p.mv.inY];
IF shot
THEN
BEGIN
left, top, topCompl: INTEGER;
[left, top] ← ViewerOps.UserToScreenCoords[
self,
p.mv.inX + p.mv.topX - wb,
p.mv.inY + p.mv.topY + wb];
topCompl ← screenBitmap.height-top;
Graphics.SetCP[blastContext, 0, 0];
[] ← Graphics.SetPaintMode[blastContext, opaque];
IF left < 0
OR topCompl < 0
THEN
BEGIN --ViewerBlast.DrawBitmap should do this, but doesn't
Graphics.SetColor[blastContext, Graphics.white];
Graphics.DrawBox[blastContext, [-wb, -wb, wb, wb]];
Graphics.SetColor[blastContext, Graphics.black];
END;
ViewerBlast.DrawBitmap[self: blastContext, bitmap: screenBitmap,
w: 2*wb, h: 2*wb, x: left, y: topCompl,
xorigin: left+wb, yorigin: screenBitmap.height-top+wb];
ViewerBlast.Blast[bm: blastBitmap, bmw: [0, 0, blastBitmap.width, blastBitmap.height], lowerLeft: [left, top-2*wb], speedChooser: ViewerBlast.RandomSpeed, initial: TRUE, backwards: FALSE];
DrawHall[blastContext, p.mv, prow, pcol, pdrow, pdcol, pangle];
ViewerBlast.Blast[bm: blastBitmap, bmw: [0, 0, blastBitmap.width, blastBitmap.height], lowerLeft: [left, top-2*wb], speedChooser: ViewerBlast.RandomSpeed, initial: TRUE, backwards: TRUE];
END
ELSE
BEGIN
DrawHall[context, p.mv, prow, pcol, pdrow, pdcol, pangle];
END;
END;
DrawHallPlayer:
PROC [context: Context, q: Player, d:
INTEGER, angle: Angle, shot, backwards:
BOOLEAN] =
BEGIN
b: Bitmap ← q.pics.pics[d][angle];
IF shot
THEN
BEGIN
lowerLeft: ViewerBlast.IntPt;
[lowerLeft.x, lowerLeft.y] ← ViewerOps.UserToScreenCoords[
q.mv.maze,
q.mv.inX + q.mv.topX - b.width/2,
q.mv.inY + q.mv.topY + b.height/2 - b.height];
ViewerBlast.Blast[bm: b, bmw: [0, 0, b.width, b.height], lowerLeft: lowerLeft, speedChooser: ViewerBlast.RandomSpeed, backwards: backwards];
END
ELSE GraphicsOps.DrawBitmap[self: context, bitmap: b, w: b.width, h: b.height, x: 0, y: 0, xorigin: b.width/2, yorigin: b.height/2];
END;