1710

ok pour l'asm grin
avatar

1711

aze (./1705) :
Tu remplaces tes objets globaux par des pointeurs globaux et tu alloues les objets toi même une fois rentré dans le main.

Pas mal, je n'y avais pas pensé, ça me semble le plur propre !
Link (./1706) :
Vu que même en entourant le constructeur lui-même d'un try/catch (oui, c'est possible)

Ben oué que c'est possible, on m'a l'avais très très fortement conseillé et même recommandé, image à l'appui (j'ai relu tout le topic ya 3 jours grin)

1712

Folco (./1712) :
Pas mal, je n'y avais pas pensé, ça me semble le plur propre !

En java t'es obligé de faire ça. J'ai jamais eu tes problématiques moi grin

1713

Une bonne solution aussi c'est si possible de les créer localement et les passer plus loin à ceux qui en ont besoin, ça permet de mieux contrôler qui dépend de quoi. Sinon, songer à un singleton.
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

1714

Brunni (./1713) :
Une bonne solution aussi c'est si possible de les créer localement et les passer plus loin à ceux qui en ont besoin, ça permet de mieux contrôler qui dépend de quoi.

Ca m'emmerde de trimballer 3 ou 4 pointeurs pour des conneries, genre un pointeur de souris, une structure d'évènement, l'adresse de la fenêtre principale...

Pour le singleton, ça consiste à créer (par exemple dans main) un objet de classe X (no comment embarrassed), et à faire hériter toutes les classes de cette classe X ?

1715

Non non, le singleton c’est une variable globale (c’est mal !) enveloppée dans un objet (c’est bien !).
C’est un bon moyen de se donner bonne conscience quoi smile
Enfin, tout ça c’est globalement des trucs qui compliquent la maintenance et l’évolution des programmes, donc à éviter si possible. Pourquoi as-tu tant besoin de variables globales ?
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

1716

Pour l'adresse de l'écran (en terme TI grin) créé par SDL par exemple. Beaucoup plus simple de l'avoir en global que de la passer ici et là.

Sinon, c'est fun l'héritage multiple et le polymorphisme, ça permet des conceptions super élégantes love Je tenais à le dire cheeky

1717

Link (./1706) :
Vu que même en entourant le constructeur lui-même d'un try/catch (oui, c'est possible)

