Skip to content

Instantly share code, notes, and snippets.

@timo

timo/snake.pl Secret

Created November 19, 2014 17:32
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/326205e041d3c184a5c7 to your computer and use it in GitHub Desktop.
Save timo/326205e041d3c184a5c7 to your computer and use it in GitHub Desktop.
a little implementation of snake. try to bite off your own tail!
use v6;
use NativeCall;
use SDL2::Raw;
use Cairo;
constant W = 1280;
constant H = 960;
constant FIELDW = W div 32;
constant FIELDH = H div 32;
SDL_Init(VIDEO);
my CArray[SDL_Window] $pass_win .= new;
my CArray[SDL_Renderer] $pass_render .= new;
$pass_win[0] = SDL_Window;
$pass_render[0] = SDL_Renderer;
say SDL_CreateWindowAndRenderer(1280, 960, 2, $pass_win, $pass_render);
my $window = $pass_win[0];
my $render = $pass_render[0];
my $snake_image = Cairo::Image.record(
-> $_ {
.save;
.rectangle: 0, 0, 64, 64;
.clip;
.rgb: 0, 1, 0;
.rectangle: 0, 0, 64, 64;
.fill :preserve;
.rgb: 0, 0, 0;
.stroke;
.restore;
.save;
.translate: 64, 0;
.rectangle: 0, 0, 64, 64;
.clip;
.rgb: 1, 0, 0;
.arc: 32, 32, 30, 0, 2 * pi;
.fill :preserve;
.rgb: 0, 0, 0;
.stroke;
.restore;
}, 128, 128, FORMAT_ARGB32);
my $snake_texture = SDL_CreateTexture($render, %PIXELFORMAT<ARGB8888>, STATIC, 128, 128);
SDL_UpdateTexture($snake_texture, SDL_Rect.new(:x(0), :y(0), :w(128), :h(128)), $snake_image.data, $snake_image.stride // 128 * 4);
SDL_SetTextureBlendMode($snake_texture, 1);
SDL_SetRenderDrawBlendMode($render, 1);
my $snakepiece_srcrect = SDL_Rect.new(:w(64), :h(64));
my $foodpiece_srcrect = SDL_Rect.new(:x(64), :w(64), :h(64));
my @times;
my num $start = nqp::time_n();
my $event = SDL_Event.new;
enum GAME_KEYS (
K_UP => 82,
K_DOWN => 81,
K_LEFT => 80,
K_RIGHT => 79,
K_SPACE => 44,
);
my %down_keys;
my Complex @snakepieces = 10 + 10i;
my Complex @noms;
my $nomspawn = 0;
my $snakespeed = 0.1;
my $snakestep = 0;
my Complex $snakedir = 1+0i;
my $nom = 4;
my num $last_frame_start = nqp::time_n();
main: loop {
my num $start = nqp::time_n();
my $dt = $start - $last_frame_start // 0.00001;
while SDL_PollEvent($event) {
my $casted_event = SDL_CastEvent($event);
given $casted_event {
when *.type == QUIT {
last main;
}
when *.type == KEYDOWN {
if GAME_KEYS(.scancode) -> $comm {
%down_keys{$comm} = 1;
} else { say "new keycode found: $_.scancode()"; }
CATCH { say $_ }
}
when *.type == KEYUP {
if GAME_KEYS(.scancode) -> $comm {
%down_keys{$comm} = 0;
} else { say "new keycode found: $_.scancode()"; }
CATCH { say $_ }
}
}
}
if %down_keys<K_LEFT> {
$snakedir = -1+0i unless $snakedir == 1+0i;
} elsif %down_keys<K_RIGHT> {
$snakedir = 1+0i unless $snakedir == -1+0i;
} elsif %down_keys<K_UP> {
$snakedir = 0-1i unless $snakedir == 0+1i;
} elsif %down_keys<K_DOWN> {
$snakedir = 0+1i unless $snakedir == 0-1i;
}
if ($nomspawn -= $dt) < 0 {
$nomspawn += 1;
@noms.push: (^FIELDW).pick + (^FIELDH).pick\i + 1 + 1i unless @noms > 3;
@noms.pop if @noms[*-1] == any(@snakepieces);
}
if ($snakestep -= $dt) < 0 {
$snakestep += $snakespeed;
@snakepieces.unshift: do given @snakepieces[0] {
($_.re + $snakedir.re) % FIELDW
+ (($_.im + $snakedir.im) % FIELDH)\i
}
if @snakepieces[2..*].first-index({ $_ == @snakepieces[0] }) -> $idx {
@snakepieces = @snakepieces[1..($idx + 1)];
}
@noms .= grep({
$^piece == @snakepieces[0] ?? ($nom = $nom + 3) && False
!! True
});
if $nom == 0 {
@snakepieces.pop;
} else {
$nom = $nom - 1;
}
}
for @snakepieces {
SDL_SetTextureColorMod($snake_texture, 255, (cos((++$) / 10) * 100 + 155).round, 255);
SDL_RenderCopy($render, $snake_texture,
$snakepiece_srcrect,
SDL_Rect.new(:x(.re.Int * 32 - 16), :y(.im.Int * 32 - 16), :w(32), :h(32)));
}
SDL_SetTextureColorMod($snake_texture, 255, 255, 255);
for @noms {
SDL_RenderCopy($render, $snake_texture,
$foodpiece_srcrect,
SDL_Rect.new(:x(.re.Int * 32 - 16), :y(.im.Int * 32 - 16), :w(32), :h(32)));
}
SDL_RenderPresent($render);
SDL_SetRenderDrawColor($render, 0, 0, 0, 0);
SDL_RenderClear($render);
nqp::force_gc() if 5.rand < 1;
@times.push: nqp::time_n() - $start;
$last_frame_start = $start;
}
SDL_Quit();
@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