Evening there.
I need to return an (x,y) tuple of an object, This x,y will be used to help 1 object calculate where the other object is and move towards it.

My problem is that both the objects need to know the others' x,y.
(i'm unsure how to get the x,y of both the objects in one tuple and still tell them apart.)

While writing that i thought that maybe i put 4 values in the tuple say, x1,y1,x2,y2 and then for the 1st object call x1,y1 only and the same for object 2, would that work?

Also i thought tuples are not changable and hence after the objects move towards each other, the loop'll start again and check their x,y but the x,y will be the same wont it because tuples cant be changed?

am i right or am i missing some way around this?


Sorry if i'm unclear and i apologies for the long post, i sometime have ideas of solving things while i'm writing the problem out.
Gets your brain moving and all.

Cheers guys

Recommended Answers

All 17 Replies

You can use the observer pattern.

class Observed(object):
    def register_observer(self,observer):
        self.observer=observer
    def notify(self):
        self.observer.update(self)

class Observer(object):
    def update(self,other):
        print(self,"gets that ",other," has moved")
        #decide what to do
        pass


class Something(Observer,Observed):
    def __init__(self,x,y):
        self.x=x
        self.y=y
        #super(Something,self).__init__()
    def move_to(self,x,y):
        self.x=x
        self.y=y
        self.notify()
    def update(self,other):
        super(Something,self).update(other)
        if other.x<self.x: self.move_to(self.x-1,self.y)# or whatever

o1=Something(1,2)
o2=Something(5,4)

o1.register_observer(o2)
o2.register_observer(o1)
o1.move_to(1,2)

More detailed

why not use a set for this?

info = {'x1': 123, 'y1': 456, 'x2: 789, 'y2': 012}

I have heard sets are pretty much better than tuple but for this piece of code i am required to use tuples.
Doctor's orders.

Thanks slate i'll have a look that this observer's pattern and try to see if i can work out my issues from that.

I'll get back with my progress later today.

I'm having problems with a beast of an error.
A Beast i tell you!

I'm going to try explaining it without pasting ALL my code.

i wrote my getPos like this:

def getpos():
        r1 = x,y = 100,100
        r2 = x,y = 800,800

i get the error:

[I]Traceback (most recent call last):
    r1.step(r2.getPos()[0],r2.getPos()[1])
AttributeError: r2 instance has no attribute 'getPos'[/I]

thats quite a shortened down version, it might be enough.
The part that confuses me is the part in the error was written by my lecturer and therefore is correct.

I have defined getPos() for both r1 and r2 (my objects), so why do i get that error?
Any one got any clues? As i dont.

cheers

def getpos():
        r1 = x,y = 100,100
        r2 = x,y = 800,800

i get the error:

[I]Traceback (most recent call last):
    r1.step(r2.getPos()[0],r2.getPos()[1])
AttributeError: r2 instance has no attribute 'getPos'[/I]

I have defined getPos() for both r1 and r2 (my objects), so why do i get that error?
Any one got any clues?

So if getpos() is a function for a class object, then you forgot the most important detail. The parameter self !

Your function should be defined as such:

def getpos(self):
        r1 = x,y = 100,100
        r2 = x,y = 800,800

But then again you're using r1 and r2 inside this function, which may indicate this isn't a class function at all. So in that case, you wouldn't use r2.getPos(), you should just use getPos().

Maybe you should post a little bit more code so that we have some context to go by.

commented: Very good detail and help +1

Check the spelling of getPos()

commented: Dedicated to helpfulness! thanks +1

oh fudge, i must have changed that by mistake with all my changing of code to try and fix the problem, i definetly had it as getPos before.

I changed it and i got the error that i remember seeing before i must have screwed it up... Progress! haha.

[I]r1.step(r2.getPos()[0],r2.getPos()[1])
TypeError: getPos() takes no arguments (1 given)[/I]

i've given 1 arguement for getPos which apprently shouldnt take one.
Is that my r1=x,y=100,100 thing? should i not give them the values of 100,100 and let them do by themselves?

oh fudge, i must have changed that by mistake with all my changing of code to try and fix the problem, i definetly had it as getPos before.

I changed it and i got the error that i remember seeing before i must have screwed it up... Progress! haha.

[I]r1.step(r2.getPos()[0],r2.getPos()[1])
TypeError: getPos() takes no arguments (1 given)[/I]

See my above post

Give it a little test ...

class RobotB:
    def getPos(self):
        self.r1 = x,y = 100,200
        self.r2 = x,y = 700,800
        return self.r1, self.r2

r2 = RobotB()
print r2.getPos()         # ((100, 200), (700, 800))
print r2.getPos()[1]      # (700, 800)
print r2.getPos()[1][0]   # 700

sorry, i didnt spot you jlm699
i didnt expect people to respond so fast, let alone to.
Forgive me, i'll check it out now.

Cheers for the help

def getPos(self):
        self.RobotA = x,y = 100,200
        self.RobotB = x,y = 700,800
        return self.RobotA, self.RobotB

that worked. I feel quite bad for constantly asking when i run up against errors, but they just keep coming up.

pygame.draw.circle(screen,WHITE,r.getPos()[:2],10)
TypeError: an integer is required

It's not clear where i have to put/get this integer from.

My apologese guys.

def getPos(self):
        self.RobotA = x,y = 100,200
        self.RobotB = x,y = 700,800
        return self.RobotA, self.RobotB

that worked. I feel quite bad for constantly asking when i run up against errors, but they just keep coming up.

pygame.draw.circle(screen,WHITE,r.getPos()[:2],10)
TypeError: an integer is required

It's not clear where i have to put/get this integer from.

My apologese guys.

My suggestion is to test print WHITE and r.getPos()[:2], they should both be integer tuples.

Okay i test printed WHITE and r.getPos()[:2]
WHITE = (255, 255, 255)
r.getPos()[:2] = ((100, 200), (700, 800))

i was doing a bit of looking around and the pygame.draw.circle takes 5 values.

(screen, color, (x,y), radius, thickness) pygame.draw.circle(screen,WHITE,r.getPos()[:2],10) we have screen,
and the color,
r.getPos()[:2] are 2 different (x,y) tuples,
and we have 10 as the last radius or thickness,

I have tried putting another 10 after that 10 but i still get the same error thats an integer is required.

Strange?

r.getPos()[:2] = ((100, 200), (700, 800))

pygame.draw.circle takes 5 values:
(screen, color, (x,y), radius, thickness)
... pygame.draw.circle(screen,WHITE,r.getPos()[:2],10) ...
we have screen,
and the color,
r.getPos()[:2] are 2 different (x,y) tuples,
and we have 10 as the last radius or thickness,
...
Strange?

Okay, you've solved your own problem you just don't even realize it yet. The circle function is looking for the values you suggested above. Everything you've provided is correct except the r.getPos() part, which you even identified as being incorrect (r.getPos()[:2] are 2 different (x,y) tuples). Now if you take another peek at the circle parameters it's looking for ONE (x,y) tuple. But you're giving it two, as you yourself noted.

Do you see the problem yet? You need to decide which tuple you want to go with, the first or the second.

I have a feeling the confusion comes from the way you're trying to do your indexing. Here's a little example:

>>> r = ((5,2),(7,3))
>>> r[0]
(5, 2)
>>> r[1]
(7, 3)
>>> r[2]
Traceback (most recent call last):
  File "<input>", line 1, in <module>
IndexError: tuple index out of range
>>> r[:2]
((5, 2), (7, 3))
>>>

In most computer languages, indexing starts from position 0 (zero). This index is the first element. The second element is thus at index 1. The index after the second element is 2; however in our case there is no third element, so when we try to explicitly call it, we get an error.

Using a colon in indexing means you want a range of indices. When there is no number present, it represents either the starting or ending index. If I use only a colon with no numbers, it is literally giving me a copy of the entire object, from beginning to end:

>>> r[:]
((5, 2), (7, 3))
>>> len(r)
2

As you can see, the length of r is 2. So even though there is no element at index 2, it is still pointing to the "end" of the list. I'll try to draw a picture of how the indexing is represented in a list:

List:
          [ A  B  ]
Indices:  0  1  2

So when I provide the range of [:2] that's the same as saying [0:2] , which is our starting and ending indices. So in this example we get all elements that are between the 0th and 2nd index (A and B, or first and second elements).

If we wanted just the first element we could either use the index [:1] (a.k.a. the element between index 0 and index 1), or explicitly call it using [0] , which is essentially the same thing.

I hope that explanation was clear, it'd be easier to explain if you were in front of me with a chalk board, but hopefully that makes a little bit more sense for you.

I appreciate the explianation along with that, it was very helpful,
i used [0]
and wrote the draw.circle line again and wrote[1] instead.

This now works and 2 circles are now shown properly on screen when run.

They don't move like they're supposed to (or at all) but thats a different problem.

I think this problem is solved then?

Thanks for both your help Vega and jlm, it was very much appreciated and helpful!

you too slate.

Here is a little pygame circle expriment that should give you a hint ...

# exploring module pygame
# draw a white circle on a black screen
# vegaseat

import pygame as pg

# window/screen width and height
w = 500
h = 500
# default background is black
screen = pg.display.set_mode((w, h))

# set up the circle specs
color = (255, 255, 255)  # (r, g, b) tuple --> white
position = (200, 200)    # (x,y) coordinates of center
radius = 150
# optional width of the circle's border
# if width = 0 (or not given) the circle is filled with color
width = 2
pg.draw.circle(screen, color, position, radius, width)

# update display
pg.display.flip()

# event loop ...
running = True
while running:
    for event in pg.event.get():
        # quit when window corner x is clicked
        if event.type == pg.QUIT:
            running = False

while we're on the subject, after you draw that circle.
How would you go about moving it to the right say 5 pixels.

I tried doing something like: self.move_to(self.x-5,self.y) but it didnt do anything. It might be because my definitions aren't done right.

Is there a simple way of doing this that i might look at and adapt and implement into my program?

Thanks for the circle code, theres quite abit of comments on it thats very helpful in the understanding.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.