Vibrating rectangles

From Rosetta Code
Vibrating rectangles is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Create Vibrating rectangles

JavaScript

HTML you'll need for testing

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Vibrating rectangles</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            body{background-color:black;text-align:center;margin-top:150px}
        </style>
        <script src="vibRects.js"></script>
    </head>
    <body onload="start()">
        <div id='wnd'></div>
    </body>
</html>

<lang javascript> const SIZE = 400, WAIT = .025; class VibRects {

   constructor() {
       this.wait = WAIT;
       this.colorIndex = 0;
       this.dimension = 5;
       this.lastTime = 0;
       this.accumulator = 0;
       this.deltaTime = 1 / 60;
       this.colors = ["#ff0000", "#ff8000", "#ffff00", "#80ff00", "#00ff00", "#00ff80", 
                      "#00ffff", "#0080ff", "#0000ff", "#8000ff", "#ff00ff", "#ff0080"];
       this.canvas = document.createElement('canvas');
       this.canvas.width = SIZE;
       this.canvas.height = SIZE;
       const d = document.getElementById("wnd");
       d.appendChild(this.canvas);
       this.ctx = this.canvas.getContext('2d');
       for(let d = this.dimension; d < SIZE / 2; d += 10) {
           this.draw("#404040", d);
       }
   }
   draw(clr, d) {
       this.ctx.strokeStyle = clr;
       this.ctx.beginPath();
       this.ctx.moveTo(d, d);
       this.ctx.lineTo(SIZE - d, d);
       this.ctx.lineTo(SIZE - d, SIZE - d);
       this.ctx.lineTo(d, SIZE - d);
       this.ctx.closePath();
       this.ctx.stroke();
   }
   update(dt) {
       if((this.wait -= dt) < 0) {
           this.draw(this.colors[this.colorIndex], this.dimension);
           this.wait = WAIT;
           if((this.dimension += 10) > SIZE / 2) {
               this.dimension = 5;
               this.colorIndex = (this.colorIndex + 1) % this.colors.length;
           }
       }
   }
   start() {
       this.loop = (time) => {
           this.accumulator += (time - this.lastTime) / 1000;
           while(this.accumulator > this.deltaTime) {
               this.accumulator -= this.deltaTime;
               this.update(Math.min(this.deltaTime));
           }
           this.lastTime = time;
           requestAnimationFrame(this.loop);
       }
       this.loop(0);
   }

} function start() {

   const vibRects = new VibRects();
   vibRects.start();

} </lang>

Perl

Using the core module Time::HiRres to get sub-second sleep

Translation of: Perl 6

<lang perl>use utf8; binmode STDOUT, ":utf8"; use Time::HiRes qw(sleep);

%r = ('tl' => qw<┌>, 'tr' => qw<┐>, 'h' => qw<─>, 'v' => qw<│>, 'bl' => qw<└>, 'br' => qw<┘>); @colors = ("\e[1;31m", "\e[1;32m", "\e[1;33m", "\e[1;34m", "\e[1;35m", "\e[1;36m");

print "\e[?25l"; # hide the cursor

$SIG{INT} = sub { print "\e[0H\e[0J\e[?25h"; exit; }; # clean up on exit

while (1) {

   @c = palette() unless $n % 16;
   rect($_, 31-$_) for 0..15;
   display(@vibe);
   sleep .20;
   push @c, $c[0]; shift @c;
   $n++;

}

sub palette {

   my @c = sort { -1 + 2*int(rand 2) } @colors;
   ($c[0], $c[1], $c[2]) x 12;

}

sub rect {

   my ($b, $e) = @_;
   my $c = $c[$b % @c];
   my @bb = ($c.$r{tl}, (($r{h})x($e-$b-1)), $r{tr}."\e[0m");
   my @ee = ($c.$r{bl}, (($r{h})x($e-$b-1)), $r{br}."\e[0m");
   $vibe[$b][$_] = shift @bb for $b .. $e;
   $vibe[$e][$_] = shift @ee for $b .. $e;
   $vibe[$_][$b] = $vibe[$_][$e] = $c.$r{v}."\e[0m" for $b+1 .. $e-1;

}

sub display {

   my(@rect) = @_;
   print "\e[0H\e[0J\n\n";
   for my $row (@rect) {
       print "\t\t\t";
       print $_ // ' ' for @$row;
       print "\n";
   }

}</lang>

Perl 6

Works with: Rakudo version 2018.06

Ok. The task description is essentially non-existent. In looking at the reference implementation (Ring) it seems like we are supposed to draw a series of concentric rectangles and then alter the colors step-wise. No actual vibration apparent.

Could fire up a GUI but WTH, let's try it at a command line with ANSI.

Draws a series of concentric rectangles then rotates through the color palette. Every three seconds, chooses new random palette colors and reverses rotation direction.

<lang perl6># box drawing characters my %r = :tl<┌>, :h<─>, :tr<┐>, :v<│>, :bl<└>, :br<┘>;

my @colors = « \e[1;31m \e[1;94m \e[1;33m \e[1;35m \e[1;36m \e[1;32m \e[1;34m »;

  1. color palette

my @c = flat @colors[0] xx 12, @colors[3] xx 12, @colors[2] xx 12;

print "\e[?25l"; # hide the cursor

signal(SIGINT).tap: {

   print "\e[0H\e[0J\e[?25h"; # clean up on exit
   exit;

}

my $rot = 1;

my @vibe;

loop {

   rect($_, 31-$_) for ^15;
   display @vibe;
   @c.=rotate($rot);
   if ++$ %% 30 {
       @c = |@colors.pick(3);
       @c = sort(flat @c xx 12);
       $rot *= -1;
   }
   sleep .1;

}

sub rect ($b, $e) {

@vibe[$b;$b..$e] = @c[$b % @c]~%r<tl>, |((%r<h>) xx ($e - $b - 1)), %r~"\e[0m"; @vibe[$e;$b..$e] = @c[$b % @c]~%r<bl>, |((%r<h>) xx ($e - $b - 1)), %r
~"\e[0m"; ($b ^..^ $e).map: { @vibe[$_;$b] = @vibe[$_;$e] = @c[$b % @c]~%r<v>~"\e[0m" } } sub display (@rect) { print "\e[0H\e[0J\n\n"; for @rect -> @row { print "\t\t\t"; print $_ // ' ' for @row; print "\n"; } }</lang> See: Vibrating rectangles (.gif image)

Ring

<lang ring>

  1. Project : Vibrating rectangles

Load "guilib.ring"

color1 = new qcolor() { setrgb( 255,0,0,255 ) } pen1 = new qpen() { setcolor(color1) setwidth(2) }

color2 = new qcolor() { setrgb( 0,255,0,255 ) } pen2 = new qpen() { setcolor(color2) setwidth(2) }

color3 = new qcolor() { setrgb( 0,0,255,255 ) } pen3 = new qpen() { setcolor(color3) setwidth(2) }

penArray = [pen1, pen2, pen3] penNbr = 1

New qapp {

  win1 =  new qwidget()
   {
             setwindowtitle("Drawing using QPixMap")
             setgeometry(100,100,500,500)
             label1 = new qlabel(win1)
             {
                          setgeometry(10,10,500,500)
                          settext("")
             }       
             Canvas = new qlabel(win1)
            {              
                           MonaLisa = new qPixMap2( 500,500)  
                           color = new qcolor(){ setrgb(255,0,0,255) }
                          daVinci = new qpainter() 
                          {
                                        begin(MonaLisa)               
                          }            
            setpixmap(MonaLisa)         
            }       

nCounter = 0 oTimer = new qTimer(win1) { setinterval(500) settimeoutevent("DrawCounter()") start() }

      show()      
   }
  exec()

} DrawCounter()

func DrawCounter()

       nCounter++
       if nCounter < 15
          Draw(penArray[penNbr])
       elseif nCounter % 15 = 0
           nCounter = 0
           penNbr++
           if penNbr > 3
              penNbr = 1
           ok       
           Draw(penArray[penNbr])
       ok

return

Func Draw(pen1)

        daVinci.setpen(penArray[penNbr])
        daVinci.drawrect(50+nCounter*10, 50+nCounter*10, 300-nCounter*20, 300-nCounter*20)
        Canvas.setpixmap(MonaLisa)      
        win1.show()                     

return </lang> Output:

Vibrating rectangles