I think this question has been asked before but I have not found an answer suited to my problem. I basically have a class for different characters, which each have a cost. When creating a character, I want to take their cost away from the players score.
Here is an example of a class:
class Assassin(pygame.sprite.Sprite):
def __init__(self, x, y, row, column):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("assassin.png")
self.x = x
self.type = "assassin"
self.y = y
self.rect = self.image.get_rect(center=(self.x, self.y))
self.damage = 60
self.health = 40
self.speed = 2
self.move = False
self.cost = 4
self.row = row
self.column = column
And here is the code where I would want to use the variable:
if assassin.collidepoint(pygame.mouse.get_pos()) and mouseDown[0]:
for block in blockGroup:
if block.team1Taken == False and block.column ==1:
team1.add(Assassin(block.team1[0], block.team1[1], block.row, block.column))
block.team1Taken = True
score -= Assassin.__init__.cost #Example of what I think you would do
break
I hope I have explained this well enough to understand what I want.
You can't call score -= Assassin.__init__.cost in python.
The init method is the constructor of the Class and should be used to do so.
The value that you want is inside the object that you created, so you could call assassin.cost directly, assuming that assassin is the object.
So, you just need to change to:
if assassin.collidepoint(pygame.mouse.get_pos()) and mouseDown[0]:
for block in blockGroup:
if block.team1Taken == False and block.column ==1:
current_assassin = Assassin(block.team1[0], block.team1[1], block.row, block.column)
team1.add(current_assassin)
block.team1Taken = True
score -= current_assassin.cost
break
You will need to keep a reference to the Assassin instance you create and then access its cost attribute:
if assassin.collidepoint(pygame.mouse.get_pos()) and mouseDown[0]:
for block in blockGroup:
if block.team1Taken == False and block.column == 1:
new_assassin = Assassin(block.team1[0], block.team1[1],
block.row, block.column)
team1.add(new_assassin)
block.team1Taken = True
score -= new_assassin.cost
break
Related
i have this code:
class PLAYER:
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1
#print(self.score)
i want to calling self.score from outside the PLAYER class
You need to add a constructor (the init method) as done below, and within the constructor you must define self.score, as well as all the other fields you want your PLAYER class to have. In the code below I am assuming that when you are initializing a PLAYER object that you are providing the new_block, direction, and body information, however you defined these fields, which is unclear from the question.
class PLAYER:
def __init__(self, new_block,direction,body):
self.score = 0
self.new_block = new_block
self.direction = direction
self.body = body
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1
I'm very new to pygame and python in general, and I'm trying to make a simple game. In the code, I made a class Enemy, and an instance of it enemy, here.
class Enemy:
def __init__(self):
self.list = []
self.size = 20
self.x = random.randint(0 , WIDTH - self.size)
self.y = random.randint(70 , HEIGHT - self.size)
self.new_enemy = pygame.Rect(self.x , self.y , self.size , self.size)
def add_enemy(self):
if score % 5 == 0 and score != 0:
self.list.append(self.new_enemy)
print(enemy.list)
#to see if it works
enemy = Enemy()
But when I run enemy.add_enemy(), while score == 5 (or 10, 15, etc), it adds not just one but tons of items to the list. Is there a way around this? help would be appreciated.
So i still have doubts about this, since i dont have more of the code.
But fundamentally what's happening here is that self.newenemy is being delared and created, then in add_enemy you run self.list.append(self.newenemy) which is essentially adding the same object into the list. so the list has n objects, but they are all the "same" as in not copy or duplicates, but the exact same. so if you were to "kill" list[0] enemy they all would die.
EDIT: Additionally, your randint will always generate the same values, so x and y will always be the same once the class gets created.
try changing your code to something like this. NOTE the return in add_enemy after the append is done.
class Enemy:
def __init__(self):
self.list = []
self.size = 20
def add_enemy(self):
if score % 5 == 0 and score != 0:
self.list.append(pygame.Rect(self.get_rand_x() , self.get_rand_y() , self.size , self.size))
return
def get_rand_x(self):
return random.randint(0 , WIDTH - self.size)
def get_rand_y(self):
return random.randint(70 , HEIGHT - self.size)
enemy = Enemy()
enemy.add_enemy()
print(enemy.list)
I have just started OOPS and am completely new to it. I have a very basic question regarding the different ways I can call a function within another function in same class.
class StuffAnimal:
def __init__(self,name,color,weight,issitting):
self.name = name
self.color = color
self.weight = weight
self.issitting = issitting
self.x = 0
self.y = 0
self.situation = " "
def standup (self):
if self.issitting == True :
print("the stuff toy is sitting")
return "sit"
else :
print ("the stuff toy is not sitting")
return "notsit"
def move_teddy (self):
self.situation = standup(self.issitting)
if self.situation == 'sit' :
print ("teddy is not in the situation to move please change issitting to True")
elif self.situation == 'notsit' :
print ("teddy is in the situation to move please give cordinates")
self.x = int(input("x cordinates : "))
self.y = int(input("y cordinates : "))
print("teddy moved to ",self.x,self.y)
but when i tried to call the function I got the following error.
teddy.move_teddy()
NameError: name 'standup' is not defined
This doesn't works. Can someone explain where did I go wrong.
Thank you.
As the method definition tells the method def standup(self)
is a instance method, (because of self)
does not accept parameters (because there is only self)
So the good way to cal it is
self.situation = self.standup()
Regarding the name of your methods, I'd say standup should set issitting to False, and define a sitdown method. Then the code of move_teddy would be more logic
class StuffAnimal:
def __init__(self, name, color, weight, issitting):
self.name = name
self.color = color
self.weight = weight
self.issitting = issitting
self.x = 0
self.y = 0
def standup(self):
self.issitting = False
print("the stuff toy is now up")
def sitdown(self):
self.issitting = True
print("the stuff toy is now sit")
def move_teddy(self):
if self.issitting:
print("teddy is not in the situation to move please change issitting to True")
else:
print("teddy is in the situation to move please give cordinates")
self.x = int(input("x cordinates : "))
self.y = int(input("y cordinates : "))
print("teddy moved to ", self.x, self.y)
teddy = StuffAnimal("teddy", "black", 20, True)
teddy.move_teddy()
teddy.standup()
teddy.move_teddy()
teddy is not in the situation to move please change issitting to True
the stuff toy is now up
teddy is in the situation to move please give cordinates
x cordinates : 12
y cordinates : 34
teddy moved to 12 34
self parameter doesn't require to be called, and when you call a function from a class in the same class, your self. prefix !
class StuffAnimal:
def __init__(self,name,color,weight,issitting):
self.name = name
self.color = color
self.weight = weight
self.issitting = issitting
self.x = 0
self.y = 0
self.situation = " "
def standup (self):
if self.issitting == True :
print("the stuff toy is sitting")
return "sit"
else :
print ("the stuff toy is not sitting")
return "notsit"
def move_teddy (self):
self.situation = self.standup()
if self.situation == 'sit' :
print ("teddy is not in the situation to move please change issitting to True")
elif self.situation == 'notsit' :
print ("teddy is in the situation to move please give cordinates")
self.x = int(input("x cordinates : "))
self.y = int(input("y cordinates : "))
print("teddy moved to ",self.x,self.y)
I found this pygame project online and was curious how 'moveSpeed' is being used as a number? like below?
def move(self, moveSpeed):
self.x -= moveSpeed
class HurdleManager:
def __init__(self, scale, spawnRange):
self.img = transform.scale(image.load('homework.png'), (7 * scale, 15 * scale))
self.spawnRange = spawnRange
self.hurdleList = []
self.scale = scale
def update(self, doSpawn, moveSpeed):
if doSpawn:
self.spawn()
self.manage(moveSpeed)
def manage(self, moveSpeed):
hurdles2 = []
for hurdle in self.hurdleList:
hurdle.update(moveSpeed)
if hurdle.onScreen():
hurdles2.append(hurdle)
self.hurdleList = hurdles2
spawnTick = 0
def spawn(self):
if self.spawnTick >= self.spawnRange[1]:
newHurdle = HurdleClass(windowX, self.img, 7 * self.scale, 15 * self.scale)
self.hurdleList.append(newHurdle)
self.spawnTick = 0
elif self.spawnTick > self.spawnRange[0]:
if random.randint(0, self.spawnRange[1] - self.spawnRange[0]) == 0:
newHurdle = HurdleClass(windowX, self.img, 7 * self.scale, 15 * self.scale)
self.hurdleList.append(newHurdle)
self.spawnTick = 0
self.spawnTick += 1
hurdleManager = HurdleManager(3, (45, 90))
class HurdleClass:
def __init__(self, x, img, width, height):
self.x = x
self.img = img
self.width = width
self.height = height
self.y = ground - height
def update(self, moveSpeed):
self.move(moveSpeed)
self.show()
def move(self, moveSpeed):
self.x -= moveSpeed
def show(self):
window.blit(self.img, (self.x, self.y))
def onScreen(self):
if self.x + self.width > 0:
return True
else:
return False
def move(self, moveSpeed):
def move says "I'm creating a function definition here. When I've finished defining it, I'd like the function to be bound to the name "move" in the current scope. Also, the function can use bindings from the current scope."
(self, moveSpeed) says "To run this function, I need two arguments. The first one is called self and the second one is called moveSpeed."
An argument is also known as a parameter. Just like when being asked to cut a cake, you might ask "Which cake?" and "Which knife?". In most programming languages, you pass parameters (also known as arguments) in the order each is declared. For example, given:
def cut(cake, knife):
...
writing cut(a, b) would "call" cut with the caller's "a" bound to the called function's "cake" variable and with the caller's "b" bound to the called function's "knife" variable.
In Python, you can also give the names of arguments explicitly. For example, cut(cake=a, knife=b) would do the same thing. These are called "keyword arguments." You don't need to pass things in declaration order when you use keyword arguments. For example, cut(knife=b, cake=a) would do the same thing as well.
I'm trying to create two subclasses based on the same parent class, so that they each have their own versions of the same variables defined in the parent object. However I realized that changing these variables in one of these subclasses will cause the versions in the other subclass to change as well. I know I am probably not fully understanding the idea of Inheritance. Please help!
import random
class PlayerParent():
id = 1
# Cooperate: True; Betrayal: False
opponent_moves_history = {}
self_moves_history = {}
def append_opponent_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.opponent_moves_history[round_num] = c_true
def append_self_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.self_moves_history[round_num] = c_true
score = int(0)
def score_keeper(self, round_num):
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == False):
self.score += 7
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == True):
self.score += 5
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == True):
self.score += 1
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == False):
self.score += 2
def get_score(self):
return self.score
class TitForTat(PlayerParent):
def rule(self, round_num):
if len(self.opponent_moves_history) == 0:
return True
else:
return self.opponent_moves_history[round_num - 1]
class Random(PlayerParent):
def rule(self, round_num):
random_num = random.uniform(0, 1)
if random_num >= 0.5:
return True
else:
return False
Random = Random()
Random.id = 1
TitForTat = TitForTat()
TitForTat.id = 2
def match(a, b):
game_counter = 1
# while game_counter <= 10:
#a_result = a.rule(game_counter)
# b_result = b.rule(game_counter)
# print(a_result, b_result)
# a.append_self_history(game_counter, a_result)
# b.append_opponent_history(game_counter, a_result)
# b.append_self_history(game_counter, b_result)
# a.append_opponent_history(game_counter, b_result)
# a.score_keeper(game_counter)
# b.score_keeper(game_counter)
# game_counter += 1
# print(a.get_score(), b.get_score())
a.self_moves_history[1] = True
print(a.self_moves_history, '\n', b.self_moves_history)
match(Random, TitForTat)
Resulting a.self_moves_history and b.self_moves_history is identical even though no alteration has been done to the b class variable.
I commented out chunks of the codes just to test where went wrong.
You are making opponent_moves_history a class variable, so naturally any change to it is class-wide.
In your case you should make opponent_moves_history, along with self_moves_history and id instance variables instead, so that changes made to them are specific to the instances.
class PlayerParent():
def __init__(self):
self.id = 1
self.opponent_moves_history = {}
self.self_moves_history = {}