this slowpoke moves

Sand Screensaver

Ich war ja nie ein Fan von Screensaver, doch dieser ist besonders gut.

Der Desktop fällt praktisch als Sandhaufen auf den Boden.

Der Effekt überträgt sich auf alle Monitore oder auf erweiterte Desktops.
Projekt Datei sand.dpr
program sand;

uses
  Forms,
  windows,
  SysUtils,
  graphics,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
{$E scr}

function Screenshot(var bmp: TBitmap; MonitorNumber: Integer): Boolean;
const
  CAPTUREBLT = $40000000;
var
  DC: HDC;
  Left, Top: Integer;
begin
  Result := False;
  if (MonitorNumber >= Screen.MonitorCount) then  Exit;
  DC:= GetDC(0);
  try
    if (DC = 0) then  Exit;
    Bmp.Width := Screen.Monitors[MonitorNumber].Width;
    Bmp.Height := Screen.Monitors[MonitorNumber].Height;
    Left := Screen.Monitors[MonitorNumber].Left;
    Top := Screen.Monitors[MonitorNumber].Top;
    try
      Result := BitBlt(
        Bmp.Canvas.Handle,
        0, 0, Bmp.Width, Bmp.Height,
        DC, Left,Top,
        SRCCOPY or CAPTUREBLT);
      Result:= True;
    finally
    end;
  finally
    if (DC <> 0) then  ReleaseDC(0, DC);
  end;
end;


var
 i:integer;
 bmp:tbitmap;
 
begin
  Param1 := Copy(UpperCase(ParamStr(1)),1,2);
  Param2 := UpperCase(ParamStr(2));
  If (Length(Param1)>0)And Not (Param1[1] In ['A'..'Z']) Then
    Param1 := Copy(Param1,2,1);

  ssMode := ssAffiche;
  If Param1='P' Then ssMode := ssPrevisu;
  If Param1='C' Then ssMode := ssConfig;
  If Param1='S' Then ssMode := ssAffiche;
  If Param1='A' Then ssMode := ssMotDePasse;

  SetLastError(NO_ERROR);
  CreateMutex (nil, False, 'MONSCREENSAVER');
  if GetLastError = ERROR_ALREADY_EXISTS Then Exit;

  case ssMode of
  ssAffiche:
   begin
    SystemParametersInfo(SPI_SCREENSAVERRUNNING,1,@i,0);
    Application.Initialize;
    bmp:=tbitmap.Create;
    for i:=0 to screen.MonitorCount-1 do
     begin
      Application.CreateForm(TForm1, Form1);
  Form1.Cursor:=-1;
      Screenshot(Form1.bitmap,i);
      if not form1.Visible then Form1.Show;
      Form1.BoundsRect:=screen.Monitors[i].BoundsRect;
      Form1.iniPicture;
     end;
    bmp.Free;
    Application.Run;
    SystemParametersInfo(SPI_SCREENSAVERRUNNING,0,@i,0);
   end;
  ssPrevisu:
   begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Form1.bitmap.assign(Form1.image1.picture.bitmap);
    Form1.iniPicture;
    Form1.ParentWindow := StrToInt(paramstr(2));
    Form1.WindowState:=wsMaximized;
    Application.Run;
   end;
  ssConfig:
   begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Form1.bitmap.assign(Form1.image1.picture.bitmap);
    Form1.iniPicture;
    ssmode:=ssPrevisu;
    Form1.WindowState:=wsMaximized;
    Form1.Show;
    Application.Run;
   end;
  ssMotDePasse:
   begin
   end;
  end;
end.
Unit1 :
uses Math

Type TssMode = ( ssAffiche , ssConfig , ssMotDePasse , ssPrevisu );
Const
 Vitesse_Maxi=200;
 Ralentissement=10;

Var
  ssMode      : TssMode = ssAffiche;
  Param1      : String;
  Param2      : String;
  
private
    w,h:integer;
    dx:integer;
    count:integer;
    BackColor:integer;
    WallColor:integer;
    palette:array[0..360] of longint;
    v:array of integer;
    LastN:integer;
    CountN:integer;
    procedure DoSand;
    function GetBackGround:integer;
    function countMoving:integer;
  public
    bitmap:tbitmap;
    procedure iniPicture;
  end;
  
var
  Form1:TForm1;
  mousepos:tpoint;

type
  PQuadArray = ^TQuadArray;
  TQuadArray = array [Byte] of longint;
  TGrain =record Pt:tpoint;V:TPoint;color:integer;actif:boolean; end;
type
 PArbreCouleur=^TArbreCouleur;
 TArbreCouleur=record
                count:integer;
                bit0,bit1:PArbreCouleur;
               end;
               
//

procedure nouvellefeuille(var feuille:PArbreCouleur);
begin
 new(feuille);
 feuille.count:=0;
 feuille.bit0:=nil;
 feuille.bit1:=nil;
end;

function ClasseCouleur(c:dword;level:byte;feuille:PArbreCouleur):integer;
begin
 if level=0 then
  begin
   inc(feuille.count);
   result:=feuille.count;
   exit;
  end;
 if c and 1=0 then
  begin
   if feuille.bit0=nil then nouvellefeuille(feuille.bit0);
   result:=ClasseCouleur(c shr 1,level-1,feuille.bit0);
  end
 else
  begin
   if feuille.bit1=nil then nouvellefeuille(feuille.bit1);
   result:=ClasseCouleur(c shr 1,level-1,feuille.bit1);
  end;
end;

procedure EffaceArbre(feuille:PArbreCouleur);
begin
 if feuille=nil then exit;
 EffaceArbre(feuille.bit0);
 EffaceArbre(feuille.bit1);
 dispose(feuille);
end;

function Tform1.GetBackGround:integer;
var
 i:integer;
 n,m:integer;
 q:PQuadArray;
 arbre:PArbreCouleur;
begin
 m:=0;
 result:=$FFFFFF;
 nouvellefeuille(arbre);
 q:=bitmap.scanline[h-1];
 for i:=0 to w*h-1 do
  begin
   n:=ClasseCouleur(q[i],32,arbre);
   if n>m then begin m:=n;result:=q[i]; end;
  end;
 EffaceArbre(arbre);
end;

function Tform1.countMoving:integer;
var
 i,n:integer;
begin
 n:=0;
 for i:=0 to w*h-1 do if v[i]<>0 then inc(n);
 result:=n;
end;

procedure TForm1.DoSand;
var
 x,y,tx,ox:integer;
 a,b,c,d,e,ia,ib,ic,id:integer;
 bg,wc:integer;
 q:PQuadArray;
 px1,py1,px2,py2:integer;
 tv:integer;
 function tombe(index,n:integer):integer;
 var
  pe,i,linedown:integer;
 begin
  linedown:=index-w;
  if n=0 then
   begin
    result:=index;
   end
  else
  if q[linedown]<>BG then
   begin
    pe:=0;
    if q[linedown-1]<>bg then pe:=pe+1;
    if q[linedown+1]<>bg then pe:=pe+2;
    if pe=0 then pe:=random(2)+1;
    case pe of
     1: result:=tombe(linedown+1,n-1);
     2: result:=tombe(linedown-1,n-1);
     3: begin tv:=0; result:=index; end;
    end;
   end
  else
   begin
    result:=tombe(linedown,n-1);
   end;
 end;
 procedure tombeN(ida:integer);
 var
  r:integer;
 begin
  tv:=v[ida]+1;
  r:=tombe(ida,tv div Ralentissement+1);
  if r<>-1 then
   begin
    if tv>Vitesse_Maxi then tv:=Vitesse_Maxi;
    q[r]:=q[ida];
    v[r]:=tv;
    q[ida]:=BG;
    v[ida]:=0;
   end
  else
   v[ida]:=0;
 end;
 procedure tombeAB(ida,idb:integer);
 begin
  v[idb]:=v[ida];
  q[idb]:=q[ida];
  v[ida]:=0;
  q[ida]:=BG;
 end;
begin
 bg:=BackColor;
 wc:=WallColor;
 q:=bitmap.scanline[h-1];
 dx:=-dx;
 if dx=1 then ox:=1 else ox:=w-2;
 for y:=0 to h-3 do
  begin
   x:=ox;
   for tx:=0 to w-3 do
    begin
        ib:=x+w*y;
        ia:=ib+w;
        ic:=ib-1;
        id:=ia-1;
        a:=q[ia];
        b:=q[ib];
        c:=q[ic];
        d:=q[id];
        e:=0;
        if (a<>bg) then e:=e+1;
        if (b<>bg) then e:=e+2;
        if (c<>bg) then e:=e+4;
        if (d<>bg) then e:=e+8;
        if (a=wc)  then e:=e+100-1;
        if (b=wc)  then e:=e+200-2;
        if (c=wc)  then e:=e+400-4;
        if (d=wc)  then e:=e+800-8;
        if (e>=100) and (e<=199) then e:=e-100;
        if (e>=800) and (e<=899) then e:=e-800;
        if (e>=900) and (e<=999) then e:=e-900;
        case e of
          2,4,6,402,403,204,212,800,1500,1400,1300,1100,700,1302,1104,
          300,1200,500,1000,304,1202,502,1004:;
          601,7,205,1401,1203,1001,1005:begin v[ia]:=0;  end;
          608,14,410,708,312,508,510:begin v[ib]:=0; end;
          609,15,411,213:begin v[ia]:=0; v[id]:=0; end;
          201: begin tombeAB(ia,ic); end;
          408: begin tombeAB(id,ib); end;
          5,401,409,1201: begin tombeN(ia); end;
          13:
           if random(2)=0 then
            begin tombeN(ia); end
           else
            begin tombeAB(ic,ib);tombeAB(id,ic); end;
          10,208,209,308: begin tombeN(id); end;
          11:
           if random(2)=0 then
            begin tombeN(id); end
           else
            begin tombeAB(ib,ic);tombeAB(ia,ib); end;
          3:
           if random(2)=0 then
            begin tombeAB(ia,ic); end
           else
            begin tombeAB(ib,ic);tombeAB(ia,ib); end;
          12:
           if random(2)=0 then
            begin tombeAB(id,ib); end
           else
            begin tombeAB(ic,ib);tombeAB(id,ic); end;
          1:begin tombeN(ia); end;
          8:begin tombeN(id); end;
          9:begin tombeN(ia); tombeN(id); end;
        end;
        x:=x+dx;
    end;
  end;
end;

procedure Tform1.iniPicture;
begin
 w:=Bitmap.Width;
 h:=Bitmap.Height;
 bitmap.PixelFormat:=pf32bit;
 BackColor:=GetBackGround;
 if BackColor=0 then WallColor:=$FFFFFF else WallColor:=0;
 Bitmap.Width:=Bitmap.Width+2;
 Bitmap.Height:=Bitmap.Height+2;
 Bitmap.Canvas.Draw(1,1,Bitmap);
 w:=w+2;
 h:=h+2;
 bitmap.Canvas.Brush.Color:=WallColor;
 bitmap.Canvas.FrameRect(rect(0,0,w,h));
 bitmap.Canvas.Brush.Color:=0;
 setlength(v,w*h);
 timer.Enabled:=true;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
 Paintbox1.canvas.draw(-1,-1,bitmap);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 i:integer;
begin
 bitmap:=tbitmap.Create;
 DoubleBuffered:=true;
 dx:=1;
 count:=0;
 BackColor:=$FFFFFF;
 WallColor:=$000000;
 GetCursorPos(mousepos);
  for i:=0 to 360 do
   Case (i div 60) of
      0,6:palette[i]:=rgb(255,(i Mod 60)*255 div 60,0);
      1: palette[i]:=rgb(255-(i Mod 60)*255 div 60,255,0);
      2: palette[i]:=rgb(0,255,(i Mod 60)*255 div 60);
      3: palette[i]:=rgb(0,255-(i Mod 60)*255 div 60,255);
      4: palette[i]:=rgb((i Mod 60)*255 div 60,0,255);
      5: palette[i]:=rgb(255,0,255-(i Mod 60)*255 div 60);
   end;
end;

procedure TForm1.FormClick(Sender: TObject);
begin
 if ssmode=ssPrevisu then exit;
 Close;
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
 if ssmode=ssPrevisu then exit;
 Close;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 inherited;
 bitmap.Free;
end;

procedure TForm1.TimerTimer(Sender: TObject);
var
 n:integer;
 q:pquadarray;
 tmp:tbitmap;
 i:integer;
begin
 DoSand;
 Paintbox1.canvas.draw(-1,-1,bitmap);
 n:=countMoving;
 if lastN=n then
  begin
   inc(CountN);
   if CountN>30*5 then
    begin
     bitmap.Canvas.CopyRect(rect(0,h-1,w-1,0),bitmap.Canvas,rect(0,0,w-1,h-1));
     CountN:=0;
     LastN:=0;
    end;
  end
 else
  begin
   LastN:=n;
   CountN:=0;
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 timer.Enabled:=false;
 application.Terminate;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
pt:tpoint;
begin
 if ssmode=ssPrevisu then exit;
 GetCursorPos(pt);
 if abs(sqr(pt.x-mousepos.X)+sqr(pt.y-mousepos.Y))>25 then close;
end;

Keine Kommentare:

Kommentar veröffentlichen

Beliebte Posts

Translate