Also, gestern morgen hat mich jemand gefragt ob ich einen Wassereffekt basteln könnnte. Dieser Aufgabe habe ich mir gestellt und es dann auch vollbracht.
Funktionsweise:
Als erstes wird ein 2 dimensionales netzt erstellt. Dieses netzt besteht aus punkten. Jeder punkt (als array gespeichert) hat ein paar werte:
hspeed, vspeed, pos_x und pos_y.
Diese Punkte können dann auf 2 verschidene Arten bewegt werden. Ein mal können die wellen ausgelöst werden, an einem bestimmten punkt. Zum anderen kann man generell wellen haben. D.h es sind überall Wellen, und sie werden nicht von einem bestimmten Punkt ausgelöst.
Im draw event wird dann ein screenshot vom screen gemacht, dieser dann transformiert gedrawt, da der folgende schritt eine textur im 512x512 oder 1024x1024 u.s.w format brauch. Dieser wird dann wiederrum auch wieder fotografiert und dann als textur für ein primitve genutzt.
Kommentar:
Wenn man den schritt mit dem erstellen einer textur vom screen rausnimmt, und statt dessen nur eine fertige textur nutzt, ist diese Extention sogar relativ produktiv. Leider besitzt der Gamemaker keine funktion wie texture_set_width. Von daher muss ich viele zwischenschritte machen, die sowohl sehr auf die performance gehen, und auch die quallität sehr verringern. Wer einen view von 640x480 nutzt, muss die resolution auf 256 stellen. Man kann sich jetzt gut vorstellen, was für ein wischiwaschi das wird. Ich habe noch die option eingebaut, einzustellen ob man interpolation nutzten will. Dann wird aus dem wischiwaschi wenigsten ein retro pixel look. Wer will kann sich ja mal mit dem code auseinadersetzen. Ich schätzte jetzt einfach mal pi*daumen dass da mehr kommentare als wirklicher code ist
. Hier ein screen:
view: 640x480;
resolution: 256;
Wer noch probleme damit hatte, sich die Funktionsweise vorzustellen, dem hilft vieleicht das hier:
Genug gequatscht. Hier also die 5 funktionen:
[hide=water_set() - initalisiert alles oder ändert die Einstelungen]
Alles anzeigen
[/hide][hide=water_calc1() - Der angesprochene 1. Effekt]
Alles anzeigen
[/hide][hide=water_calc2() - der 2. Effekt]
Alles anzeigen
[/hide][hide=water_draw() - drawt den wasser effekt]
Alles anzeigen
[/hide][hide=water_stop() - stoppt die wellen]
[/hide]
Ich hoffe 1. dass es einigen Hilft. Aber vielmehr hoffe ich, dass jemand vieleicht noch ne bessere idee hat, wie man das problem mit der textur in den Griff zu bekommen. Vieleicht mit einer dll?
Hier eine ZIP mit der .gmk und der .gml.
Hier eine EXE für jene die nur lite/gar nichts haben.
(irgendwas vergessen? - ne!)
MfG SDX
Funktionsweise:
Als erstes wird ein 2 dimensionales netzt erstellt. Dieses netzt besteht aus punkten. Jeder punkt (als array gespeichert) hat ein paar werte:
hspeed, vspeed, pos_x und pos_y.
Diese Punkte können dann auf 2 verschidene Arten bewegt werden. Ein mal können die wellen ausgelöst werden, an einem bestimmten punkt. Zum anderen kann man generell wellen haben. D.h es sind überall Wellen, und sie werden nicht von einem bestimmten Punkt ausgelöst.
Im draw event wird dann ein screenshot vom screen gemacht, dieser dann transformiert gedrawt, da der folgende schritt eine textur im 512x512 oder 1024x1024 u.s.w format brauch. Dieser wird dann wiederrum auch wieder fotografiert und dann als textur für ein primitve genutzt.
Kommentar:
Wenn man den schritt mit dem erstellen einer textur vom screen rausnimmt, und statt dessen nur eine fertige textur nutzt, ist diese Extention sogar relativ produktiv. Leider besitzt der Gamemaker keine funktion wie texture_set_width. Von daher muss ich viele zwischenschritte machen, die sowohl sehr auf die performance gehen, und auch die quallität sehr verringern. Wer einen view von 640x480 nutzt, muss die resolution auf 256 stellen. Man kann sich jetzt gut vorstellen, was für ein wischiwaschi das wird. Ich habe noch die option eingebaut, einzustellen ob man interpolation nutzten will. Dann wird aus dem wischiwaschi wenigsten ein retro pixel look. Wer will kann sich ja mal mit dem code auseinadersetzen. Ich schätzte jetzt einfach mal pi*daumen dass da mehr kommentare als wirklicher code ist

view: 640x480;
resolution: 256;

Wer noch probleme damit hatte, sich die Funktionsweise vorzustellen, dem hilft vieleicht das hier:

