Add: snake game! (basics)

This commit is contained in:
xamidev
2024-09-12 17:54:30 +02:00
parent 8093880eaa
commit 40561a6537
9 changed files with 206 additions and 6 deletions

View File

@@ -12,11 +12,9 @@ extern char* framebuffer;
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));
*pixel_addr = color;
}
}
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
{

View File

@@ -140,3 +140,19 @@ char keyboard_getchar()
keyboard_buffer_start = (keyboard_buffer_start+1) % KEYBOARD_BUFFER_SIZE;
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;
}

View File

@@ -14,5 +14,7 @@
#define RIGHT_SHIFT_RELEASED 0xB6
char keyboard_getchar();
int keyboard_has_input();
char keyboard_getchar_non_blocking();
#endif

View File

@@ -145,6 +145,7 @@ void shell_install()
register_command("bmp", program_bmp);
register_command("lspci", program_lspci);
register_command("naval", program_navalbattle);
register_command("snake", program_snake);
for (;;)
{

View File

@@ -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()
{
draw_cursor(black);

View File

@@ -22,8 +22,10 @@
void draw_cursor(uint32_t color);
void erase_cursor();
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 puts(const char* str);
void clear(void);

View File

@@ -74,7 +74,7 @@ void program_uptime()
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

View File

@@ -43,5 +43,6 @@ void program_lspci();
// Games
void program_navalbattle();
void program_conway();
void program_snake();
#endif

161
src/programs/snake.c Normal file
View 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);
}
}