Matrix digital rain: Difference between revisions
Content deleted Content added
m →{{header|Wren}}: Changed to Wren S/H |
→{{header|Locomotive Basic}}: add screenshot |
||
(16 intermediate revisions by 2 users not shown) | |||
Line 1,274:
Some key issues are the (deliberate) relatively low resolution of the screen in the movie, a somewhat slow update rate and some variation over time in the update rate of the screen. This implementation is, of course, only an approximation...
<syntaxhighlight lang="j">require'
coinsert'jgl2'
Line 1,285:
rows=: i.0
scale=: 24
live=: (#heat)#<i.
try.
wd 'psel rain'
glsel 'green'
glfill 0 0 0 255
glfont font=.'courier ',":0.8*scale
upd=. 0>._3++/?2 2 2 2 4
cols=: cols,upd{.(?~{.sz)-.(-<.0.3*{:sz){.cols
rows=: (#cols){.rows
live=: }.live,<(scale*cols,.rows),.?(#cols)##junk
for_p. live do.
gltextcolor glrgb p_index{heat
if.p_index=<:#live do.
glfont font,' bold'
end.
for_xyj.;p do.
gltextxy 2{.xyj
gltext 8 u:junk{~{:xyj
end.
end.
keep=:
cols=: keep#cols
rows=: keep#rows+1
EMPTY
catch.
wd'ptimer 0'
end.
}}
wd rplc&('DIMS';":scale*sz) {{)n
Line 1,316 ⟶ 1,322:
cc green isidraw flush;
pshow;
}}</syntaxhighlight>
[[File:J-matrix-digital-rain.png|thumb]]
Notes:
<tt>
In the movie, the display was somewhat pixelated, and had some other artifacts which were characteristic of cathode display tubes. The font support we use here does not emulate all of that.
Conceptually, we are emulating an emulation of a cathode ray tube with a long phosphor persistence time. Thus, there's an initial "burst" of light when the phosphor is being painted followed by a lingering glow which gradually fades out. Here, we use a <span style="background-color: black; color: #e0ffff"> light cyan </span> to represent the initial paint event and <span style="color: #00ff00">f</span><span style="color: #00ec00">a</span><span style="color: #00da00">d</span><span style="color: #00c900">i</span><span style="color: #00b900">n</span><span style="color: #00aa00">g</span><span style="color: #009b00"> </span><span style="color: #008d00">s</span><span style="color: #007f00">h</span><span style="color: #007200">a</span><span style="color: #006600">d</span><span style="color: #005b00">e</span><span style="color: #004f00">s</span><span style="color: #004500"> </span><span style="color: #003b00">o</span><span style="color: #003100">f</span><span style="color: #002800"> </span><span style="color: #001f00">g</span><span style="color: #001700">r</span><span style="color: #000f00">e</span><span style="color: #000700">e</span><span style="color: #000000">n</span> to represent the fading phosphors. To better approximate the phosphor persistence mechanism, we have intensity fall off exponentially (and then we adjust the numeric range of the result so it still fades from our brightest green to black).
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.JFrame;
public final class MatrixDigitalRain {
public static void main(String[] args) {
EventQueue.invokeLater( () -> {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Matrix Digital Rain");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
DigitalRain digitalRain = new DigitalRain(800, 600);
frame.add(digitalRain);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
digitalRain.start();
} );
}
private static final class DigitalRain extends Canvas {
public DigitalRain(int aWidth, int aHeight) {
setPreferredSize( new Dimension(aWidth, aHeight) );
setBackground(Color.BLACK);
columnCount = aWidth / ( 2 * halfColumnWidth ) - 1;
rowCount = aHeight / ( 2 * halfFontSize );
setCursor(getToolkit().createCustomCursor(
new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB), new Point(0, 0), "transparent"));
executiveService = Executors.newSingleThreadExecutor();
random = ThreadLocalRandom.current();
}
public void start() {
requestFocus();
createBufferStrategy(2);
executiveService.execute( new DrawingCycle(rowCount) );
}
private final class DrawingCycle implements Runnable {
public DrawingCycle(int rowCount) {
columns = Stream.generate( () -> new Column(rowCount) )
.limit(columnCount).collect(Collectors.toList());
bufferStrategy = getBufferStrategy();
scheduler = Executors.newSingleThreadScheduledExecutor();
}
@Override
public void run() {
scheduler.scheduleAtFixedRate( () -> { draw(); update(); }, 0, 100, TimeUnit.MILLISECONDS);
}
private void draw() {
Graphics2D graphics2D = (Graphics2D) bufferStrategy.getDrawGraphics();
graphics2D.setColor(Color.BLACK);
graphics2D.fillRect(0, 0, getWidth(), getHeight());
for ( int col = 0; col < columnCount; col++ ) {
for ( int row = 0; row < rowCount; row++ ) {
Symbol symbol = columns.get(col).symbols.get(row);
graphics2D.setFont(symbol.font);
graphics2D.setColor(symbol.color());
final int size = symbol.font.getSize();
graphics2D.drawString(
symbol.element,
2 * halfColumnWidth * col + halfColumnWidth + ( 6 * halfFontSize - size ) / 2,
row * 2 * halfFontSize);
}
}
graphics2D.dispose();
bufferStrategy.show();
}
private void update() {
for ( Column column : columns ) {
if ( column.index >= 0 ) {
String element = elements.get(random.nextInt(elements.size()));
column.symbols.set(column.index, new Symbol(element, column.font, 255) );
}
column.index = Math.min(column.index + 1, rowCount);
column.darken();
if ( column.index == rowCount ) {
column.reset();
}
}
}
private final List<Column> columns;
private final BufferStrategy bufferStrategy;
private final ScheduledExecutorService scheduler;
} // End DrawingCycle class
private final class Column {
public Column(int aRowCount) {
rowCount = aRowCount;
index = random.nextInt(-rowCount, rowCount);
setFont();
symbols = Stream.generate( () -> new Symbol(font) ).limit(rowCount).collect(Collectors.toList());
}
public void darken() {
symbols.stream().forEach(Symbol::darken);
}
public void reset() {
index = random.nextInt(-rowCount, rowCount / 2);
setFont();
}
private void setFont() {
final int fontSize = ( random.nextInt(2) == 0 ) ?
2 * halfFontSize : ( random.nextInt(2) == 0 ) ?
(int) ( 1.5 * halfFontSize ) : 3 * halfFontSize;
final int fontStyle = ( random.nextInt(3) == 0 ) ? Font.BOLD : Font.PLAIN;
font = new Font("Dialog", fontStyle, fontSize);
}
private int index;
private Font font;
private List<Symbol> symbols;
private final int rowCount;
} // End Column class
private final class Symbol {
public Symbol(String aElement, Font aFont, int aBrightness) {
element = aElement;
font = aFont;
brightness = aBrightness;
}
public Symbol(Font font) {
this(" ", font, 0);
}
public Color color() {
return new Color(0, 255, 0, brightness);
}
public void darken() {
brightness = Math.max(0, brightness - 5);
}
public String toString() {
return element;
}
private int brightness;
private final Font font;
private final String element;
} // End Symbol class
private final int columnCount;
private final int rowCount;
private final ExecutorService executiveService;
private final int halfFontSize = 6;
private final int halfColumnWidth = 10;
private final ThreadLocalRandom random;
private final List<String> elements = List.of(
"M", "Ї", "Љ", "Њ", "Ћ", "Ќ", "Ѝ", "Ў", "Џ", "Б", "Г", "Д", "Ж", "И", "Й", "Л", "П", "Ф", "Ц", "Ч", "Ш",
"Щ", "Ъ", "Ы", "Э", "Ю", "Я", "в", "д", "ж", "з", "и", "й", "к", "л", "м", "н", "п", "т", "ф", "ц", "ч",
"ш", "щ", "ъ", "ы", "ь", "э", "ю", "я", "ѐ", "ё", "ђ", "ѓ", "є", "ї", "љ", "њ", "ћ", "ќ", "ѝ", "ў", "џ",
"Ѣ", "ѣ", "ѧ", "Ѯ", "ѱ", "Ѳ", "ѳ", "ҋ", "Ҍ", "ҍ", "Ҏ", "ҏ", "Ґ", "ґ", "Ғ", "ғ", "Ҕ", "ҕ", "Җ", "җ", "Ҙ",
"ҙ", "Қ", "қ", "ҝ", "ҟ", "ҡ", "Ң", "ң", "Ҥ", "ҥ", "ҩ", "Ҫ", "ҫ", "Ҭ", "ҭ", "Ұ", "ұ", "Ҳ", "ҳ", "ҵ", "ҷ",
"ҹ", "Һ", "ҿ", "Ӂ", "ӂ", "Ӄ", "ӄ", "ӆ", "Ӈ", "ӈ", "ӊ", "Ӌ", "ӌ", "ӎ", "Ӑ", "ӑ", "Ӓ", "ӓ", "Ӕ", "ӕ", "Ӗ",
"ӗ", "Ә", "ә", "Ӛ", "ӛ", "Ӝ", "ӝ", "Ӟ", "ӟ", "ӡ", "Ӣ", "ӣ", "Ӥ", "ӥ", "Ӧ", "ӧ", "Ө", "ө", "Ӫ", "ӫ", "Ӭ",
"ӭ", "Ӯ", "ӯ", "Ӱ", "ӱ", "Ӳ", "ӳ", "Ӵ", "ӵ", "Ӷ", "ӷ", "Ӹ", "ӹ", "Ӻ", "ӽ", "ӿ", "Ԁ", "ԍ", "ԏ", "Ԑ", "ԑ",
"ԓ", "Ԛ", "ԟ", "Ԧ", "ԧ", "Ϥ", "ϥ", "ϫ", "ϭ", "ゥ", "ェ", "ォ", "ャ", "ュ", "ョ", "ッ", "ー", "ア", "イ", "ウ", "エ",
"オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ",
"ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ヤ", "ユ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ン", "ⲁ",
"Ⲃ", "ⲃ", "Ⲅ", "Γ", "Δ", "Θ", "Λ", "Ξ", "Π", "Ѐ", "Ё", "Ђ", "Ѓ", "Є", "ⲉ", "Ⲋ", "ⲋ", "Ⲍ", "ⲍ", "ⲏ", "ⲑ",
"ⲓ", "ⲕ", "ⲗ", "ⲙ", "ⲛ", "Ⲝ", "ⲝ", "ⲡ", "ⲧ", "ⲩ", "ⲫ", "ⲭ", "ⲯ", "ⳁ", "Ⳉ", "ⳉ", "ⳋ", "ⳤ", "⳥", "⳦", "⳨",
"⳩", "∀", "∁", "∂", "∃", "∄", "∅", "∆", "∇", "∈", "∉", "∊", "∋", "∌", "∍", "∎", "∏", "∐", "∑", "∓",
"ℇ", "ℏ", "℥", "Ⅎ", "ℷ", "⩫", "⨀", "⨅", "⨆", "⨉", "⨍", "⨎", "⨏", "⨐", "⨑", "⨒", "⨓", "⨔", "⨕", "⨖",
"⨗", "⨘", "⨙", "⨚", "⨛", "⨜", "⨝", "⨿", "⩪" );
} // End DigitalRain class
} // End MatrixDigitalRain class
</syntaxhighlight>
{{ out }}
A screenshot from the running program.
[[Media: JavaMatrixDigitalRain.png]]
=={{header|Javascript}}==
Line 1,583 ⟶ 1,809:
=={{header|Locomotive Basic}}==
[[File:Matrix mode 3 locomotive basic.png|thumb|Output in CPCBasic (graphics mode 3 version)]]
<syntaxhighlight lang="locobasic">10 mode 0:defint a-z:randomize time:ink 0,0:ink 1,26:ink 2,19:border 0
20 dim p(20):mm=5:dim act(mm):for i=1 to mm:act(i)=rnd*19+1:next
|