[LINUX] Nostalgisch, lasst uns ein Charakterspiel wie CBM-3032 mit ncursesw reproduzieren.

Bei ncurses beträgt der Bildschirm 80 x 24, bei ncursesw unter Verwendung des UTF-8-Codes in voller Breite mit einem quadratischen Zeichen vor etwa 40 Jahren 40 x 24, PET, MZ-80, CBM-3032, Ich habe versucht, das Spiel PC-8001 (das auch den 80x25-Modus hat) neu zu schreiben. Ich habe das Spiel "Raging Robots" ein wenig modifiziert und es zu "Maneaters" gemacht.

Ich werde die ausführliche Erklärung von ncursesw anderen Artikeln (Oioi) überlassen, aber ich werde die Programmliste veröffentlichen. Da es keine Erklärung für ncursesw gibt, habe ich die Kommentare so sorgfältig wie möglich geschrieben. Sie werden sehen, wie Sie die minimalen Flüche w verwenden.

Darüber hinaus war die Funktionsprüfung ubuntu18.04 und Debian Stretch (9.6). Das Binärpaket finden Sie auf GitHub. https://github.com/fygar256/maneaters/blob/master/maneaters_1.3-1_amd64.deb

~~ Ubuntu libncursesw5 (6.1-1ubuntu1.18.04) und Debian libncursesw5 (6.0 + 20161126-1 + deb9u2) haben einen Fehler, und selbst wenn Sie vim verwenden, wird dieser mit einem bestimmten Symbol von utf-8 angezeigt. Möglicherweise ist es abgebrochen oder die Zeichenbreite ist möglicherweise nicht groß genug. Zum Beispiel ~~ "◯" (großer Kreis: kein modellabhängiges Zeichen, mehrdeutige Breite) verursacht ein Problem, aber "O" (oberer Buchstabe O, volle Breite) verursacht kein Problem. In diesem Zusammenhang wies Siracamus darauf hin: "Bei Ubuntu-Terminals kann dies durch Ändern von" Mehrdeutiges Breitenzeichen: "auf der Registerkarte" Kompatibilität "der Einstellung" Einstellungen "des Terminals auf" Volle Breite "behoben werden. Als ich es ausprobierte, wurde es sicherlich im Spiel gelöst (Prototyp).

~~ Aber vim hat nicht richtig funktioniert. ~~ Es scheint, dass die ostasiatische Mehrdeutigkeitsschrift je nach Gebietsschema unterschiedliche Anzeigen in halber oder voller Breite aufweist. Nach Angaben von Siracamus funktionierte vim auch gut mit : set ambiwidth = double.

Die Terminal- und VIM-Einstellungen wurden mit den beiden oben genannten Punkten aufgelöst. Vielen Dank, Siracamus.

Dieses Programm wird ohne Verwendung mehrdeutiger Schriftarten erstellt.

Vor dem Kompilieren

sudo apt-get install libncursesw5-dev

Bitte installieren Sie das Paket als. Wie zu kompilieren

cc maneaters.c -o maneaters -lncursesw

ist.

maneaters.c


//
//Nostalgisch, CBM-Charakterspiele wie 3032
//Realisiert mit ncursesw.
//  Maneaters. Ver 1.3
//

#include  <stdio.h>
#include  <stdlib.h>
#include  <time.h>

//Um ncursesw zu verwenden, werden die folgenden zwei Header-Dateien verwendet
#include  <ncursesw/ncurses.h>
#include  <locale.h>

//Die auszugebenden Zeichen sind als Konstanten definiert.
#define ENEMY   "O"
#define PLAYER  "@"
#define ROCK    "#"
#define CRASH   "X"
#define SPACE   " "

//Definition einer Funktion, die eine Zufallszahl von 0 bis x generiert.
#define rnd(x) (rand()%x)

int enemyl[40];   //Flagge, ob der Feind lebt
int enemyx[40];   //Feindliche x-Koordinate
int enemyy[40];   //Feindliche y-Koordinate

