Coder le jeu Geometry dash en python
Résolu/FerméBonjour bonjour !!
Je fais un geometry dash pour l'école et je suis de ce qu'il y a de plus débutant.
J'ai pour l'instant mon personnage qui se déplace et qui saute. L'étape suivant est de créer des plateformes dans l'air et des obstacles ; ainsi que de faire défiler le background. Je commence par les obstacles, et les plateformes mais j'arrive pas a les connecter a mon code.
Ma question est la suivante ; est-ce que quelqu'un aurait un lien vers un tutoriel de plateforme et d'obstacles que je pourrai facilement adapter et comprendre pour mon code ?
Merci
- Geometry dash python
- Citizen code python avis - Accueil - Outils
- Ce programme est écrit en python ✓ - Forum Python
- Python est introuvable. exúcutez sans argument pour procúder ó l ✓ - Forum Python
- Python generator - Télécharger - Sécurité
6 réponses
Modifié le 1 mars 2023 à 12:51
Bonjour,
Sans voir ton code, difficile de réponder.
Mais en faisant une petite recherche google, j'ai trouvé cette vidéo qui me paraît répondre exactement à ta question, et la description fournit le lien vers le code.
Le code est basé sur ursina.
Bonne chance
3 mars 2023 à 12:57
Bonjour,
Si tu ne veux pas utiliser ursina et que tu préfère utiliser pygame, tu peux regarder ce dépôt.
Bonne chance
Salut.
Le truc, c'est que pour faire même un simple jeu, il faut beaucoup se familiariser avec la bibliothèque dont on veut se servir, donc en faisant des tas de tests, et bien évidemment cela prend du temps, faire un jeu avec obstacles et plateformes demande beaucoup de temps, que ce soit sur la mécanique du jeu ou sur la réflexion, stratégie du jeu, conception des maps, etc. Sans compter qu'évidemment il faut maitriser les concepts primaires de python, y compris l'objet, faire un jeu complexe sans modèle objet est pour moi mission impossible, enfin, c'est faisable mais au détriment de la lisibilité et organisation du code, surtout qu'en python tout est objet.
Faire un jeu avec pygame, c'est utiliser des sprites, un sprite pygame doit avoir comme attributs image et rect, donc player, obstacles, plateformes et toutes entités doivent être des sprites.
Je ne sais ce que tu nommes par "geometry dash", faire apparaitre des obstacles que le joueur doit éviter ou collecter, ce n'est pas difficile (enfin pour si peu que l'on connaisse un peu pygame).
.
Fais à la va vite selon ton code.
import pygame import random SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_COLOR = 120, 170, 255 FLOOR_Y = 550 PLAYER_COLOR = 255, 255, 255 EVENT_OBSTACLE_SPAWN = pygame.USEREVENT + 1 FPS = 60 class Floor(pygame.sprite.Sprite): def __init__(self, y): super().__init__() self.image = pygame.Surface((SCREEN_RECT.w, 100)) self.image.fill((100, 200, 80)) self.rect = self.image.get_rect() self.rect.topleft = 0, y class Player(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.image = pygame.Surface((50, 50)) self.image.fill(PLAYER_COLOR) self.rect = self.image.get_rect() self.rect.bottomleft = x, y self.x = x self.y = y self.jumping = False self.jump_count = 20 def move(self, amount): self.rect.x += amount def jump(self): self.jumping = True def collide(self, sprites): # Retourne les sprites en collision avec le joueur return tuple(sprites[i] for i in self.rect.collidelistall(sprites)) def update(self): if self.jumping: # step = -(0.5 * self.jump_count ** 2) step = -(0.05 * self.jump_count ** 2) * (60 / FPS) if self.jump_count > 0: step *= -1 self.rect.y -= step self.jump_count -= 1 if self.rect.bottom >= self.y: self.rect.bottom = self.y self.jumping = False self.jump_count = 20 class Obstacle(pygame.sprite.Sprite): def __init__(self, x, y, width, height): super().__init__() self.image = pygame.Surface((width, height), pygame.SRCALPHA) self.rect = self.image.get_rect() self.rect.bottomleft = x, y def update(self): self.rect.x -= 5 class Friend(Obstacle): points = 10 def __init__(self, x, y): super().__init__(x, y, 60, 60) pygame.draw.circle(self.image, (0, 155, 155), (30, 30), 30) class Ennemy(Obstacle): points = -15 def __init__(self, x, y): super().__init__(x, y, 60, 60) pygame.draw.polygon(self.image, (0, 0, 0), ((30, 0), (0, 60), (60, 60))) def obstacle_spawn(): # Choix d'un obstacle (30% ami, 70% ennemi) obstacle_class = random.choices((Friend, Ennemy), (3, 7))[0] obstacle = obstacle_class(SCREEN_RECT.w, FLOOR_Y) draw_group.add(obstacle) obstacles_group.add(obstacle) def spawn_timer(): ms = random.randrange(500, 1100) pygame.time.set_timer(EVENT_OBSTACLE_SPAWN, ms) def sprites_clear(surface, rect): surface.fill(SCREEN_COLOR, rect) def pause(): clock = pygame.time.Clock() while True: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.KEYDOWN and event.key == pygame.K_p: return screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) SCREEN_RECT = screen.get_rect() pygame.mouse.set_visible(False) pygame.display.set_caption("test jeu") draw_group = pygame.sprite.RenderUpdates() obstacles_group = pygame.sprite.Group() player = Player(150, FLOOR_Y) draw_group.add(player) floor = Floor(FLOOR_Y) draw_group.add(floor) screen.fill(SCREEN_COLOR) pygame.display.update() clock = pygame.time.Clock() running = True points = 0 spawn_timer() game_paused = False while running: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP and not player.jumping: player.jump() elif event.key == pygame.K_p: game_paused = not game_paused if game_paused: pause() game_paused = False elif event.key == pygame.K_ESCAPE: running = False elif event.type == EVENT_OBSTACLE_SPAWN: obstacle_spawn() spawn_timer() draw_group.remove(player) draw_group.add(player) elif event.type == pygame.QUIT: running = False # Collision obstacles avec le joueur for sprite in player.collide(obstacles_group.sprites()): points += sprite.points obstacles_group.remove(sprite) draw_group.remove(sprite) print("points : ", points) # Suppression des sprites hors écran for sprite in obstacles_group.copy().sprites(): if sprite.rect.right < SCREEN_RECT.x: obstacles_group.remove(sprite) draw_group.remove(sprite) draw_group.clear(screen, sprites_clear) draw_group.update() rects = draw_group.draw(screen) pygame.display.update(rects) pygame.quit()
Maintenant si tu veux créer également des plateformes avec des ennemis et des objets à collecter, cela ne va pas pouvoir se faire à la volée, il va falloir créer une map (ou plusieurs si niveaux), gérer la vie, le score, et tout ce qui est nécessaire au bon fonctionnement du jeu.
.
Alors pour un simple projet d'étudiant, peut-être devrais-tu revoir tes prétentions à la baisse et conceptualiser un simple jeu 2d plus simple, pas forcément un pong (qui même pour un novice n'est pas si simple que ça), mais quelque chose à près similaire niveau complexité.
.
Bon courage.
Modifié le 5 mars 2023 à 20:12
Bonsoir, c'est encore moi (et la dernière fois je pense)
J'ai un dernier problème : j'essaie désespérément de faire afficher le score en haut de l'écran en fonction du temps, et y a un problème que je ne comprends pas ligne 139
import pygame import random pygame.init() SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCREEN_COLOR = 120, 170, 255 SOL_Y = 550 PLAYER_COLOR = 255, 255, 255 PLAYER_HEIGHT = 30 PLAYER_WIDTH = 30 EVENT_OBSTACLE_SPAWN = pygame.USEREVENT + 1 FPS = 60 class Sol(pygame.sprite.Sprite): def __init__(self, y): super().__init__() self.image = pygame.Surface((SCREEN_RECT.w, 100)) self.image.fill((100, 200, 80)) self.rect = self.image.get_rect() self.rect.topleft = 0, y class Player(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.image = pygame.Surface((30, 30)) self.image.fill(PLAYER_COLOR) self.rect = self.image.get_rect() self.rect.bottomleft = x, y self.x = x self.y = y self.jumping = False self.jump_count = 20 def move(self, amount): self.rect.x += amount def jump(self): self.jumping = True def collision(self, sprites): for sprite in sprites: if isinstance(sprite, Cercle): if self.rect.colliderect(sprite.rect): if self.rect.bottom <= sprite.rect.centery: self.rect.bottom = sprite.rect.top elif self.rect.top >= sprite.rect.centery: pygame.time.wait(2000) quit() else: if self.rect.centerx < sprite.rect.centerx: self.rect.right = sprite.rect.left else: self.rect.left = sprite.rect.right elif isinstance(sprite, Triangle): if self.rect.colliderect(sprite.rect): if self.rect.bottom <= sprite.rect.centery: self.rect.bottom = sprite.rect.top elif self.rect.top >= sprite.rect.centery: pygame.time.wait(2000) quit() else: if self.rect.centerx < sprite.rect.centerx: self.rect.right = sprite.rect.left else: self.rect.left = sprite.rect.right elif isinstance(sprite, Rectangle): if self.rect.colliderect(sprite.rect): if self.rect.bottom <= sprite.rect.centery: self.rect.bottom = sprite.rect.top elif self.rect.top >= sprite.rect.centery: pygame.time.wait(2000) quit() else: if self.rect.centerx < sprite.rect.centerx: self.rect.right = sprite.rect.left else: self.rect.left = sprite.rect.right # Retourne les sprites en collision avec le joueur return tuple(s for s in sprites if s.rect.colliderect(self.rect)) def update(self): if self.jumping: step = -(0.05 * self.jump_count ** 2) * (60 / FPS) if self.jump_count > 0: step *= -1 self.rect.y -= step self.jump_count -= 1 if self.rect.bottom >= self.y: self.rect.bottom = self.y self.jumping = False self.jump_count = 20 class ScoreBoard: def __init__(self, screen_rect): self.screen_rect = screen_rect self.score = 0 self.font = pygame.font.SysFont('Arial', 30) self.color = (255, 255, 255) def update1(self, time): self.score = int(time / 1000) def draw(self, screen): text_surface = self.font.render(f"Score: {self.score}", True, self.color) text_rect = text_surface.get_rect(topleft=(0, 0)) screen.blit(text_surface, text_rect) score_board = ScoreBoard(SCREEN_WIDTH, SCREEN_HEIGHT) SCREEN_HEIGHT = 600 class Obstacle(pygame.sprite.Sprite): def __init__(self, x, y, width, height): super().__init__() self.image = pygame.Surface((width, height), pygame.SRCALPHA) self.rect = self.image.get_rect() self.rect.bottomleft = x, y def update(self): self.rect.x -= 6 class Cercle(Obstacle): points = 10 def __init__(self, x, y): super().__init__(x, y, 60, 60) pygame.draw.circle(self.image, (0, 155, 155), (30, 30), 30) class Triangle(Obstacle): points = -15 def __init__(self, x, y): super().__init__(x, y, 60, 60) pygame.draw.polygon(self.image, (0, 255, 0), ((30, 0), (0, 60), (60, 60))) # formation du triangle class Rectangle(Obstacle): points = 10 def __init__(self, x, y): super().__init__(x, y, 70, 135) pygame.draw.rect(self.image, (12, 48, 255), (5, 5, 130, 130)) class LongRectangle(Obstacle): points = 10 def __init__(self, x, y): super().__init__(x, y, 620, 65) pygame.draw.rect(self.image, (255, 255, 0), (15, 15, 230, 230)) # le spawn ; c'est une sorte de création en direct d'objets ou de personnages (ici ça va être les obstacles) def obstacle_spawn(): # Choix de l'obstacle (en mode tu choisis si tu veux plus de triangle ou de cercles obstacle_class = random.choices((Cercle, Triangle, Rectangle, LongRectangle), (10, 14, 6, 3))[0] obstacle = obstacle_class(SCREEN_RECT.w, SOL_Y) draw_group.add(obstacle) obstacles_group.add(obstacle) def spawn_timer(): ms = random.randrange(500, 1100) pygame.time.set_timer(EVENT_OBSTACLE_SPAWN, ms) def sprites_clear(surface, rect): surface.fill(SCREEN_COLOR, rect) # applicatio, screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) SCREEN_RECT = screen.get_rect() pygame.mouse.set_visible(False) pygame.display.set_caption("Geo update") draw_group = pygame.sprite.RenderUpdates() obstacles_group = pygame.sprite.Group() player = Player(100, SOL_Y) draw_group.add(player) sol = Sol(SOL_Y) draw_group.add(sol) screen.fill(SCREEN_COLOR) pygame.display.update() clock = pygame.time.Clock() running = True points = 0 spawn_timer() # boucle principale running = True while running: clock.tick(FPS) score_board.update1(pygame.time.get_ticks()) sprites_clear(screen, SCREEN_WIDTH, SCREEN_HEIGHT) score_board.draw(screen) draw_group.update() draw_group.draw(screen) obstacles_group.update() pygame.display.update(SCREEN_HEIGHT, SCREEN_WIDTH) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == EVENT_OBSTACLE_SPAWN: obstacle_spawn() spawn_timer() if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP or pygame.K_SPACE and not player.jumping: player.jump() elif event.type == EVENT_OBSTACLE_SPAWN: obstacle_spawn() spawn_timer() draw_group.remove(player) draw_group.add(player) if pygame.sprite.spritecollide(player, obstacles_group, False): running = False # Collision obstacles avec le joueur for sprite in player.collision(obstacles_group.sprites()): # systeme de points à changer points += sprite.points obstacles_group.remove(sprite) draw_group.remove(sprite) print("points : ", points) # Suppression des sprites hors écran for sprite in obstacles_group.copy().sprites(): if sprite.rect.right < SCREEN_RECT.x: obstacles_group.remove(sprite) draw_group.remove(sprite) draw_group.clear(screen, sprites_clear) pygame.display.update() pygame.quit()
donc j'ai créer une classe pour le score, et je l'ai aussi appelé dans la boucle principale mais je ne comprends pas le problème
Pourquoi ??
Merci :))
Salut,
Ta classe ScoreBoard prend un seul argument screen_rect (pourquoi ?), or tu lui passes 2 paramètres lorsque tu l'instancies, SCREEN_WIDTH et SCREEN_HEIGHT, donc forcément python bronche.
Cette classe n'a nul besoin de cela, elle doit juste recevoir la position x, y où le score doit être affiché, rien de plus, et encore, on pourrait même s'en passer et gérer la position hors cette classe.
.
Qu'est censée faire ce que tu as fait dans la collision du joueur ? Je ne comprends pas pourquoi tu fais quitter le jeu, ni pourquoi tu veux gérer la collision différemment en fonction du type d'obstacle.
.
Pour n'importe quel type d'élément à afficher, utilise un sprite.
.
class ScoreBoard(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.x = x self.y = y self.score = 0 self.font = pygame.font.SysFont('Arial', 30) self.color = (255, 255, 255) self.image = self.font.render('0', True, self.color) self.rect = self.image.get_rect() self.rect.topright = x, y def add(self, amount): self.score += amount self.image = self.font.render(str(self.score), True, self.color) self.rect = self.image.get_rect() self.rect.topright = self.x, self.y
.
On l'ajoute ensuite, comme pour les autres objets, au groupe d'affichage.
.
# .... sol = Sol(SOL_Y) draw_group.add(sol) score = ScoreBoard(SCREEN_RECT.right - 10, 10) draw_group.add(score) # ...
.
Et update du score dans la boucle du jeu lorsque le joueur entre en collision avec les obstacles.
.
# Collision obstacles avec le joueur for sprite in player.collision(obstacles_group.sprites()): obstacles_group.remove(sprite) draw_group.remove(sprite) score.add(sprite.points)
.
Cela fonctionne en laissant le code de la méthode collision que je t'avais montré.
Jvais essayer ça tout à l'heure.
Mon but avec les collisions :
Pour les triangles et les cercles des qu'il le touche j'ai mis un temps d'arrêt pour faire afficher un message et j'enlèverai le quit plus tard lorsque j'aurais mis de presser une touche pour arriver à la page d'accueil ou pour recommencer le jeu
Et pour les rectangles en hauteur c'est pour qu'il puisse passer dessus (mais je vois que c'est pas le bon moyen :(
Merci :)
Bonsoir.
.
Si tu souhaites que le joueur puisse se balader sur les obstacles, alors il va falloir revoir la façon dont le joueur saute, c-à-d gérer cela en 2 phases, une d'ascension, celle-là est simple, et donc une phase de chute tant que le joueur n'a pas touché une surface sur laquelle il peut se mouvoir.
.
Il faudra donc détecter lorsque le joueur chute qu'il entre en collision avec un élément solide, les collisions est une des choses les plus difficiles à gérer dans un jeu, cela peut rapidement se complexifier et devenir un cauchemar ^^
.
Tu devrais réduire ton code au plus simple pour créer ton système de jump, un sol, un simple bloc (voir plusieurs à différentes hauteurs), et évidemment le joueur. Il y a pas mal d'exemples sur internet concernant la mécanique des sauts.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question1 mars 2023 à 17:33
Salut merci de me répondre :)
Ouais j'ai vu cette vidéo
Mon code ressemble à ça; mais je sais pas j'arrive pas :(
import pygame #taille de l'ecran et initialisation LARGEUR_ECRAN = 1600 HAUTEUR_ECRAN = 850 pygame.display.set_caption("test jeu") ecran = pygame.display.set_mode([LARGEUR_ECRAN, HAUTEUR_ECRAN]) pygame.init() #saut x = 800 #position du cube au début y = 600 #position du cube au début width = 80 height = 80 vel = 15 isJump = False jumpCount = 10 #hauteur du saut """on peut mettre des classes entre là et la boucle continuelle""" #boucle run = True while run: pygame.time.delay(30) #clock for event in pygame.event.get(): if event.type == pygame.QUIT: run = False keys = pygame.key.get_pressed() #directions if keys[pygame.K_LEFT] and x > vel: x -= vel if keys[pygame.K_RIGHT] and x < 1600 - vel - width: x += vel #saut if not (isJump): if keys[pygame.K_SPACE]: isJump = True else: if jumpCount >= -10: y -= (jumpCount * abs(jumpCount)) * 0.5 jumpCount -= 1 else: jumpCount = 10 isJump = False #appeler les elements ecran.fill((120, 170, 255)) pygame.draw.rect(ecran, (100, 200, 80), (0, 680, 1600, 350)) pygame.draw.rect(ecran, (255, 255, 255), (x, y, width, height)) pygame.display.update() pygame.quit()