Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Snake - problem z rozjeżdżaniem się węża

Ostatnio zmodyfikowano 2012-02-27 06:38
Autor Wiadomość
programista12
Temat założony przez niniejszego użytkownika
Snake - problem z rozjeżdżaniem się węża
» 2012-02-26 20:04:18
Próbuję napisać snake'a w SDL. Udało mi się już zrobić dodawanie segmentów węża i poruszanie się. Jednak z poruszaniem się węża mam problem. Normalnie wąż chodzi prawidłowo, ale jeżeli szybko nacisnę np. strzałkę w górę i w lewo, to jego ciało się rozjeżdża - pierwszy i czasami drugi segment (od głowy licząc) idą prawidłowo, a reszta idzie w starym kierunku. Tu na forum wyczytałem, że to wina nadpisujących się eventów. Próbowałem zapamiętać wciśnięty klawisz, ale to nic nie dało. Może algorytm poruszania segmentami jest zły? Oto klasa węża:
C/C++
/*Snake.h*/
#pragma once
#include <vector>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_gfxPrimitives.h>
#include "timer.h"
#include "functions.h"

using namespace std;

enum DIRECTION { LEFT, RIGHT, UP, DOWN };

struct Segment
{
    int x, y;
    DIRECTION dir;
   
    Segment( int nx, int ny, DIRECTION ndir )
    {
        x = nx;
        y = ny;
        dir = ndir;
    }
    Segment() { }
    void Move( int speed )
    {
        if( dir == UP ) y -= 10;
       
        if( dir == DOWN ) y += 10;
       
        if( dir == LEFT ) x -= 10;
       
        if( dir == RIGHT ) x += 10;
       
    }
    void Show( SDL_Surface * dst )
    {
        boxRGBA( dst, x, y, x + 10, y + 10, 0, 255, 0, 255 );
    }
};

class Snake
{
private:
    int x, y, speed;
    vector < Segment > segments;
    DIRECTION dir;
    void SetUpSegments();
public:
    Snake();
    void HandleEvents( SDL_Event e );
    void Show( SDL_Surface * dst, TTF_Font * f );
    void Move( SDL_Surface * dst );
    void Eat();
    SDL_Rect GetRect();
};

C/C++
/*Snake.cpp*/
#include "Snake.h"


Snake::Snake()
{
    x = y = 450;
    speed = 150;
    dir = UP;
   
    segments.push_back( Segment( 450, 460, UP ) );
}

void Snake::HandleEvents( SDL_Event e )
{
    static SDLKey k;
    if( e.type == SDL_KEYDOWN )
    {
        if( e.key.keysym.sym == SDLK_LEFT && dir != RIGHT ) k = SDLK_LEFT;
       
        if( e.key.keysym.sym == SDLK_RIGHT && dir != LEFT ) k = SDLK_RIGHT;
       
        if( e.key.keysym.sym == SDLK_UP && dir != DOWN ) k = SDLK_UP;
       
        if( e.key.keysym.sym == SDLK_DOWN && dir != UP ) k = SDLK_DOWN;
       
        if( e.key.keysym.sym == SDLK_a ) speed++;
       
        if( e.key.keysym.sym == SDLK_z ) speed--;
       
    }
   
    if( k == SDLK_LEFT ) dir = LEFT;
    else if( k == SDLK_RIGHT ) dir = RIGHT;
    else if( k == SDLK_UP ) dir = UP;
    else if( k == SDLK_DOWN ) dir = DOWN;
    else return;
   
}

void Snake::Show( SDL_Surface * dst )
{
    boxRGBA( dst, x, y, x + 10, y + 10, 50, 128, 0, 255 );
    for( unsigned i = 0; i < segments.size(); i++ )
         segments[ i ].Show( dst );
   
}

void Snake::Move( SDL_Surface * dst )
{
    static Timer t;
    static bool a = false;
    if( !a )
    {
        t.start();
        a = true;
    }
   
    if( t.get_ticks() >= speed )
    {
        if( dir == LEFT ) x -= 10;
       
        if( dir == RIGHT ) x += 10;
       
        if( dir == UP ) y -= 10;
       
        if( dir == DOWN ) y += 10;
       
        for( unsigned i = 0; i < segments.size(); i++ )
             segments[ i ].Move( speed );
       
        SetUpSegments(); //próbowałem też używać tej metody przed ruchem segmentów, ale to nic nie dało
        t.start();
    }
}

void Snake::Eat()
{
    Segment s = segments.back();
    int nx, ny;
    DIRECTION ndir;
   
    //wąż idzie w górę
    if( dir == UP )
    {
        //ostatni element idzie w górę
        if( s.dir == UP )
        {
            nx = s.x;
            ny = s.y + 10;
            ndir = UP;
        }
       
        //ostatni element idzie w dół
        if( s.dir == DOWN )
        {
            nx = s.x;
            ny = s.y - 10;
            ndir = DOWN;
        }
       
        //ostatni element idzie w lewo
        if( s.dir == LEFT )
        {
            nx = s.x + 10;
            ny = s.y;
            ndir = LEFT;
        }
       
        //ostatni element idzie w prawo
        if( s.dir == RIGHT )
        {
            nx = s.x - 10;
            ny = s.y;
            ndir = RIGHT;
        }
    }
   
    //wąż idzie w dół
    if( dir == DOWN )
    {
        //ostatni element idzie w górę
        if( s.dir == UP )
        {
            nx = s.x;
            ny = s.y + 10;
            ndir = UP;
        }
       
        //ostatni element idzie w dół
        if( s.dir == DOWN )
        {
            nx = s.x;
            ny = s.y - 10;
            ndir = DOWN;
        }
       
        //ostatni element idzie w lewo
        if( s.dir == LEFT )
        {
            nx = s.x - 10;
            ny = s.y;
            ndir = LEFT;
        }
       
        //ostatni element idzie w prawo
        if( s.dir == RIGHT )
        {
            nx = s.x + 10;
            ny = s.y;
            ndir = RIGHT;
        }
    }
   
    //wąż idzie w lewo
    if( dir == LEFT )
    {
        //ostatni element idzie w górę
        if( s.dir == UP )
        {
            nx = s.x;
            ny = s.y + 10;
            ndir = UP;
        }
       
        //ostatni element idzie w dół
        if( s.dir == DOWN )
        {
            nx = s.x;
            ny = s.y - 10;
            ndir = UP;
        }
       
        //ostatni element idzie w lewo
        if( s.dir == LEFT )
        {
            nx = s.x + 10;
            ny = s.y;
            ndir = LEFT;
        }
       
        //ostatni element idzie w prawo
        if( s.dir == RIGHT )
        {
            nx = s.x - 10;
            ny = s.y;
            ndir = RIGHT;
        }
    }
   
    //wąż idzie w prawo
    if( dir == RIGHT )
    {
        //ostatni element idzie w górę
        if( s.dir == UP )
        {
            nx = s.x;
            ny = s.y + 10;
            ndir = UP;
        }
       
        //ostatni elemnet idzie w dół
        if( s.dir == DOWN )
        {
            nx = s.x;
            ny = s.y - 10;
            ndir = DOWN;
        }
       
        //ostatni element idzie w lewo
        if( s.dir == LEFT )
        {
            nx = s.x + 10;
            ny = s.y;
            ndir = LEFT;
        }
       
        //ostatni element idzie w prawo
        if( s.dir == RIGHT )
        {
            nx = s.x - 10;
            ny = s.y;
            ndir = RIGHT;
        }
       
    }
   
    segments.push_back( Segment( nx, ny, ndir ) );
}

void Snake::SetUpSegments()
{
    for( int i = 0; i < segments.size(); i++ )
    {
        if( i == 0 )
        {
            if( dir == UP || dir == DOWN )
            {
                if( segments[ i ].dir == LEFT || segments[ i ].dir == RIGHT )
                {
                    if( segments[ i ].x == x )
                         segments[ i ].dir = dir;
                   
                }
                else
                {
                    if( segments[ i ].y == y )
                         segments[ i ].dir = dir;
                   
                }
            }
           
            if( dir == LEFT || dir == RIGHT )
            {
                if( segments[ i ].dir == UP || segments[ i ].dir == DOWN )
                {
                    if( segments[ i ].y == y )
                         segments[ i ].dir = dir;
                   
                }
                else
                {
                    if( segments[ i ].x == x )
                         segments[ i ].dir = dir;
                   
                }
            }
        }
       
        else
        {
            if( segments[ i - 1 ].dir == UP || segments[ i - 1 ].dir == DOWN )
            {
                if( segments[ i ].dir == LEFT || segments[ i ].dir == RIGHT )
                {
                    if( segments[ i ].x == segments[ i - 1 ].x )
                         segments[ i ].dir = segments[ i - 1 ].dir;
                   
                }
                else
                {
                    if( segments[ i ].y == segments[ i - 1 ].y )
                         segments[ i ].dir = segments[ i - 1 ].dir;
                   
                }
            }
           
            if( segments[ i - 1 ].dir == LEFT || segments[ i - 1 ].dir == RIGHT )
            {
                if( segments[ i ].dir == UP || segments[ i ].dir == DOWN )
                {
                    if( segments[ i ].y == segments[ i - 1 ].y )
                         segments[ i ].dir = segments[ i - 1 ].dir;
                   
                }
                else
                {
                    if( segments[ i ].x == segments[ i - 1 ].x )
                         segments[ i ].dir = segments[ i - 1 ].dir;
                   
                }
            }
        }
    }
}

SDL_Rect Snake::GetRect()
{
    SDL_Rect r;
    r.x = x;
    r.y = y;
    r.w = r.h = 10;
    return r;
}
Z góry dzięki za pomoc.
P-51483
RazzorFlame
» 2012-02-26 20:41:52
emm nie wiem czy to zadziala ale zmien na Uint8 * keystate = SDL_GetKeyState( NULL );
i pózniej uzywaj tego:
C/C++
if( keystate[ SDLK_ < klawisz > ] ) //...
Zreszta tak jest w kursie
P-51486
programista12
Temat założony przez niniejszego użytkownika
» 2012-02-27 06:38:37
Niestety, nie działa.
P-51495
« 1 »
  Strona 1 z 1