Advertisement
felixnardella

STARFIELD

Jun 3rd, 2025
700
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.73 KB | Source Code | 0 0
  1. /*
  2.  * ============================================================================
  3.  *  STARFIELD - Simulazione di campo stellare in movimento
  4.  * ============================================================================
  5.  *  Autore   : Felice Nardella (Kimono)
  6.  *  Data     : 2025-05-31
  7.  *  Modalità : Compilare con il compilatore C di Oscar64
  8.  *
  9.  *  Descrizione:
  10.  *  Questo programma scritto in linguaggio C per il Commodore 64,
  11.  *  usando il compilatore Oscar64, simula un campo stellare (starfield):
  12.  *  un effetto grafico usato nei vecchi giochi per dare l'impressione
  13.  *  che il giocatore stesse viaggiando su un'astronave che avanza
  14.  *  nello spazio.
  15.  *  Le stelle vengono disegnate come singoli pixel che si muovono
  16.  *  in direzione radiale, a velocità costante. Il programma termina
  17.  *  quando si preme il tasto 'SPAZIO'.
  18.  *
  19.  *  Compilazione:
  20.  *      oscar64 -n starfield.c
  21.  *
  22.  *  Link da cui scaricare il compilatore:
  23.  *      https://github.com/drmortalwombat/oscar64/releases
  24.  *
  25.  * ============================================================================
  26.  */
  27.  
  28. #include <c64/vic.h>
  29. #include <c64/memmap.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32.  
  33. // Costanti principali
  34. #define NUM_STARS 100
  35. #define SCREEN_WIDTH 320
  36. #define SCREEN_HEIGHT 200
  37. #define CENTER_X 160
  38. #define CENTER_Y 100
  39. #define SCALE 8    // Fattore di scala per il movimento
  40. #define SPEED 20  // Velocità costante per tutte le stelle
  41. // CIA1 porta A per lettura tastiera
  42. #define CIA1_PORT_A (*(volatile unsigned char*)0xDC01)
  43.  
  44. // Puntatori al bitmap high-resolution
  45. static char * const Screen = (char *)0xc800;
  46. static char * const Hires = (char *)0xe000;
  47. // Array di puntatori a righe dello schermo
  48. static char * Hirows[25];
  49.  
  50. // Maschere per settare e resettare pixel
  51. static const char setmask[8]  = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
  52. static const char clrmask[8]  = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
  53.  
  54. // Struttura dati per una stella
  55. struct Star {
  56.     int x, y;   // Coordinate attuali (con scala)
  57.     int dx, dy; // Vettore di direzione normalizzato
  58. };
  59.  
  60. // Array di stelle
  61. struct Star stars[NUM_STARS];
  62.  
  63. // Inizializza la tabella di puntatori a righe da 320 byte ciascuna
  64. void init_hirows() {
  65.     for (int i = 0; i < 25; i++) {
  66.         Hirows[i] = Hires + 320 * i;
  67.     }
  68. }
  69.  
  70. // Attiva un pixel
  71. void pix_set(unsigned px, unsigned py) {
  72.     if (px >= SCREEN_WIDTH || py >= SCREEN_HEIGHT) return;
  73.     char *dp = Hirows[py >> 3] + (px & ~7);
  74.     dp[py & 7] |= setmask[px & 7];
  75. }
  76.  
  77. // Disattiva un pixel
  78. void pix_clr(unsigned px, unsigned py) {
  79.     if (px >= SCREEN_WIDTH || py >= SCREEN_HEIGHT) return;
  80.     char *dp = Hirows[py >> 3] + (px & ~7);
  81.     dp[py & 7] &= clrmask[px & 7];
  82. }
  83.  
  84. // Inizializza la posizione e direzione di ogni stella
  85. void init_stars() {
  86.     for (int i = 0; i < NUM_STARS; ++i) {
  87.         int px, py, dx, dy;
  88.         int min_distance = 10; // Distanza minima dal centro
  89.         int distance_squared, min_distance_squared;
  90.        
  91.         min_distance_squared = min_distance * min_distance;
  92.        
  93.         // Genera posizioni random, abbastanza distanti dal centro
  94.         do {
  95.             px = rand() % SCREEN_WIDTH;
  96.             py = rand() % SCREEN_HEIGHT;
  97.            
  98.             dx = px - CENTER_X;
  99.             dy = py - CENTER_Y;
  100.            
  101.             // Calcola distanza dal centro (semplificata senza radice quadrata)
  102.             distance_squared = dx * dx + dy * dy;
  103.            
  104.         } while (distance_squared < min_distance_squared);
  105.        
  106.         // Assegna le coordinate scalate
  107.         stars[i].x = px * SCALE;
  108.         stars[i].y = py * SCALE;
  109.  
  110.         // Ricalcola direzione usando le coordinate scalate
  111.         int scaled_dx = stars[i].x - CENTER_X * SCALE;
  112.         int scaled_dy = stars[i].y - CENTER_Y * SCALE;
  113.  
  114.         // Normalizza la velocità
  115.        
  116.         // Calcola il valore assoluto di scaled_dx
  117.         int abs_dx;
  118.         if (scaled_dx >= 0) {
  119.             abs_dx = scaled_dx;
  120.         } else {
  121.             abs_dx = -scaled_dx;
  122.         }
  123.  
  124.         // Calcola il valore assoluto di scaled_dy
  125.         int abs_dy;
  126.         if (scaled_dy >= 0) {
  127.             abs_dy = scaled_dy;
  128.         } else {
  129.             abs_dy = -scaled_dy;
  130.         }
  131.  
  132.         // Trova il valore massimo tra abs_dx e abs_dy
  133.         int max;
  134.         if (abs_dx > abs_dy) {
  135.             max = abs_dx;
  136.         } else {
  137.             max = abs_dy;
  138.         }
  139.         if (max == 0) max = 1;
  140.  
  141.         stars[i].dx = (scaled_dx * SPEED) / max;
  142.         stars[i].dy = (scaled_dy * SPEED) / max;
  143.     }
  144. }
  145.  
  146. // Aggiorna la posizione delle stelle e le ridisegna
  147. void update_stars() {
  148.     for (int i = 0; i < NUM_STARS; ++i) {
  149.         // Cancella il pixel precedente
  150.         int px = stars[i].x / SCALE;
  151.         int py = stars[i].y / SCALE;
  152.         pix_clr(px, py);
  153.  
  154.         // Aggiorna la posizione
  155.         stars[i].x += stars[i].dx;
  156.         stars[i].y += stars[i].dy;
  157.        
  158.         // Nuove coordinate pixel
  159.         px = stars[i].x / SCALE;
  160.         py = stars[i].y / SCALE;
  161.  
  162.         // Se la stella esce dallo schermo, la reinizializza
  163.         if (px < 0 || px >= SCREEN_WIDTH || py < 0 || py >= SCREEN_HEIGHT) {
  164.             // Reinizializza la stella con distanza minima dal centro
  165.             int new_px, new_py, dx, dy;
  166.             int min_distance = 10; // Stessa distanza usata in init_stars()
  167.             int distance_squared, min_distance_squared;
  168.            
  169.             min_distance_squared = min_distance * min_distance;
  170.            
  171.             // Genera nuova posizione distante dal centro
  172.             do {
  173.                 new_px = rand() % SCREEN_WIDTH;
  174.                 new_py = rand() % SCREEN_HEIGHT;
  175.                
  176.                 dx = new_px - CENTER_X;
  177.                 dy = new_py - CENTER_Y;
  178.                
  179.                 distance_squared = dx * dx + dy * dy;
  180.                
  181.             } while (distance_squared < min_distance_squared);
  182.  
  183.             // Assegna le nuove coordinate scalate
  184.             stars[i].x = new_px * SCALE;
  185.             stars[i].y = new_py * SCALE;
  186.  
  187.             // Ricalcola direzione usando le coordinate scalate
  188.             int scaled_dx = stars[i].x - CENTER_X * SCALE;
  189.             int scaled_dy = stars[i].y - CENTER_Y * SCALE;
  190.  
  191.             // Normalizza la velocità
  192.         // Calcola il valore assoluto di scaled_dx
  193.         int abs_dx;
  194.         if (scaled_dx >= 0) {
  195.             abs_dx = scaled_dx;
  196.         } else {
  197.             abs_dx = -scaled_dx;
  198.         }
  199.  
  200.         // Calcola il valore assoluto di scaled_dy
  201.         int abs_dy;
  202.         if (scaled_dy >= 0) {
  203.             abs_dy = scaled_dy;
  204.         } else {
  205.             abs_dy = -scaled_dy;
  206.         }
  207.  
  208.         // Trova il valore massimo tra abs_dx e abs_dy
  209.         int max;
  210.         if (abs_dx > abs_dy) {
  211.             max = abs_dx;
  212.         } else {
  213.             max = abs_dy;
  214.         }
  215.         if (max == 0) max = 1;
  216.        
  217.         stars[i].dx = (scaled_dx * SPEED) / max;
  218.         stars[i].dy = (scaled_dy * SPEED) / max;
  219.         }
  220.         // Disegna il pixel
  221.         pix_set(px, py);
  222.     }
  223. }
  224.  
  225. // Programma principale
  226. int main(void) {
  227.     // Disattiva BASIC e ROM
  228.     mmap_set(MMAP_NO_BASIC);
  229.     mmap_trampoline();
  230.     mmap_set(MMAP_NO_ROM);
  231.    
  232.     // Imposta modalità Hi-Res
  233.     vic_setmode(VICM_HIRES, Screen, Hires);
  234.     vic.color_border = 0;
  235.     vic.color_back = 0;
  236.  
  237.     memset(Screen, 0x10, 1000);
  238.     // Cancella schermo bitmap
  239.     memset(Hires, 0x00, 8000);
  240.    
  241.     // Prepara le righe dello schermo e inizializza le stelle
  242.     init_hirows();
  243.     init_stars();
  244.  
  245.     // Loop principale finchè non viene premuto 'SPAZIO'
  246.     for (;;) {
  247.         update_stars();
  248.         if (CIA1_PORT_A != 0xFF)
  249.             break;
  250.     }
  251.  
  252.     return 0;
  253. }
  254.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement