원 환상 애니메이션 만들기


84

당신의 임무는이 원 환상 을 애니메이션하는 입니다. 원 내부에서 회전하는 점처럼 보이지만 실제로는 직선으로 움직입니다.

여기에 이미지 설명을 입력하십시오

기준

  • 결과는 애니메이션이어야합니다. 애니메이션을 수행하는 방식은 관련이 없으며을 생성 .gif하고 창, 일부 장치 화면 또는 기타로 그릴 수 있습니다.
  • 이것은 인기 경연 대회이므로 포인트 수를 변경하는 등 더 많은 투표를 얻기 위해 프로그램에 추가 기능을 추가 할 수 있습니다.
  • 우승자는 가장 upvoted입니다 유효 칠일 마지막 유효 제출 후 대답.
  • 실제로 다른 방향으로 움직이지 않고 직선으로 움직이는 점을 구현하는 답변은 더 환영받습니다.

"승자는 7 일 후에 가장 많이지지되는 사람입니다." 별이 죽을 때까지 누군가가 6 일마다 무언가를 올리면 우리에게는 승자가 없습니까?
Kevin L

3
@KevinL은 일어날 것 같지 않으며 그 15 명의 추가 담당자는이 질문에서 얻을 수있는 모든 공감대와 비교할 때 6 일마다 최고에 부딪친다고 생각하지 않습니다.
마틴 엔더

1
때로는 어떤 사람들이 일을 끝내기 위해 이런 일을하는지 궁금합니다.
Daniel Pendergast

3
"원 내부에서 회전하는 점처럼 보이지만 실제로는 직선으로 움직이고 있습니다."또는 실제로 원 내부에서 회전 하고 직선으로 움직이는 것처럼 보일 수 있습니다.
coredump

1
이 애니메이션을 얻을 수 없습니다 .. 내 마음에서 .. 특히 3 점 버전!
Thomas

답변:


126

파이썬 3.4

거북이 모듈 사용. 거북이는 색이 다르고 항상 같은 방향을 향하고 있기 때문에 그중 하나에 집중하면 직선을 따라 움직이는 것을 쉽게 볼 수 있습니다. 그럼에도 불구하고 원 착각은 여전히 ​​강하다.

거북이 11 마리

3 ~ 4 마리의 거북이 만 있어도 환상은 여전히 ​​강해 보입니다.

거북이 3 마리거북이 4 마리

이러한 GIF 예제의 경우 프레임 속도가 상당히 줄어들지 만 환상에서 벗어나지 않는 것 같습니다. 코드를 로컬로 실행하면보다 부드러운 애니메이션이 제공됩니다.

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:]))

대조적으로 여기에 실제로 회전하는 일부가 있습니다.

루프 거북 23 개개미 새 23 마리

... 또는 그렇습니까?

코드는 모집단, 해상도, 루프, 플립 및 라인의 5 가지 선택적 인수로 실행될 수 있습니다.

  • population 거북이의 수
  • resolution 시간 해상도 (반복 당 애니메이션 프레임 수)
  • loops거북이 몇 번이나 반복되는지 결정합니다. 기본값 1은 표준 원을 제공하고, 다른 홀수는 거북이의 끈에 그 수의 루프를 제공하며, 숫자조차도 끝에서 연결이 끊긴 거북이를 제공하지만 여전히 곡선 운동의 환상을 제공합니다.
  • flip0이 아닌 경우 거북이 돌아 오는 방향으로 뒤집히는 경우 (동반 에서 제안한대로 거꾸로 움직이지 않음) 기본적으로 끝점에서 시각적 방해를 피하기 위해 고정 된 방향을 유지합니다.
  • lines 0이 아닌 경우 문제의 예제 이미지와 일치하도록 거북이가 움직이는 선을 표시합니다.

flipwith, without 및 set이있는 예제 lines. 산발적 인 점프를 선호하지 않기 때문에 위의 주요 예를 뒤집지 않고 떠났지만 모든 거북이가 정렬되면 원의 가장자리가 매끄럽게 보이므로 사람들은 달리기를 할 때 선호하는 스타일을 선택할 수 있습니다 코드.

플립과 라인 11 거북이플립 11 거북이

위의 이미지가 모두 동일한 코드로 어떻게 생성되었는지는 분명하지 않을 수 있습니다. 특히 느린 외부 루프와 빠른 내부 루프 (누군가 실수로 떨어 뜨린 카디오이드처럼 보이는 이미지)가있는 이미지가 더 위로 올라갑니다. 누군가가 실험 / 생각하는 동안 발견을 지연시키고 싶을 때 아래 에이 설명을 숨겼습니다.

루프 수를 15로 설정하고 거북 수를 23 (15 루프를 나타내기에는 너무 낮음)으로 유지하여 크기가 다른 내부 및 외부 루프가있는 애니메이션이 만들어졌습니다. 많은 수의 거북이를 사용하면 15 개의 명확하게 정의 된 고리가 생깁니다. 거북이를 너무 적게 사용하면 이미지 처리 및 렌더링과 같은 이유로 앨리어싱이 발생합니다. 너무 높은 주파수를 나타내려고하면 더 낮은 주파수가 표시되고 왜곡됩니다.

다른 숫자를 시험해 보면서이 왜곡 중 일부가보다 대칭적인 원본보다 흥미로운 것을 발견했기 때문에 여기에 하나를 포함시키고 싶었습니다 ...


18
나는 거북이를 좋아한다.
FreeAsInBeer

18
나는 거북을 위해 +1을 벗겼다
MrEngineer13

구문 강조에 대한 @ProgramFOX 감사합니다! 도움말과 메타를 검색하여 코드 골프에 구문 강조 표시가 없다는 것을 확신했습니다. 지금은 훨씬 더 행복합니다.
trichoplax

1
@aslum을 사용하면 간단하게 변경할 수 있지만 직선 방향에서 벗어나지 않는다는 점을 강조하기 위해 얼어 붙은 방향을 원했습니다. 사람들이 선호하는 접근 방식을 선택할 수 있도록 옵션으로 코드에 추가해야 할 수도 있습니다.
trichoplax

4
+1-마칭 밴드가이 펑키 한 밴드 중 일부를하는 것이 멋지다!
mkoistinen

96

결과:

여기에 이미지 설명을 입력하십시오

#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
일부 프레임에서는 약간 떨어져 있습니다. 그러나 ASCII로 해 주셔서 감사합니다!
justhalf

10
ASCII의 경우 +1system("cls"); // xD
Christoph Böhmwalder

1
이것은 아름답다.
trichoplax


필수 증언자 의견 : "이것은 C가 아닙니다! 표준은 Sleep, COORD 또는 SetConsoleCursorPosition을 정의하지 않습니다!"
immibis

52

SVG (자바 스크립트 없음)

JSFiddle 링크는 여기

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

흠, 나는 이것이 규칙을 가진 소집자를 통과한다고 확신하지만, 나는 개인적으로 당신이 실제로 반대하는 것을 실망했습니다. "원 내부에서 점이 회전하는 것처럼 보이지만 실제로 는 직선으로 움직입니다 ."대신 다음과 같이 구현합니다. "점은 직선으로 움직이는 것처럼 보이지만 실제로는 점입니다. 단지 내의 원을 회전 . "
mkoistinen

가장 부드러운 답변!
Derek 朕 會 功夫

14
@mkoistinen 무슨 말인지 알지만 요점은 실제로 직선 으로 움직입니다. 그것은 단지 두 회전으로 자신의 위치를 ​​계산하는 것이 더 쉽다 :-)
squeamish ossifrage

모두 '수작업'으로 했습니까? 아니면 텍스트가 아닌 편집기를 사용 했습니까?
flawr

5
@flawr 방금 일반 텍스트 편집기 와 휴대 전화의 계산기를 사용하여 숫자를 계산했습니다. :-)
squeamish ossifrage

47

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

intervaltimeFPS를 변경합니다 (FPS = 1000 / 간격).
balls# 공을 변경합니다.
maxstep사이클에서 # 단계를 조정하면 '스모 더'가 커집니다. 64는 매끄럽게 보일 정도로 충분히 커야합니다.

공을 선을 따라 이동하는 대신 원을 움직이는 것으로 모델링했지만 시각적 효과는 동일해야합니다. 일부 코드는 매우 장황하지만 코드 골프가 아닙니다. 그래서 ...

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
너무 부드럽습니다! 아주 좋아요
nneonneo

5
애니메이션에 setInterval을 사용하지 말고 requestAnimationFrame대신을 사용하십시오 . 사용하여 JSFiddle수정했습니다requestAnimationFrame .
klingt.net

1
몇 가지 매개 변수를 조정하면 매우 다른 결과 를 얻을 수 있습니다.
FreeAsInBeer

@KevinL Yep도 그 사실을 알아 차 렸습니다. 업데이트되었습니다.
FreeAsInBeer

1
@FreeAsInBeer 오, 당신이 매우 다른 것을 말할 때, 나는 당신이 jsfiddle.net/z6vhD/100에
Kevin L

41

CSS 애니메이션

CSS 애니메이션 만 사용하는 솔루션 ( JSFiddle의 애니메이션 참조 -바이올린에 브라우저 특정 접두어를 추가하여 최신 버전에서 작동 할 수 있음에 유의하십시오).

<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이 최신 Chrome에서 작동하지 않음 = /
mkoistinen

1
@mkoistinen-다른 브라우저에서 작동하려면 다른 접두사를 추가해야합니다. ( -webkit-Webkit 기반 및 -moz-Mozilla 기반) 다음은 업데이트 된 접두사가있는 동일한 바이올린입니다. jsfiddle.net/nBCxz/3
Derek 朕 會 功夫

@mkoistinen 당신이 맞아요. 새로운 바이올린은 필요한 모든 브라우저 접두사를 추가하고 최신 Chrome에서 작동합니다.
Howard

원시 링크 텍스트에는 닫는 괄호가 없습니다. 수정하려는 경우에 대비하여 여전히 완벽하게 사용할 수 있습니다 (변경할 수있는 6 자 미만).
trichoplax

35

매스 매 티카

다음은 매우 간단한 제출입니다.

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

전화 animateCircle[32]하면 32 줄과 원으로 깔끔한 애니메이션을 얻을 수 있습니다.

여기에 이미지 설명을 입력하십시오

Mathematica에서는 완전히 매끄럽지 만 GIF의 프레임 수를 약간 제한해야했습니다.

각 줄에 두 개의 디스크를 넣으면 어떻게됩니까? (즉, Disk[-Sin[t + phase]*line, 0.05]의 목록에 추가 하십시오 Map.)

여기에 이미지 설명을 입력하십시오

또한 위상을 90 °에서 벗어나게 할 수도 있습니다 ( Cos대신 사용 -Sin).

여기에 이미지 설명을 입력하십시오


아마 변경해야, 당신이 무슨 뜻인지 글리치 할 몰라 {t, 0, 2 \[Pi]}{t, 0, 2 \[Pi] - 2 \[Pi]/60, 2 \[Pi]/60}이 두 개의 동일한 프레임 수 변경되지 않도록 AnimateTable. 그런 다음 GIF를 내보낼 수 있습니다.

@swish 아니요 실제로 존재하지 않는 이상한 추가 라인과 디스크를 존재하지 않아야하는 위치 (및 실제 결과가없는 위치)에 디스크를 렌더링합니다 Animate. Table그래도 다시 사용하려고 합니다.
Martin Ender

@swish 그것은 효과가 있었다. 나는 어제 이와 같은 것을 시도했다고 생각했지만 분명히하지 않았다.
Martin Ender

25

VBScript + VBA + Excel 원형 차트

이렇게하면 프로세서가 약간 울리지 만 예쁘게 보이고 사양에 따라 작동한다고 생각합니다. @Fabricio의 답변을 원 운동 알고리즘을 구현하기위한 가이드로 사용했습니다.

편집 : 렌더링 속도를 향상시키기 위해 조정했습니다.

파이 차트의 스크린 샷

코드:

'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

그것은 줄 81, 오류 80070057, "주어진 이름을 가진 요소가 존재하지 않습니다"또는 이와 비슷한 것 (헝가리어에서 번역되었으므로 정확한 오류 메시지를 모르는 이유)에서 나에게 충돌합니다.
marczellm

Szervusz, @marczellm. "애니메이션"상태에서 차트 외부를 클릭하면 해당 오류를 재현 할 수 있습니다. 초점을 두어야합니다. 그렇지 않으면 프로그램 오류가 발생합니다. 그렇지 않으면 Office와의 비 호환성 때문일 수 있습니다. 저는 Win7에서 Office 2010을 사용하고 있습니다.
편안하게

Office 2007, Win7. 내 경우에는 차트에 전혀 초점이 맞지 않는 것 같습니다.
marczellm

21

Excel, 161 바이트

뛰어나다

=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 (마침표)는 전체 '혁명'에 대한 시간 (초)을 결정합니다.

라인 내의 각 셀은 해당 라인의 값과 관련된 기본 조건입니다. 예를 들어 K2는 다음과 같습니다.

 =1*(A5=7)

그리고 중앙 셀 (K9)은 다음과 같습니다.

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

무작위 셀에서 '삭제'를 눌러 애니메이션을 강제로 새로 고침을 트리거했습니다.

나는 이것이 오래된 주제라는 것을 알고 있지만 최근 활동으로 인해 정상에 올랐고 어떤 이유로 든 매력적으로 보였습니다. 장시간 PCG 청취자, 처음 발신자. 조심해


와우, 엑셀로 그렇게 할 수 있다는 것은 놀라운 일입니다. : D
Beta Decay

15

PSTricks와 재미를 위해.

여기에 이미지 설명을 입력하십시오

\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

포트란

각 프레임은 포트란 GIF 모듈에서 사용 개별 GIF 파일로 생성 http://fortranwiki.org/fortran/show/writegif을
그럼 한 애니메이션 GIF로 개별 GIF를 ImageMagick이 병합을 이용하여 약간의 속임수.

포트란

업데이트 : new = .true로 설정하십시오. 다음을 얻으려면 :

여기에 이미지 설명을 입력하십시오

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
나는 수직 및 수평 요소에 대한 충격 'squish'를 좋아합니다.
포틀랜드 주자

11

필수 C64 버전.

좋아하는 에뮬레이터에 복사하여 붙여 넣기 :

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

기본 설정을 다른 것으로 변경하는 소형 자바 스크립트 버전

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

HTML :

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

자바 스크립트 :

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
도넛을 만들었 습니까 ? 실제로 애니메이션은 작은 점으로 멋지게 보입니다 (시도 bw=10). 코드를 표시하려면 답변을 수정하십시오. 오, 그리고 당신이 그것을하는 동안 수정해야 할 버그가 있습니다 : 삼각 계산에서 바꾸기 time+i*0.39*0.29time+i*Math.PI/num좌표가의 값에 대해 올바르게 계산되도록하십시오 num. (PS 업데이트 JSFiddle 여기 . codegolf.stackexchange.com에 오신 것을 환영합니다)
squeamish ossifrage

나는 단지 다른 것을 만들고 싶었습니다 (거북처럼). 여기 codegolf의 초보자 :) 아, 그리고 공식에 감사드립니다 : DI는 서두르고 무작위 값을 시도했지만 올바른 공식에 도달하기 위해 1 분을 멈추지 않았습니다 : P
Diego

1
약간의 시각적 재미를위한 작은 변화 +1 : http://jsfiddle.net/9TQrm/ 또는 http://jsfiddle.net/Wrqs4/1/
Portland Runner

4

Elm 과 함께 합니다. 이 솔루션을 개선하기 위해 PR을 기꺼이 받아들이는 총 초보자입니다 ( GitHub ).

여기에 이미지 설명을 입력하십시오

이 제출물은 실제로 직선으로 움직이는 점입니다.

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
그 커서는 나를 속였고, 내 검거 나 그 크기도 아닙니다.
cole

2

세컨드 라이프 LSL

생기 거북이 시작 알파 이미지 (이미지를 저장하려면 아래를 클릭하십시오.)
turtle.png
거북이 알파 이미지의 끝 (이미지를 저장하려면 위를 클릭하십시오)

:
루트 프라임 실린더 크기를 <1, 1, 0.01> 슬라이스 0.49, 0.51, 색상 < 0, 0, 0>
은 따옴표없이이 실린더에 대한 설명을 "8,1,1,1"으로
만들고 (매우 중요) 실린더를 만들고 이름을 "cyl", 색상 <0.25, 0.25, 0.25> alpha 0.5
와 cyl 48 번
상자를 만들고 이름을 "sphere", color <1, ​​1, 1> 투명도 100을 제외하고 상단 투명도 0을 제외하고
거북 텍스처를 상자의 0면에 놓고 거북은 + x
상자를 48 번 복제 해야합니다
모든 상자와 실린더를 선택하고 마지막으로 루트 실린더를 선택하십시오.링크 (제어 L)

이 두 스크립트를 루트에 넣으십시오.

//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);
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.