2015-05-16 1 views
1

Я создаю игру на C на микропроцессоре. Оценка контролируется тем, как долго вы можете выжить; счет увеличивается на 1 раз в 3 секунды. Счет представляет собой целое число, которое объявляется глобально, но отображается из функции.Увеличение целого числа за раз задержка

int score = 0;//globally declared 

void draw_score(int score_d) 
{ 
    char score_draw[99]; 
    sprintf(score_draw,"%d", score_d); 
    draw_string(score_draw, 9, 0); 
} 

Я думал о функции, которая просто увеличивает счет на один с опозданием на него, однако, что не работал.

void score_increaser(int score) 
{ 
    score++; 
    _delay_ms(3000); 
} 

Нужно ли находиться в замкнутом цикле? сама по себе функция в любом случае будет входить в цикл while.

ответ

2

C проходит по значению.

score_increaser(), как показано в вашем вопросе увеличивается только копировальной, что передается в

Чтобы исправить это есть (в основном) два варианта:.

  1. Как score определен во всем мире, не проходят ни в чем:

    void score_increaser(void) { 
        score++; 
        _delay_ms(3000); 
    } 
    

    Это modifes в Globale score напрямую.

  2. Pass в адрес score и разыменовываются его внутри функции

    void score_increaser(int * pscore) { 
        (*pscore)++; 
        _delay_ms(3000); 
    } 
    

    Называйте это как этот

    ... 
    score_increaser(&score); 
    ... 
    

3-я, немного более сложный, подход (который предполагает, что сигналы поддерживаются на целевой платформе) будет

  1. настройте сигнал и обработчик ссылок, затем
  2. настроить таймер для подачи сигнала каждые N секунд.
  3. Этот сигнал затем обрабатывается обработчиком, который, в свою очередь
  4. увеличивает глобальную score и
  5. запускает таймер снова.

Это может выглядеть следующим образом:

#include <signal.h> /* for signal() and sig_atomic_t */ 
#include <unistd.h> /* for alarm() */ 


#define DURATION (3) /* Increase score every 3 seconds. */ 

sig_atomic_t score = 0; 


void set_alarm(unsigned); 

void handler_alarm(int sig) 
{ 
    ++score; 
    set_alarm(DURATION); 
} 

void set_alarm(unsigned duration) 
{ 
    signal(SIGALRM, handler_alarm); 
    alarm(duration); 
} 


int main(void) 
{ 
    set_alarm(DURATION); 

    ... /* The game's codes here. */ 
} 

Этот последний подход имеет то преимущество, что код вашей игры не нужно заботиться об увеличении score. score увеличивается только каждые 3 секунды, пока программа работает.

+0

Хороший ответ, но Wouldn 't '#include ' ограничивать использование этого только на платформах Unix? – WedaPashi

+0

@WedaPashi: «unistd.h» может быть легко заменен любым другим заголовком, предоставляющим прототип для 'alarm()'. То же самое относится к сигнальным материалам. – alk

+0

Несмотря на сложность, это решение будет работать лучше всего в долгосрочной перспективе и быть совместимым с другими работающими функциями. Спасибо. – James

1

score глобальное значение, то не нужно передать его в функцию, если эта функция имеет доступ к этому глобальному пространству

void score_increaser() { 
score++; 
_delay_ms(3000); 
} 
2

Я бы рекомендовал использовать прерывание таймера. Настройте таймер на 3 секунды.

volatile int score = 0; //global 

void Intr_Init(peripheral_t per) 
{ 
    //Initialize the timer interrupt 
} 

void draw_score(int score_d) 
{ 
    char score_draw[99]; 
    sprintf(score_draw,"%d", score_d); 
    draw_string(score_draw, 9, 0); 
} 

int main(void) 
{ 
    Intr_Init(TIMER); 
    while(1) 
    { 
     //Code that makes your game run 
     draw_score(score); 
    } 
} 

ISR (TIMER1_COMPA_vect) 
{ 
    //clear disable interrupt 
    score++; 
    //enable interrupt 
} 

Во встроенной памяти вы должны полагаться на таймеры для достижения более точных критических задач и точности. Способ реализации Delay обычно представляет собой цикл или счетчик вверх/вниз. В то время как таймер обычно основан на подсчете SysTicks. Другим важным преимуществом прерываний является то, что вы позволяете процессору выполнять свои задачи все время, а не блокировать его в цикле задержки.

1

Вам не нужно параметр для очков, так как он объявлен во всем мире ..

//global 
int score = 0; 

void score_increaser() 
{ 
    _delay_ms(3000); 
    score++; 
} 

призвание как: score_increaser(); должен делать работу .. я предлагаю вам проверить score в любой другой линии/функции .. может быть, вы его повторно объявлен или случайно изменил значение ..

надеюсь, что это помогло ..

+0

, чтобы работать, требуется упреждающая ОС. для проекта «голый металл» это не очень хорошая идея. – user3629249

1

здесь хороший метод для обработки счет.

в функции 'начать игру',

clear 'score' to 0 
setup a timer: 
--to expire once each 3 seconds 
--enable the automatic reload feature, 
--enable the timer interrupt 
--enable the timer counter 

в функции обработчика прерываний таймера

--increment 'score' 
--clear the timer interrupt pending flag 

в 'конец игры' функция

disable the timer counter 
disable the timer interrupt 
display the 'score' value