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