int rockl[320];   //Flagge, wenn es einen Stein gibt
int rockx[320];   //Rock x Koordinaten
int rocky[320];   //Rock y Koordinaten

int enemymax=12;  //Anzahl der ersten Feinde

int rockmax=120;  //Anzahl der ersten Steine

int playerx,playery;  //Spielerkoordinaten

int h,w;              //Bildschirmhöhe,width

int xsize,ysize;      //Bildschirmgröße des Spiels.
                      //80x25 Bildschirm, quadratische UTF in voller Breite mit gleich breiter Schrift-8
                      //Und ich benutze es
                      //Hier ist xsize 40.

int gamestat;         //Spielstatus: 0 Spielt gerade
                      //Ich verliere
                      //3 gewinnen

/*
 *Wenn sich der Spieler bewegt
 *Feststellen, ob Sie etwas treffen
 *Rückgabewert;1: Kollision 0: Nichts
 */
int check_player_crash() {
  //
  //Feststellen, ob Sie einen Feind treffen
  //
  for(int i=0;i<enemymax;i++) {
    if((enemyl[i]==1)&&(playerx==enemyx[i]) && (playery==enemyy[i]))
      return(1);
    }
  //
  //Beurteilung, ob es einen Stein getroffen hat oder nicht
  //
  for(int i=0;i<rockmax;i++) {
    if((rockl[i]==1)&&(playerx==rockx[i]) && (playery==rocky[i]))
      return(1);
    }
  return(0);
}

/*
 *Eine Funktion, die Zeichen auf dem Bildschirm anzeigt.
 *Da es in Einheiten voller Breite gehandhabt wird
 *Die x-Koordinate wird verdoppelt.
 */
int putchara(int x,int y,char *str){
  move(y,x*2);
  addstr(str);
}

/*
 *Spielinitialisierung
 */
int init_game() {
  int i;
  clear();            //Bildschirm löschen

  gamestat=0;         //Spielstatus initialisieren

  //Nehmen Sie den Startwert der Zufallszahl aus der Zeit und initialisieren Sie ihn.
  srand((unsigned)time(NULL));

  //
  //Platziere einen Stein.
  //Die 0. besteht darin, eine Kollision zwischen dem Spieler und dem Feind zu vermeiden
  //Platzieren Sie den Dummy in der Mitte des Bildschirms. Daher ist die Anzahl der Steine
  //  rockmax-Es wird 1.
  // 
  rockx[0]=xsize/2;
  rocky[0]=ysize/2;
  rockl[0]=0;
  for(i=1;i<rockmax;i++) {
    putchara(rockx[i]=rnd(xsize),rocky[i]=rnd(ysize),ROCK);
    rockl[i]=1;
    }

  //Platziere den Feind so, dass er nicht auf den Felsen trifft.
  i=0;
  while(i<enemymax) {
    int ex,ey,f;
    ex = rnd(xsize);
    ey = rnd(ysize);
    f = 0;
    for(int j=0;j<rockmax;j++) {
      if ((ex==rockx[j])&&(ey==rocky[j]))
        f=f|1;
      }
    if (f==0) {
      putchara(enemyx[i]=ex,enemyy[i]=ey,ENEMY);
      enemyl[i]=1;
      i++;
      }
    }

  //Platzieren Sie den Player in der Mitte des Bildschirms.
  putchara(playerx=xsize/2,playery=ysize/2,PLAYER);

}

/*
 *Bewege die Feinde
 */
void  move_maneaters() {
  int dx,dy;
  int x,y;

  for(int i=0;i<enemymax;i++) {
    if (enemyl[i]==0)   //Überspringen, wenn der Feind tot ist
          continue;
    //
    //Fragen Sie nach dem Unterschied, um den Spieler zu jagen
    //
    dx=0,dy=0;
    if (enemyx[i]<playerx) dx=1;
    if (enemyx[i]>playerx) dx=-1;
    if (enemyy[i]<playery) dy=1;
    if (enemyy[i]>playery) dy=-1;

    //Verschwinde den Feind in der aktuellen Position
    putchara(enemyx[i],enemyy[i],SPACE);

    //Finden Sie die Koordinaten, wo sich der Feind bewegt hat
    x=enemyx[i]+dx,y=enemyy[i]+dy;

    //
    //Auf Kollisionen zwischen Feinden prüfen
    //
    for(int j=0;j<enemymax;j++) {
      if ((i!=j)&&(enemyl[j]==1) && (x==enemyx[j]) && (y==enemyy[j])) {
          enemyl[i]=0;          //Senken Sie die Flagge, dass der Feind lebt.
          }
      }

    //
    //Kollisionskontrolle mit Steinen
    //
    for(int j=0;j<rockmax;j++) {
      if ((rockl[j]==1)&&(x==rockx[j]) && (y==rocky[j])) { //Hast du den Felsen getroffen?
        rockl[j]=enemyl[i]=0;
        putchara(x,y,SPACE);  //Lösche den Stein
        }
      }

    enemyx[i]=x,enemyy[i]=y;  //Gehen Sie den Feind noch einen Schritt weiter
    if (enemyl[i])    //Sind die Feinde am Leben?
      putchara(enemyx[i],enemyy[i],ENEMY);  //Zeichne einen Feind

    //
    //Überprüfen Sie, ob es mit dem Player kollidiert ist
    //
    if ((x==playerx) && (y==playery))
        gamestat=1;     //Wenn Sie kollidieren, verlieren Sie
    }

}

//
//Hauptschleife des Spiels
//
int main_game() {
  int f,dx,dy;
  while(1) {

/*
 *Spielerverarbeitung
 */
  switch(getch()) {     //Eingabe der Spielertaste und Erfassung der Bewegungsrichtung
    case  '7': dx=-1,dy=-1; break;
    case  '8': dx= 0,dy=-1; break;
    case  '9': dx= 1,dy=-1; break;
    case  'u': case  '4': dx=-1,dy=0; break;
    case  'i': case  '5': dx= 0,dy=0; break;
    case  'o': case  '6': dx= 1,dy=0; break;
    case  'j': case  '1': dx=-1,dy=1; break;
    case  'k': case  '2': dx= 0,dy=1; break;
    case  'l': case  '3': dx= 1,dy=1; break;
    default:
      continue;
    }

    //Geht der Player vom Bildschirm?
    if (((playerx+dx)>=0) && ((playerx+dx)<xsize) &&
        ((playery+dy)>=0) && ((playery+dy)<ysize)) {

      putchara(playerx,playery,SPACE);  //Gehen Sie mit dem Spieler noch einen Schritt weiter.
      playerx+=dx;
      playery+=dy;
      putchara(playerx,playery,PLAYER);

      //Wenn der Spieler einen Stein oder einen Feind trifft, ist das Spiel beendet.
      if (check_player_crash()) {
              gamestat=1;
              return(0);
            }
      }
    /*
     *Feindliche Verarbeitung
     */
    move_maneaters();
    if (gamestat!=0) return(0);

    /*
     *Gewinnen Sie, wenn der Menschenfresser vernichtet wird
     */
    f=0;
    for(int j=0;j<enemymax;j++)
      f|=enemyl[j];
    if (f==0) {
      gamestat=3;
      return(0);
      }
  }
}
    
/*
 *Eine Funktion, die Sie fragt, ob Sie erneut spielen möchten
 *Rückgabewert; 0: Nein 1: Ja
 */
int tryagainp() {
  printw("Try Again? [y/n]");
  while(1) {
    switch(getch()) {
      case  'n': return(0);
      case  'y': return(1);
      default: continue;
      }
    }
}

/*
 *Spielbeschreibungsbildschirm
 *
 */
void  instruction() {
    clear();      //Bildschirm löschen

    printw("Maneaters Ver 1.3\n"); //Drucken Sie mit printw auf stdscr.

    printw("Mission : kill all maneaters to survive!\n");
    printw("%s -- Maneater, chase player step by step.\n",ENEMY);
    printw("%s -- Rock, die maneaters and player when touched. \n",ROCK);
    printw("%s -- Player, control for maneaters to crash to rock and survive!\n",PLAYER);
    printw("\n");
    printw("Key control:             Tenkey:     \n");
    printw(" 7  8  9            7 8  9   \n");
    printw("  ↖ ↑  ↗                 ↖ ↑  ↗     \n");
    printw("u← i →o             4← 5→ 6   \n");
    printw("  ↙ ↓  ↘                 ↙ ↓  ↘     \n");
    printw(" j  k   l           1  2  3   \n");
    printw("\n");
    printw(" 'i' and '5' move maneater and don't move player.\n");
    printw("             Good Luck\n");
    printw("hit key\n");

    getch();    //Warten auf die Eingabe einer einstelligen Taste.
  }

//
//Spielbeschreibungsbildschirm und Hauptschleifenschleife
//
void  play_game() {
  while(1) {

    instruction();    //Rufen Sie den Spielbeschreibungsbildschirm auf.

    init_game();      //Spielinitialisierung

    main_game();      //Hauptschleife des Spiels

    if (gamestat==1) {  //Spieler verliert
      putchara(playerx,playery,CRASH);
      move(0,0);
      printw("You Lose ");
      }

    if (gamestat==3) {  //Spieler gewinnt
      move(0,0);
      printw("You Win!! ");
      }

    if (tryagainp()==0) return; //Zurück, wenn nicht wiederholt.
    }
}
/*
 *Hauptfunktion
 */
int main() {
  setlocale( LC_ALL,"" ); //UTF mit ncursesw-8 verwenden
                          // LC_Setzen Sie alle.

  initscr();              //Bildschirminitialisierung

  noecho();               //Schalten Sie das Tastaturecho aus

  curs_set(0);            //Verstecke den Cursor.

  getmaxyx(stdscr,h,w);   //Bildschirmgröße, h,Speichern in w
                          //Normalerweise 80x25

  xsize=w/2;              //Finde die im Spiel verwendete Bildschirmgröße.

  ysize=h;                //Finde die Y-Größe des im Spiel verwendeten Bildschirms.

  play_game();            //Führen Sie das Spiel aus.

  endwin();               //Schließen Sie den Bildschirm.

  exit(0);                //Fertig.
}


Recommended Posts

Nostalgisch, lasst uns ein Charakterspiel wie CBM-3032 mit ncursesw reproduzieren.
Versuchen Sie, ein einfaches Spiel mit Python 3 und iPhone zu erstellen
Fühlen wir uns wie ein Materialforscher mit maschinellem Lernen
Ich habe mit Tkinter of Python ein Puzzlespiel (wie) gemacht
Fühlen wir uns wie ein Materialforscher mit Python [Einführung in Pymatgen]
Lassen Sie uns eine GUI mit Python erstellen.
Machen wir einen Blockbruch mit wxPython
Zura machte wie ein Lebensspiel
Lassen Sie uns ein Diagramm mit Python erstellen! !!
Machen wir mit xCAT einen Spacon
Spielen Sie wie eine Web-App mit ipywidgets
Ich habe mit Python einen Zeichenzähler erstellt
Erstellen wir mit Python eine kostenlose Gruppe
Lassen Sie uns mit Docker eine dynamische Site kratzen
Lassen Sie uns mit Python langsam sprechen
Lassen Sie uns mit PLY 1 eine einfache Sprache erstellen
Ich habe ein Lebensspiel mit Numpy gemacht
Erstellen Sie ein Webframework mit Python! (1)
Machen wir mit Pylearn 2 eine dreiäugige KI
Lassen Sie uns die chinesische Retro-Spielmaschine analysieren
Zeichendatendatei mit numpy lesen
Machen wir einen Twitter-Bot mit Python!
Ich habe mit Python ein schurkenhaftes Spiel gemacht
Erstellen Sie ein Webframework mit Python! (2)