Skip to content

Instantly share code, notes, and snippets.

@timo

timo/ca.p6 Secret

Last active November 20, 2018 10:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timo/df03c7b36305ea3aaaace438f84422c1 to your computer and use it in GitHub Desktop.
Save timo/df03c7b36305ea3aaaace438f84422c1 to your computer and use it in GitHub Desktop.
1d cellular automaton simulator with SDL2 display
#!/usr/bin/env perl6
use NativeCall;
use SDL2::Raw;
use nqp;
my int ($w, $h) = 1280, 960;
my SDL_Window $window;
my SDL_Renderer $renderer;
SDL_Init(VIDEO);
$window = SDL_CreateWindow(
"cellular automaton simulator",
SDL_WINDOWPOS_CENTERED_MASK, SDL_WINDOWPOS_CENTERED_MASK,
$w, $h,
SHOWN
);
$renderer = SDL_CreateRenderer( $window, -1, ACCELERATED +| TARGETTEXTURE );
SDL_ClearError();
#my $noise_texture = SDL_CreateTexture($renderer, %PIXELFORMAT<RGB332>, STREAMING, $w, 1);
my $noise_texture = SDL_CreateTexture($renderer, %PIXELFORMAT<RGB555>, STREAMING, $w, 1);
#my CArray[int32] $points .= new;
my $pixdatabuf = CArray[int64].new(0);
my int $line-position;
my int @cells = flat 0, (0..1).roll($w), 0;
#my int @lut = 1, 0, 0, 1, 1, 0, 0, 1;
my int @lut;
my int @backbuf = @cells;
sub simulate(--> Nil) {
@backbuf = nqp::atpos_i(@cells, nqp::elems(@cells) - 2);
my int $left = nqp::atpos_i(@cells, 0) * 4;
my int $middle = nqp::atpos_i(@cells, 1) * 2;
loop (my int $i = 2; $i < $w; $i++) {
my int $right = nqp::atpos_i(@cells, $i);
my int $value = nqp::add_i(nqp::add_i(nqp::add_i($left, $middle), 2), $right);
$left = $middle +< 1;
$middle = $right +< 1;
nqp::push_i(@backbuf, nqp::atpos_i(@lut, $value));
}
@backbuf.push: @cells[1];
@cells = @backbuf;
}
my SDL_Rect $target .= new: 0, 0, $w * 2, 2;
my int @colors;
my int $color;
sub reset-field(--> Nil) {
@lut = (0..1).roll(8);
@cells[(^@cells).pick] = 1;
@cells[(^@cells).pick] = 0;
}();
sub reset-colors(--> Nil) {
@colors = ((0b111 .. 0b11111).rand.ceiling xx 3);
$color = @colors[0] +< 10 + @colors[1] +< 5 + @colors[2];
}();
sub render(--> Nil) {
my int $pitch;
# this is a work-around because i'm too dumb to figure out how
# to pass the pointer-pointer correctly.
my $pixdata = nativecast(Pointer[int64], $pixdatabuf);
SDL_LockTexture($noise_texture, SDL_Rect, $pixdata, $pitch);
#$pitch div= 4; # pitch is in bytes, so depending on the pixelformat
# we have, we will have to divide here.
$pitch div= 2;
$pixdata := nativecast(CArray[uint16], Pointer.new($pixdatabuf[0]));
my int $localw = $w;
my int $col;
loop ($col = 0; $col < $localw; $col++) {
# foo
nqp::bindpos_i(nqp::decont($pixdata),
#$pixdata.ASSIGN-POS(
$col,
#nqp::bitxor_i(nqp::bitxor_i($cursor, $row), $counter++));
nqp::atpos_i(@cells, nqp::add_i($col, 1)) * $color);
}
$target.y = nqp::add_i($target.y, 2);
if $target.y > nqp::mul_i($h, 2) {
$target.y = 0;
reset-colors;
reset-field if Bool.pick;
}
SDL_UnlockTexture($noise_texture);
SDL_RenderCopy($renderer, $noise_texture, SDL_Rect, $target);
SDL_RenderPresent($renderer);
}
my $event = SDL_Event.new;
my @times;
main: loop {
my $start = nqp::time_n();
while SDL_PollEvent($event) {
my $casted_event = SDL_CastEvent($event);
given $casted_event {
when *.type == QUIT {
last main;
}
}
}
simulate();
render();
@times.push: nqp::time_n() - $start;
}
@times .= sort;
my @timings = (@times[* div 50], @times[* div 4], @times[* div 2], @times[* * 3 div 4], @times[* - * div 100]);
say "frames per second:";
say (1 X/ @timings).fmt("%3.4f");
say "timings:";
say ( @timings).fmt("%3.4f");
say "";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment