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

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 contient une version Python3/Qt5 et une version Python3/Qt6.

La suite sera Face au mur.
Avatar de josmiley
Membre éprouvé https://www.developpez.com
Le 22/08/2021 à 14:45
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
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
Avatar de Sve@r
Expert éminent sénior https://www.developpez.com
Le 20/08/2021 à 20:17
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 ?
Avatar de josmiley
Membre éprouvé https://www.developpez.com
Le 21/08/2021 à 20:54
Je ne connais pas pyQt mais ça me paraît beaucoup 600 lignes de code.
Avatar de Sve@r
Expert éminent sénior https://www.developpez.com
Le 21/08/2021 à 22:16
Avatar de josmiley
Membre éprouvé https://www.developpez.com
Le 21/08/2021 à 23:27
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.
Avatar de Sve@r
Expert éminent sénior https://www.developpez.com
Le 22/08/2021 à 8:57
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...
Avatar de Sve@r
Expert éminent sénior https://www.developpez.com
Le 22/08/2021 à 19:18
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
Avatar de josmiley
Membre éprouvé https://www.developpez.com
Le 22/08/2021 à 19:41
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.
Avatar de Sve@r
Expert éminent sénior https://www.developpez.com
Le 22/08/2021 à 20:04
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
Developpez.com décline toute responsabilité quant à l'utilisation des différents éléments téléchargés.