Najbardziej kompaktowy kod symulowanej eksplozji

13

Czy potrafisz napisać program, który renderuje ekran rozbijającej się grupy pikseli (jak w prostym silniku cząstek) i czy możesz to zrobić przy dowolnej wyjątkowo małej liczbie znaków (naciśnięcia klawiszy)? (Przypomnij sobie lemingi z gry, kiedy ci mali faceci eksplodują, a ich małe piksele rozpadną się).

Ktoś zaprogramował tutaj prosty układ cząstek jako szkic przetwarzania i jest on dość potężny w porównaniu z tym, co moim zdaniem inni powinni być w stanie osiągnąć, jeśli spróbują. Byłbym jednak pod większym wrażeniem, gdyby ktoś mógł zrobić to samo w c ++ i sdl, a nawet java lub c #.

Todd Hopkinson
źródło
2
„Linie kodu” to metryka, która otwiera wiele niejednoznaczności i na pewno nie jest to [code-golf], który jest „liczbą znaków”, a czasem „liczbą bajtów”. Powiązana dyskusja na temat meta.
dmckee --- były moderator kociak
4
BTW - Kwestia, którą poruszyłem powyżej, i raczej niekompletna specyfikacja to rzeczy, które można by skutecznie opracować, omawiając to z góry na czacie Puzzle Lab lub Sandbox na meta . W każdym razie witamy na CodeGolf.SE.
dmckee --- były moderator kociak
Zaktualizowano pytanie, zastąpiono LOC liczbą znaków.
Todd Hopkinson
1
tak, jeśli napiszesz C / C ++ / Java / Any C pochodną, ​​możesz napisać cały system operacyjny w 1 linii kodu
Nate Koppenhaver

Odpowiedzi:

13

Python, 245 znaków

import random,time
R=lambda:random.randrange(-999,999)/1e3
P=[(40+20j,R()+1j*R())for i in' '*20]
for i in' '*20:
 C=([' ']*80+['\n'])*40
 for p,v in P:C[int(p.real)+81*int(p.imag)]='*'
 print''.join(C);P=[(p+v,v*.95)for p,v in P];time.sleep(.1)
Keith Randall
źródło
To nie jest eksplozja lemingowa, ale zdecydowanie +1 za zwięzłość!
Todd Hopkinson
10

C #, WPF - 1523

Niezbyt poważnie; była to głównie próba tego, czy rzeczywiście zadziałało.

To, co robię tutaj, to używanie ItemsControl (menu, ponieważ jest krótszy) w WPF do wyświetlania cząstek poprzez wiązanie danych i tworzenie szablonów. Szablon danych kontroluje wygląd cząstek (w tym przypadku proste kółko), a wiązanie danych steruje kolorem i położeniem cząstek.

Każda cząstka ma pozycję, kolor i kierunek, które są aktualizowane przez timer. Początkowo w środku okna generowana jest wiązka cząstek o losowych kierunkach (o rozkładzie normalnym). Ta kolekcja jest powiązana z danymi w ItemsControl, który następnie automatycznie wyświetla cząstki za każdym razem, gdy właściwości są aktualizowane. Cząstki są nieco przeciągane w dół z powodu grawitacji.

Trzeba przyznać, że trochę się wydłużyło. Ale przynajmniej ładnie wygląda:

wprowadź opis zdjęcia tutaj

Można go z pewnością skrócić, pomijając:

  • grawitacja, powodująca równomierne rozszerzanie się cząstek na wszystkie strony;
  • rozkład normalny dla wektorów początkowych, powodujący ekspansję cząstek w rzadkim »pudełku«;
  • zmiana jasności, pozostawiając czarne cząstki.

Zdecydowałem się tego nie robić w interesie estetyki. To rozwiązanie jest znacznie dłuższe niż prawie wszystko inne. Wiązanie danych i tworzenie szablonów może być eleganckie, ale jest również dość szczegółowe w porównaniu z prostą aktualizacją mapy bitowej. (Uwaga: obniżyłem to wszystko do 1356 roku , ale wtedy wygląda to okropnie.)

Kod jest rozpowszechniany w trzech plikach, które są tutaj sformatowane w celu zapewnienia czytelności:

App.xaml

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" StartupUri="W.xaml"/>

W.xaml

<Window x:Class="W" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Menu Name="i">
        <Menu.ItemTemplate>
            <DataTemplate>
                <Ellipse Width="2" Height="2" Fill="#000" Opacity="{Binding O}">
                    <Ellipse.RenderTransform>
                        <TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
                    </Ellipse.RenderTransform>
                </Ellipse>
            </DataTemplate>
        </Menu.ItemTemplate>
        <Menu.Template>
            <ControlTemplate>
                <ItemsPresenter/>
            </ControlTemplate>
        </Menu.Template>
        <Menu.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </Menu.ItemsPanel>
    </Menu>
</Window>

W.xaml.cs

using M = System.Math;
using T = System.Timers.Timer;
using System;
using System.ComponentModel;

partial class W
{
    int a;
    T t = new T(99);

    public W()
    {
        InitializeComponent();
        Height = Width = 500;
        var r = new Random();
        Func<double> n = () => 2 * (M.Sqrt(-2 * M.Log(r.NextDouble())) * M.Sin(6 * r.NextDouble()));
        var l = new System.Collections.Generic.List<P>();
        for (; a++ < 300; )
            l.Add(new P { X = 250, Y = 250, f = n(), g = n() });
        i.ItemsSource = l;
        t.Elapsed += delegate
        {
            foreach (P x in l)
            {
                x.X += x.f;
                x.Y += x.g += .2;
                x.O = M.Max(1 - M.Sqrt(M.Pow(250 - x.X, 2) + M.Pow(250 - x.Y, 2)) / 250, 0);
            }
        };
        t.Start();
    }
}

class P : System.Windows.ContentElement, INotifyPropertyChanged
{
    public double y, f, g;
    public double X { get; set; }
    public double O { get; set; }
    public double Y
    {
        get { return y; }
        set
        {
            y = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(""));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
Joey
źródło
1
+1 Świetnie wyglądający przykład! Podobnie jak te klasyczne eksplodujące lemingi minionych dni. I myślę, że to bije kod przetwarzania w początkowym pytaniu.
Todd Hopkinson
@icnivad: Muszę przyznać, że szkic przetwarzania (patrzyłem tylko na końcowy wynik, a nie kod) był moją inspiracją do tego.
Joey
Gah! Teraz przestaję grać w golfa. Do tej pory ma kilka fajnych sztuczek (takich jak PropertyChanged dla wszystkich właściwości i tylko na ostatniej ustawionej). Biorąc pod uwagę, że zacząłem od ponad 2000 znaków, myślę, że redukcja o 500 znaków nie jest taka zła. Do tej pory również stało się dość wolne. DispatcherTimer działa znacznie lepiej niż Timer, ale jest znacznie dłuższy. Jednak może kusi mnie, aby przenieść to do Silverlight i uruchomić na moim telefonie.
Joey
Myślę, że to ten, który jest lepszy od kombinacji rozmiaru kodu i jakości estetycznej eksplozji.
Todd Hopkinson
icnivad: Później przepiszę wszystko, aby malować bezpośrednio na mapie bitowej; powinno to być znacznie krótsze. 45% kodu to XAML; duża część kodu zaczyna wiązać elementy interfejsu użytkownika z właściwościami cząstek. Dodaj do tego ogólną gadatliwość języka C # i jest ona o wiele bardziej szczegółowa, niż powinna być.
Joey
7

PostScript - 287 244 znaków

currentpagedevice/q{exch def}def/PageSize get/z{dup 3 1 roll add exch 4 2 roll}def{2
div}forall/y/r{rand 2 27 exp div 8 sub}def q/x q[99{[x r y r]}repeat]50{dup{aload/t q
3 index 2 index 4 4 rectfill 1 sub z z t astore pop}forall showpage}repeat

Biegnij z gs -dNOPAUSE asplode.ps

Możesz nawet wydrukować i zrobić flipbook

Geoff Reedy
źródło
Wspaniale! To jest piękne!
użytkownik nieznany
5

JavaScript - 268 znaków

Oto 1-wymiarowa, 2-cząstkowa eksplozja:

javascript:d=document;c=d.createElement('canvas');d.body.appendChild(c);g=c.getContext("2d");function e(x,y,m){g.arc(x,y,m,0,2*Math.PI,false);g.fill()}function s(a,b,v,t){c.width=c.width;e(50+t*v,50,b);e(50+t*b*v/(b-a),50,a-b);setTimeout(function(){s(a,b,v,t+1)},100)};s(9,5,1,0)

Aby go uruchomić, otwórz pustą stronę about: w dobrej przeglądarce internetowej, wklej do paska adresu i naciśnij enter. Możesz zmodyfikować eksplozję, edytując wartości na końcu w s(10,5,1,0). Pierwsza wartość to rozmiar eksplodowanej cząstki. Druga wartość to rozmiar cząstki, która z niej eksploduje. Trzecią wartością jest prędkość wybuchającej z niej cząstki. Pozostaw „0” bez zmian.

david4dev
źródło
1
Nie działa to w przeglądarce Safari 5.0.5 (pokazuje coś, co wygląda trochę jak kij baseballowy) lub w przeglądarce Chrome 11.0.696.68 (pokazuje dwie kule, jedna nieco większa od drugiej, powoli się rozsuwające).
marinus
1
@marinus To, co dzieje się w Chrome, ma się wydarzyć.
david4dev
Nie mogę go uruchomić na FF4, IE8. :(
st0le
Testowałem to na Firefox 4.0.1 i Chromium 11.0.696.65. Spraw, abyś skopiował cały skrypt - łatwo mi pominąć nawias końcowy podczas kopiowania.
david4dev
@ st0le IE8 nie obsługuje tagu canvas , chyba że wykonasz kilka brudnych sztuczek: stackoverflow.com/questions/1332501/...
Cristian Lupascu
4

APL ( 120 118)

Ma ten sam rodzaj danych wyjściowych co pozycja Python (tzn. Po prostu wyświetla stany na siatce znaków). Tylko siatka ma wymiary 30 x 15, a źródło cząstek ma wymiary 15 x 7.

⍎⊃,⌿(9⍴⊂'(⎕DL.1)⊢{{(A+2↑⍵),0.95×A←2↓⍵}¨⍵⊣⎕←'' ⍟''[1+(⍳15 30)∊2↑¨⌊⍵]}'),⊂',⌿⍉10 4⍴⍎''⍬'',420⍴'',(7 15,.01×99-?2⍴199)'''
marinus
źródło
2

JavaScript 502 500 496

Jest to kombinacja odpowiedzi Joeya i david4dev (to bezwstydna kopia algorytmu Joeya zaimplementowana przy użyciu Javascript / canvas ☺):

W=500;H=250;function r(){return 2*m.sqrt(-2*m.log(m.random()))*m.sin(6*m.random())}function n(){z=[];for(i=W;i;i--){s={};s.x=s.y=H;s.f=r();s.g=r();z.push(s)}}function w(){x.clearRect(0,0,W,W);z.forEach(function(a){a.x+=a.f;a.y+=a.g+=.2;x.fillStyle="rgba(0,0,0,"+m.max(1-m.sqrt(m.pow(H-a.x,2)+m.pow(H-a.y,2))/H,0)+")";x.fillRect(a.x,a.y,2,2)})}z=[];m=Math;d=document;c=d.createElement("canvas");c.width=c.height=W;d.body.appendChild(c);x=c.getContext("2d");n();setInterval(n,2e3);setInterval(w,10)

Podgląd JSFiddle: http://jsfiddle.net/GVqFr/60/ (możesz nacisnąć przycisk TidyUp, aby ładnie sformatować kod)

Cristian Lupascu
źródło
@Qqwy Dzięki za edycję!
Cristian Lupascu
Nie jestem ekspertem od javascript, ale 500często używasz stałej . Jeśli można zdefiniować zmienną globalną a=500, można zaoszczędzić kilka znaków zastępując wszystko 500z a.
Pan Llama
@GigaWatt masz rację; to też działało 250.
Cristian Lupascu
1

Bash 380

C="4443311177"
t=".-xxXMXxx-."
alias c='echo -e "\e[2J"'
g(){
echo -e "\e[1;$4\e[$2;$1H$3"
}
f(){
x=$1
y=$2
p=$((2-RANDOM%5))
q=$((2-RANDOM%5))
for i in {-5..5}
do
x=$((x+p))
y=$((y+q))
n=$((5+i))
c=$((5+i))
g $x $y ${t:n:1} 3${C:c:1}m 
w=$(printf "%04i\n" $((5*i*i)))
sleep ${w/0/0.}
g $x $y " " 3${C:c:1}m
done
}
e(){
c
for i in {1..10}
do
f $((COLUMNS/2)) $((LINES/2)) &
done
}

Zadzwoń jak wybuch.

aktualizacja: pokolorowana

t = tekst, c = cls, g = gotoksy, f = mucha, C = KOLOR

nieznany użytkownik
źródło
1

C z SDL, 423 znaków

Ponieważ w oryginalnym opisie problemu wyraźnie wspomniano o SDL, czułem, że nadszedł czas na przesłanie rozwiązania SDL. Niestety, nazwy funkcji i struktur SDL nie są szczególnie zwięzłe, więc ten program jest trochę długi. W rzeczywistości nie mogę nawet pominąć #include.

#include<math.h>
#include"SDL.h"
SDL_Surface*s;SDL_Event e;SDL_Rect p;int i,n;double q[256];main(){
SDL_Init(SDL_INIT_VIDEO);s=SDL_SetVideoMode(320,320,32,0);
for(srand(time(0));e.type-SDL_QUIT;n=-~n%64){
for(i=256*!n;i;q[--i]=rand()%65536*9.5874e-5);
for(SDL_FillRect(s,0,i=0);++i<256;SDL_FillRect(s,&p,-n*67372036))
p.x=160+cos(q[i])*q[i-1]*n,p.y=160+sin(q[i])*q[i-1]*n,p.w=p.h=1;
SDL_Flip(s);SDL_Delay(50);SDL_PollEvent(&e);}}

(Ponieważ kod jest już tak duży, zostawiłem kilka dodatkowych bitów, aby skompilować bez ostrzeżeń. Czasami brakuje mi kompilacji bez ostrzeżeń. Usunięcie ich pozwoliłoby zaoszczędzić około 30 znaków).

Animacja działa w nieskończonej pętli. Zamknij okno, aby wyjść z programu. Każda eksplozja wykorzystuje nowy zestaw przypadkowych cząstek.

Chciałbym również wskazać liczbę 67372036w kodzie. Pojawia się w wyrażeniu ostatniego argumentu w drugim wywołaniu do SDL_FillRect(). W obecnym kodzie eksplozja jest renderowana w całości w odcieniach szarości. Lekka zmiana tej liczby doda bardzo subtelny, ale przyjemny efekt kolorystyczny do eksplozji. Liczba zabarwia 67372032cząsteczki na początku eksplozji, a liczba 67372034zapewnia efekt kolorystyczny, gdy znikają na końcu. Inne liczby mogą powodować mniej subtelne efekty zmiany kolorów. Zachęcam do wypróbowania ich.

chlebak
źródło
1

Po obejrzeniu innych świetnych przykładów tutaj postanowiłem spróbować i stworzyć funkcję cząstki, która mieści się w 140byt.es

JavaScript, 282 znaków

( 138 cząstek funkcja cząstki i 150 znaków podstawowa tablica rysunkowa płótna)

p=function(a,t,x,y,n,g,s,i,d){with(Math)for(i=n;i--;d=cos(i*sin(i*s)),a.globalAlpha=n/t/i,a.fillRect(x+t*sin(i)*d, y+t*cos(i)*d+t*g,2,2));};d=document;a=d.body.appendChild(d.createElement('canvas')).getContext('2d');t=setInterval("a.clearRect(0,0,300,150);p(a,t++, 50,50,1e3,.2,1)")

Przykład JSFiddle na żywo tutaj

Dzięki temu, że kod jest w pełni proceduralny, nie potrzebuję już kodu tablicy ani przypisania obiektu, co znacznie zmniejsza rozmiar. Wykonywanie efektu proceduralnego ma również inne fajne skutki uboczne.

Kod może zostać zmniejszony przez zwolnienie grawitacji, nasion, liczby cząstek itp., Ale myślę, że te funkcje są zbyt ładne, aby je usunąć;).

cechy

  • Konfigurowalny środek wybuchu X, Y.
  • Konfigurowalna liczba cząstek
  • Grawitacja w kierunku pionowym: Niech twoje cząsteczki spadną lub polecą w górę!
  • Siew, każde ziarno ma własną eksplozję i za każdym razem pokaże dokładnie tę eksplozję na komputerach.
  • Slowmotion, Fast Forward i odtwarzanie eksplozji Cofanie jest możliwe dzięki proceduralnemu sposobowi tworzenia efektu.
  • Rozmiar: 138 bajtów.

Sprawdź także w GitHub , aby uzyskać wersję z adnotacjami.

Qqwy
źródło
0

Python z PyGame, 240 znaków

Zdaję sobie sprawę, że w Pythonie jest już rozwiązanie, ale ponieważ ten drukuje tylko postacie, pomyślałem, że warto stworzyć taką, która rysuje fajną animację.

Niegolfowany, od czego zacząłem:

import math
import random
import pygame
pygame.init()

screen = pygame.display.set_mode((800, 800))
particles = [(random.gauss(0,.5), random.uniform(0,6.28318)) for i in range(2000)]

for i in range(399):
    screen.fill((255,255,255))
    for speed, angle in particles:
        distance = i * speed
        x = 400 + distance * math.cos(angle)
        y = 400 + distance * math.sin(angle)
        screen.set_at((int(x), int(y)), (0,0,0))
    pygame.display.flip()

Po wielu włamaniach. Pełny ekran, aby zapisać niektóre znaki. Nie używam dźwięku ani czcionek, więc myślę, że nie init()jest to konieczne (działa dla mnie).

import math as m,random,pygame
d,x,g=pygame.display,range(999),random.gauss
s,e=d.set_mode(),[(g(0,.2),g(0,9))for i in x]
for i in x:
 d.flip(),s.fill([255]*3)
 for v,a in e:
        y=400+i*v*m.cos(a),400+i*v*m.sin(a)
        s.set_at(map(int,y),[0]*3)
bezradny
źródło
0

Python - 327 znaków

Interesujące rzeczy:

  • Użyj liczby zespolonej jako wektora 2D
  • (v * cos(a), v * sin(a)) realizowane jako v*e**(1j*a)
  • Wygląda jak eksplozja 3D.
  • Powaga.

.

import pygame as P,random as R,math
R=R.random
D=P.display
D.init()
W=800
S=D.set_mode((W,W))
T=P.time.Clock()
C=lambda v:map(int,(v.real,v.imag))
X=[(8+R())*math.cos(R()*1.57)*2.7**(1j*R()*6.28) for i in range(999)]
for t in range(250):
 D.flip();T.tick(30);S.fill(2**24-1)
 for v in X:S.set_at(C(v*t+.005j*t*t+W/2*(1+1j)),0)
Promień
źródło
0

mieszkaniec 112

c.width^=0
t?o.push({X:1e3,Y:500,U:S(99*t),V:C(9*t)}):o=[]
o.map(a=>{a.X+=a.U,a.Y+=a.V,x.fillRect(a.X,a.Y,9,9)})

wypróbuj to, kopiując / wklejając kod do dwitter.net

Don Bright
źródło
Kiedy język jest późniejszy niż termin wyzwania, należy oznaczyć go jako niekonkurujący.
fəˈnɛtɪk