Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

SilentDragon

Alter Hase

  • »SilentDragon« ist der Autor dieses Themas

Beiträge: 530

Wohnort: Köln

Beruf: Student

  • Private Nachricht senden

1

26.02.2013, 12:09

JavaScript zu langsam oder Code ineffizient ?

Hallo zusammen,

wie schon hier im Thread geschrieben geht es um ein Malprogramm auf Pixelebene.
Habe ich nicht gefunden -> selber machen!
Wenn ich mir einmal die arbeit mache, soll es bequem sein d.h. online ohne das jeder einen Client herunter laden muss.
Hier bin ich allerdings direkt auf ein Problem gestoßen:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function draw(){
    //menu
    ctx.strokeStyle = "black";      
    ctx.strokeRect(0,0,menuscale,menuscale); //+
    ctx.strokeRect(menuscale,0,menuscale,menuscale); //-
    
    //Felder
    for(var x=0; x< size; x++){
        for(var y=0; y<size; y++){  
            ctx.fillStyle = painttabel[x][y];   //farbe 
            ctx.fillRect((x*scale)+1,1+menuscale+(y*scale),scale-1,scale-1); 
        }
    }   
    
    //Raster
    for(var x=0; x< size; x++){
        for(var y=0; y<size; y++){  
            ctx.strokeStyle = "black";      
            ctx.strokeRect(x*scale,menuscale+(y*scale),scale,scale); 
        }
    }   
}



Hier zeichne ich zuerst oben das Menü, da drunter das Feld und wenn gewünscht ein Raster.
100x100 Funktioniert es Prima, allerdings gibt es ja z.b. bei Minecraft Projekte die eine deutlich größere Fläche besitzen als 1000x1000...
Da ich keinem zumuten möchte, bei jeder Scale Änderung ca. 4 Sekunden zu warten
Habe ich im code was falsch gemacht ?
oder muss ich doch auf einen download Client umsteigen ? :(
...

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

26.02.2013, 13:24

Ich habe zwar keine Erfahrung mit Canvas, aber soweit ich weiß, gibt es Methoden um direkt ein Pixelbild zu zeichnen.
Das dürfte deutlich schneller sein als jedes Pixel als Rechteck zu zeichnen.

3

26.02.2013, 13:39

Zweimal dieselbe Schleife zu durchlaufen wird sich auch nicht positiv auf die Laufzeit auswirken.
"Theory is when you know something, but it doesn’t work. Practice is when something works, but you don’t know why. Programmers combine theory and practice: Nothing works and they don’t know why." - Anon

SilentDragon

Alter Hase

  • »SilentDragon« ist der Autor dieses Themas

Beiträge: 530

Wohnort: Köln

Beruf: Student

  • Private Nachricht senden

4

26.02.2013, 14:49

Ich habe zwar keine Erfahrung mit Canvas, aber soweit ich weiß, gibt es Methoden um direkt ein Pixelbild zu zeichnen.
Das dürfte deutlich schneller sein als jedes Pixel als Rechteck zu zeichnen.
ja die gibt es:

Quellcode

1
2
img = new Image(); 
img.src = "img/backup.png";

da aber jeder Webbrowser automatisch interpoliert muss ich trotzdem in javascript scalen:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var newimg = resize(img,scale); 
ctx.imageSmoothingEnabled = false;  
ctx.drawImage(newimg,0,0+menuscale,newimg.width, newimg.height);
var resize = function( img, scale ) {    
    var widthScaled = img.width * scale;
    var heightScaled = img.height * scale;
    
    var orig = document.createElement('canvas');
    orig.width = img.width;
    orig.height = img.height;
    var origCtx = orig.getContext('2d');
    origCtx.drawImage(img, 0, 0);
    var origPixels = origCtx.getImageData(0, 0, img.width, img.height);
    
    var scaled = document.createElement('canvas');
    scaled.width = widthScaled;
    scaled.height = heightScaled;
    var scaledCtx = scaled.getContext('2d');
    var scaledPixels = scaledCtx.getImageData( 0, 0, widthScaled, heightScaled );
    
    for( var y = 0; y < heightScaled; y++ ) {
        for( var x = 0; x < widthScaled; x++ ) {
            var index = (Math.floor(y / scale) * img.width + Math.floor(x / scale)) * 4;
            var indexScaled = (y * widthScaled + x) * 4;
            scaledPixels.data[ indexScaled ] = origPixels.data[ index ];
            scaledPixels.data[ indexScaled+1 ] = origPixels.data[ index+1 ];
            scaledPixels.data[ indexScaled+2 ] = origPixels.data[ index+2 ];
            scaledPixels.data[ indexScaled+3 ] = origPixels.data[ index+3 ];
        }
    }
    scaledCtx.putImageData( scaledPixels, 0, 0 );
    return scaled;
}

und so lade ich ebenfalls 4 sekunden bei jedem zoom -_-
...

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

26.02.2013, 14:52

Probier mal die Pixel als normale HTML-div-Elemente zu bauen.
Vielleicht geht das schneller.

SilentDragon

Alter Hase

  • »SilentDragon« ist der Autor dieses Themas

Beiträge: 530

Wohnort: Köln

Beruf: Student

  • Private Nachricht senden

6

26.02.2013, 15:46

Probier mal die Pixel als normale HTML-div-Elemente zu bauen.
Vielleicht geht das schneller.
habe es mit <div id="field"></div>
und im code dann

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
var div = document.getElementById('field');
    var content = "";
    for(var x=0; x< size; x++){
        for(var y=0; y<size; y++){  
          content += "<HR COLOR='";
          if(y%2==0)
            content+="Black";
          else
            content+="Blue";
          content+="' SIZE='1px' WIDTH='1px'></hr>"; 
        }
    }
    div.innerHTML = content;

probiert. Geschwindigkeit sah schonmal gut aus, und mit einer Passenden CSS würde ich das Padding etc. wegbekommen. Allerdings ist das Bild trotz Width="1px" in die breite gezogen.
Danke für die Hilfe, aber ich glaube bei dem Projekt komme ich einfach auf keinen grünen Zweig :dash:
...

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

7

26.02.2013, 18:10

Hatte ich in dem anderen Thread schon mal geschrieben. Wenn Windows Only ok ist, dann mach ein Programm mit WPF als Client. Da hast du im Prinzip alles gegeben was du brauchst. Sowas ist wirklich schnell geschrieben. Einen Server dafür zu schreiben sollte auch nicht besonders schwer sein. Im Prinzip müssen ja nur folgende Befehle gesendet/empfangen werden:
komplettes Bild vom Server beantragen, bzw zum Client senden,
Einen einzelnen Pixel einfärben,
und man könnte noch drüber nachdenken: mehrere Pixel einfärben. Beim starten eines Clients, holt er sich den aktuellen Stand vom Server. Wenn man nun im Client malt, schickt der seine Änderung an den Server und dieser leitet die Änderung direkt an die restlichen Clients weiter. Ich würde behaupten an einem Wochenende hat man so ein Projekt locker fertig. Kommt natürlich immer drauf an wie schön es alles aussehen soll und ob du eine Authentifizierung etc möchtest. Aber selbst dann sollte es locker machbar sein in der kurzen Zeit.
Ist natürlich nur ein Vorschlag.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

8

26.02.2013, 18:56

Ich denke das koennte fuer dich interessant sein: http://stackoverflow.com/questions/76150…caling-a-canvas

Du kannst die pixel in den canvas malen und dann mit nearest-neighbour hochskalieren. Damit solltest du den Effekt kriegen den du suchst.

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

9

26.02.2013, 20:22

Ein Canvas kann doch selber mit HW Support skalen. Von daher: Code ist ineffizient.

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

10

26.02.2013, 21:42

Wenn du mit dem Stackoverflow post nicht weiter kommst, kann ich nur empfehlen dort selbst zu posten. Dort sind einige Experten unterwegs die dir sicher helfen koennen. Aber ich denke die Frage sollte dort recht gut beantwortet sein.
JS sollte definitiv effizient genug dafuer sein, das Zeigen einige Demos wie z.B. 100,000 Stars fuer Chrome: http://workshop.chromeexperiments.com/stars/

Werbeanzeige