Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * ============================================================================
- * STARFIELD - Simulazione di campo stellare in movimento
- * ============================================================================
- * Autore : Felice Nardella (Kimono)
- * Data : 2025-05-31
- * Modalità : Compilare con il compilatore C di Oscar64
- *
- * Descrizione:
- * Questo programma scritto in linguaggio C per il Commodore 64,
- * usando il compilatore Oscar64, simula un campo stellare (starfield):
- * un effetto grafico usato nei vecchi giochi per dare l'impressione
- * che il giocatore stesse viaggiando su un'astronave che avanza
- * nello spazio.
- * Le stelle vengono disegnate come singoli pixel che si muovono
- * in direzione radiale, a velocità costante. Il programma termina
- * quando si preme il tasto 'SPAZIO'.
- *
- * Compilazione:
- * oscar64 -n starfield.c
- *
- * Link da cui scaricare il compilatore:
- * https://github.com/drmortalwombat/oscar64/releases
- *
- * ============================================================================
- */
- #include <c64/vic.h>
- #include <c64/memmap.h>
- #include <string.h>
- #include <stdlib.h>
- // Costanti principali
- #define NUM_STARS 100
- #define SCREEN_WIDTH 320
- #define SCREEN_HEIGHT 200
- #define CENTER_X 160
- #define CENTER_Y 100
- #define SCALE 8 // Fattore di scala per il movimento
- #define SPEED 20 // Velocità costante per tutte le stelle
- // CIA1 porta A per lettura tastiera
- #define CIA1_PORT_A (*(volatile unsigned char*)0xDC01)
- // Puntatori al bitmap high-resolution
- static char * const Screen = (char *)0xc800;
- static char * const Hires = (char *)0xe000;
- // Array di puntatori a righe dello schermo
- static char * Hirows[25];
- // Maschere per settare e resettare pixel
- static const char setmask[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
- static const char clrmask[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
- // Struttura dati per una stella
- struct Star {
- int x, y; // Coordinate attuali (con scala)
- int dx, dy; // Vettore di direzione normalizzato
- };
- // Array di stelle
- struct Star stars[NUM_STARS];
- // Inizializza la tabella di puntatori a righe da 320 byte ciascuna
- void init_hirows() {
- for (int i = 0; i < 25; i++) {
- Hirows[i] = Hires + 320 * i;
- }
- }
- // Attiva un pixel
- void pix_set(unsigned px, unsigned py) {
- if (px >= SCREEN_WIDTH || py >= SCREEN_HEIGHT) return;
- char *dp = Hirows[py >> 3] + (px & ~7);
- dp[py & 7] |= setmask[px & 7];
- }
- // Disattiva un pixel
- void pix_clr(unsigned px, unsigned py) {
- if (px >= SCREEN_WIDTH || py >= SCREEN_HEIGHT) return;
- char *dp = Hirows[py >> 3] + (px & ~7);
- dp[py & 7] &= clrmask[px & 7];
- }
- // Inizializza la posizione e direzione di ogni stella
- void init_stars() {
- for (int i = 0; i < NUM_STARS; ++i) {
- int px, py, dx, dy;
- int min_distance = 10; // Distanza minima dal centro
- int distance_squared, min_distance_squared;
- min_distance_squared = min_distance * min_distance;
- // Genera posizioni random, abbastanza distanti dal centro
- do {
- px = rand() % SCREEN_WIDTH;
- py = rand() % SCREEN_HEIGHT;
- dx = px - CENTER_X;
- dy = py - CENTER_Y;
- // Calcola distanza dal centro (semplificata senza radice quadrata)
- distance_squared = dx * dx + dy * dy;
- } while (distance_squared < min_distance_squared);
- // Assegna le coordinate scalate
- stars[i].x = px * SCALE;
- stars[i].y = py * SCALE;
- // Ricalcola direzione usando le coordinate scalate
- int scaled_dx = stars[i].x - CENTER_X * SCALE;
- int scaled_dy = stars[i].y - CENTER_Y * SCALE;
- // Normalizza la velocità
- // Calcola il valore assoluto di scaled_dx
- int abs_dx;
- if (scaled_dx >= 0) {
- abs_dx = scaled_dx;
- } else {
- abs_dx = -scaled_dx;
- }
- // Calcola il valore assoluto di scaled_dy
- int abs_dy;
- if (scaled_dy >= 0) {
- abs_dy = scaled_dy;
- } else {
- abs_dy = -scaled_dy;
- }
- // Trova il valore massimo tra abs_dx e abs_dy
- int max;
- if (abs_dx > abs_dy) {
- max = abs_dx;
- } else {
- max = abs_dy;
- }
- if (max == 0) max = 1;
- stars[i].dx = (scaled_dx * SPEED) / max;
- stars[i].dy = (scaled_dy * SPEED) / max;
- }
- }
- // Aggiorna la posizione delle stelle e le ridisegna
- void update_stars() {
- for (int i = 0; i < NUM_STARS; ++i) {
- // Cancella il pixel precedente
- int px = stars[i].x / SCALE;
- int py = stars[i].y / SCALE;
- pix_clr(px, py);
- // Aggiorna la posizione
- stars[i].x += stars[i].dx;
- stars[i].y += stars[i].dy;
- // Nuove coordinate pixel
- px = stars[i].x / SCALE;
- py = stars[i].y / SCALE;
- // Se la stella esce dallo schermo, la reinizializza
- if (px < 0 || px >= SCREEN_WIDTH || py < 0 || py >= SCREEN_HEIGHT) {
- // Reinizializza la stella con distanza minima dal centro
- int new_px, new_py, dx, dy;
- int min_distance = 10; // Stessa distanza usata in init_stars()
- int distance_squared, min_distance_squared;
- min_distance_squared = min_distance * min_distance;
- // Genera nuova posizione distante dal centro
- do {
- new_px = rand() % SCREEN_WIDTH;
- new_py = rand() % SCREEN_HEIGHT;
- dx = new_px - CENTER_X;
- dy = new_py - CENTER_Y;
- distance_squared = dx * dx + dy * dy;
- } while (distance_squared < min_distance_squared);
- // Assegna le nuove coordinate scalate
- stars[i].x = new_px * SCALE;
- stars[i].y = new_py * SCALE;
- // Ricalcola direzione usando le coordinate scalate
- int scaled_dx = stars[i].x - CENTER_X * SCALE;
- int scaled_dy = stars[i].y - CENTER_Y * SCALE;
- // Normalizza la velocità
- // Calcola il valore assoluto di scaled_dx
- int abs_dx;
- if (scaled_dx >= 0) {
- abs_dx = scaled_dx;
- } else {
- abs_dx = -scaled_dx;
- }
- // Calcola il valore assoluto di scaled_dy
- int abs_dy;
- if (scaled_dy >= 0) {
- abs_dy = scaled_dy;
- } else {
- abs_dy = -scaled_dy;
- }
- // Trova il valore massimo tra abs_dx e abs_dy
- int max;
- if (abs_dx > abs_dy) {
- max = abs_dx;
- } else {
- max = abs_dy;
- }
- if (max == 0) max = 1;
- stars[i].dx = (scaled_dx * SPEED) / max;
- stars[i].dy = (scaled_dy * SPEED) / max;
- }
- // Disegna il pixel
- pix_set(px, py);
- }
- }
- // Programma principale
- int main(void) {
- // Disattiva BASIC e ROM
- mmap_set(MMAP_NO_BASIC);
- mmap_trampoline();
- mmap_set(MMAP_NO_ROM);
- // Imposta modalità Hi-Res
- vic_setmode(VICM_HIRES, Screen, Hires);
- vic.color_border = 0;
- vic.color_back = 0;
- memset(Screen, 0x10, 1000);
- // Cancella schermo bitmap
- memset(Hires, 0x00, 8000);
- // Prepara le righe dello schermo e inizializza le stelle
- init_hirows();
- init_stars();
- // Loop principale finchè non viene premuto 'SPAZIO'
- for (;;) {
- update_stars();
- if (CIA1_PORT_A != 0xFF)
- break;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement