Tạo một hình ảnh động ảo ảnh vòng tròn


84

Công việc của bạn là làm sinh động ảo ảnh vòng tròn này . Trông giống như các điểm quay bên trong vòng tròn, nhưng thực ra chúng chỉ đang di chuyển theo đường thẳng.

nhập mô tả hình ảnh ở đây

Tiêu chí

  • Kết quả phải được hoạt hình. Cách bạn làm hoạt hình là không liên quan, nó có thể tạo ra một .gif, nó có thể vẽ vào một cửa sổ, một số màn hình thiết bị hoặc bất cứ điều gì.
  • Đây là một cuộc thi phổ biến, vì vậy bạn có thể muốn thêm một số tính năng bổ sung vào chương trình của mình để nhận được nhiều lượt nâng cấp hơn, ví dụ như thay đổi số điểm.
  • Người chiến thắng là câu trả lời hợp lệ được đánh giá cao nhất 7 ngày sau lần gửi hợp lệ cuối cùng.
  • Các câu trả lời thực sự sẽ thực hiện các điểm di chuyển trên các đường thẳng và không có cách nào khác được hoan nghênh hơn

"Người chiến thắng là người có giá trị cao nhất sau 7 ngày". Vì vậy, nếu ai đó đăng một cái gì đó cứ sau 6 ngày cho đến khi các ngôi sao chết, chúng ta không có người chiến thắng?
Kevin L

3
@KevinL điều đó khó có thể xảy ra và tôi không nghĩ 15 đại diện thêm đó quan trọng so với tất cả các ưu đãi bạn nhận được từ câu hỏi này được đưa lên đầu mỗi 6 ngày.
Martin Ender

1
Đôi khi tôi tự hỏi liệu một số người làm những việc này chỉ để hoàn thành công việc ...
Daniel Pendergast

3
"Trông giống như các điểm quay bên trong vòng tròn, nhưng thực ra chúng chỉ đang di chuyển theo đường thẳng.", Hoặc, có lẽ chúng thực sự đang quay bên trong một vòng tròn và dường như di chuyển theo đường thẳng ...
coredump

1
Không thể .. lấy hình ảnh động này .. ra khỏi tâm trí của tôi .. đặc biệt là phiên bản 3 điểm!
Thomas

Câu trả lời:


126

Con trăn 3,4

Sử dụng mô-đun rùa. Những con rùa có màu sắc khác nhau và chúng luôn phải đối mặt theo cùng một hướng, vì vậy chúng có thể dễ dàng được nhìn thấy đang di chuyển dọc theo các đường thẳng bằng cách chỉ tập trung vào một trong số chúng. Mặc dù vậy, ảo ảnh vòng tròn vẫn mạnh mẽ.

11 con rùa

Ảo ảnh vẫn có vẻ khá mạnh ngay cả khi chỉ có 3 hoặc 4 con rùa:

3 con rùa4 con rùa

Tốc độ khung hình được giảm đáng kể cho tất cả các ví dụ GIF này, nhưng dường như nó không làm mất đi ảo ảnh. Chạy mã cục bộ cho hình ảnh động mượt mà hơn.

import turtle
import time
from math import sin, pi
from random import random


def circle_dance(population=11, resolution=480, loops=1, flip=0, lines=0):
    population = int(population)
    resolution = int(resolution)
    radius = 250
    screen = turtle.Screen()
    screen.tracer(0)
    if lines:
        arrange_lines(population, radius)
    turtles = [turtle.Turtle() for i in range(population)]
    for i in range(population):
        dancer = turtles[i]
        make_dancer(dancer, i, population)
    animate(turtles, resolution, screen, loops, flip, radius)


def arrange_lines(population, radius):
    artist = turtle.Turtle()
    for n in range(population):
        artist.penup()
        artist.setposition(0, 0)
        artist.setheading(n / population * 180)
        artist.forward(-radius)
        artist.pendown()
        artist.forward(radius * 2)
    artist.hideturtle()


def make_dancer(dancer, i, population):
    dancer.setheading(i / population * 180)
    dancer.color(random_turtle_colour())
    dancer.penup()
    dancer.shape('turtle')
    dancer.turtlesize(2)


def random_turtle_colour():
    return random() * 0.9, 0.5 + random() * 0.5, random() * 0.7


def animate(turtles, resolution, screen, loops, flip, radius):
    delay = 4 / resolution      # 4 seconds per repetition
    while True:
        for step in range(resolution):
            timer = time.perf_counter()
            phase = step / resolution * 2 * pi
            draw_dancers(turtles, phase, screen, loops, flip, radius)
            elapsed = time.perf_counter() - timer
            adjusted_delay = max(0, delay - elapsed)
            time.sleep(adjusted_delay)


def draw_dancers(turtles, phase, screen, loops, flip, radius):
    population = len(turtles)
    for i in range(population):
        individual_phase = (phase + i / population * loops * pi) % (2*pi)
        dancer = turtles[i]
        if flip:
            if pi / 2 < individual_phase <= 3 * pi / 2:
                dancer.settiltangle(180)
            else:
                dancer.settiltangle(0)
        distance = radius * sin(individual_phase)
        dancer.setposition(0, 0)
        dancer.forward(distance)
    screen.update()


if __name__ == '__main__':
    import sys
    circle_dance(*(float(n) for n in sys.argv[1:]))

Để tương phản ở đây là một số thực sự xoay:

Rùa 23 vòng23 con rùa

... Hay họ?

Mã có thể được chạy với 5 đối số tùy chọn: dân số, độ phân giải, vòng lặp, lật và dòng.

  • population là số lượng rùa
  • resolution là độ phân giải thời gian (số khung hình động trên mỗi lần lặp lại)
  • loopsxác định số lần rùa tự lặp lại. Mặc định là 1 cho một vòng tròn tiêu chuẩn, các số lẻ khác cho số vòng lặp đó trong chuỗi rùa, trong khi các số chẵn cho một chuỗi rùa bị ngắt ở hai đầu, nhưng vẫn có ảo giác về chuyển động cong.
  • flipnếu khác không làm cho rùa lật hướng cho chuyến trở về của chúng (như được đề xuất bởi aslum để chúng không bao giờ di chuyển ngược). Theo mặc định, họ giữ một hướng cố định để tránh sự phân tâm thị giác ở các điểm cuối.
  • lines nếu khác không hiển thị các dòng mà rùa di chuyển, để thống nhất với hình ảnh ví dụ trong câu hỏi.

