Проблема с анимацией?

Прямо сейчас, когда я запускаю свою игру, которую делаю на C++, я иду влево вправо вверх или вниз.. Но персонаж просто скользит, это не похоже на то, что он идет.. И у меня все картинки уже загружены в мою игру, и они работают. , Но я не знаю, как бы я это решил .. Я не могу понять, как изменить изображение, когда вы удерживаете кнопку ..

Это кстати аллегро..

Вот мой код для проигрывателя рисунков:

void Player::Draw(BITMAP *Buffer){
    draw_sprite(Buffer, Oskar[picNumber], x, y);
}

Oskar[] - это имя массива со всеми картинками..

Вот что меняет картинку персонажа при нажатии на кнопки:

void Player::Controls(){

if(key[KEY_RIGHT]){
    velocityX = speed;
    picNumber = 6;
}

else if(key [KEY_LEFT]){
    velocityX = -speed;
    picNumber = 9;
}

else{
    velocityX = 0;
}

if(key [KEY_UP]){
    velocityY = -speed;
    picNumber = 3;
}
else if(key [KEY_DOWN]){
    velocityY = speed;
    picNumber = 0;
}
else{
    velocityY = 0;
}

x += velocityX;
y += velocityY;
}

Все дело в переменной, которую я создал picNumber. Все изображения, которые у меня есть, находятся в массиве, а picNumber представляет собой изображение, которое нужно нарисовать. Было бы неплохо получить некоторую помощь в этом. Я думал об этом весь день ..

РЕДАКТИРОВАТЬ

#include "Player.h"
#include "Global.h"
#include <allegro.h>


Player::Player(){

}


Player::~Player(){

}

void Player::Init(){
        x = 10;
        y = 10;
        velocityX = 0;
        velocityY = 0;
        speed = 1;
        picNumber = x % MAXPICS;

        OskarFront[0] = load_bitmap("Character\\OskarFront.bmp", NULL);
        OskarFront[1] = load_bitmap("Character\\OskarStanding.bmp", NULL);
        OskarFront[2] = load_bitmap("Character\\OskarFront2.bmp", NULL);

        OskarBack[0] = load_bitmap("Character\\OskarBack.bmp", NULL);
        OskarBack[1] = load_bitmap("Character\\OskarStandingBack.bmp", NULL);
        OskarBack[2] = load_bitmap("Character\\OskarBack2.bmp", NULL);

        OskarRight[0] = load_bitmap("Character\\Oskar1.bmp", NULL);
        OskarRight[1] = load_bitmap("Character\\Oskar.bmp", NULL);
        OskarRight[2] = load_bitmap("Character\\Oskar2.bmp", NULL);

        OskarLeft[0] = load_bitmap("Character\\OskarLeft.bmp", NULL);
        OskarLeft[1] = load_bitmap("Character\\OskarLeftStand.bmp", NULL);
        OskarLeft[2] = load_bitmap("Character\\OskarLeft2.bmp", NULL);
}

void Player::Update(){
        Player::Controls();
}

void Player::Draw(BITMAP *Buffer){

        if(walkingRight == true){
                draw_sprite(Buffer, OskarRight[picNumber], x, y);
        }

        else if(walkingLeft == true){
                draw_sprite(Buffer, OskarLeft[picNumber], x, y);
        }

        else if(walkingFront == true){
                draw_sprite(Buffer, OskarFront[picNumber], x, y);
        }

        else if(walkingBack == true){
                draw_sprite(Buffer, OskarBack[picNumber], x, y);
        }

        else{
                draw_sprite(Buffer, OskarFront[1], x, y);
        }
}

void Player::Controls(){

        if(key[KEY_RIGHT]){
                velocityX = speed;
                walkingRight = true;
        }

        else if(key [KEY_LEFT]){
                velocityX = -speed;
                walkingLeft = true;
        }

        else{
                walkingRight = false;
                walkingLeft = false;
                velocityX = 0;
        }

        if(key [KEY_UP]){
                velocityY = -speed;
                walkingFront = true;
        }
        else if(key [KEY_DOWN]){
                velocityY = speed;
                walkingBack = true;
        }
        else{
                velocityY = 0;
                walkingFront = false;
                walkingBack = false;
        }

        x += velocityX;
        y += velocityY;
}

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


person Rakso    schedule 23.08.2011    source источник


Ответы (3)


У вас есть только один индекс для каждого направления движения!

Предполагая, что вы нарисовали около 3 (левая нога вперед, перекрытие, правая нога вперед), вам нужно будет увеличивать индекс со временем или движением по мере продвижения марша.

Интересно, как далеко продвинулось Allegro — десять лет назад это была в основном графика DOS (я использовал ее с DJGPP) и была заметка от автора, живущего в лондонской квартире. Как сурово я думал, только теперь я вижу, как далеко мы, провинциалы, от лондонских цен.

В ответ на ваш комментарий попробуйте что-то вроде:

#define MAXPICS 3
BITMAP *OskarWalksLeft[MAXPICS];
BITMAP *OskarWalksRight[MAXPICS];
picNumber = x % MAXPICS;
if (facingLeft) {
    draw_sprite(Buffer, OskarWalksLeft[picNumber], x, y);
} else //facingRight
    draw_sprite(Buffer, OskarWalksRight[picNumber], x, y);

или если вам не нужен новый кадр на пиксель, но каждые 3 или около того, попробуйте заменить

picNumber = x % MAXPICS;

с

picNumber = (x / 3)  % MAXPICS;

Я попытался немного привести в порядок ваш код и придумал это, у меня нет аллегро, поэтому я не смог его проверить:

#include "Player.h"
#include "Global.h"
#include <allegro.h>

Player::Player(){}

Player::~Player(){}

enum playerDir {left, right, front, back, stationary} direction;
BITMAP *Oskar[stationary][3];

void Player::Init(){
    x = 10;
    y = 10;
    velocityX = 0;
    velocityY = 0;
    speed = 1;
    picNumber = x % MAXPICS;

    char filename[256];
    const char *dirStrs[] = {"left","right","front","back"};
    for (playerDir i = left; i < stationary; (int)i = (int)i + 1)
        for (j = 0; j < 3; ++j) {
            strcpy(filename, "Character\\Oskar");
            strcat(filename, dirStrs[i]);
            strcat(filename, itoa(j));
            strcat(filename, ".bmp");
            Oskar[i][j] = load_bitmap(filename, NULL);
        }
}

void Player::Update(){Player::Controls();}
void Player::Draw(BITMAP *Buffer){
    switch (direction) {
        case left :
                draw_sprite(Buffer, OskarLeft[picNumber], x, y);
                break;
        case right :
                draw_sprite(Buffer, OskarRight[picNumber], x, y);
                break;
        case front :
                draw_sprite(Buffer, OskarFront[picNumber], x, y);
                break;
        case back :
                draw_sprite(Buffer, OskarBack[picNumber], x, y);
                break;
        default:
                draw_sprite(Buffer, OskarFront[1], x, y);
        }
}

void Player::Controls(){
    direction = stationary;
    if(key[KEY_RIGHT]){
        velocityX = speed;
        direction = right;
    } else if(key [KEY_LEFT]){
        velocityX = -speed;
        direction = left;
    } else velocityX = 0;

    if(key [KEY_UP]){
        velocityY = -speed;
        direction = front;
    } else if(key [KEY_DOWN]){
        velocityY = speed;
        direction = back;
    } else velocityY = 0;

    x += velocityX;
    y += velocityY;
 }
person John    schedule 23.08.2011
comment
И все изображения находятся в одном массиве, поэтому мне в основном нужно знать, как заставить его переключаться между этими 2 или 3 изображениями и не выходить за предел, потому что тогда это будет изображение, когда он, возможно, идет в другом направлении. - person Rakso; 23.08.2011
comment
Не стесняйтесь расширять решение для движения вверх и вниз, но похоже, что вам действительно нужно начать с самого начала. - person John; 23.08.2011
comment
я начал изучать С++ две недели назад. Но мне все равно, сейчас я учу С++ трудным путем: D - person Rakso; 23.08.2011
comment
Компилятор — ваш друг, научитесь интерпретировать сообщения об ошибках, и он заткнется. - person John; 23.08.2011
comment
Это не было сообщение об ошибке, просто я не смог найти хорошего решения для создания анимации без использования листов спрайтов.. :) - person Rakso; 23.08.2011

Кажется, вы не делаете никакой анимации. Кажется, вы просто устанавливаете определенный кадр на основе клавиши направления, которую нажимает пользователь. Вам нужна функция, которая делает что-то вроде этого:

void Player::updateFrame(float time_delta)
{
    time_to_next_frame -= time_delta;
    while (time_to_next_frame <= 0.0f)
    {
        nextFrame();
        time_to_next_frame += time_per_frame;
    }
}

Назовите его каждый кадр, передав ему количество времени, прошедшее с момента последнего кадра.

person Benjamin Lindley    schedule 23.08.2011
comment
У меня есть 3 изображения, как сказал Джон Сильвер ниже. может он идет в другом направлении.. - person Rakso; 23.08.2011
comment
@ Бен, зачем использовать таймеры? Он будет выглядеть как луноход, когда стоит на месте, слишком много над головой. - person John; 23.08.2011
comment
@John: Ваш комментарий не имеет смысла. Вы не видели определение функции nextFrame(). Предположительно, объект игрока должен знать, стоит ли он на месте, и функция nextFrame может учесть это, не изменяя кадр. А без таймеров анимация будет зависеть от частоты кадров. Так что это будет выглядеть по-разному в зависимости от настроения компьютера. - person Benjamin Lindley; 23.08.2011
comment
Хорошо, вам нужны таймеры для gfx-библиотек без событий. Я забыл, что так долго жил на земле .NET. Качели и карусели, однако, я не думаю, что мы можем использовать слишком много функциональности в остальной части кода. - person John; 23.08.2011

В ответ на ваши комментарии к двум другим ответам вы, кажется, не знаете, как не перейти к определенному значению.

Для этого (например, вам нужно что-то в диапазоне [0, 2] + c, где c — некоторая константа, определяющая начало вашего индекса. Например, вы можете сделать следующее:

void Player::nextFrame( int startIndex /* Changes based on your direction */) {
      static unsigned short iIndex = 0;

      // Increment and map value to the range [0, 2]
      ++iIndex;
      iIndex %= 3;


      // Note: this assumes that picNumber is a member function, else you
      // will have to pass it by reference to this function.
      picNumber = iIndex + startIndex;
}

Это должно делать то, что вы хотите (т.е. в зависимости от направления, в котором вы меняете начальный индекс, а затем он увеличивается, сопоставляя значение с диапазоном [0, 2].

Надеюсь это поможет!

person Thomas Russell    schedule 23.08.2011