kernels,snake: port to AM
This commit is contained in:
parent
ec82e0f2cd
commit
3388801aea
2 changed files with 154 additions and 212 deletions
3
kernels/snake/Makefile
Normal file
3
kernels/snake/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
NAME = snake
|
||||||
|
SRCS = snake.c
|
||||||
|
include $(AM_HOME)/Makefile
|
|
@ -1,249 +1,188 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#define _Bool unsigned int /* lcc doesn't define this */
|
#include <stdio.h>
|
||||||
#include <ncurses.h>
|
#include <am.h>
|
||||||
|
#include <amdev.h>
|
||||||
|
#include <klib-macros.h>
|
||||||
|
|
||||||
#define MAX_LENGTH 100
|
#define MAX_LENGTH 100
|
||||||
|
#define TILE_W 8
|
||||||
|
|
||||||
typedef enum { NONE, UP, DOWN, LEFT, RIGHT } dir_t;
|
typedef enum { NONE, UP, DOWN, LEFT, RIGHT } dir_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int x, y;
|
int x, y;
|
||||||
} point_t;
|
} point_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int width, height;
|
int width, height;
|
||||||
} dim_t;
|
} dim_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int top, bottom, left, right;
|
int top, bottom, left, right;
|
||||||
} rect_t;
|
} rect_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
point_t body[MAX_LENGTH];
|
point_t body[MAX_LENGTH];
|
||||||
int length;
|
int length;
|
||||||
int index;
|
int index;
|
||||||
int dead;
|
int dead;
|
||||||
} snake_t;
|
} snake_t;
|
||||||
|
|
||||||
point_t create_food(dim_t);
|
static void refresh() {
|
||||||
void print_board(rect_t);
|
io_write(AM_GPU_FBDRAW, 0, 0, NULL, 0, 0, true);
|
||||||
void print_food(point_t, rect_t);
|
|
||||||
void print_head(snake_t*, rect_t);
|
|
||||||
void clear_tail(snake_t*, rect_t);
|
|
||||||
dir_t get_dir(int);
|
|
||||||
void move_snake(snake_t*, dir_t);
|
|
||||||
int is_dead(snake_t*, dim_t);
|
|
||||||
int has_food(snake_t*, point_t);
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
snake_t snake={0};
|
|
||||||
point_t food;
|
|
||||||
rect_t board;
|
|
||||||
dim_t screen;
|
|
||||||
dim_t game_size;
|
|
||||||
dir_t dir=RIGHT;
|
|
||||||
dir_t move_dir=NONE;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
srand(time(0));
|
|
||||||
initscr();
|
|
||||||
|
|
||||||
getmaxyx(stdscr, screen.height, screen.width);
|
|
||||||
|
|
||||||
game_size.width=screen.width/2;
|
|
||||||
game_size.height=screen.height/2;
|
|
||||||
|
|
||||||
food=create_food(game_size);
|
|
||||||
|
|
||||||
snake.body[0].x=game_size.width/2;
|
|
||||||
snake.body[0].y=game_size.height/2;
|
|
||||||
snake.body[1].x=game_size.width/2;
|
|
||||||
snake.body[1].y=game_size.height/2+1;
|
|
||||||
snake.length=2;
|
|
||||||
snake.index=1;
|
|
||||||
|
|
||||||
board.left=screen.width/2-game_size.width/2-1;
|
|
||||||
board.right=board.left+game_size.width+1;
|
|
||||||
board.top=screen.height/2-game_size.height/2-1;
|
|
||||||
board.bottom=board.top+game_size.height+1;
|
|
||||||
|
|
||||||
noecho();
|
|
||||||
cbreak();
|
|
||||||
timeout(0);
|
|
||||||
curs_set(0);
|
|
||||||
|
|
||||||
clear();
|
|
||||||
do {
|
|
||||||
print_board(board);
|
|
||||||
print_food(food,board);
|
|
||||||
print_head(&snake,board);
|
|
||||||
clear_tail(&snake,board);
|
|
||||||
refresh();
|
|
||||||
|
|
||||||
c=getch();
|
|
||||||
move_dir=get_dir(c);
|
|
||||||
if (move_dir!=NONE) {
|
|
||||||
dir=move_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
move_snake(&snake, dir);
|
|
||||||
snake.dead=is_dead(&snake,game_size);
|
|
||||||
|
|
||||||
if (has_food(&snake, food)) {
|
|
||||||
snake.length++;
|
|
||||||
food=create_food(game_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
usleep (100000-snake.length*5000<5000?5000:100000-snake.length*5000);
|
|
||||||
|
|
||||||
} while (c!=27 && !snake.dead);
|
|
||||||
|
|
||||||
move(
|
|
||||||
screen.height/2,
|
|
||||||
screen.width/2-5
|
|
||||||
);
|
|
||||||
printw("GAME OVER");
|
|
||||||
refresh();
|
|
||||||
nocbreak();
|
|
||||||
timeout(-1);
|
|
||||||
c=getch();
|
|
||||||
endwin();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
point_t create_food(dim_t game_size)
|
static void draw_tile(int y, int x, uint32_t color) {
|
||||||
{
|
static uint32_t buf[TILE_W * TILE_W];
|
||||||
point_t f;
|
uint32_t last_color = 0xffffffff;
|
||||||
f.x=rand()%game_size.width;
|
if (last_color != color) {
|
||||||
f.y=rand()%game_size.height;
|
for (int i = 0; i < LENGTH(buf); i ++) { buf[i] = color; }
|
||||||
return f;
|
}
|
||||||
|
io_write(AM_GPU_FBDRAW, x * TILE_W, y * TILE_W, buf, TILE_W, TILE_W, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_board(rect_t board)
|
static int read_key() {
|
||||||
{
|
while (1) {
|
||||||
int i;
|
AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
|
||||||
|
if (ev.keydown || ev.keycode == AM_KEY_NONE) return ev.keycode;
|
||||||
for (i=board.left; i<=board.right; i++) {
|
}
|
||||||
move(board.top, i);
|
|
||||||
addch(' '|A_REVERSE);
|
|
||||||
move(board.bottom, i);
|
|
||||||
addch(' '|A_REVERSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=board.top; i<=board.bottom; i++) {
|
|
||||||
move(i, board.left);
|
|
||||||
addch(' '|A_REVERSE);
|
|
||||||
move(i, board.right);
|
|
||||||
addch(' '|A_REVERSE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_food(point_t food, rect_t board)
|
static point_t create_food(dim_t game_size) {
|
||||||
{
|
point_t f;
|
||||||
move(
|
f.x = rand() % game_size.width;
|
||||||
food.y+board.top+1,
|
f.y = rand() % game_size.height;
|
||||||
food.x+board.left+1
|
return f;
|
||||||
);
|
|
||||||
printw("@");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_head(snake_t* snake, rect_t board)
|
static void print_board(rect_t board) {
|
||||||
{
|
uint32_t color = 0x0000ff00;
|
||||||
move(
|
for (int i = board.left; i <= board.right; i++) {
|
||||||
snake->body[snake->index].y+board.top+1,
|
draw_tile(board.top, i, color);
|
||||||
snake->body[snake->index].x+board.left+1
|
draw_tile(board.bottom, i, color);
|
||||||
);
|
}
|
||||||
printw("o");
|
for (int i = board.top; i <= board.bottom; i++) {
|
||||||
|
draw_tile(i, board.left, color);
|
||||||
|
draw_tile(i, board.right, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_tail(snake_t* snake, rect_t board)
|
static void print_food(point_t food, rect_t board) {
|
||||||
{
|
draw_tile(food.y + board.top + 1, food.x + board.left + 1, 0x000000ff);
|
||||||
int t=snake->index-snake->length;
|
|
||||||
if (t<0) {
|
|
||||||
t+=MAX_LENGTH;
|
|
||||||
}
|
|
||||||
move(
|
|
||||||
snake->body[t].y+board.top+1,
|
|
||||||
snake->body[t].x+board.left+1
|
|
||||||
);
|
|
||||||
printw(" ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_t get_dir(int c)
|
static void print_head(snake_t* snake, rect_t board) {
|
||||||
{
|
point_t *p = &snake->body[snake->index];
|
||||||
if (c=='a') {
|
draw_tile(p->y + board.top + 1, p->x + board.left + 1, 0x00ff0000);
|
||||||
return LEFT;
|
|
||||||
}
|
|
||||||
else if (c=='w') {
|
|
||||||
return UP;
|
|
||||||
}
|
|
||||||
else if (c=='d') {
|
|
||||||
return RIGHT;
|
|
||||||
}
|
|
||||||
else if (c=='s') {
|
|
||||||
return DOWN;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void move_snake(snake_t* snake, dir_t dir)
|
static void clear_tail(snake_t* snake, rect_t board) {
|
||||||
{
|
int t = snake->index-snake->length;
|
||||||
point_t p;
|
if (t < 0) { t += MAX_LENGTH; }
|
||||||
p=snake->body[snake->index];
|
draw_tile(snake->body[t].y + board.top + 1, snake->body[t].x + board.left + 1, 0);
|
||||||
|
|
||||||
if (dir==LEFT) {
|
|
||||||
p.x--;
|
|
||||||
}
|
|
||||||
else if (dir==DOWN) {
|
|
||||||
p.y++;
|
|
||||||
}
|
|
||||||
else if (dir==RIGHT) {
|
|
||||||
p.x++;
|
|
||||||
}
|
|
||||||
else if (dir==UP) {
|
|
||||||
p.y--;
|
|
||||||
}
|
|
||||||
|
|
||||||
snake->index++;
|
|
||||||
if (snake->index==MAX_LENGTH) {
|
|
||||||
snake->index=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
snake->body[snake->index]=p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_dead(snake_t* snake, dim_t game_size)
|
static dir_t get_dir(int c) {
|
||||||
{
|
switch (c) {
|
||||||
int i, j;
|
case AM_KEY_LEFT: return LEFT;
|
||||||
point_t head=snake->body[snake->index];
|
case AM_KEY_UP: return UP;
|
||||||
|
case AM_KEY_RIGHT: return RIGHT;
|
||||||
if (head.x==-1) return 1;
|
case AM_KEY_DOWN: return DOWN;
|
||||||
if (head.x==game_size.width) return 1;
|
default: return NONE;
|
||||||
if (head.y==-1) return 1;
|
}
|
||||||
if (head.y==game_size.height) return 1;
|
|
||||||
|
|
||||||
i=1;
|
|
||||||
while (i!=snake->length) {
|
|
||||||
j=snake->index-i;
|
|
||||||
if (j<0) {
|
|
||||||
j+=MAX_LENGTH;
|
|
||||||
}
|
|
||||||
if (head.x==snake->body[j].x && head.y==snake->body[j].y) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int has_food(snake_t* snake, point_t food)
|
static void move_snake(snake_t* snake, dir_t dir) {
|
||||||
{
|
point_t p = snake->body[snake->index];
|
||||||
return
|
switch (dir) {
|
||||||
snake->body[snake->index].x==food.x &&
|
case LEFT: p.x --; break;
|
||||||
snake->body[snake->index].y==food.y;
|
case DOWN: p.y ++; break;
|
||||||
|
case RIGHT: p.x ++; break;
|
||||||
|
case UP: p.y --; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
snake->index ++;
|
||||||
|
if (snake->index == MAX_LENGTH) { snake->index = 0; }
|
||||||
|
snake->body[snake->index] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_dead(snake_t* snake, dim_t game_size) {
|
||||||
|
point_t head = snake->body[snake->index];
|
||||||
|
if (head.x == -1) return 1;
|
||||||
|
if (head.x == game_size.width) return 1;
|
||||||
|
if (head.y == -1) return 1;
|
||||||
|
if (head.y == game_size.height) return 1;
|
||||||
|
|
||||||
|
for (int i = 1; i != snake->length; i ++) {
|
||||||
|
int j = snake->index-i;
|
||||||
|
if (j < 0) { j += MAX_LENGTH; }
|
||||||
|
if (head.x == snake->body[j].x && head.y == snake->body[j].y) { return 1; }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int has_food(snake_t* snake, point_t food) {
|
||||||
|
return snake->body[snake->index].x == food.x && snake->body[snake->index].y == food.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
snake_t snake = {0};
|
||||||
|
rect_t board;
|
||||||
|
dim_t screen;
|
||||||
|
dim_t game_size;
|
||||||
|
dir_t dir = RIGHT;
|
||||||
|
|
||||||
|
ioe_init();
|
||||||
|
screen.height = io_read(AM_GPU_CONFIG).height / TILE_W;
|
||||||
|
screen.width = io_read(AM_GPU_CONFIG).width / TILE_W;
|
||||||
|
|
||||||
|
game_size.width = screen.width - 2;
|
||||||
|
game_size.height = screen.height - 2;
|
||||||
|
|
||||||
|
snake.body[0].x = game_size.width / 2;
|
||||||
|
snake.body[0].y = game_size.height / 2;
|
||||||
|
snake.body[1].x = game_size.width / 2;
|
||||||
|
snake.body[1].y = game_size.height / 2 + 1;
|
||||||
|
snake.length = 2;
|
||||||
|
snake.index = 1;
|
||||||
|
|
||||||
|
board.left = screen.width / 2 - game_size.width / 2 - 1;
|
||||||
|
board.right = board.left + game_size.width + 1;
|
||||||
|
board.top = screen.height / 2 - game_size.height / 2 - 1;
|
||||||
|
board.bottom = board.top + game_size.height + 1;
|
||||||
|
print_board(board);
|
||||||
|
|
||||||
|
point_t food = create_food(game_size);
|
||||||
|
print_food(food, board);
|
||||||
|
do {
|
||||||
|
print_head(&snake, board);
|
||||||
|
clear_tail(&snake, board);
|
||||||
|
|
||||||
|
dir_t move_dir = get_dir(read_key());
|
||||||
|
switch (move_dir) {
|
||||||
|
case UP: if (dir != DOWN) dir = move_dir; break;
|
||||||
|
case DOWN: if (dir != UP) dir = move_dir; break;
|
||||||
|
case LEFT: if (dir != RIGHT) dir = move_dir; break;
|
||||||
|
case RIGHT: if (dir != LEFT) dir = move_dir; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
move_snake(&snake, dir);
|
||||||
|
snake.dead = is_dead(&snake, game_size);
|
||||||
|
|
||||||
|
if (has_food(&snake, food)) {
|
||||||
|
snake.length ++;
|
||||||
|
food = create_food(game_size);
|
||||||
|
print_food(food, board);
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
uint64_t sleep = 100000 - snake.length * 5000 < 5000 ? 5000 : 100000 - snake.length * 5000;
|
||||||
|
uint64_t next_us = io_read(AM_TIMER_UPTIME).us + sleep;
|
||||||
|
while (io_read(AM_TIMER_UPTIME).us < next_us) ;
|
||||||
|
} while (!snake.dead);
|
||||||
|
|
||||||
|
printf("GAME OVER\nPress Q to Exit\n");
|
||||||
|
while (read_key() != AM_KEY_Q);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue