Code le plus compact pour une explosion simulée

13

Pouvez-vous écrire un programme qui rend l'écran d'un groupe de pixels éclatant (comme dans un simple moteur de particules) et pouvez-vous le faire en un nombre remarquablement petit de caractères (touches)? (Rappelez-vous les lemmings du jeu, lorsque ces petits gars explosaient et que leurs petits morceaux de pixels se séparaient.)

Quelqu'un a programmé un simple système de particules ici comme une esquisse de traitement et c'est assez lourd par rapport à ce que je pense que d'autres devraient pouvoir accomplir s'ils essayaient. Mais je serais beaucoup plus impressionné si quelqu'un pouvait faire de même en c ++ et sdl, ou même java ou c #.

Todd Hopkinson
la source
2
"Lignes de code" est une métrique qui ouvre beaucoup d'ambiguïté, et n'est certainement pas [code-golf] qui est "nombre de caractères" ou parfois "nombre d'octets". Discussion connexe sur la méta.
dmckee --- chaton ex-modérateur
4
BTW - Le problème que j'ai soulevé ci-dessus, et la spécification plutôt incomplète sont des choses qui auraient pu être utilement résolues en discutant à l'avance dans le chat Puzzle Lab ou le Sandbox sur la méta . Mais, en tout cas, bienvenue sur CodeGolf.SE.
dmckee --- chaton ex-modérateur
Question mise à jour, remplacé LOC par le nombre de caractères.
Todd Hopkinson,
1
oui, si vous écrivez C / C ++ / Java / Tout dérivé C, vous pouvez écrire un système d'exploitation complet en 1 ligne de code
Nate Koppenhaver

Réponses:

13

Python, 245 caractères

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
la source
Ce n'est pas une explosion de lemming, mais certainement un +1 pour plus de brièveté!
Todd Hopkinson
10

C #, WPF - 1523

Pas terriblement sérieux; c'était principalement une tentative pour savoir si cela fonctionnait réellement.

Ce que je fais ici, c'est d'utiliser un ItemsControl (Menu, car il est plus court) dans WPF pour afficher les particules via la liaison de données et les modèles. Un modèle de données contrôle l'apparence des particules (dans ce cas, un simple cercle) et la liaison de données contrôle la couleur et la position des particules.

Chaque particule a une position, une couleur et une direction qui sont mises à jour par une minuterie. Initialement, un tas de particules sont générées au centre de la fenêtre avec des directions aléatoires (réparties normalement). Cette collection est liée aux données à ItemsControl qui gère ensuite l'affichage automatique des particules, chaque fois que les propriétés sont mises à jour. Les particules sont un peu entraînées par la gravité.

Certes, cela a pris un peu de temps. Mais au moins ça a l'air sympa:

enter image description here

Il peut sûrement être raccourci en omettant:

  • gravité, provoquant une expansion uniforme des particules de tous les côtés;
  • la distribution normale des vecteurs initiaux, provoquant l'expansion des particules dans une «boîte» clairsemée;
  • la variation de luminosité, laissant les particules noires.

J'ai choisi de ne pas le faire dans un souci d'esthétique. Cette solution est bien plus longue que presque tout le reste. L'approche de liaison de données et de modèles peut être élégante, mais elle est également assez détaillée par rapport à la simple mise à jour d'une image bitmap. (Remarque: je l'ai compris 1356 en omettant tout ce qui précède, mais ça a l'air horrible alors.)

Le code est distribué dans trois fichiers, qui sont donnés ici sous forme formatée pour plus de lisibilité:

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
la source
1
+1 Un bel exemple! Tout comme ces lemmings explosifs classiques d'autrefois. Et je pense que cela bat le code de traitement dans la question initiale.
Todd Hopkinson
@icnivad: Je dois admettre que l'esquisse de traitement (je n'ai regardé que le résultat final, pas le code) a été mon inspiration pour les looks.
Joey
Gah! J'arrête de jouer au golf maintenant. Il contient maintenant de belles astuces (comme le PropertyChanged pour toutes les propriétés et uniquement sur la dernière qui est définie). Étant donné que j'ai commencé au-dessus de 2000 caractères, je suppose qu'une réduction de 500 caractères n'est pas trop mauvaise. Il est également devenu assez lent maintenant. DispatcherTimer fonctionne beaucoup mieux que Timer, mais est beaucoup plus long. Je pourrais être tenté de porter cela sur Silverlight et de l'exécuter sur mon téléphone.
Joey
Je pense que c'est celui à battre pour la combinaison de la taille du code et de la qualité esthétique de l'explosion.
Todd Hopkinson
icnivad: Je réécrirai le tout pour peindre directement sur un bitmap plus tard; il devrait donc être beaucoup plus court. 45% du code sont XAML; une grande partie du code permet de lier des éléments d'interface utilisateur aux propriétés des particules. Ajoutez à cela la verbosité générale de C # et c'est beaucoup plus verbeux qu'il ne devrait l'être.
Joey
7

postscript - 287 244 caractères

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

courir avec gs -dNOPAUSE asplode.ps

Vous pouvez même l'imprimer et faire un flipbook

Geoff Reedy
la source
Formidable! C'est beau!
utilisateur inconnu
5

Javascript - 268 caractères

Voici une explosion à 1 dimension, 2 particules:

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)

Pour l'exécuter, ouvrez une page about: blank dans un bon navigateur Web, collez-la dans la barre d'url et appuyez sur Entrée. Vous pouvez modifier l'explosion en modifiant les valeurs à la fin de s(10,5,1,0). La première valeur est la taille de la particule qui est éclatée. La deuxième valeur est la taille de la particule qui en est éclatée. La troisième valeur est la vitesse de l'explosion de la particule. Laissez le «0» tel quel.

david4dev
la source
1
Cela ne fonctionne pas dans Safari 5.0.5 (montre quelque chose qui ressemble un peu à une batte de baseball) ou dans Chrome 11.0.696.68 (montre deux balles, l'une légèrement plus grande que l'autre, s'écartant lentement).
marinus
1
@marinus ce qui se passe dans Chrome est ce qui est censé se produire.
david4dev
Impossible de le faire fonctionner sur FF4, IE8. :(
st0le
Eh bien, je l'ai testé sur Firefox 4.0.1 et Chromium 11.0.696.65. Faites en sorte que vous ayez copié l'intégralité du script - je trouve qu'il est facile de passer à côté du crochet de fin lors de la copie.
david4dev
@ st0le IE8 ne prend pas en charge la balise canvas , sauf si vous effectuez quelques trucs sales: stackoverflow.com/questions/1332501/…
Cristian Lupascu
4

APL ( 120 118)

Il a le même type de sortie que l'entrée Python (c'est-à-dire qu'il ne sort que les états sur une grille de caractères). Seule la grille est de 30x15 et l'origine des particules est de 15x7.

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

JavaScript 502 500 496

Ceci est une combinaison des réponses de Joey et david4dev (c'est une copie éhontée de l'algorithme de Joey implémenté en utilisant 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)

Aperçu de JSFiddle: http://jsfiddle.net/GVqFr/60/ (vous pouvez appuyer sur le bouton TidyUp pour bien formater le code)

Cristian Lupascu
la source
@Qqwy Merci pour la modification!
Cristian Lupascu
Je ne suis pas un expert en javascript, mais vous utilisez 500beaucoup la constante . Si vous pouvez définir une variable globale a=500, vous pouvez enregistrer quelques caractères en les remplaçant tous 500par a.
M. Llama
@GigaWatt vous avez raison; qui a fonctionné 250aussi.
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
}

Appelez e comme exploser.

mise à jour: colorisée

t = texte, c = cls, g = gotoxy, f = fly, C = COLOR

Utilisateur inconnu
la source
1

C avec SDL, 423 caractères

Étant donné que la description du problème d'origine mentionnait explicitement SDL, je pensais qu'il était temps qu'une solution SDL soit soumise. Malheureusement, les noms de la fonction et des structures SDL ne sont pas particulièrement concis, donc ce programme est un peu long. En fait, je ne peux même pas laisser de côté #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);}}

(Étant donné que le code est déjà si énorme, j'ai laissé quelques bits supplémentaires pour qu'il compile sans avertissements. Parfois, la compilation sans avertissements me manque. Les supprimer ferait économiser environ 30 caractères environ.)

L'animation s'exécute dans une boucle infinie. Fermez la fenêtre pour quitter le programme. Chaque explosion utilise un nouvel ensemble de particules aléatoires.

Je voudrais également signaler le numéro 67372036dans le code. Il apparaît dans l'expression du dernier argument du deuxième appel à SDL_FillRect(). En l'état, l'explosion est entièrement rendue en gris. Changer légèrement ce nombre ajoutera un effet de couleur très subtil mais agréable à l'explosion. Le nombre 67372032colore les particules au début de l'explosion, tandis que le nombre 67372034fournit un effet de couleur lorsqu'elles disparaissent à la fin. D'autres nombres peuvent produire des effets de cycle de couleur moins subtils. Je vous encourage à les essayer.

boite à pain
la source
1

Après avoir vu quelques-uns des autres grands exemples ici, j'ai décidé d'essayer et de créer une fonction de particules qui s'intègre dans essayer 140byt.es

Javascript, 282 caractères

( Fonction de particules de 138 caractères et passe- partout de dessin sur toile de base de 150 caractères)

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

Exemple JSFiddle en direct ici

En rendant le code entièrement procédural, je n'avais plus besoin de tableau ou de code d'affectation d'objet, ce qui réduisait considérablement la taille. Faire un effet procédural a également quelques autres effets secondaires intéressants.

Le code pourrait être réduit en omettant Gravity, Seeds, Number of Particles, etc., mais je pense que ces fonctionnalités sont trop agréables à supprimer;).

traits

  • Centre d'explosion X, Y configurable.
  • Nombre de particules configurable
  • Gravité dans le sens vertical: faites tomber ou voler vos particules!
  • Seedable, chaque graine a sa propre explosion et montrera exactement cette explosion à chaque fois, à travers les ordinateurs.
  • Slowmotion, Fast Forward et jouer des explosions en arrière est possible, en raison de la façon procédurale avec laquelle l'effet est créé.
  • Taille: 138 octets.

Consultez-le également sur GitHub , pour une version annotée.

Qqwy
la source
0

Python avec PyGame, 240 caractères

Je me rends compte qu'il existe déjà une solution en python, mais comme celui-ci ne fait qu'imprimer des caractères, j'ai pensé qu'il serait utile d'en faire une qui dessine une belle animation.

Ungolfed, ce que j'ai commencé avec:

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

Après beaucoup de hackery. Plein écran pour enregistrer certains caractères. Ne pas utiliser de son ou de polices, donc je pense que ce init()n'est pas nécessaire (ça marche pour moi).

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)
Aucune idée
la source
0

Python - 327 caractères

Choses intéressantes:

  • Utiliser un nombre complexe comme vecteur 2D
  • (v * cos(a), v * sin(a)) mis en œuvre comme v*e**(1j*a)
  • On dirait une explosion 3D.
  • La gravité.

.

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)
Rayon
la source
0

habitant 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)})

essayez-le en copiant / collant le code sur dwitter.net

Don Bright
la source
Lorsque la langue est postérieure au défi, vous êtes censé la marquer comme non compétitive.
fəˈnɛtɪk