Snake mit AVR

Moderatoren: Tim Sasdrich, Sebi

Snake mit AVR

Beitragvon Anse » 09.03.2013, 16:37

Jetzt gibt es mal ein Spaßprojekt für zwischendurch von mir. Als ich das Pong von Chef gesehen hatte, kam mir die Idee auf dem gleichen Display Snake zu spielen. Mit C ist die Aufgabe schnell gelöst. Die Hardware besteht aus dem µC Atmega8, 4 Taster, Dot-Matrix Display 5x7 (TC07-11) und etwas Hünerfutter.

Nach dem Start erscheinen zwei Punkte auf dem Display. Einer in der Mitte und einer auf einer weiteren Position. Wenn jetzt eine der Richtungstasten gedrückt wir, bewegt sich der Punkt aus der Mitte in die gedrückte Richtung. Jetzt kann die Schlange auf den anderen Punkt gesteuert werden. Wenn er erreicht ist, erscheint ein neuer Punkt und die Schlange wird ein Punkt länger. Wenn der Displayrand überschritten wir oder sich die Schlange selbst berührt ist das Spiel vorbei.

Das "kleine" Programm:
Spoiler: show
Code: Alles auswählen
/*
* snake.c
*
*  Author: Anse
Chip: Mega8
Fuse high 0xFF, low x0E4
int. RC Osc 8MHz
*/


#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

//Konstanten
#define up 10
#define down 20
#define right 30
#define left 40




volatile uint8_t zeichen[5] = {0,0,0,0,0};//Displayspeicher

//volatile uint8_t zeile[5]={0b01111,0b10111,0b11011,0b11101,0b11110};
volatile uint8_t zeile[5]={0b10000,0b01000,0b00100,0b00010,0b00001};

uint8_t end[5]={0b1000001,0b0000010,0b0011010,0b0000010,0b1000001};

volatile uint8_t a=0,p=0,i=0;
uint8_t level_count=0, index=0,punkt=0,direction=0,length=1,x=2,y=3,key=0,last_key=0,game_over=0,catched=0,c=0;

//Array für die Positionen der Punkte auf der Schlange
uint8_t xs[37]={2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t ys[37]={3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};


const uint8_t punkt_x[] PROGMEM={1,4,1,0,0,2,2,1,4,4,1,2,2,1,1,3,3,4,4,3,2,2,3,2,1,3,2,3,4,1,4,2,2,4,4};
const uint8_t punkt_y[] PROGMEM={2,1,3,3,4,5,6,6,1,2,3,4,2,6,0,2,4,5,4,6,2,2,4,2,4,4,5,4,4,2,4,4,5,6,0};

//Prototypes
void gameover(void);   //stellt ein Bild da wenn das Spiel vorbei ist           
void set_pixel(uint8_t,uint8_t);  //setzt ein Pixel auf dem Display, übergeben wird die x und y Position.
void clear_pixel(uint8_t,uint8_t); //das Gegenteil von set_pixel
void clear_display(void); //Löscht das Display
uint8_t getkay(void);//Fragt die Tasten ab
void shift(void); //schiebt die Schlange eine Stelle weiter
uint8_t check_if_point_on_snake(uint8_t,uint8_t,uint8_t); //Wenn die übergebenen Koordinate auf
                                                           //der Schlange liegt wird eine 1 zurückgegeben
void set_point(void); //setzt einen neuen Fangpunkt


int main(void)
{

//Timer0 für den Multiplexbetrieb   
TCCR0 |=(1<<CS01)|(1<<CS00) ;
TIMSK |=(1<<TOIE0);
sei();


   DDRD=0b11111111; //Zeilen
   DDRB=0b11111; //Spalten
    //Port für die Tasten
   DDRC=0;
   PORTC=0xff;
   PORTD=0;


   
   set_pixel(2,3); //Startpunkt auf Mitte des Displays


   while(1)

    {
      
      
    key=getkay();//Abfragen der Tasten
   
    if (key!=last_key) //gabs eine Veränderung?
    {
   last_key=key;  //Tastenwert speichern
   if (key>0)
   {
   //Richtung setzen
   if (key==up)
   {
   if (direction!=down)
   {
   direction=key;
   }
      
   }
   
   if (key==down)
   {
   if (direction!=up)
   {
   direction=key;
   }
   }
   
   if (key==right)
   {
   if (direction!=left)
   {
   direction=key;
   }
   
   }
   
   if (key==left)
   {
   if (direction!=right)
   {
   direction=key;
   }
      
   }
   
   }
   }
   
   
   
   shift(); //Schlange um eine Position verschieben    
   
   //Richtung auswerten
   switch (direction)
   {
   case up:ys[0]++;
   if (ys[0]==7)
   {
      game_over=1;
   }
   break;
   case down:ys[0]--;
   if (ys[0]==255)
   {
      game_over=1;
   }
   break;
   case right:xs[0]++;
     if (xs[0]==5)
   {
      game_over=1;
   }
   break;
   case left:xs[0]--;
   if (xs[0]==255)
   {
      game_over=1;
   }
   break;
   }
   
   
   //Wenn der Anfang der Schlange auf dem zu fangenden Punkt liegt...
   if (xs[0]==x)
   {
   if (ys[0]==y)
   {
         
   length++; //Länge wird erhöht
   index=0;
      
   catched=1;
   
   set_point();//neuer zu fangender Punkt setzten   
   }
   }      
   
   
   //Zeichnen der Schlange
    for (i=0;i<length;i++)
    {
   set_pixel(xs[i],ys[i]);   
   }   
      
      if (direction>0) //Abfragen, ob das Spiel läuft
   {   
   c=check_if_point_on_snake(2,xs[0],ys[0]); //Prüfen ob der Schlangenanfang auf der Schlange liegt
   if (c==1)
   {
      game_over=1; //wenn ja, dan Gameover
   }
   
   if (game_over==1)
   {
   game_over=0;
   length=2;
   xs[0]=2;
   ys[0]=3;
   punkt=0;
   direction=0;
   clear_display();
   gameover();
   _delay_ms(1000);   
   clear_display();
   set_pixel(xs[0],ys[0]);
   set_point();
   }   

   
   clear_pixel(xs[length],ys[length]);   //pixel am Schlangenende löschen
    }
   
   
   //warten für den nächtsten Schritt
   if (catched==0)
    {
      
    _delay_ms(1000);
   }
   else
   {
   catched=0;   
   _delay_ms(500);
   }
   }
      
}


void set_point(void)
{
   do
   {
   x=pgm_read_byte(&punkt_x[punkt]);
   y=pgm_read_byte(&punkt_y[punkt]);
   c=check_if_point_on_snake(0,x,y);
   punkt++;
   if (punkt==35)
   {
      punkt=0;
   }
   } while (c==1);
      
   set_pixel(x,y);
   
}


uint8_t check_if_point_on_snake(uint8_t start,uint8_t x,uint8_t y)
{
uint8_t sign=0,i=start,end;
end=length+1;
while (i<end)
{
if(xs[i]==x)
{
if(ys[i]==y)
{
sign=1;
}
}
i++;
}



return sign;   
   
}



void gameover(void)
{
for (uint8_t i=0;i<5;i++)
{
zeichen[i]=end[i];   
}

}

void shift(void)
{
   uint8_t i2=36;
for (uint8_t i=36;i>0;i--)
{
i2=i-1;   
xs[i]=xs[(i2)];
ys[i]=ys[(i2)];
}
   
   
   
}

uint8_t getkay(void)
{
uint8_t p,key=0;


p=PINC;
switch (p)
{
case 0b011111:key=up;
break;
case 0b101111:key=down;
break;
case 0b110111:key=right;
break;
case 0b111011:key=left;
break;
}   

return key;   
}

void clear_display(void)
{
for (uint8_t y=0;y<8;y++)
{
for (uint8_t x=0;x<5;x++)
{
   clear_pixel(x,y);
}

}
   
   
}

void clear_pixel(uint8_t x,uint8_t y)
{

zeichen[x]&=~(1<<y);   
   
}


void set_pixel(uint8_t x,uint8_t y)
{

zeichen[x]|=(1<<y);   
   
}


//Zeichen auf dem Display ausgeben
ISR(TIMER0_OVF_vect)
{
PORTB=0xff;
PORTD=zeichen[a];
PORTB=zeile[a];
a++;
if (a==5)
{
   a=0;
}
   
   
}


Schaltplan:
Snake.png

Die Belegung der Richtungstasten muss durch probieren herausgefunden werden.
Das gleiche gilt zum Teil auch beim Display.

Die Software ist noch nicht ganz Bug frei.
Bugs die mir bekannt sind:
  • Manchmal kommt es zu zufälligen Bildfehler.
  • Es kann vorkommen, das kein neuer Fangpunkt erscheint.
Was noch erweitert werden könnte:
  • Leveleinstellung
  • Highscore Anzeige

@Chef: wäre es auch möglich die Endung .HEX zu zulassen?

LG
Anse
Anse
 
Beiträge: 1442
Registriert: 09.06.2011, 14:18

Re: Snake mit AVR

Beitragvon dussel07 » 09.03.2013, 16:53

Super!
Die HEX auf die wir uns schon jetzt freuen kannst Du zippen und dann anhängen -
Ja, - ich bin Zwilling
Benutzeravatar
dussel07
 
Beiträge: 1627
Registriert: 30.04.2009, 21:04
Wohnort: Goslar

Re: Snake mit AVR

Beitragvon Anse » 09.03.2013, 18:10

snake.zip
(1.59 KiB) 170-mal heruntergeladen
Anse
 
Beiträge: 1442
Registriert: 09.06.2011, 14:18

Re: Snake mit AVR

Beitragvon alterhase » 09.03.2013, 19:54

Freut mich, dass du bereits deine ersten Erfolge mit C feiern kannst. 8)
Gratuliere! :wink:
Löten verbindet ...manchmals. :mrgreen:
73 55
alterhase
 
Beiträge: 12050
Registriert: 14.11.2008, 08:58
Wohnort: Wien/Kapfenberg

Re: Snake mit AVR

Beitragvon Anse » 09.03.2013, 20:17

Freut mich, dass du bereits deine ersten Erfolge mit C feiern kannst.
Nicht ganz, es ist das zweite größere Projekt. Als erstes kam eins mit LCD und Tastenabfrage drann. Das ganze ist aber nicht für andere interessant, weil es ein spezial Gerät ist. Wenn jemand Interesse hat, kann ich die Funktionen für das LCD rausrücken.
Anse
 
Beiträge: 1442
Registriert: 09.06.2011, 14:18

Re: Snake mit AVR

Beitragvon alterhase » 09.03.2013, 21:48

Klug! :wink:
Ich würd auch nicht bei meinem erstgelegten Ei zu gackern beginnen :mrgreen:
Löten verbindet ...manchmals. :mrgreen:
73 55
alterhase
 
Beiträge: 12050
Registriert: 14.11.2008, 08:58
Wohnort: Wien/Kapfenberg

Re: Snake mit AVR

Beitragvon topas » 11.03.2013, 17:30

Ich hasse C. Andere auch.
topas
 
Beiträge: 3796
Registriert: 16.08.2010, 12:47

Re: Snake mit AVR

Beitragvon Anse » 11.03.2013, 17:51

Hassen kann man erst etwas, was man kennt.
Anse
 
Beiträge: 1442
Registriert: 09.06.2011, 14:18

Re: Snake mit AVR

Beitragvon Sebi » 11.03.2013, 18:17

Das einzige was micht bei C nervt sind Speicherzugriffsfehler, aber das haben Maschinennahe Programmiersprachen eben so an sich ;)
Das könnte man natürlich mit Java etc. umgehen, aber dass Java in der Performance einige Probleme hat sieht man bei Minecraft ja am besten.
Wenn man Pointer etc. verstanden hat, ist C eine Wunderschöne Programmiersprache :D
Sebi
 
Beiträge: 842
Registriert: 10.08.2009, 17:57
Wohnort: Darmstadt

Re: Snake mit AVR

Beitragvon topas » 15.03.2013, 21:05

Sebi hat geschrieben:Wenn man Pointer etc. verstanden hat, ist C eine Wunderschöne Programmiersprache :D
"Jau!"
Pointer sind keine Alleineigenschaft von C. Mikrobasic, das ich verwende kann Pointer (und auch mit ihnen rechnen) - Das kann nicht der Vorteil von C sein. Das unverständliche ++ Gekürzel? Die blöden geschweiften Klammern?
Den einzigen Unterschied (grundlegend von den Möglichkeiten) sehe ich im Fehlen der Datenstrukturen : struct und unions.
Sonst gibts meiner Meinung nach gar nichts!

Ich hab sie nicht vermisst!

Mit dem AVR-Luna-Projekt gibt es sogar den Versuch, so etwas wie Objekte einzuführen. Sehr akademisch - aber auch praktisch - ich find es toll!
Objekte braucht bei µCs (meiner Meinung nach) eh kein Mensch. Wenn man ARM-Prozessoren und LCD-Bildschirme, SD-Cards, USB-Sticks usw. braucht, dann wird es mit Basic einen kleinen Tick aufwendiger. Aber wirklich nur ein Tick. Structs und unions - aber mehr auch nicht.

Mit Basic muss man manchmal das Rad neu erfinden. Für C findet man oft fertige Lösungen und Bibliotheken - auch von den Chip-Herstellern.
Bei der eigenen Vorstellung von Basic muss man sich von Bascom lösen - es gibt auch erwachsenes Basic. Wer schon mal einen Blick auf den SourceCode von pahlbasic riskiert hat, wird vielleicht feststellen, was ich für ein Programmierer bin :D - aber vielleicht auch welche Möglichkeiten in Basic stecken.

Schöner ist Basic allemal.

Das Klammergeschweife ist m.M. extrem hässlich.

Aber:
If Basictext then
Basictext...........
else Basictext.............
end if
dat is schön. :D

Sollte "C" eines Tages mal so etwas Klares hervorbringen, kann man mich auch überzeugen.
Für alles andre bin ich zu alt. :D
topas
 
Beiträge: 3796
Registriert: 16.08.2010, 12:47

Re: Snake mit AVR

Beitragvon Tim Sasdrich » 15.03.2013, 21:59

Mir gefällt C auch nicht. Immer muss man auf die Groß- und Kleinschreibung achten, sonst gibt es Fehler, die man ewig sucht.
Auch das ; am Ende einer Zeile finde ich nicht so toll.

Und einen einfachen Befehl, wie z.B. "Wait 1" um eine Sekunde zu warten habe ich da auch noch nicht gefunden.
"Der Kluge lernt aus allem und von jedem, der Normale aus seinen Erfahrungen und der Dumme weiß alles besser." - Sokrates (470 - 399 v. Chr.), griechischer Philosoph
Tim Sasdrich
 
Beiträge: 2961
Registriert: 07.01.2009, 14:15
Wohnort: Villingen-Schwenningen

Re: Snake mit AVR

Beitragvon topas » 15.03.2013, 22:24

Tim Sasdrich hat geschrieben:Und einen einfachen Befehl, wie z.B. "Wait 1" ....

So einen "Befehl" gibt es auch in "Erwachsenen Basic" nicht.

Anweisungen, Befehle kennt nur der Kern einer Programmiersprache. goto, gosub sind so Anweisungen, die in Erwachsenenbasic aber keiner mehr verwendet. If, while, select usw. sind Kernbestandteile der Sprache.
wait 1 wäre eine Funktion, die selbst in der Programmiersprache geschrieben wäre - kein Befehl, der zur Sprache selbst gehört. Bascom macht da keinen Unterschied und führt zur Vermischung der Begriffe. Man kann diese Funktion (oder Prozedur) auf verschiedene Weise gestalten. Man kann im Vordergrund (als Programmschleife) einfach eine Programmwiederholung zählen und wenn man weiss, wie lange sie dauert, eine Zeit daraus ableiten. Man könnte genauso gut, einen der Hardwaretimer zur Zeiterzeugung heranziehen. Man lädt ihn mit den nötigen Startwerten (z.B. für 1 sec) und schaltet ihn ein und wartet bis er fertig ist. Auch das könnte eine Funktion wait 1 machen. wait 1 ist also kein Befehl, der zu irgendeiner Programmiersprache gehört, sondern eine Funktion oder Prozedur, die selbst in der Programmiersprache geschrieben wurde und nur wie eine Anweisung benutzt werden kann.
topas
 
Beiträge: 3796
Registriert: 16.08.2010, 12:47

Re: Snake mit AVR

Beitragvon topas » 15.03.2013, 22:44

@Tim, weil Deine Anfrage so interessant war:
Gerade weil Funktionen (oder Prozeduren) durch ihren Namen aufgerufen werden und daher von den Anweisungen der Programmiersprache kaum zu unterscheiden sind, (das ist ihr Sinn - Erweiterung) kann man mit ihrer Hilfe sogar eine eigene Programmiersprache bauen: ich verweise auf Processing.
topas
 
Beiträge: 3796
Registriert: 16.08.2010, 12:47

Re: Snake mit AVR

Beitragvon Tim Sasdrich » 15.03.2013, 23:09

Ok, da habe ich wieder etwas dazu gelernt. Ich dachte immer das gehört fest dazu.
Ist ja auch nicht so leicht zu Unterscheiden.
"Der Kluge lernt aus allem und von jedem, der Normale aus seinen Erfahrungen und der Dumme weiß alles besser." - Sokrates (470 - 399 v. Chr.), griechischer Philosoph
Tim Sasdrich
 
Beiträge: 2961
Registriert: 07.01.2009, 14:15
Wohnort: Villingen-Schwenningen

Re: Snake mit AVR

Beitragvon topas » 15.03.2013, 23:25

So wie Dir Tim geht es bestimmt vielen, die mit Bascom oder ähnlichem gearbeitet haben. Euch kann ich nur raten: werft wenigstens einen Blick auf "C". Die Programmiersprache C hat alle anderen auf jeden Fall beeinflusst. Selbst mein kleines Basic.
Wer bei Basic bleiben will: http://www.mikroe.com/mikrobasic/avr/ ist eine Alternative.
Ich benutze dieses Basic, es gibt es für fast alle relevanten Prozessoren. Soll keine Werbung sein, ich bin halt von der Qualität überzeugt. Die Demoversion kann 4KByte Code erzeugen. Die Trennung zwischen Sprache und Bibliotheken geht klar hervor. Anschauen kostet ja nichts. :D
topas
 
Beiträge: 3796
Registriert: 16.08.2010, 12:47

Nächste

Zurück zu C

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast