Demande renseignement sur python

a marqué ce sujet comme résolu.

Bonjour, je cherche depuis hier soir sur le net à comment copier une partie du fond d’écran avec python et pygame.

Si vous avez une solution ?

+0 -0

Salut,

Je ne connais pas assez pygame, mais je ne suis pas sûr que c’est de ce côté là que tu trouveras une solution.

Il te faut trouver une bibliothèque capable de communiquer avec l’environnement de bureau pour connaître ce qui est extérieur à ta fenêtre.

Ta question est beaucoup trop vaste.

Explique précisément ce que tu veux faire, sur quel système et ce que tu as tenté.
Ça fait 3 informations, je suppose que des captures d’écrans aideraient à bien comprendre, un code source aussi.

+1 -0

bonsoir, Je parles du fond d’écran d’un jeu que je fais, une image quoi, et avant d’y coller un sprite j’ai besoin de copier la zone exacte (rect) où va se coller le sprite.

Je n’arrives pas à trouver comment et le site officiel demande de s’inscrire je préfère pas.

Dans mon cas, il ne s’agit pas de travailler sur le systeme, mais juste connaître la fonction de copie d’un rect du fond d’écran, ou d’une image en général, par exemple dans pascal/delphi on fait un truc du genre :

monRect=image.copyRect(X1,Y1,X2,Y2)

J’ai vu dans pygame qu’il existait ceci : monImage.rect_copy()

Mais il y a pas de parametres de positions, donc ça copie tout le rect d’une image, et moi je ne veux pas copier tout le fond, mais juste un rect précis qui correspond à la taille et la position du sprite sur le fond.

D’ailleurs si j’essaie de faire cette instruction avec l’image, en y mettant le rect du sprite :

robot_back=fond.rect_copy(robot_pos) robot_pos est le rect du sprite.

robot_back va devenir la zone rect que je veux de l’image "fond" (fond est la variable image)

ça me dit que cet objet n’a pas de fonction rect_copy.

Mais là c’était un test pour voir sil l’acceptait, car je ne sais pas comment faire.

J’ai tenté aussi ça : robot_back=fond.copy(robot_pos)

Mais ça me dit que copy() ne prend pas d’arguments.

+0 -0

Ah cool, merci je vais voir !

with an interior area removed

Je comprend pas ça ci-dessus.

Je viens d’essayer ça : robot_back=pygame.transform.chop(fond,robot_pos)

ça me saoule, j’ai l’impression que ça me donne un rect au lieu d’une image de la taille du rect

Je sais pas comment l’utiliser :

Je voudrais à la fin de la boucle du jeu, faire une copie de la zone rect de l’image de fond où se trouve le sprite, puis remettre cette copie du fond à sa place par un blit() mais en début de boucle.

Je voudrais faire ça :

1) début de boucle : fenetre.blit(macopie,rectangle du sprite)

2) Traitement de boucle

3) Copier la zone rect_sprite du fond écran où je vais mettre le sprite.

4) Placer le sprite sur le fond à l’emplacement où j’ai fait ma copie du fond.

5) fin de boucle

+0 -0

Je viens de faire un test :

rback=pygame.transform.chop(fond,robot_pos) pygame.image.save(rback, 'test-crop.png’)

Pygame me crée une image png dans le dossier courant, et cette image est supposée etre de la taille donnée par robot_pos qui est un rect du sprite, mais au lieu de me créer une image du fond de la taille du sprite ça me donne une image du fond totale, le fond de l’ecran quoi et non la zone indiquée par le rect du sprite.

Merci Entwanne ! tu m’as trouvé la fonction que je voulais mais je ne sais pas l’utiliser peut-etre, en tous cas ça me crée une grande image au lieu de me créer une petite image dont la taille est indiquée par robot_pos (un rect)

+0 -0

Bonjour la doc de Pygame déconseille chop pour faire une copie d’image te préconise d’utiliser blit :

If you like to receive the inner rectangle, the blit is a much better setup.

import pygame as pg

def crop(orig_surf, pos, size): 
     """ orig_surf : pg.Surface --> image d'origine 
         size : (sx, sy) --> taille de la zone copier 
         pos : (px, py) --> origine de la zone a copier depuis orig_surf""" 
     #Création de la surface vierge , le flag sert à préserver la transparence
     dest_surf = pg.Surface(size, flags=pg.SRCALPHA) 
     #Copie de la zone sur la surface vierge 
     (sx, sy), (px, py) = size, pos 
     dest_rect = (px, py, px+sx, py+sy)  
     dest_surf.blit(orig_surf, (0,0), dest_rect) 
     return dest_surf 

# si screen est l'ecran d'affichage et surf la surface contenant le fond de jeu.
copie = crop(surf, (600,600), (32,32)) # copie un carré de 32px en position 600,600
# pleins de choses à faires, qui vont masquer cette zone.
screen.blit(copie, (600,600)) # je restore la zone

Ce code devrait fonctionner , mais faire un blit de toute la surface surf et des autres sprites ne sera pas forcement lent, j’avais testé box2D avec des centaines de formes, sur mon vieux I5 ca faisait encore plus de 30fps.

+1 -0

Merci beaucoup Kayou !!! C’est exactement ce qu’il me faut !

Je vous suis franchement reconnaissant de votre aide à tous deux, je vous donnerais un lien pour télécharger le jeu dés que je l’aurais terminé ;) Il s’agit d’un robot que l’on dirige contre d’autres robots et sa première mission est de se sauver de l’usine où il a été construit.

De ce qu’a posté Kayou, J’ai cette ligne qui a 3 paramètres :

def crop(orig_surf, pos, size):

Alors que moi j’ai un rect à la place : (le rect robot_pos)

robot_back=crop(fond,robot_pos)

Comment je peux faire pour que ça marche ? La position de mon rect c’est le point central(xy) du rect. donc c’est pas son coin haut/gauche. le message d’erreur c’est qu’il me manque le paramètre "size" mais c’est normal puisque dans le rect il est inclu. Le problème c’est que la fonction crop() demande ce paramètre.

Je croyais avoir trouvé la solution pour convertir mon rect en x,y et size : ……………………… robot_back=crop(fond,robot_pos.pos,robot_pos.size)

j’avais mis rect.pos et rect.size ….. donc robot_pos.pos et robot_pos.size

Mais python dit que le rect n’a pas le terme pos dans ses valeurs (il ne connait pas)

Il faudrait peut-être que je modifie la fonction crop pour quelle fonctionne avec un rect comme parametre mais je sais pas comment faire.

L’autre choix que j’ai c’est de me débrouiller pour lui fournir ce qu’elle demande : la position et la taille, au lieu de lui donner le rect. ……. Mais je vois pas comment :/ …….. Moi ce que je connais c’est le centre du rect et sa taille.

La fonction crop() en fait retourne une surface qu’elle crée avec ça :

dest_surf = piggame.Surface(size, flags=pg.SRCALPHA)

J’ai bossé toute la nuit pour essayer d’adapter mon rect à la fonction fournie par Kayou

j’ai trouvé ça :

def crop(orig_surf, rect, size): 
     """ orig_surf : pg.Surface --> image d'origine 
         size : (sx, sy) --> taille de la zone copier 
         pos : (px, py) --> origine de la zone a copier depuis orig_surf""" 
     #Création de la surface vierge , le flag sert à préserver la transparence
     surf = pygame.Surface(size, flags=pygame.SRCALPHA) 
     #Copie de la zone sur la surface vierge
     surf.blit(orig_surf, rect) 
     return surf 

Et en faisant ça :

copie dans robot_back la zone de l’image "fond" indiquée par le rectangle robot_pos et de taille 51x51.

robot_back=crop(fond,robot_pos,(51,51)) 

ça donne pas de message d’erreur mais ça na pas d’effets. En si ça me crée une surface transparente vide qui a pour nom robot_back et de taille 51x51, mais ce que je voudrais obtenir c’est la copie du fond de taille 51x51 à la position donnée par rect donc par robot_pos.

d’après ce que je comprend, pour copier une zone, il faut utiliser la méthode blit() qui appartient à la surface de destination, et qui a besoin pour ça d’une surface source et d’un rect. donc si je fais théoriquement ça :

robot_back=crop(fond,robot_pos,(51,51))
robot_back.blit(fond,robot_pos)

C’est sensé me faire une copie vers robot_back mais ça marche pas.

+0 -0

Tu n’es pas loin du résultat voulu ;)

1 -Remplacer size et pos dans l’appel de fonction par un Rect :

def crop(orig_surf, rect): 
     """ orig_surf : pygame.Surface --> image d'origine 
         rect : pygame.Rect --> zone à copier """ 
     #Création de la surface vierge , le flag sert à préserver la transparence
     surf = pygame.Surface(rect.size, flags=pygame.SRCALPHA) 
     #Copie de la zone sur la surface vierge
     surf.blit(orig_surf, rect) 
     return surf 

2 - Ensuite tu as inversé les objets dans l’appel de blit :

robot_back=crop(fond,robot_pos) #il n'y a plus besoin de size qui est deja dans le Rect
fond.blit(robot_back,robot_pos) #il faut "blitter" robot_back sur fond et pas l'inverse
+0 -0

Merci beaucoup Kayou !!! ;)

Je vais rectifier mon code.

EDIT : je fais ça, car avant de dessiner robot_pos, je sauve le fond dans robot_back (back comme backup).

            # ici sauver le fond de la nouvelle position
            robot_back.blit(fond,robot_pos)
            
            # Donner la nouvelle position au robot.
            robot_pos=robot_pos.move(robot_VX,robot_VY)

Mais pour le moment ça ne marche pas. (pas d’effets)

+0 -0

tu devrais inverser les 2 lignes, avec ce code tu sauves le fond dans robot_back mais à son ancienne position, en gros tu devrais avoir:

#restaurer le fond à l'ancienne position
fond.blit(robot_back,robot_pos)

#Calculer (pas Donner) la nouvelle position au robot.
robot_pos=robot_pos.move(robot_VX,robot_VY)

# ici sauver le fond de la nouvelle position
robot_back.blit(fond,robot_pos)

Nota : Ce code suppose que robot_back et robot_pos existent avant le debut de la boucle de jeu.

Merci ! Oui ils existent avant la boucle.

EDIT : toujours pas, même resultat, robot_pos laisse sa trainée derriere lui, quelque soit la direction.

Longtemps avant la boucle, je fais ça :

# ici sauver le fond de la position de debut
rect_back=robot_pos
robot_back=crop(fond,robot_pos)
# faire une preuve tangible de la sauvegarde
pygame.image.save(robot_back, 'test-crop.png')
+0 -0

Résolu !!!!!!!!!!!!!!!!!!!!!!!!!!

Merci beaucoup à tous ceux qui m’ont aidé, je suis super content ;)

Un double merci à Kayou sur ce coup ;) Je vais enfin pouvoir avancer plus loin dans mon projet.

+0 -0

Salut ;)

Quelqu’un aurait une idée comment pivoter une image sans qu’elle se déplace ?

Je sais faire pivoter, et je sais faire déplacer, mais quand je fais pivoter vers la droite, l’image pivote bien mais se déplace en même temps vers la dernière direction verticale qui a été faite.

pourtant je lui donne un centre :

robot_pos=myrobot.get_rect(center=(robot_VX,robot_VY))

robot_VX et robot_VY sont modifiés seulement par les touches haut et bas, donc je comprend pas que l’image se déplace quand je pivote à droite.

+0 -0

Je viens de comprendre pour le déplacement pendant la rotation, c’est que si j’appuie pas sur "haut" ni sur "bas" il faut que deltaY soit à 0. ça regle tout ;)

Résolu !!!!!!!!!!!!!!!!!!!!! ;)

+0 -0

Bonjour, je fais appel à nouveau à vos compétences en pygame et programmation car je m’en sors pas, bien que j’ai pas mal avancé depuis la dernière fois ;)

J’ai ces trois instructions :

radian=-(degre+90)*(pi/180)

robot_pos1=myrobot_turn.get_rect(center=(robot_VX,robot_VY))

robot_pos=NewPos(robot_pos,radian,robot_VT)

La première calcule un angle radian à partir du degré d’orientation de mon image.

La deuxième recupère le rect de l’image pivotée dans le programme.

La troisième appelle la fonction Newpos et lui fournit le rect de mon image, le radian, et la vitesse de l’image.

Mon problème est que je suis partagé dans le choix entre la deuxième et la troisième.

1) Si j’utilise que la deuxième, l’image se pivote sur son bon centre, mais ne peut pas être dirigée dans le sens de son orientation.

2) Si j’utilise que la troisième, l’image se pivote et peut se diriger dans le sens de son orientation. MAIS elle pivote sur un centre légèrement décalé de la normale, et ça voit trop, l’image gigote trop.

Moi je voudrais que ça fasse les deux, c’est à dire qu’elle puisse pivoter sur son bon centre, et quelle soit dirigeable dans le sens de son orientation.

La fonction Newpos() :

def NewPos(rect,angle,z):
    (dx,dy) = (z*math.cos(angle),z*math.sin(angle))
    return rect.move(dx,dy
```)
+0 -0

Je pense que le décalage du centre de rotation doit être dû au changement de dimensions que le rect du robot subit lors des rotations, un rect est toujours un rectangle dons les cotés sont horizontaux et verticaux, par exemple si une image carrée de n pixels est tournée de 45°, le centre va se décaler de (±n2cos(45),±n2sin(45))( \pm \frac n 2 \cdot cos(45), \pm \frac n 2 \cdot sin(45)) suivant les axes x et y.

Il faut donc tenir compte de la rotation dans le calcul du déplacement, un dessin et un peu de trigo te permettraient de visualiser cela assez facilement. (ce que je n’ai pas fait, donc j’ai pu me tromper un peu ;) mais l’idée est là)

oui je pense que tu as complètement raison, mais même si j’arrivais à le visualiser, je saurais pas corriger car je suis nul en math, j’ai toujours eu zéro en math à l’école :/ en programmation je suis autodidacte et j’ai progressé en math depuis, mais la trigo c’est trop élevé pour moi. Ce qui m’enerve c’est que y a pas de tuto de pygame qui explique en français des trucs qu’on trouve dans tous les jeux, comme presser deux touches en même temps, et la différence entre keypressed et onkeydown, la copie d’une portion de l’ecran, et d’autres trucs du genre, enfin ce qu’il y a de base dans les jeux quoi. Tous les tutos en français que j’ai vu sont simplistes, et ils utilisent tous la même technique de colorier le fond d’ecran avant d’afficher les sprites, c’est debile comme methode. J’essaie de chercher dans les sites anglais mais je comprend rien, des fois oui. Je suis en train de faire mon jeu avec pygame mais je crois qu’elle est pas terrible en fait comme librairie, pour faire un truc basique d’un jeu elle complique les choses, depuis le début je galère pour chaque étape, c’est preuve que c’est pas top pour les jeux, car je sais très bien tout ce qui compose un jeu quelqu’il soit, je sais fabriquer des jeux de tous types, sauf que je sais pas me servir de pygame. Avant je faisais mes jeux en delphi 1 et j’avais pas tous les problèmes que j’ai avec pygame, enfin, je m’entête à l’apprendre pour voir ce que je peux faire de bien avec, mais je pense qu’après ce jeu, j’utiliserais une autre façon de faire. En tous cas, merci de ton aide ! ;)

PS: dans delphi on peut travailler sur des surfaces d’écran comme dans pygame, sauf que c’est logiciel, pas d’accélération, à moins d’utiliser delphix, qui a ete abandonnée depuis, mais la plupart des jeux que je fais ont pas besoin de l’accélération matérielle et ça se passe bien, d’ailleurs je crois (pas sûr) que c’est l’auteur même de pygame qui a écrit sur un wiki pygame qu’il valait mieux utiliser l’affichage logiciel avec optimisation plutot que d’utiliser l’accélération matérielle.lien :

EDIT : Hier et aujourd’hui j’ai vu dans plusieurs sites anglais l’utilisation de pygame, et plein d’utilisateurs avaient des problèmes pour utiliser pygame pour faire un jeu basique, le problème ne vient donc pas du fait que les docs soient en anglais, comme on pourrait le penser.

RE-EDIT : Info pour ceux qui sauraient pas et qui passeraient par là, la différence entre keypressed et keydown : Le premier (keypressed) détecte le fait qu’une touche soit dans l’état "appuyé" (comme un niveau bas en logique) tandis que le deuxième (keydown) détecte le fait qu’une touche devienne "appuyée", donc quand elle passe de l’état normal vers l’état "appuyé" (comme un front descendant en logique). Donc si vous avez à détecter deux touches appuyées en même temps, il faut utiliser "keypressed".

Mon problème : C’est que je sais pas comment corriger le point central du rect de l’image sans abimer les points qui font que l’on peut diriger l’image dans le sens de l’orientation. Et ça pygame ne l’explique pas, comment diriger une image dans le sens de son orientation, c’est un des cas pour lequel je dis qu’elle est trop simpliste, et sa vue simpliste rend les choses difficiles.

+0 -0

Dans mon programme, j’utilise random, et en pressant une touche pour faire un randint(1,8) j’appuie 50 fois et pas un seul chiffre 8 ! pourtant je l’ai initialisé avec random.seed()

Tiens je sais pas si vous le savez déjà ou pas, mais la doc de python informe sur :

Le Mersenne Twister est l’un des générateurs de nombres aléatoires les plus largement testés qui existent. Cependant, étant complètement déterministe, il n’est pas adapté à tous les usages et est totalement inadapté à des fins cryptographiques.

Les fonctions fournies par ce module dépendent en réalité de méthodes d’une instance cachée de la classe random.Random. Vous pouvez créer vos propres instances de Random pour obtenir des générateurs sans états partagés.

La classe Random peut également être sous-classée si vous voulez utiliser un générateur de base différent, de votre propre conception.

Si ça peut servir à quelqu’un.

+0 -0

Si tu dois tourner tes surface et que tu ne veux pas calculer les décalages, place tes surfaces sur l’ecran en fonction de leurs centres et non de leu coin supérieur gauche (il faut quand même que le centre de rotation soit aussi le centre du Rect pour que ca fonctionne):

# rob_pos est le Rect associée au robot
# pour deplacer le robot on bouge son centre
rob_pos.centre = (x, y)
fenetre.blit(robot, rob_pos)

# tour de boucle suivant

# le robot subit une rotation
# je crée une nouvelle Surface pour éviter de dégrader l'image apres plusieurs rot
rot_bot = pg.transform.rotate(robot, angle)
# je prend son Rect qui n'a plus la même taille que celui de robot
rot_pos = rot_bot.get_rect()
# je mets son centre au même point que le robot "droit"
rot_pos.centre = rob_pos.centre
fenetre.blit(rot_bot, rot_pos) 

Tout ca fonctionne sans calcul, mais il faut toujours positionner le robot par son centre et penser que la taille de robot_back (pour restaurer le fond) va aussi changer, si la boucle est bien faite ca ne devrait pas poser de problèmes.

La doc de Pygame est plutôt bien faite et complète par rapport à d’autre modules (Voir la SFML lire la doc C++ pour avoir des infos à jour…), mais c’est vrai que c’est tout en anglais (comme beaucoup de doc). De plus Pygame est stable on a pas revoir une partie du code avec les changement version (SFML …..).

Pygame te fournis les briques de base, donc plutôt que tout réinventer à chaque fois code des fonctions basique qui te simplifient la vie et rassemble dans un module dédié que tu utiliseras dans tes jeux, si tu reprends le morceau de code ci dessus dans ta boucle de jeu (ainsi que le reste de ta logique de jeu) tu va rendre ton code difficile à lire même pour toi.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte