Matrix digital rain: Difference between revisions

m
Uploaded a new screenshot.
m (Uploaded a new screenshot.)
 
(16 intermediate revisions by 3 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'ide/qt/gl2'
coinsert'jgl2'
 
Line 1,285:
rows=: i.0
scale=: 24
live=: (#heat)#<i.3 0 3
 
updaterain_timer=: {{
try.
try. glfill 0 0 0 255 catch. wd'timer 0' return. end.
wd 'psel rain'
glfont font=.'courier ',":0.8*scale
glsel 'green'
upd=. 0>._3++/?2 2 2 2 4
glfill 0 0 0 255
cols=: cols,upd{.(?~{.sz)-.(-<.0.3*{:sz){.cols
glfont font=.'courier ',":0.8*scale
rows=: (#cols){.rows
upd=. 0>._3++/?2 2 2 2 4
live=: }.live,<(scale*cols,.rows),.?(#cols)##junk
cols=: cols,upd{.(?~{.sz)-.(-<.0.3*{:sz){.cols
for_p. live do.
rows=: (#cols){.rows
gltextcolor glrgb p_index{heat
live=: }.live,<(scale*cols,.rows),.?(#cols)##junk
if.p_index=<:#live do.
for_p. live do.
glfont font,' bold'
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.
for_xyj.;p do.glpaintx''
keep=: gltextxy 2rows<{.xyj:sz-1
cols=: keep#cols
gltext 8 u:junk{~{:xyj
rows=: keep#rows+1
end.
EMPTY
end. glpaint''
catch.
keep=: rows<{:sz-1
wd'ptimer 0'
cols=: keep#cols
end.
rows=: keep#rows+1
EMPTY
}}
sys_timer_z_=: update_base_
 
wd rplc&('DIMS';":scale*sz) {{)n
Line 1,316 ⟶ 1,322:
cc green isidraw flush;
pshow;
timerptimer 100
}}</syntaxhighlight>
 
[[File:J-matrix-digital-rain.png|thumb]]
 
Notes:
 
<tt>timerptimer 100</tt> to roughly match the update rate used in the matrix movie.
 
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 2,791 ⟶ 3,017:
{{libheader|DOME}}
The ''memory.ttf'' file is included with the DOME 'fonts' example and can be downloaded from [https://github.com/domeengine/dome/blob/main/examples/fonts/memory.ttf here].
<syntaxhighlight lang="ecmascriptwren">import "dome" for Window
import "graphics" for Canvas, Color, Font
import "random" for Random
884

edits