-
-
Save timo/df03c7b36305ea3aaaace438f84422c1 to your computer and use it in GitHub Desktop.
1d cellular automaton simulator with SDL2 display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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