(単純なパーティクルエンジンのように)爆発するピクセルのグループを画面にレンダリングするプログラムを作成できますか。また、非常に少数の文字(キーストローク)でこれを実行できますか。(それらの小さな男が爆発し、小さなピクセルの破片が飛び散るときのゲームのレミングを思い出してください。)
誰かがここで簡単なパーティクルシステムを処理スケッチとしてプログラムしました。しかし、誰かがc ++とsdlで、あるいはjavaやc#でも同じことができたら、もっと感銘を受けるでしょう。
(単純なパーティクルエンジンのように)爆発するピクセルのグループを画面にレンダリングするプログラムを作成できますか。また、非常に少数の文字(キーストローク)でこれを実行できますか。(それらの小さな男が爆発し、小さなピクセルの破片が飛び散るときのゲームのレミングを思い出してください。)
誰かがここで簡単なパーティクルシステムを処理スケッチとしてプログラムしました。しかし、誰かがc ++とsdlで、あるいはjavaやc#でも同じことができたら、もっと感銘を受けるでしょう。
回答:
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)
それほど深刻ではありません。これは主に、実際に機能するかどうかの試みでした。
ここで行っているのは、WPFでItemsControl(メニューが短いため)を使用して、データバインディングとテンプレートを介してパーティクルを表示することです。データテンプレートは、パーティクルの外観(この場合は単純な円)を制御し、データバインディングはパーティクルの色と位置を制御します。
各パーティクルには、タイマーによって更新される位置、色、方向があります。最初に、(正規分布の)ランダムな方向で、ウィンドウの中央に多数のパーティクルが生成されます。そのコレクションはItemsControlにデータバインドされ、プロパティが更新されるたびに、パーティクルの表示を自動的に処理します。粒子は重力により少し引きずられます。
確かに少し長くなりました。しかし、少なくともそれは見栄えが良いです:

以下を省略することで確実に短くすることができます:
私は美学のためにそうしないことを選んだ。このソリューションは、他のほとんどすべての方法よりもずっと長くなります。データバインディングとテンプレート化のアプローチはエレガントかもしれませんが、単にビットマップを更新するのに比べてかなり冗長です。(注:上記のすべてを除外することで1356まで下げましたが、その時は恐ろしく見えます。)
コードは、読みやすいようにフォーマットされた形式でここに示されている3つのファイルで配布されます。
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" StartupUri="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>
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;
}
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
と走る gs -dNOPAUSE asplode.ps
印刷してフリップブックを作成することもできます
これは、1次元、2粒子、爆発です。
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)
実行するには、適切なWebブラウザーでabout:blankページを開き、URLバーに貼り付けてEnterキーを押します。の最後にある値を編集して、爆発を修正できますs(10,5,1,0)。最初の値は、展開されるパーティクルのサイズです。2番目の値は、そこから爆発するパーティクルのサイズです。3番目の値は、パーティクルが爆発する速度です。「0」のままにします。
これはJoeyの回答とdavid4devの回答の組み合わせです(Javascript / canvas usingを使用して実装されたJoeyのアルゴリズムの恥知らずなコピーです)。
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)
JSFiddleプレビュー:http ://jsfiddle.net/GVqFr/60/ (TidyUpボタンを押してコードを適切にフォーマットできます)
500をたくさん使用しています。グローバル変数を定義できる場合はa=500、すべて500をで置き換えることにより、いくつかの文字を保存できますa。
250もうまくいきました。
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
}
爆発のようにeを呼び出します。
t = text、c = cls、g = gotoxy、f = fly、C = COLOR
元の問題の説明でSDLが明示的に言及されていたため、SDLソリューションが提出されたのは過去のことだと感じました。残念ながら、SDL関数と構造体の名前は特に簡潔ではないため、このプログラムは少し長くなります。実際、私も除外することはできません#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);}}
(コードは既に非常に大きいので、警告なしでコンパイルできるように余分なビットを残しました。警告なしでコンパイルできない場合があります。それらを削除すると、約30文字節約できます。)
アニメーションは無限ループで実行されます。ウィンドウを閉じてプログラムを終了します。各爆発は、ランダムな粒子の新しいセットを使用します。
また67372036、コード内の番号を指摘したいと思います。の2回目の呼び出しの最後の引数の式に表示されSDL_FillRect()ます。コードが立っていると、爆発は完全に灰色でレンダリングされます。この数値をわずかに変更すると、爆発に非常に微妙ですが快適な色の効果が追加されます。番号67372032は爆発の開始時にパーティクルに色を付け、番号67372034は最後にフェードアウトするときに色効果を提供します。他の数値では、微妙な色の循環効果が少なくなる場合があります。ぜひ試してみることをお勧めします。
ここで他の素晴らしい例をいくつか見た後、私はそれを試して、140byt.esに適合するパーティクル関数を作成することにしました。
(138文字のパーティクル関数と150文字の基本的なキャンバス描画ボイラープレート)
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)")
コードを完全に手続き型にすることで、配列やオブジェクト割り当てコードが不要になり、サイズが大幅に削減されました。手続き型の効果を作成することには、他にもいくつかの素晴らしい副作用があります。
Gravity、Seeds、Number of Particlesなどを省略することでコードを小さくすることもできますが、これらの機能は削除するには余りにも良いと思います;)。
pythonにはすでに解決策があることがわかりますが、それは文字を印刷するだけなので、素敵なアニメーションを描くものを作成する価値があると思いました。
Ungolfed、私が始めたもの:
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()
多くのハッカーの後。一部のキャラクターを保存するフルスクリーン。音やフォントを使わないので、私init()は不必要だと思います(私にとってはうまくいきます)。
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)
興味深いもの:
(v * cos(a), v * sin(a)) として実装 v*e**(1j*a)。
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)