Performance d'un jeu en 2D
@Ollivier nana le prend pas comme sa ^^'
c'est juste que en général on pense en premier au performance du jeux. Et bon sur les machines récentes on a deux cœurs (voir plus pour ceux plein de sous) alors si on en monopolise un je trouve pas sa très grave ^^'. Après pour un simple pong le "delay(1)" est logique.
c'est juste que en général on pense en premier au performance du jeux. Et bon sur les machines récentes on a deux cœurs (voir plus pour ceux plein de sous) alors si on en monopolise un je trouve pas sa très grave ^^'. Après pour un simple pong le "delay(1)" est logique.
si tu veux continuer a avoir l'air "out" !! (je suis gentil là)Norswap a écrit :Ca sonne moins bien pourtant, je pense que je vais persévérer dans mon vice ^^Dobro a écrit :ps : on dit UN sprite !
la regle en français, c'est de privilégier le masculin, lorsqu'on ne sait pas ..
tiens , une idée , tu pourrai aussi dire:
une cheval , une tabouret , une avion , une homme et meme pourquoi pas , UN femme
bref , ta réponse , m'indique ton grand potentiel , je sens qu'a ce train
on va se marrer dans quelques mois !

tiens pour ta culture :
http://fr.wikipedia.org/wiki/Sprite_(jeu_vid%C3%A9o)
ben !! c'est clair !!!tonton a écrit :Heureusement pour Norswap, qu' il na pas dit "Une Dobro!!"![]()
en parant de vice, j' en connais pas mal qui dise UN vis!!


ce qui m'a gonflé c'est surtout le coté obtus de sa réponse
mais bon , il fait comme il veux hein ...

mais je l'épingle sur ma liste noire !!

Dernière modification par Backup le dim. 15/mars/2009 22:33, modifié 1 fois.
Et la France battait ses records de consommation en anxiolitiques...Cpl.Bator a écrit :Ta pas pris tes médocs ? j'ai même pas vu ton code... Confused
Ben... En tout cas, j'ai mis quelque chose de clair avant, et puis surtout après ta remarque. A mon avis, c'est une base essentielle que nous négligeons souvent.
D'ailleurs, si toi, ou un Linuxien pouvait vérifier la véracité du petit code plus bas (celui qui mesure le différentiel minimum entre 2 ElapsedMilliseconds()... ), ça me ferait plaisir de savoir s'il fonctionne pareillement sous µsoft comme sous Linux.
Sous Linux, vous pouvez peut-être même avoir carrément plus efficace que sous Windows en matière de Timer. Une femme nommée Diana Gruber avait fait un ouvrage ("Programmation des jeux d'arcade en C") montrant comment user du Timing matériel sur les jeux sous Dos (mode réel). Alors, si vous pouvez modifier (provisoirement, j'entends) la table des interruptions (comme les virus le font d'ailleurs...) pour y rajouter l'adresse de votre propre procédure principale de jeu et réajuster la pile (Registre ESP) (Cf Code ASM IRET = Interruption RETurn) à chaque retour d'appel. C'est le matériel même qui fait exécuter votre boucle principale.
Une accélération de la fréquence d'appel du Timer en plus de cette modif, et vous (chers Linuxiens!), seriez alors les as du jeu fluide !(hors Windows, cela s'entend...). Dans ce cas (si l'écriture de la table des interruptions ne vous entraîne pas une error d'exception), nul besoin d'utiliser ton modèle de procédure principal. Mais bon... Peut-être que je fantasme... Je vais prendre mes médocs... Norswap! Gerbe mes boules rouge stp!

-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
de l'assembleur avec plein de goto, c'est rigolo
merci, je viens d'installer la dernière version( parce que la mienne remontais à 2007, c'est peu de dire que je ne l'utilise pas)... et le moniteur est bien là, oufDobro a écrit :ben le moniteur CPU fonctionne bien avec japbe et la v 4.30

merci, c'est effectivement plus stable comme outil, chuis con des fois moi. Le problème du jour, fait en réalité suite à un éternel débat sur l'utilisation de ce delay. Ma dernière conclusion c'est qu'il ne faut pas l'utiliser. Mais face à tes tests, ben j'ai décider de me remettre en question:Norswap a écrit :Le Delay(16) aide effectivement a diminuer l'usage cpu, mais l'image est moins fluide, tandis qu'à 1 l'impact est minimal sur l'usage cpu. En fait 8 est un assez bon compromis je trouve.
Sinon je préfère rester en fenêtré pour le moment, le jeu étant censé être quelque chose d'assez réduit. En plus, c'est plus facile pour tester
Tu peux aussi utiliser le moniteur de performances de Windows (avec ctrl+alt+delete) qui a l'avantage de moins oscillier.beauregard a écrit :je n'ai plus accès au moniteur CPU, c'est moi ou spécifique à la version 4.30 ?
test avec le jeu vers l'infini, temps cpu:
sans delay -> 99% max
avec un delay( 8 ) -> 54% max
avec un delay(10) -> 44% max
avec un delay(12) ->36% max
avec un delay(16), çà rame, chute de fps donc fin de l'exprérience
http://www.purebasic.fr/french/viewtopi ... 4963#94963
Sur ma 2eme machine, bien plus ancienne, çà tourne à 54 i/s de manière fluide avec un delay(12), alors je retiens cette solution

Les explications des différents intervenants sont intéressante...
tonton à mis un delay(20) et déconnecté un delay(10), pour son jeu( un jeu complet qui plus est):
http://www.purebasic.fr/french/viewtopi ... sc&start=0
Comme quoi, même les meilleurs peuvent, heu, réfléchir grandement sur cette petite commande. L'avis de tonton sur ce sujet sera des plus précieux...
Dernière modification par beauregard le lun. 16/mars/2009 0:29, modifié 1 fois.
Norswap a écrit :Pas la peine de s'enflammer etc...
@ Norswap
En conclusion moins hâtive, si tu veux contrôler les ressources CPU compatible, ce que j'ai écrit en page 1 (et première "inflammation" ou "ignition", je ne sais pas exactement comment l'exprimer, mais au moins c'est repérable pas la manière dont j'ai présenté l'explication!) est une méthode qui, à mon avis n'a pas d'égal.
Sous XP (ChaOs, Cpl.Bator ou d'autres personnes possédant aussi Linux pourront te renseigner bien mieux que moi pour Linux), au moins sous XP, l'OS apprécie de convention qu'on lui rende la main de manière amiable grâce à l'instruction Delay(n) avec n en milliseconde(s). L'OS étant le "supérieur", c'est lui qui décide quand est-ce qu'il te rend la main. La seule chose est que si toutes les applications en parallèles fonctionnent dans les normes (ce qui n'est pas toujours le cas), et s'il n'y a pas un nombre trop important d'applications en arrière-plan, l'OS te rend la main à intervalles réguliers.
Sans ton application (ou ton jeu), l'OS a toujours la main (signes "-"), et, parce qu'il est conçu ainsi, il nécessite la main de manière irrégulière (signes "X")
Code : Tout sélectionner
-----------|----XXXXXX|----XXXXXX|---------|---------|----> t
t0 t1 t2 t3 t4
Avec ton application légère en ressource, "O" représente ce que ton application consomme ("D" symbolise d'une part ce qu'elle consomme, d'autre part le fait qu'elle rende la main à l'OS avec l'instruction Delay).
Code : Tout sélectionner
Repeat ; Application légère en ressources
Delay(1)
ForEver
Code : Tout sélectionner
-----------|OD--XXXXXX|OD--XXXXXX|OD-------|OD-------|OD--> t
t0 t1 t2 t3 t4
l'argument de 1ms dans le Delay() est une durée minimum.
Au fur et à mesure que tu rajoutes des instructions de contrôle et de mise à jour, tes ressources consommées vont augmenter.
Code : Tout sélectionner
-----------|OOOOOOD---|OOD-------|OOOOD----|OOOOD----|D---> t
t0 t1 t2 t3 t4
En effet, comme dit ChaOs, ça n'est pas forcément la mer à boire. Ben, il a raison: il ne travaille pas que sous Windows!!
Parce que le Windows qui se chatouille tout seul sans prévenir de temps à autre, ça donne ça:
Code : Tout sélectionner
-----------|OOOOOODXXX|XXX-------|OODXXXXXX|OOOOD-----|D---> t
t0 t1 t2 t3 t4
Pourquoi? Parce que ses fabricants ont mis une tolérance très large...
Code : Tout sélectionner
-----------|OOOOOOD---|XXXXXX----|---------|XXXXXX-----|OOD-> t
t0 t1 t2 t3 t4
Code : Tout sélectionner
-----------|OOOOOOO---|XXXXXX----|YYY------|XXXXXX-----|OOOO> t
t0 t1 t2 t3 t4
Code : Tout sélectionner
-----------|OOOOOOD---|XXXXXX----|YYYRR----|YYYRR----|XXXX> t
t0 t1 t2 t3 t4
Si, pendant ce temps-là, tu étais train de défoncer Billy The Skeleton à coup de M79, tu n'apprécies pas trop, que l'explosion fatale reste figée, et que Billy ne se retrouve pas au sol, comme tout le monde à l'écran depuis 10 minutes non-stop. De surcroît, tu vas instinctivement rester appuyé sur la détente de ton arme (touche Espace ou autre) pour lui remettre une deuxième mandalle. Résultat: En plus d'une réparation d'un bug qui n'est pas de ton ressort, Windows risque de te dire "Coco tiens-toi tranquille 100ms stp ou je te colle un plantage du bâton de plusieurs secondes!!". Cela n'a bien entendu pas de frontière de compilateur! Pour éviter cette conflictuelle, en PB, un Delay(1) sans condition est obligatoire. (Information généreusement offerte, page 1 par HuitBit)
Et si tu respectes cette douce règle de t'en tenir à environ 2 cycles de l'OS dans tes jeux, comme dans tes applications, (env. 32ms = 30Hertz), l'OS ne t'appellera jamais (ou très rarement) "Coco". Donc deux instructions Delay(1) sont à placer quelque part dans ta boucle principale...(Ou 1 Delay(16) )
Il n'y a rien besoin d'autre pour qu'un jeu ou une application garde la même vitesse générale sur 36 bécanes diverses à 36 vitesses différentes (au moins sur XP) :
60 Hertz environ pour 1 cycles OS (on ne gère pas grand chose + ralentissement à 30 Hz avec risques "Coco" de temps à autres)
30 Hz~ pour 2 cycles OS(on gère pleins de choses + régularité)
20 Hz~ pour 3 cycles OS(saccades visibles)
Avec
1 cycles OS = 1 instruction Delay(1)
2 cycles OS = 2 instructions Delay(1) ou une instruction Delay(16)
3 cycles OS = 3 instructions Delay(1) ou Delay(1)+Delay(16) ou Delay(33)
Remarques:
Un Delay(2) = Delay(1)
Un Delay(3) = Delay(1)
Etc...
On a :
Code : Tout sélectionner
Delay(F(n) )
Code : Tout sélectionner
Procedure.I F(n.I)
Protected Result.I
Result = 16 + n - n % 16
; Délai réel = 16 + Délai théorique - (Délai théorique modulo 16)
; Résultat précis à + ou - 3%
ProcedureReturn Result
EndProcedure
Il a pris en considération que sa boucle principale tournait dans un de ces trois cas:
soit durant 6ms sur 1 cycle OS de ~16ms à ~40% de conso CPU
soit durant 23ms sur 2 cycles OS de ~33ms à ~68% de conso CPU
soit durant 37ms sur 3 cycles OS de ~47ms à ~78% de conso CPU
(je mets les 3 cas parce que je n'ai pas vu son code)
Or, sur mon PC sans doute plus lent que le sien (on va être gentil, on va inventer, on va dire 2 fois plus lent), je pourrais obtenir quelque choses comme:
12ms sur 2 cycles OS de ~33ms à ~37% de conso CPU ; Incompatibilité
46ms sur 3 cycles OS de ~63ms à ~75% de conso CPU ; Incompatibilité
74ms sur 5 cycles OS de ~94ms à ~80% de conso CPU ; Incompatibilité
Dans le premier cas, mon PC exécute 2 fois plus lentement.
Dans le deuxième cas, mon PC exécute 1.5 fois plus lentement.
Dans le troisième cas, mon PC 1.6 fois plus lentement
Pourtant, s'il avait mis "Delay(1)"
J'obtiendrais sur mon PC deux fois plus lent:
12ms sur 1 cycles OS de ~16ms à ~75% de conso CPU ; Compatible
46ms sur 3 cycles OS de ~47ms à ~98% de conso CPU ; Incompatibilité
74ms sur 4 cycles OS de ~80ms à ~94% de conso CPU ; Incompatibilité
Dans le cas où son jeu ne bouffe qu'un cycle par boucle (on va admettre que c'est ce cas de figure pour comprendre les deux autres : on y reviendra), il est compatible avec mon PC puisque, même 2 fois plus lent, il lui faut le même nombre de cycles OS (1 cycle OS, soit une fréquence de 60 Hertz) que sur le sien. Seul inconvénient, mais lui n'y pourra rien a priori : mon PC va bouffer 75% de ressources contre 40% pour le sien.
Alors Tonton (bon, excuse-moi Tonton, j'invente une fiction romanesque pour me faire comprendre correctement par un large public sur cette subtilité technique...), ébahi à l'idée que je puisse bouffer autant de ressources me dit "Ne t'inquiète pas Ollivier, je suis un malin. Je peux bien enlever 2 ou 3 bricoles pour que tu uses de moins de ressources sur ta grosse dau... ton PC un peu plus ancien!"
Moi, gourdin en main de découvrir un jeu aussi puissant fonctionner soudain sur mon PC, j'exclame ma joie : "Merci Tonton ! Youpi! C'est génial !"
Mais là, c'est Tonton qui fait la gueule: sur son PC, le jeu allégé de quelques détails et le Delay() réglé à 1, il fonce beaucoup trop vite et est injouable...
Alors là, magie de la providence, simple hasard, ou bien illumination shadokienne, je n'en sais rien, je lui porte ce conseil à l'oreille:
"Mais Tonton, tu peux peut-être rajouter un deuxième Delay(1) tous les x boucles, et ce "x", tu le calcules en début de jeu, avant la boucle principale!"
Résultat des courses : Tonton est content sur son 2GHz, et moi je suis content sur ma grosse daube.
Fin de l'histoire.
Petit apparte concernant les critiques susceptibles de naître quand à mon bon conseil de prôner une gestion à 30 Hertz (2 cycles OS) plutôt qu'à 60 Hertz (1 cycle OS), les gens qui, bien évidemment souhaiterait me prouver (par du code, cela va de soi) que j'ai tort peuvent toujours essayer : avant qu'ils perdent du temps à, je le répète essayer de prouver que j'ai tort (de ne jamais travailler à plus de 30 Hertz) (Pour qu'ils m'évitent de perdre moi-même du temps à devoir leur répondre par un code qui leur montre qu'ils ont tort définitivement), qu'ils comprennent juste ma douleur d'être à ce point aveugle :
- Quand je me prends des baffes en pleine tronche à 25 Hertz, je les sens toutes, sans exception, cependant, même les yeux ouverts et le plus sobrement du monde, je n'en vois aucune, ni arriver, ni repartir, et cela, bien évidemment sans exception : Persistence rétinienne oblige, le reste n'est que marketing matériel déviant tranquillement mais bêtement vers les logiciels. J'espère que cette compassion suffira.
Concernant le différentiel minimum, les fameuses 15 (ou 14, ou 16 ms) millisecondes que j'évoque tout au long de ce tutoriel, j'ai fait un code tout bête pour le mesurer donc page 1.
Je peux le remettre là même, ça ressemble à ça:
Code : Tout sélectionner
Depart = ElapsedMilliseconds()
Delay(1)
Fin = ElapsedMilliseconds()
Debug Fin - Depart
Alors, je t'explique le mode d'emploi du cas Ollivier.
1) Sélectionner son code publié dans le forum (il n'y a qu'ici) sans en oublier ni la première, ni la dernière ligne
2) Appuyer sur Ctrl-C
3) Retourner dans ton éditeur
4) Cliquer sur "Nouveau" dans l'éditeur, puis cliquez sur la feuille
5) Appuyer sur Ctrl-V
6) Appuyer sur F5
Tu vois, cette règle est valable pour un de mes codes de 4 lignes comme de 40, 400 ou 4000 lignes. Elle est valable, aujourd'hui comme demain, dans un an, dans dix ans, et tout cela si le Ciel le veut. Mais il n'y aura jamais plus compliqué à attraper pour que le fruit s'affiche à ton écran.
Si tu comprends cela, tu as tout compris du cas Ollivier. Simple (là, devant ce mot, tu en as au moins 10 qui se marrent...)
Alors toi, fais-moi plaisir, au lieu de me couler gaiement et surtout, inutilement, teste les codes que je poste: au moins le tout dernier!!! Celui-là, juste ci-dessus ne fait pas 25000 lignes!! C'est un minimum de le tester et de donner un réponse qui puisse être commentée: quel nombre vois-tu s'afficher ?
@Olivier
j'ai testé ton code
sous Windows j'ai
Je connait pas le noyau de Windows mais sous nux l'OS privilégie les applications possédant une interface quelconque vers l'utilisateur, après c'est une question de priorité et l'ordonnanceur distribue équitablement les temps (quantum) d'exécution c'est le principe d'un système multi-taches . Seul bémol quand on veut accéder a des périphériques partagé (comme par exemple le disque dur) le temps d'exécutions devient aléatoire, je suppose qu'il en est de même pour la carte graphique qui doit être gérée par le serveur X(la sur couche qui gère l'interface graphique sous linux).
Sinon j'ai lue un articles récemment qui parlait du frame rate. http://www.nofrag.com/2003/nov/24/8629/ si vous avez deux seconde je vous conseille d'aller y faire un tour.
j'ai testé ton code
sous Windows j'ai
et sous linuxQté de boucles effectuées : 1
Différentiel (en ms) = 15
le Windows est un core 2 duo a 2.2ghz et le nux un pentium M(dérivé du P4 pour portable) a 1.7ghz mais il tourne a 700mhz en moyenne (je sait pas si ce genre d'optimisation d'économie d'énergie existe sous Windows)Qté de boucles effectuées : 1
Différentiel (en ms) = 1
Je connait pas le noyau de Windows mais sous nux l'OS privilégie les applications possédant une interface quelconque vers l'utilisateur, après c'est une question de priorité et l'ordonnanceur distribue équitablement les temps (quantum) d'exécution c'est le principe d'un système multi-taches . Seul bémol quand on veut accéder a des périphériques partagé (comme par exemple le disque dur) le temps d'exécutions devient aléatoire, je suppose qu'il en est de même pour la carte graphique qui doit être gérée par le serveur X(la sur couche qui gère l'interface graphique sous linux).
Sinon j'ai lue un articles récemment qui parlait du frame rate. http://www.nofrag.com/2003/nov/24/8629/ si vous avez deux seconde je vous conseille d'aller y faire un tour.
celui qui distribut équitablement c'est le system multitache Préamptif !cha0s a écrit : c'est une question de priorité et l'ordonnanceur distribue équitablement les temps (quantum) d'exécution c'est le principe d'un système multi-taches .
comme le Multitos , Amos, MagiC ,etc ..
de plus on pouvais détourner les interruptions hard (Hbl,VBL)
pour synchroniser un prg .... ha la belle epoque des hard scroll

le multitache Coopératif , lui attends, que les applications rendent la main !!
c'était le cas de windows 3.11 , et 95,98 (d'ou la presence de la fonction DO EVENT en visual Basic , et de DELAY()en PureBasic
une application qui gardait la main, pouvais bloquer le systeme !!
d'ailleurs a ce propos sur Atari Falcon030 on se foutais de la gueule des windAube de l'époque, parceque si tu mettais une musique d'intro de 5 minutes sur windows, au moment du boot, ben fallait attendre 5 minutes pour voir apparaitre le bureau !!
justement parceque la tache qui s'occupais de jouer la musique gardait la main !!

Sur Falcon030 , le Hard etait geré de façon parallèle et independant,(DSP) ce qui fait que meme sans le system d'exloitation multitache , tu pouvais mettre un morceau de 5 minutes, au boot, ton bureau apparaissait , tout en continuant d'entrendre ta musique d'intro !

depuis XP , il me semble que le multitache est un compromis entre les 2 system
bref, c'est batard !

d'ou cette imprecision , dans le system
la seul chose sur lequel on puisse compter, c'est peut etre l'horloge !!

et encore pas sur !!
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
Deux, c'est mieux qu'une.
non, tu as lu trop vite. Je te remet le lien de son code( j'avais précisé qu'il avait déconnecté le delay(10) ):Ollivier a écrit :Donc, pour info, si Tonton a mis un Delay(10) quelque part (je vois ça en lisant le message de Beauregard...), avec toutes mes plus plates et mes plus profondes excuses, ainsi qu'avec mon plus grand respect envers lui comme envers les autres, il s'est planté...
le code de tonton, ici, là:http://www.purebasic.fr/french/viewtopi ... 14&start=0
Heu..., pour résumer tu pense alors qu'il faut 2 delay(1), bon ben c'est cool, hum, grat, grat. Oui, alors où je dois le mettre moi, ce 2eme delay ?Ollivier a écrit : Avec
1 cycles OS = 1 instruction Delay(1)
2 cycles OS = 2 instructions Delay(1) ou une instruction Delay(16)
3 cycles OS = 3 instructions Delay(1) ou Delay(1)+Delay(16) ou Delay(33)
Remarques:
Un Delay(2) = Delay(1)
Un Delay(3) = Delay(1)
Etc...
Code : Tout sélectionner
; ******************************************************************************************************
Repeat ; Boucle principale
; ******************************************************************************************************
Event= WindowEvent ()
If CreateImage(0,26,20)
StartDrawing(ImageOutput(0))
Box(0,0,26,20,RGB(255,255,255))
Circle(13,10,5,RGB(255,0,0))
StopDrawing()
SetClipboardImage(0)
EndIf
;Event= WaitWindowEvent (100)
Start3D(); on place cette commande dès le début de la boucle principale.
ExamineKeyboard ()
; °°°°°°°°°°°°°°°°°°°°°°
;- Commandes: °°°°°°°°°°°°
If manette=1:ExamineJoystick(0):EndIf
; °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
If pause=0:ReleaseMouse(0); on récupère la souris pour le jeu
ExamineMouse()
EndIf
If pause>0:ReleaseMouse(1):EndIf; on libère la souris
If manette=0
If KeyboardPushed ( #PB_Key_P ) And pause=0:pause=1:EndIf
If KeyboardPushed ( #PB_Key_P )=0 And pause=1:pause=2:EndIf
If KeyboardPushed ( #PB_Key_P ) And pause=2:pause=3:EndIf
If KeyboardPushed ( #PB_Key_P )=0 And pause=3:pause=0:EndIf
EndIf
If manette=1
If JoystickButton(0,8) And pause=0:pause=1:EndIf
If JoystickButton(0,8)=0 And pause=1:pause=2:EndIf
If JoystickButton(0,8) And pause=2:pause=3:EndIf
If JoystickButton(0,8)=0 And pause=3:pause=0:EndIf
EndIf
; °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
directionX=0:bouton1=0
If manette=0
If KeyboardPushed ( #PB_Key_Right ):directionX=1:EndIf ; droite.
If KeyboardPushed ( #PB_Key_Left ):directionX=-1:EndIf ; gauche.
If KeyboardPushed ( #PB_Key_X ):bouton1=1:EndIf ; bouton action
EndIf
If manette=1
If JoystickAxisX(0)=1:directionX=1:EndIf ; droite.
If JoystickAxisX(0)=-1:directionX=-1:EndIf ; gauche.
If JoystickButton(0,1):bouton1=1:EndIf ; bouton action
EndIf
; °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;- étapes: °°°°°°°°°°°°
If etape=0; *******
Affichageintro()
EndIf
If etape=1; *******
Affichagelevel(); dans cette procédure -> fabrication des étoiles et des brutes
EndIf
If etape=10; *******
;- fond étoilé
Affichagetoile()
Affichsoucoupe()
If extra=1 Or extra=2:Fsoucoupe(extra):extra=10:EndIf; ordre de Fabrication clone soucoupe volante
AffichagebruteA() ; ordre d'affichage des clones bruteA.
AffichagebruteB() ; ordre d'affichage des clones bruteB.
AffichagebruteC() ; ordre d'affichage des clones bruteC.
ordretirbrute=0
Affichagetirbrute() ; ordre d'affichage des clones tirs brute.
Affichageship(); vaisseau du joueur
Affichagescorep()
Affichagelifeup()
;- changement de niveau, explication:
; pour le 1er niveau, il y a 16 brutesA à détruire.
; pour le 2eme niveau, il y a 8 brutesA et 8 brutesB à détruire.
; pour le 3eme niveau, il y a 16 brutesA et 8 brutesB à détruire.
; 4 niveau-> Boss( non effectif)
; pour le 5eme niveau, il y a 16 brutesB à détruire.
; pour le 6eme niveau, il y a 8 brutesB et 8 brutesC à détruire.
; pour le 7eme niveau, il y a 8 brutesA et 8 brutesB et 8 brutesC à détruire.
; 8 niveau-> Boss( non effectif)
; ... et provisoire la même chose pour tout les niveau suivant.
If nextlevel=0
If (nbrdetruit>16-1 And level=1) Or (nbrdetruit>16-1 And level=2) Or (nbrdetruit>24-1 And level=3):nextlevel=1:EndIf
EndIf
If nextlevel=0
If level=4:nextlevel=1:EndIf; niveau du 1er Boss( non effectif, alors on zappe).
If level=8:nextlevel=1:EndIf; niveau du 2eme Boss( non effectif, alors on zappe).
If level=10:nextlevel=1:level=0:EndIf; niveau 10 terminus, alors on zappe et on propose de recommencer.
EndIf
If nextlevel=0
If (nbrdetruit>16-1 And level=5) Or (nbrdetruit>16-1 And level=6) Or (nbrdetruit>24-1 And level=7):nextlevel=1:EndIf
EndIf
If nextlevel=0
If (nbrdetruit>40-1 And level=9):nextlevel=1:EndIf; Or (nbrdetruit>16-1 And level=6) Or (nbrdetruit>24-1 And level=7):nextlevel=1:EndIf
EndIf
If nextlevel=1:nextlevel=0
If extra=0:nombrextra=0:topdepartextra=0
level+1:etape=1
dirbruteA=0:dirbruteB=0:dirbruteC=0; dans une même direction, pour un même but ;)
speedbrut=1:nbrdetruit=0
EndIf
EndIf
;- joueur gagne une vie
If (score>490 And bonusvie=0) Or (score>990 And bonusvie=1) Or (score>1490 And bonusvie=2) Or (score>1990 And bonusvie=3)
bonusvie+1:vie+1:Flifeup(Xgentil+11, Ygentil) ; joueur gagne une vie tout les 500 pts
EndIf
If (score>2490 And bonusvie=4) Or (score>2990 And bonusvie=5) Or (score>3490 And bonusvie=6) Or (score>3990 And bonusvie=7)
bonusvie+1:vie+1:Flifeup(Xgentil+11, Ygentil) ; joueur gagne une vie tout les 500 pts
EndIf
If (score>4500-10 And bonusvie=8) Or (score>5000-10 And bonusvie=9) Or (score>5500-10 And bonusvie=10) Or (score>6000-10 And bonusvie=11)
bonusvie+1:vie+1:Flifeup(Xgentil+11, Ygentil) ; joueur gagne une vie tout les 500 pts
EndIf
If (score>6500-10 And bonusvie=12) Or (score>7000-10 And bonusvie=13) Or (score>7500-10 And bonusvie=14) Or (score>8000-10 And bonusvie=15)
bonusvie+1:vie+1:Flifeup(Xgentil+11, Ygentil) ; joueur gagne une vie tout les 500 pts
EndIf
If (score>8500-10 And bonusvie=16) Or (score>9000-10 And bonusvie=17) Or (score>9500-10 And bonusvie=18) Or (score>10000-10 And bonusvie=19)
bonusvie+1:vie+1:Flifeup(Xgentil+11, Ygentil) ; joueur gagne une vie tout les 500 pts
EndIf
ClipSprite(#shipb, 0, 208, 64, 48):DisplayTransparentSprite( #shipb , 10, 10)
StartDrawing ( ScreenOutput ())
DrawingMode (1)
FrontColor ( RGB (255,255,255))
DrawingFont ( FontID (0))
score$= Str (score)
FrontColor ( RGB (154,154,154)) :DrawText (350+1, 5+1, "SCORE " +score$)
FrontColor ( RGB (234,234,234)) :DrawText (350, 5, "SCORE " +score$)
DrawingFont ( FontID (0))
hiscore$= Str (hiscore)
FrontColor ( RGB (255, 153, 0)) :DrawText (680+1, 5+1, "HI-SCORE ")
FrontColor ( RGB (255,224,0)) :DrawText (680, 5, "HI-SCORE ")
FrontColor ( RGB (255, 153, 0)) :DrawText (680+1,25+1, "" +hiscore$)
FrontColor ( RGB (255, 224, 0)) :DrawText (680,25, "" +hiscore$)
DrawingFont ( FontID (1))
vie$= Str (vie)
FrontColor ( RGB (164,21,21)) :DrawText (42+1, 4+1, " " +vie$)
FrontColor ( RGB (253,201,255)) :DrawText (42, 4, " " +vie$)
StopDrawing ()
; Si invuln=100, alors explosion 1.
; Si invuln=101, alors explosion 2.
If vie<1 And invuln<100:etape=20:EndIf
If etape=10 And tousensemble=1:tousensemble=0:topdepartextra=1
ForEach bruteA()
bruteA()\y+24
Next
ForEach bruteB()
bruteB()\y+24
Next
ForEach bruteC()
bruteC()\y+24
Next
EndIf
If etape=10 ; désigner la brute qui va tirer: il faut utiliser 2 variables globales: choixtirbrute et ordretirbrute
If pause=0:tempotirbrute+1:EndIf
If tempotirbrute>64:tempotirbrute=0:nbrdebrute=0
ForEach bruteA()
nbrdebrute+1
Next
ForEach bruteB()
nbrdebrute+1
Next
ForEach bruteC()
nbrdebrute+1
Next
choixtirbrute=Random(nbrdebrute); de 0 à 7...
choixtirbrute+1; ...et là +1, donc maintenant de 1 à nombre de brute présent à l'écran.
EndIf
EndIf
EndIf; If etape=10
If etape=20; *******
Affichagegameover()
EndIf
If KeyboardPushed ( #PB_Key_F ) And nbreis=0:nbreis+1:EndIf
If KeyboardPushed ( #PB_Key_F )=0 And nbreis=1:nbreis+1:EndIf
If KeyboardPushed ( #PB_Key_F ) And nbreis=2:nbreis+1:EndIf
If KeyboardPushed ( #PB_Key_F )=0 And nbreis=3:nbreis=0:EndIf
Gosub fps ; nombre d'image par seconde.
Stop3D(); on place cette commande à la fin de la boucle principale.
FlipBuffers(1)
;-
Delay(12) ;- là
;-
ClearScreen(RGB(0,0,0))
; ******************************************************************************************************
If Event= #PB_Event_CloseWindow Or KeyboardPushed ( #PB_Key_Escape ):Fin():EndIf; si clique coin haut droit ou touche Esc, alors ferme fenêtre.
ForEver
Ollivier>
Tu es un gros bosseur toi! J'apprécie le travail que tu fais; à titre d'information, tonton, comme moi et d'autres anciens nous basons sur ce que nous connaissons. Nous avons programmé beaucoup d'applis graphiques sur des machines qui étaient synchronisées sur l'affichage, notamment la VBL dont tu as sans doute déjà entendu parler. Nous sommes très habitués à un affichage hyper fluide de ce fait (une synchro constante, jamais un frame drop!). Sur ces machines, il y avait (au moins) une véritable interruption processeur pour la VBL (ça existait sur PC aussi d'ailleurs); donc nous étions sûrs de pouvoir faire nos calculs et notre redraw sans nous faire voler du temps CPU par d'autres tâches.
En programmation système, l'OS nous permettait d'avoir une priorité supérieure afin, de la même façon, de ne pas perdre nos cycles. Cela venait d'un constat simple, mais qui a échappé aux programmeurs de Windows (normal, celui-ci était plutôt fait pour la bureautique), à savoir que l'OS est là pour répondre à l'utilisateur, et ne pas le faire attendre. Avec Windows, l'utilisateur n'est pas prioritaire, souvent lui ou l'application en cours se font voler le focus par une autre appli, c'est exaspérant. Mais ça tient aux fondamentaux de Windows, un programme=une fenêtre, d'où son nom, avec celle au premier plan avec un boost de priorité. Le swap de fenêtres demande à l'OS un jonglage de priorités qui n'améliore pas la réactivité. Windows date, et n'a jamais été le mieux pensé des OS (d'ailleurs ce n'en était pas un!), mais c'est ainsi.
Les anciens sont un peu irrités de devoir utiliser des timers, qui s'ils permettent un affichage et une réaction de l'OS à peu près constants, ne permettent pas une action bien synchronisée sur l'affichage; si en 3d cela ne se voit pas trop, en 2D, quand un vaisseau avance de 5 pixels, de 3, puis de 8, même si la moyenne est constante, à l'oeil c'est horrible, surtout pour les habitués. Moi quand je vois un frame drop j'ai instinctivement un rejet. Je n'y peux rien, j'ai connu trop de bons jeux à 50hz pour supporter ça. C'est pour ça aussi qu'on préfère jouer sur consoles qui ne souffrent pas trop de ces défauts.
Quand j'aurai un peu de temps je testerai ton truc des deux delay(1), ça m'a l'air intéressant. Avec une bonne quantité de sprites 3d de belles dimensions ce serait plus démonstratif.

En programmation système, l'OS nous permettait d'avoir une priorité supérieure afin, de la même façon, de ne pas perdre nos cycles. Cela venait d'un constat simple, mais qui a échappé aux programmeurs de Windows (normal, celui-ci était plutôt fait pour la bureautique), à savoir que l'OS est là pour répondre à l'utilisateur, et ne pas le faire attendre. Avec Windows, l'utilisateur n'est pas prioritaire, souvent lui ou l'application en cours se font voler le focus par une autre appli, c'est exaspérant. Mais ça tient aux fondamentaux de Windows, un programme=une fenêtre, d'où son nom, avec celle au premier plan avec un boost de priorité. Le swap de fenêtres demande à l'OS un jonglage de priorités qui n'améliore pas la réactivité. Windows date, et n'a jamais été le mieux pensé des OS (d'ailleurs ce n'en était pas un!), mais c'est ainsi.
Les anciens sont un peu irrités de devoir utiliser des timers, qui s'ils permettent un affichage et une réaction de l'OS à peu près constants, ne permettent pas une action bien synchronisée sur l'affichage; si en 3d cela ne se voit pas trop, en 2D, quand un vaisseau avance de 5 pixels, de 3, puis de 8, même si la moyenne est constante, à l'oeil c'est horrible, surtout pour les habitués. Moi quand je vois un frame drop j'ai instinctivement un rejet. Je n'y peux rien, j'ai connu trop de bons jeux à 50hz pour supporter ça. C'est pour ça aussi qu'on préfère jouer sur consoles qui ne souffrent pas trop de ces défauts.
Quand j'aurai un peu de temps je testerai ton truc des deux delay(1), ça m'a l'air intéressant. Avec une bonne quantité de sprites 3d de belles dimensions ce serait plus démonstratif.
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
Tout d'abord, merci pour toutes ses explications. Quand je disais qu'il ne fallait pas s'enflammer, je parle bien sur de la forme et non du fond.
Ceci étant dit, je trouve tout de même tes explications un brin confuses.
J'ai donc quelques questions :
Tu soulignes l'importance de rendre la main à l'OS, mais est-ce que dans le cas du code de Cpl.Bator, on ne lui rend pas la main ?
D'ailleurs cette histoire de "main" me rend un peu confus l'un dans l'autre. Windows XP est un OS mutlitâches et donc il est supposé divisé le temps d'exécution en petites tranches et faire s'exécuter les programes à tour de rôle (ce qu'on appelle time-slicing). Tu le mentionnes d'ailleurs quand tu parles de tâches en parallèle.
Mais alors, logiquement l'os se trouve à un niveau supérieur comme tu dit, et peut juste décider de suspendre l'exécution pour faire place à la tranche de temps d'un autre programme logiquement. Alors que quand on parle de "rendre la main" on a l'impression que l'OS s'éxecute lui aussi dans une tranche de temps similaire aux autres programmes.
Concernant ceci :
Un Delay(1) me donne 0ms à tous les coups (Windows XP Dual Core 2Ghz), si j'augmente l'argument, j'aurais 16ms ou 0ms (plus j'augmente l'argument, plus le 16 est fréquent, pour couvrir quasi 100% des cas à 14).
Le même phénomène se reproduit pour la suite : un Delay(20) (qui devrait d'après toi me donner 32ms), me donne soit 16ms ou 32ms.
Donc ta formule, même si très liée à la réalité, ne me semble pas fiable à 100%. Elle est même décalée puisque d'après elle un Delay(16) devrait me donner 32ms alors qu'il ne m'en donne que 16 et qu'un Delay(32) devrait me donner 48ms alors qu'il m'en donne que 32.
EDIT :
J'ajouterais en plus que mon problème ne concerne pas de crash comme c'est suggéré à un endroit, mais bien de consommation de cpu trop élévée.
Je viens de tester la méthode Cpl.Bator, elle rend en effet l'impact sur le cpu presque nul. De plus il n'y à priori aucun risque de "désynchronisation" entre différent pc, puisque la boucle vérifie effectivement le temps écoulé. Je ne vois vraiment pas où se situe le problème avec cette méthode.
Ceci étant dit, je trouve tout de même tes explications un brin confuses.
J'ai donc quelques questions :
Tu soulignes l'importance de rendre la main à l'OS, mais est-ce que dans le cas du code de Cpl.Bator, on ne lui rend pas la main ?
D'ailleurs cette histoire de "main" me rend un peu confus l'un dans l'autre. Windows XP est un OS mutlitâches et donc il est supposé divisé le temps d'exécution en petites tranches et faire s'exécuter les programes à tour de rôle (ce qu'on appelle time-slicing). Tu le mentionnes d'ailleurs quand tu parles de tâches en parallèle.
Mais alors, logiquement l'os se trouve à un niveau supérieur comme tu dit, et peut juste décider de suspendre l'exécution pour faire place à la tranche de temps d'un autre programme logiquement. Alors que quand on parle de "rendre la main" on a l'impression que l'OS s'éxecute lui aussi dans une tranche de temps similaire aux autres programmes.
Concernant ceci :
Code : Tout sélectionner
Procedure.I F(n.I)
Protected Result.I
Result = 16 + n - n % 16
; Délai réel = 16 + Délai théorique - (Délai théorique modulo 16)
; Résultat précis à + ou - 3%
ProcedureReturn Result
EndProcedure
Code : Tout sélectionner
Depart = ElapsedMilliseconds()
Delay(1)
Fin = ElapsedMilliseconds()
Debug Fin - Depart
Le même phénomène se reproduit pour la suite : un Delay(20) (qui devrait d'après toi me donner 32ms), me donne soit 16ms ou 32ms.
Donc ta formule, même si très liée à la réalité, ne me semble pas fiable à 100%. Elle est même décalée puisque d'après elle un Delay(16) devrait me donner 32ms alors qu'il ne m'en donne que 16 et qu'un Delay(32) devrait me donner 48ms alors qu'il m'en donne que 32.
EDIT :
J'ajouterais en plus que mon problème ne concerne pas de crash comme c'est suggéré à un endroit, mais bien de consommation de cpu trop élévée.
Je viens de tester la méthode Cpl.Bator, elle rend en effet l'impact sur le cpu presque nul. De plus il n'y à priori aucun risque de "désynchronisation" entre différent pc, puisque la boucle vérifie effectivement le temps écoulé. Je ne vois vraiment pas où se situe le problème avec cette méthode.