mgr inż. Wacław Libront * Bobowa 2017-2019

ZSO Bobowa, ul. Długoszowskich 1, 38-350 Bobowa, tel: 0183514009, fax: 0183530221, email: sekretariat@zsobobowa.eu, www: zsobobowa.eu

Lekcja 6a

Listy w JS

  1. tablice
  2. losowanie
  3. rysowanie
  4. odcinki

Obiekt - lista
Czy zwróciłeś uwagę, jak niewygodne jest operować numerami komórek, w których znajdują się konkretne zmienne: x – TK[i][0] … Ten problem da się rozwiązać za pomocą list, które zapamiętują dane pod konkretną nazwą podczas gdy tablica zapamiętywała zmienną pod konkretnym numerem.

Lista Rk={} również mieści w sobie zestaw zmiennych potrzebnych do animowania jednego kwadratu. Jednak dostęp do tych danych jest dużo wygodniejszy, bo poprzez konkretną nazwę. Rysowanie i sprawdzanie wygląda bardzo podobnie, ale o wiele łatwiej się czyta program.


Losowanie
Losowanie przebiega bardzo podobnie. Za każdym przebiegiem pętli tworzymy nowy pusty obiekt listy RK i podczas przypisywania konkretnych wartości określamy, jak ma nazywać się element listy, np. Rk.x=100;.

var ILE = 100;
var TK = [];

for (var i = 0; i < ILE; i = i + 1){
  var Rk={};
  Rk.x=losowa(100,300);
  Rk.y=losowa(100,300);
  Rk.bok=losowa(1,100);
  Rk.kat=losowa(0,45);
  Rk.kolor=LosRGBA();
  Rk.vx=losowa(-5,5);
  Rk.vy=losowa(-5,5);
  Rk.vk=losowa(-5,5);
  TK[i]=Rk;

Rysowanie i odbicia
Rysowanie i sprawdzanie wygląda bardzo podobnie, ale o wiele łatwiej się czyta program.

for (i=0;i<ILE;i=i+1){
  //rysowanie kwadratu
  kwaO(TK[i].x,TK[i].y,TK[i].bok,TK[i].kat,TK[i].kolor);
  //przesuwanie
  TK[i].x = TK[i].x + TK[i].vx;
  TK[i].y = TK[i].y + TK[i].vy;
  TK[i].kat = TK[i].kat + TK[i].vk;
  //odbicia
  if (TK[i].x > w || TK[i].x < TK[i].bok){
    TK[i].vx = -TK[i].vx; 
    TK[i].vk = -TK[i].vk;
  }
  if (TK[i].y > h || TK[i].y < TK[i].bok){
    TK[i].vy = -TK[i].vy; 
    TK[i].vk = -TK[i].vk;
  }
  if (TK[i][3]>=360){
    TK[i][3]=0;
  }
}

Cały program animacji 100 kolorowych kwadratów

<;canvas width="400" height="400" id="can"></canvas>
<script>
  var c = can.getContext("2d");

  var w = c.canvas.width;
  var h = c.canvas.height;
  var skok = 10;
  var czas;

function kwaO(xs,ys,bok,kat,kolor){
  c.save();
  c.translate(xs-bok/2,ys-bok/2);
  c.rotate(Math.PI*kat/180);
  c.fillStyle=kolor;
  c.fillRect(-bok/2,-bok/2,bok,bok);
  c.restore();
} 

function losowa(p,k) {
  return Math.round(Math.random()*(k-p)+p);
}

function LosRGBA(){
  var r = losowa(0,255);
  var g = losowa(0,255);
  var b = losowa(0,255);
  var a = Math.random();
  return "rgb("+r+","+g+","+b+","+a+")";
}
//losowanie danych początkowych
var ILE = 100;
var TK = [ILE];

for (var i = 0; i < ILE; i = i + 1){
  var Rk={};
  Rk.x=losowa(100,300);
  Rk.y=losowa(100,300);
  Rk.bok=losowa(1,100);
  Rk.kat=losowa(0,45);
  Rk.kolor=LosRGBA();
  Rk.vx=losowa(-5,5);
  Rk.vy=losowa(-5,5);
  Rk.vk=losowa(-5,5);
  TK[i]=Rk;
}

function animacja() {
  c.clearRect(0, 0, w, h);
  c.strokeRect(0, 0, w, h);

  for (i=0;i<ILE;i=i+1){
    kwaO(TK[i].x,TK[i].y,TK[i].bok,TK[i].kat,TK[i].kolor);

    TK[i].x = TK[i].x + TK[i].vx;
    TK[i].y = TK[i].y + TK[i].vy;
    TK[i].kat = TK[i].kat + TK[i].vk;

    if (TK[i].x > w || TK[i].x < TK[i].bok){
      TK[i].vx = -TK[i].vx; 
      TK[i].vk = -TK[i].vk;
    }
    
    if (TK[i].y > h || TK[i].y < TK[i].bok){
      TK[i].vy = -TK[i].vy; 
      TK[i].vk = -TK[i].vk;
    }
    
    if (TK[i][3]>=360){
      TK[i][3]=0;
    }

  clearTimeout(czas);
  czas = setTimeout(animacja, skok); 
}

animacja();
  
</script>

Odcinkowe łamańce
Z listami już mieliśmy do czynienia podczas rysowania trójkątów w lekcji 2. Funkcja ODCINEK zwracała dwie współrzędne w postaci listy. Wykorzystamy funkcję do narysowania animowanego łamańca.

Po ekranie przesuwają się i obracają cztery połączone ze sobą odcinki. Aby obliczyć położenie odcinków na końcach dłuższych ramion wykorzystaliśmy listę, którą zwraca funkcja ODCINEK. Punkt P1 i P2, to listy zawierające współrzędne – one określają początki ramion krótszych. Zwróć uwagę na sposób ich wykorzystania: współrzędna x zawarta jest na liście P1.x1 i P2.x1, a współrzędne y na liście P1.y1 i P2.y1.

function ODCINEK(x,y,bok,kat){
  var x1=x+bok*Math.cos(kat*Math.PI/180);
  var y1=y+bok*Math.sin(kat*Math.PI/180);
  c.beginPath();
  c.moveTo(x,y); c.lineTo(x1,y1);
  c.stroke();
  return {x1,y1};
}

var x=100;
var y=100;
var vx=1;
var vy=2;
var bok=50;
var kat=0;

function animacja() {
  c.clearRect(0, 0, w, h);
  c.strokeStyle="black";
  c.strokeRect(0, 0, w, h);
  //przesuwanie
  x=x+vx;
  y=y+vy;
  kat=kat+1;

  //rysowanie odcinków
  c.lineWidth=5;
  c.strokeStyle="green";
  var P1=ODCINEK(x,y,bok,kat);
  c.strokeStyle="yellow";
  var P2=ODCINEK(x,y,bok,-kat*1.5);
  c.strokeStyle="blue";
  ODCINEK(P1.x1,P1.y1,bok/2,-kat*2+45);
  c.strokeStyle="red";
  ODCINEK(P2.x1,P2.y1,bok/2,kat*3);
  
  //odbicia
  if (x<0 || x>w) vx=-vx; 
  if (y<0 || y>h) vy=-vy; 

  clearTimeout(czas);
  czas = setTimeout(animacja, skok); 
}
animacja()

Szablon

<canvas width="400" height="400" id="can"></canvas>
<script>
  var c = can.getContext("2d");

  var w = c.canvas.width;
  var h = c.canvas.height;
  var skok = 10;
  var czas;
  
function animacja() {
  c.clearRect(0, 0, w, h);
  //rysowanie i przesuwanie obiektu




  clearTimeout(czas);
  czas = setTimeout(animacja, skok); 
}

animacja();
</script>