Ví dụ với fliptập hợp, có và không có lines. Tôi đã để lại ví dụ chính của mình ở trên mà không lật vì tôi không muốn có bước nhảy lẻ tẻ, nhưng cạnh của vòng tròn trông mượt mà hơn với tất cả các con rùa được căn chỉnh, vì vậy tùy chọn là có cho mọi người chọn kiểu nào họ thích khi chạy mật mã.

11 con rùa với lật và dòng11 con rùa có lật

Có thể không rõ ràng ngay lập tức làm thế nào những hình ảnh trên được tạo ra từ cùng một mã này. Cụ thể là hình ảnh xa hơn có vòng ngoài chậm và vòng trong nhanh (hình trông giống như một cardioid mà ai đó vô tình làm rơi). Tôi đã ẩn lời giải thích này dưới đây trong trường hợp bất kỳ ai muốn trì hoãn việc tìm hiểu trong khi thử nghiệm / suy nghĩ.

Hoạt hình với một vòng lặp bên trong và bên ngoài có kích thước khác nhau đã được tạo bằng cách đặt số vòng lặp thành 15 và để số rùa ở mức 23 (quá thấp để thể hiện 15 vòng). Sử dụng một số lượng lớn rùa sẽ dẫn đến 15 vòng được xác định rõ ràng. Sử dụng quá ít rùa dẫn đến răng cưa (vì lý do tương tự như trong xử lý và kết xuất hình ảnh). Cố gắng biểu thị tần số quá cao dẫn đến tần số thấp hơn được hiển thị, với độ méo.

Thử các số khác nhau tôi thấy một số biến dạng này thú vị hơn các bản gốc đối xứng hơn, vì vậy tôi muốn đưa vào một số ở đây ...


18
Tôi thích rùa.
FreeAsInBeer

18
Tôi bóc ra +1 cho rùa
MrEngineer13

@ProgramFOX cảm ơn vì đã đánh dấu cú pháp! Tôi đã tìm kiếm thông qua trợ giúp và meta và tự thuyết phục bản thân rằng chúng tôi không có cú pháp tô sáng trên mã golf - bây giờ tôi rất vui hơn với điều này.
trichoplax

1
@aslum đó sẽ là một thay đổi đơn giản để thực hiện, nhưng tôi muốn định hướng của họ bị đóng băng để thực sự nhấn mạnh rằng họ không đi chệch khỏi đường thẳng của họ. Có lẽ tôi nên thêm nó vào mã dưới dạng tùy chọn để mọi người có thể chọn cách tiếp cận họ thích.
trichoplax

4
+1 - Thật tuyệt vời khi thấy một ban nhạc diễu hành làm một vài trong số những người vui tính này!
mkoistinen

96

C

Kết quả:

nhập mô tả hình ảnh ở đây

#include <stdio.h>
#include <Windows.h>
#include <Math.h>

int round (double r) { return (r > 0.0) ? (r + 0.5) : (r - 0.5); }
void print (int x, int y, char c) {
    COORD p = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p);
    printf("%c", c);
}

int main ()
{
    float pi = 3.14159265358979323846;
    float circle = pi * 2;
    int len = 12;
    int hlen = len / 2;
    int cx = 13;
    int cy = 8;
    float w = 11.0;
    float h =  8.0;
    float step = 0.0;

    while (1)
    {
        system("cls"); // xD

        for (int i = 0; i < len; i++)
        {
            float a = (i / (float)len) * circle;
            int x = cx + round(cos(a) * w);
            int y = cy + round(sin(a) * h);
            print(x, y, 'O');

            if (i < hlen) continue;

            step -= 0.05;
            float range = cos(a + step);
            x = cx + round(cos(a) * (w - 1) * range);
            y = cy + round(sin(a) * (h - 1) * range);
            print(x, y, 'O');
        }

        Sleep(100);
    }

    return 0;
}

3
Trong một số khung hình, nó hơi bị tắt. Nhưng chúc mừng bạn đã làm điều đó trong ASCII!
justhalf

10
+1 cho ASCII vàsystem("cls"); // xD
Christoph Böhmwalder

1
Thật là đẹp
trichoplax


Bình luận ghét người bắt buộc: "Đây không phải là C! Tiêu chuẩn không xác định chế độ Ngủ, COORD hoặc SetConsoleCthonPocation!"
dùng253751

52

SVG (không có Javascript)

Liên kết JSFiddle tại đây

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 380 380" width="380" height="380" version="1.0">
  <g transform="translate(190 190)">
    <circle cx="0" cy="0" r="190" fill="#000"/>
    <line x1="0" y1="-190" x2="0" y2="190" stroke="#fff" stroke-width="1.5"/>
    <line x1="72.71" y1="175.54" x2="-72.71" y2="-175.54" stroke="#fff" stroke-width="1.5"/>
    <line x1="134.35" y1="134.35" x2="-134.35" y2="-134.35" stroke="#fff" stroke-width="1.5"/>
    <line x1="175.54" y1="72.71" x2="-175.54" y2="-72.71" stroke="#fff" stroke-width="1.5"/>
    <line x1="190" y1="0" x2="-190" y2="0" stroke="#fff" stroke-width="1.5"/>
    <line x1="175.54" y1="-72.71" x2="-175.54" y2="72.71" stroke="#fff" stroke-width="1.5"/>
    <line x1="134.35" y1="-134.35" x2="-134.35" y2="134.35" stroke="#fff" stroke-width="1.5"/>
    <line x1="72.71" y1="-175.54" x2="-72.71" y2="175.54" stroke="#fff" stroke-width="1.5"/>
    <g transform="rotate(0)">
      <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0" to="360" begin="0" dur="8s" repeatCount="indefinite"/>
      <g transform="translate(0 90)">
        <g transform="rotate(0)">
          <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0" to="-360" begin="0" dur="4s" repeatCount="indefinite"/>
          <circle cx="0" cy="90" r="10" fill="#fff"/>
          <circle cx="63.64" cy="63.64" r="10" fill="#fff"/>
          <circle cx="90" cy="0" r="10" fill="#fff"/>
          <circle cx="63.64" cy="-63.64" r="10" fill="#fff"/>
          <circle cx="0" cy="-90" r="10" fill="#fff"/>
          <circle cx="-63.64" cy="-63.64" r="10" fill="#fff"/>
          <circle cx="-90" cy="0" r="10" fill="#fff"/>
          <circle cx="-63.64" cy="63.64" r="10" fill="#fff"/>
        </g>
      </g>
    </g>
  </g>
