Back to posts Edit this post
Copy content

13 Oct 09:07

#include "platform.h" #include "xil_printf.h" #include "displayport.h" #include "vtc.h" #include "tpg.h" #include "xparameters.h" #include "./../../../hw/sdt/drivers/myip_v1_0/src/myip.h" #include <stdint.h> #include "xil_types.h" #include "xil_io.h" // Deklaracja funkcji do odbierania pojedynczego bajtu z UART extern char inbyte(void); // Definicje stałych gry #define BOARD_WIDTH 20 #define BOARD_HEIGHT 15 #define MAX_SNAKE_LEN 100 // Kierunki ruchu typedef enum { UP, DOWN, LEFT, RIGHT } Direction; // Struktura punktu na planszy typedef struct { int8_t x; int8_t y; } Point; // Funkcja konwertująca Hue (0-360) oraz Jasność (0-100%) na format XRGB (0x00RRGGBB) u32 hsv_to_xrgb(u16 hue, u8 value) { if (hue >= 360) hue = hue % 360; if (value > 100) value = 100; u8 max_val = (value * 255) / 100; if (max_val == 0) return 0x00000000; u8 r = 0, g = 0, b = 0; u32 sector = hue / 60; u32 remainder = hue % 60; u8 x_val = (max_val * remainder) / 60; u8 inv_x_val = max_val - x_val; switch (sector) { case 0: r = max_val; g = x_val; b = 0; break; case 1: r = inv_x_val; g = max_val; b = 0; break; case 2: r = 0; g = max_val; b = x_val; break; case 3: r = 0; g = inv_x_val; b = max_val; break; case 4: r = x_val; g = 0; b = max_val; break; case 5: r = max_val; g = 0; b = inv_x_val; break; default: r = 0; g = 0; b = 0; break; } return ((u32)0x00 << 24) | ((u32)r << 16) | ((u32)g << 8) | b; } // Prosta funkcja opóźniająca (zastępuje sleep) void simple_delay(u32 cycles) { volatile u32 i; for (i = 0; i < cycles; i++) { __asm__("nop"); } } int main() { init_platform(); xil_printf("\n\n\n\n\n--- SNAKE GAME IN HUE/RGB ---\r\n"); xil_printf("Sterowanie strzalkami na klawiaturze terminala!\r\n"); // Inicjalizacja potoku wideo displayport_init(); displayport_setup_interrupts(); vtc_init(); tpg_init(); xil_printf("Video pipeline ready.\r\n"); // Kolory gry zdefiniowane w Hue u32 color_snake = hsv_to_xrgb(120, 100); // Zielony wąż u32 color_apple = hsv_to_xrgb(0, 100); // Czerwone jabłko u32 color_dead = hsv_to_xrgb(280, 100); // Fioletowy (koniec gry) // Stan gry Point snake[MAX_SNAKE_LEN]; u8 snake_len = 3; Direction dir = RIGHT; Point apple = {12, 7}; u8 game_over = 0; u32 score = 0; // Pozycja startowa węża (środek planszy) snake[0].x = 10; snake[0].y = 7; // Głowa snake[1].x = 9; snake[1].y = 7; snake[2].x = 8; snake[2].y = 7; // Ogon // Pseudo-losowy licznik do generowania jabłek u32 rand_counter = 0; while (1) { rand_counter++; // --- 1. OBSŁUGA STEROWANIA (Nieblokujące sprawdzanie UART lub symulacja ruchu) --- // Ponieważ inbyte() domyślnie blokuje procesor, w grach na mikrokontrolerach // sterowanie opiera się na taktowaniu pętli z opóźnieniem. // Aby zagrać, klikaj strzałki rytmicznie w terminalu. char c = inbyte(); if (c == 0x1B) { c = inbyte(); if (c == 0x5B) { c = inbyte(); switch (c) { case 0x41: if (dir != DOWN) dir = UP; break; // Góra case 0x42: if (dir != UP) dir = DOWN; break; // Dół case 0x43: if (dir != LEFT) dir = RIGHT; break; // Prawo case 0x44: if (dir != RIGHT) dir = LEFT; break; // Lewo } } } if (game_over) { MYIP_mWriteReg(XPAR_MYIP_0_BASEADDR, MYIP_S00_AXI_SLV_REG0_OFFSET, color_dead); xil_printf("\rGAME OVER! Wynik: %d. Nacisnij dowolny klawisz, aby restartowac...", score); inbyte(); // Czekaj na klawisz restartu // Reset stanu gry snake_len = 3; dir = RIGHT; snake[0].x = 10; snake[0].y = 7; snake[1].x = 9; snake[1].y = 7; snake[2].x = 8; snake[2].y = 7; apple.x = 12; apple.y = 7; score = 0; game_over = 0; xil_printf("\nNowa gra wystartowala!\n"); continue; } // --- 2. LOGIKA RUCHU --- // Przesunięcie ogona węża for (int i = snake_len - 1; i > 0; i--) { snake[i] = snake[i - 1]; } // Ruch głowy węża switch (dir) { case UP: snake[0].y--; break; case DOWN: snake[0].y++; break; case LEFT: snake[0].x--; break; case RIGHT: snake[0].x++; break; } // --- 3. KOLIZJE ZE ŚCIANAMI --- if (snake[0].x < 0 || snake[0].x >= BOARD_WIDTH || snake[0].y < 0 || snake[0].y >= BOARD_HEIGHT) { game_over = 1; } // Kolizja z samym sobą for (int i = 1; i < snake_len; i++) { if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) { game_over = 1; } } // --- 4. ZJADANIE JABŁKA --- if (snake[0].x == apple.x && snake[0].y == apple.y) { score += 10; if (snake_len < MAX_SNAKE_LEN) { snake_len++; } // Proste generowanie nowej pozycji jabłka na podstawie licznika cykli pętli apple.x = (rand_counter % (BOARD_WIDTH - 2)) + 1; apple.y = (rand_counter / 3 % (BOARD_HEIGHT - 2)) + 1; } // --- 5. RENDEROWANIE SYGNAŁU NA EKRAN --- // Kod dynamicznie przełącza rejestr MYIP_REG0 w takt odświeżania gry. // Kiedy wąż zbliża się do jabłka, rejestr błyska na czerwono; kiedy się porusza, koloruje ekran na zielono. if (snake[0].x == apple.x || snake[0].y == apple.y) { // Sygnalizacja bliskości jedzenia na ekranie wideo MYIP_mWriteReg(XPAR_MYIP_0_BASEADDR, MYIP_S00_AXI_SLV_REG0_OFFSET, color_apple); } else { // Standardowy kolor życia węża przekazywany do potoku obrazu MYIP_mWriteReg(XPAR_MYIP_0_BASEADDR, MYIP_S00_AXI_SLV_REG0_OFFSET, color_snake); } // Wydruk kontrolny stanu gry do konsoli szeregowej UART xil_printf("\rGlowa: [%2d,%2d] | Jabłko: [%2d,%2d] | Wynik: %d ", snake[0].x, snake[0].y, apple.x, apple.y, score); // Regulacja prędkości gry (ok. 5-10 klatek na sekundę w zależności od architektury procesora) simple_delay(2000000); } cleanup_platform(); return 0; }

No files