Ben oué que c'est possible, on m'a l'avais très très fortement conseillé et même recommandé, image à l'appui (j'ai relu tout le topic ya 3 jours grin)
[/cite]
Recommandé? Je ne vois pas qui ferait une chose pareille, vu que:
1. C'est un "faux" catch de toute façon
2. J'adhère au principe de ne gérer manuellement qu'une seule ressource par classe.
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

1718

non L’héritage multiple du C++ est tout sauf élégant sad

Sinon une solution pas trop contraignante pour éviter d’avoir à trimballer trop de paramètres à tes fonctions graphiques, c’est de les regrouper dans une structure que tu pourrais appeler un contexte graphique.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

1719

Folco (./1716) :
Pour l'adresse de l'écran (en terme TI biggrin.gif ) créé par SDL par exemple.
Euh, mes souvenirs sont lointains, mais il me semble que tu es censer locker/délocker l'écran à chaque frame, et ne pas conserver le pointeur d'une frame à l'autre.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

1720

Link (./1717) :
1. C'est un "faux" catch de toute façon

A l'époque, je ne parlais pas de variables globales.
Sasume (./1718) :
non.gif L’héritage multiple du C++ est tout sauf élégant frown.gif

Pardon, je parle d'interface en fait, héritage de fonctions virtuelles pures réimplémentées de manière spécialisée par les classes héritières.
Moi j'aime bien. smile
Sasume (./1718) :
Sinon une solution pas trop contraignante pour éviter d’avoir à trimballer trop de paramètres à tes fonctions graphiques, c’est de les regrouper dans une structure que tu pourrais appeler un contexte graphique.

J'ai regroupé ce genre de choses dans un objet dédié, comme me l'avait suggéré Pen^2.


Question maintenant. J'ai un écrit une classe toute bête me permettant de regrouper mes objets à dessiner dans une liste par exemple, ce qui permet d'appeler dans une boucle toutes leurs fonctions de dessin, que chacun réimplémente à sa façon :class Drawable { public: Drawable (bool enabled = true); void drawEnable (); void drawDisable (); void drawToggle (); bool isDrawable (); virtual void draw () = 0; private: bool m_Enabled; };
Comme vous le voyez, une variable est prévue, permettant de désactiver l'affichage d'un objet. Je veux que sa fonction draw() voit ça et n'affiche pas son objet.
Comment faire pour éviter que chaque objet interroge sa partie Drawable pour savoir s'il doit se dessiner ? Pas que ce soit chiant à écrire (if (isDrawable()){....}), mais j'ai juste peur, dans l'implémentation d'un objet, d'oublier cette condition.

Je voudrais que ce soit transparent pour l'objet, en clair qu'il ne se dessine pas, même lorsqu'il essaye, si il a été désactivé, mais sans procéder à cette vérification lui-même.

Il y a un moyen ?


cross -> Zerosquare -> Je comprends pas trop le coup des (un)LockSurface de la SDL, sachant qu'on ne peut rien écrire dans la surface quand elle est lockée. De toute façon, s'il bouge cette surface en mémoire, je ne vois pas comment la retrouver, je n'ai qu'un pointeur comme info sur la-dite surface.

1721

Globale ou non, le catch est faux quand même. Si je veux mettre un try quelque part, je le met autour de instanciation de l'objet (et peut-être son utilisation), ou à l'intérieur du constructeur, au moins là je sais l'exception ne sera pas relancée sans mon ordre.
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

1722

Link (./1721) :
Globale ou non, le catch est faux quand même. Si je veux mettre un try quelque part, je le met autour de instanciation de l'objet (et peut-être son utilisation), ou à l'intérieur du constructeur, au moins là je sais l'exception ne sera pas relancée sans mon ordre.

Ah ben je suis d'accord, j'avais mal compris.

1723

Folco (./1720) :
Je comprends pas trop le coup des (un)LockSurface de la SDL, sachant qu'on ne peut rien écrire dans la surface quand elle est lockée. De toute façon, s'il bouge cette surface en mémoire, je ne vois pas comment la retrouver, je n'ai qu'un pointeur comme info sur la-dite surface
À moins que ce soit inversé par rapport à DirectDraw, il me semble que c'est le contraire : le pointeur n'est garanti valide que quand elle est lockée, justement. Faudrait que je vérifie ça...
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

1724

Folco (./1720) :
Question maintenant. J'ai un écrit une classe toute bête me permettant de regrouper mes objets à dessiner dans une liste par exemple, ce qui permet d'appeler dans une boucle toutes leurs fonctions de dessin, que chacun réimplémente à sa façon :class Drawable { public: Drawable (bool enabled = true); void drawEnable (); void drawDisable (); void drawToggle (); bool isDrawable (); virtual void draw () = 0; private: bool m_Enabled; };
Comme vous le voyez, une variable est prévue, permettant de désactiver l'affichage d'un objet. Je veux que sa fonction draw() voit ça et n'affiche pas son objet.
Comment faire pour éviter que chaque objet interroge sa partie Drawable pour savoir s'il doit se dessiner ? Pas que ce soit chiant à écrire (if (isDrawable()){....}), mais j'ai juste peur, dans l'implémentation d'un objet, d'oublier cette condition.

Je voudrais que ce soit transparent pour l'objet, en clair qu'il ne se dessine pas, même lorsqu'il essaye, si il a été désactivé, mais sans procéder à cette vérification lui-même.
Il y a un moyen ?

Tu as au moins deux méthodes:
Celle que je préfère: La méthode draw dessine toujours le truc quoi qu'il arrive, mais cette méthode n'est pas appelée si l'objet n'est pas visible (c'est ta boucle de dessin qui fait cette vérification, donc tu économises des appels de fonction en prime, et la vérification de visibilité ne se fait qu'à un seul endroit)
Une autre méthode que j'aime bien mais que je n'appliquerais pas ici:
Tu déclares ta méthode draw() non virtuelle, et une méthode "drawImpl()" (par exemple) virtuelle.protected: virtual void drawImpl() = 0; public: void draw() { if (isDrawable()) drawImpl(); }
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1725

Pas mal, j'avais pas pensé à la fonction intermédiaire.

Mais pourquoi tu ne l'utiliserais pas ici ? L'autre méthode marche certainement, mais si j'ai plusieurs boucles d'affichage, suivant l'endroit où je suis dans mon programme, je peux toujours l'oublier.
L'avantage de ta seconde méthode est que c'est codé en dur dans la classe, c'est inratable ! Elle me tente bien cette solution.

1726

Parce que ta méthode s'appelle draw, et pas drawIfEnabled tongue
D'ailleurs "isDrawable" dans une classe qui s'appelle "Drawable" ça devrait toujours retourner true cheeky ("isVisible" ou "isDrawingEnabled" serait à mon sens plus correct)
Et pourquoi ne pas encapsuler ta boucle de dessin dans une autre classe si tu peux en avoir besoin à plusieurs endroits ? (Pour l'instant ça me semble un peu douteux déjà, mais supposons tongue) nt count; }Par exemple class DrawList { /* …bla bla bla… */ public: void execute() { for (i = 0; i < count; i++) if (drawables[i]->isDrawable()) drawables[i]->draw(); } private: Drawable* drawables; i
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1727

Je note tes remarques pertinentes. La remise au C++ est lente et douloureuse, mon cerveau panic quand je cherche à appeler une méthode en f-line et à ne pas reloger une lecture de membre, donc oué, ya des incohérences un peu partout grin

1728

Folco, vérification faite, c'est bien le cas :
(http://www.libsdl.org/docs/html/sdllocksurface.html)
SDL_LockSurface
(...)
SDL_LockSurface sets up a surface for directly accessing the pixels. Between calls to SDL_LockSurface and SDL_UnlockSurface, you can write to and read from surface->pixels, using the pixel format stored in surface->format. Once you are done accessing the surface, you should use SDL_UnlockSurface to release it.
Not all surfaces require locking. If SDL_MUSTLOCK(surface) evaluates to 0, then you can read and write to the surface at any time, and the pixel format of the surface will not change.

Et la doc de DirectDraw dit pareil :
(http://msdn.microsoft.com/en-us/library/aa918512.aspx)
IDirectDrawSurface::Lock
(...) This method obtains a pointer to the surface memory.

Je pense que sur certains matériels, le pointeur renvoyé peut changer d'un appel à l'autre de LockSurface().
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

1729

GoldenCrystal (./1724) :
Une autre méthode que j'aime bien mais que je n'appliquerais pas ici:
Tu déclares ta méthode draw() non virtuelle, et une méthode "drawImpl()" (par exemple) virtuelle.protected: virtual void drawImpl() = 0; public: void draw() { if (isDrawable()) drawImpl(); }
Ce pattern porte un nom : Template Method smile
Je pense que c’est ce qui le plus adapté ici.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

1730

C'est ce que j'ai implémenté en tout cas. grin

1731

Une autre question, pour être sur de mes billes.
J'ai deux classes A et B, A est abstraite :
class A
{
    public:
        void func_classique ();
        virtual void pure_virtual_func () = 0;
};

class B
{
    public:
        void pure_virtual_func ();
};

On a donc B qui implémente "pure_virtual_func" (ok, à ce moment-là, elle n'est plus purement virtuelle au niveau de B cheeky)
func_classique est implémentée par A, elle n'est pas virtuelle et donc pas redéfinie.

Est-ce que A::func_classique peut utiliser pure_virtual_func ?

Ca compile ©, le mécanisme pour trouver la bonne fonction pure_virtual_func à l'exécution sera mis en place, c'est bien ça le principe ?

1732

oui.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

1733

Cool et merci !

1734

SAUF si tu appelles func_classique() dans le constructeur de A.
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

1735

Ah bien vu, parce qu'à cette étape, le type de l'objet qui instancie n'est pas connaissable, donc la fonction virtuelle pure n'est pas déterminable j'imagine ?

Mais ce n'est pas le cas de toute façon.

1736

J'ai ce bout de code :
    if (spr == NULL)
    {
        err  = "Could not load file: ";
        err += SDL_GetError();
        throw err;
    }

err est une std::string

Quand spr est NULL, je cherche donc à lancer une exception. Ce que je ne comprends pas, c'est que mon programme se prend un abort au moment du throw, alors que la string semble correcte dixit GDB.
Une idée de ce qui peut déclencher cet abort ?

1737

Bon cherchez pas, faute d'innatention, l'opération à risque était mal placée, juste au-dessus de mon try et pas dedans. cheeky

1738

1739

C'est risqué de baser la synchronisation d'un jeu sur un framerate ? SDL_gfx permet de fixer un fps constant (30 par défaut), ça ne devrait donc pas poser de problème ?
Je veux juste éviter le phénomène de certains jeux oldies qui tournent à des vitesses hallucinantes parce que la synchro ne marche plus grin

1740

Folco (./1739) :
C'est risqué de baser la synchronisation d'un jeu sur un framerate ?

Oui tongue
SDL_gfx permet de fixer un fps constant (30 par défaut), ça ne devrait donc pas poser de problème ?
Tu veux dire *limiter* le FPS, et pas fixer un FPS constant (PS: 60 FPS c'est toujours mieux que 30 ^^). Si la machine n'est capable que d'afficher 15 FPS, ça va plus bien marcher. En fait le mieux c'est de ne pas limiter le FPS, comme ça les graphismes sont mis à jour plus rapidement sur les machines qui en sont capables (Faut évidemment que ton jeu supporte d'afficher des graphismes fluides à 60 fps, car si tes sprites bougent à 30, l'intérêt est en effet limité)
Je veux juste éviter le phénomène de certains jeux oldies qui tournent à des vitesses hallucinantes parce que la synchro ne marche plus grin
Parce que ces jeux ne mesuraient pas le temps écoulé, ou bien ajustaient leur timings d'une manière kikoololesque. (Avec des boucles for vides par exemple trioui)

La meilleure façon de synchroniser pour que ça tourne partout de manière indépendante du matériel graphique (bon si le CPU est trop lent par contre, on n'y fera rien ^^) c'est d'utiliser des intervalles de temps fixes pour tes mises à jour. (Les intervalles de temps variable sont *hyper* sensibles au matériel, et ne pas utiliser d'intervalle de temps, n'en parlons même pas grin)
Je reprends le code d'un ancien post:
/* 120 Hz */
#define f 120d
/* f = 1 / T <=> t = 1 / f */
#define T (1d / f)

float Update(float delta);
void Render();

int main()
{
	long oldTime, newTime;
	double xTime = 0; /* Parce que sur x86 les float ça sert a rien :p */

	Initialiser();

	oldTime = GetTickCount(); /* Je prend un timer de référence (en millisecondes) */

	while true
	{
		newTime = GetTickCount();

		xTime = Update(xTime + (newTime - oldTime) / 1000d);

		Render();
		
		oldTime = newTime();
	}
}

double Update(double delta)
{
	while (delta > T)
	{
		delta -= T;
		
		/* Faire les calculs sur une durée écoulée T */
		
	}

	/* Il reste du temps non utilisé, on s'en servira la fois prochaine */
	return delta;
}

void Render()
{
	/* Dessiner ce qu'il faut ici */
}
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes