Add: snake game! (basics)
This commit is contained in:
@@ -12,10 +12,8 @@ extern char* framebuffer;
|
|||||||
|
|
||||||
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
|
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
|
||||||
{
|
{
|
||||||
if (bpp == 32) {
|
|
||||||
uint32_t* pixel_addr = (uint32_t*)((uint8_t*)fb + y * pitch + x *(bpp / 8));
|
uint32_t* pixel_addr = (uint32_t*)((uint8_t*)fb + y * pitch + x *(bpp / 8));
|
||||||
*pixel_addr = color;
|
*pixel_addr = color;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
|
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
|
||||||
|
|||||||
@@ -140,3 +140,19 @@ char keyboard_getchar()
|
|||||||
keyboard_buffer_start = (keyboard_buffer_start+1) % KEYBOARD_BUFFER_SIZE;
|
keyboard_buffer_start = (keyboard_buffer_start+1) % KEYBOARD_BUFFER_SIZE;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int keyboard_has_input()
|
||||||
|
{
|
||||||
|
return keyboard_buffer_start != keyboard_buffer_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
char keyboard_getchar_non_blocking()
|
||||||
|
{
|
||||||
|
if (keyboard_has_input())
|
||||||
|
{
|
||||||
|
char c = keyboard_buffer[keyboard_buffer_start];
|
||||||
|
keyboard_buffer_start = (keyboard_buffer_start+1)%KEYBOARD_BUFFER_SIZE;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,5 +14,7 @@
|
|||||||
#define RIGHT_SHIFT_RELEASED 0xB6
|
#define RIGHT_SHIFT_RELEASED 0xB6
|
||||||
|
|
||||||
char keyboard_getchar();
|
char keyboard_getchar();
|
||||||
|
int keyboard_has_input();
|
||||||
|
char keyboard_getchar_non_blocking();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ void shell_install()
|
|||||||
register_command("bmp", program_bmp);
|
register_command("bmp", program_bmp);
|
||||||
register_command("lspci", program_lspci);
|
register_command("lspci", program_lspci);
|
||||||
register_command("naval", program_navalbattle);
|
register_command("naval", program_navalbattle);
|
||||||
|
register_command("snake", program_snake);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,6 +39,25 @@ void draw_cursor(uint32_t color)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_pixel(int x, int y, uint32_t color) //high level wrapper for putpixel
|
||||||
|
{
|
||||||
|
putpixel(framebuffer, scanline, 32, x, y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_square(int x, int y, uint32_t color, int size)
|
||||||
|
{
|
||||||
|
int startx = x*size;
|
||||||
|
int starty = y*size;
|
||||||
|
|
||||||
|
for (int i=0; i<size; i++)
|
||||||
|
{
|
||||||
|
for (int j=0; j<size; j++)
|
||||||
|
{
|
||||||
|
draw_pixel(startx+i, starty+j, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void erase_cursor()
|
void erase_cursor()
|
||||||
{
|
{
|
||||||
draw_cursor(black);
|
draw_cursor(black);
|
||||||
|
|||||||
@@ -22,8 +22,10 @@
|
|||||||
|
|
||||||
void draw_cursor(uint32_t color);
|
void draw_cursor(uint32_t color);
|
||||||
void erase_cursor();
|
void erase_cursor();
|
||||||
|
|
||||||
void move_cursor(int x, int y);
|
void move_cursor(int x, int y);
|
||||||
|
|
||||||
|
void draw_pixel(int x, int y, uint32_t color);
|
||||||
|
void draw_square(int x, int y, uint32_t color, int size);
|
||||||
void putchar(unsigned short int c, int x, int y, uint32_t fg, uint32_t bg);
|
void putchar(unsigned short int c, int x, int y, uint32_t fg, uint32_t bg);
|
||||||
void puts(const char* str);
|
void puts(const char* str);
|
||||||
void clear(void);
|
void clear(void);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ void program_uptime()
|
|||||||
|
|
||||||
void program_help()
|
void program_help()
|
||||||
{
|
{
|
||||||
printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\t naval\n");
|
printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\t naval\nsnake\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panic
|
// Panic
|
||||||
|
|||||||
@@ -43,5 +43,6 @@ void program_lspci();
|
|||||||
// Games
|
// Games
|
||||||
void program_navalbattle();
|
void program_navalbattle();
|
||||||
void program_conway();
|
void program_conway();
|
||||||
|
void program_snake();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
161
src/programs/snake.c
Normal file
161
src/programs/snake.c
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
// Snake game
|
||||||
|
// Author: xamidev
|
||||||
|
// Licensed under the Unlicense. See the repo below.
|
||||||
|
// https://github.com/xamidev/blankos
|
||||||
|
|
||||||
|
#include "../kernel/system.h"
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
#include "../drivers/framebuffer.h"
|
||||||
|
#include "../drivers/kb.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
#include "../libc/crypto.h"
|
||||||
|
|
||||||
|
#define WIDTH 25
|
||||||
|
#define HEIGHT 25
|
||||||
|
#define PIXEL_SIZE 20
|
||||||
|
|
||||||
|
// to add:
|
||||||
|
// score
|
||||||
|
// sound
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
} SnakeSegment;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SnakeSegment segments[100];
|
||||||
|
int length;
|
||||||
|
int dx;
|
||||||
|
int dy;
|
||||||
|
} Snake;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
} Food;
|
||||||
|
|
||||||
|
Snake snake;
|
||||||
|
Food food;
|
||||||
|
|
||||||
|
int is_snake(int x, int y);
|
||||||
|
|
||||||
|
void init_game()
|
||||||
|
{
|
||||||
|
snake.length = 1;
|
||||||
|
snake.segments[0].x = WIDTH/2;
|
||||||
|
snake.segments[0].y = HEIGHT/2;
|
||||||
|
snake.dx = 1;
|
||||||
|
snake.dy = 0;
|
||||||
|
|
||||||
|
food.x = rand() % (WIDTH-1);
|
||||||
|
food.y = rand() % (HEIGHT-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_board()
|
||||||
|
{
|
||||||
|
erase_cursor();
|
||||||
|
for (int y=0; y<=HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for (int x=0; x<=WIDTH; x++)
|
||||||
|
{
|
||||||
|
if (x == 0 || x == WIDTH || y == 0 || y == HEIGHT)
|
||||||
|
{
|
||||||
|
draw_square(x, y, white, PIXEL_SIZE);
|
||||||
|
}
|
||||||
|
else if (is_snake(x, y)) {
|
||||||
|
draw_square(x, y, green, PIXEL_SIZE);
|
||||||
|
} else if(x == food.x && y == food.y) {
|
||||||
|
draw_square(x, y, red, PIXEL_SIZE);
|
||||||
|
} else {
|
||||||
|
draw_square(x, y, black, PIXEL_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_snake(int x, int y)
|
||||||
|
{
|
||||||
|
for (int i=0; i<snake.length; i++)
|
||||||
|
{
|
||||||
|
if (snake.segments[i].x == x && snake.segments[i].y == y)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_snake()
|
||||||
|
{
|
||||||
|
for (int i=snake.length-1; i>0; i--)
|
||||||
|
{
|
||||||
|
snake.segments[i] = snake.segments[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
snake.segments[0].x += snake.dx;
|
||||||
|
snake.segments[0].y += snake.dy;
|
||||||
|
|
||||||
|
if (snake.segments[0].x < 0) snake.segments[0].x = WIDTH-1;
|
||||||
|
if (snake.segments[0].x >= WIDTH) snake.segments[0].x = 0;
|
||||||
|
if (snake.segments[0].y < 0) snake.segments[0].y = HEIGHT-1;
|
||||||
|
if (snake.segments[0].y >= HEIGHT) snake.segments[0].y = 0;
|
||||||
|
|
||||||
|
if (snake.segments[0].x == food.x && snake.segments[0].y == food.y)
|
||||||
|
{
|
||||||
|
snake.length++;
|
||||||
|
food.x = rand() % (WIDTH-1);
|
||||||
|
food.y = rand() % (HEIGHT-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_input(char key)
|
||||||
|
{
|
||||||
|
if (key == 'w' && snake.dy == 0) {
|
||||||
|
snake.dx = 0;
|
||||||
|
snake.dy = -1;
|
||||||
|
} else if (key == 's' && snake.dy == 0) {
|
||||||
|
snake.dx = 0;
|
||||||
|
snake.dy = 1;
|
||||||
|
} else if (key == 'a' && snake.dx == 0) {
|
||||||
|
snake.dx = -1;
|
||||||
|
snake.dy = 0;
|
||||||
|
} else if (key == 'd' && snake.dx == 0) {
|
||||||
|
snake.dx = 1;
|
||||||
|
snake.dy = 0;
|
||||||
|
} else if (key =='q') {
|
||||||
|
clear();
|
||||||
|
shell_install();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_snake(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int game_speed;
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
game_speed = 4;
|
||||||
|
} else {
|
||||||
|
game_speed = atoi(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear();
|
||||||
|
init_game();
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
char key = keyboard_getchar_non_blocking();
|
||||||
|
|
||||||
|
if (key)
|
||||||
|
{
|
||||||
|
handle_input(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
move_snake();
|
||||||
|
draw_board();
|
||||||
|
delay(game_speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user