Genug gequatscht. Hier also die 5 funktionen:
[hide=water_set() - initalisiert alles oder ändert die Einstelungen]
GML-Quellcode
- /*
- real - rgument0=gridsize - muss in die nächsten beiden arguemente aufgehen!
- real - argument1=width;
- real - arguemnt2=height;
- real - argument3=friction;
- real - argument4=stärke - gravitation - die stärke mit der das wasser wieder in die ursprüngliche position geht größer=langsamer;
- real - argument5=resolution; bitte nur 2potenz nutzen
- bool - argument6=interpolation;
- */
- grid_hspeed=0; // wird nachher als array genutzt um die geschwindichkeit der punkte zu speichern
- grid_vspeed=0; // wird nachher als array genutzt um die geschwindichkeit der punkte zu speichern
- grid_pos_x=0; // wird nachher als array genutzt um die absolute position des punktes zu speichern
- grid_pos_y=0; // wird nachher als array genutzt um die absolute position des punktes zu speichern
- // ab hier ändern
- gridsize=argument[0]; // die größe des grides in pixel - muss in width un heigth aufgehen!!!!
- width=argument[1]; // breite
- height=argument[2]; // höhe
- fric=argument[3]; // der wiederstand
- starke=argument[4]; // die stärke mit der das wasser wieder in die ursprüngliche position geht größer=langsamer
- resolution=argument[5]; // die auflösung.. bitte nur 2potenz nutzen
- interpolation=argument[6];
- //ende
- textur=0; // die textur, wird im draw genutzt um die textur zu speichern
- background=0; // temporär - für den screen;
- xmacher=0; // position des auslösen der wellen
- ymacher=0; // muss im step gesetzt werden
- prev_xmacher=0;// wichtig um die distance und
- prev_ymacher=0;// die geschwindichkeit der punkte
- pointx=0; // die position von xmacher im grid
- pointy=0; // die position von xmacher im grid
- vtimes=height/gridsize+1;
- htimes=width/gridsize+1;
- for(h=0;h<vtimes;h+=1) {
- for(w=0;w<htimes;w+=1) {
- grid_pos_x[w,h]=w*gridsize;
- grid_pos_y[w,h]=h*gridsize;
- grid_hspeed[w,h]=0; // array mit nichts füllen :P
- grid_vspeed[w,h]=0;
- }
- }
GML-Quellcode
- /*
- typ: wellen auslöser;
- berechnet das wasser - im step event aufrufen
- real - argument0=x position des auslösers neuer wellen;
- real - arguemnt1=y positoon des auslösers neuer wellen;
- bool - arguemnt2=soll eine welle ausgelöst werden?
- real - argument3=die stärke: 0->1;
- */
- //bewegung des ganzen berechnen
- prev_xmacher=xmacher;
- prev_ymacher=ymacher;
- xmacher=argument[0];
- ymacher=argument[1];
- // den punkt finden, der am nächsten zum y/xmacher ist
- pointx=round(xmacher/gridsize);
- pointy=round(ymacher/gridsize);
- // die änderun dem punkt zufügen
- if (argument[2]) { // wenn die änderung sein soll
- grid_hspeed[pointx,pointy]+=(xmacher-prev_xmacher)*argument[3];
- grid_vspeed[pointx,pointy]+=(ymacher-prev_ymacher)*argument[3];
- }
- for(w=0;w<htimes;w+=1) {="" wollen="" wir="" jedem="" punkt="" noch="" friction="" und="" eine="" kraft="" verleihen,="" die="" punkte="" wieder="" an="" deren="" ursprünglichle="" position="" bewegt
- for(h=0;h<vtimes;h+=1) {=""
- grid_vspeed[w,h]+=(h*gridsize-grid_pos_y[w,h])/starke; // die kraft hinzufügen
- grid_hspeed[w,h]+=(w*gridsize-grid_pos_x[w,h])/starke;
- grid_hspeed[w,h]/=fric+1; // friction
- grid_vspeed[w,h]/=fric+1;
- // alle änderung auf die position übergeben
- grid_pos_x[w,h]+=grid_hspeed[w,h];
- grid_pos_y[w,h]+=grid_vspeed[w,h];
- }
- }
[/hide][hide=water_calc2() - der 2. Effekt]
GML-Quellcode
- /*
- typ: generell wellen;
- berechnet das wasser - im step event aufrufen
- real - arguemnt0=wellengang;
- */
- for(w=1;w<htimes-1;w+=1) {="" wir="" starten="" nicht="" mit="" dem="" ersten="" um="" machen="" auch="" den="" letzten,="" damit="" die="" äußersten="" punkte="" still="" bleiben.
- for(h=1;h<vtimes-1;h+=1) {=""
- //bewegung des ganzen berechnen
- prev_xmacher=xmacher;
- prev_ymacher=ymacher;
- xmacher=random(argument[0])-argument[0]/2;
- ymacher=xmacher;
- // die änderung dem punkt zufügen
- grid_hspeed[w,h]+=xmacher-prev_xmacher;
- grid_vspeed[w,h]+=ymacher-prev_ymacher;
- // die gravity hinzufügen
- grid_vspeed[w,h]+=(h*gridsize-grid_pos_y[w,h])/starke;
- grid_hspeed[w,h]+=(w*gridsize-grid_pos_x[w,h])/starke;
- grid_hspeed[w,h]/=fric+1; // friction
- grid_vspeed[w,h]/=fric+1;
- // alle änderung auf die position übergeben
- grid_pos_x[w,h]+=grid_hspeed[w,h];
- grid_pos_y[w,h]+=grid_vspeed[w,h];
- }
- }
[/hide][hide=water_draw() - drawt den wasser effekt]
GML-Quellcode
- /* drawt das wasser an der positon;
- real - argument0=x;
- real - argument1=y;
- bool - argument2=hilfsmittel - sollen auch hilfslinien oder punkte gedrawt werden?;
- */
- var xx,yy;
- xx=argument[0];
- yy=argument[1];
- background=background_create_from_screen(xx,yy,width,height,0,0,1); // screencapture
- draw_background_ext(background,0,0,resolution/width,resolution/height,0,-1,1); // draw im richtigen format
- textur=background_create_from_screen(0,0,resolution,resolution,0,0,1) // das capturen
- // lass uns alles drawen
- texture_set_blending(-1); // wichtig!
- texture_set_interpolation(interpolation); // nicht wichtig!
- draw_primitive_begin_texture(pr_trianglelist,background_get_texture(textur));
- for(w=0;w<htimes-1;w+=1) {
- for(h=0;h<vtimes-1;h+=1){
- draw_vertex_texture(grid_pos_x[w,h]+xx,grid_pos_y[w,h]+yy,w*gridsize/width,h*gridsize/height);
- draw_vertex_texture(grid_pos_x[w+1,h]+xx,grid_pos_y[w+1,h]+yy,(w+1)*gridsize/width,h*gridsize/height);
- draw_vertex_texture(grid_pos_x[w,h+1]+xx,grid_pos_y[w,h+1]+yy,w*gridsize/width,(h+1)*gridsize/height);
- // das erste dreieck.. wir brauchen aber 2, um ein 4eck zu bekommen
- draw_vertex_texture(grid_pos_x[w+1,h]+xx,grid_pos_y[w+1,h]+yy,(w+1)*gridsize/width,h*gridsize/height);
- draw_vertex_texture(grid_pos_x[w+1,h+1]+xx,grid_pos_y[w+1,h+1]+yy,(w+1)*gridsize/width,(h+1)*gridsize/height);
- draw_vertex_texture(grid_pos_x[w,h+1]+xx,grid_pos_y[w,h+1]+yy,w*gridsize/width,(h+1)*gridsize/height);
- }
- }
- draw_primitive_end(); // fertig
- background_delete(background); // speicher von der textur befreien
- background_delete(textur);
- if (argument[2]) {
- // das ganze ein mal ohne textur nur mit linien
- draw_primitive_begin(pr_linestrip);
- for(w=0;w<htimes-1;w+=1) {
- for(h=0;h<vtimes-1;h+=1){
- draw_set_color(c_lime);
- draw_circle(grid_pos_x[w,h]+xx,grid_pos_y[w,h]+yy,4,0);
- draw_set_color(c_blue);
- draw_vertex(grid_pos_x[w,h]+xx,grid_pos_y[w,h]+yy);
- draw_vertex(grid_pos_x[w+1,h]+xx,grid_pos_y[w+1,h]+yy);
- draw_vertex(grid_pos_x[w,h+1]+xx,grid_pos_y[w,h+1]+yy);
- draw_vertex(grid_pos_x[w,h]+xx,grid_pos_y[w,h]+yy);
- // das erste dreieck.. wir brauchen aber 2, um ein 4eck zu bekommen
- draw_vertex(grid_pos_x[w+1,h]+xx,grid_pos_y[w+1,h]+yy);
- draw_vertex(grid_pos_x[w+1,h+1]+xx,grid_pos_y[w+1,h+1]+yy);
- draw_vertex(grid_pos_x[w,h+1]+xx,grid_pos_y[w,h+1]+yy);
- draw_vertex(grid_pos_x[w+1,h]+xx,grid_pos_y[w+1,h]+yy);
- }
- }
- draw_primitive_end(); // fertig
- draw_set_color(c_red);
- draw_circle(pointx*gridsize+xx,pointy*gridsize+yy,4,0);
- }
[/hide]
Ich hoffe 1. dass es einigen Hilft. Aber vielmehr hoffe ich, dass jemand vieleicht noch ne bessere idee hat, wie man das problem mit der textur in den Griff zu bekommen. Vieleicht mit einer dll?
Hier eine ZIP mit der .gmk und der .gml.
Hier eine EXE für jene die nur lite/gar nichts haben.
(irgendwas vergessen? - ne!)
MfG SDX
Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von SDX ()