SpaceTraffic: TestPohybPlanet1 |
from Wiki KIVu |
Zpět na HomePage
Původní implementace je hned ve dvou bodech:
Nová implementace získá od serveru pouze výchozí parametry jednotlivých objektů.
Základ je počáteční poloha (v čase t), parametry dráhy a parametry objektu. Veškeré další vykreslování bude prováděno na straně klineta včetně optimalizací pro klientovo rozlišení.
Dynamické objekty (lodě) budou do vykreslování přidávány za chodu.
Využití css vlastností top a left a jejich nastavení pomocí skriptu. V této variantě není dostupná transformace rotace.
Ukázka pohybu
Ukázka pohybu
Vlastnost transform umožňuje zadat objektu transformační matici pro vykreslení.
Tato vlastnost je podporována ve všech současných prohlížečích kromě IE8?, kde však lze použít vestavěnou funkci pro dosažení stejného efektu.
Výhodou tohoto řešení je především jednoduchost a možnost používat běžné postupy z počítačové grafiky pro výpočty.
Lze doplnit o podporu další grafiky.
Podpora canvas a svg je další možná implementace. Je zde problém s IE, který bude obě technologie podporovat až ve verzi 9.
Předpokládá se spíše využití pro doplňující grafiku (lepší vykreslování trajektorií a efekty).
Základem je sjednotit všechny animace pohybů pod jeden časovač a tím dosáhnout plynulého překreslování celého obrazu.
Zásadní je zde otázka optimalizace. Při běžné rychlosti překreslování 24 snímků za sekundu je zatížení prohlížeče příliš veliké.
Proto je třeba provést následující optimalizace:
Zajimavé soubory | Odkaz na soubor |
stt.js | Zobrazit kód souboru testu s javascriptem |
stt.html | Zobrazit kód souboru testu s html kódem |
Demo stt.html
demonstruje možnosti vykreslování pomocí css pro soustavu s pohybem po kružnici.
Planety mají zadánu úhlovou rychlost.
Řešení je funkční ve Firefoxu, Safari a Chrome ve verzích k lednu 2011. V IE nastavení pozic funguje, ale je zde jiný problém s proměnnými v javascriptu.
V Opeře dochází k problémům se zaokrouhlováním při násobení matic. Problém je pravděpodobně v použitém maticovém frameworku Sylvester, ale může se jednat i o bug v Opeře, protože při zapnutém dragonfly jsou výsledky výpočtů správné.
Tento problém lze odstranit vlastní implementací násobení matic, které by zároveň pomohlo i s optimalizací (napevno implementované násobení matic 3x3 oproti cyklům).
Toto demo není optimalizované a pohyb planet je zde mnohem rychlejší, než ten uvažovaný ve hře.
/// Tento soubor obsahuje experiment s vykreslování animace sluneční soustavy /// s využitím CSS3. /// Je použita kruhová dráha planet. var $graphics = null; var lastRenderT = 0; /** * Vytvoření divu planety i s transformacemi pro innerHtml injection. */ function createPlanet(identifier, r, a, b, c, d, tx, ty) { //console.log("createPlanet"); return '<div class="planet" id="'+identifier+'" style="'+ 'width:'+r*2+'px;'+ 'height:'+r*2+'px;'+ 'border-radius:'+r+'px;'+ '-moz-border-radius: '+r+'px;'+ '-moz-transform: matrix('+a+','+b+','+c+','+d+','+tx+'px,'+ty+'px);'+ '-webkit-transform: matrix('+a+','+b+','+c+','+d+','+tx+','+ty+');'+ '-o-transform: matrix('+a+','+b+','+c+','+d+','+tx+','+ty+');'+ 'transform: matrix('+a+','+b+','+c+','+d+','+tx+','+ty+');'+ '"></div>'; } /** * Nastavení divu planety na požadované parametry. * Vytvoří kulatý div o požadovaném poloměru. * @param $identifier selector jquery pro div. * @param data data planety. */ function setPlanet($identifier, data) { //console.log("setPlanet"); $identifier.css({ 'border-radius': data.r+'px', '-moz-border-radius': data.r+'px', 'width':data.r*2, 'height':data.r*2 }) } /** * Sada funkcí pro generování transformačních matic. */ var GT = { // Rotace rotate: function(deg) { var rad = parseFloat(deg) * (Math.PI/180.0), costheta = Math.cos(rad), sintheta = Math.sin(rad); var a = costheta, b = sintheta, c = -sintheta, d = costheta; return $M([ [a, c, 0.0], [b, d, 0.0], [0.0, 0.0, 1.0] ]); }, // Scale scale: function (sx, sy) { sx = sx || sx === 0 ? sx : 1; sy = sy || sy === 0 ? sy : 1; return $M([ [sx, 0, 0], [0, sy, 0], [0, 0, 1] ]); }, scaleX: function (sx) { return this.scale(sx); }, scaleY: function (sy) { return this.scale(1, sy); }, // Skew (Zkosení) skew: function (degX, degY) { var radX = parseFloat(degX) * (Math.PI/180), radY = parseFloat(degY) * (Math.PI/180), x = Math.tan(radX), y = Math.tan(radY); return $M([ [1, x, 0], [y, 1, 0], [0, 0, 1] ]); }, skewX: function (deg) { var rad = parseFloat(deg) * (Math.PI/180), x = Math.tan(rad); return $M([ [1, x, 0], [0, 1, 0], [0, 0, 1] ]); }, skewY: function (deg) { var rad = parseFloat(deg) * (Math.PI/180.0), y = Math.tan(rad); return $M([ [1.0, 0.0, 0.0], [y, 1.0, 0.0], [0.0, 0.0, 1.0] ]); }, // Posunutí. translate: function (tx, ty) { tx = tx ? tx : 0.0; ty = ty ? ty : 0.0; return $M([ [1.0, 0.0, tx], [0.0, 1.0, ty], [0.0, 0.0, 1.0] ]); }, translateX: function (tx) { return this.translate(tx); }, translateY: function (ty) { return this.translate(0, ty); }, // Generuje pole odpovídající matici transformace pro potřeby nastavení v css. toCssMatrix: function(matrix) { return [matrix.e(1,1), matrix.e(2,1), matrix.e(1,2), matrix.e(2,2), matrix.e(1,3), matrix.e(2,3) ]; /*return [Math.round(matrix.e(1,1)), Math.round(matrix.e(2,1)), Math.round(matrix.e(1,2)), Math.round(matrix.e(2,2)), Math.round(matrix.e(1,3)), Math.round(matrix.e(2,3)) ];*/ }, // Vypíše matici transformace. Pro ladící účely. toString: function(matrix) { return '['+matrix.e(1,1)+', '+matrix.e(2,1)+', '+matrix.e(1,2)+', '+matrix.e(2,2)+', '+matrix.e(1,3)+', '+matrix.e(2,3)+']'; } }; /** * Ruční nastavení transformační matice ve stylu elementu. * @param $identifier selektor elementu * @param matrix matice */ function setCssMatrix($identifier, matrix) { var a = Math.round(matrix.e(1,1)), b = Math.round(matrix.e(2,1)), c = Math.round(matrix.e(1,2)), d = Math.round(matrix.e(2,2)), tx = Math.round(matrix.e(1,3)), ty = Math.round(matrix.e(2,3)); $identifier.css({'-moz-transform':'matrix('+a+','+b+','+c+','+d+','+tx+'px,'+ty+'px)', '-webkit-transform':'matrix('+a+','+b+','+c+','+d+','+tx+'px,'+ty+'px)', '-o-transform':'matrix('+a+','+b+','+c+','+d+','+tx+'px,'+ty+'px)', 'transform':'matrix('+a+','+b+','+c+','+d+','+tx+'px,'+ty+'px)'}); } /** * Renderovací funkce. */ function render() { // Zjištění aktuálního času var t = (new Date().getTime())/1000; var dt = t-lastRenderT; // Výpočet souřadnic počátku (uprostřed divu. var origin_x = $graphics.width()/2.0; var origin_y = $graphics.height()/2.0; // Transformační matice zobrazení (posune na střed divu) var TView = GT.translate(origin_x, origin_x); // Transformační matice polohy hvězdy. var TSun = GT.translate(sun.x0-sun.r, sun.y0-sun.r); // Nastavení polohy vhězdy. var m1 = TView.x(TSun); $sun.transform({ matrix: GT.toCssMatrix(m1)}, { preserve: false }); // Výpis ladících údajů $('#timer').html(t+'; MSun='+GT.toString(m1)+'; TView='+GT.toString(TView)+'; TSun='+GT.toString(TSun)); // Nastavení poloh planet. for(i=0;i<planets.length;i++) { var planet = planets[i]; var m1 = TView.x(planetCircularPositionMatrix(planet.data, t)); planet.$id.transform({ matrix: GT.toCssMatrix(m1)}, { preserve: false }); } } /** * Výpočet pozice planety na kruhové dráze. * Je zadána úhlová rychlost planety. * @param planet planeta * @param t čas * @returns transformační matice pro polohu planety v t. */ function planetCircularPositionMatrix(planet, t) { var alpha = (planet.w*t)%360.0; var TPos = GT.translate(planet.x0, planet.y0); var RRot = GT.rotate(alpha); var TCorection = GT.translate(-planet.r, -planet.r); return TCorection.x(RRot.x(TPos)); }
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cs"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="description" content="SpaceTraffic-description" /> <meta name="author" xml:lang="cs" content="Space Traffic Team" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <title>Space Traffic Test Page</title> <link rel="stylesheet" media="screen,projection,tv" href="/webgame_new/www/css/cssmap.css" type="text/css" /> <!--<link rel="stylesheet" media="print" href="/webgame_new/www/css/print.css" type="text/css">--> <link rel="shortcut icon" href="/webgame_new/www/favicon.ico" type="image/x-icon" /> <!--<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js"></script>--> <script type="text/javascript" src="jquery-1.4.4.js"></script> <!--<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.8/jquery-ui.js"></script>--> <script type="text/javascript" src="jquery.transform-0.9.3.min.js"></script> <script type="text/javascript" src="sylvester.min.js"></script> <script type="text/javascript" src="stt.js"></script> <!-- <script type="text/javascript" src="/webgame_new/www/js/netteForms.js"></script> --> <script type="text/javascript"> var transX = 0; var sun = null; var $graphics = null; // Definice planet var sun = { x0 : 0, y0 : 0, r : 25, w : 0 }; var planet1 = { x0 : 60, y0 : 0, r : 5, w : 18 }; var planet2 = { x0 : 90, y0 : 0, r : 8, w : 6 }; var planet3 = { x0 : 130, y0 : 0, r : 15, w : 7 }; var planet4 = { x0 : 150, y0 : 0, r : 14, w : 3 }; var planet9 = { x0 : 180, y0 : 0, r : 59, w : 3 }; var planets = null; // Inicializace renderování. $(document).ready(function() { //console.log("ready"); $sun=$(".sun"); $planet1 = $("#planet1"); $planet2 = $("#planet2"); $planet3 = $("#planet3"); $planet4 = $("#planet4"); $planet9 = $("#planet9"); setPlanet($sun, sun); setPlanet($planet1, planet1); setPlanet($planet2, planet2); setPlanet($planet3, planet3); setPlanet($planet4, planet4); planets = [{$id: $planet1, data: planet1}, {$id: $planet2, data: planet2}, {$id: $planet3, data: planet3}, {$id: $planet4, data: planet4}, {$id: $planet9, data: planet9} ]; $graphics = $("#graphics"); render(); setInterval('render()',50); }); </script> <link rel="start" href="/webgame_new/www" title="Home" /> <link rel="stylesheet" media="screen,projection,tv" href="stt.css" type="text/css" /> </head> <body> <div id="envelope"> <div id="header"> <h1>Space Traffic Test Page</h1> <div style="text-align: right; margin: 0 10px 2px 10px;"> <!--<span>Czech | English</span>--></div> </div> <div id="content"> <div id="topPanel"> <div class="topbrick"><p>Space Traffic</p></div> <div class="topbrick"><p>5/8</p><p>Lodě</p></div> <div class="topbrick"><p>10/8</p><p>Základny</p></div> <div class="topbrick"><p>10/8</p><p>Zprávy</p></div> <div class="topbrick"><p>Prachy</p></div> </div> <div id="menuPanel"> <h2>Menu</h2> <ul class="mainmenu"> <li><a class="ajax" href="#">Events</a></li> <li><a class="ajax" href="#">Ships</a></li> <li><a class="ajax" href="#">Bases</a></li> <li><a class="ajax" href="#">Messages</a></li> <li><a class="ajax" href="#">Map</a></li> <li><a class="ajax" href="#">Scoreboard</a></li> <li><a class="ajax" href="#">Profile</a></li> <li><a class="ajax" href="#">Help</a></li> </ul> </div> <div id="mainPanel"> <div id="graphics"> <span id="timer"></span> <div class="crossair" ></div> <div class="sun"> </div> <div class="planet" id="planet1">1</div> <div class="planet" id="planet2">2</div> <div class="planet" id="planet3">3</div> <div class="planet" id="planet4">4</div> <div class="planet9" id="planet9"><img width="30px" height="30px" src="images/solarsystem/planets/zeme.png" ></div> <div class="orbit"></div> </div> <div id="graphics2"> </div> </div> <div id="contextPanel"> </div> </div> <div id="footer"> <p>© Space Traffic Team | <span xml:lang="cs">ZCU</span> | <span xml:lang="cs">FAV</span> | <span xml:lang="cs">KIV</span></p> <p xml:lang="cs">Sources for background images were taken by Hubble Space Telescope and published by NASA.</p> </div> </div> </body> </html>
Zpět na HomePage