This is part two of our Tetris-like clone in J series. In this part we're going to see how the ncurses
interface was created.
Creating the ncurses UI
To create the user interface we used the ncurses
UI using the api/ncurses
package. Sadly all interactions with this API makes the code look like straightforward imperative code.
Since we represented the game field using a matrix, we need a way to visualize this matrix. The next snippet shows how we used the wattr_on
and mvwprintw
functions to print each cell of the game field with the given color.
drawGame=: 3 : 0
matrix =. >{.}.y
win =. >{.y
cols =. }. $ matrix
rows =. {. $ matrix
for_row. i.rows do.
for_col. i.cols do.
value =. (<row, col) { matrix
wattr_on_ncurses_ win;(COLOR_PAIR_ncurses_ (value+1));0
mvwprintw_1_ncurses_ win; row; (2*col); ((' '))
end.
end.
)
The game loop handles user interactions and game rules . Here's how it looks:
NB. Game loop
while. 1 do.
c =. wgetch_ncurses_ vin
if. c = KEY_UP_ncurses_ do.
game =: put_in_matrix (current*_1);k;j;game
current =. rotate current
needs_refresh =. 1
elseif. c = KEY_RIGHT_ncurses_ do.
game_tmp =. put_in_matrix (current*_1);k;j;game
if. can_put_in_matrix current;k;(j + 1);game_tmp do.
game =: game_tmp
j =. j + 1
needs_refresh =. 1
end.
elseif. c = KEY_LEFT_ncurses_ do.
game_tmp =. put_in_matrix (current*_1);k;j;game
if. can_put_in_matrix (current);k;(j - 1);game_tmp do.
game =: game_tmp
j =. j - 1
needs_refresh =. 1
end.
elseif. 1 do.
if. ((seconds_from_start'') - timestamp) < 0.1 do.
continue.
else.
timestamp =. seconds_from_start''
end.
if. automove = 0 do.
game =: put_in_matrix (current*_1);k;j;game
if. can_put_in_matrix (current);(k+1);j;game do.
k =. k + 1
else.
game =: put_in_matrix (current);k;j;game
k =. 0
j =. 0
if. can_put_in_matrix current;k;j;game do.
current =. (?@$ tetriminos) {:: tetriminos
else.
mvwprintw_1_ncurses_ vin; 0; 0; ' Game over '
nodelay_ncurses_ vin ;'0'
wgetch_ncurses_ vin
exit''
end.
end.
automove =. 2
needs_refresh =. 1
else.
automove =. automove - 1
end.
end.
unget_wch_ncurses_ c
if. needs_refresh do.
game =: put_in_matrix (current);k;j;game
game =: remove_full_rows game
drawGame vin; game
wrefresh_ncurses_ vin
needs_refresh =. 0
end.
end.
The rest of the code is pure ncurses
initialization which is not that interesting. Code for this post can be found here: : https://github.com/ldfallas/jcurtris .