So I've been working on this game (I'm a big noob at python and I've only worked on this for like 3 days) and I've been trying to move the Location (Add or Subtract one from Location's x and y values) but the fuction doesn't work. I know because I put a print in the function and the print didn't work at all. What is wrong? (I have created a folder for this project and there is a folder called Decisions containing 2 files.)
Locations.py:
class Location:
def __init__(self, x, y):
self.x = x
self.y = y
def move_forward(self):
self.y = self.y + 1
return self.y
def move_back(self):
self.y = self.y - 1
return self.y
def move_left(self):
self.x = self.x - 1
return self.x
def move_right(self):
self.x = self.x + 1
return self.x
main.py (Main Function):
import Decisions
import Characters
import Locations
def main():
Player = Characters.Character([], 100)
Loc = Locations.Location(0, 0)
answer = Decisions.choice_yes_no.choice_yes_no("You woke up, discovering
that somehow you were in the middle of a dark dungeon. A sword lies to the
left of you, pick it up? (Yes/No) ")
if answer == True:
print("You picked up the sword.")
Player.add_item("Sword")
elif answer == False:
print("You chose not to pick up the sword.")
answer_2 = Decisions.choice_direction.choice_direction("You stood up,
patting the dust off your clothes, you looked around. The room was dark and
you view was limited to a few meters. Where do you go?
\n(Left/Right/Forward/Back) ")
if answer == "forward":
Loc.y = Loc.y + 1
elif answer == "back":
Loc.move_back()
elif answer == "left":
Loc.move_left()
elif answer == "right":
Loc.move_right()
print(Loc.x)
print(Loc.y)
main() #REMOVE BEFORE USING#
The function add_item works just fine, what is wrong? There aren't any errors, it's just when I print the x and y values at the end they stay 0.
Related
Im running Python 3.8.2 and Pygame 2.0.0.dev6 in Pycharm.
I read a few of the other threads on similar issues but couldn't figure out why I'm getting this error in this instance. The purpose of this post is two-fold: 1 is that I would like to understand this error (I am very new to programming), and 2 is that I would like to know if there is a better method to accomplish what I am trying to do.
I am trying to make enemies that sway back and forth in the x-direction, their change being triggered either by a certain amount of time passing or (haven't added this yet) a certain number of collisions with other enemies.
The error seems to be triggered by the second if statement in the movement method here:
class EnemyShip(ShipGeneral):
MOVEMENT_TIME = 180
SHIP_TYPE_DIC = {
'pawn': Images().pawn_ship_img,
'boss': Images().boss_ship_img
}
def __init__(self, x, y, enemy_type=None):
super().__init__(x, y, enemy_type)
self.ship_img = self.SHIP_TYPE_DIC[enemy_type]
self.mask = pygame.mask.from_surface(self.ship_img)
self.health = 100
self.movement_time_counter = 0 # Defaut set to zero
def movement_timer(self):
if self.movement_time_counter >= self.MOVEMENT_TIME:
self.movement_time_counter = 0
elif self.movement_time_counter > 0:
self.movement_time_counter +=1
def movement(self): # TODO fix enemy movement to prevent overlapping and allow for advances
y_vel = 10
x_vel = 2
boundaries = Settings()
if self.y <= 100:
self.y += y_vel
if self.movement_time_counter == 0: # should be true and run first in the while loop
x_direction = random.choice(['R', 'L'])
self.movement_time_counter += 1
if x_direction == 'R' and self.x + self.ship_img.get_width() + x_vel < boundaries.screen_width:
self.x += x_vel
if x_direction == 'L' and self.x > 0:
self.x -= x_vel
I call the class and the functions in the game's main while loop here:
enemies = []
running = True
while running:
clock.tick(FPS)
gf.check_events() # checks for user quit event
if len(enemies) == 0: # updates level and spawns new enemies after each wave
level += 1
fleet_size += 5
for enemy in range(fleet_size):
enemy = EnemyShip(
random.randrange(20, 800 - 20),
random.randrange(-1000, -100, 10),
enemy_type=random.choice(['pawn', 'pawn', 'pawn', 'pawn', 'boss'])
)
enemies.append(enemy)
for enemy in enemies: # enables each enemy to move
enemy.movement()
enemy.move_missile(7, playership)
enemy.movement_timer()
if enemy.health <=0:
enemies.remove(enemy)
If I run this I get the following error:
File >"/Users/aaronbastian/Documents/PythonCode/Part_II_Projects/alien_invasion/ships.py", line 114, in movement
if x_direction == 'R' and self.x + self.ship_img.get_width() + x_vel < boundaries.screen_width:
UnboundLocalError: local variable 'x_direction' referenced before assignment
I don't understand the error because I thought self.movement_time_counter == 0 should evaluate to True and thus assign x_direction before the following if statements were run.
If someone could explain to me my error, I would greatly appreciate it! Also, I apologize if this is a redundant post, I just couldn't understand the other similar threads.
This error is raised during compilation because you have not initialized the variable anywhere. Just initialize the variable with some default value in the ____init____().
Example:
self.x_direction = None
I am coding a simple maze game. I've created a Player class with a move method -- but whenever I want to check if the move is in the available paths list, it does run the move method and changes my character position.
class Player :
def __init__ (self, position):
self.position = position
def move (self, direction):
if direction == "right": self.position[0] += 1
elif direction == "left": self.position[0] -= 1
elif direction == "up": self.position[1] -= 1
elif direction == "down": self.position[1] += 1
return self.position
maze_paths = [[0,0], [1,0]]
mac = Player([0,0])
direction = 'left'
if mac.move(direction) in maze_paths:
print('ok')
else:
print('No way!')
print('Final position is: %r' % (mac.position))
The output I expect is:
No way!
Final position is: [0, 0]
...because the move left shouldn't be allowed with the maze as it's defined. However, what we have instead is:
No way!
Final position is: [-1, 0]
...with the move happening even though it shouldn't be allowed.
As #TimRichardson suggested in the comments, the act of calculating state should be split out from the act of changing state. Functional programming languages are built to make this easy, but Python isn't one -- so you need to jump through some hoops.
Consider splitting move into two methods, like the calculate_move and do_move shown below:
class Player:
def calculate_move(self, direction):
"""Calculate where we would be if we moved in a direction"""
emulated_position = self.position[:] # make a copy
if direction == "right": emulated_position[0] += 1
elif direction == "left": emulated_position[0] -= 1
elif direction == "up": emulated_position[1] -= 1
elif direction == "down": emulated_position[1] += 1
return emulated_position
def do_move(self, direction):
"""Actually move in the given direction"""
self.position = self.calculate_move(direction)
maze_paths = [[0,0], [1,0]]
mac = Player([0,0])
direction = 'left'
if mac.calculate_move(direction) in maze_paths:
mac.do_move(direction)
print('ok')
else:
print('No way!')
print('Final position is: %r' % mac.position)
...which properly emits as output:
No way!
Final position is: [0, 0]
Create a meningful separate validate function like. Did this on my phone.
def validateMove(direction):
if direction == "right":
return self.position[0] + 1 in self.maze_paths
if direction == "down":
return self.position[1] + 1 in self.maze_paths
if direction == "left":
return self.position[0] - 1 in self.maze_paths
if direction =="up":
return self.position[1] - 1 in self.maze_paths
return false
Im trying to make a stepping function in python for rhino,
The function is supposed to make a step in a random direction, without going backwards.
How do i prevent a step back?
import rhinoscriptsyntax as rs
import random as r
r.seed(seed)
class Walker:
def __init__(self):
self.x = 0
self.y = 0
def point(self):
shape = rs.AddPoint(self.x, self.y, 0)
return shape
def step(self):
choice = r.randint(0,3)
choice = r.randint(1,3)
if (choice == 0):
self.x = self.x + r.choice(uList)
elif (choice == 1):
self.x = self.x - r.choice(uList)
elif (choice == 2):
self.y = self.y + r.choice(uList)
else:
self.y = self.y - r.choice(uList)
uList = [8,11,14]
w = Walker()
pList = []
for t in range(time):
w.step()
pList.append(w.point())
for t-1 in range(time):
a = pList
This line:
choice = r.randint(0,3)
chooses one of 4 directions randomly. But if you don't want to go backwards, then you only want forward, left and right. So change the parameters to randint() so that it only chooses from 3 possible numbers, avoiding the one that corresponds to the direction you are calling backwards, whichever that is.
Sorry if I don't do this correctly, I am new here. I am trying to make it so that raw_input loops through saving the value of self.x every time so that it asks "r or l"? Whenever you click enter, then raise or lower self.x but I'm not sure how to. If someone could check my work, that would mean a lot. Thank you.
q = raw_input("r or l: ")
class game:
def __init__(self):
self.x = 0
def raise_n(self):
self.x += 1
return self.x
def lower_n(self):
self.x -= 1
return self.x
def main():
g = game()
while q == "r":
print g.raise_n()
break
while q == "l":
print g.lower_n()
break
main()
I also tried this, but it didn't save the value of self.x even if I tried to call main() again.
q = raw_input("r or l: ")
class game:
def __init__(self):
self.x = 0
def raise_n(self):
self.x += 1
return self.x
def lower_n(self):
self.x -= 1
return self.x
def main():
g = game()
while q == "r":
print g.raise_n()
break
while q == "l":
print g.lower_n()
break
main()
Any help would be very useful, thank you!
Your second approach was closer to a valid solution. There are several approaches, and below I show you one, without introducing too many changes. Basically:
The main() function is executed in an endless loop. Change the True condition if you want to change the stop condition.
The question is asked and evaluated every time it enters the main() function. Afterwards, it checks if it has to run the raise_n() or lower_n() methods.
The code:
class game():
def __init__(self):
self.x = 0
def raise_n(self):
self.x += 1
return self.x
def lower_n(self):
self.x -= 1
return self.x
def main():
q = raw_input("r or l: ")
if q == "r":
print g.raise_n()
if q == "l":
print g.lower_n()
g = game()
while True:
main()
EDIT: In order to put as condition for the while loop to iterate a determinated number of times, a constant can be succesively increased and check if it has reached the desired limit:
#... Copy previous code here
g = game()
iterations_limit = 10 #Substitute 10 by any positive integer
while k > iterations_limit:
k += 1 #Increase variable k
main()
I am new to programming in python and, I started writing a simple text based adventure game. I came across a problem when passing an object from one function to another. Here is my code:
import random
import time
num = random.randint(0,2)
xp1 = random.randint(1,2)
class player:
def __init__ (self, name, health, strength, defense, potion, xp, level):
self.__health = health
self.__strength = strength
self.__defense = defense
self.__name = name
self.__potion = potion
self.__xp = xp
self.__level = level
def getName(self):
return self.__name
def getHealth(self):
return self.__health
def getStrength(self):
return self.__strength
def getDefense(self):
return self.__defense
def getPotion(self):
return self.__potion
def getXP(self):
return self.__xp
def getLevel(self):
return self.__level
def setHealth(self):
self.__health = 10
def setLevel(self):
self.__level = 1
def subHealth(self, num):
self.__health -= num
def subPotion(self):
self.__potion -= 1
return self.__health
def addPotion(self, num1):
self.__potion += num1
def addHealth(self):
self.__health +=2
def addStrength(self):
self.__strength += 1
def addDefense(self):
self.__defense += 1
def addXP(self):
self.__xp += xp1
def addLevel(self):
self.__level += 1
self.__addHealth += 1
self.__defense += 1
self.__strength += 1
def battle(enemy, player1, name1):
player1 = player(name1, player1.getHealth(), player1.getStrength(), player1.getDefense(), player1.getPotion(), player1.getXP(), player1.getLevel())
enemy = player('Dongus', enemy.getHealth(), enemy.getStrength(), enemy.getDefense(), enemy.getPotion(), enemy.getXP(), enemy.getLevel())
s = 0
while s == 0:
time.sleep(1)
attack =int(input("Type 1 to attack, type 2 to use a potion."))
if attack == 1:
time.sleep(1)
print("Dongus's health is", enemy.subHealth(num))
print("Dongus hit you and your health is now at", player1.subHealth(num-player1.getDefense()))
elif attack == 2:
time.sleep(1)
print("You used a potion.")
player1.addHealth(), player1.subPotion()
if player1.getHealth() > 10:
player1.setHealth()
print("Dongus hit you and your health is now at", player1.subHealth(num-player1.getDefense()))
if enemy.getHealth()<=0:
print("Congratulations, you won! You recieved", xp1, "xp!")
player.addXP()
s = 2
def main():
name1 = input("What would you like your name to be?")
time.sleep(1)
print("Hello,", name1, "you are on a quest to save otis from the evil Dongus. You must slay him, or Otis will poop.")
time.sleep(2)
player1 = player(name1, 10, 2, 1, 0, 0, 1)
enemy = player('Dongus', 8, 4, 0, 0, 0, 0)
print("Your stats are, health:", player1.getHealth(), "strength:", player1.getStrength(), "and defense:", player1.getDefense())
time.sleep(2)
print("Fight!")
pick = input("You found a health potion! Press 'p' to pick it up.")
p = 0
while p == 0:
if pick == "p":
print("You added a potion to your inventory.")
player1.addPotion(1)
p = 2
else:
print("You have no potions, you should probably pick this one up.")
player1.addPotion(1)
p = 2
battle(enemy, player1, name1)
if self.__getXP() == 1:
print("You leveled up. You are now level 2.")
player1.addLevel()
print("Your stats are, health:", player1.getHealth(), "strength:", player1.getStrength(), "and defense:", player.getDefense())
loot1 = int(input("Type ''1'' to loot the enemy chest."))
if loot1 == 1:
print("You recieved two potions!")
player1.__addPotion(2)
enemy.setHealth(10)
battle(enemy, player1, name1)
main()
Now the problem is when I run the game, I get to a point where I type "1" to attack the enemy, but it says, for some reason, that after attacking the enemy, the enemies health is at "None". This is the same case when the enemy attacks player1, it says player1's health is at "None". I assume that "None" is the default value in python 3.4.1, so my thinking is that the player1's object from def main() are not being transferred over to def battle() and I cannot see the reason why this is happening. I most likely am missing something here, or it is something I do not already know about Python that is causing the issue. Does anybody know what I can do to fix this, and why it is doing this?
BTW some of the terms I am using may be wrong, so please correct me if they are... I have only been coding for 2 weeks :p.
Thanks!!!
First, received not recieved
2nd yes, If you have a Python function that does not return a value, the result is None
# dummy will return "Positive" or None
def dummy(x):
if X > 0:
return "Positive"
So, you probably want to change
def subHealth(self, num):
self.__health -= num
to
def subHealth(self, num):
self.__health -= num
return self.__health
Your question re: the "player" classes from def main() are not being transferred over to def battle() does not really make sense to me.
But, I see that in the first 2 lines of battle, you are replacing the formal parameters player1 and enemy with local variables, this seems like odd usage in your program.