</svg>

Hmmm, tôi chắc chắn rằng điều này vượt qua các quy tắc, nhưng cá nhân tôi đã thất vọng vì thực tế bạn đang làm điều ngược lại. Thay vì có vẻ như các điểm [đang] quay bên trong vòng tròn, nhưng chúng thực sự chỉ đang di chuyển theo đường thẳng . Trực tiếp, bạn thực hiện: Hồi Có vẻ như các điểm [đang] di chuyển theo đường thẳng, nhưng thực ra chúng là chỉ cần quay bên trong vòng tròn . Hãy
mkoistinen

Câu trả lời mượt mà nhất!
Derek 朕 會

14
@mkoistinen Tôi hiểu ý của bạn, nhưng các điểm thực sự đang di chuyển theo đường thẳng. Nó chỉ đơn giản là dễ dàng hơn để tính toán vị trí của họ với hai lần quay :-)
ossifrage squeamish

Bạn đã làm tất cả 'bằng tay' hay bạn đã sử dụng bất kỳ loại trình soạn thảo (không phải văn bản-) nào?
flawr

5
@flawr Tôi chỉ sử dụng một trình soạn thảo văn bản đơn giản và máy tính trong điện thoại của tôi để tìm ra các con số :-)
squossish ossifrage

47

http://jsfiddle.net/z6vhD/13/

intervaltimethay đổi FPS (FPS = 1000 / khoảng thời gian).
ballsthay đổi các quả bóng #.
maxstepđiều chỉnh các bước # trong một chu kỳ, càng lớn thì 'càng mượt'. 64 phải đủ lớn, nơi nó xuất hiện trơn tru.

Được mô hình như một vòng tròn chuyển động, thay vì di chuyển các quả bóng dọc theo các đường, nhưng hiệu ứng hình ảnh (nên là?) Giống nhau. Một số mã khá dài dòng, nhưng đây không phải là mã golf, vì vậy ...

var intervalTime = 40;
var balls = 8;
var maxstep = 64;

var canvas = $('#c').get(0); // 100% necessary jquery
var ctx = canvas.getContext('2d');
var step = 0;

animateWorld = function() {
    createBase();
    step = step % maxstep;
    var centerX = canvas.width/2 + 115 * Math.cos(step * 2 / maxstep * Math.PI);
    var centerY = canvas.height/2 + 115 * Math.sin(step * 2 / maxstep * Math.PI);

    for (var i=0; i<balls; i++) {
        drawCircle(ctx, (centerX + 115 * Math.cos((i * 2 / balls - step * 2 / maxstep) * Math.PI)), (centerY + 115 * Math.sin((i * 2 / balls - step * 2 / maxstep) * Math.PI)), 10, '#FFFFFF');     
    }

    step++;
}

function createBase() {
    drawCircle(ctx, canvas.width/2, canvas.height/2, 240, '#000000');
    for(var i=0; i<balls*2; i++) {
        drawLine(ctx, canvas.width/2, canvas.height/2, canvas.width/2 + 240 * Math.cos(i / balls * Math.PI), canvas.height/2 + 240 * Math.sin(i / balls * Math.PI), '#FFFFFF');
    }
}

function drawLine(context, x1, y1, x2, y2, c) {
    context.beginPath();
    context.moveTo(x1,y1);
    context.lineTo(x2,y2);
    context.lineWidth = 3;
    context.strokeStyle = c;
    context.stroke();
}

function drawCircle(context, x, y, r, c) {
    context.beginPath();
    context.arc(x, y, r, 0, 2*Math.PI);
    context.fillStyle = c;
    context.fill();
}

function drawRect(context, x, y, w, h, c) {
    context.fillStyle = c;
    context.fillRect(x, y, w, h);
}

$(document).ready(function() {
    intervalID = window.setInterval(animateWorld, intervalTime);
});

2
Thật là mượt mà! Rất đẹp.
nneonneo

5
Đừng sử dụng setInterval cho hình ảnh động, requestAnimationFramethay vào đó . Đã sửa đổi JSFiddle bằng cách sử dụng requestAnimationFrame.
klingt.net

1
Chỉ với một vài điều chỉnh thông số, bạn sẽ có được một điều rất khác biệt .
FreeAsInBeer

@KevinL Yep, chỉ cần chú ý rằng quá. Đã cập nhật.
FreeAsInBeer

1
@FreeAsInBeer Ồ, khi bạn nói điều rất khác, tôi nghĩ bạn có ý nghĩa như những người trong jsfiddle.net/z6vhD/100
Kevin L

41

Hoạt hình CSS

Một giải pháp chỉ sử dụng hoạt hình css (xem hoạt hình trên JSFiddle - lưu ý rằng tôi đã thêm các tiền tố cụ thể của trình duyệt trong fiddle để nó có thể hoạt động trong hầu hết các phiên bản gần đây).

<body>
    <div id="w1"></div>
    <div id="w2"></div>
    <div id="w3"></div>
    <div id="w4"></div>
    <div id="w5"></div>
    <div id="w6"></div>
    <div id="w7"></div>
    <div id="w8"></div>
</body>


div {
    position: absolute;
    width: 20px;
    height: 20px;
    border-radius: 20px;
    background: red;
    animation-duration: 4s;
    animation-iteration-count: infinite;
    animation-direction: alternate;
    animation-timing-function: ease-in-out;
}

#w1 { animation-name: s1; animation-delay: 0.0s }
#w2 { animation-name: s2; animation-delay: 0.5s }
#w3 { animation-name: s3; animation-delay: 1.0s }
#w4 { animation-name: s4; animation-delay: 1.5s }
#w5 { animation-name: s5; animation-delay: 2.0s }
#w6 { animation-name: s6; animation-delay: 2.5s }
#w7 { animation-name: s7; animation-delay: 3.0s }
#w8 { animation-name: s8; animation-delay: 3.5s }

@keyframes s1 { from {top: 100px; left:   0px;} to {top: 100px; left: 200px;} } 
@keyframes s2 { from {top:  62px; left:   8px;} to {top: 138px; left: 192px;} } 
@keyframes s3 { from {top:  29px; left:  29px;} to {top: 171px; left: 171px;} } 
@keyframes s4 { from {top:   8px; left:  62px;} to {top: 192px; left: 138px;} } 
@keyframes s5 { from {top:   0px; left: 100px;} to {top: 200px; left: 100px;} } 
@keyframes s6 { from {top:   8px; left: 138px;} to {top: 192px; left:  62px;} } 
@keyframes s7 { from {top:  29px; left: 171px;} to {top: 171px; left:  29px;} } 
@keyframes s8 { from {top:  62px; left: 192px;} to {top: 138px; left:   8px;} } 

3
Fiddle không hoạt động với tôi trên Chrome mới nhất = /
mkoistinen

1
@mkoistinen - Bạn phải thêm các tiền tố khác nhau để nó hoạt động trong các trình duyệt khác nhau. ( -webkit-dành cho dựa trên Webkit và dựa trên -moz-Mozilla) Đây là cùng một câu đố với các tiền tố được cập nhật: jsfiddle.net/nBCxz/3
Derek 會

@mkoistinen Bạn nói đúng. Fiddle mới thêm tất cả các tiền tố trình duyệt cần thiết và hoạt động trên Chrome mới nhất.
Howard

Văn bản liên kết thô chỉ thiếu dấu ngoặc đơn đóng - vẫn hoàn toàn có thể sử dụng được chỉ cho bạn biết trong trường hợp bạn muốn sửa nó (Tôi không thể thay đổi ít hơn 6 ký tự).
trichoplax

35

Toán học

Đây là một đệ trình khá đơn giản.

animateCircle[n_] := Animate[Graphics[
   Flatten@{
     Disk[],
     White,
     Map[
      (
        phase = #*2 \[Pi]/n;
        line = {Cos[phase], Sin[phase]};
        {Line[{-line, line}],
         Disk[Sin[t + phase]*line, 0.05]}
        ) &,
      Range[n]
      ]
     },
   PlotRange -> {{-1.1, 1.1}, {-1.1, 1.1}}
   ],
  {t, 0, 2 \[Pi]}
  ]

Nếu bạn gọi, animateCircle[32]bạn sẽ có được một hình ảnh động gọn gàng với 32 dòng và vòng tròn.

nhập mô tả hình ảnh ở đây

Nó hoàn toàn mượt mà trong Mathicala, nhưng tôi đã phải giới hạn số lượng khung hình cho GIF một chút.

Bây giờ điều gì xảy ra nếu bạn đặt hai đĩa trên mỗi dòng? (Đó là, thêm Disk[-Sin[t + phase]*line, 0.05]vào danh sách trong Map.)

nhập mô tả hình ảnh ở đây

Bạn cũng có thể đặt chúng lệch pha 90 ° (sử dụng Costhay vì -Sin):

nhập mô tả hình ảnh ở đây


Tôi không biết ý của bạn là gì, có lẽ bạn cần thay đổi {t, 0, 2 \[Pi]}để {t, 0, 2 \[Pi] - 2 \[Pi]/60, 2 \[Pi]/60}không có hai khung hình giống hệt nhau và thay đổi Animatethành Table. Sau đó, bạn sẽ có thể xuất GIF.
swish

@swish Không, nó thực sự biểu hiện các dòng bổ sung kỳ lạ không có ở đó và các đĩa ở những nơi không nên đến (và nơi chúng không bao giờ nằm ​​trong kết quả thực tế của Animate). Tôi sẽ thử sử dụng Tablelại mặc dù.
Martin Ender

@swish Điều đó đã làm việc. Tôi nghĩ rằng tôi đã thử một cái gì đó như thế này ngày hôm qua, nhưng dường như tôi đã không làm thế.
Martin Ender

25

Biểu đồ VBScript + VBA + Excel

Điều này sẽ làm cho bộ xử lý của bạn khóc một chút nhưng nó trông khá đẹp và tôi tin rằng nó hoạt động theo thông số kỹ thuật. Tôi đã sử dụng câu trả lời của @ Fabricio như một hướng dẫn để thực hiện thuật toán chuyển động vòng tròn.

EDIT: Thực hiện một số điều chỉnh để cải thiện tốc độ kết xuất.

Ảnh chụp màn hình của biểu đồ Pie

Mật mã:

'Open Excel
Set objX = CreateObject("Excel.Application")
objX.Visible = True
objX.Workbooks.Add

'Populate values
objX.Cells(1, 1).Value = "Lbl"
objX.Cells(1, 2).Value = "Amt"
For fillX = 2 to 17
    objX.Cells(fillX, 1).Value = "V"+Cstr(fillX-1)
    objX.Cells(fillX, 2).Value = "1"
Next

'Create pie
objX.Range("A2:B17").Select
objX.ActiveSheet.Shapes.AddChart.Select
With objX.ActiveChart
    .ChartType = 5 'pieChart
    .SetSourceData  objX.Range("$A$2:$B$17")
    .SeriesCollection(1).Select
End with    

'Format pie
With objX.Selection.Format
    .Fill.ForeColor.RGB = 0 'black
    .Fill.Solid
    .Line.Weight = 2
    .Line.Visible = 1
    .Line.ForeColor.RGB = 16777215 'white
End With

'animation variables
pi = 3.14159265358979323846
circle = pi * 2 : l  = 16.0
hlen = l / 2    : cx = 152.0
cy = 99.0       : w  = 90.0
h  = 90.0       : s  = 0.0
Dim posArry(7,1)

