Vibrating rectangles
- Task
- 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.
- Animate the colours of the rectangles by fading in the colour from the outermost rectangle to the innermost.
- The animation loop can continue for a definite number of iterations or forever.
Create Vibrating rectangles
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*/
- 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>
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
<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
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 »;
- 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)
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?
Ring
<lang ring>
- 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: