Avatar billede bjarke Nybegynder
09. september 1999 - 09:17 Der er 2 kommentarer og
1 løsning

"Sprites" og gentegning

På 64'eren kunne man lave sprites og flytte dem rundt. Så vidt jeg ved findes der ikke noget tilsvarende i C/C++, men hvordan kan man så selv lave det - eller findes der headerfiler/class librarys eller hvad ved jeg, som implementerer mulighed for at designe sprites og funktioner for gentegning af skærm?

Det skal være til C/C++ (ikke Builder) og jeg kan ikke programmere ASM! (men er det svært at lære hvis man kan C/C++?)
Avatar billede soepro Nybegynder
09. september 1999 - 13:46 #1
Jeg har selv kodet sprites på min C64, så jeg ved godt hvad du mener. Jeg har en ide med en ny klasse, som du definerer ca. sådan her:

class sprite
{
  public:
    sprite(int orgx, int orgy, char* newimage = NULL, char visible = 0);
    void setimage(char *newimage);
    char* getimage(void);
    void show(void);
    void hide(void);
    int getx(void);
    int gety(void);
    int setx(int newx);
    int sety(int newy);
    int moveto(int newx, int newy);
  protected:
    void    draw(void);
    int      curx, cury;
    char  imageDefined, imageVisible;
    char  *image;
};

Du skal selvfølgelig så selv tegne dine sprites på skærmen og hente spriten ind vha. getimage som ligger i <graphics.h>. (Eksempel findes i on-line vejledningen til TC.) Derefter kan du danne din sprite ved at lave en variabel f.eks. sprite Musen(10, 10, HentetSprite);

Ved kun at tillade ændring af sprites x/y position via såkaldte "setters", kan du få disse til at fjerne den gamle tegning, og tegne den et andet sted (Jeg antager at hver sprite er 32*32 pixels i 256 farver som på C64):

void sprite::moveto(int newx, int newy)
{
  if (!imageDefined)
    return;

  // Remove old image, move koordinates and redraw.
  draw();
  x = newx; y = newy;
  draw();
}

hvor

void sprite::draw(void)
{
  if (imageVisible)
    putimage(x, y, x+32, y+32, image, XOR_PUT);
}

Du kan så "tænde" og slukke ved at kalde show & hide:

void sprite::show(void)
{
  imageVisible = 1;
  show();
}

void sprite::hide(void)
{
  imageVisible = 0;
  show();
}

Hvis du så skal styre en hel skærm med flere sprites og lave "collisions detect" som vi havde på C64, kan du jo bare lave en nye klasse:

class spritescreen
{
  public:
      spritescreen(int nbrObjects);
      int addsprite(int x, int y, char* image, char visible);
      int showsprite(int nbr);
      int hidesprite(int nbr);
      int movesprite(int newx, int newy);
      int collission(void);
  private:
      int      nbrObjects, nbrInUse;
      char    collisionDetect;
      sprite *objects;
      void    draw(void);
      void    checkcollision(void);
}

spritescreen::spritescreen(int nbrSprites)
{
  // Noget der checker/stopper hvis vi allerede er i grafik mode.
  objects = (sprite *)malloc(nbrSprites * sizeof(*objects));
  for (int idx = 0; idx < nbrSprites; idx++)
    objects[idx] = NULL;
  nbrObjects = nbrSprites;
  nbrInUse = 0;
  collisionDetect = 0;
}

int spritescreen::addsprite(int newx, int newy, char* image, char visible)
{
  if (nbrInUse < nbrObjects)
  {
    object[++nbrInUse] = new sprite(newx, newy, image, visible);
    return 1;
  }
  else
    return 0;
}

int spritescreen::collision(void)
{
  return collisionDetect;
}

void spritescreen::checkcollision(void)
{
  for (int idx = 0; idx < nbrInUse; idx++)
    for (int idy = 0; idy < idx; idy++)
        if (object[idy].getx() >= object[idx].getx()
        && object[idy].getx() <= object[idx].getx()+32
        && object[idy].gety() >= object[idx].gety()
        && object[idy].gety() <= object[idx].gety()+32
        ||  object[idy].getx()+32 <= object[idx].getx()
        && object[idy].getx()+32 <= object[idx].getx()+32
        && object[idy].gety()+32 >= object[idx].gety()
        && object[idy].gety()+32 <= object[idx].gety()+32)
        { // Øverste venstre hjørne eller nederste højre hjørne
          // indenfor venstre hjørne og nederste højre hjørne på anden sprite.
          collisionDetect = 1;
          idx        = idy = nbrInuse; // Afbryd begge loops.
      }
      else
          collisionDetect = 0;
}

void spritescreen::draw(void)
{
  for (int idx = 0; idx < nbrInUse)
    objects[idx].draw();
}

void spritescreen::movesprite(int nbr, int newx, newy)
{
  if (nbr < nbrInUse)
  objects[nbr].moveto(newx, newy);
  checkcollision();
}

ooops - det lod jeg mig vist rive med. Du kan sikkert komme videre herfra - ellers må du jo sige til.
Avatar billede bjarke Nybegynder
09. september 1999 - 15:35 #2
Fedt nok, at du gider at gøre så meget ud af det. Desværre har jeg ikke tid til at kigge på det lige nu, så du må vente lidt med at få dine eventuelle points.

I øvrigt har jeg aldrig programmeret C64, men min bror har.

Du nævner 256 farver, men det kan man jo netop ikke med VGA-driveren (jvf. mit andet spørgsmål om grafikdriver/-modes).
Avatar billede bjarke Nybegynder
12. september 1999 - 09:12 #3
soepro >> Tak skal du have. Jeg er ikke kommet i gang med at lave klassen, men så vidt jeg har kigget på det du har lavet, så ser det meget lovende ud (og jeg har jo erfaret fra andre spørgsmål at du ved hvad du taler om), så du får hermed pointene:-)

Men lige 2 ting:
1)  Er du gammel c-programmør siden du bruger malloc() i stedet for alloc()?
2)  Hvis nu mine "sprites" er runde, så "crasher" de stadig i øverste venstre hjørne og nederste højre uden de egentlig visuelt rammer hinanden ikke? + at noget baggrund bliver dækket af "ingenting" (var det også sådan på C64'eren?)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester