Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 Pong clone with classes
#1
Recently I came across this video https://www.youtube.com/watch?v=C6jJg9Zan7w and since I'm trying to understand OOP design principles I thought it could be a good exercise to modify the code a little bit. I used basically the same idea, but redesigned it using classes.
Every observation is more than welcome.

import turtle

class Window:
	
	def __init__(self, width, height, bgc, title):
		
		self.width = width
		self.height = height
		self.bgc = bgc
		self.title = title
		
		self.window = turtle.Screen()
		self.window.bgcolor(bgc)
		self.window.title(title)
		self.window.setup(width=self.width, height=self.height)
		
class Paddle:
	
	def __init__(self, color, posx, posy, shape="square", width=5, len=1):
	
		self.shape = shape
		self.color = color
		self.posx = posx
		self.posy = posy
		self.width = width
		self.len = len
		
		self.paddle = turtle.Turtle()		
		self.paddle.speed(0)
		self.paddle.shape(self.shape)
		self.paddle.color(self.color)
		self.paddle.shapesize(stretch_wid=self.width,stretch_len=self.len)
		self.paddle.penup()
		self.paddle.goto(self.posx, self.posy)
		
	def paddle_up(self):
		
		y = self.paddle.ycor()
		if y < 245:
			y += 30
			self.paddle.sety(y)
	
	def paddle_down(self):
		
		y = self.paddle.ycor()
		if y > -245:
			y -= 30
			self.paddle.sety(y)
			
class Ball:
	
	def __init__(self, color, vx=4, vy=4, shape="square", posx=0, posy=0):
		
		self.shape = shape
		self.color = color
		self.vx = vx
		self.vy = vy
		self.posx = posx
		self.posy = posy	
		
		self.ball = turtle.Turtle()
		self.ball.speed(0)
		self.ball.shape(self.shape)
		self.ball.color(self.color)
		self.ball.penup()
		self.ball.goto(self.posx, self.posy)

class Score:
		
	score_1 = 0
	score_2 = 0
	
	def __init__(self, color, posx, posy, shape="square"):
		self.color = color
		self.posx = posx
		self.posy = posy
		self.shape = shape
		
		self.score = turtle.Turtle()
		self.score.speed(0)
		self.score.shape(self.shape)
		self.score.color(self.color)
		self.score.penup()
		self.score.goto(self.posx, self.posy)
		self.score.hideturtle()
		self.score.write("Player 1: 0  Player 2: 0", align="center", font=("Courier", 24, "normal"))		

		
win = Window(800, 600, "black", "Pong")
paddle_1 = Paddle("white", -350, 0)
paddle_2 = Paddle("white", 350, 0)
b = Ball("white", vx=6,vy=6)
s = Score("white", 0, 260)

win.window.listen()
win.window.onkeypress(paddle_1.paddle_up, "w")
win.window.onkeypress(paddle_1.paddle_down, "s")
win.window.onkeypress(paddle_2.paddle_up, "Up")
win.window.onkeypress(paddle_2.paddle_down, "Down")

while True:

	win.window.update()
	
	b.ball.setx(b.ball.xcor() + b.vx)
	b.ball.sety(b.ball.ycor() + b.vy)
	
	if b.ball.ycor() > 250:
		b.vy *= -1
	
	if b.ball.ycor() < -280:
		b.vy *= -1
		
	if b.ball.xcor() > 400:
		s.score_1 += 1
		s.score.clear()
		s.score.write("Player 1: {}  Player 2: {}".format(s.score_1, s.score_2), align="center", font=("Courier", 24, "normal"))
		b.ball.goto(0, 0)
		b.vx *= -1
		
	elif b.ball.xcor() < -400:
		s.score_2 += 1
		s.score.clear()
		s.score.write("Player 1: {}  Player 2: {}".format(s.score_1, s.score_2), align="center", font=("Courier", 24, "normal"))
		b.ball.goto(0, 0)
		b.vx *= -1
	
	
	if b.ball.xcor() < -330 and b.ball.ycor() < paddle_1.paddle.ycor() + 50 and b.ball.ycor() > paddle_1.paddle.ycor() - 50:
		b.vx *= -1
	
	elif b.ball.xcor() > 330 and b.ball.ycor() < paddle_2.paddle.ycor() + 50 and b.ball.ycor() > paddle_2.paddle.ycor() - 50:
		b.vx *= -1
	
Quote
#2
I just tried it. The collision detection is a little wonky but it works. When I ran it in IDLE, I got an error traceback when I closed it. The error wasn't in your code, it was in turtle. I suspect that the module itself might be buggy. People who write a lot of games all swear by a third party library called pygame. I'm not very familiar with turtle, but when I see tracebacks coming from within a module, I take it as a sign that I should be using different software. Nothing can be more frustrating than spending all day trying to debug your code all with the suspicion that a bug in somebody else's code is giving you problems.

The traceback I got when I ran your program:
Error:
Traceback (most recent call last): File "C:\Users\seame\Desktop\pong.pyw", line 105, in <module> b.ball.setx(b.ball.xcor() + b.vx) File "C:\Users\seame\AppData\Local\Programs\Python\Python37-32\lib\turtle.py", line 1808, in setx self._goto(Vec2D(x, self._position[1])) File "C:\Users\seame\AppData\Local\Programs\Python\Python37-32\lib\turtle.py", line 3158, in _goto screen._pointlist(self.currentLineItem), File "C:\Users\seame\AppData\Local\Programs\Python\Python37-32\lib\turtle.py", line 755, in _pointlist cl = self.cv.coords(item) File "<string>", line 1, in coords File "C:\Users\seame\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 2469, in coords self.tk.call((self._w, 'coords') + args))] _tkinter.TclError: invalid command name ".!canvas"
As for the object oriented code, I would recommend always using the instance variables once they're created up in your constructor rather than using the parameters they're assigned.

Instead of this:
class Window:
     
    def __init__(self, width, height, bgc, title):
         
        self.width = width
        self.height = height
        self.bgc = bgc
        self.title = title
         
        self.window = turtle.Screen()
        self.window.bgcolor(bgc)
        self.window.title(title)
        self.window.setup(width=self.width, height=self.height)
    .
    .
    .
Do this:
class Window:
     
    def __init__(self, width, height, bgc, title):
         
        self.width = width
        self.height = height
        self.bgc = bgc
        self.title = title
         
        self.window = turtle.Screen()
        self.window.bgcolor(self.bgc)
        self.window.title(self.title)
        self.window.setup(width=self.width, height=self.height)
Admittedly, it still works the same; it's just a convention/style thing. It makes your code look better.
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  C++-type static members for python classes Gribouillis 0 384 Nov-01-2018, 06:32 PM
Last Post: Gribouillis
  Best Practice to Pass a Variable Between Two Classes? MIPython 9 1,147 Apr-11-2018, 05:35 PM
Last Post: MIPython
  Pygame simple pong example metulburr 5 2,411 Nov-07-2016, 06:40 PM
Last Post: Kai.

Forum Jump:


Users browsing this thread: 1 Guest(s)