Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 Using classes for room movement (text game)
#1
Hello again. This time, I'm using a class to define different rooms, but am having trouble moving between them whenever I run the program:
class Rooms:

    def __init__(self, name, desc, co_x, co_y, directions):
        self.name = name
        self.desc = desc
        self.co_x = co_x
        self.co_y = co_y
        self.loc = (self.co_x, self.co_y)
        self.directions = directions

    def __str__(self):
        return f' {self.name}, {self.desc}, {self.co_x}, {self.co_y}'


room1 = Rooms('Room1', 'the first room', 0, 0, ['north', 'east',])
room2 = Rooms('Room2', 'the second room', 0, 1, ['south',])

current_room = room1


while True:
    command = input('Enter a command: ')
    print(current_room)
    if current_room.loc == (0, 0):
        current_room = room1
    if current_room.loc == (0, 1):
        current_room = room2
    if command in current_room.directions:
        if command == 'north':
            current_room.co_y = current_room.co_y + 1
I was hoping that when I changed the current_room.co_y by adding 1, the program would check current_room.loc and see that it had changed to (0, 1), but that isn't the case. Is there an easier, or more efficient way to set this up? I've been searching around and found a text rpg tutorial but I don't want to copy the tutorial's code since I won't learn anything that way. I understand that the program is just adding one to the current room's y value every time the command is 'north'. However, I want it to change to a different room via the location each time the command is inputted, if there is a room in that direction.
Quote
#2
One thing to do is store them by coordinate in a dictionary. You can even do this as a class attribute and automate it with __init__:

class Rooms:

    map = {}
 
    def __init__(self, name, desc, co_x, co_y, directions):
        self.name = name
        self.desc = desc
        self.co_x = co_x
        self.co_y = co_y
        self.loc = (self.co_x, self.co_y)
        Rooms.map[self.loc] = self
        self.directions = directions
 
    def __str__(self):
        return f' {self.name}, {self.desc}, {self.co_x}, {self.co_y}'
Now you get the current room from the dictionary, and move around based on that:

current_room = Rooms.map[(0, 0)]
while True:
    print(current_room.name)
    print(current_room.desc)
    command = input('Enter a command: ')
    if command in current_room.directions:
        loc = current_room.loc
        if command == 'north':
             current_room = Rooms.map[(loc[0], loc[1] + 1)]
        ...
If the tutorial you found isn't the one I wrote, I not so humbly suggest your read mine (link below in my signature).
Lawr3y likes this post
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures

Quote
#3
Alright, so let me restructure your question, to make sure I understand it right.

Given this code:
class Room:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.loc = (x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.y += 1
print(room_1.loc)
...why is the same tuple printed twice? Or, why didn't the change to the y variable also change the loc variable?

The loc variable is created with copies of the x/y variables, not references to them. So changes to the x/y variables will not effect the loc.

The easy way to fix this, is to use a method to return the current location:
    def get_loc(self):
        return (self.x, self.y)
The other option would be to use objects to store positioning, instead of primitive types (like an int). That would look something like this:
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_loc(self):
        return (self.x, self.y)

    def __str__(self):
        return "Point: ({0}, {1})".format(self.x, self.y)

class Room:
    def __init__(self, x, y):
        self.loc = Point(x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.loc.y += 1
print(room_1.loc)
Lawr3y likes this post
Quote
#4
(Aug-19-2019, 07:02 PM)nilamo Wrote: Alright, so let me restructure your question, to make sure I understand it right.

Given this code:
class Room:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.loc = (x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.y += 1
print(room_1.loc)
...why is the same tuple printed twice? Or, why didn't the change to the y variable also change the loc variable?

The loc variable is created with copies of the x/y variables, not references to them. So changes to the x/y variables will not effect the loc.

The easy way to fix this, is to use a method to return the current location:
    def get_loc(self):
        return (self.x, self.y)
The other option would be to use objects to store positioning, instead of primitive types (like an int). That would look something like this:
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_loc(self):
        return (self.x, self.y)

    def __str__(self):
        return "Point: ({0}, {1})".format(self.x, self.y)

class Room:
    def __init__(self, x, y):
        self.loc = Point(x, y)

room_1 = Room(0, 0)
print(room_1.loc)
room_1.loc.y += 1
print(room_1.loc)

Thanks nilamo, you answered a few questions of mine. :) I hadn't taken into consideration that the loc variable just copied the x and y vars and left it at that. I'll probably use both your method and Ichabod's to make a more expanded piece of code, and then move on to more complicated practices for learning purposes ^^

(Aug-19-2019, 06:59 PM)ichabod801 Wrote: One thing to do is store them by coordinate in a dictionary. You can even do this as a class attribute and automate it with __init__:

class Rooms:

    map = {}
 
    def __init__(self, name, desc, co_x, co_y, directions):
        self.name = name
        self.desc = desc
        self.co_x = co_x
        self.co_y = co_y
        self.loc = (self.co_x, self.co_y)
        Rooms.map[self.loc] = self
        self.directions = directions
 
    def __str__(self):
        return f' {self.name}, {self.desc}, {self.co_x}, {self.co_y}'
Now you get the current room from the dictionary, and move around based on that:

current_room = Rooms.map[(0, 0)]
while True:
    print(current_room.name)
    print(current_room.desc)
    command = input('Enter a command: ')
    if command in current_room.directions:
        loc = current_room.loc
        if command == 'north':
             current_room = Rooms.map[(loc[0], loc[1] + 1)]
        ...
If the tutorial you found isn't the one I wrote, I not so humbly suggest your read mine (link below in my signature).

Your tutorial (and some old MUD's) was my inspiration to make a more complicated version of a text-based rpg, for learning purposes of course. Your response was very informative, I had no clue one could use a dictionary within a class object to automate some processes. I'll grind this information into memory, thanks again!!

p.s Your tutorial is VERY useful for newbie programmers like myself to learn the ropes to some basic python practices, excellent work!
nilamo and ichabod801 like this post
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  Problem with coding for movement keys Aresofthesea 3 366 Jul-05-2019, 07:05 PM
Last Post: nilamo
  Pygame Movement X/Y coord TheHumbleIdiot 2 424 Mar-19-2019, 02:21 PM
Last Post: TheHumbleIdiot
  Movement after KEYUP, only after pause func esteel 2 709 Aug-22-2018, 03:03 PM
Last Post: Windspar
  Text Based Game DuaneJack 3 949 Aug-15-2018, 12:02 PM
Last Post: ichabod801
  [PyGame] How to stop the sprite's movement when it touches the edges of the screen? mrmn 5 2,399 May-13-2018, 06:33 PM
Last Post: mrmn
  Text Game Testing/Dev PKMindBlow 21 3,319 Feb-05-2018, 11:04 PM
Last Post: PKMindBlow

Forum Jump:


Users browsing this thread: 1 Guest(s)