IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Téléchargez Python Discussion :

Game Over.


Sujet :

Téléchargez Python

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut Game Over.
    Bonjour,

    Je vous propose un nouvel élément à utiliser : Game Over.

    En continuant de Accrochons des briques en l'air, on rajoute une gestion du score et une limitation des tirs. Plus un bouton pour redémarrer le jeu et on arrive à un jeu presque fonctionnel.

    Il a été écrit en Python3/Qt5.

    Qu'en pensez-vous ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    Je ne connais pas pyQt mais ça me paraît beaucoup 600 lignes de code.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par josmiley Voir le message
    Je ne connais pas pyQt mais ça me paraît beaucoup 600 lignes de code.
    Salut, merci de t'intéresser. Mais si tu ne connais pas PyQt tu devrais commencer par le premier exemple Hello World qui n'en fait que 17

    Sinon difficile de répondre à cet avis très (trop?) subjectif. Est-ce que 600 lignes pour ce programme qui génère une cible, gère un angle et une force, associe tout ça à un dessin et programme une trajectoire parabolique tout en gérant aussi l'intersection avec la cible et un compteur de coups c'est beaucoup? Peut-on arriver à faire la même chose en moins de lignes avec une autre librairie? Et "moins de lignes" sera-ce "beaucoup moins" ou seulement "un peu moins"??? Parce que ce sont vers ces questions que ta remarque nous entraine.
    Bon déjà il faut savoir que dans le tuto officiel d'où j'ai sorti ces exemples (exemples écrits à l'origine en C++/Qt), ils sont découpés en plusieurs modules. Un module pour gérer le champ de tir, un module pour gérer les paramètres, etc. Et quand on découpe, c'est plus facile à appréhender. Mais pour ici, pour que les utilisateurs puissent télécharger facilement, j'ai mis le tout dans un gros et unique source qui fatalement devient énorme (et je suis en train de finir la 6° et dernière partie qui en fait presque 900).

    Ensuite Qt c'est une librairie assez puissante mais (corollaire) assez lourde à programmer (et perso je trouve qu'elle en fait trop en voulant toucher à pleins de trucs qui ne sont pas de l'IHM tel sql, les threads, j'ai même vu que l'exemple originel passait par un QTime et qRand pour générer ses nombres aléatoires !!!) donc qui dit "lourde à programmer" dit "beaucoup de lignes". Et encore Qt5 a pas mal raccourcis certains trucs. Par exemple pour créer un bouton et le connecter à un slot, en Qt4 ça s'écrivait ainsi
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    btn=QPushButton(...)
    QObject.connect(btn, SIGNAL("clicked(bool)"), autreWidget, SLOT("truc()")

    Cette syntaxe déjà s'est vachement allégée sous Qt5 car elle s'écrit maintenant...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    btn=QPushButton(...)
    btn.clicked[bool].connect(autreWidget.truc)
    ... et peut même (quand on n'a qu'un signal à gérer et qu'on n'a pas besoin de récupérer le booléen "bouton pressé/bouton relaché") devenir alors btn=QPushButton(..., clicked=autreWidget.truc). Mais malgré ces optimisations, il reste toutefois que quand on veut faire pas mal de trucs il faut alors pas mal de lignes. Par exemple je viens de rajouter une mise à jour pour centrer le message "Missed/Gotcha" qui apparait quand le tir rate ou réussit. Ce message est un texte (donc un QLabel dans Qt). J'aurais bien aimé pouvoir directement écrire truc=QLabel(..., aligment=Qt.AlignHCenter) malheureusement l'option "alignment" n'est pas disponible à la construction du QLabel donc me faut 2 lignes, la première qui crée le QLabel et la seconde qui positionne l'alignement et ça on peut pas passer outre.

    Mais bon, te plonger directement sur cet exemple sans connaitre Qt je comprends que ça puisse effrayer. C'est pour ça que j'en ai écrit 4 autres (en plus du tuto mentionné plus haut) qui commencent avec des éléments plus simples.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    Ouais, trop d'options ... C'est pour ça que je préfère pygame. Certes il faut réinventer la roue à chaque fois, mais ça fait moins "bricolage" je trouve. Je veux dire, j'ai pas l'impression de planter un clou avec un marteau piqueur.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Je comprends. C'est vrai que Qt n'a pas pour objectif de faire des jeux à la base (et encore heureusement qu'il sait trouver l'intersection entre deux dessins sinon il fallait se la farcir mathématiquement) mais des IHM. Peut-être que le tuto de base n'aurait pas dû proposer cet exemple.

    J'ai une idée. Je ne connais pas PyGame. Pourquoi ne referais-tu pas la même chose avec PyGame? Tu pourrais intituler ça comme "suite au tuto Qt, je vous propose le même exemple avec PyGame pour vous montrer comment faire la même chose avec un outil dédié". A mon avis ça devrait plaire...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je ne suis pas d'accord quand on dit que PyQt5 est trop complexe parce qu'il fait des choses que Python sait déjà faire. Mais, bien sûr, dans ce cas, il faut choisir entre les fonctions du Python de base et de PyQt selon ce qu'elles apportent.

    Par exemple: la gestion des bases de données relationnelles:

    - les opérations non graphiques peuvent être réalisées avec avantage par le Python de base, parce qu'elles sont plus faciles à utiliser, et que les pilotes de Python supportent des fonctionnalités intéressantes comme d'ajouter des fonctions supplémentaires utilisables dans les requêtes SQL.

    - les opérations graphiques, par contre, doivent utiliser les possibilités de PyQt5 (QtSql et pilotes Qt5), ce qui permet, par exemple de consulter et de modifier des tables d'une base de données relationnelle avec un QTableView (grille de type tableur) relié directement aux données de la table. C'est très puissant et très élégant, et je ne vois comment faire ça autrement.

    Autre exemple: l'utilisation d'un thread. L'avantage de QThread au lieu de threading permet d'envoyer des signaux et des informations au graphique, ce qui permet, de mettre à jour ce graphique au fur et à mesure de l'avancement du thread. Là encore, je ne vois pas comment faire ça avec threading (à part de faire de l'héritage multiple). Avantage supplémentaire, le thread de QThread peut être arrêté "sauvagement" (terminate) quand c'est nécessaire, alors que ce n'est pas prévu avec threading.

    Autre exemple: utilisation de QProcess au lieu de subprocess, permet d'appeler un programme externe et de renvoyer sa sortie directement sur un QTextEdit.

    On pourrait citer d'autres exemples. En résumé, dès que ça concerne le graphique, les solutions PyQt sont beaucoup plus adaptées et plus performantes, même si elles existent déjà avec le Python de base. Mais si ça ne concerne pas le graphique, les solutions du Python de base sont en général plus facile à utiliser et quelquefois plus rapides.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Je comprends. C'est vrai que Qt n'a pas pour objectif de faire des jeux à la base (et encore heureusement qu'il sait trouver l'intersection entre deux dessins sinon il fallait se la farcir mathématiquement) mais des IHM. Peut-être que le tuto de base n'aurait pas dû proposer cet exemple.

    J'ai une idée. Je ne connais pas PyGame. Pourquoi ne referais-tu pas la même chose avec PyGame? Tu pourrais intituler ça comme "suite au tuto Qt, je vous propose le même exemple avec PyGame pour vous montrer comment faire la même chose avec un outil dédié". A mon avis ça devrait plaire...

    olalala ... c'est beaucoup demander. Comme j'ai dit plus haut, c'est réinventer la roue à chaque fois.
    mais je me suis quand même amusé à faire des class pour le slide et la jauge, voici un exemple si tu veux voir.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
     
    from pygame import *
     
    font.init()
     
    class Slider(Rect):
     
        def __init__(self,parent,rect):
            Rect.__init__(self,rect)
            self.surface          = parent
            self.button           = self.copy()
            self.button.width     = self.height
            self.focus            = False
            self.keyfocus         = False
            self.button_color     = Color('grey')
            self.line_left_color  = Color('CornflowerBlue')
            self.line_right_color = Color('black')
     
        def update(self,event):
            if event.type == MOUSEBUTTONDOWN and event.button == 1:
                if self.button.move(self.surface.get_abs_offset()).collidepoint(event.pos):
                    self.focus = True
     
            elif event.type == MOUSEBUTTONUP and event.button == 1:
                self.focus = False
     
            elif event.type == MOUSEMOTION and self.focus:
                self.button.move_ip(event.rel)
                self.button.clamp_ip(self)
                return True
     
            return
     
        def draw(self):
            draw.line(self.surface,self.line_left_color, self.midleft, self.button.midleft, 4)
            draw.line(self.surface,self.line_right_color, self.midright, self.button.midright, 4)
            self.surface.fill(self.button_color,self.button)
            draw.rect(self.surface,self.line_left_color//Color(2,2,2),self.button,1)
     
        @property
        def value(self):
            return (self.button.x-self.x)/(self.w-self.h)
     
        @value.setter
        def value(self,value):
            self.button.x = value*(self.w-self.h)+self.x
            self.button.clamp_ip(self)
     
     
    class Displayer(Rect):
     
        def __init__(self,parent,rect):
            Rect.__init__(self,rect)
            self.surface = parent
     
        def draw(self,text,font,color):
            text = font.render(text,1,color)
            rect = text.get_rect(center=self.center)
            self.surface.set_clip(self)
            self.surface.blit(text,rect)
            self.surface.set_clip()
     
     
     
     
    class SliderWithGauge:
     
        font = font.Font(font.get_default_font(),30)
     
        def update(self,event):
            self.slider.update(event)
     
        def draw(self):
            self.title.draw(self.title.text,self.font,self.slider.button_color)
            self.slider.draw()
            rect = self.gauge.copy()
            rect.w *= self.slider.value
            self.gauge.surface.fill(self.slider.line_left_color,rect)
            self.gauge.draw(self.gauge.form(),self.font,self.slider.button_color)
            draw.rect(self.gauge.surface,self.slider.line_right_color,self.gauge,2)
     
     
    class Canon:
     
        positionX = 0
        positionY = 980
     
        @staticmethod
        def draw():
            surface = Surface((300,300),SRCALPHA)
            draw.ellipse(surface,Color('black'),(100,100,100,100))
            draw.line(surface,Color('black'),(150,150),(240,150),26)
            draw.line(surface,Color('black'),(150,150),(250+50*force.slider.value,150),20)
            surface = transform.rotate(surface,angle.angle)        
            game_panel.blit(surface,surface.get_rect(center=(Canon.positionX,Canon.positionY)))
     
     
    scr = display.set_mode((1000,1000))
    ctrl_panel = scr.subsurface(500,10,490,980)
    game_panel = scr.subsurface(10,10,490,980)
     
    force = SliderWithGauge()
    force.title = Displayer(ctrl_panel,(45,50,390,40))
    force.title.text = "FORCE DU CANON"
    force.slider = Slider(ctrl_panel,(45,100,390,40))
    force.slider.button_color = Color('white')
    force.gauge = Displayer(ctrl_panel,(45,150,390,40))
    force.gauge.form = lambda:f'{int(force.slider.value*100)} %'
     
     
    Angle = type('',(SliderWithGauge,),{})
    angle = Angle()
    angle.min = 5
    angle.max = 70
    angle.title = Displayer(ctrl_panel,(45,250,390,40))
    angle.title.text = "ANGLE DU CANON"
    angle.slider = Slider(ctrl_panel,(45,300,390,40))
    angle.slider.button_color = Color('white')
    angle.gauge = Displayer(ctrl_panel,(45,350,390,40))
    angle.gauge.form = lambda:f'{int(angle.angle)}°'
    Angle.angle = property(lambda self:int(self.slider.value*(self.max-self.min)+self.min))
     
     
     
    timer = time.Clock()
    laps  = 40
    while True:
        laps += timer.tick()
        if laps >= 40:
            scr.fill(0)
            ctrl_panel.fill((100,100,100))
            game_panel.fill(-1)
            force.draw()
            angle.draw()
            Canon.draw()
            display.flip()
            laps = 0
        for ev in event.get():
            if ev.type == QUIT: break
            force.update(ev)
            angle.update(ev)
        else:
            continue
        break

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par josmiley Voir le message
    mais je me suis quand même amusé à faire des class pour le slide et la jauge, voici un exemple si tu veux voir.
    Ben... chez-moi avec Python3.8 (sous Linux) ça ne fonctionne pas.
    C'est la ligne draw.rect(self.gauge.surface,self.slider.line_right_color,self.gauge,width=2) qui est en erreur. Il me dit que draw() n'est pas présumé recevoir d'argument. Et si je la commente, j'ai la même chose sur draw.line(surface,Color('black'),(150,150),(240,150),width=26) et celle du dessous.

    Mais si je commente ces 3 lignes, j'ai un résultat. J'ai deux sliders "force" et "angle" avec une barre de progression, tout comme mon truc (mais malheureusement pas de canon vu qu'il doit être dans les lignes commentées). Mais c'est amusant
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    je vois, certains keywords ne sont pas supportés avec pygame 1.9(je suppose que c'est le problème, j'utilise pygame 2.0). Il suffit de retirer width= et ne laisser que la valeur dans les lignes concernées.
    je mets mon code à jour.

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par josmiley Voir le message
    je vois, certains keywords ne sont pas supportés avec pygame 1.9(je suppose que c'est le problème, j'utilise pygame 2.0).
    Effectivement j'étais avec pygame 1.9 (pourtant installé depuis le net via pip3 !!!)
    Citation Envoyé par josmiley Voir le message
    Il suffit de retirer width= et ne laisser que la valeur dans les lignes concernées.
    Mouais. Assez bizarre ce comportement vu que les appels de fonctions avec arguments nommés étaient déjà acceptés dans Python2. Mais effectivement en supprimant ça fonctionne. Merci de t'être investi dans ce minime exemple. Je pense que dourouc05 serait heureux si tu te lançais dans un tuto Pygame
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    'tite évolution du code pygame, on peut tirer sur les briques. Il se peut que la brique soit hors de portée, j'ai pas géré ça (pas envie pour le moment).
    Le code est vilain, mais c'était pour s'amuser.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    from pygame import *
    from math import cos,sin
    from random import randint
     
    font.init()
     
     
    class Slider(Rect):
     
        button_color     = Color('grey')
        line_left_color  = Color('CornflowerBlue')
        line_right_color = Color('black')
     
        def __init__(self,parent,rect):
            Rect.__init__(self,rect)
            self.surface          = parent
            self.button           = self.copy()
            self.button.width     = self.height
            self.focus            = False
            self.keyfocus         = False
     
        def update(self,event):
            if event.type == MOUSEBUTTONDOWN and event.button == 1:
                if self.button.move(self.surface.get_abs_offset()).collidepoint(event.pos):
                    self.focus = True
     
            elif event.type == MOUSEBUTTONUP and event.button == 1:
                self.focus = False
     
            elif event.type == MOUSEMOTION and self.focus:
                self.button.move_ip(event.rel)
                self.button.clamp_ip(self)
                return True
     
            return
     
        def draw(self):
            draw.line(self.surface,self.line_left_color, self.midleft, self.button.midleft, 4)
            draw.line(self.surface,self.line_right_color, self.midright, self.button.midright, 4)
            self.surface.fill(self.button_color,self.button)
            draw.rect(self.surface,self.line_left_color//Color(2,2,2),self.button,1)
     
        @property
        def value(self):
            return (self.button.x-self.x)/(self.w-self.h)
     
        @value.setter
        def value(self,value):
            self.button.x = value*(self.w-self.h)+self.x
            self.button.clamp_ip(self)
     
     
    class Displayer(Rect):
     
        def __init__(self,parent,rect):
            Rect.__init__(self,rect)
            self.surface = parent
     
        def draw(self,text,font,color):
            text = font.render(text,1,color)
            rect = text.get_rect(center=self.center)
            self.surface.set_clip(self)
            self.surface.blit(text,rect)
            self.surface.set_clip()
     
     
    class Button(Rect):
     
        bg_color   = Color('grey')
        color      = Color('black')
        text       = ''
     
        def __init__(self,parent,rect):
            Rect.__init__(self,rect)
            self.surface    = parent
            self.font       = font.Font(font.get_default_font(),int(self.h*.8))
     
        def update(self,event):
            if event.type == MOUSEBUTTONDOWN and event.button == 1:
                if self.move(self.surface.get_abs_offset()).collidepoint(event.pos):
                    return True
     
        def draw(self):
            self.surface.fill(self.bg_color,self)
            Displayer.draw(self,self.text,self.font,self.color)
     
     
    class SliderWithGauge:
     
        font = font.Font(font.get_default_font(),30)
     
        def update(self,event):
            self.slider.update(event)
     
        def draw(self):
            self.title.draw(self.title.text,self.font,self.slider.button_color)
            self.slider.draw()
            rect = self.gauge.copy()
            rect.w *= self.slider.value
            self.gauge.surface.fill(self.slider.line_left_color,rect)
            self.gauge.draw(self.gauge.form(),self.font,self.slider.button_color)
            draw.rect(self.gauge.surface,self.slider.line_right_color,self.gauge,2)
     
     
    class Canon:
     
        positionX = 0
        positionY = 980
     
        @staticmethod
        def draw():
            surface = Surface((300,300),SRCALPHA)
            draw.ellipse(surface,Color('black'),(100,100,100,100))
            draw.line(surface,Color('black'),(150,150),(240,150),26)
            draw.line(surface,Color('black'),(150,150),(250+50*jaugeForce.slider.value,150),20)
            surface = transform.rotate(surface,jaugeAngle.angle)        
            game_panel.blit(surface,surface.get_rect(center=(Canon.positionX,Canon.positionY)))
     
    class Obus(Rect):
     
        size = 8
        clk = time.Clock()
     
        def __init__(self):
            self.X = Canon.positionX
            self.Y = Canon.positionY
            Rect.__init__(self,0,0,Obus.size,Obus.size)
            self.center = self.X,self.Y
            self.vy = sin(0.017453292519943295*jaugeAngle.angle)*Obus.size
            self.vx = cos(0.017453292519943295*jaugeAngle.angle)*Obus.size
            self.laps = 0
     
        def update(self):
            self.laps += self.clk.tick()
            if self.laps >= 5:
                self.Y -= self.vy
                self.X += self.vx
                self.vy -= jaugeForce.force
                self.center = self.X,self.Y
                self.laps = 0
     
        def draw(self):
            game_panel.fill(0,self)
     
     
    class Cible(Rect):
     
        def __init__(self):
            Rect.__init__(self,(randint(50,800),randint(50,800),20,10))
            self.surface = game_panel
     
        def draw(self):
            self.surface.fill(0,self)
     
    # ~ **********init physique**********
    scr = display.set_mode((2000,1000))
    ctrl_panel = scr.subsurface(1500,10,490,980)
    game_panel = scr.subsurface(10,10,1490,980)
    timer = time.Clock()
     
    # ~ **********jaugle force et angle du canon**********
     
    Force = type('',(SliderWithGauge,),{})
    jaugeForce = Force()
    jaugeForce.min = 10
    jaugeForce.max = 30
    jaugeForce.title = Displayer(ctrl_panel,(45,50,390,40))
    jaugeForce.title.text = "FORCE DU CANON"
    jaugeForce.slider = Slider(ctrl_panel,(45,100,390,40))
    jaugeForce.slider.button_color = Color('white')
    jaugeForce.gauge = Displayer(ctrl_panel,(45,150,390,40))
    jaugeForce.gauge.form = lambda:f'+ {int(jaugeForce.slider.value*(jaugeForce.max/jaugeForce.min-1)*100)} %'
    Force.force = property(lambda self:1/(self.slider.value*(self.max-self.min)+self.min))
     
    Angle = type('',(SliderWithGauge,),{})
    jaugeAngle = Angle()
    jaugeAngle.min = 5
    jaugeAngle.max = 85
    jaugeAngle.title = Displayer(ctrl_panel,(45,250,390,40))
    jaugeAngle.title.text = "ANGLE DU CANON"
    jaugeAngle.slider = Slider(ctrl_panel,(45,300,390,40))
    jaugeAngle.slider.button_color = Color('white')
    jaugeAngle.gauge = Displayer(ctrl_panel,(45,350,390,40))
    jaugeAngle.gauge.form = lambda:f'{int(jaugeAngle.angle)}°'
    Angle.angle = property(lambda self:int(self.slider.value*(self.max-self.min)+self.min))
     
    # ~ **********bouton de tir et reset**********
    shootButton = Button(ctrl_panel,(45,550,390,50))
    shootButton.text = "SHOOT"
     
    restartButton = Button(ctrl_panel,(45,650,390,50))
    restartButton.text = "RESTART"
     
    # ~ **********differents textes**********
    ciblesatteintesMsg = Displayer(ctrl_panel,(45,750,390,50))
    nombreCiblesToucheesDsp = Displayer(ctrl_panel,(45,850,390,50))
     
    # ~ **********init variables**********
    class Globales:
     
        @staticmethod
        def reset():        
            Globales.font           = font.Font(font.get_default_font(),30)
            Globales.laps           = 40
            Globales.obus           = None
            Globales.touche         = 0
            Globales.munition        = 30
            jaugeAngle.slider.value = 0.5
            jaugeForce.slider.value = 0.5
            Globales.cible          = Cible()
     
    Globales.reset()
     
    while True:
        Globales.laps += timer.tick()
        # ~ *****gestion affichage*****
        if Globales.laps >= 40:
            if not Globales.obus and Globales.munition:
                shootButton.text = f'SHOOT {Globales.munition}'
            else:
                shootButton.text = '...'
            ctrl_panel.fill((100,100,100))
            game_panel.fill(-1)
            shootButton.draw()
            restartButton.draw()
            jaugeForce.draw()
            jaugeAngle.draw()
            Canon.draw()
            Globales.cible.draw()
            ciblesatteintesMsg.draw('CIBLES ATTEINTES',Globales.font,Color('lightgrey'))
            nombreCiblesToucheesDsp.draw(f'{Globales.touche}',Globales.font,Color('lightgrey'))
            if Globales.obus: Globales.obus.draw()
            display.flip()
            Globales.laps = 0
        # ~ *****logique*****
        for ev in event.get():
            if ev.type == QUIT: break
            if shootButton.update(ev) and Globales.munition:
                if not Globales.obus:
                    Globales.obus = Obus()
                    Globales.munition -= 1
            if restartButton.update(ev):
                Globales.reset()
            jaugeForce.update(ev)
            jaugeAngle.update(ev)
        else:
            if Globales.obus:
                Globales.obus.update()
                if not game_panel.get_rect().collidepoint(Globales.obus.center):
                    Globales.obus = None
                elif Globales.cible.colliderect(Globales.obus):
                    Globales.obus = None
                    Globales.touche += 1
                    Globales.cible = Cible()
            continue
        break

Discussions similaires

  1. snake pygame game over
    Par menna21 dans le forum Programmation multimédia/Jeux
    Réponses: 5
    Dernier message: 21/05/2018, 15h39
  2. Réponses: 29
    Dernier message: 10/01/2017, 19h06
  3. Game Over
    Par dourouc05 dans le forum Téléchargez
    Réponses: 0
    Dernier message: 12/11/2010, 21h01
  4. zone alarm game over : bloquage
    Par rare1 dans le forum Administration
    Réponses: 9
    Dernier message: 02/08/2006, 17h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo