LCD 4 Bit Text Adventure - Gelöst

Fertig :wink:

Ein kleines Textadventure...

Zum Nachbau benötigt:

  • Arduino Uno oder Duemilanove (andere könnten auch gehen, kenne nur die beiden)
  • LCD Keypad Shield (oder entsprechende Verkabelung mit 4 Buttons)
  • Bei Verkabelung ohne Shield: LCD Display 2x16 weiß auf blau (ja, die Profis wissen es besser :wink: )

(LCD Shield für Arduino [DFR0009] - 10.10EUR : komputer.de, Arduino Open Source Hardware)

Man spielt einen unbekannten Char, der sich durch die Wälder bewegt. Wenn man einem Feind begegnet, kann man diesem nur mit einer Waffe beikommen. Das Spiel ist vorbei, wenn

  • der Gegner besiegt wurde
  • man(n) vom Genger geschlagen wurde
  • der Ausgang gefunden wurde

Viel Spaß damit.
Bei Weiterentwicklungen würde ich mich über eine Benachrichtigung freuen (oder vielleicht einen Eintrag in meinem Forum).

LG

DA

/*

 Little text adventure
 
 By DarkAngel
 
 *technikzumanfassen.forumieren.com*
 
 XXXXXXXXXX
 X O      X
 X   X  X X
 X XXX  X X
 X   X CX X   <-- your Char ;-)
 XE  X  XSX
 XXX XXXXXX
    ^ Exit
 */

#include <LCD4Bit_mod.h> 
//create object to control an LCD.  // (original Code from example)
//number of lines in display=2
LCD4Bit_mod lcd = LCD4Bit_mod(2); 

//Key sequence: right, up, down, left, select
int adc_key_val[5] ={
  30, 150, 360, 535, 760 };
int NUM_KEYS = 5;  // there are 5 keys
int adc_key_in;
int key=-1;
int last_key=-1;   // needed to go back to last position

// Variables for the game
int playerposition[2] = { 
  4, 5};
int x = playerposition[0]; // giving actual player position to variables
int y = playerposition[1]; // needed for next position and status

int playfield[9][7] =  {
  { 0,0,0,0,0,0,0  }
  ,
  { 0,1,1,1,1,5,0  }
  ,
  { 0,2,1,0,1,1,9  }
  ,
  { 0,1,0,0,0,0,0  }
  ,
  { 0,1,1,1,1,1,0  }
  ,
  { 0,1,1,1,1,1,0  }
  ,
  { 0,1,0,0,0,0,0  }
  ,
  { 0,1,1,1,1,3,0  }
  ,
  { 0,0,0,0,0,0,0  }
}; // 0=wall, 1=free field, 2=coin, 3=weapon, 5=enemy, 9=exit
   // and I really don't know why this has to be rotated right by 90° and horizontally flipped...
int inventory[1];  //only to say the player if he has a weapon
char messages[10][19] =  {
  "a tree...        ",
  "moving           ",
  "got a coin       ",
  "got a weapon     ",
  "an enemy         ",
  "defended         ",
  "enemy dies       ",
  "nothing to defend",
  "you die          ",
  "GAME OVER        "};

void setup() 
{ 
  // (original Code from example)
  pinMode(13, OUTPUT);  //we'll use the debug LED to output a heartbeat

  lcd.init();
  //optionally, now set up our application-specific display settings, overriding whatever the lcd did in lcd.init()
  //lcd.commandWrite(0x0F);//cursor on, display on, blink on.  (nasty!)
  lcd.clear();
  lcd.printIn("In the woods");  // my Title ;-)
  Serial.begin(9600);
}

void loop() 
{
  lcd.cursorTo(2, 0);  //line=2, x=0  (original Code from example)

  if(x==0 && y==0) // if game over, don't do anything
  {
    delay(5000);
  }
  else
  {  
    adc_key_in = analogRead(0);    // read the value from the sensor   (original Code from example)
    digitalWrite(13, HIGH);

    key = get_key(adc_key_in);	   // convert into key press   (original Code from example)
    delay(50);		           // wait for debounce time   (original Code from example)
    adc_key_in = analogRead(0);    // read the value from the sensor   (original Code from example)
    key = get_key(adc_key_in);	   // convert into key press   (original Code from example)

    digitalWrite(13, LOW);   // (original Code from example)

    if (key >=0)                   // if pressed any key
    {
      delay(50);
      int z = get_point(key);      // sending the pressed key to function get_point
      delay(100);
      key=-1;

      if(z==0)                    // if standing in front of a tree, tell them
      {
        switch(last_key)
        {
        case 0: 
          x--;
          break;
        case 1: 
          y++;
          break;
        case 2: 
          y--;
          break;
        case 3: 
          x++;
          break;
        default: 
          last_key = -1;
          break;
        }
        lcd.cursorTo(2, 0);
        lcd.printIn(messages[z]);
        lcd.cursorTo(2, 0);
      } // End z==0

        if(z==1 || z==2)             // if found a coin or free field, move
      {
        playerposition[0] = x;
        playerposition[1] = y;
        lcd.cursorTo(2, 0);
        lcd.printIn(messages[z]);   // the coin has no use (yet)
        lcd.cursorTo(2, 0);
      } // End z==1, z==2
      if(z==3)                     // if found a weapon, equip it and move
      {
        inventory[0] = 3;
        playerposition[0] = x;
        playerposition[1] = y;
        lcd.cursorTo(2, 0);
        lcd.printIn(messages[z]);
        lcd.cursorTo(2, 0);
      } // End z==3
      if(z==5)                       // if found an enemy, search weapon
      {
        playerposition[0] = x;
        playerposition[1] = y;
        playfield[x][y] = '1';     // remove enemy from map

        if(inventory[0]==3)          // if weapon is found,
        {
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[5]);  // destroy enemy
          delay(500);
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[6]);  // and win game
          lcd.cursorTo(2, 0);
          delay(1500);
          z = 9;
        }
        else
        {
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[7]);  // else you will be destroyed by enemy
          delay(500);
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[8]);  // Game Over
          lcd.cursorTo(2, 0);
          z = 9;
        }
      }//end z==5
      if(z==9)                    // if game is lost or won, show game over
      {
        x=0;
        y=0;
        lcd.cursorTo(2, 0);
        lcd.printIn(messages[9]);
        delay(5000);
      }//end z==9        
    }//end key>=0   
  }//end else
}


// Convert ADC value to key number    (original Code from example)
int get_key(unsigned int input)
{
  int k;

  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }

  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed

  return k;
}

/*************************
 * Get point on playfield *
 **************************/
int get_point(unsigned int key)
{
  lcd.cursorTo(2, 0);
  int point;

  if(key==0)                // show direction where you wanted to go
  {
    x++;
    last_key=0;
    lcd.printIn("right            ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==1)
  {
    y--;
    last_key=1;
    lcd.printIn("up               ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==2)
  {
    y++;
    last_key=2;
    lcd.printIn("down             ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==3)
  {
    x--;
    last_key=3;
    lcd.printIn("left             ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==4)                // if select key was pressed, show inventory
  {
    if(inventory[0]==3)
    {
      lcd.printIn("weapon           ");
      lcd.cursorTo(2, 0);
      delay(500);
    }
    else
    {
      lcd.printIn("nothing          ");
      lcd.cursorTo(2, 0);
      delay(500);
    }
  }

  point = playfield[x][y];  // get point of playfield where you wanted to go

  switch(point)
  {
  case 0: 
    return 0;               // point is a wall (tree)?
    break; 
  case 1: 
    return 1;               // point is a free field?
    break; 
  case 2: 
    return 2;               // point is a coin (and actually a free field)?
    break;
  case 3: 
    return 3;               // point is a weapon?
    break;   
  case 5: 
    return 5;               // point is the enemy?
    break;
  case 9: 
    return 9;               // point is the exit?
    break;

  }
}

Hallo !

Kann dir zwar absolut nicht weiterhelfen, muss aber mal meine Hochachtung vor deinem Projekt ausdrücken.

Genauso cool wie der hier: - YouTube
( Mit Level-Editor ! )

Falls es geht, stelle doch auch ein Video ein ( auch mit dem Fehler ).

MfG

Vielen Dank für die aufmunternden Worte...

Das war mal wieder logisch, dass der Hamster, an dem ich schon während meines Studiums (Wirtschaftsinformatik) verzweifelt bin, mir mal wieder das Genick bricht. Dabei ist doch alles so einfach?!

Das Super Mario Spiel sieht auch toll aus. Auf die Idee wäre ich gar nicht gekommen. Ich habe aber auch nur zwei Zeilen, gelle :wink:

LG

Das war mal wieder logisch, dass der Hamster, an dem ich schon während meines Studiums (Wirtschaftsinformatik) verzweifelt bin, mir mal wieder das Genick bricht. Dabei ist doch alles so einfach?!

Du sprichst in Adventure-Rätseln ? Ein Hamster bricht dir das Genick ?

Gehe Sued; Nimm Schwert; Toete Hamster

Auf meinem ersten Rechner ( Texas Instruments TI-99/4A – Wikipedia ), gab es auch eine Reihe Text-Adventures mit Zusatz-Modul.
Andere funktionierten auch ohne das Zusatz-Modul. Der Rechner hatte nur 16 kByte RAM. Der Arduino ( mit 328 ) hat das Doppelte an Speicher !

MfG

Gurkengraeber:

Das war mal wieder logisch, dass der Hamster, an dem ich schon während meines Studiums (Wirtschaftsinformatik) verzweifelt bin, mir mal wieder das Genick bricht. Dabei ist doch alles so einfach?!

Du sprichst in Adventure-Rätseln ? Ein Hamster bricht dir das Genick ?

Das Hamster-Projekt ist für Programmieranfänger gedacht. Normalerweise fängt man mit sowas an: Informationssysteme // Universität Oldenburg
An der Uni hatte ich allerdings die Programmiersprache Java vor der Nase, musste als Konsolenprogramm einen ähnlichen Raum aufbauen, wie in meinem jetzigen Arduino-Projekt und dann sollte der Hamster (Symbol: ^) sich automatisch da drin bewegen.

Wenn in meinem Projekt das "E" für den Hamster steht, dann wäre ich schwer begeistert, wenn sich mein "Char" dazu bewegen lassen könnte das Schwert "S" einzusammeln...

Hallo DarkAngel1004 !

Das ist ja cool ! War mir völlig unbekannt !

Logo kannte ich: Logo (Programmiersprache) – Wikipedia

wohl so 'ne Art Vorläufer davon für Kinder.
Aber den Hamster werde ich mal meinem Neffen beibiegen.

Außerdem solltest du, DarkAngel1004, dafür dankbar sein ! Das Hamster-Ding hat Ansätze von OOP wie eben Java ( und C++, C# ) .
Ich kann Assembler ( wovon ich bei jedem Prozessor die Mnemonics nach 2 Wochen vergesse), BASIC ( Auch schon kein VisiualBASIC mehr ), und eben C ( ohne Zusätze )
Eben nur Straight-Programmierung. OOP begreife ich nimmer mehr.

MfG

Jetzt funktioniert es soweit (ich musste nach jeder Ausgabe auf dem Display den Cursor wieder zurücksetzen), allerdings scheint sich der Char nicht durch das Labyrinth zu bewegen, das ich ihm gebastelt habe:

/*

 Little text adventure
 
 By DarkAngel
 
 *technikzumanfassen.forumieren.com*
 
 XXXXXXXXXX
 X O      X
 X   X  X X
 X XXX CX X   <-- your Char ;-)
 X   X  X X
 XE  X  XSX
 XXX XXXXXX
    ^ Exit
 */
// (original Code from example)
#include <LCD4Bit_mod.h> 
//create object to control an LCD.  
//number of lines in display=2
LCD4Bit_mod lcd = LCD4Bit_mod(2); 

//Key Reihenfolge: rechts, oben, unten, links, select
int adc_key_val[5] ={
  30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;

// Variables for the game
int playerposition[2] = { 5, 4};
int x = playerposition[0]; // giving actual player position to variables
int y = playerposition[1]; // needed for next position and status

int playfield[7][9] =  {
  {0,0,0,0,0,0,0,0,0},
  {0,1,2,1,1,1,1,1,0},
  {0,1,1,0,1,1,0,1,0},
  {0,1,0,0,1,1,0,1,0},
  {0,1,1,0,1,1,0,1,0},
  {0,5,1,0,1,1,0,3,0},
  {0,0,9,0,0,0,0,0,0}
                       }; // 0=wall, 1=free field, 2=coin, 3=weapon, 5=enemy, 9=exit
int inventory[1];
char messages[10][19] =  {
  "a tree...        ",
  "moving           ",
  "got a coin       ",
  "got a weapon     ",
  "an enemy         ",
  "defended         ",
  "enemy dies       ",
  "nothing to defend",
  "you die          ",
  "GAME OVER        "};

void setup() 
{ 
  // (original Code from example)
  pinMode(13, OUTPUT);  //we'll use the debug LED to output a heartbeat

  lcd.init();
  //optionally, now set up our application-specific display settings, overriding whatever the lcd did in lcd.init()
  //lcd.commandWrite(0x0F);//cursor on, display on, blink on.  (nasty!)
  lcd.clear();
  lcd.printIn("In the woods");  // my Title ;-)

}

void loop() 
{
  lcd.cursorTo(2, 0);  //line=2, x=0  (original Code from example)

  if(x==0 && x==0) // if game over, don't do anything
  {
    delay(5000);
  }
  else
  {  
    adc_key_in = analogRead(0);    // read the value from the sensor   (original Code from example)
    digitalWrite(13, HIGH);

    key = get_key(adc_key_in);	   // convert into key press   (original Code from example)
    delay(50);		           // wait for debounce time   (original Code from example)
    adc_key_in = analogRead(0);    // read the value from the sensor   (original Code from example)
    key = get_key(adc_key_in);	   // convert into key press   (original Code from example)

    digitalWrite(13, LOW);   // (original Code from example)

    if (key >=0)                   // if pressed any key
    {
      delay(50);
      int z = get_point(key);      // sending the pressed key to function get_point
      delay(100);
      
      //lcd.cursorTo(2, 0);
      //lcd.printIn(messages[9]);
      
      if(z==0)                    // if standing in front of a tree, tell them
      {
        lcd.cursorTo(2, 0);
        lcd.printIn(messages[z]);
        lcd.cursorTo(2, 0);
      } // End x==0
      
      if(z==1 || z==2)             // if found a coin or free field, move
      {
        playerposition[0] = x;
        playerposition[1] = y;
        lcd.cursorTo(2, 0);
        lcd.printIn(messages[z]);
        lcd.cursorTo(2, 0);
      } // End x==1, x==2
      if(z==3)                     // if found a weapon, equip it and move
      {
        inventory[0] = 3;
        playerposition[0] = x;
        playerposition[1] = y;
        lcd.cursorTo(2, 0);
        lcd.printIn(messages[z]);
        lcd.cursorTo(2, 0);
      } // End x==3
      if(z==4)                       // if found an enemy, search weapon
      {
        if(inventory[0]==3)          // if weapon is found,
        {
          delay(100);
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[5]);  // destroy enemy
          delay(50);
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[6]);  // and win game
          lcd.cursorTo(2, 0);
        }
        else
        {
          delay(100);
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[7]);  // else you will be destroyed by enemy
          delay(100);
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[8]);  // and loose game
          lcd.cursorTo(2, 0);
          z = 9;
        }
        if(z==9)                     // if game is lost or won, show game over
        {
          playerposition[0] = 0;
          playerposition[1] = 0;
          lcd.cursorTo(2, 0);
          lcd.printIn(messages[9]);
          delay(5000);
        }        
      }   
    }
  }
}

// Convert ADC value to key number    (original Code from example)
int get_key(unsigned int input)
{
  int k;

  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }

  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed

  return k;
}

/*************************
 * Get point on playfield *
 **************************/
int get_point(unsigned int key)
{
  lcd.cursorTo(2, 0);
  int point;

  if(key==0)                // show direction where you wanted to go
  {
    x++;
    lcd.printIn("right            ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==1)
  {
    y--;
    lcd.printIn("up               ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==2)
  {
    y++;
    lcd.printIn("down             ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==3)
  {
    x--;
    lcd.printIn("left             ");
    lcd.cursorTo(2, 0);
    delay(100);
  }
  if(key==4)                // if select key was pressed, show inventory
  {
    if(inventory[0]==3)
    {
      lcd.printIn("weapon           ");
      lcd.cursorTo(2, 0);
      delay(500);
    }
    else
    {
      lcd.printIn("nothing          ");
      lcd.cursorTo(2, 0);
      delay(500);
    }
  }

  point = playfield[x][y];  // get point of playfield where you wanted to go

  switch(point)
  {
  case 0: 
    return 0;               // point is a wall (tree)?
    break; 
  case 1: 
    return 1;               // point is a free field?
    break; 
  case 2: 
    return 2;               // point is a coin (and actually a free field)?
    break;
  case 3: 
    return 3;               // point is a weapon?
    break;   
  case 5: 
    return 5;               // point is the enemy?
    break;
  case 9: 
    return 9;               // point is the exit?
    break;

  }
}

Inzwischen jemand von der Arbeit zu Hause, der den Fehler sieht? :slight_smile:

FERTIG!!!