[program-l] Re: Python circular import issue

  • From: "Cody Hurst" <dmarc-noreply@xxxxxxxxxxxxx> ("codyt20")
  • To: program-l@xxxxxxxxxxxxx, Jonathan Fine <jfine2358@xxxxxxxxx>
  • Date: Fri, 4 Nov 2022 08:02:17 -0700

Hi John,


  Thanks so much for your feedback. If you grab the code again from the link I have updated it early this morning with it working.

  Yes, I am familiar with classes and instances of classes, I.E. objects. I'm currently trying to get a good keyboard input implementation but it is being a bit finicky.

  I simply just had to create an addMap() method in the keymanager, pass in the map object and I was able to move around the map just fine. But, there may be an easier way of doing this. Later, I'll code a networking component so the code needs to be scalable. I figured I could eventually save these maps into files or whatever to be loaded back into the game by way of dictionaries.

  Anyway, I will be adding additional methods for the player, but I figured I could access everything, including player info and map info by passing in the entire newmap object to the mapKeys method. Have a look at the updated code from earlier and see what you think. Your suggestions are valuable, thank you.




On 11/4/2022 7:37 AM, Jonathan Fine wrote:

Hi Cody

I'm a sighted Python programmer, although not a user of pygame. I've downloaded and am looking at your code, and I hope I can help you. But please forgive me if out of ignorance I talk nonsense about pygame.

In your top-level file ol.py

 1. You create instances of Keymanager, Player and Maptool.
 2. You then so to speak link these instances to each other.
 3. You then define and run your main() method.

Describing your issue, you wrote "how can I get keyboard input to the instance of the map object so my move method will work?". Thank you for this clear description of the problem.

Your Keymanager has a mapKeys method that gets events from pygame and does things with them. Your main() function calls this mapKeys method.

Your Player class creates player objects that have (x, y, z) coordinates and some other attributes. I suggest you add to your player class some methods that allow instance attributes to be changed. For example (not checked)

    def move_rel(self, x=0, y=0, z=0):
        self.x = self.x + x
        self.y = self.y + y
        self.z = self.z + z

and now you can write player.move_rel(x=1) to move the player to the right by 1 unit.

Back to the Keymanager.  Looking at its code, I see that the only way it can communicate movements is via self.map. And looking at your Maptool class I notice that it has the player movement code that I earlier suggested you place in the Player class.

By the way, I hope you're comfortable with the difference between a class and an instance of a class. From your code it seems that you are.

Tracing events, I see that mapKeys can result in self.newmap.moveForward(). When things are correctly set up this results in a Maptool instance calling its moveForward, and hence for some perhaps none players in the list moving the player.

At this point I become confused, because I would expect the player to be already known at the time of the keyboard event. I suspect that your linkage and import problem arises at least in part because your Maptool has and depends on a list of players.

Here's what I might do in your situation. I would backtrack to a simpler problem, and solve that first. And simplify the components where possible. And also I have a big hint for you, which is to replace your key manager with an iterable.

Once you have an iterable, you can use it in a for loop.

    for item in items:
        # do something with item

In your case (not tested)

    def map_keys(events):
        for event in events:
              if event.type == pg.KEYDOWN:
                 # code much as before except write
                 yield 'moveForward'
                 # instead of self.newmap.checkPos()

By the way, to use the resulting 'moveForward' you might want first to understand:

>>> name.upper()
'CODY'
>>> getattr(name, 'upper')
<built-in method upper of str object at 0x7f9b7ca888b0>
>>> getattr(name, 'upper')()
'CODY'

I think that's enough for now. I hope at least some of this has been helpful. I think what would really help you would be some well-explained examples of similar pygame problems being solved. But although I know Python, the above is the closest I've got to writing PyGame code.

with best wishes

Jonathan






--
Cody Hurst
Accessible Technology Specialist
Portland Community College
CCENT, Network+, A+

Other related posts: