2017-04-23 1 views
0

Ich lerne gerade, mein erstes Spiel zu entwickeln, und ich habe SDL2 als Spiel-Engine gewählt. Ich kann die Animation für das Hauptcharakter-Sprite separat machen. Allerdings dachte ich, dass es lächerlich langwierig wäre, das Sprite so zu steuern. Also habe ich das Sprite-Blatt in ein zweidimensionales Array geladen, in der Hoffnung, dass ich das Sprite mit allen möglichen Aktionen mit nur einem Sprite Sheet steuern könnte.Sprite mit 2-dimensionalem Array steuern SDL2

#define HOR_FRAMES 16 
#define VER_FRAMES 16 


    // These are for the images and sprites 
    Sprite catGif; 
    SDL_Rect catRect[VER_FRAMES][HOR_FRAMES]; 

    bool load() 
    { 
    bool success = true; 
    // Load cat sprite sheets 
    if (!catGif.loadFromFile("./assets/pets/fighter_cat_sprite/cat_sprite_base_64.png", 
          sceneRenderer, 0X00, 0x00, 0x00)) 
    { 
     printf("%s", SDL_GetError()); 
     success = false; 
    } 
    else 
    { 
     int initX = 0; 
     int initY = 0; 
     for (int ver = 0; ver < VER_FRAMES; ver++) 
     { 

      for (int hor = 0; hor < HOR_FRAMES; hor++) 
      { 
       catRect[ver][hor].x = initX; 
       catRect[ver][hor].y = initY; 
       catRect[ver][hor].w = 64; 
       catRect[ver][hor].h = 64; 
       initX += 64; 
      } 
      initX = 0; 
      initY += 64; 
     } 
     initX = 0; 
     initY = 0; 
    } 
    return success; 
    } 

Dann habe ich eine einfache ENUM die Aktionen zu definieren, die die Zeilen in der Sprite-Blatt ist

enum Actions{ 
    IDLE, 
    WALK, 
    TOTAL 
}; 

Danach werden in main(), füge ich die Steuerlogik und stellen die Variablen In weg, dass ich passend zum Rendern denke.

#include "init.h" 
#include "Sprite.h" 

LTexture background(SCREEN_WIDTH, SCREEN_HEIGHT); 
SDL_Rect bgRect; 

LTexture foreground(SCREEN_WIDTH, SCREEN_HEIGHT); 
SDL_Rect fgRect; 

int frame = 0; 
int maxFrame = 0; 
SDL_RendererFlip flipType; 
int main(int argc, char* argv[]) 
{ 
    init(); 
    load(); 

    int action; 

    bool quitFlag = false; 
    SDL_Event event; 

    while (!quitFlag) 
    { 
     action = IDLE; 
     while (SDL_PollEvent(&event) != 0) // Handle events in queue 
     { 
      if (event.type == SDL_QUIT || 
       event.key.keysym.sym == SDLK_ESCAPE) 
       quitFlag = true; 
     } 

     const Uint8* states = SDL_GetKeyboardState(NULL); 

     if (states[SDL_SCANCODE_A]) 
     { 
      maxFrame = 8; 
      action = WALK; 
      flipType = SDL_FLIP_HORIZONTAL; 
      catGif.moveLeft(); 
     } 
     else if (states[SDL_SCANCODE_D]) 
     { 
      maxFrame = 8; 
      action = WALK; 
      flipType = SDL_FLIP_NONE; 
      catGif.moveRight(); 
     } 
     else 
     { 
      maxFrame = 4; 
      action = IDLE; 
     } 

     // Drawing 
     background.clipRender(0, 0, sceneRenderer, &bgRect); 
     foreground.clipRender(0, SCREEN_HEIGHT/2, sceneRenderer, &fgRect); 

     SDL_Rect* currFrame = &catRect[action][frame/maxFrame]; 
     int x = catGif.xGetter(); 
     int y = catGif.yGetter(); 

     catGif.render(x, y, sceneRenderer, currFrame, NULL, 0, flipType); 

     // Update 
     SDL_RenderPresent(sceneRenderer); 

     frame++; 
     if (frame/maxFrame == maxFrame) 
     { 
      frame = 0; 
     } 
    } 

    clean(); 

    return 0; 
} 

Das Sprite spielte reibungslos, als ich die A/D-Tasten drückte. Nachdem ich die Knöpfe losgelassen habe, traten Probleme auf, das Sprite Sheet fuhr fort, sich bis zum Ende durchzuspielen und dann verschwand das Sprite, obwohl die Variable "action" gesetzt wurde und es keine Möglichkeit gibt, dass sie sich selbst erhöhen kann. Da bin ich ziemlich sicher. Bitte helfen Sie mir zu verstehen, wie das passiert ist, hoffentlich kann ich versuchen, es zu beheben oder einen anderen Ansatz zu nehmen. Vielen Dank. Ich benutze code :: blocks 16.01 auf Fedora Linux. Und das ist das Sprite-Blatt: cat_sprite_sheet

Antwort

0

Sie frame zu 0 zurückgesetzt müssen, wenn die Animation Zustand zu ändern.

{ 
    maxFrame = ...; 
    frame = 0; 
    ... 
} 

Der Fehler ist es wegen == Prüfung in Ihrem Rahmen Schritt. Wenn frame40 ist und Sie A/D freigeben, wird maxFrame auf 4 zurückgesetzt. frame/maxFrame = 40/4 = 10 > 4, so wird es nie gleich maxFrame sein, und frame hält immer für immer an, damit Ihr Sprite verschwindet, wenn [frame/maxFrame] aus dem Bunde geht. Reset frame auf 0 wird dies lösen.

+0

Vielen Dank für Ihre Antwort, ich werde das versuchen und Ihnen das Ergebnis sagen. – CutTheCode

+0

Ich konzentrierte mich auf den Bug, den Sie darauf hingewiesen, und dann habe ich ein Bool-Flag hinzugefügt, um die Zustände des Sprites anzuzeigen, dann die Logik hinzugefügt, um die Frame-Variable zurückzusetzen, und es hat funktioniert, vielen Dank! – CutTheCode