[js] layers+images verschuifen dmv javascript erg traag

Pagina: 1
Acties:

  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
allereerst wil ik even uitleggen dat ik al gezocht heb op got en tweakers maar hier niets heb kunnen vinden behalve iets over objecten scrollen.

Ik heb op een website een x aantal layers met daarin een plaatje,
deze layers zijn opgebouwd door een array met alle nodige gegevens met een for loopje door te lopen en daarna deze met document.write op het scherm te gooien.

Dit gaat allemaal prefect, wel wat traag, maar dat komt meer door de grote van de array.

Nu wil ik deze layers allemaal bijvoorbeeld 2 pixels per seconde opschuifen, hier heb ik een simpele functie voor gemaakt welke via een loopje (for i=0;i<layers.length;i++)

deze loop past voor iedere row gevonden in de layers array 1 layer object aan,
hij past dus gewoon de style van dit object aan en replaced deze met een waarde die 2 hoger is,
dit gaat ook perfect, alleen zodra ik meerdere images doe (vanaf een stuk of 15) gaat alles in eens heel erg traag.

weet iemand welk stuk er zo traag is? of welke stuk er oponthoud veroorzaakt?
Ik las iets over threading simulren zodat alles niet op elkaar hoeft te wachten, kan iemand dit toelichten?

de scroll functie, wordt aangeroepen met onmouseover='scroll_up=true;scrollup();' en wordt gestopt door onmouseout='scroll_up=false;'

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var scrollspeed=70;
var scrollamount=8;
function scrollup(){
    for(i=0;i<tilescount;i++){
        tiles[i][1]+=scrollamount;
        obj=document.getElementById(i).style;
        if(tiles[i][0] < window.innerWidth-128 && tiles[i][1] < window.innerHeight-64){
            obj.top=tiles[i][1];
            obj.left=tiles[i][0];
            obj.visibility='visible';
        } else {
            obj.visibility='hidden';
        }
    }
    if(scroll_up==true){
        setTimeout("scrollup()",scrollspeed);
    }
}


De array met layers: in format: id,x,y,image,imagedir
code:
1
2
3
4
5
6
7
8
9
tiles[0]=new Array(1568,186,6,'1-2-1-0','grass/');
tiles[1]=new Array(1600,194,7,'1-2-2-0','grass/');
tiles[2]=new Array(1632,202,8,'0-1-1-0','rock/');
tiles[3]=new Array(1664,210,9,'0-0-0-0','rock/');
tiles[4]=new Array(1696,226,10,'0-1-0-0','rock/');
tiles[5]=new Array(1728,234,11,'1-1-0-0','rock/');
tiles[6]=new Array(1760,250,12,'1-2-1-0','rock/');
tiles[7]=new Array(1792,258,13,'1-1-1-0','rock/');
tiles[8]=new Array(1824,274,14,'0-0-0-0','rock/');


en de code waarmee deze op het scherm gegooid wordt:
code:
1
2
3
4
5
6
7
8
9
10
var output=new Array();
for(i=0;i<tilescount;i++){
    if(tiles[i][0] < window.innerWidth-128 && tiles[i][1] < window.innerHeight-64){
        output[i]="<div id=\""+i+"\" name=\""+i+"\" style=\"position:absolute;left:"+tiles[i][0]+";top:"+tiles[i][1]+"; z-index:"+tiles[i][2]+";\">[img]"+backgroundpath+tiles[i][4]+tiles[i][3]+".png></div[/img]";
    } else {
        output[i]="<div id=\""+i+"\" name=\""+i+"\" style=\"position:absolute;left:0;top:0; z-index:"+tiles[i][2]+";visibility:hidden;\">[img]"+backgroundpath+tiles[i][4]+tiles[i][3]+".png></div[/img]";
    }
}
var output=output.join();
document.write(output);

Ik had het idee dat een document.write sneller is dan een hele stapel document.writes, klopt dit?


Zoals je kunt zien disable ik objecten die buiten het scherm gebied komen, en stop ik met scrollen zodat er geen scrollbars in de browser zichbaar worden,
uiteraard zijn er ook functies om de andere kanten op te scrollen.

Alvast bedankt voor jullie hulp,

[ Voor 14% gewijzigd door killercow op 11-11-2003 13:23 ]

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

2 tips:

-je doet nu elke keer opnieuw lookups dmv document.getElementById - sla dit op in een global array, dat scheelt enorm
-gebruik meerdere 'threads' in plaats van in 1 thread al je objecten te verplaatsen

kijk anders eens naar de sourcecode van pumpkins ;)

[ Voor 22% gewijzigd door crisp op 11-11-2003 13:34 ]

Intentionally left blank


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
uhm, tjah klinkt logisch, maar dat komt meer omdat jij master of pumpkins het zegt :)
wtf, is een global array? (ik ga zo direct zoeken daar neit van maar toch), en vreet dit niet geheugen bij een grote source array?

Hoe maak ik dan threads in js? gewoon functies? of doe je dat op een andere manier?
(zou je wellicht stukje code kunnen quoten met aanpassing? )(ik weet dat dat erg op een script request lijkt :X :X )

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Leuk voorbeeldje met wat commentaar:

HTML:
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<html>
<head>
<title>Firework</title>
<script type="text/javascript">

var h,w,n;
var fireworks = [];
var colors = ['#ffffff','#ffff00','#00ff00','#ff0000','#0000ff',
              '#ff00ff','#00ffff'];

function init() {

  h = document.body.clientHeight, w = document.body.clientWidth;

  var y = Math.random()*h, x = Math.random()*w, i = n = 50, f, a, s;

  // maak een zooi divjes met random achtergrondkleur
  do {

    f = document.createElement('div');
    f.className = 'spark';
    f.style.backgroundColor = colors[Math.floor(Math.random()*7)];
    f.style.top = y+'px';
    f.style.left = x+'px';
    f.y = y;
    f.x = x;
    a = Math.random() * 6.294;
    s = (Math.random() >.6) ? 4 : Math.random() * 4;
    f.dy = s * Math.cos(a) - 4;
    f.dx = s * Math.sin(a);

    // toevoegen aan het document
    document.body.appendChild(f);

    // referentie opslaan in array
    fireworks[i] = f;

    // elk element krijgt z'n eigen 'thread'
    setTimeout('firework_ani('+i+')',20);

  } while (--i > 0);

}

function firework_ani(i) {

  // haal element referentie op
  var f = fireworks[i];

  f.y += f.dy += 0.18;
  f.x += f.dx;

  // als het element buiten het scherm valt, verwijder het dan
  // en ruim de referentie op
  if (f.y < 0 || f.y > h || f.x < 0 || f.x > w) {

    document.body.removeChild(f);
    delete fireworks[i];
    n--;
    if (n == 0) init(); // opnieuw beginnen

  } else {

    // verplaats het element en zet de timeout voor de volgende
    // verplaatsing
    f.style.top = f.y + 'px';
    f.style.left = f.x + 'px';
    setTimeout('firework_ani('+i+')',20);

  }

}

window.onload = init;

</script>
<style type="text/css">

body,html {
  background-color: #000000;
  height: 100%;
  overflow: hidden;
}

div.spark {
  position: absolute;
  height: 2px;
  width: 2px;
  font-size: 0px;
  line-height: 0px;
}

</style>
<body>
</body>
</html>


edit: even een soort van screensaver van gemaakt :)

[ Voor 21% gewijzigd door crisp op 11-11-2003 14:52 ]

Intentionally left blank


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
dus als ik het goed begrijp kan ik het beste in de orginele layers array, nog een veld toevoegen en daarin de document.getElementById(i) voor dat object opslaan?

Aan heb ik alles netjes bij elkaar opgeslagen en kan ik ze ook makkenlijk opzoeken.. ik ga het even testen.

edit:

Okey, dat werkt, nu alleen dat threading nog, want ze moeten duidenlijk op elkaar wachten, de layers verschuifen namenlijk steeds langzamer naarmate er meer images visible worden, scrollen van alle layers met in totaal maar 1 image visible gaat wel snel genoeg, dus de bottleneck is niet meer de code die de loopjes doet en de objecten vind en aanpast, het is puur het verplaatsen van een image.

[ Voor 44% gewijzigd door killercow op 11-11-2003 14:31 ]

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

killercow schreef op 11 november 2003 @ 14:20:
dus als ik het goed begrijp kan ik het beste in de orginele layers array, nog een veld toevoegen en daarin de document.getElementById(i) voor dat object opslaan?

Aan heb ik alles netjes bij elkaar opgeslagen en kan ik ze ook makkenlijk opzoeken.. ik ga het even testen.
jep, nog mooier is om met createElement je elementen aan te maken, dan heb je gelijk die referentie en hoef je in feite alleen nog maar daarmee te werken - id's zijn dan overbodig.
In feite hoef jij ook alleen maar een divje te creëeren, dat plaatje kan je ook als background-image doen, en die mouseover op de div zetten :)

Als je mijn voorbeeldje goed bekijkt en uitprobeert zal je zien dat zelfs met 100 divjes het niet echt traag te noemen is :)

[ Voor 9% gewijzigd door crisp op 11-11-2003 14:28 ]

Intentionally left blank


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
dus ipv klooien met document.wite en daarna getElementById gewoon met createElement de boel aanmaken? werkt dit btw ook on the fly vanuit een ander frame? dus dat ik in frame x vauit frame y een nieuwe layer kan aanmaken en vullen?

edit:

reactie op hieronder \/
Oke dat komt er dus ook in, want dat is inderdaad een stuk netter, en sneller denk ik.
Aangezien de game multi-player wordt moet ik af en toe met een server connecten en daar nieuwe layers en dingen kunnen aanmaken op de client side, dit kan dus op deze manier.

Verder ben ik nog aan het zoeken naar dat threading, wat volgens 'dat ene topic' een verschil kan maken tussen 30 stotterende images en 100 vloeiende images.

weet jij hier iets van, oh grote crisp :P ??

ps hier een screenshotje:
Afbeeldingslocatie: http://www.pc-gamers.com/webgame/screenshots/features_engine_0.5.jpg
en ja alle images zijn met php gegenereerd, ook de alpha shading.

[ Voor 62% gewijzigd door killercow op 11-11-2003 14:47 ]

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

killercow schreef op 11 november 2003 @ 14:34:
dus ipv klooien met document.wite en daarna getElementById gewoon met createElement de boel aanmaken? werkt dit btw ook on the fly vanuit een ander frame? dus dat ik in frame x vauit frame y een nieuwe layer kan aanmaken en vullen?
ja:

JavaScript:
1
2
3
var frame = parent.frames['anderframe'].document;
var f = frame.createElement('div');
frame.body.appendChild(f);

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

wb de 'threading' - je ziet in mijn voorbeeldje dat ik per element eigenlijk de fireworks_ani functie aanroep met de index als parameter. In feite lopen er dus meerdere timeouts (voor elk element 1) naast elkaar. Door zoveel mogelijk load te verdelen over meerdere intervals / timeouts des te soepeler het wordt, alleen afhankelijkheid wordt wat lastiger.
Je kan de load ook functioneel verdelen - 1 thread die elke keer alle objecten afgaat en alleen maar de positionering doet, en een andere thread die bijvoorbeeld andere logica uitvoerd.
Uiteindelijk moet je kijken waar het optimum ligt - teveel threads kan ook weer gaan vertragen uiteindelijk...

Intentionally left blank


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
Het gaat door die 'threading' absoluut niet sneller,

ik heb er nieuwe functie gemaakt die de verplaatsing en de berekening op zich neemt, en deze via de for loop aangesproken maar het gaat er alleen maar langzamer van volgens mij.

ik heb nu zo'n 50 layers denk ik, allemaal met een plaatje van 64x32 24bits png.
weet iemand of dit uberhaupt niet te zwaar is, en dat alleen hardware scrolling nog enigzinds te doen is..

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

killercow schreef op 11 november 2003 @ 17:56:
Het gaat door die 'threading' absoluut niet sneller,

ik heb er nieuwe functie gemaakt die de verplaatsing en de berekening op zich neemt, en deze via de for loop aangesproken maar het gaat er alleen maar langzamer van volgens mij.

ik heb nu zo'n 50 layers denk ik, allemaal met een plaatje van 64x32 24bits png.
weet iemand of dit uberhaupt niet te zwaar is, en dat alleen hardware scrolling nog enigzinds te doen is..
Staat je CPU al op 100% te stampen?

Intentionally left blank


Verwijderd

crisp schreef op 11 november 2003 @ 18:02:
[...]

Staat je CPU al op 100% te stampen?
Ja onder zowel linux als windows staat hij zich helemaal scheel te werken :( lijkt me niet de bedoeling van een light weight webgame :P (op zowel een duron 800, xp1800)
edit:

egh, fuck reageer ik onder het account van m'n vriendin omdat ik op haar bak (die 1800 zit te testen)

[ Voor 16% gewijzigd door Verwijderd op 11-11-2003 18:09 ]


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
Of, is het verplicht dat je de functie die je wilt 'threaden' via een setTimeout moet aanroepen?
lijkt me niet toch?
al lijkt het me ook vrij sterk dat hij alle functies als threads afloopt en nie wacht op de afloop ervan tot hij verder gaat naar de volgende iteration van de loop.

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

hoi Scratch :w ;)

tsja, 50 layertjes alleen maar verplaatsen gaat nog wel, maar zodra je daar weer meer logica in gaat stoppen dan wordt het in 1 keer een stuk zwaarder. Nou moet ik zeggen dat pumpkins met 50 of meer mannekes ook heel zwaar wordt. Wat ik heb gedaan is een generieke trigger ingebouwd waarmee ik met 1 simpele afvraging kan bepalen of er wat speciaals moet gebeuren of niet. Zo niet (90% van de gevallen) is het puur een kwestie van verplaatsen waardoor het nog redelijk vlot blijft, als er wel iets speciaals moet gebeuren ga ik een andere (zwaardere) routine in waarin ik ga bepalen wat er dan moet gaan gebeuren.

Kortom: hou je main-routine zo schoon mogelijk. Hoe minder afvragingen en logica hoe beter, probeer exceptionele gevallen op een simpele manier te filteren en behandel die buiten de main-routine.

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

killercow schreef op 11 november 2003 @ 18:27:
Of, is het verplicht dat je de functie die je wilt 'threaden' via een setTimeout moet aanroepen?
lijkt me niet toch?
al lijkt het me ook vrij sterk dat hij alle functies als threads afloopt en nie wacht op de afloop ervan tot hij verder gaat naar de volgende iteration van de loop.
'threaden' kan alleen via timeout of interval - intern wordt het denk ik wel op een stack geplaatst (ligt een beetje aan de implementatie), maar daardoor krijg je wel een soepeler verloop omdat je niet in 1x een spike hebt qua CPU waarbij alle rendering even stokt, en er vervolgens een periode weer niets gebeurd...

Intentionally left blank


Verwijderd

crisp schreef op 11 november 2003 @ 18:47:
[...]

'threaden' kan alleen via timeout of interval - intern wordt het denk ik wel op een stack geplaatst (ligt een beetje aan de implementatie), maar daardoor krijg je wel een soepeler verloop omdat je niet in 1x een spike hebt qua CPU waarbij alle rendering even stokt, en er vervolgens een periode weer niets gebeurd...
Okey, heb er nu een settimeout van 5 miliseconde omheen geplaats, maar op zch gaat het er niet sneller op, (gewoon getest door scroll de andere kant op normal te houden), de normale scroll zonder thread loopt even snel, en soepel volgens mij, alleen de threaded scroll geeft een vertekening in de tiles, aangezien het een tile-based map is zoals op het plaatje is te zien krijg ik problemen met de aansluiting van de map.
zijn er nog andere optimalisaties mogenlijk, mischien de file formats?

  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 22-06 13:51

Clay

cookie erbij?

Timeouts of intervals hoeven niet echt veel lager dan 40. dat is 25 of meer fps, je browser gaat toch niet erg veel harder, het ziet er vloeiend uit, en anders maak je het alleen maar zwaarder.
Elementen visueel verplaatsten kost verhoudingsgewijs bergen tijd. Als de verplaats logica in dezelfde for loop zit als je rekenlogica moet je rekenlogica per iteratie dus wachten op het verplaatsen van elementen; Haal dit los, 1 thread kan bv. met een grote for loop alle logica doen. Elementen kan je hun eigen threads geven (of groepen elementen per thread) zodat dat elkaar niet in de weg zit.

Instagram | Flickr | "Let my music become battle cries" - Frédéric Chopin


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
Clay schreef op 12 november 2003 @ 09:59:
Timeouts of intervals hoeven niet echt veel lager dan 40. dat is 25 of meer fps, je browser gaat toch niet erg veel harder, het ziet er vloeiend uit, en anders maak je het alleen maar zwaarder.
Elementen visueel verplaatsten kost verhoudingsgewijs bergen tijd. Als de verplaats logica in dezelfde for loop zit als je rekenlogica moet je rekenlogica per iteratie dus wachten op het verplaatsen van elementen; Haal dit los, 1 thread kan bv. met een grote for loop alle logica doen. Elementen kan je hun eigen threads geven (of groepen elementen per thread) zodat dat elkaar niet in de weg zit.
klikt wederom best logish,
ik zal de timeouts aanpassen naar 40, hij scrollt dan eens per 40 mili seconden, dan doet hij de for-loop. en deze roept op zijn beurt de functie move_tile(i) aan welke de berekening doet EN de tile verplaats, dit gebeurt dus threaded via een setTimeOut van 1 zodat hier niet nogmaals een vertraging kan ontstaan.

Als jullie willen kun je hem (gedeeltelijk en op het moment alleen onder Mozilla) bekijken op
LET OP ZWAAR! http://pc-gamers.com/webgame/iso_js_scroll.php

(ik dacht al dat Clay ook wel zou gaan reageren :P )

edit:

Zou het trouwens lichter zijn voor de browser als ik alle te verplaatsen layers op een andere layer plaats en dit in zijn geheel verplaats? dan hoeft hij maar een maal de verplaatsing te berekenen.

[ Voor 11% gewijzigd door killercow op 12-11-2003 10:53 ]

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

killercow schreef op 12 november 2003 @ 10:42:
[...]

edit:

Zou het trouwens lichter zijn voor de browser als ik alle te verplaatsen layers op een andere layer plaats en dit in zijn geheel verplaats? dan hoeft hij maar een maal de verplaatsing te berekenen.
De meeste browsers hanteren sowieso een minimum van 10ms voor een timeout of interval ;)

en ja; als het mogelijk is zou ik inderdaad proberen of je alle tiles in een container kan zetten en die container verplaatsen, mijn ervaringen daarmee zijn bijzonder goed, ik wist echter niet of het voor jou een optie zou zijn :)

[ Voor 5% gewijzigd door crisp op 12-11-2003 11:22 ]

Intentionally left blank


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
Oh okey, dan doe ik dat, ik verschuif toch mijn hele speelveld, en dan moet ik alleen weer een beetje stoeien met de scroll-bars, wellicht kan de container in nog een container plaatsen die aan clipping doet zodat de container geen ruimte opneemt als hij buiten het scherm komt.

openkat.nl al gezien?


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

verwijs ik weer naar pumpkins ;)
daar heb ik een algemene content-div met overflow:hidden en een DHTML scrollbar. In die content-div zit het speelveld (dat dus breder is dan de content-div). Binnen die speelveld-div heb ik vervolgens de speelveld-elementen absoluut geplaatst. Als ik nu de speelveld-div verplaats binnen de content-div dan scrolled dus het gehele speelveld inclusief de elementen daarin.
Enige nadeel is dat ook de animaties in het niet-zichtbare deel doorlopen; daar zijn natuurlijk ook wel constructies voor te bedenken dat je alleen maar naar scherm rendert als een object zich in het zichtbare deel bevind, maar naar mijn idee zou die detectie in mijn geval zelf al ontzettend veel overhead veroorzaken.

Intentionally left blank


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 07-08 19:18
hmmfz, heb het geprobeerd zoals in pumpkins, alleen nu vertekend de hele boel, m'n top afstand wordt ineens een factor 4 zo groot ofzo, best wel vaag, ben er nog wel ff mee bezig. (das ook weer opgelost, nu nog die container laten scrollen om te kijken of het idd sneller is)

[ Voor 23% gewijzigd door killercow op 12-11-2003 14:09 ]

openkat.nl al gezien?

Pagina: 1