2011-07-23 116 views
1

我在簡單的遊戲中扼殺自我C和我碰到一個非常簡單的問題,我沒有能夠谷歌答案。遊戲中移動敵人的簡單問題(C/SDL)

代碼如下,供其noobie可畏的事道歉(批評,不勝感激!):

#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

你的問題是由於四捨五入。

對於你的「夥計」,你正在使用一個SDL_Rect,它使用整數座標(如果我沒有記錯的話,可以使用short int)。

你將你的傢伙速度設置爲50,如果你的遊戲運行速度爲60fps(可能是因爲它的簡單性,如果vsync關閉,可能會更多),你會得到每幀的移動值0.83333。

此值將被截斷到int和結果將是零,例如,如果dude.x是10和按下右,計算出的值將是10.83和截斷時,這將導致10

左,它的工作原理,因爲該值向下取整,再假設dude.x是10,剩下的就是按下時,在第一次迭代計算的值將是9.17,截斷這會給你9

簡單,糟糕和黑客解決方案

增加AMOUNT_OF_PIXELS_TO_M OVE的值越高,迫使int增加,這將解決問題。

很好的解決

不使用SDL_Rect用於存儲你的角色位置,創建一個「MyRect」,並在其使用浮點值和描畫了該角色的時候不僅四捨五入。實際上,你只需要存儲字符位置,所以我將創建一個只有x和y的Point2D結構,並使用它來跟蹤字符位置。

+0

非常好的答案,非常感謝。但是,SDL_BlitSurface func只接受SDL_Rect。我會四處搜尋,看看我能否找到替代方案。 – plewh

+0

嗯,他已經編寫了解決方案。編寫一個函數(完全是lazyfoo.net第2課給出的函數),它將採用x/y位置,源和目標矩形的寬度和高度來創建這些矩形和邊界。然後當你真正做blitting傳遞上面給出的myRect類的float值。 – devsaw