Got an issue with the graph unit in my Pascal program - pascal

I'm new to this forum. I'm here to ask you guys your help.
I have an assignment where I have to code a game in Pascal, which is a brick breaker in my case. Though I stumbled upon a problem that I don't quite manage to solve and it's probably related to the graph unit.
It's supposed to display a wall of bricks of various colours in the graphic interface (generated by the graph unit) but nothing appears. The window stays all black. And I know it's not due to having wrtiten a wrong path to the BGI graphic file in the initialisation of the graph unit as I used the same initalisation in an other program where I managed to draw things in the graphic interface.
Finally, my game is in french, so just a few words that you'll need to know: Niveau means level, Jouer means play and Règles means rules. You'll see by choosing a level in the menu that the application will compile but nothing will be displayed in the graph window.
I'd be very glad if you help me out (please).
Here is the main program:
program principal;
uses
Crt, Keyboard, sysutils, jeu, graph;
var
t : TKeyEvent;
c : char;
x, y, mur : Integer;
F , F2 : Text;
V: r;
GraphicsDriver, GraphicsMode, ErrCode : Smallint;
s : String;
begin
x := 62;
y := 12;
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, y);
writeln('Niveaux');
GoToXY(55, y + 2);
writeln('Regles');
GoToXY(x, y);
InitKeyBoard();
repeat //boucle pour déplacer le curseur de haut en bas dans la première fenêtre du menu
t := GetKeyEvent();
t := TranslateKeyEvent(t);
c := GetKeyEventChar(t);
if c = 's' then
begin
GoToXY(x - 1, y + 2);
x := 61;
end;
if c = 'z' then
begin
GoToXY(x, y);
x := 62;
end;
until c = 'm';
ClrScr();
case x of
62: begin
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, y);
writeln('Niveau 1');
GoToXY(55, y + 2);
writeln('Niveau 2');
GoToXY(55, y + 4);
writeln('Niveau 3');
GoToXY(63, 14);
end;
61: begin //affichage des règles
DoneKeyBoard();
assign(F2, 'Regles.txt');
reset(F2);
while not eof(F2) do
begin
readln(F2, S);
writeln(S);
end;
RetourArriereMenu(X, Y, mur, T, C, f, f2, V, GraphicsDriver, GraphicsMode, ErrCode, s);
end;
end;
x := 63;
repeat //boucle pour déplacer le curseur de ahut en bas dans la fenêtre de la séléction des niveau
t := GetKeyEvent();
t := TranslateKeyEvent(t);
c := GetKeyEventChar(t);
if c = 's' then
begin
if y < 16 then
begin
GoToXY(x, y + 2);
y := y + 2;
end;
end;
if c = 'z' then
begin
if y > 12 then
begin
GoToXY(x, y - 2);
y := y - 2;
end;
end;
until (c = 'm') or (c = 'w');
if c = 'm' then
begin
DoneKeyboard();
case y of //pour chaque niveau séléctionné, une valeur est assignée à mur (ça serivira au déroulement des procédures ci-dessous)
12: mur := 1;
14: mur := 2;
16: mur := 3;
end;
ClrScr();
GraphicsDriver := Detect; //initialisation de l'unité graph
InitGraph(GraphicsDriver, GraphicsMode,'C:\PP\BGI');
ErrCode := GraphResult;
If GraphResult <> grOK Then //affichage d'un message d'erreur si ça n'arrive pas à trouver le fichier graphique dans le répertoire indiqué ci-dessus
Begin
Writeln('Une erreur graphique s est produite: ', GraphErrorMsg(ErrCode));
Writeln('Le fichier graphique (.BGI) n a pas ete trouve, donc veuillez changer le chemin dans InitGraph');
Readln;
Halt(1);
End
Else
begin
remplissageDoc(mur,F);
MiseEnPlaceMur(mur,F,V);
end;
readln;
closegraph;
end;
if c= 'w' then
RetourArriereMenu(X,Y,mur,T,C,f,f2,V, GraphicsDriver, GraphicsMode, ErrCode,s);
end.
Here is the unit in which is stored all the procedures needed to run the main program
unit jeu;
interface
uses
sysutils, Crt, Keyboard, graph;
const
MAXtabX = 100;
MAXtabY = 50;
Type r = array [1..MAXtabX,1..MAXtabY] of Integer;
procedure remplissageDoc(m: Integer; var f: Text); //remplir les documents aléatoirement à chaque lancement de niveau. m correspond au niveau que le joueur a choisi
procedure MiseEnPlaceMur(m: Integer; var f: Text; res: r); //affichage du mur avec pour chaque bloque des vies (soit 1 soit 2 soit 3)
procedure RetourArriereMenu(X,Y: Integer; var m: Integer; var T: TkeyEvent; var C: char; var f,f2: Text; var res: r; var GraphicsDriver, GraphicsMode, ErrCode : Smallint; s: String); //pour retourner en arrière dans n'importe quel endroit du menu
procedure DessinerBrique(i,j: Integer; res: r; x1,y1,x2,y2: Integer); //dessine une brique
implementation
procedure DessinerBrique(i, j : Integer; res : r; x1, y1, x2, y2 : Integer);
begin
writeln(x1, ',', y1, ' ', x2, ',', y2, '-', res[i][j]);
setcolor(15);
rectangle(x1, y1, x2, y2);
if res[i][j]= 1 then
begin
setfillstyle(1,1);
floodfill((x1+x2)div 2,(y1+y2)div 2,15);
end;
if res[i][j] = 2 then
begin
setfillstyle(1, 2);
floodfill((x1 + x2) div 2, (y1 + y2) div 2, 15);
end;
if res[i][j]= 3 then
begin
setfillstyle(1,4);
floodfill((x1 + x2) div 2, (y1 + y2) div 2, 15);
end;
end;
procedure remplissageDoc(m : Integer; var f : Text);
var
a : Integer;
begin
if m = 1 then
begin
assign(f, 'Niveau 1.txt');
rewrite(f);
for a := 1 to 30 do //30 chiffres vont êtres saisis dans le fichier
begin
write(f, 1);
writeln;
end;
close(f);
end;
if m = 2 then
begin
assign(f, 'Niveau 2.txt');
rewrite(f);
randomize();
for a := 1 to 30 do
begin
write(f, random(2) + 1);
writeln;
end;
close(f);
end;
if m = 3 then
begin
assign(f, 'Niveau 3.txt');
rewrite(f);
randomize();
for a := 1 to 30 do
begin
write(f, random(3) + 1);
writeln;
end;
close(f);
end;
end;
procedure MiseEnPlaceMur(m : Integer; var f : Text; res : r);
var
i, j : Integer;
x1, y1, x2, y2 : Integer;
s : String;
begin
i := 1;
x1 := 200;
x2 := 245;
y1 := 0;
y2 := 25;
reset(f);
read(f, s);
while not eof do
begin
for j:= 1 to length(s) do
begin
res[i][j] := StrToInt(s[j]); //remplissage du tableau des vies
DessinerBrique(i, j, res, x1, y1, x2, y2);
x1 := x2;
x2 := x2 + 10;
if (j = 5) or (j = 10) or (j = 15) or (j = 20) or (j = 25) then //pour avoir des 6 lignes de 5 briques
begin
x1 := 200;
x2 := 245;
y1 := y2;
y2 := y1 + 25
end;
end;
end;
i := i + 1;
close(f);
end;
procedure RetourArriereMenu(X, Y : Integer; var m : Integer; var T : TkeyEvent; var C : char; var f, f2 : Text; var res : r; var GraphicsDriver, GraphicsMode, ErrCode : Smallint; s : String); //retourner en arrière à n'importe quel moment dans le menu
begin
InitKeyBoard();
T := GetKeyEvent();
T := TranslateKeyEvent(T);
C := GetKeyEventChar(T);
if C = 'w' then
begin
X := 62;
Y := 12;
ClrScr();
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, Y);
writeln('Niveaux');
GoToXY(55, Y + 2);
writeln('Regles');
GoToXY(X,Y);
repeat
T := GetKeyEvent();
T := TranslateKeyEvent(t);
C := GetKeyEventChar(t);
if C = 's' then
begin
GoToXY(X - 1, Y + 2);
X := 61;
end;
if C = 'z' then
begin
GoToXY(X, Y);
X := 62;
end;
until C = 'm';
ClrScr();
case X of
62: begin
GoToXY(47, 4);
writeln('CASSE BRIQUE STPI EDITION');
GoToXY(55, Y);
writeln('Niveau 1');
GoToXY(55,Y + 2);
writeln('Niveau 2');
GoToXY(55,Y + 4);
writeln('Niveau 3');
GoToXY(63, 14);
x := 63;
end;
61: begin
DoneKeyBoard();
assign(F2, 'Regles.txt');
reset(F2);
while not eof(F2) do
begin
readln(F2, S);
writeln(S);
end;
RetourArriereMenu(X, Y, m, T, C, f, f2, res, GraphicsDriver, GraphicsMode, ErrCode, s);
end;
end;
x:=63;
repeat
t := GetKeyEvent();
t := TranslateKeyEvent(t);
c := GetKeyEventChar(t);
if c = 's' then
begin
if y < 16 then
begin
GoToXY(x, y + 2);
y := y + 2;
end;
end;
if c = 'z' then
begin
if y > 12 then
begin
GoToXY(x, y - 2);
y := y - 2;
end;
end;
until (c = 'm') or (c = 'w');
if c = 'm' then
begin
DoneKeyboard();
case y of
12: m := 1;
14: m := 2;
16: m := 3;
end;
ClrScr();
GraphicsDriver := Detect;
InitGraph(GraphicsDriver, GraphicsMode, 'C:\PP\BGI');
ErrCode := GraphResult;
If GraphResult <> grOK Then
Begin
Writeln('Une erreur graphique s est produite: ', GraphErrorMsg(ErrCode));
Writeln('Le fichier graphique (.BGI) n a pas ete trouve, donc veuillez changer le chemin dans InitGraph');
Readln;
Halt(1);
End
Else
begin
remplissageDoc(m, f);
MiseEnPlaceMur(m, f, res);
end;
readln;
closegraph;
end;
if c = 'w' then
RetourArriereMenu(X, Y, m, T, C, f, f2, res, GraphicsDriver, GraphicsMode, ErrCode, s);
end;
end;
end.

Graphics mode is failing to initialize but you are ignoring the result. Read GraphResult exactly once, and act on that.
Edit: put the BGI fonts in your .exe directory and use '' for the BGI path.
Code Organization
Your code is very disorganized and uses a lot of meaningless variable names — making it very hard to understand what you are trying to do. That and you keep trying to switch back and forth between graphics mode and text mode (and not quite getting it right).
This “answer” is designed to help you better organize your code.
Since this is a graphical game, forget WriteLn and everything else that is not graphical. The very first thing you should do is initialize graphics mode. Put that in a procedure if you wish:
procedure Initialiser;
var
gd, gm : integer;
begin
gd := Detect;
InitGraph( gd, gm, '' );
if GraphResult <> grOK then
begin
WriteLn( 'Impossible de démarrer le mode graphique.' );
Halt( 1 )
end;
ClearDevice
end;
begin
Initialiser;
end.
Next you want to do a menu. Make that a function:
type
ActionDeMenu = (Niveau1, Niveau2, Niveau3, Aider, Quitter);
function Menu : ActionDeMenu;
begin
// dessinez votre menu ici
// obtenir l'entrée de l'utilisateur
// retourner le choix de l'utilisateur
end;
You can then update your main program. You might as well put it in a loop; Break to quit.
begin
Initialiser;
repeat
case Menu of
Niveau1: Jouer( 1 );
Niveau2: Jouer( 2 );
Niveau3: Jouer( 3 );
Aider: Aider;
Quitter: Break
end
until false;
CloseGraph
end.
After that you need to write procedures to show help and to play the game at a specified level of difficulty:
procedure Aider;
begin
// afficher l'aide
// l'utilisateur doit appuyer sur Entrée (ou quelque chose) pour continuer
end;
procedure Jouer( niveau : integer );
begin
// initialiser le niveau de jeu
// jouer le jeu
// affichage gagné/perdu
end;
As you can see, we keep breaking tasks down into simpler tasks that:
do not need to be repeated
keep tasks separate
are simple
With just this organic sense of organization you can make the game much more understandable and easier to implement.

Related

What's wrong with max values of GotoXY function?

My code is doing strange thing when MoveMessage procedure takes max values(ScreenWidth and ScreenHeight). So the "Hello, world" string moves to the right down corner and doing strange thing, but the max and min values are set correctly.
Can someone tell me where is my mistake.
program HelloCrt;
uses crt;
const
Message = 'Hello, world!';
procedure GetKey(var code: integer);
var
c: char;
begin
c := Readkey;
if c = #0 then
begin
c := Readkey;
code := -ord(c);
end
else
code := ord(c);
end;
procedure ShowMessage(x, y: integer; msg: string);
begin
GotoXY(x, y);
write(msg);
GotoXY(1, 1);
end;
procedure HideMessage(x, y: integer; msg: string);
var
len, i: integer;
begin
len := Length(msg);
GotoXY(x, y);
for i := 1 to len do
write(' ');
GotoXY(1, 1);
end;
procedure MoveMessage(var x, y: integer; msg: string; dx, dy: integer);
begin
HideMessage(x, y, msg);
x := x + dx;
y := y + dy;
if x > (ScreenWidth - length(msg)) then
x := (ScreenWidth - length(msg) + 1);
if x < 1 then
x := 1;
if y > ScreenHeight then
y := ScreenHeight;
if y < 1 then
y := 1;
ShowMessage(x, y, msg);
end;
var
CurX, CurY: integer;
c: integer;
begin
clrscr;
CurX := (ScreenWidth - length(Message)) div 2;
CurY := ScreenHeight div 2;
ShowMessage(CurX, CurY, Message);
while true do
begin
Getkey(c);
if c > 0 then
break;
case c of
-75:
MoveMessage(CurX, CurY, Message, -1, 0);
-77:
MoveMessage(CurX, CurY, Message, 1, 0);
-72:
MoveMessage(CurX, CurY, Message, 0, -1);
-80:
MoveMessage(CurX, CurY, Message, 0, 1);
end
end;
clrscr;
end.

Programming PascalABC. Why is "output" without any text?

Even just in the middle of the program I inserted "write (OutPut, '2');" and even at the very end it is, but the "output" file is still created empty.
program HelloFromRussia;
var
s, y, h, n, x: Integer;
InPut, OutPut: Text;
begin
assign(InPut,'c:\input.txt');
assign(OutPut,'c:\output.txt');
reset(InPut);
rewrite(OutPut);
read(InPut, y);
write(OutPut, '1');
for var i:=1 to y do
begin
read(InPut, s);
if s mod 2 = 0 then write(OutPut, s, ' ');
end;
writeln(OutPut);
reset(InPut);
read(InPut, y);
for var i:=1 to y do
begin
read(InPut, s);
if s mod 2 <> 0 then writeln(OutPut);
write(OutPut, s, ' ');
end;
for h:=1 to y do begin
if s mod 2=0 then
n:=n+1;
if s mod 2<>0 then
x:=x+1;
end;
if (n>x) then writeln(OutPut, 'YES')
else writeln(OutPut, 'NO');
write(OutPut, '2');
close(InPut);
close(OutPut);
end.

Clearing a single space from the console

I don't know how to word the title correctly but I was wondering if there is any way for me to be able to clear a single space from the console instead of clearing the entire thing just to re-write it again? for example, say I was to draw out a 3 by 3 square with the numbers counting from 1-9 all the way down, is there a way for me to change the final 9 without clearing all the prior numbers. when I clear the entire console it creates a flicker effect which is very annoying. if you want to see an example of this in code here is the thing I plan to use it on:
program randomPath;
uses crt, sysutils;
type StrMultiArray = array of array of String;
var
finishedBoard : StrMultiArray;
size, i, j : integer;
regenerate : boolean;
function generateMap(size : integer) : StrMultiArray;
var
posx, posy, choice, counter : integer;
ongoing : boolean;
board : StrMultiArray;
begin
setLength(board, size, size);
for i := 0 to (size-1) do
begin
for j := 0 to (size-1) do
begin
board[i,j] := '#';
end;
end;
posx := (size div 2);
posy := (size div 2);
board[posx,posy] := ' ';
ongoing := true;
counter := 0;
while ongoing = true do
begin
choice := random(2);
if (choice = 0) then
begin
choice := random(2);
if (choice = 0) then
begin
if (posx > 0) then
begin
posx := posx - 1;
end;
end
else
begin
if (posx < size-1) then
begin
posx := posx + 1;
end;
end;
end
else
begin
choice := random(2);
if (choice = 0) then
begin
if (posy > 0) then
begin
posy := posy - 1;
end;
end
else
begin
if (posy < size-1) then
begin
posy := posy + 1;
end;
end;
end;
counter := counter + 1;
board[posx,posy] := ' ';
if counter = (size * 12) then
begin
ongoing := false;
end;
end;
generateMap := board;
end;
procedure printBoard(board : StrMultiArray; size : integer);
begin
textColor(Cyan);
write('+');
for i := 0 to (size-1) do
begin
write('-');
end;
writeLn('+');
for i := 0 to (size-1) do
begin
textColor(Cyan);
write('|');
textColor(White);
for j := 0 to (size-1) do
begin
if (board[i,j] = '#') then
begin
textBackground(White);
end;
if (board[i,j] = '#') then
begin
textBackground(Red);
end;
//write(board[i,j]);
write(' ');
textBackground(Black);
end;
textColor(Cyan);
writeLn('|');
end;
textColor(Cyan);
write('+');
for i := 0 to (size-1) do
begin
write('-');
end;
writeLn('+');
textColor(White);
end;
procedure movePlayer(board : StrMultiArray; size : integer);
var
ongoing : boolean;
posx, posy, prevx, prevy : integer;
input : char;
begin
ongoing := true;
posx := (size div 2);
posy := (size div 2);
while (ongoing = true) do
begin
board[posx,posy] := '#';
prevx := posx;
prevy := posy;
printBoard(board, size);
input := readKey();
clrScr();
case input of
'w' :
if (posx > 0) then
begin
if (board[posx-1,posy] = ' ') then
posx := posx - 1;
end;
'a' :
if (posy > 0) then
begin
if (board[posx,posy-1] = ' ') then
posy := posy - 1;
end;
's' :
if (posx < (size-1)) then
begin
if (board[posx+1,posy] = ' ') then
posx := posx + 1;
end;
'd' :
if (posy < (size-1)) then
begin
if (board[posx,posy+1] = ' ') then
posy := posy + 1;
end;
'x' :
begin
regenerate := false;
ongoing := false;
end;
else
ongoing := false;
end;
board[prevx,prevy] := ' ';
end;
end;
begin
size := 10;
regenerate := true;
randomize;
while (regenerate = true) do
begin
finishedBoard := generateMap(size);
movePlayer(finishedBoard, size);
end;
end.
I found a useful function in Pascal that allow you to select a position in the console to move the "cursor" to from which point you can write in that location. the function is called GoToXY(). documentation can be found here: https://www.freepascal.org/docs-html/rtl/crt/gotoxy.html.

How to make a water effect on TImage or anything?

OK, I just installed a Tortoise git in my PC. And I'm quiet amuse about the water effect from its about page.
try to move your mouse cursor on the turtle picture from tortoise GIT - About
its more like we are playing out finger on a water.
Does anyone know how to do make that kind of water effect in Delphi ?
See Leonel Togniolli's "Water Effects" at efg's lab.
The ripple effect is based on 2D Water Effects in December 1999 Game Developer Magazine Article
.
The algorithm is described in here 2D Water, as mentioned by François and as a reference in the source code.
Leonel's implementation is partly based on the gamedev article the-water-effect-explained by Roy Willemse. Here is also pascal code.
There is one more Delphi example at efg's called "Ripple Project", a screen shot is shown below.
Please do the following :
01. Create a Delphi Unit named "WaterEffect.pas" and paste the following codes:
unit WaterEffect;
interface
uses
Winapi.Windows, System.SysUtils, Vcl.Graphics, Math;
const
DampingConstant = 15;
type
PIntArray = ^TIntArray;
TIntArray = array[0..16777215] of Integer;
PPIntArray = ^TPIntArray;
TPIntArray = array[0..16777215] of PIntArray;
PRGBArray = ^TRGBArray;
TRGBArray = array[0..16777215] of TRGBTriple;
PPRGBArray = ^TPRGBArray;
TPRGBArray = array[0..16777215] of PRGBArray;
TWaterDamping = 1..99;
TWaterEffect = class(TObject)
private
{ Private declarations }
FrameWidth: Integer;
FrameHeight: Integer;
FrameBuffer01: Pointer;
FrameBuffer02: Pointer;
FrameLightModifier: Integer;
FrameScanLine01: PPIntArray;
FrameScanLine02: PPIntArray;
FrameScanLineScreen: PPRGBArray;
FrameDamping: TWaterDamping;
procedure SetDamping(Value: TWaterDamping);
protected
{ Protected declarations }
procedure CalculateWater;
procedure DrawWater(ALightModifier: Integer; Screen, Distance: TBitmap);
public
{ Public declarations }
constructor Create;
destructor Destroy; override;
procedure ClearWater;
procedure SetSize(EffectBackgroundWidth, EffectBackgroundHeight: Integer);
procedure Render(Screen, Distance: TBitmap);
procedure Bubble(X, Y: Integer; BubbleRadius, EffectBackgroundHeight: Integer);
property Damping: TWaterDamping read FrameDamping write SetDamping;
end;
implementation
{ TWaterEffect }
const
RandomConstant = $7FFF;
procedure TWaterEffect.Bubble(X, Y: Integer; BubbleRadius, EffectBackgroundHeight: Integer);
var
Rquad: Integer;
CX, CY, CYQ: Integer;
Left, Top, Right, Bottom: Integer;
begin
if (X < 0) or (X > FrameWidth - 1) then X := 1 + BubbleRadius + Random(RandomConstant) mod (FrameWidth - 2 * BubbleRadius - 1);
if (Y < 0) or (Y > FrameHeight - 1) then Y := 1 + BubbleRadius + Random(RandomConstant) mod (FrameHeight - 2 * BubbleRadius - 1);
Left := -Min(X, BubbleRadius);
Right := Min(FrameWidth - 1 - X, BubbleRadius);
Top := -Min(Y, BubbleRadius);
Bottom := Min(FrameHeight - 1 - Y, BubbleRadius);
Rquad := BubbleRadius * BubbleRadius;
for CY := Top to Bottom do
begin
CYQ := CY * CY;
for CX := Left to Right do
begin
if (CX * CX + CYQ <= Rquad) then
begin
Inc(FrameScanLine01[CY + Y][CX + X], EffectBackgroundHeight);
end;
end;
end;
end;
procedure TWaterEffect.CalculateWater;
var
X, Y, XL, XR: Integer;
NewH: Integer;
P1, P2, P3, P4: PIntArray;
PT: Pointer;
Rate: Integer;
begin
Rate := (100 - FrameDamping) * 256 div 100;
for Y := 0 to FrameHeight - 1 do
begin
P1 := FrameScanLine02[Y];
P2 := FrameScanLine01[Max(Y - 1, 0)];
P3 := FrameScanLine01[Y];
P4 := FrameScanLine01[Min(Y + 1, FrameHeight - 1)];
for X := 0 to FrameWidth - 1 do
begin
XL := Max(X - 1, 0);
XR := Min(X + 1, FrameWidth - 1);
NewH := (P2[XL] + P2[X] + P2[XR] + P3[XL] + P3[XR] + P4[XL] + P4[X] +
P4[XR]) div 4 - P1[X];
P1[X] := NewH * Rate div 256;
end;
end;
PT := FrameBuffer01;
FrameBuffer01 := FrameBuffer02;
FrameBuffer02 := PT;
PT := FrameScanLine01;
FrameScanLine01 := FrameScanLine02;
FrameScanLine02 := PT;
end;
procedure TWaterEffect.ClearWater;
begin
if FrameBuffer01 <> nil then ZeroMemory(FrameBuffer01, (FrameWidth * FrameHeight) * SizeOf(Integer));
if FrameBuffer02 <> nil then ZeroMemory(FrameBuffer02, (FrameWidth * FrameHeight) * SizeOf(Integer));
end;
constructor TWaterEffect.Create;
begin
inherited;
FrameLightModifier := 10;
FrameDamping := DampingConstant;
end;
destructor TWaterEffect.Destroy;
begin
if FrameBuffer01 <> nil then FreeMem(FrameBuffer01);
if FrameBuffer02 <> nil then FreeMem(FrameBuffer02);
if FrameScanLine01 <> nil then FreeMem(FrameScanLine01);
if FrameScanLine02 <> nil then FreeMem(FrameScanLine02);
if FrameScanLineScreen <> nil then FreeMem(FrameScanLineScreen);
inherited;
end;
procedure TWaterEffect.DrawWater(ALightModifier: Integer; Screen, Distance:
TBitmap);
var
DX, DY: Integer;
I, C, X, Y: Integer;
P1, P2, P3: PIntArray;
PScreen, PDistance: PRGBArray;
PScreenDot, PDistanceDot: PRGBTriple;
BytesPerLine1, BytesPerLine2: Integer;
begin
Screen.PixelFormat := pf24bit;
Distance.PixelFormat := pf24bit;
FrameScanLineScreen[0] := Screen.ScanLine[0];
BytesPerLine1 := Integer(Screen.ScanLine[1]) - Integer(FrameScanLineScreen[0]);
for I := 1 to FrameHeight - 1 do FrameScanLineScreen[i] := PRGBArray(Integer(FrameScanLineScreen[i - 1]) + BytesPerLine1);
begin
PDistance := Distance.ScanLine[0];
BytesPerLine2 := Integer(Distance.ScanLine[1]) - Integer(PDistance);
for Y := 0 to FrameHeight - 1 do
begin
PScreen := FrameScanLineScreen[Y];
P1 := FrameScanLine01[Max(Y - 1, 0)];
P2 := FrameScanLine01[Y];
P3 := FrameScanLine01[Min(Y + 1, FrameHeight - 1)];
for X := 0 to FrameWidth - 1 do
begin
DX := P2[Max(X - 1, 0)] - P2[Min(X + 1, FrameWidth - 1)];
DY := P1[X] - P3[X];
if (X + DX >= 0) and (X + DX < FrameWidth) and (Y + DY >= 0) and (Y + DY < FrameHeight) then
begin
PScreenDot := #FrameScanLineScreen[Y + DY][X + DX];
PDistanceDot := #PDistance[X];
C := PScreenDot.rgbtBlue - DX;
if C < 0 then PDistanceDot.rgbtBlue := 0 else if C > 255 then PDistanceDot.rgbtBlue := 255 else
begin
PDistanceDot.rgbtBlue := C;
C := PScreenDot.rgbtGreen - DX;
end;
if C < 0 then PDistanceDot.rgbtGreen := 0 else if C > 255 then PDistanceDot.rgbtGreen := 255 else
begin
PDistanceDot.rgbtGreen := C;
C := PScreenDot.rgbtRed - DX;
end;
if C < 0 then PDistanceDot.rgbtRed := 0 else if C > 255 then PDistanceDot.rgbtRed := 255 else
begin
PDistanceDot.rgbtRed := C;
end;
end
else
begin
PDistance[X] := PScreen[X];
end;
end;
PDistance := PRGBArray(Integer(PDistance) + BytesPerLine2);
end;
end;
end;
procedure TWaterEffect.Render(Screen, Distance: TBitmap);
begin
CalculateWater;
DrawWater(FrameLightModifier, Screen, Distance);
end;
procedure TWaterEffect.SetDamping(Value: TWaterDamping);
begin
if (Value >= Low(TWaterDamping)) and (Value <= High(TWaterDamping)) then FrameDamping := Value;
end;
procedure TWaterEffect.SetSize(EffectBackgroundWidth, EffectBackgroundHeight: Integer);
var
I: Integer;
begin
if (EffectBackgroundWidth <= 0) or (EffectBackgroundHeight <= 0) then
begin
EffectBackgroundWidth := 0;
EffectBackgroundHeight := 0;
end;
FrameWidth := EffectBackgroundWidth;
FrameHeight := EffectBackgroundHeight;
ReallocMem(FrameBuffer01, FrameWidth * FrameHeight * SizeOf(Integer));
ReallocMem(FrameBuffer02, FrameWidth * FrameHeight * SizeOf(Integer));
ReallocMem(FrameScanLine01, FrameHeight * SizeOf(PIntArray));
ReallocMem(FrameScanLine02, FrameHeight * SizeOf(PIntArray));
ReallocMem(FrameScanLineScreen, FrameHeight * SizeOf(PRGBArray));
ClearWater;
if FrameHeight > 0 then
begin
FrameScanLine01[0] := FrameBuffer01;
FrameScanLine02[0] := FrameBuffer02;
for I := 1 to FrameHeight - 1 do
begin
FrameScanLine01[I] := #FrameScanLine01[I - 1][FrameWidth];
FrameScanLine02[I] := #FrameScanLine02[I - 1][FrameWidth];
end;
end;
end;
end.
In "uses" add "WaterEffect".
Add a "Timer" with "Enable" property and "Interval=25".
In "Private Declaration" add "Water: TWaterEffect;" and "FrameBackground: TBitmap;".
Define "var X:Integer;"
Define the following
procedure TMainForm.FormCreate(Sender: TObject);
begin
Timer01.Enabled := true;
FrameBackground := TBitmap.Create;
FrameBackground.Assign(Image01.Picture.Graphic);
Image01.Picture.Graphic := nil;
Image01.Picture.Bitmap.Height := FrameBackground.Height;
Image01.Picture.Bitmap.Width := FrameBackground.Width;
Water := TWaterEffect.Create;
Water.SetSize(FrameBackground.Width,FrameBackground.Height);
X:=Image01.Height;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FrameBackground.Free;
Water.Free;
end;
procedure TMainForm.Image01MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Water.Bubble(X,Y,1,100);
end;
procedure TMainForm.Image01MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
Water.Bubble(X,Y,1,100);
end;
procedure TMainForm.Timer01Timer(Sender: TObject);
begin
if Random(8)= 1 then
Water.Bubble(-1,-1,Random(1)+1,Random(500)+50);
Water.Render(FrameBackground,Image01.Picture.Bitmap);
with Image01.Canvas do
begin
Brush.Style:=bsClear;
font.size:=12;
Font.Style:=[];
Font.Name := 'Comic Sans MS';
font.color:=$e4e4e4;
Textout(190, 30, DateTimeToStr(Now));
end;
end;
Now Compile. I think you will get the required effect.
That effect is generated by applying certain numerical transformations to the image. They're defined in the CWaterEffect class, which you can inspect for yourself in the WaterEffect.cpp source file.

Draw Pascal's triangle in PASCAL Programming like a diamond

How I can draw a Pascal's triangle in PASCAL Programming like a diamond from n number which we get that from input?
Edit:
This program I tried:
program Pascal_triangle;
var
i,j,n : integer;
A : Array[1..6,1..6] of Integer;
begin
n := 6;
for i:=1 to n do
begin
for j:=1 to i do
begin
if (j=1) or (i=j) then
begin
A[i,j]:=1;
end
else
begin
A[i,j] := A[i-1,j] + A[i-1,j-1];
end;
end;
end;
for i:=1 to n do
begin
Gotoxy(41-i,i);
for j:=1 to i do
write(A[i,j])
end;
readln;
end.
but I got an error on gotoxy line and I need it to be diamond.
Dec 31 '11 at 21:22: Thanks, I wrote this and works
program Pascal_triangle;
var d,c,y,x,n : integer;
begin
readln(n);
writeln;
for y:=0 to n do
begin
c:=1;
for d:=0 to n - y do
begin
write(' ');
end;
for x:=0 to y do
begin
write(c);
write(' ');
c := c * (y - x) DIV (x + 1);
end;
writeln;
end;
for y:=n-1 downto 0 do
begin
c:=1;
for d:=0 to n - y do
begin
write(' ');
end;
for x:=0 to y do
begin
write(c);
write(' ');
c := c * (y - x) DIV (x + 1);
end;
writeln;
end;
readln;
end.

Resources