2012-04-19 6 views
25

ठीक है, मैं बस अपना पीसी में एक कछुआ Git स्थापित। और मैं अपने पृष्ठ से पानी के प्रभाव के बारे में शांत हूं।टीआईमेज या कुछ भी पर पानी का प्रभाव कैसे बनाया जाए?

enter image description here

कोशिश कछुआ GIT से कछुआ चित्र पर अपने माउस कर्सर ले जाने के लिए - के बारे में

इसकी अधिक हम एक पानी पर उंगली बाहर खेल रहे हैं की तरह।

किसी को भी कैसे डेल्फी में पानी प्रभाव उस तरह का बनाना करने के लिए पता है?

+1

"जल प्रभाव" बहुत अस्पष्ट है। क्या आप पृष्ठ पर एक लिंक प्रदान करने के लिए अपना प्रश्न संपादित कर सकते हैं, इसलिए हम जान लेंगे कि आप क्या करने की कोशिश कर रहे हैं? –

+2

ये ओपन सोर्स प्रोग्राम हैं। यदि आपको ऐसा कुछ करने का मौका मिलेगा, तो आपको टोर्टोइस के स्रोत कोड को खोजने, डाउनलोड करने और पढ़ने में सक्षम होना होगा। –

+1

आपके द्वारा पोस्ट की गई छवि आपके द्वारा उल्लिखित प्रभाव प्रदर्शित नहीं करती है। क्या यह प्रभाव वेबसाइट पर या टोर्टोइज जीआईटी कार्यक्रम पर ही है? –

उत्तर

35

देखें लियोनेल Togniolli के "Water Effects" EFG की प्रयोगशाला में।

enter image description here

असर 2D Water Effects in December 1999 Game Developer Magazine Article पर आधारित है।

एल्गोरिथ्म यहाँ 2D Water में वर्णन किया गया है, के रूप फ़्राँस्वा द्वारा और स्रोत कोड में एक संदर्भ के रूप में उल्लेख किया है।

लियोनेल के कार्यान्वयन आंशिक रूप से gamedev लेख the-water-effect-explained रॉय Willemse द्वारा पर आधारित है। यहां पास्कल कोड भी है।

वहाँ EFG के मैदान पर एक और डेल्फी उदाहरण "लहर परियोजना" कहा जाता है, एक स्क्रीन शॉट नीचे दिखाया गया है है।

enter image description here

+0

बढ़िया !!! ^^ –

+6

@ एलयू आरडी का जवाब देने के लिए धन्यवाद, उत्कृष्ट उत्तर! +2 अगर मैं कर सकता था ... –

+0

मैंने डेल्फी 200 9 और एक्सई 3 में डेल्फी अनुवाद को संकलित करने का प्रयास किया है, लेकिन यह बहुत अधिक CPU समय का उपभोग करता है। सीपीपी संस्करण की तुलना में, अनुवाद के साथ कुछ गलत होना चाहिए। – TLama

3

प्रभाव छवि के लिए कुछ संख्यात्मक परिवर्तनों को लागू करने के द्वारा उत्पन्न होता है यही कारण है कि। उन्हें CWaterEffect कक्षा में परिभाषित किया गया है, जिसे आप the WaterEffect.cpp source file में अपने लिए देख सकते हैं।

+0

डेल्फी से संबंधित प्रश्न नहीं था? सी या डेल्फी, कोई फर्क नहीं पड़ता! वैसे भी लिंक टूट गया है! – Ampere

17

कृपया निम्नलिखित: 01 एक डेल्फी इकाई नाम "WaterEffect.pas" बनाएं और निम्नलिखित कोड:

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. 
  1. में "का उपयोग करता है" जोड़ें "WaterEffect" ।
  2. "सक्षम करें" संपत्ति और "अंतराल = 25" के साथ एक "टाइमर" जोड़ें।
  3. "निजी घोषणा" में "पानी: TWaterEffect," जोड़ने और "फ़्रेमबैकग्राउंड: टीबीटमैप;"।
  4. परिभाषित करें "var एक्स: पूर्णांक,"
  5. निम्नलिखित
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; 

अब संकलित को परिभाषित करें। मुझे लगता है कि आपको आवश्यक प्रभाव मिलेगा।

+5

बहुत अच्छा लगता है, लेकिन यह पूरी तरह से असम्बद्ध है - यह काम करने के लिए क्या एल्गोरिदम लागू कर रहा है? क्या यह आपका कोड है या यह कहीं और सोर्स किया गया है? –

+0

उपरोक्त क्योंकि आपका कोड लियोनेल टोग्नियोली की तुलना में बहुत तेज है। दुर्भाग्यवश, इसका वास्तविक समय में सभ्य आकार की छवि पर उपयोग नहीं किया जा सकता है! कोई केवल 8-12 एफपीएस प्राप्त कर सकता है। – Ampere

संबंधित मुद्दे