2011-07-23 24 views
1

私は単純なゲームでハッキングしてCを教えてしまいます。私はGoogleに答えが得られていないという怒りを伴って簡単な問題に立ち向かいました。 。コードは以下のシンプルな問題(C/SDL)

、そのnoobie terriblenessための謝罪は(批判は感謝!):

#include <stdio.h> 
#include <stdlib.h> 
#include <SDL/SDL.h> 

#define AMOUNT_OF_ENEMIES 10 
#define AMOUNT_OF_PIXELS_TO_MOVE 50.0 

struct enemy 
{ 
    int alive; 
    SDL_Rect rect; 
}; 

void create_enemy(struct enemy *position) 
{ 
// Take a pointer to an array. Iterate through array looking for any 'dead' instances. 
// (Re)initialise when found, ignore entirely if array is full of alive instances. 

int j = 0; 
while(position[j].alive == 1 && j < AMOUNT_OF_ENEMIES) 
{ 
    ++j; 
} 

if(position[j].alive == 0) 
{ 
    position[j].alive = 1; 
    position[j].rect.y = 0; 
} 
} 

void update_enemies(struct enemy *position) 
{ 
// Iterate through a passed array looking for alive instances. If found increment  vertical position, 
// unless instance is at bottom of screen in which case it's marked as dead. 

int j = 0; 
while(j < AMOUNT_OF_ENEMIES) 
{ 
    if(position[j].alive == 1) 
    { 
     position[j].rect.y += 1; 
     if(position[j].rect.y > 570) 
     { 
      position[j].alive = 0; 
      } 
     } 
     ++j; 
    } 
} 

int main(void) 
{ 
// INITS ********************************************************************* 
int k; 
int current_time = 0; 
int previous_time = 0; 
float difference_in_time = 0.0; 

// Load SDL library 
if(SDL_Init(SDL_INIT_EVERYTHING) != 0) 
{ 
    printf("Problem, yo\n"); 
    return 1; 
} 

// Setup event queue 
SDL_Event event; 

// Create array to store enemys, initialise it 
struct enemy *enemy_array = malloc(sizeof(struct enemy) * AMOUNT_OF_ENEMIES); 
int j; 
for(j = 0; j < AMOUNT_OF_ENEMIES; ++j) 
{ 
    enemy_array[j].alive = 0; 
    enemy_array[j].rect.x = 150; 
    enemy_array[j].rect.y = 0; 
} 

// Create an array to flag keypresses, initialise it 
int pressed_keys[323]; 
int l; 
for(l = 0; l < 323; ++l) 
{ 
    pressed_keys[l] = 0; 
} 

// Create surfaces 
SDL_Surface *screen = SDL_SetVideoMode(300, 600, 0, SDL_HWSURFACE); 
int black = SDL_MapRGB(screen->format, 0, 0, 0); 

SDL_Surface *tower = SDL_LoadBMP("tower.bmp"); 
SDL_Rect tower_rect; 
tower_rect.x = 50; 
tower_rect.y = 0; 
tower_rect.w = 200; 
tower_rect.h = 600; 

SDL_Surface *dude = SDL_LoadBMP("dude.bmp"); 
float dude_x = 0.0; 
SDL_Rect dude_rect; 
dude_rect.x = 120; 
dude_rect.y = 500; 
dude_rect.w = 60; 
dude_rect.h = 100; 

SDL_Surface *enemy = SDL_LoadBMP("enemy.bmp"); 

// GAME LOOP ***************************************************************** 
while(1) 
{ 
    current_time = SDL_GetTicks(); 
    difference_in_time = (float)(current_time - previous_time)/1000; 
    previous_time = current_time; 

    if(SDL_PollEvent(&event)) 
    { 
     if(event.key.keysym.sym == SDLK_DOWN) 
     { 
      create_enemy(enemy_array); 
     } 
     else 
     { 
      switch(event.type) 
      { 
       case SDL_QUIT: 
        printf("NOOOOOO\n"); 
        SDL_FreeSurface(screen); 
        SDL_FreeSurface(tower); 
        SDL_FreeSurface(enemy); 
        free(enemy_array); 
        SDL_Quit(); 
       return 0; 

       case SDL_KEYDOWN: 
        pressed_keys[event.key.keysym.sym] = 1; 
        break; 

       case SDL_KEYUP: 
        pressed_keys[event.key.keysym.sym] = 0; 
        break; 
      } 
     } 
    } 

    if(pressed_keys[SDLK_LEFT] && dude_rect.x > 50) 
    { 
     dude_rect.x -= (AMOUNT_OF_PIXELS_TO_MOVE * difference_in_time); 
    } 

    if(pressed_keys[SDLK_RIGHT] && dude_rect.x < 190) 
    { 
     dude_rect.x += (AMOUNT_OF_PIXELS_TO_MOVE * difference_in_time); 
    } 

    update_enemies(enemy_array); 

    SDL_FillRect(screen, NULL, black); 
    SDL_BlitSurface(tower, NULL, screen, &tower_rect); 
    for(k = 0; k < AMOUNT_OF_ENEMIES; ++k) 
    { 
     if(enemy_array[k].alive == 1) 
     { 
      SDL_BlitSurface(enemy, NULL, screen, &enemy_array[k].rect); 
     } 
    } 
    SDL_BlitSurface(dude, NULL, screen, &dude_rect); 
    SDL_Flip(screen); 
} 
return 0; 
} 

問題は、この部分で発生する:正しく左へ

if(pressed_keys[SDLK_LEFT] && dude_rect.x > 50) 
{ 
    dude_rect.x -= (AMOUNT_OF_PIXELS_TO_MOVE * difference_in_time); 
} 

if(pressed_keys[SDLK_RIGHT] && dude_rect.x < 190) 
{ 
    dude_rect.x += (AMOUNT_OF_PIXELS_TO_MOVE * difference_in_time); 
} 

'男' オブジェクトが移動し、右矢印キーを押すと何も起こりません。

printfを追加すると、if文が正しく実行されていることがわかります。 difference_in_timeを削除すると動作します。そのため、その変数またはその操作とAMOUNT_OF_PIXELS_TO_MOVEで行う操作のどちらかです。

私の人生では、前者のブロックが正しく実行され、後者(本質的には同じもの)がなぜ正しく動作しないのか理解できません。私はそれが私が見落としているシンプルなものだと確信していますが、私はそれを見つけることを狂っているつもりです。

答えて

4

問題は四捨五入によるものです。

"dude"には、整数座標(私が正しいと思いますと短いint)を使用するSDL_Rectを使用しています。

あなたの仲間のスピードを50に設定しました。ゲームが60fpsで実行されている場合(おそらくシンプルさがあり、vsyncがオフの場合よりもはるかに多いかもしれません)、各フレームの移動値は0.83333になります。 dude.xが10であり、あなたは、計算値は10.83になり、右を押すと切り捨てられたときに、これは10

につながる場合

、例えば、この値はint型に切り捨てられます、結果はゼロになります左の場合

は、値が切り捨てされているので、それは動作しますが、再びdude.xと仮定すると、これはあなたに9

を与える切り捨て、左が押されたときに、最初の反復で計算された値は9.17になり、10でありますシンプル、不良、ハックソリューション

AMOUNT_OF_PIXELS_TO_M OVEを増やして高い値にすると、問題が解決されます。

良い解決策は

は「MyRect」を作成し、あなたの文字の位置を格納するためSDL_Rectを使用して、それにfloat値を使用して文字を描画するときにのみ、丸めんません。実際には、文字の位置を格納するだけで済むので、xとyだけでPoint2D構造体を作成し、これを使用して文字の位置を追跡します。

+0

優秀な回答、ありがとうございます。ただし、SDL_BlitSurface関数はSDL_Rectを受け入れます。私は周りを検索し、私は代替を見つけることができます参照してください。 – plewh

+0

まあ、彼は解決策を書いています。ソースと宛先の矩形のx/yの位置、幅、高さを取る関数(正確にlazyfoo.netレッスン2で与えられた関数)を記述すると、これらの矩形が作成され、blitだけが作成されます。次に、blitを実際に実行すると、上記のmyRectクラスからfloat値が渡されます。 – devsaw