Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
not running
#1
I'm making a ping pong game but for some reason the .frame functions aren't working

import pygame
from random import randint
from math import sin, cos
 
window = pygame.display.set_mode((800, 600))
keys = pygame.key.get_pressed()
 
class Paddle:
    def __init__(self, playernum):
        self.instance = pygame.Surface((10, 70))
        self.rect = self.instance.get_rect(center=((10 if playernum == 1 else 790), 300))
        self.playernum = playernum
        self.instance.fill('white')
    def frame(self):
        if self.playernum == 1:
            if keys[pygame.K_w]:
              self.rect.y -= 3
            if keys[pygame.K_x]:
              self.rect.y += 3
        else:
            if keys[pygame.K_i]:
                self.rect.y -= 3
            if keys[pygame.K_m]:
                self.rect.y += 3
 
class Ball:
    def __init__(self):
        self.instance = pygame.Surface((25, 25))
        self.rect = self.instance.get_rect(center=(400, 300))
        self.direction = 270 if randint(1, 2) == 1 else 90
         
    def frame(self):
        if self.rect.colliderect(p1.rect) or self.rect.colliderect(p2.rect) or self.rect.y > 600 or self.rect.y < 0:
            self.direction += 90
            self.rect.x += 3 * sin(self.direction)
            self.rect.y += 3 * cos(self.direction)
             
        if self.rect.x > 800 or self.rect.x < 0
            self.rect.x = 400
            self.rect.y = 300
            self.direction = 270 if randint(1, 2) == 1 else 90
       
p1, p2 = Paddle(1), Paddle(2)
ball = Ball()
       
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
             
    window.fill('black')
       
    key = pygame.key.get_pressed()
       
    p1.frame()
    p2.frame()
    ball.frame()
       
    window.blit(p1, p1.rect)
    window.blit(p2, p2.rect)
    window.blit(ball, ball.rect)
   
    pygame.display.flip()
    pygame.time.Clock().tick(120)
     
Reply
#2
a bit of friendly advise - start using descriptive post titles, as well as providing more information in your post - "for some reason the .frame functions aren't working" is as cryptic as it gets.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
You did not set a fill color for the ball, so it is drawn black against a black background. Your logic for moving the paddles is wrong. If no key is pressed the paddle should not move.

I don't understand why you don't want to use pygame when writing games in pygame. Ball and Paddle should be sprites. They should have an update method, not a frame method. Their surface should be called image, not instance. This is your game written with sprites.
import pygame
import random


class Paddle(pygame.sprite.Sprite):
    def __init__(self, window,  pos, keys):
        super().__init__()
        self.window = window
        self.image = pygame.Surface((10, 70))
        self.image.fill('white')
        self.rect = self.image.get_rect(center=pos)
        self.up, self.down = keys

    def update(self, keys):
        if keys[self.down]:
            y = self.rect.y + 3
            self.rect.y = min(y, self.window.get_height()-self.rect.height)
        elif keys[self.up]:
            y = self.rect.y - 3
            self.rect.y = max(y, 0)


class Ball(pygame.sprite.Sprite):
    def __init__(self, window):
        super().__init__()
        self.window = window
        self.image = pygame.Surface((25, 25))
        self.image.fill('white')
        self.pos = (window.get_width() // 2, window.get_height() // 2)
        self.rect = self.image.get_rect(center=self.pos)
        self.dx = random.choice((1, -1))
        self.dy = random.choice((1, -1))

    def update(self):
        self.rect.x += self.dx
        self.rect.y += self.dy
        wide, high = self.window.get_size()
        if self.rect.y <= 0 or self.rect.bottom >= high:
            self.dy = -self.dy
        if self.rect.x <= 0:
            return 2
        if self.rect.right >= wide:
            return 1
        return 0

    def hit(self):
        self.dx = -self.dx

    def serve(self, side):
        self.rect.center = self.pos
        self.dx = 1 if side == 2 else -1
        self.dy = random.choice((1, -1))


pygame.init()
window = pygame.display.set_mode((800, 600))
ball = Ball(window)
p1 = Paddle(window, (5, 300), (pygame.K_w, pygame.K_x))
p2 = Paddle(window, (795, 300), (pygame.K_i, pygame.K_m))
paddles = pygame.sprite.Group(p1, p2)
all_sprites = pygame.sprite.Group(ball, p1, p2)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    paddles.update(pygame.key.get_pressed())
    score = ball.update()
    if score != 0:
        ball.serve(score)
    elif pygame.sprite.spritecollide(ball, paddles, False):
        ball.hit()

    window.fill('black')
    all_sprites.draw(window)
    pygame.display.flip()
    pygame.time.Clock().tick(120)
This is areally boring version of pong. More variability in how the ball is initially served would be an easy change that makes it more playable. Changing how the ball bounces off the paddle would add an element of strategy. And of course keeping and displaying score is always a good idea.

Pygame programs need to init the modules they use. Currently you only use the display module, and that gets initialized when you call pygame.display.set_mode(). In the future you might begin using other modules, and some of those need to be initialized before use. Having pygame.init() be the first pygame instruction in you code is an easy way to do that.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020