您是否可以编写一个程序来渲染一组爆炸的像素(如在简单的粒子引擎中),并且可以用很少数量的字符(按键)完成此操作?(回想一下游戏中的旅鼠,那时候这些小家伙会爆炸并且他们的小像素碎片飞散开来。)
有人在这里将一个简单的粒子系统编程为“ 处理”草图,与我认为其他人应该尝试完成的工作相比,它相当庞大。但是如果有人可以在c ++和sdl甚至Java或c#中做同样的事情,我会印象深刻。
您是否可以编写一个程序来渲染一组爆炸的像素(如在简单的粒子引擎中),并且可以用很少数量的字符(按键)完成此操作?(回想一下游戏中的旅鼠,那时候这些小家伙会爆炸并且他们的小像素碎片飞散开来。)
有人在这里将一个简单的粒子系统编程为“ 处理”草图,与我认为其他人应该尝试完成的工作相比,它相当庞大。但是如果有人可以在c ++和sdl甚至Java或c#中做同样的事情,我会印象深刻。
Answers:
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,然后每当属性更新时,ItemsControl就会自动处理显示粒子。粒子由于重力而向下拖动。
诚然,它有点冗长。但至少看起来不错:
可以通过省略来缩短它:
我选择不这样做是为了美观。该解决方案比几乎其他任何方法都长。数据绑定和模板化方法可能很优雅,但与仅更新位图相比,它也很冗长。(注意:我忽略了以上所有内容,将其降低到1356,但那时看起来太可怕了。)
该代码分布在三个文件中,为便于阅读,此处以格式化的形式给出:
<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
您甚至可以将其打印出来并制作为活动簿
这是一维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页面,粘贴到网址栏中,然后按Enter。您可以通过在末尾编辑值来修改爆炸s(10,5,1,0)
。第一个值是爆炸的粒子的大小。第二个值是从中爆炸出来的粒子的大小。第三个值是粒子从其中爆炸的速度。保持“ 0”不变。
这是Joey和david4dev答案的结合(这是使用Javascript / canvas☺实现的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 =文字,c = cls,g =果胶,f =果蝇,C =颜色
由于最初的问题描述明确提到了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
代码中的数字。它出现在第二个调用中的最后一个参数的表达式中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)")
通过使代码完全具有过程性,我不再需要任何数组或对象分配代码,从而大大减少了代码大小。产生程序效果还具有其他一些不错的副作用。
通过省略重力,种子,粒子数等可以使代码更小,但是我认为这些功能太好了,无法删除;)。
还可以在GitHub上检出带注释的版本。
我意识到python中已经存在一种解决方案,但是由于该解决方案仅打印字符,所以我认为制作一个可以绘制精美动画的解决方案是值得的。
脱胎换骨,我从什么开始:
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)