Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Gorebase

Frischling

  • »Gorebase« ist der Autor dieses Themas

Beiträge: 3

Beruf: Administrator (langweilig^^)

  • Private Nachricht senden

1

03.06.2014, 17:54

[Gelöst] (C++/SFML 2.1) Übergabe Problem

Hallo Leute ich bin neu im Forum und starte gleich mal mit einer Frage :)

Folgendes:
Ich verwende C++ mit SFML 2.1
Ich habe mir ein eine "Sprites" Klasse gebaut die für mich Funktionen wie einen Sprite laden, Animationen handeln etc regelt.
Das funktioniert auch soweit.
Jetzt wollte ich das ganze so erweitern das ich die sprites in verschiedenen Layern rendern kann.
Dafür habe ich eine AddSprites Funktion gebaut die, die Sprites in einen std::Vector speichern soll.

Der Header sieht so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
class Sprites
{
public:
void Load(const string Filename);
etc... (Nicht von belang)

enum Layer { LayerOne, LayerTow };

private:
    void AddSprite(sf::Sprite sprite, Sprites::Layer layer);
    void Draw();

};


In der Sprites.cpp wird nach dem Include des Headers der Vector definiert.

C-/C++-Quelltext

1
2
#include "Sprites.hpp"
std::vector<Sprites> layer1, layer2;



Die AddSprites funktion ist ja private und wird nur von Render und AnimateRender Funktionen aufgerufen.
(In den Render funktionen wird nichts gedrawed zur Info^^)
Und zwar so:

C-/C++-Quelltext

1
AddSprite(sprite, LayerOne); //Oder halt LayerTow, LayerThree etc


AddSprites Funktion sieht so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Sprites::AddSprite(sf::Sprite sprite, Sprites::Layer layer)
{
    switch (layer)
    {
    case Sprites::Layer::LayerOne:
        layer1.push_back(sprite);
        break;
    case Sprites::Layer::LayerTow:
        layer2.push_back(sprite);
        break;
    }

    Draw();
}


Und die Draw so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
void Sprites::Draw()
{

    for (Sprites& sprite : layer1)
    {
        sprite.Draw();
    }
    for (Sprites& sprite : layer2)
    {
        sprite.Draw();
    }

}


Das Problem hierbei liegt in der Addsprites Funktion.
Ich erhalte folgenden Fehler:

(Link)




Ich hab jetzt ewigkeiten rumprobiert und mir fällt einfach nichts ein :(
Würde mich riesig freuen wenn mir jemand helfen könnte :)
Wenn ihr noch irgendwelche Informationen braucht sagt es einfach.

Danke euch^^

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Gorebase« (05.06.2014, 19:48)


Fawkes

Frischling

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

2

03.06.2014, 18:06

Dein Argument ist ein Sprite, du übergibst aber einen Vektor. Vielleicht hilft es wenn du vorher den Vektor in ein Sprite konvertierst oder als Argument einen Vektor einsetzt.

Edit: Mir fällt grad auf das du die Funtkion push_back benutzt. Diese nimmt als Argument einen Sprite und keinen Vektor. Vektor in einen Sprite konvertieren und dannach zurück in einen Vektor wenn du unbedingt die Vektoren brauchst. Du könntest auch versuchen es zu Casten ( Brechstangenmethode ).

Das ganze würde dann so aussehen:

C-/C++-Quelltext

1
layer1.push_back((sf::Sprite)sprite)

3

03.06.2014, 19:04

C-/C++-Quelltext

1
std::vector<Sprites> layer1

C-/C++-Quelltext

1
sf::Sprite sprite

C-/C++-Quelltext

1
layer1.push_back(sprite);


Fällt dir was auf? :)

Was ich auch nicht verstehe ist, was die Load(const string Filename) - Methode machen soll. Wenn sie ein einzelnes Sprite lädt, warum wird dieser nicht zurückgegeben? Wenn sie tatsächlich mehrere Sprites lädt, sollte sie auch entsprechend heißen: "LoadSprites" oder "LoadSpriteCollection", o.ä.
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

4

03.06.2014, 19:05

Ähm nein? @Fawked
Du könntest einen Konstruktor für Sprites definieren, der einen sf::Sprite nimmt. Dann einfach bla.push_back(Sprites(sprite, maybeSomeOtherParam));
Aber so ganz verstehe ich nicht, was du da komisches versuchst, vor allem die Vektoren machen mir Kopfschmerzen in Anbetracht dessen, wo sie deklariert wurden. Das Ziel ist klar, keine Sorge. Der Weg wirkt undurchsichtig und umständlich. Vielleicht macht die Tage ja jemand einen Wikiartikel... :)

MfG
Check

Gorebase

Frischling

  • »Gorebase« ist der Autor dieses Themas

Beiträge: 3

Beruf: Administrator (langweilig^^)

  • Private Nachricht senden

5

03.06.2014, 20:10

Also erstmal vielen vielen Dank euch das ihr mir helfen wollt :)

@Fawkes: Funktioniert so leider nicht :( selber fehler
@iSmokiieZz: Hmm.. du meinst weil ich versuch nen Sprite als Vector zurückzugeben?^^
@Checkmateing&iSmokiieZz: Ich weiß mein Quellcode ist bestimmt verwirrend^^ I
Ich sollte wohl erwähnen das ich mich erst seit einem Monat mit dem Programmieren befasse denn das letzte mal war vor ca. 10 Jahren im guten alten C :)
Ich denke es wird das beste sein wenn ich euch mal den gesamten Quellcode gebe. (Damit die zusammenhänge zumindestens ein bisschen klarer werden^^)
Ich wollte euch eigentlich nicht mit dem ganzen erschlagen^^

Zuerst mal der Header:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#pragma once

#include <iostream>
#include "Game.hpp"
#include <memory>

using namespace std;

class Sprites
{
public:
    Sprites();
    ~Sprites();

    void Load(const string Filename);
    void AnimateLoad(const string Filename, int FrameWidth, int FrameHeight);
    void Render(Game& Game, int Layer);
    void AnimateRender(int RowNumber, Game& Game, int FrameWidth, int FrameHeight, int AnimationSpeed);

    const string Filename;
    enum Layer { LayerOne, LayerTow};

private:
    void AddSprite(sf::Sprite sprite, Sprites::Layer layer);
    void Draw();

    sf::Texture texture;
    sf::Image image;  
    sf::Sprite sprite;
    
    sf::Clock clock;
    sf::Event SpriteEvent;
    sf::Time time;
    
    int FrameWidth;       
    int FrameHeight;      
};


Und dann die cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "Sprites.hpp"
sf::Vector2i source(0, 0);
std::vector<Sprites> layer1, layer2;


Sprites::Sprites()
{
    //Momentan leer
} 

Sprites::~Sprites()
{
    //Momentan leer
}


//Sprite laden - zb Level Background
void Sprites::Load(const string Filename)
{
image.loadFromFile(Filename.c_str());
texture.loadFromImage(image);
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, texture.getSize().x, texture.getSize().y));
}


// Animiertes Sprite laden - zb Player
void Sprites::AnimateLoad(const string Filename, int FrameWidth, int FrameHeight)
{
image.loadFromFile(Filename.c_str());
texture.loadFromImage(image);
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, FrameWidth, FrameHeight));
} 


// Sprite rendern - zb Level Background
void Sprites::Render(Game& Game)
{
        AddSprite(sprite, LayerOne);
} 


//Animiertes Sprite rendern - zb Player
void Sprites::AnimateRender(int RowNumber, Game& Game, int FrameWidth, int FrameHeight, int AnimationSpeed)
{
    source.y = RowNumber;

    time = clock.getElapsedTime();

    if (time.asMilliseconds() >= AnimationSpeed)
    {
        source.x++;
        if (source.x * FrameWidth >= texture.getSize().x)
            source.x = 0;
        clock.restart();
    }
    sprite.setTextureRect(sf::IntRect(source.x * FrameWidth, source.y * FrameHeight, FrameWidth, FrameHeight));
    
    AddSprite(sprite, LayerTow);
} 


//Sprites in Vector setzten
void Sprites::AddSprite(sf::Sprite sprite, Sprites::Layer layer)
{
    switch (layer)
    {
    case Sprites::Layer::LayerOne:
        layer1.push_back(sprite);
        break;
    case Sprites::Layer::LayerTow:
        layer2.push_back(sprite);
        break;
    }

    Draw();
}


//Sprite Vectoren drawen
void Sprites::Draw()
{
    for (Sprites& sprite : layer1)
    {
//Nur ein Stub
        std::cout << "Layer 1 wird gedrawed" << std::endl;
    }
    for (Sprites& sprite : layer2)
    {
//Nur ein Stub
        std::cout << "Layer 2 wird gedrawed" << std::endl;
    }
}


Ich hoffe ihr blickt durch mein Chaos und könnt mir weiterhelfen ;(

6

03.06.2014, 20:32

Jo du musst dir halt einfach eine Möglichkeit der Konvertierung von sf::Sprite zu Sprites machen. Konstruktor oder operator oder normale Funktion oder...
Also

C-/C++-Quelltext

1
2
3
4
5
6
7
class Sprites
{
public:
    A(const sf::Sprite& spr) : sprite(spr) {}

    const Sprites& operator=(const sf::Sprite& spr) { sprite = spr; }
};

Macht es denn Sinn einzelne sf::Sprites als Sprites-Objekte in einem Container zu haben?
Wir sind uns glücklicherweise einig, dass dein Stil veraltet ist. :P Neben dem fällt nämlich noch mehr auf, dass jedes Sprites eine sf::Texture und ein sf::Image hat. Warum?

MfG
Check

7

03.06.2014, 21:41

Ich verstehe nicht ganz, warum du die Klasse Sprites schachtelst. Warum ist sie dazu noch im Plural bezeichnet? Und auch die Korrellation zwischen Render() und Draw() sowie die Benennung von AddSprite machen dir im Grunde genommen nur das Leben schwer ;)

Ich glaube du solltest versuchen, deine Klasse Sprites zu teilen, in etwa:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Sprite
{    
public:
    enum ELayer { eSPRITELAYER_1, eSPRITELAYER_2 };

    LoadFromFile(...);
    SetLevel(Level lvl);
    Render();
    ...
private:
    sf::Sprite m_SFMLSprites;
    ELayer m_Level;
}

class SpriteManager
{
private:
    vector<Sprite> m_Sprites;
public:
    AddSpriteFromFile(...);
    AddSpriteFromScratch();
    AddExistingSprite(const Sprite& existingSprite, Sprite::ELevel lvl);
    void RenderAllSprites(...);   
 ...
};

SpriteManager::RenderAllSprites()
{
    for (auto itSprite = m_SFMLSprites.begin(); itSprite != m_SFMLSprites.end(); ++itSprite)
        itSprite->Render();
}
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Gorebase

Frischling

  • »Gorebase« ist der Autor dieses Themas

Beiträge: 3

Beruf: Administrator (langweilig^^)

  • Private Nachricht senden

8

05.06.2014, 19:47

Okay alsooooo nachdem die Konvertierung nun funktionierte, stand ich vor dem nächsten Problem.
Die gesamte Layer funktion hat einfach nichts gebracht :(
Nach reichlichen Nachdenken bin ich dann drauf gekommen das es so mit meiner Gamestruktur gar nicht funktionieren kann.
Lösen konnte ich das ganze dann auf eine ganz andere Methode.
(Draw Funktionen der einzelnen Inhalte also Player, Level etc einfach an verschiedenen Punkten aufrufen)

Aber trotzdem abschließend noch mal viel Dank an euch für die Hilfe :)

~kann geclosed werden~

Werbeanzeige