Vibrating rectangles: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added solution for Action!)
Line 8: Line 8:
Create [https://1drv.ms/v/s!AqDUIunCqVnIg1MxKPi5DzwUbJEf Vibrating rectangles]
Create [https://1drv.ms/v/s!AqDUIunCqVnIg1MxKPi5DzwUbJEf Vibrating rectangles]
<br>
<br>

=={{header|Action!}}==
<lang Action!>PROC DrawRectangles()
BYTE i,x1,y1,x2,y2
x1=40 y1=8 x2=119 y2=87
FOR i=1 TO 20
DO
Plot(x1,y1)
DrawTo(x2,y1)
DrawTo(x2,y2)
DrawTo(x1,y2)
DrawTo(x1,y1)
x1==+2 y1==+2
x2==-2 y2==-2
OD
RETURN

PROC Main()
BYTE CH=$02FC
BYTE hue,lum

Graphics(7+16)
Color=1
DO
IF Color=1 THEN
Color=2
ELSE
Color=1
FI
hue=Rand(16)
lum=Rand(8)*2
SetColor(Color-1,hue,lum)
DrawRectangles()
UNTIL CH#$FF
OD
CH=$FF
RETURN</lang>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Vibrating_rectangles.png Screenshot from Atari 8-bit computer]


=={{header|C}}==
=={{header|C}}==

Revision as of 18:37, 3 December 2021

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.
Task
  1. Draw at least 20 rectangles with a common center, to be more precise, the circumcenter of all the rectangles must coincide. None of the rectangles must touch or intersect any other rectangle.
  2. Animate the colours of the rectangles by fading in the colour from the outermost rectangle to the innermost.
  3. The animation loop can continue for a definite number of iterations or forever.

Create Vibrating rectangles

Action!

<lang Action!>PROC DrawRectangles()

 BYTE i,x1,y1,x2,y2
 
 x1=40 y1=8 x2=119 y2=87
 FOR i=1 TO 20
 DO
   Plot(x1,y1)
   DrawTo(x2,y1)
   DrawTo(x2,y2)
   DrawTo(x1,y2)
   DrawTo(x1,y1)
   x1==+2 y1==+2
   x2==-2 y2==-2
 OD

RETURN

PROC Main()

 BYTE CH=$02FC
 BYTE hue,lum
 Graphics(7+16)
 Color=1
 DO
   IF Color=1 THEN
     Color=2
   ELSE
     Color=1
   FI
   hue=Rand(16)
   lum=Rand(8)*2
   SetColor(Color-1,hue,lum)
   DrawRectangles()
 UNTIL CH#$FF
 OD
 CH=$FF

RETURN</lang>

Output:

Screenshot from Atari 8-bit computer

C

Dimensions of the rectangles, their number and the animation delay can be configured. Requires the WinBGIm library. <lang C> /*Abhishek Ghosh, 15th September 2018*/

  1. include<graphics.h>

void vibratingRectangles(int winWidth,int winHeight,int leastLength,int leastWidth,int num, int msec) { int color = 1,i,x = winWidth/2, y = winHeight/2;

while(!kbhit()){ setcolor(color++); for(i=num;i>0;i--){ rectangle(x - i*leastLength,y - i*leastWidth,x + i*leastLength,y + i*leastWidth); delay(msec); }

if(color>MAXCOLORS){ color = 1; } } }

int main() { initwindow(1000,1000,"Vibrating Rectangles...");

vibratingRectangles(1000,1000,30,15,20,500);

closegraph();

return 0; } </lang>

EasyLang

Run it

<lang>on timer

 sz -= 2
 if sz < 0
   sz = 49
   set_color random 1000
 .
 move_pen 50 - sz 50 - sz
 draw_line 50 + sz 50 - sz
 draw_line 50 + sz 50 + sz
 draw_line 50 - sz 50 + sz
 draw_line 50 - sz 50 - sz
 set_timer 0.2

. set_timer 0.2</lang>

Factor

<lang factor>USING: accessors calendar colors.constants combinators kernel locals math math.vectors opengl timers ui ui.gadgets ui.gadgets.worlds ui.pens.solid ui.render ; IN: rosetta-code.vibrating-squares

TUPLE: vibrating < gadget

   { old-color initial: COLOR: black }
   { new-color initial: COLOR: red }
   { frame initial: 0 } ;

DEFER: on-tick

<vibrating-gadget> ( -- gadget )
   vibrating new COLOR: black <solid> >>interior COLOR: red
   >>new-color COLOR: black >>old-color dup [ on-tick ] curry f
   250 milliseconds <timer> start-timer ;

M: vibrating pref-dim* drop { 420 420 } ;

draw-squares ( loc dim n -- loc' dim' )
   [ 2dup gl-rect [ { 10 10 } v+ ] [ { -20 -20 } v+ ] bi* ]
   times ;

M:: vibrating draw-gadget* ( GADGET -- )

   GADGET frame>> 20 mod :> n
   GADGET new-color>> gl-color
   { 10 10 } { 400 400 } n draw-squares
   GADGET old-color>> gl-color
   20 n - draw-squares 2drop ;
on-tick ( GADGET -- )
   GADGET relayout-1
   GADGET [ 1 + ] change-frame frame>> 20 mod zero? [
       GADGET new-color>> GADGET old-color<<
       GADGET new-color>> {
           { COLOR: red [ COLOR: green ] }
           { COLOR: green [ COLOR: blue ] }
           [ drop COLOR: red ]
       } case GADGET new-color<<
   ] when ;

MAIN-WINDOW: vibrating-squares

   {
       { title "Vibrating Squares" }
       { window-controls
           { normal-title-bar close-button minimize-button } }
   } <vibrating-gadget> >>gadgets ;</lang>

Go

This uses Go's 'image' packages in its standard library to create an animated GIF.

When played this is somewhat similar to the Python entry except that it uses a 7 (rather than 6) color palette and repeats indefinitely.

Although the .gif works fine in Firefox it might not do so in EOG due to optimizations made during its creation. If so, then the following ImageMagick command should fix it:

  $ convert vibrating.gif -coalesce vibrating2.gif
  $ eog vibrating2.gif

<lang go>package main

import (

   "image"
   "image/color"
   "image/gif"
   "log"
   "os"

)

var (

   black   = color.RGBA{0, 0, 0, 255}
   red     = color.RGBA{255, 0, 0, 255}
   green   = color.RGBA{0, 255, 0, 255}
   blue    = color.RGBA{0, 0, 255, 255}
   magenta = color.RGBA{255, 0, 255, 255}
   cyan    = color.RGBA{0, 255, 255, 255}
   yellow  = color.RGBA{255, 255, 0, 255}
   white   = color.RGBA{255, 255, 255, 255}

)

var palette = []color.Color{red, green, blue, magenta, cyan, yellow, white, black}

func hline(img *image.Paletted, x1, y, x2 int, ci uint8) {

   for ; x1 <= x2; x1++ {
       img.SetColorIndex(x1, y, ci)
   }

}

func vline(img *image.Paletted, x, y1, y2 int, ci uint8) {

   for ; y1 <= y2; y1++ {
       img.SetColorIndex(x, y1, ci)
   }

}

func setBackgroundColor(img *image.Paletted, w, h int, ci uint8) {

   for x := 0; x < w; x++ {
       for y := 0; y < h; y++ {
           img.SetColorIndex(x, y, ci)
       }
   }

}

func drawRectangle(img *image.Paletted, x1, y1, x2, y2 int, ci uint8) {

   hline(img, x1, y1, x2, ci)
   hline(img, x1, y2, x2, ci)
   vline(img, x1, y1, y2, ci)
   vline(img, x2, y1, y2, ci)

}

func main() {

   const nframes = 140
   const delay = 10 // 100ms
   width, height := 500, 500
   anim := gif.GIF{LoopCount: nframes}
   rect := image.Rect(0, 0, width, height)
   for c := uint8(0); c < 7; c++ {
       for f := 0; f < 20; f++ {
           img := image.NewPaletted(rect, palette)
           setBackgroundColor(img, width, height, 7) // black background
           for r := 0; r < 20; r++ {
               ix := c
               if r < f {
                   ix = (ix + 1) % 7
               }
               x := width * (r + 1) / 50
               y := height * (r + 1) / 50
               w := width - x
               h := height - y
               drawRectangle(img, x, y, w, h, ix)
           }
           anim.Delay = append(anim.Delay, delay)
           anim.Image = append(anim.Image, img)
       }
   }
   file, err := os.Create("vibrating.gif")
   if err != nil {
       log.Fatal(err)
   }
   defer file.Close() 
   if err2 := gif.EncodeAll(file, &anim); err != nil {
       log.Fatal(err2)
   }   

}</lang>

J

   NB. warning: overwrites /tmp/10[0-3][0-9].jpg
   NB.          and        /tmp/r.gif

   NB. uses imagemagic convert and a browser to display the animation.
   NB. works on linux

   NB. https://rosettacode.org/wiki/Ulam_spiral_(for_primes)#J

   require'jpeg'

   spiral =: ,~ $ [: /: }.@(2 # >:@i.@-) +/\@# <:@+: $ (, -)@(1&,)
   ulamspiral =: *: - spiral

   NB. Corners are the squares of every other odd number.
   NB. Rectangles ulams with first column < and <: second column of CORNERS
   [CORNERS=: *: 1 2 p. i. _20 2
5929 6241
5329 5625
4761 5041
4225 4489
3721 3969
3249 3481
2809 3025
2401 2601
2025 2209
1681 1849
1369 1521
1089 1225
 841  961
 625  729
 441  529
 289  361
 169  225
  81  121
  25   49
   1    9
   

   NB. S is a sufficiently large Ulam spiral matrix
   S=: ulamspiral 81
   
   NB. A are 20 Boolean bitmaps of squares
   A =: CORNERS ((> {.)~ *. (<: {:)~)"1 _ S
   
   NB. B is a bitmap of all the squares
   B =: +/ A

   NB. C is a running sum.  first 6 upper left corners shown
   <"2 ] 6 10 10 {. C =: B +"2 +/\ A
┌───────────────────┬───────────────────┬───────────────────┬───────────────────┬───────────────────┬───────────────────┐
│0 0 0 0 0 0 0 0 0 0│0 0 0 0 0 0 0 0 0 0│0 0 0 0 0 0 0 0 0 0│0 0 0 0 0 0 0 0 0 0│0 0 0 0 0 0 0 0 0 0│0 0 0 0 0 0 0 0 0 0│
│0 2 2 2 2 2 2 2 2 2│0 2 2 2 2 2 2 2 2 2│0 2 2 2 2 2 2 2 2 2│0 2 2 2 2 2 2 2 2 2│0 2 2 2 2 2 2 2 2 2│0 2 2 2 2 2 2 2 2 2│
│0 2 0 0 0 0 0 0 0 0│0 2 0 0 0 0 0 0 0 0│0 2 0 0 0 0 0 0 0 0│0 2 0 0 0 0 0 0 0 0│0 2 0 0 0 0 0 0 0 0│0 2 0 0 0 0 0 0 0 0│
│0 2 0 1 1 1 1 1 1 1│0 2 0 2 2 2 2 2 2 2│0 2 0 2 2 2 2 2 2 2│0 2 0 2 2 2 2 2 2 2│0 2 0 2 2 2 2 2 2 2│0 2 0 2 2 2 2 2 2 2│
│0 2 0 1 0 0 0 0 0 0│0 2 0 2 0 0 0 0 0 0│0 2 0 2 0 0 0 0 0 0│0 2 0 2 0 0 0 0 0 0│0 2 0 2 0 0 0 0 0 0│0 2 0 2 0 0 0 0 0 0│
│0 2 0 1 0 1 1 1 1 1│0 2 0 2 0 1 1 1 1 1│0 2 0 2 0 2 2 2 2 2│0 2 0 2 0 2 2 2 2 2│0 2 0 2 0 2 2 2 2 2│0 2 0 2 0 2 2 2 2 2│
│0 2 0 1 0 1 0 0 0 0│0 2 0 2 0 1 0 0 0 0│0 2 0 2 0 2 0 0 0 0│0 2 0 2 0 2 0 0 0 0│0 2 0 2 0 2 0 0 0 0│0 2 0 2 0 2 0 0 0 0│
│0 2 0 1 0 1 0 1 1 1│0 2 0 2 0 1 0 1 1 1│0 2 0 2 0 2 0 1 1 1│0 2 0 2 0 2 0 2 2 2│0 2 0 2 0 2 0 2 2 2│0 2 0 2 0 2 0 2 2 2│
│0 2 0 1 0 1 0 1 0 0│0 2 0 2 0 1 0 1 0 0│0 2 0 2 0 2 0 1 0 0│0 2 0 2 0 2 0 2 0 0│0 2 0 2 0 2 0 2 0 0│0 2 0 2 0 2 0 2 0 0│
│0 2 0 1 0 1 0 1 0 1│0 2 0 2 0 1 0 1 0 1│0 2 0 2 0 2 0 1 0 1│0 2 0 2 0 2 0 2 0 1│0 2 0 2 0 2 0 2 0 2│0 2 0 2 0 2 0 2 0 2│
└───────────────────┴───────────────────┴───────────────────┴───────────────────┴───────────────────┴───────────────────┘

   NB. D is C catenated to itself with the ones and twos swapped.
   D=: (, ]`(0,2,:1"0)}) C

   NB. E is the 40 matrices with ID, in 3 levels
   E=: (;"2 0 (1000 + i.@#))@:(*&16b301070) D

   NB. overwrite the files then get some help from the shell
   empty@:(writejpeg('.jpg' ,~ '/tmp/' , ":))&>/"1 E
   2!:0'convert -resize 600%  /tmp/10[0-3][0-9].jpg -delay 10 -loop 0 /tmp/r.gif'

   echo 'please view the animation /tmp/r.gif in chrome browser'

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>

Julia

<lang julia>using Gtk, Graphics, Colors

const height, width, x0, y0 = 480, 640, 320, 240 const can = @GtkCanvas() const win = GtkWindow(can, "Vibrating Rectangles", width, height) const colrs = colormap("rdBu") const sizes = collect(2:4:div(width, 2)) const params = [1, 2]

draw(can) do widget

   ctx = getgc(can)
   set_line_width(ctx, 1)
   c = colrs[params[1]]
   set_source_rgb(ctx, c.r, c.g, c.b)
   i = sizes[params[2]]
   rectangle(ctx, x0 - i, y0 - i, 2i, div(8i, 3))
   stroke(ctx)

end

while true

   params[1] = params[1] % 99 + 1
   params[2] = params[2] % (length(sizes) - 1) + 1
   draw(can)
   show(can)
   sleep(0.25)

end </lang>

Nim

Library: gintro

Should work on any platform where Gtk is available. Tested on Linux. <lang Nim>import sugar

import gintro/[gobject, gdk, gtk, gio, cairo] import gintro/glib except Pi

const

 Width = 640
 Height = 480
 X0 = Width div 2 - 1
 Y0 = Height div 2 - 1
 Colors = [(0.0, 0.0, 0.0), (255.0, 0.0, 0.0), (0.0, 255.0, 0.0), (0.0, 0.0, 255.0),
           (255.0, 0.0, 255.0), (0.0, 255.0, 255.0), (255.0, 255.0, 0.0), (255.0, 255.0, 255.0)]
 Sizes = collect(newSeq, for size in countdown(Width, 4, 16): float(size))

type

 # Description of the simulation.
 Simulation = ref object
   area: DrawingArea       # Drawing area.
   isize: Natural          # Size index.
   icolor: Natural         # Color index.
  1. ---------------------------------------------------------------------------------------------------

proc newSimulation(area: DrawingArea): Simulation =

 ## Allocate and initialize the simulation object.
 new(result)
 result.area = area
 result.isize = 0
  1. ---------------------------------------------------------------------------------------------------

proc draw(sim: Simulation; context: cairo.Context) =

 ## Draw the rectangles.
 context.setSource(Colors[sim.icolor])
 let width = Sizes[sim.isize]
 let height = width * 3 / 4
 context.rectangle(X0 - width * 0.5, Y0 - height * 0.5, width, height)
 context.stroke()
  1. ---------------------------------------------------------------------------------------------------

proc update(sim: Simulation): gboolean =

 ## Update the simulation state.
 sim.isize = (sim.isize + 1) mod Sizes.len
 if sim.isize == 0:
   # Change color for next cycle.
   sim.icolor = (sim.icolor + 1) mod Colors.len
 sim.draw(sim.area.window.cairoCreate())
 result = gboolean(1)
  1. ---------------------------------------------------------------------------------------------------

proc activate(app: Application) =

 ## Activate the application.
 let window = app.newApplicationWindow()
 window.setSizeRequest(Width, Height)
 window.setTitle("Vibrating rectangles")
 let area = newDrawingArea()
 window.add(area)
 let sim = newSimulation(area)
 timeoutAdd(40, update, sim)
 window.showAll()
  1. ———————————————————————————————————————————————————————————————————————————————————————————————————

let app = newApplication(Application, "Rosetta.vibrating_rectangles") discard app.connect("activate", activate) discard app.run()</lang>

Objeck

Uses SLD2 libraries and 80's neon colors. <lang objeck>use Game.SDL2; use Game.Framework;

class Vibrating {

 @framework : GameFramework;
 @rec_offset : Int;
 @rec_colors : Color[];
 @rec_color_index : Int;
 function : Main(args : String[]) ~ Nil {
   vibrating := Vibrating->New();
   vibrating->Run();
 }
 New() {
   @framework := GameFramework->New(GameConsts->SCREEN_WIDTH, GameConsts->SCREEN_HEIGHT, "Vibrating Rectangles");
   @framework->SetClearColor(Color->New(0, 0, 0));
   @rec_colors := Color->New[5];
   @rec_colors[0] := Color->New(255, 240, 1); 
   @rec_colors[1] := Color->New(253, 25, 153); 
   @rec_colors[2] := Color->New(153, 252, 32);  
   @rec_colors[3] := Color->New(0, 230, 254);
   @rec_colors[4] := Color->New(161, 14, 236);
 }
 
 method : Run() ~ Nil {
   if(@framework->IsOk()) {
     e := @framework->GetEvent();
     
     frame_count := 0;
     quit := false;
     while(<>quit) {
       @framework->FrameStart();
       
       # process input
       while(e->Poll() <> 0) {
         if(e->GetType() = EventType->SDL_QUIT) {
           quit := true;
         };
       };
       Render(frame_count);
       @framework->FrameEnd();
       frame_count += 1;
       if(frame_count >= @framework->GetFps()) {
         frame_count := 0;
       };
     };
   }
   else {
     "--- Error Initializing Environment ---"->ErrorLine();
     return;
   };
   leaving {
     @framework->Quit();
   };
 }
 method : Render(frame_count : Int) ~ Nil {
   # rectangle offsets
   if(frame_count % GameConsts->REC_REFRESH = 0) {
     @rec_offset += 1;
     if(@rec_offset >= GameConsts->REC_MAX) {
       @rec_offset := 0;
       @rec_color_index += 1;
     };
   };
   # rectangle colors
   first_color := @rec_colors[@rec_color_index];
   second_color : Color;
   if(@rec_color_index + 1 < @rec_colors->Size()) {
     second_color := @rec_colors[@rec_color_index + 1];
   }
   else {
     second_color := @rec_colors[0];
     @rec_color_index := 0;
   };
   @framework->Clear();
   for(i := 1; i < GameConsts->REC_MAX; i += 1;) {
     if(i < @rec_offset) {
       DrawRectangle(i, first_color);
     }
     else {
       DrawRectangle(i, second_color);
     };
   };
   @framework->Show();
 }
 method : DrawRectangle(step : Int, color : Color) ~ Nil {
   x := step * GameConsts->REC_DIST; w := GameConsts->SCREEN_WIDTH - x * 2;
   y := step * GameConsts->REC_DIST; h := GameConsts->SCREEN_HEIGHT - y * 2;
   renderer := @framework->GetRenderer();
   renderer->SetDrawColor(color->GetR(), color->GetG(), color->GetB(), 0);
   renderer->DrawRect(Rect->New(x, y, w, h));
   renderer->DrawRect(Rect->New(x + 1, y + 1, w - 2, h - 2));
   renderer->DrawRect(Rect->New(x + 2, y + 2, w - 4, h - 4));
 }

}

consts GameConsts {

 SCREEN_WIDTH := 640,
 SCREEN_HEIGHT := 480,
 REC_DIST := 12,
 REC_MAX := 20,
 REC_REFRESH := 15

} </lang>

Perl

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

Translation of: Raku

<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>

Phix

Library: Phix/pGUI

<lang Phix>-- demo\rosetta\vibrect.exw -- -- Draws concentric rectangles in random colours to simulate vibration. -- Press +/- to increase/decrease the number of rectangles being drawn. -- Resizing the window, as it turns out, achieves much the same effect -- as +/-, only much quicker (by increasing/decreasing the spacing). -- integer numrects = 125 -- (max non-touching for a height of 500)

include pGUI.e

Ihandle dlg, canvas cdCanvas cddbuffer, cdcanvas

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)

   integer {w,h} = IupGetIntInt(canvas, "DRAWSIZE")
   atom dw = w/(numrects*2+1),
        dh = h/(numrects*2+1)
   cdCanvasActivate(cddbuffer)
   for i=1 to numrects do
       cdCanvasSetForeground(cddbuffer,rand(#FFFFFF))
       atom wd = i*dw,
            hd = i*dh
       cdCanvasRect(cddbuffer, wd, w-wd, hd, h-hd) 
   end for 
   cdCanvasFlush(cddbuffer)
   return IUP_DEFAULT

end function

function map_cb(Ihandle ih)

   cdcanvas = cdCreateCanvas(CD_IUP, ih)
   cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
   cdCanvasSetBackground(cddbuffer, CD_WHITE)
   cdCanvasSetForeground(cddbuffer, CD_BLACK)
   return IUP_DEFAULT

end function

function timer_cb(Ihandle /*ih*/)

   IupUpdate(canvas)
   return IUP_IGNORE

end function

function esc_close(Ihandle /*ih*/, atom c)

   if c=K_ESC then return IUP_CLOSE end if
   if c='+' or (c='-' and numrects>3) then
       numrects -= c-','
       cdCanvasClear(cddbuffer)
       IupUpdate(canvas)
   end if
   return IUP_CONTINUE

end function

procedure main()

   IupOpen()
   
   canvas = IupCanvas(NULL)
   IupSetAttribute(canvas, "RASTERSIZE", "602x502") -- initial size
   IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
   dlg = IupDialog(canvas)
   IupSetAttribute(dlg, "TITLE", "Vibrating Rectangles")
   IupSetCallback(dlg, "K_ANY",     Icallback("esc_close"))
   IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
   IupMap(dlg)
   IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation
   IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
   Ihandle timer = IupTimer(Icallback("timer_cb"), 40)
   IupMainLoop()
   IupClose()

end procedure main()</lang>

Python

<lang python>import turtle from itertools import cycle from time import sleep

def rect(t, x, y):

   x2, y2 = x/2, y/2
   t.setpos(-x2, -y2)
   t.pendown()
   for pos in [(-x2, y2), (x2, y2), (x2, -y2), (-x2, -y2)]: 
       t.goto(pos)
   t.penup()

def rects(t, colour, wait_between_rect=0.1):

   for x in range(550, 0, -25):
       t.color(colour)
       rect(t, x, x*.75)
       sleep(wait_between_rect)

tl=turtle.Turtle() screen=turtle.Screen() screen.setup(620,620) screen.bgcolor('black') screen.title('Rosetta Code Vibrating Rectangles') tl.pensize(3) tl.speed(0) tl.penup() tl.ht() colours = 'red green blue orange white yellow'.split() for colour in cycle(colours):

   rects(tl, colour)
   sleep(0.5)

</lang>

Output:

Hmm, maybe this?

Racket

Via big-bang.

<lang racket>#lang racket

(require 2htdp/image

        2htdp/universe)

(define N 20) (define SIZE 400) (define OFFSET 80) (define RATE 0.2)

a state is a pair of color index and position

(define colors '(red orange yellow green blue indigo violet)) (define (mod x) (modulo x (length colors)))

(big-bang (cons 0 (sub1 N))

 [on-tick
  (match-lambda
    [(cons m 0) (cons (mod (add1 m)) (sub1 N))]
    [(cons m n) (cons m (sub1 n))])
  RATE]
 [to-draw
  (match-lambda
    [(cons m n) 
     (apply
      overlay
      (append
       (for/list ([i (in-range N 0 -1)])
         (square (* i (/ (- SIZE OFFSET) N))
                 'outline
                 (if (> i n)
                     (list-ref colors (mod (add1 m)))
                     (list-ref colors m))))
       (list (empty-scene SIZE SIZE 'black))))])])</lang>

Raku

(formerly Perl 6)

Works with: Rakudo version 2018.06

ANSI graphics

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)

SDL Animation

Fully animated SDL2 graphics lib version. Will adjust rendered rectangles to fill resized windows. Hit the space bar to toggle palette rotation direction.

<lang perl6>use SDL2::Raw;

my $width = 1200; my $height = 800;

SDL_Init(VIDEO);

my $window = SDL_CreateWindow(

   'Vibrating rectangles',
   SDL_WINDOWPOS_CENTERED_MASK,
   SDL_WINDOWPOS_CENTERED_MASK,
   $width, $height,
   RESIZABLE

);

my $render = SDL_CreateRenderer($window, -1, ACCELERATED +| PRESENTVSYNC);

my $event = SDL_Event.new;

enum KEY_CODES (

   K_SPACE  => 44,

);

my $num = 80; my @rgb = palette($num); my ($cx, $cy); my $dir = 1;

main: loop {

   while SDL_PollEvent($event) {
       my $casted_event = SDL_CastEvent($event);
       given $casted_event {
           when *.type == QUIT { last main }
           when *.type == WINDOWEVENT {
               if .event == 5 {
                   $width  = .data1;
                   $height = .data2;
               }
           }
           when *.type == KEYDOWN {
               if KEY_CODES(.scancode) -> $comm {
                   given $comm {
                       when 'K_SPACE'  { $dir *= -1; }
                   }
               }
               #say .scancode; # unknown key pressed
           }
       }
   }
   ($cx, $cy) = $width div 2, $height div 2;
   for 1..^$num {
       my ($x, $y) = ($cx - ($width/2/$num*$_), $cy - ($height/2/$num*$_))».round;
       my ($w, $h) = ($width/$num*$_, $height/$num*$_)».round;
       SDL_SetRenderDrawColor($render, |@rgb[$_], 255);
       SDL_RenderDrawRect($render, SDL_Rect.new(:x($x), :y($y), :w($w), :h($h)));
   }
   @rgb.=rotate($dir);
   SDL_RenderPresent($render);
   SDL_SetRenderDrawColor($render, 0, 0, 0, 0);
   SDL_RenderClear($render);

}

SDL_Quit();

sub palette ($l) { (^$l).map: { hsv2rgb(($_ * 360/$l % 360)/360, 1, 1).list } };

sub hsv2rgb ( $h, $s, $v ){ # inputs normalized 0-1

   my $c = $v * $s;
   my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
   my $m = $v - $c;
   my ($r, $g, $b) = do given $h {
       when   0..^(1/6) { $c, $x, 0 }
       when 1/6..^(1/3) { $x, $c, 0 }
       when 1/3..^(1/2) { 0, $c, $x }
       when 1/2..^(2/3) { 0, $x, $c }
       when 2/3..^(5/6) { $x, 0, $c }
       when 5/6..1      { $c, 0, $x }
   }
   ( $r, $g, $b ).map: ((*+$m) * 255).Int

}</lang>

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

Wren

Library: DOME

<lang ecmascript>import "graphics" for Canvas, Color import "dome" for Window

var Palette = [

   Color.red, Color.green, Color.blue, Color.orange,
   Color.indigo, Color.pink, Color.yellow, Color.white

]

class VibratingRectangles {

   construct new(width, height) {
       Window.title = "Vibrating Rectangles"
       Window.resize(width, height)
       Canvas.resize(width, height)
       _w = width
       _h = height
   }
   init() {
       _c = 0
       _r = 0
       _frame = 0
   }
   update() {
       _frame = _frame + 1
       if (_frame == 60) _frame = 0
       if (_frame % 15 == 0) {
           _r = _r + 1
           if (_r > 20) {
               _r = 0
               _c = (_c + 1) % 8
           }
       }
   }
   draw(alpha) {
       var x = (_w * (_r + 1) / 50).floor
       var y = (_h * (_r + 1) / 50).floor
       var w = _w - 2 * x
       var h = _h - 2 * y
       Canvas.rect(x, y, w, h, Palette[_c])        
   }

}

var Game = VibratingRectangles.new(500, 500)</lang>

X86 Assembly

<lang asm> 1 ;Tanslation of XPL0 and EasyLang. A 75-byte program.

     2                                  ;Assemble with: tasm, tlink /t
     3     0000                                 .model  tiny
     4     0000                                 .code
     5                                          .386
     6                                          org     100h
     7                                  ;assume: ax=0, bx=0, cx=00FFh, bp=09??h, direction flag is clear
     8
     9     0100  B0 13                  start:  mov     al, 13h         ;set 320x200x8 graphics mode
    10     0102  CD 10                          int     10h
    11     0104  68 A000                        push    0A000h          ;set segment register to graphics memory
    12     0107  07                             pop     es
    13
    14                                  ;ax = misc, color
    15                                  ;bx = size
    16                                  ;cx = loop counter
    17                                  ;dx = delay
    18                                  ;si = direction
    19                                  ;di = pen location
    20                                  ;bp = color
    21
    22     0108  B4 86                  main:   mov     ah, 86h         ;delay 0.2 seconds
    23     010A  B1 03                          mov     cl, 3           ;200000 = 30D40h; (ch=0)
    24     010C  BA 0D40                        mov     dx, 0D40h
    25     010F  CD 15                          int     15h
    26
    27     0111  80 EB 02                       sub     bl, 2           ;Size:= Size - 2
    28     0114  7D 06                          jge     draw            ;if Size < 0 then
    29     0116  B3 31                           mov    bl, 49          ;  Size:= 49
    30     0118  0F AF EB                        imul   bp, bx          ;color:= Random; (bh=0)
    31     011B  45                              inc    bp
    32     011C                         draw:                           ;Move(50-Size, 50-Size)
    33     011C  69 FB FEBF                     imul    di, bx, -321    ;di:= 50-Size + (50-Size)*320
    34     0120  81 C7 3EB2                     add     di, 50*321      ;di:= (50-Size)*321
    35                                                                  ;di:= Size*-321 + 50*321
    36     0124  BE 0006                        mov     si, 3*2         ;set index for dir table
    37     0127  8B C5                          mov     ax, bp          ;Line(50-Size, 50+Size, Color);
    38     0129  6B CB 02               lin20:  imul    cx, bx, 2       ;length = Size*2
    39     012C  AA                     lin30:  stosb                   ;es:[di++]:= al
    40     012D  03 BC 0143r                    add     di, [si+dir]    ;next pixel position
    41     0131  E2 F9                          loop    lin30           ;cx--
    42     0133  4E                             dec     si
    43     0134  4E                             dec     si
    44     0135  79 F2                          jns     lin20
    45
    46     0137  B4 01                          mov     ah, 01h         ;loop until keystroke
    47     0139  CD 16                          int     16h
    48     013B  74 CB                          jz      main
    49
    50     013D  B8 0003                        mov     ax, 0003h       ;restore normal text-mode screen
    51     0140  CD 10                          int     10h
    52     0142  C3                             ret                     ;return to DOS
    53
    54     0143  FEBF FFFE 013F 0000    dir     dw      -320-1, -1-1, 320-1, 1-1 ;directions: up, right, down, left
    55                                          end     start

</lang>

XPL0

Translation of EasyLang. <lang XPL0>int Sz, Color;

proc OnTimer; [Sz:= Sz - 2; if Sz < 0 then

   [Sz:= 49;
   Color:= Ran(256);
   ];

Move(50-Sz, 50-Sz); Line(50+Sz, 50-Sz, Color); Line(50+Sz, 50+Sz, Color); Line(50-Sz, 50+Sz, Color); Line(50-Sz, 50-Sz, Color); ];

[SetVid($13); \set video to VGA 320x200 in 256 colors Sz:= 0; repeat DelayUS(200_000);

       OnTimer;

until KeyHit; ]</lang>