Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de sauts avec la 2eme loi de Newton

Pygame

Sujet résolu
16 mai 2015 à 17:50:04

Bonjour,

Je me suis lancer dans ma première programmation d'un saut grâce aux lois de Newton mais je bloque déjà >_<

En fait je ne comprends pas très bien pourquoi mais j'ai l'impression que mon personnage se fiche royalement de la gravité …

Voici mes différentes parties:

# -*- coding: cp1252 -*-
import pygame
from math import sqrt, cos, sin
import time as time

class Newton():

    def __init__(self):

        pygame.init()
        self.g = 9.81
        self.m = 10

    def sauter(self,x,y,t,perso):

        if x == 0:
            a = 90

        else:
            a = 45

        y = y/self.m
        x = x/self.m
        v0 = sqrt(pow(x,2) + pow(y,2))
        vx = v0*cos(a)
        h = 0  #Je ne sais pas comment déterminer la hauteur h ici :/
        vy = self.g * t + v0* sin (a)
        y = 1/2*self.g*pow(t,2)+v0*(sin(a)) *t + h
        print y
        x = v0*cos(a) * t

        rect = perso.move(x,y)
        return rect
import pygame
from perso import *
import time as time



class moteur():
    def __init__(self):

        pygame.init()

        self.pers = perso()
        taille_x = 1000
        taille_y = 1000
        self.fenetre = pygame.display.set_mode((taille_x,taille_y),pygame.RESIZABLE)
        self.decor = pygame.sprite.Group()


    def add(self, typ,coord):

        if typ == "mur":
            
            self.mur = pygame.sprite.Sprite()
            self.mur.image = pygame.image.load("Images/Decor/Objets/mur.png").convert_alpha()
            self.mur.rect = self.mur.image.get_rect()
            self.mur.rect = self.mur.rect.move(coord)
            self.decor.add(self.mur)

        if typ == "perso":
            princi = self.pers.princi(coord)
            

    def add_fond(self,fond):
        self.fond = pygame.image.load(fond).convert()

    def partie(self):
        boucle = True

        fin = time.time() + 15

        x = 1
        y = -1

        while boucle:
            pygame.time.Clock().tick(30)
            debut = time.time()
            t = fin - debut
            if fin - debut > 0:
                fin = fin - 1
                self.pers.avancer((x,y),"princi")
                self.pers.saut(x,y,t,"princi")

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    boucle = False
            

                
            self.fenetre.blit(self.fond,(0,0))
            self.decor.draw(self.fenetre)
            self.pers.afficher(self.fenetre)
            pygame.display.flip()

            
            
            
            

        

        
import pygame
from Newton import * 

class perso():

    def __init__(self):
        pygame.init()
        self.allie = pygame.sprite.Group()
        self.ennemi = pygame.sprite.Group()
        self.gravitee = Newton()

    def princi(self,coord):
    
        self.perso = pygame.sprite.Sprite()
        self.perso.image = pygame.image.load("Images/Mob/Perso/dk_bas.png").convert_alpha()
        self.perso.rect = self.perso.image.get_rect()
        self.perso.rect = self.perso.rect.move(coord)
        self.allie.add(self.perso)

    def avancer(self,coord,typ):
        
        if typ == "princi":
            self.perso.rect = self.perso.rect.move(coord)
            
    def saut(self,x,y,t,perso):

        if perso == "princi":
            self.perso.rect = self.gravitee.sauter(x,y,t,self.perso.rect)
            
        
        

    def afficher(self,fen):

        try:
            self.allie.draw(fen)
        except AttributeError:
            pass


        

Quelqu'un pourrait m'aider a corriger mes calculs ?

Merci d'avance pour votre aide :)





  • Partager sur Facebook
  • Partager sur Twitter
16 mai 2015 à 23:52:54

Que se passe-t-il exactement ? Est-ce que tu as une idée de la partie du code qui fonctionne mal ?

Essaye de faire ça avant ton code :

a *= (180/pi)

Ca convertira a en radians, ça peut expliquer certains bugs :)

  • Partager sur Facebook
  • Partager sur Twitter
17 mai 2015 à 10:30:51

Salut, BunshinKage ,

Oui moi aussi j'ai pensé aux conversions des angles hier, j'ai aussi modifier ma variable t car elle devenait de plus en plus petite au lieu de grandir, cependant j'ai l'impression que le saut n'a toujours pas la trajectoire d'une parabole :euh:

Voici les fichiers avec les modifs:

# -*- coding: cp1252 -*-
import pygame
from math import sqrt, cos, sin
import time as time

class Newton():

    def __init__(self):

        pygame.init()
        self.g = 9.81
        self.m = 10

    def sauter(self,x,y,t,perso):

        pi = 3.141592654

        if x == 0:
            a = 90*pi/180

        else:
            a = 45*pi/180

        y = y/self.m
        x = x/self.m
        v0 = sqrt(pow(x,2) + pow(y,2))
        print v0-(0.5*self.g*pow(t,2))
        vx = v0*cos(a)
        h = 0  #Je ne sais pas comment déterminer la hauteur h ici :/
        vy = self.g * t + v0* sin (a)
        y = 0.5*self.g*pow(t,2)+v0*(sin(a)) *t + h
        x = v0*cos(a) * t

        rect = perso.move(x,y)
        return rect

        
import pygame
from perso import *
import time as time



class moteur():
    def __init__(self):

        pygame.init()

        self.pers = perso()
        taille_x = 1000
        taille_y = 1000
        self.fenetre = pygame.display.set_mode((taille_x,taille_y),pygame.RESIZABLE)
        self.decor = pygame.sprite.Group()


    def add(self, typ,coord):

        if typ == "mur":
            
            self.mur = pygame.sprite.Sprite()
            self.mur.image = pygame.image.load("Images/Decor/Objets/mur.png").convert_alpha()
            self.mur.rect = self.mur.image.get_rect()
            self.mur.rect = self.mur.rect.move(coord)
            self.decor.add(self.mur)

        if typ == "perso":
            princi = self.pers.princi(coord)
            

    def add_fond(self,fond):
        self.fond = pygame.image.load(fond).convert()

    def partie(self):
        boucle = True

        debut = time.time()
        y = 100
        pygame.key.set_repeat(500,30)
        t = 0
        action = "tomber"
        while boucle:
            pygame.time.Clock().tick(30)

            x = 1
            if action == "tomber":
                self.pers.saut(x,y,t,"princi")
                fin = time.time()
                t = fin - debut

                
            if t >= 2:
                t = 0
                action = "rien"
            

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    boucle = False

                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        x = -10

            self.pers.avancer((x,0),"princi")

                
            self.fenetre.blit(self.fond,(0,0))
            self.decor.draw(self.fenetre)
            self.pers.afficher(self.fenetre)
            pygame.display.flip()

            
            
            
            

        

        

tu aurais une idée d'ou peut venir le reste du problème ?


  • Partager sur Facebook
  • Partager sur Twitter
17 mai 2015 à 14:12:44

c'est bon j'ai corrigé :

# -*- coding: cp1252 -*-
import pygame
from math import sqrt, cos, sin
import time as time

class Newton():

    def __init__(self):

        pygame.init()
        self.g = 9.81
        self.m = 10

    def sauter(self,x,y,t,perso):

        pi = 3.141592654

        if x == 0:
            a = 90*pi/180

        else:
            a = 45*pi/180

        y = y/self.m
        x = x/self.m
        v0 = sqrt(pow(x,2) + pow(y,2))
        h = 0  #Je ne sais pas comment déterminer la hauteur h ici :/
        vy = self.g * t + v0* sin (a)
        y = -1*(vy- 0.5*self.g*pow(t,2))
        x = v0*cos(a) * t

        rect = perso.move(x,y)
        return rect

        

Cependant je ne comprends pas pourquoi mon calcul de y était erroné (j'ai l'impression que c'était la trajectoire d'une chute libre ...)

Quelqu'un pour m'expliquer ?

-
Edité par Marty_and_Doc 17 mai 2015 à 14:14:22

  • Partager sur Facebook
  • Partager sur Twitter
20 mai 2015 à 15:51:19

Tu n'aurais pas moyen de tout mettre dans un meme fichier, qu'on n'ai quà faire un copier coller pour le tester ?

Et si tu pouvais commenter ton code ça serrait sympa, car c'est propre, mais même si tu as utilisé des noms explicites, on doit jouer aux devinettes pour savoir à quoi servent les parties de ton programme. et ça ralenti beaucoup notre compréhension de ton programme

-
Edité par fauquette 20 mai 2015 à 15:53:06

  • Partager sur Facebook
  • Partager sur Twitter
20 mai 2015 à 16:27:08

Salut,

Si je regarde un peu ton code, la ligne qui me paraît suspecte est celle-ci: v0 = sqrt(pow(x,2) + pow(y,2)). Car les unités ne sont pas bonne :o

  • Partager sur Facebook
  • Partager sur Twitter
Précepte: Le mieux est l'ennemi du bien
20 mai 2015 à 16:50:04

Salut fauquette ,

Si tu veux essayer le code voici un fichier .rar contenant tout le code (normalement) fonctionnel:

http://www.cjoint.com/data3/3EuqZ2rj4WI.htm

Sinon Olygrim pourrait tu m'aider à corriger le problème d'unité stp ? (il faut peut être que je multiplie y par 10 ou que je ne le modifie pas ?)

-
Edité par Marty_and_Doc 20 mai 2015 à 16:52:09

  • Partager sur Facebook
  • Partager sur Twitter
20 mai 2015 à 17:26:12

Non, c'est unité dans le sens metre/seconde. Là ta vitesse est exprimée en mètre ;). Il faut diviser par dt je pense. Mais normalement v0 est une condition initiale donc il n'y as pas de calcul dessus (comme ta variable h que tu n'arrive pas à déterminer).
  • Partager sur Facebook
  • Partager sur Twitter
Précepte: Le mieux est l'ennemi du bien
20 mai 2015 à 17:59:18

Ouf, j'ai compris ton erreur de calcule ! En fait tu calcules la même chose 2 fois

vy = self.g * t + v0* sin (a)
y = -1*(vy- 0.5*self.g*pow(t,2))

Tu calcules vy en intégrant le PFD (la loi de Sir Newton). Donc tu calcules Vy pour chaque instant t.

Alors que dans la formule

y = -1*(vy- 0.5*self.g*pow(t,2))

Vy c'est la vitesse initiale suivant l'axe (Oy)

conclusion, remplace vy par sa valeur initiale

vy = self.g * t + v0 * sin(a)#pour tout t
vy =  v0 * sin(a)#celle dont tu as vraiment besoins



  • Partager sur Facebook
  • Partager sur Twitter
20 mai 2015 à 18:39:13

Merci beaucoup pour votre aide :)

Je n'ai appris ces lois qu'il n'y a quelques mois donc je ne m'y connait pas trop sur le sujet ...

Quoiqu'il en soit je vais mettre de ce pas en application vos conseils :)

  • Partager sur Facebook
  • Partager sur Twitter
20 mai 2015 à 20:26:01

De rien, le programmer est la meilleur façon de comprendre les cours de physique de terminale ;)
  • Partager sur Facebook
  • Partager sur Twitter