Téléchargé 7 fois
Vote des utilisateurs
0
0
Détails
Licence : LGPL
Mise en ligne le 9 mars 2024
Plate-formes :
Linux, Mac, Windows
Langue : Français
Référencé dans
Navigation
Game Over.
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. Ce qui donne toutefois une gestion de signaux assez conséquente mais on arrive à un jeu presque fonctionnel.
Cet exemple est disponible dans les versions PyQt5, PyQt6 et PySide6.
La suite sera Face au mur.
Cet exemple est disponible dans les versions PyQt5, PyQt6 et PySide6.
La suite sera Face au mur.
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 |
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 |
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 ?
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 ?
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
Cette syntaxe déjà s'est vachement allégée sous Qt5 car elle s'écrit maintenant...
... 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.
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 |
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 |
1 2 | btn=QPushButton(...) btn.clicked[bool].connect(autreWidget.truc) |
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.
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.
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...
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...
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
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
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.
je mets mon code à jour.
Effectivement j'étais avec pygame 1.9 (pourtant installé depuis le net via pip3 !!!)
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
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
Developpez.com décline toute responsabilité quant à l'utilisation des différents éléments téléchargés.