'Animate
While 1 
  For i = 0 to hlen-1
    a = (i / l) * circle
    range = cos(a + s)
    x = cx + cos(a) * w * range
    y = cy + sin(a) * h * range

    If whileInx = 1 Then 
        createOval x, y
    ElseIf whileInx = 2 Then 
        objX.ActiveChart.Legend.Select
    ElseIf whileInx > 2 Then
        ovalName = "Oval "+ Cstr(i+1)
        dx = x - posArry(i,0)
        dy = y - posArry(i,1)
        moveOval ovalName, dx, dy
    End if

    posArry(i,0) = x
    posArry(i,1) = y
  Next

  s=s-0.05
  wscript.Sleep 1000/60 '60fps
  whileInx = 1 + whileInx
Wend

'create circles
sub createOval(posX, posY)
    objX.ActiveChart.Shapes.AddShape(9, posX, posY, 10, 10).Select '9=oval
    objX.Selection.ShapeRange.Line.Visible = 0
    with objX.Selection.ShapeRange.Fill
       .Visible = 1
       .ForeColor.RGB = 16777215 'white
       .solid
    end with
end sub

'move circles
sub moveOval(ovalName, dx, dy)
    with objX.ActiveChart.Shapes(ovalName)      
        .IncrementLeft dx
        .IncrementTop  dy
    end with
end sub

Nó gặp sự cố với tôi ở dòng 81, lỗi 80070057, "phần tử với tên đã cho không tồn tại" hoặc đại loại như thế này (dịch lại từ tiếng Hungary, đó là lý do tại sao tôi không biết thông báo lỗi chính xác).
marczellm

Szervusz, @marczellm. Tôi có thể tái tạo lỗi đó khi tôi nhấp vào bên ngoài biểu đồ trong khi nó đang "hoạt hình". Bạn phải cho phép nó tập trung hoặc chương trình sẽ lỗi. Mặt khác, điều này có thể là do sự không tương thích với Office. Tôi đang dùng Office 2010 trên Win7.
thoải

Văn phòng 2007, Win7. Có vẻ như trong trường hợp của tôi, biểu đồ hoàn toàn không tập trung.
marczellm

21

Excel, 161 byte

Excel

=2*PI()*(NOW()*24*60*60/A2-FLOOR(NOW()*24*60*60/A2,1))
=ROUND(7*SIN(A1),0)
=ROUND(5*SIN(A1+1*PI()/4),0)
=ROUND(7*SIN(A1+2*PI()/4),0)
=ROUND(5*SIN(A1+3*PI()/4),0)

A2 (giai đoạn) xác định thời gian (giây) cho một 'cuộc cách mạng' đầy đủ.

Mỗi ô trong các dòng là một điều kiện cơ bản liên quan đến giá trị của dòng tương ứng. Ví dụ: K2 là:

 =1*(A5=7)

Và ô trung tâm (K9) là:

=1*OR(A5=0,A6=0,A7=0,A8=0)

Buộc hoạt hình bằng cách giữ 'xóa' trên một ô ngẫu nhiên để liên tục kích hoạt làm mới.

Tôi biết đây là một chủ đề cũ, nhưng hoạt động gần đây đã đưa nó lên hàng đầu và nó có vẻ hấp dẫn vì một số lý do. Người nghe pcg thời gian dài, người gọi lần đầu. Hãy nhẹ nhàng.


Ồ, thật đáng kinh ngạc khi bạn có thể làm điều đó với Excel: D
Beta Decay

15

Chỉ để cho vui với PSTricks.

nhập mô tả hình ảnh ở đây

\documentclass[preview,border=12pt,multi]{standalone}
\usepackage{pstricks}

\psset{unit=.3}

% static point
% #1 : half of the number of points
% #2 : ith point
\def\x[#1,#2]{(3*cos(Pi/#1*#2))}
\def\y[#1,#2]{(3*sin(Pi/#1*#2))}

% oscillated point
% #1 : half of the number of points
% #2 : ith point
% #3 : time parameter
\def\X[#1,#2]#3{(\x[#1,#2]*cos(#3+Pi/#1*#2))}
\def\Y[#1,#2]#3{(\y[#1,#2]*cos(#3+Pi/#1*#2))}

% single frame
% #1 : half of the number of points
% #2 : time parameter
\def\Frame#1#2{%
\begin{pspicture}(-3,-3)(3,3)
    \pstVerb{/I2P {AlgParser cvx exec} bind def}%
    \pscircle*{\dimexpr3\psunit+2pt\relax}
    \foreach \i in {1,...,#1}{\psline[linecolor=yellow](!\x[#1,\i] I2P \y[#1,\i] I2P)(!\x[#1,\i] I2P neg \y[#1,\i] I2P neg)}
    \foreach \i in {1,...,#1}{\pscircle*[linecolor=white](!\X[#1,\i]{#2} I2P \Y[#1,\i]{#2} I2P){2pt}}   
\end{pspicture}}

\begin{document}
\foreach \t in {0,...,24}
{   
    \preview
    \Frame{1}{2*Pi*\t/25} \quad \Frame{2}{2*Pi*\t/25} \quad \Frame{3}{2*Pi*\t/25} \quad \Frame{5}{2*Pi*\t/25} \quad \Frame{10}{2*Pi*\t/25}
    \endpreview
}
\end{document}

11

Pháo đài

Mỗi khung được tạo dưới dạng tệp gif riêng bằng mô-đun gif Fortran tại: http://fortranwiki.org/fortran/show/writegif
Sau đó, tôi gian lận một chút bằng cách sử dụng ImageMagick để hợp nhất các gif riêng lẻ thành một gif hoạt hình.

Pháo đài

CẬP NHẬT: Đặt mới = .true. để có được những điều sau đây:

nhập mô tả hình ảnh ở đây

program circle_illusion

use, intrinsic :: iso_fortran_env, only: wp=>real64
use gif_util  !gif writing module from http://fortranwiki.org/fortran/show/writegif

implicit none

logical,parameter :: new = .false.

integer,parameter  :: n        = 500  !550  !size of image (square)     
real(wp),parameter :: rcircle  = n/2  !250  !radius of the big circle
integer,parameter  :: time_sep = 5    !deg

real(wp),parameter :: deg2rad = acos(-1.0_wp)/180.0_wp
integer,dimension(0:n,0:n):: pixel     ! pixel values
integer,dimension(3,0:3)  :: colormap  ! RGB 0:255 for colors 0:ncol    
real(wp),dimension(2)     :: xy
integer,dimension(2)      :: ixy
real(wp)                  :: r,t
integer                   :: i,j,k,row,col,m,n_cases,ang_sep
character(len=10)         :: istr

integer,parameter  :: black = 0
integer,parameter  :: white = 1
integer,parameter  :: red   = 2
integer,parameter  :: gray  = 3    
colormap(:,0) = [0,0,0]          !black
colormap(:,1) = [255,255,255]    !white
colormap(:,2) = [255,0,0]        !red
colormap(:,3) = [200,200,200]    !gray

if (new) then
    ang_sep = 5
    n_cases = 3
else
    ang_sep = 20
    n_cases = 0
end if

do k=0,355,time_sep

    !clear entire image:
    pixel = white      

    if (new) call draw_circle(n/2,n/2,black,n/2)  

    !draw polar grid:    
    do j=0,180-ang_sep,ang_sep
        do i=-n/2, n/2
            call spherical_to_cartesian(dble(i),dble(j)*deg2rad,xy)
            call convert(xy,row,col)
            if (new) then
                pixel(row,col) = gray
            else
                pixel(row,col) = black  
            end if  
        end do
    end do

    !draw dots:
    do m=0,n_cases
        do j=0,360-ang_sep,ang_sep
            r = sin(m*90.0_wp*deg2rad + (k + j)*deg2rad)*rcircle                
            t = dble(j)*deg2rad    
            call spherical_to_cartesian(r,t,xy)
            call convert(xy,row,col)
            if (new) then
                !call draw_circle(row,col,black,10)  !v2
                !call draw_circle(row,col,m,5)       !v2
                call draw_circle(row,col,white,10)   !v3
            else
                call draw_square(row,col,red)        !v1
            end if
        end do
    end do

    !write the gif file for this frame:        
    write(istr,'(I5.3)') k
    call writegif('gifs/test'//trim(adjustl(istr))//'.gif',pixel,colormap)

end do

!use imagemagick to make animated gif from all the frames:
! from: http://thanosk.net/content/create-animated-gif-linux
if (new) then
    call system('convert -delay 5 gifs/test*.gif -loop 0 animated.gif')
else
    call system('convert -delay 10 gifs/test*.gif -loop 0 animated.gif')
end if

!delete individual files:
call system('rm gifs/test*.gif')

contains

    subroutine draw_square(r,c,icolor)

    implicit none
    integer,intent(in) :: r,c  !row,col of center
    integer,intent(in) :: icolor

    integer,parameter :: d = 10 !square size

    pixel(max(0,r-d):min(n,r+d),max(0,c-d):min(n,c+d)) = icolor

    end subroutine draw_square

    subroutine draw_circle(r,c,icolor,d)

    implicit none
    integer,intent(in) :: r,c  !row,col of center
    integer,intent(in) :: icolor
    integer,intent(in) :: d  !diameter

    integer :: i,j

    do i=max(0,r-d),min(n,r+d)
        do j=max(0,c-d),min(n,c+d)
            if (sqrt(dble(i-r)**2 + dble(j-c)**2)<=d) &
                pixel(i,j) = icolor
        end do
    end do

    end subroutine draw_circle

    subroutine convert(xy,row,col)

    implicit none
    real(wp),dimension(2),intent(in) :: xy  !coordinates
    integer,intent(out) :: row,col

    row = int(-xy(2) + n/2.0_wp)
    col = int( xy(1) + n/2.0_wp)

    end subroutine convert

    subroutine spherical_to_cartesian(r,theta,xy)

    implicit none
    real(wp),intent(in) :: r,theta
    real(wp),dimension(2),intent(out) :: xy

    xy(1) = r * cos(theta)
    xy(2) = r * sin(theta)

    end subroutine spherical_to_cartesian

end program circle_illusion

1
Tôi thích tác động 'squish' cho các yếu tố dọc và ngang.
Người chạy Portland

11

Phiên bản C64 bắt buộc .

Sao chép và dán vào trình giả lập yêu thích của bạn:

Phiên bản C64

1 print chr$(147)
2 poke 53281,0
3 for p=0 to 7
5 x=int(11+(cos(p*0.78)*10)):y=int(12+(sin(p*0.78)*10))
6 poke 1024+x+(y*40),15
9 next p
10 for sp=2040 to 2047:poke sp,13:next sp
20 for i=0 to 62:read a:poke 832+i,a:next i
30 for i=0 to 7:poke 53287+i,i+1:next i
40 rem activate sprites
50 poke 53269,255
60 an=0.0
70 rem maincycle
75 teta=0.0:k=an
80 for i=0 to 7
90 px=cos(k)*64
92 s=i:x=px*cos(teta): y=px*sin(teta): x=x+100: y=y+137: gosub 210
94 teta=teta+0.392699
95 k=k+0.392699
96 next i
130 an=an+0.1
140 goto 70
150 end
200 rem setspritepos
210 poke 53248+s*2,int(x): poke 53249+s*2,int(y)
220 return
5000 data 0,254,0
5010 data 3,199,128
5020 data 7,0,64
5030 data 12,126,96
5040 data 25,255,48
5050 data 59,7,152
5060 data 52,1,200
5070 data 116,0,204
5080 data 120,0,100
5090 data 120,0,100
5100 data 120,0,100
5110 data 120,0,36
5120 data 104,0,36
5130 data 100,0,108
5140 data 54,0,72
5150 data 51,0,152
5160 data 25,131,16
5170 data 12,124,96
5180 data 4,0,64
5190 data 3,1,128
5200 data 0,254,0

10

Phiên bản javascript nhỏ gọn, thay đổi cài đặt mặc định thành khác

http://jsfiddle.net/yZ3DP/1/

HTML:

<canvas id="c" width="400" height="400" />

JavaScript:

var v= document.getElementById('c');
var c= v.getContext('2d');
var w= v.width, w2= w/2;
var num= 28, M2= Math.PI*2, da= M2/num;
draw();
var bw= 10;
var time= 0;
function draw()
{
    v.width= w;
    c.beginPath();
    c.fillStyle= 'black';
    circle(w2,w2,w2);
    c.lineWidth= 1.5;
    c.strokeStyle= c.fillStyle= 'white';
    var a= 0;
    for (var i=0; i< num*2; i++){
        c.moveTo(w2,w2);
        c.lineTo(w2+Math.cos(a)*w2, w2+Math.sin(a)*w2);
        a+= da/2;
    }
    c.stroke();
    a= 0;
    for (var i=0; i< num; i++){
        circle(w2+Math.cos(a)*Math.sin(time+i*Math.PI/num)*(w2-bw), 
               w2+Math.sin(a)*Math.sin(time+i*Math.PI/num)*(w2-bw), bw);
        a+= da/2;
    }
    time+=0.03;
   requestAnimationFrame(draw);
}

function circle(x,y,r)
{
    c.beginPath();
    c.arc(x, y, r, 0, M2);
    c.fill();

}

2
Bạn đã làm ... một cái bánh rán ?? Trên thực tế hoạt hình của bạn trông đẹp với các chấm nhỏ hơn (thử bw=10). Vui lòng chỉnh sửa câu trả lời của bạn để hiển thị mã của bạn. Ồ, và trong khi bạn đang ở đó, có một lỗi bạn nên sửa: thay thế time+i*0.39*0.29bằng time+i*Math.PI/numcác phép tính trig để tọa độ được tính chính xác cho bất kỳ giá trị nào num. (PS Cập nhật JSFiddle tại đây . Và chào mừng bạn đến với codegolf.stackexchange.com)
ossifrage squeamish

Tôi chỉ muốn làm một cái gì đó khác biệt (như con rùa). Newbie ở đây trong codegolf :) Ồ, và cảm ơn bạn về công thức: DI chỉ cần thực hiện vội vàng và thử các giá trị ngẫu nhiên, đã không dừng lại một phút để có được công thức chính xác: P
Diego

1
+1 Thay đổi nhỏ cho một niềm vui trực quan nhỏ: http://jsfiddle.net/9TQrm/ hoặc http://jsfiddle.net/Wrqs4/1/
Người chạy Portland

4

Tôi mang theo Elm . Tôi là một người mới bắt đầu hoàn toàn sẽ vui vẻ chấp nhận PR để cải thiện giải pháp này ( GitHub ):

nhập mô tả hình ảnh ở đây

Lưu ý rằng bài nộp này thực sự là điểm di chuyển trên các đường thẳng:

import Color exposing (..)
import Graphics.Collage exposing (..)
import Graphics.Element exposing (..)
import Time exposing (..)
import Window
import List exposing (..)
import AnimationFrame -- "jwmerrill/elm-animation-frame"
import Debug

-- CONFIG

size = 600
circleSize = 240
dotCount = 12
dotSize = 10
velocity = 0.01

-- MODEL

type alias Dot =
    { x : Float
    , angle : Float
    }

type alias State = List Dot

createDots : State
createDots = map createDot [ 0 .. dotCount - 1 ]

createDot : Int -> Dot
createDot index =
    let angle = toFloat index * pi / dotCount
    in { x = 0
       , angle = angle
       }

-- UPDATE

update : Time -> State -> State
update time dots = map (moveDot time) dots |> Debug.watch "Dots"

moveDot : Time -> Dot -> Dot
moveDot time dot =
  let t = velocity * time / pi
      newX = (-circleSize + dotSize) * cos(t + dot.angle)
  in { dot | x <- newX }

-- VIEW

view : State -> Element
view dots =
   let background = filled black (circle circleSize)
       dotLinePairs = map viewDotWithLine dots
   in collage size size (background :: dotLinePairs)

viewDotWithLine : Dot -> Form
viewDotWithLine dot =
  let dotView = viewDot dot
      lineView = createLineView
  in group [dotView , lineView] |> rotate dot.angle

viewDot : Dot -> Form
viewDot d = alpha 0.8 (filled lightOrange (circle dotSize)) |> move (d.x, 0)

createLineView : Form
createLineView = traced (solid white) (path [ (-size / 2.0, 0) , (size / 2.0, 0) ])

-- SIGNALS

main = Signal.map view (animate createDots)

animate : State -> Signal State
animate dots = Signal.foldp update dots time

time = Signal.foldp (+) 0 AnimationFrame.frame

4
Con trỏ đó đánh lừa tôi rất tốt, và tôi thậm chí không phải là màu đen hoặc kích thước đó.
cole

2

Cuộc sống thứ hai LSL

hoạt hình bắt đầu hình ảnh rùa alpha (nhấp chuột phải bên dưới để lưu hình ảnh)
rùa.png
kết thúc hình ảnh rùa alpha (nhấp chuột phải ở trên để lưu hình ảnh)

xây dựng đối tượng:
tạo kích thước hình trụ gốc <1, 1, 0,01> lát 0,49, 0,51, màu < 0, 0, 0>
làm cho mô tả của hình trụ này "8.1,1,1" không có dấu ngoặc kép (rất quan trọng)
tạo hình trụ, đặt tên là "hình trụ", màu <0,25, 0,25, 0,25> alpha 0,5
nhân đôi Xi lanh 48 lần
tạo một hộp, đặt tên là "hình cầu", màu <1, 1, 1> độ trong suốt 100 ngoại trừ độ trong suốt 0
đặt kết cấu rùa của bạn lên mặt 0 của hộp, rùa phải đối mặt + x
nhân đôi hộp 48 lần
chọn tất cả các hộp và hình trụ, đảm bảo chọn hình trụ gốc cuối cùng,liên kết (kiểm soát L)

đặt 2 script này vào thư mục gốc:

//script named "dialog"
default
{
    state_entry()
    {

    }

    link_message(integer link, integer num, string msg, key id)
    {
        list msgs = llCSV2List(msg);
        key agent = (key)llList2String(msgs, 0);
        string prompt = llList2String(msgs, 1);
        integer chan = (integer)llList2String(msgs, 2);
        msgs = llDeleteSubList(msgs, 0, 2);
        llDialog(agent, prompt, msgs, chan);
    }
}

//script named "radial animation"
float interval = 0.1;
float originalsize = 1.0;
float rate = 5;
integer maxpoints = 48;
integer points = 23; //1 to 48
integer multiplier = 15;
integer lines;
string url = "https://codegolf.stackexchange.com/questions/34887/make-a-circle-illusion-animation/34891";

list cylinders;
list spheres;
float angle;
integer running;
integer chan;
integer lh;

desc(integer on)
{
    if(on)
    {
        string desc = 
            (string)points + "," +
            (string)multiplier + "," +
            (string)running + "," +
            (string)lines
            ;

        llSetLinkPrimitiveParamsFast(1, [PRIM_DESC, desc]);
    }
    else
    {
        list params = llCSV2List(llList2String(llGetLinkPrimitiveParams(1, [PRIM_DESC]), 0));
        points = (integer)llList2String(params, 0);
        multiplier = (integer)llList2String(params, 1);
        running = (integer)llList2String(params, 2);
        lines = (integer)llList2String(params, 3);
    }    
}

init()
{
    llSetLinkPrimitiveParamsFast(LINK_ALL_OTHERS, [PRIM_POS_LOCAL, ZERO_VECTOR, 
        PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 0]);
    integer num = llGetNumberOfPrims();
    integer i;
    for(i = 2; i <= num; i++)
    {
        string name = llGetLinkName(i);

        if(name == "cyl")
            cylinders += [i];
        else if(name == "sphere")
            spheres += [i];
    }  

    vector size = llGetScale();
    float scale = size.x/originalsize;

    float r = size.x/4;
    vector cylindersize = <0.01*scale, 0.01*scale, r*4>;
    float arc = 180.0/points;

    for(i = 0; i < points; i++)
    {
        float angle = i*arc;
        rotation rot = llEuler2Rot(<0, 90, 0>*DEG_TO_RAD)*llEuler2Rot(<0, 0, angle>*DEG_TO_RAD);

        integer cyl = llList2Integer(cylinders, i);
        integer sphere = llList2Integer(spheres, i);

        llSetLinkPrimitiveParamsFast(1, [PRIM_LINK_TARGET, cyl, PRIM_POS_LOCAL, ZERO_VECTOR, PRIM_ROT_LOCAL, rot, PRIM_SIZE, cylindersize, PRIM_COLOR, ALL_SIDES, <0.25, 0.25, 0.25>, 0.5*lines,
        PRIM_LINK_TARGET, sphere, PRIM_COLOR, ALL_SIDES, <0.25 + llFrand(0.75), 0.25 + llFrand(0.75), 0.25 + llFrand(0.75)>, 1
        ]);
    }
}

run()
{
    vector size = llGetScale();
    float scale = size.x/originalsize;

    float r = size.x/2;
    vector spheresize = <0.06, 0.06, 0.02>*scale;
    float arc = 180.0/points;
    list params;
    integer i;
    for(i = 0; i < points; i++)
    {

        float x = r*llCos((angle + i*arc*multiplier)*DEG_TO_RAD);

        vector pos = <x, 0, 0>*llEuler2Rot(<0, 0, i*arc>*DEG_TO_RAD);
        rotation rot = llEuler2Rot(<0, 0, i*arc>*DEG_TO_RAD);
        integer link = llList2Integer(spheres, i);
        params += [PRIM_LINK_TARGET, link, PRIM_POS_LOCAL, pos,  
            PRIM_ROT_LOCAL, rot,
            PRIM_SIZE, spheresize
            //PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 1
            ];
    }   

    llSetLinkPrimitiveParamsFast(1, params);
}

dialog(key id)
{
    string runningstring;
    if(running)
        runningstring = "notrunning";
    else
        runningstring = "running";

    string linesstring;
    if(lines)
        linesstring = "nolines";
    else
        linesstring = "lines";
    string prompt = "\npoints: " + (string)points + "\nmultiplier: " + (string)multiplier;
    string buttons = runningstring + ",points+,points-,reset,multiplier+,multiplier-," + linesstring + ",www";
    llMessageLinked(1, 0, (string)id + "," + prompt + "," + (string)chan + "," + buttons, "");
    //llDialog(id, prompt, llCSV2List(buttons), chan);
}

default
{
    state_entry()
    {
        chan = (integer)("0x" + llGetSubString((string)llGetKey(), -8, -1));
        lh = llListen(chan, "", "", "");

        desc(FALSE);
        init();
        run();
        llSetTimerEvent(interval);
    }

    on_rez(integer param)
    {
        llListenRemove(lh);
        chan = (integer)("0x" + llGetSubString((string)llGetKey(), -8, -1));
        lh = llListen(chan, "", "", "");
    }

    touch_start(integer total_number)
    {
        key id = llDetectedKey(0);
        dialog(id);
    }

    timer()
    {
        if(!running)
            return;

        angle += rate;
        if(angle > 360)
            angle -= 360;
        else if(angle < 0)
            angle += 360;

        run();
    }

    listen(integer channel, string name, key id, string msg)
    {
        if(msg == "points+")
        {
            if(points < maxpoints)
            {
                points++;
                desc(TRUE);
                llResetScript();            
            }
        }
        else if(msg == "points-")
        {
            if(points > 0)
            {
                points--;
                desc(TRUE);
                llResetScript();
            }
        }        
        else if(msg == "multiplier+")
        {
            multiplier++;
            desc(TRUE);
        }
        else if(msg == "multiplier-")
        {
            multiplier--;
            desc(TRUE);
        }
        else if(msg == "running")
        {
            running = TRUE;
            desc(TRUE);
        }
        else if(msg == "notrunning")
        {
            running = FALSE;
            desc(TRUE);
        }
        else if(msg == "lines")
        {
            lines = TRUE;
            desc(TRUE);
            llResetScript();
        }
        else if(msg == "nolines")
        {
            lines = FALSE;
            desc(TRUE);
            llResetScript();
        }
        else if(msg == "reset")
            llResetScript();
        else if(msg == "www")
            llRegionSayTo(id, 0, url);
        dialog(id);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.