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

[C++, SFML1.6] Wprowadzanie obiektów w ruch

Ostatnio zmodyfikowano 2013-02-12 17:52
Autor Wiadomość
crash
Temat założony przez niniejszego użytkownika
[C++, SFML1.6] Wprowadzanie obiektów w ruch
» 2013-01-28 17:08:00
edit: Przepraszam za nieprawidłowy dział, mało snu, dużo monitora :x

Przeczytałem kurs DejaVu@ odnośnie wprowadzania obiektów w ruch i przystąpiłem do pisania zmodyfikowanej wersji, w której zamiast sf::Shape przemieszczam obiekt swojej klasy. Klasa ta zawiera prywatnie sf::Image oraz Sprite, który wczytywany jest z Image, a Image z pliku png.

Obiekt za pomocą kilku metod reaguje na strzałki, tylko kurka zostaje po nim ślad w starym miejscu. Jako że nie wysiliłem się i nie skopiowałem kodu DejaVu, nie widziałem efektu jak on działa w praktyce, ale coś mi mówi, że... obiekt się odrysowuje a w starym miejscu nie ma po nim śladu.

Nie lubię kopiuj-wklej, za to wszelkie próby i modyfikacje jak najbardziej, dlatego cudaczę. W ostateczności skopiuję cały kod i skompiluję, póki co chcę pokombinować po swojemu.

Wymyśliłem takie coś, że do pamięci jako mapa piksli byłby kopiowany fragment ekranu odpowiednio większy od sprajta po to, że gdy się sprajta przemieści w którymś z czterech kierunków, to wtedy byłoby odmalowanie części danej ekranu, gdzie był on przed chwilą. Jestem święcie przekonany, że to droga naokoło.

W kodzie znajduje się nieco zbędnych rzeczy, na które proszę nie zwracać uwagi - to forma pewnych wskazówek dla mnie.

Plik main.cpp:
C/C++
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

#include <iostream>

#include "hero.hpp"

using namespace std;
using namespace sf;

int main()
{
    RenderWindow RW( VideoMode( 800, 600, 32 ), "SFML test" );
   
    RW.Clear( Color( 0, 255, 0 ) );
    //RW.UseVerticalSync(true);
   
    HeroesVector Heroes;
   
    Hero MainHero(( string ) "Main",( string ) "./k1.png" ),
    Hero2(( string ) "Evil",( string ) "./k2.png", 700, 500 ); /*
    /*
        MainHero.SetOutsidePossibility(false);
        Hero2   .SetOutsidePossibility(false);
   
   
        Heroes.push_back(MainHero);
        Heroes.push_back(Hero2);
   
        HeroesVector :: iterator  HVi;
   
        for (HVi = Heroes.begin();  HVi != Heroes.end();  HVi++)
        {
             HVi->NewLocation();
             RW.Draw(HVi->GetSprite());
        }
    */
   
    while( RW.IsOpened() )
    {
        Event Ev;
       
        while( RW.GetEvent( Ev ) )
        {
            if( Ev.Type == Event::KeyPressed && Ev.Key.Code == 256 ) return 0;
           
            if( Ev.Type == Event::KeyPressed )
            {
                if( Ev.Key.Code == sf::Key::Down ) MainHero.Down( 10 );
               
                if( Ev.Key.Code == sf::Key::Up ) MainHero.Up( 10 );
               
                if( Ev.Key.Code == sf::Key::Left ) MainHero.Left( 10 );
               
                if( Ev.Key.Code == sf::Key::Right ) MainHero.Right( 10 );
               
                MainHero.RefreshLocation(); // Hero::Sprite.SetLocation(x,y)
                RW.Draw( MainHero.GetSprite() );
            }
        }
       
        RW.Display();
    }
}

Plik Hero.hpp
C/C++
#ifndef HERO_HPP_INCLUDED
#define HERO_HPP_INCLUDED

using namespace std;
using namespace sf;

class Hero
{
    string name;
    Image image;
    Sprite sprite;
   
    int x, y, speed, xmove, ymove;
    bool CanBeOutside; // if sprite can be outside a rendered window
   
    Hero(); //must be private!
   
public:
    Hero( string name, string path, int x = 0, int y = 0 );
    void SetOutsidePossibility( bool IsPossible );
    void SetSpeed( int NewSpeed );
    void MoveTo( int newx, int newy );
    void Up( int pos );
    void Down( int pos );
    void Left( int pos );
    void Right( int pos );
    void RefreshLocation();
    Sprite & GetSprite();
};

typedef vector < Hero > HeroesVector;

#endif // HERO_HPP_INCLUDED

Plik Hero.cpp
C/C++
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Image.hpp>

//#include <SFML/Window.hpp>

#include <iostream>
#include <vector>

#include "hero.hpp"

using namespace std;
using namespace sf;

Hero::Hero()
{ //private
}

Hero::Hero( string name, string path, int x, int y ) //loads sprite to mem
    : name( name )
    , x( x )
    , y( y )
{
    image.LoadFromFile( path );
    sprite.SetImage( image );
    sprite.SetPosition( x, y );
   
    speed = 1;
    CanBeOutside = false;
}

void Hero::SetOutsidePossibility( bool IsPossible )
{
    CanBeOutside = IsPossible;
}

void Hero::SetSpeed( int NewSpeed )
{
    speed = NewSpeed;
}

void Hero::MoveTo( int newx, int newy )
{
    x = newx;
    y = newy;
}

void Hero::Up( int pos )
{
    y -= pos;
    if( y < 0 ) y = 0;
   
}

void Hero::Down( int pos )
{
    y += pos;
    if( y > 600 ) y = 600;
   
}

void Hero::Left( int pos )
{
    x -= pos;
    if( x < 0 ) x = 0;
   
}

void Hero::Right( int pos )
{
    x += pos;
    if( x > 800 ) x = 800;
   
}

void Hero::RefreshLocation()
{
    sprite.SetPosition( x, y );
}

Sprite & Hero::GetSprite()
{
    return sprite;
}

typedef vector < Hero > HeroesVector;

Jakie macie sugestie poza skopiowaniem i skompilowaniem kodu DejaVu :D ?
P-75236
SeaMonster131
» 2013-01-28 17:19:26
Jako że nie wysiliłem się i nie skopiowałem kodu DejaVu, [...]
Nie lubię kopiuj-wklej, za to wszelkie próby i modyfikacje jak najbardziej, dlatego cudaczę.
Taką postawę lubię i pochwalam! :)

A co do problemu - pewnie nie czyścisz ekranu w pętli gry, a powinieneś.

// edit:
» Kurs SFML 1.6, C++Okno renderujące grafikę lekcja
P-75238
crash
Temat założony przez niniejszego użytkownika
» 2013-01-28 18:00:41
Jesteś wielki FireMonster@ ! Pomogło. Zaraz przed:

C/C++
//main.cpp

RW.Draw( MainHero.GetSprite() );

Zapodałem
RW.Clear( Color( 0, 255, 0 ) );
 i działa jak człowiek. Najlepsze są najprostsze rozwiązania...

Odnośnie jeszcze mam małe pytanie początkującego.

W moim przypadku scena jest zielona i jest tylko jeden sprajt. Jak rozumiem gdy sprajtów będzie więcej, będą przeszkody, nie wiem - chmurki, cokolwiek, to w pętli należy je odrysowywać wszystkie. A czy rozwiązanie polegające na kopiowaniu niewielkich wycinków ekranu i własnoręcznym odświeżaniu tylko tych fragmentów, które się zmieniają gdy reszta sceny "stoi" w miejscu, jest dobrą techniką? Wydaje mi się, że nie i wiem, że przekonałbym się po prostu to pisząc, nie mniej wolę zapytać o opinię ;)
P-75244
RazzorFlame
» 2013-01-29 18:55:05
BTW. On ma nick SeaMonster131
O co ci chodzi... Chcesz żeby po sprajcie zostawał taki ślad który daje efekt przyspieszenia czy cos? Tak jak w grze Exit Path?
P-75329
crash
Temat założony przez niniejszego użytkownika
» 2013-01-29 23:52:16
Widzę, jaki ma nick.

RazzorShame@ chcę maksymalnej prędkości gry dla wielu małych nieustannie animowanych naraz sprite'ów, stąd takie dywagacje z pominięciem odświeżania całego ekranu. Podsunąłeś mi ciekawą myśl, którą spróbuję zaimplementować w swoim czasie.

PS: apropos Twojego postu o funkcje trygonometryczne z innego tematu, mój nauczyciel trylion lat temu w liceum rzekł taki oto wierszyk:

"W pierwszej ćwiartce wszystkie funkcje są dodatnie,
w drugiej tylko sinus.
W trzeciej tangens i cotangens,
a w czwartej cosinus".

Miał, cholera, rację :D Pierwsza ćw. to ta, gdzie (x++,y++), druga gdzie (x++,y--), trzecia (x--, y--), czwarta (x--, y++). Dobrze znać tę własność wymienionych funkcji.
P-75353
RazzorFlame
» 2013-01-30 20:09:58
Hmm, coś mi mówi że sf::View może zdziałać to co ty chcesz. Nie za bardzo się przyglądałem temu ale chyba można mieć wiele "view'ów" i na każdym coś wyświetlać :P

EDIT:
I JAKI RAZZORSHAME! XD troche mnie to irytuje jak zmieniasz nazwy nicków :P

EDIT:
I moje "coś mi mówisie" dobrze radziło. Klasa sf::RenderTarget (którą dziedziczy sf::RenderWindow) posiada metodę SetView. Chyba tym coś zdziałasz o ile sie nie myle :P
P-75408
crash
Temat założony przez niniejszego użytkownika
» 2013-02-01 18:23:50
Kupiłem dwa zeszyty, jeden na notatki co mi ślina przeleje na klawiaturę, a drugi na spis metod klas z dokumentacji, żeby szybciej ogarnąć w zeszycie niż w trylionie zakładek. Tak więc nauka SFML ostro.

Poczytam o klasach, które wspomniałeś. Pewnie znów wyjdzie na to, że kod konstruowałem naokoło, wymyślając koło na nowo, sprowadzając go dodatkowo do kwadratury :) Dziękuję za uwagi Razzor@

offtop mode on:

Idę przez życie z humorem kompletnie bez spiny, czego m.in wyrazem jest zmiana nicków i to nie tylko na tym forum ;) Luzuj chłopak, ciesz się, żem nie troll, hehe
P-75546
RazzorFlame
» 2013-02-12 17:52:43
Skoro nie zamkneleś tematu, to pozwole sobie zacytować twoją wypowiedź:
chcę maksymalnej prędkości gry dla wielu małych nieustannie animowanych naraz sprite'ów
Otóż może nie wiesz, ale ja spotkałem się z takim choby błędem. Nie jest to błąd w kodzie czy coś, ale przez nieumiejętność pisania, zauważyłem że wiele osób pisze lub pisało (np. ja) w taki sposób że do każdego obiektu jest dodawany obiekt sf::Image - BŁĄD! - Pomyśl sobie że jako obiekt chcesz żeby był jakiś kafelek w map edytorze, czy co tam. W grze zapewne nie będzie do 50 kafelków, mało co się spotyka kilka tysięcy kafelków, a średnio kilkadziesiąt/kilkaset tysięcy kafelków (w bardziej rozbudowanych grach). Pomyśl sobie ile czasu zajmie wczytanie kilkudziesięciu/kilkuset tysięcy kafelków (a raczej ich obrazków) do bufora sf::Image! Otóż można to załatwić bardzo łatwo. Jako że sf::Sprite zawiera tylko wskaźnik (czyli sam adres) pixeli z sf::Image które sie podaje w "SetImage" zajmuje on bardzo bardzo mało. Tak więc można spokojnie zrobić tak:
C/C++
class Creature
{
public:
    sf::Sprite mSprite;
    int x, y, w, h;
    string name;
    void LoadFromImage( sf::Image & );
};

class Hero
    : public Creature
{
public:
    InventorySlot invSlots[ 8 ]; //przykladowa ilosc
};

class Monster
    : public Creature
{
public:
    std::vector < string > odglosy;
    void wydajOdglos();
};
Jak widzisz w każdym jest tylko sf::Sprite, a reszta jest nie potrzebna :)
P-76199
« 1 »
  Strona 1 z 1