2016-05-16 5 views
1

私はSDL2を掘り下げようとしています。これまで私は以下の簡単なプログラムを作りました。それは画面に長方形をレンダリングし、色を急に変えさせるだけです。新しい色の各レンダリングの間に2番目の遅延が生じる原因は何ですか?

game.h

#include<SDL2/SDL.h> 
#include<stdbool.h> 
typedef struct Game { 
bool finished; 
SDL_Event curevent; 
SDL_Window* mainwin; 
SDL_Renderer* mainren; 
}Game; 

Game *initGame(); 
void destoryGame(Game*); 
void drawRect(Game*); 
void handleEvents(Game*); 

game.c

#include<SDL2/SDL.h> 
#include<malloc.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include<time.h> 

#include"game.h" 

Game *initGame() { 
    Game *game = NULL; 
    if(SDL_Init(SDL_INIT_VIDEO) < 0) { 
     fprintf(stderr,"Error: %s",SDL_GetError()); 
    } else { 
     game = malloc(sizeof(Game)); 
     game->finished = false; 
     game->mainwin = SDL_CreateWindow("Main Window", 
             SDL_WINDOWPOS_UNDEFINED, 
             SDL_WINDOWPOS_UNDEFINED, 
             800, 640, 
             SDL_WINDOW_RESIZABLE); 
     if(game->mainwin == NULL) { 
      fprintf(stderr,"Error: %s",SDL_GetError()); 
     } else { 
      game->mainren = SDL_CreateRenderer(game->mainwin, -1, 
               SDL_RENDERER_ACCELERATED); 
      if(game->mainren == NULL) { 
       fprintf(stderr,"Error: %s",SDL_GetError()); 
      } else { 
       SDL_SetRenderDrawColor(game->mainren,0,0,0,0xFF); 
       SDL_RenderClear(game->mainren); 
      } 
     } 
    } 
    return game; 
} 

void destoryGame(Game *game) { 
    free(game); 
    SDL_Quit(); 
    printf("Exiting ...\n"); 
} 

void handleEvents(Game *game) { 

    while(SDL_PollEvent(&(game->curevent)) != 0) { 
     if(game->curevent.type == SDL_QUIT) { 
      game->finished = true; 
     } 
    } 
} 

void drawRect(Game *game) { 
    int r, b, g, h, w; 
    srand(time(NULL)); 
    r = rand() % 0xFF + 1; 
    b = rand() % 0xFF + 1; 
    g = rand() % 0xFF + 1; 
    SDL_GetWindowSize(game->mainwin,&h,&w); 
    SDL_Rect rect = {h/4,w/4,h/2,h/2}; 
    SDL_SetRenderDrawColor(game->mainren,r,b,g,0xFF); 
    SDL_RenderFillRect(game->mainren, &rect); 
    SDL_RenderPresent(game->mainren); 
} 

main.cの

#include"game.h" 
int main() { 
    Game* game = initGame(); 
    do { 
     handleEvents(game); 
     drawRect(game); 
    } while((game->finished != true)); 
    destoryGame(game); 
    return 0; 
} 

私は、Linuxシステム上でです。 Ubuntu 16.04。そしてコンパイルしています:

SRC_FILES = ./src/main.c ./src/game.c 
CC_FLAGS = -Wall -Wextra -Os -g -lSDL2 -std=gnu11 
CC = gcc 

all: 
    ${CC} ${SRC_FILES} -o game ${CC_FLAGS} 

このプログラムは問題なくコンパイルされ実行されます。各新色間の秒の遅延があり、なぜ私が疑問に思って

http://imgur.com/U5B6hB0

:アウトプットは次のようになりますか?

直感は、ループが繰り返されるたびに新しい色があることを教えてくれます。それは何百回もあるはずです。この遅延を引き起こしている何

https://youtu.be/AjbrmfjJRk0?t=6m3s

:たぶん、このような何かを探していますか?あるいは、コードに関する何かを理解できないのですが、コードを正確に実行する必要がありますか?

+0

関数: 'srand()'はプログラムの実行全体に対して一度だけ呼び出されるべきであり、いくつかの乱数が必要とされるたびに呼び出されるべきではありません。 'main()'の最初のコード行に 'srand()'を呼び出すようにしてください。 – user3629249

答えて

3

擬似乱数ジェネレータは、前の値の計算を使用して予測可能な数値シーケンスを生成します。

簡単な例:もちろん

int lastValue; 

int rand(void) { 
    lastValue = (lastValue * 13)/7; 
    return lastValue; 
} 

rand()の実際の実装はより複雑です。

前の番号がない場合は、デフォルトを使用する必要があります。また、デフォルトが常に同じ場合(たとえば、プログラムを開始するときは常にゼロ)、すべてのプログラムに対して常に同じシーケンスが生成されます。

これを修正するには、「最初の前の番号」またはシード番号を設定することができます。これはsrand()が対象です。今

...

あなたは四角形を描画srand()たびに使用して、現在時刻からのシード値を取得しています。現在の時間が変更されない場合、シードは同じであるため、数字のシーケンスは前回と同じです。

現在の時刻は1秒に1回変化します。

+0

Wow。これを理解し、それを私に説明してくれたお二人のおかげです。これは非常に目が開いていた。 – Lavos

3

drawRectでsrand()を呼び出して乱数ジェネレータを再配置しています。新しいシードとして戻り値time()を指定しています。これは、エポックの開始からの経過時間を秒単位で報告するため、毎秒1回しか変化しません。次に、rand()と呼んで、長方形の色のランダムなRGB値を取得します。

戻り値がtime()のRNGを再配分するため、メイン関数がdrawRect()と頻繁に呼び出されていても、ほぼ毎秒新しいランダムな色しか表示されません。 rand()はあなたに別の「ランダムな」値を与えるはずだと思うかもしれませんが、これはほとんどのRNGが動作する方法ではありません。それらの多くは、与えられたシード値に対して予測可能な数列を与えるため、「疑似乱数発生器」という用語が使用されます。これは実際にテスト容易性の面で利点があります。

srand()へのコールを削除するか、またはdrawRect()の外に移動すると(メインゲームループの外側にあることが望ましい)、色の変更が頻繁に行われるはずです。

+0

うわー。これを理解し、それを私に説明してくれたお二人のおかげです。これは非常に目が開いていた。 – Lavos

+0

C言語のよくある質問http://c-faq.com/lib/srand.htmlからの説明です – Ryan

関連する問題