Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #90180 > unrolled thread

How to properly apply OOP in the bouncing ball code

Started byTommy C <tommyc168168@gmail.com>
First post2015-05-08 08:40 -0700
Last post2015-05-13 20:20 +1200
Articles 10 — 8 participants

Back to article view | Back to comp.lang.python


Contents

  How to properly apply OOP in the bouncing ball code Tommy C <tommyc168168@gmail.com> - 2015-05-08 08:40 -0700
    Re: How to properly apply OOP in the bouncing ball code Mel Wilson <mwilson@the-wire.com> - 2015-05-08 18:44 +0000
    Re: How to properly apply OOP in the bouncing ball code Ian Kelly <ian.g.kelly@gmail.com> - 2015-05-08 10:22 -0600
    Re: How to properly apply OOP in the bouncing ball code Tommy C <tommyc168168@gmail.com> - 2015-05-11 08:22 -0700
      Re: How to properly apply OOP in the bouncing ball code Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2015-05-12 17:53 +0100
    Re: How to properly apply OOP in the bouncing ball code zipher <dreamingforward@gmail.com> - 2015-05-11 08:33 -0700
      Re: How to properly apply OOP in the bouncing ball code Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2015-05-11 20:24 -0400
        Re: How to properly apply OOP in the bouncing ball code zipher <dreamingforward@gmail.com> - 2015-05-11 17:42 -0700
          Re: How to properly apply OOP in the bouncing ball code Terry Reedy <tjreedy@udel.edu> - 2015-05-12 11:45 -0400
            Re: How to properly apply OOP in the bouncing ball code Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2015-05-13 20:20 +1200

#90180 — How to properly apply OOP in the bouncing ball code

FromTommy C <tommyc168168@gmail.com>
Date2015-05-08 08:40 -0700
SubjectHow to properly apply OOP in the bouncing ball code
Message-ID<009ceef8-066d-4d92-a6c9-761e86584e75@googlegroups.com>
I'm trying to apply OOP in this bouncing ball code in order to have multiple balls bouncing around the screen. The objective of this code is to create a method called settings, which controls all the settings for the screen and the bouncing behaviour of multiple balls, under the class Ball. However, I keep on getting errors related to attributes (e.g., speed). I'm new to OOP in Python so your help will be much appreciated. Thanks in advance.


import pygame
import random
import sys

pygame.init()

class Ball:
    def __init__(self, X, Y):
        self.velocity = [1,1]
        self.ball_image = pygame.image.load ("ball.jpg")
        self.ball_boundary = self.ball_image.get_rect ()
        self.black = [0,0,0]
        self.width = 800
        self.height = 600
        self.num = 8
        self.X = random.randint(0, self.width)
        self.Y = random.randint(0, self.height)

    def settings(self):
        #X = random.randint(0, self.width)
        #Y = random.randint(0, self.height)
        clock = pygame.time.Clock()
        size = self.width, self.height
        screen = pygame.display.set_mode(size)
        ball_boundary = self.ball_image.get_rect()
        speed = self.velocity
        pic = self.ball_image
        pygame.display.set_caption("Balls")
        num_balls = self.num
        ball_list = []

        for i in range(num_balls):
           ball_list.append( Ball(random.randint(10, self.width-10),random.randint(10, self.height-10)) )

        while 1:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit(0)

            screen.fill(self.black)
            for balls in ball_list:
                if balls.ball_boundary.left < 0 or balls.ball_boundary.right > self.width:
                    balls.speed[0] = -balls.speed[0]
                if balls.ball_boundary.top < 0 or balls.ball_boundary.bottom > self.height:
                    balls.speed[1] = -balls.speed[1]
                balls.ball_boundary = balls.ball_boundary.move (self.velocity)
                screen.blit (balls.ball_image, balls.ball_boundary)
            pygame.display.flip()

play = Ball(random.randint(0, 800), random.randint(0, 600))

play.settings()




Message	File Name	Line	Position	
Traceback				
    <module>	C:\....\Multiple_balls_TC.py	63		
    settings	C:\....\Multiple_balls_TC.py	56		
AttributeError: Ball instance has no attribute 'speed'				

[toc] | [next] | [standalone]


#90188

FromMel Wilson <mwilson@the-wire.com>
Date2015-05-08 18:44 +0000
Message-ID<mij06a$tgc$1@dont-email.me>
In reply to#90180
On Fri, 08 May 2015 08:40:34 -0700, Tommy C wrote:

> I'm trying to apply OOP in this bouncing ball code in order to have
> multiple balls bouncing around the screen. The objective of this code is
> to create a method called settings, which controls all the settings for
> the screen and the bouncing behaviour of multiple balls, under the class
> Ball. However, I keep on getting errors related to attributes (e.g.,
> speed). I'm new to OOP in Python so your help will be much appreciated.
> Thanks in advance.

I did something similar, with little characters running around the screen 
under joystick control.  What I think:

1. Each instance of the Ball class should control the behaviour of one 
ball.
2. The screen settings and global environment generally should be global, 
not stuffed inside the behaviour of a Ball.
3. Keeping the list of Ball instances should be something the main 
section of your program does, not stuffed inside the behaviour of a Ball.

Each of my little GamePlayer objects is subclassed from 
pygame.sprite.Sprite .  I forget what I got by doing this (it's old code) 
but looking up the docs for that class might give you some insights.  
Each GamePlayer object has an "update" method which accepts info from the 
joystick and updates the player's movements, and a "draw" method which 
the main loop calls on displaying every frame, to show the player's new 
position and attitude.

You might be able to do something along these lines.

	Mel.

[toc] | [prev] | [next] | [standalone]


#90269

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-05-08 10:22 -0600
Message-ID<mailman.258.1431102150.12865.python-list@python.org>
In reply to#90180

[Multipart message — attachments visible in raw view] — view raw

On May 8, 2015 9:46 AM, "Tommy C" <tommyc168168@gmail.com> wrote:
>
> I'm trying to apply OOP in this bouncing ball code in order to have
multiple balls bouncing around the screen. The objective of this code is to
create a method called settings, which controls all the settings for the
screen and the bouncing behaviour of multiple balls, under the class Ball.
However, I keep on getting errors related to attributes (e.g., speed). I'm
new to OOP in Python so your help will be much appreciated. Thanks in
advance.

As the error says, the attribute does not exist.

> class Ball:
>     def __init__(self, X, Y):
>         self.velocity = [1,1]

Here where you set it, you call it "velocity".

>         speed = self.velocity

Here you create a local variable called "speed", which you never use.

>                 if balls.ball_boundary.left < 0 or
balls.ball_boundary.right > self.width:
>                     balls.speed[0] = -balls.speed[0]

And here you look up an attribute of Ball called "speed", which doesn't
match the name you used in __init__.

This is a muddled design overall. Your Ball class represents the individual
balls bouncing around the screen. It should not also contain details about
window size and the logic for the event loop. Use a separate class for that.

Similarly, if the purpose of your settings method is to manage settings,
why does it also contain all the bouncing logic? These should probably be
separate methods.

[toc] | [prev] | [next] | [standalone]


#90396

FromTommy C <tommyc168168@gmail.com>
Date2015-05-11 08:22 -0700
Message-ID<e841eeeb-7a36-47fe-bd21-bfd7b53a9588@googlegroups.com>
In reply to#90180
Thanks for your help.

I have updated the code as follows, there are no more errors but the images will not move at all, as all the images are staying at the upper left corner. Please advice, thanks.


import sys, pygame

pygame.init()

size   = width,  height = 800, 600
black  = [0,0,0]
screen = pygame.display.set_mode(size)

class BALL:
    def __init__(self,image):
        self.ball     = pygame.image.load(image)
        self.ballrect = self.ball.get_rect()
        self.speed    = [2, 2]

    def control(self):
        ballmove = self.ballrect.move(self.speed)

        if ballmove.left < 0 or ballmove.right > width:
            self.speed[0] = -self.speed[0]

        if ballmove.top < 0  or ballmove.bottom > height:
            self.speed[1] = -self.speed[1]

    def settings(self):
        clock  = pygame.time.Clock()
        screen.fill(black)
        screen.blit(self.ball, self.ballrect)
        pygame.display.flip()
        clock.tick(60)
        while 1:
            for event in pygame.event.get():
                if event.type == pygame.QUIT: sys.exit()


bob = BALL("spongebob.png")
bob.control()
bob.settings()

patrick = BALL("patrick.jpg")
patrick.speed[0] = 5
patrick.speed[1] = 8
patrick.control()
patrick.settings()

jaws = BALL("jaws.jpg")
jaws.speed[0] = 1
jaws.speed[1] = 10
jaws.control()
jaws.settings()


On Friday, May 8, 2015 at 11:40:46 AM UTC-4, Tommy C wrote:
> I'm trying to apply OOP in this bouncing ball code in order to have multiple balls bouncing around the screen. The objective of this code is to create a method called settings, which controls all the settings for the screen and the bouncing behaviour of multiple balls, under the class Ball. However, I keep on getting errors related to attributes (e.g., speed). I'm new to OOP in Python so your help will be much appreciated. Thanks in advance.
> 
> 
> import pygame
> import random
> import sys
> 
> pygame.init()
> 
> class Ball:
>     def __init__(self, X, Y):
>         self.velocity = [1,1]
>         self.ball_image = pygame.image.load ("ball.jpg")
>         self.ball_boundary = self.ball_image.get_rect ()
>         self.black = [0,0,0]
>         self.width = 800
>         self.height = 600
>         self.num = 8
>         self.X = random.randint(0, self.width)
>         self.Y = random.randint(0, self.height)
> 
>     def settings(self):
>         #X = random.randint(0, self.width)
>         #Y = random.randint(0, self.height)
>         clock = pygame.time.Clock()
>         size = self.width, self.height
>         screen = pygame.display.set_mode(size)
>         ball_boundary = self.ball_image.get_rect()
>         speed = self.velocity
>         pic = self.ball_image
>         pygame.display.set_caption("Balls")
>         num_balls = self.num
>         ball_list = []
> 
>         for i in range(num_balls):
>            ball_list.append( Ball(random.randint(10, self.width-10),random.randint(10, self.height-10)) )
> 
>         while 1:
>             for event in pygame.event.get():
>                 if event.type == pygame.QUIT:
>                     sys.exit(0)
> 
>             screen.fill(self.black)
>             for balls in ball_list:
>                 if balls.ball_boundary.left < 0 or balls.ball_boundary.right > self.width:
>                     balls.speed[0] = -balls.speed[0]
>                 if balls.ball_boundary.top < 0 or balls.ball_boundary.bottom > self.height:
>                     balls.speed[1] = -balls.speed[1]
>                 balls.ball_boundary = balls.ball_boundary.move (self.velocity)
>                 screen.blit (balls.ball_image, balls.ball_boundary)
>             pygame.display.flip()
> 
> play = Ball(random.randint(0, 800), random.randint(0, 600))
> 
> play.settings()
> 
> 
> 
> 
> Message	File Name	Line	Position	
> Traceback				
>     <module>	C:\....\Multiple_balls_TC.py	63		
>     settings	C:\....\Multiple_balls_TC.py	56		
> AttributeError: Ball instance has no attribute 'speed'

[toc] | [prev] | [next] | [standalone]


#90466

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2015-05-12 17:53 +0100
Message-ID<mailman.404.1431449631.12865.python-list@python.org>
In reply to#90396
On 11 May 2015 at 16:22, Tommy C <tommyc168168@gmail.com> wrote:
> Thanks for your help.
>
> I have updated the code as follows, there are no more errors but the images will not move at all, as all the images are staying at the upper left corner. Please advice, thanks.
>
>
> import sys, pygame
>
> pygame.init()
>
> size   = width,  height = 800, 600
> black  = [0,0,0]
> screen = pygame.display.set_mode(size)
>
> class BALL:
>     def __init__(self,image):
>         self.ball     = pygame.image.load(image)
>         self.ballrect = self.ball.get_rect()
>         self.speed    = [2, 2]
>
>     def control(self):
>         ballmove = self.ballrect.move(self.speed)
>
>         if ballmove.left < 0 or ballmove.right > width:
>             self.speed[0] = -self.speed[0]
>
>         if ballmove.top < 0  or ballmove.bottom > height:
>             self.speed[1] = -self.speed[1]

The function below should not be a method on a particular ball object
as it is the global event loop for pygame. This needs to be a top
level function that updates the animation for all balls.

>     def settings(self):
>         clock  = pygame.time.Clock()
>         screen.fill(black)
>         screen.blit(self.ball, self.ballrect)
>         pygame.display.flip()
>         clock.tick(60)
>         while 1:
>             for event in pygame.event.get():
>                 if event.type == pygame.QUIT: sys.exit()

In this loop you need to add code that will call the control() method
of each ball and then redraw the screen. At the moment you only draw
the objects once at the top of the settings() method. Then the loop
runs until you quit. So it should be something like:

# The functions below would make sense as methods of an "App" class.

def run():
    while 1:
        for event in pygame.event.get():
            if event.type = pygame.QUIT:
                sys.exit()
        update()
        draw()

def update():
    for ball in balls:
        ball.control()

def draw():
    screen.fill(black)
    for ball in balls:
        ball.draw()  # You need to add this method to BALL
    pygame.display.flip()

balls = [BALL("spongebob.png"), BALL("jaws.jpg")]

run()  # Actually runs the program's event loop.


--
Oscar

[toc] | [prev] | [next] | [standalone]


#90399

Fromzipher <dreamingforward@gmail.com>
Date2015-05-11 08:33 -0700
Message-ID<45313faa-d256-4fa4-9e37-4b8dd85e1681@googlegroups.com>
In reply to#90180
On Friday, May 8, 2015 at 10:40:46 AM UTC-5, Tommy C wrote:
> I'm trying to apply OOP in this bouncing ball code in order to have multiple balls bouncing around the screen. The objective of this code is to create a method called settings, which controls all the settings for the screen and the bouncing behaviour of multiple balls, under the class Ball. However, I keep on getting errors related to attributes (e.g., speed). I'm new to OOP in Python so your help will be much appreciated. Thanks in advance.

You are making a error that few in the programming community have caught up to.  OOP design for *data abstraction* is a completely different beast that OOP for *simulation*.  The confusion is around the use of the word "object" which both denotes a physical world item and a virtual one detached from reality.

I would say that Python might not be the right fit, but instead a language dedicated to simulation.

Mark

[toc] | [prev] | [next] | [standalone]


#90423

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2015-05-11 20:24 -0400
Message-ID<mailman.383.1431390292.12865.python-list@python.org>
In reply to#90399
On Mon, 11 May 2015 08:33:56 -0700 (PDT), zipher
<dreamingforward@gmail.com> declaimed the following:

>On Friday, May 8, 2015 at 10:40:46 AM UTC-5, Tommy C wrote:
>> I'm trying to apply OOP in this bouncing ball code in order to have multiple balls bouncing around the screen. The objective of this code is to create a method called settings, which controls all the settings for the screen and the bouncing behaviour of multiple balls, under the class Ball. However, I keep on getting errors related to attributes (e.g., speed). I'm new to OOP in Python so your help will be much appreciated. Thanks in advance.
>
>You are making a error that few in the programming community have caught up to.  OOP design for *data abstraction* is a completely different beast that OOP for *simulation*.  The confusion is around the use of the word "object" which both denotes a physical world item and a virtual one detached from reality.
>
>I would say that Python might not be the right fit, but instead a language dedicated to simulation.

	The danger there is that a "language dedicated to simulation" might
mean "discrete event" simulation -- which would be an even worse fit to a
problem of particle motion simulation.

For the OP:

	In simple terms, attributes will appear in the methods of the object
class as "self.attribute" (presuming you use the normal practice of using
"self" in the method signature). Names that don't have the "self." prefix
appearing in a method are just temporary local storage (they disappear when
the method exits).

	Ball objects would have a velocity (which, properly, is a speed AND a
direction -- presuming a 2-D world, dX/time-unit and dY/time-unit is
probably easier to track than dDistance/time-unit and Azimuth; that is
10pixelX/sec, 5pixelY/sec is easier than [not the same velocity, just
numbers for an example] 12pixels @ 30degrees)... Other potential attributes
are (for graphical display) color and/or (for text output) name; radius...

	The "world" would contain the dimensions of the, uhm, world (and if it
is bounded [walls, balls bounce off] or open [no walls, balls that go off
the edge are lost] or closed [no walls, balls that go off one edge reappear
on the other... Ever play Asteroids?].

	The world would contain a list of Ball objects.

	Now -- who manages the position of the balls? Should a ball know where
it is, or is that only a matter for the world to know? This gets into
design aspects that may have viable answers on either side. If the ball
knows its position, the world has to ask each ball for the position (and
radius) and then ask each other ball is ballX (pos/radius) has bumped into
it. If the world keeps the positions, it has to pass them in to the balls
to update based on velocity, but it can (after asking for radius) compute
if any ball has hit another.

	I suspect I'd write this with the balls knowing their position --
making a simple ball.update(time_delta) [time_delta allows the world to
control the granularity of time steps, as long as it uses the same
time_delta for all balls per cycle]. Update would have the ball compute its
new position. The world would then query the ball for new location to
update the display... The world would also ask other balls if they've been
impacted.

	NOTE: this scheme does have an implied priority -- no mutual impactors.
Conway's Game of Life commonly uses a double buffered mode -- all nodes are
updated [into "next generation"] based on the "current" generation
conditions. To do that with the balls means .update has to generate a
"next" position -- THEN you handle all collisions based on "next", before
moving all "next" into "current" to start the next cycle.
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#90426

Fromzipher <dreamingforward@gmail.com>
Date2015-05-11 17:42 -0700
Message-ID<a25437cb-c525-41db-9bd4-c9759a982a3b@googlegroups.com>
In reply to#90423
On Monday, May 11, 2015 at 7:25:09 PM UTC-5, Dennis Lee Bieber wrote:
> On Mon, 11 May 2015 08:33:56 -0700 (PDT), zipher
> <dreamingforward@gmail.com> declaimed the following:
> >You are making a error that few in the programming community have caught up to.  OOP design for *data abstraction* is a completely different beast that OOP for *simulation*.  The confusion is around the use of the word "object" which both denotes a physical world item and a virtual one detached from reality.
> >
> >I would say that Python might not be the right fit, but instead a language dedicated to simulation.
> 
> 	The danger there is that a "language dedicated to simulation" might
> mean "discrete event" simulation -- which would be an even worse fit to a
> problem of particle motion simulation.

Huh?  VPython successfully models particle motion simulation with discrete events.  I don't see how you're going to update a variable non-discretely.  Tensors?  Good luck.

Mark

[toc] | [prev] | [next] | [standalone]


#90459

FromTerry Reedy <tjreedy@udel.edu>
Date2015-05-12 11:45 -0400
Message-ID<mailman.398.1431445807.12865.python-list@python.org>
In reply to#90426
On 5/11/2015 8:42 PM, zipher wrote:
> On Monday, May 11, 2015 at 7:25:09 PM UTC-5, Dennis Lee Bieber wrote:
>> On Mon, 11 May 2015 08:33:56 -0700 (PDT), zipher
>> <dreamingforward@gmail.com> declaimed the following:
>>> You are making a error that few in the programming community have caught up to.  OOP design for *data abstraction* is a completely different beast that OOP for *simulation*.  The confusion is around the use of the word "object" which both denotes a physical world item and a virtual one detached from reality.
>>>
>>> I would say that Python might not be the right fit, but instead a language dedicated to simulation.
>>
>> 	The danger there is that a "language dedicated to simulation" might
>> mean "discrete event" simulation -- which would be an even worse fit to a
>> problem of particle motion simulation.
>
> Huh?  VPython successfully models particle motion simulation with discrete events.  I don't see how you're going to update a variable non-discretely.  Tensors?  Good luck.
>
> Mark
>


-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#90538

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2015-05-13 20:20 +1200
Message-ID<crgfr9F7updU1@mid.individual.net>
In reply to#90459
Terry Reedy wrote:
> On 5/11/2015 8:42 PM, zipher wrote:
>> Huh?  VPython successfully models particle motion simulation with 
>> discrete events.

That's a discrete approximation to a continuous process.
The term "discrete event simulation" is usually used to
mean modelling a process that is inherently discrete,
e.g. sending data packets over a network.

-- 
Greg

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web