How is 'moveSpeed' used here without being defined anywhere? - python

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.

Related

I want an if statement to add a rectangle to a list, when a condition is met, but it keeps adding them until the condition is false

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)

Python reset variable values to values in _init_

I'm not sure if I'd be framing the question correctly but I'll try my best to explain my problem.
I have the code below where x and y are set to None in the beginning. In a new function, based on a condition, x and y are updated.
class problem()
def __init__(self):
self.x = None
self.y = None
def function(self):
if some_condition:
self.x = 10
self.y = 5
else:
self.x = None
self.y = None
The problem I have here is the total number of variables in __init__() are around 10 and all of these have to set to a value or reset back to original value based on the condition.
Is there a pythonic way to reset the variables back to original __init__() values when the if condition fails?
class problem():
def __init__(self):
self.reset()
def function(self):
if self.x == None:
self.x = 10
self.y = 5
else:
self.x = None
self.y = None
def reset(self):
self.x = None
self.y = None
# These prints will help you understand how it works
per = problem()
per.function()
print(per.x, per.y)
per.reset()
print(per.x, per.y)
As easy as it looks like.
I've entered reset() into init because it's just looks better.
Also i'm highly recommend to check Corey Schafer's OOP Python tutorials, he
explaining in best way i've heard.

using a variable from a class in python

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

Create a picklable Python class

I am trying to create some custom Python classes for my application. When I try to debug my code I can not pick the instances of my custom classes, I receive the error "Object XXX is not picklable".
I found this page https://docs.python.org/3/library/pickle.html#what-can-be-pickled-and-unpickled but I don't understand how I should implement the methods that make my class picklable.
For example how would you modify the following classes so that I can pick instances of them?
class Point3D:
def __init__ (self, x, y, z):
self.x = x
self.y = y
self.z = z
def move(self, vector):
self.x += vector.x
self.y += vector.y
self.z += vector.z
return
def isValidPoint(self):
isNotValid = False
isNotValid = math.isnan(self.x) or math.isnan(self.y) or math.isnan(self.z)
return not isNotValid
And
class PointCloud3D:
def __init__ (self):
self.points = []
def getNumberOfPoints(self):
return len(self.points)
def addPoint(self, point):
self.points.append(point)
return
def addPointCloud3D(self, additionalPointCloud3D):
for self.point in additionalPointCloud3D:
self.addPoint(point)
def getCloudCenter(self):
numberOfPoints = self.getNumberOfPoints()
centersSumX = 0
centersSumY = 0
centersSumZ = 0
for point in self.points:
centersSumX = centersSumX + point.x
centersSumY = centersSumY + point.y
centersSumZ = centersSumZ + point.z
centerX = centersSumX/numberOfPoints
centerY = centersSumY/numberOfPoints
centerZ = centersSumZ/numberOfPoints
center = Point3D(float(centerX), float(centerY) , float(centerZ))
return center
While here you can find the code that I am trying to debug:
from classDatabase import Point3D, PointCloud3D
testPoint1 = Point3D(1.5, 0.2, 2.3)
testPoint2 = Point3D(3.5, 1.2, 5.3)
testPointCloud3D = PointCloud3D()
testPointCloud3D.addPoint(testPoint1)
testPointCloud3D.addPoint(testPoint2)
Finally a screenshot of the issue:

Changed all objects value in list in object changed instead of only one

I have problem with my program. When I try to change object value (which is in list) I changed all object's value in that list.
My code:
class obj:
def __init__(self, x, y):
self.x = x
self.y = y
def mirrorise(self, mirror):
self.mirror = mirror
if self.mirror.type == 'teleporterx':
self.x -= (self.x-(self.mirror.x+self.mirror.x1/2))*2
class person(obj):
def __init__(self, x, y):
self.x = x
self.y = y
self.pos = [obj(self.x, self.y)]
def mirrored(self, mirrors):
self.count = 0
self.mirrors = mirrors
self.mens = 0
for men in self.pos:
self.mens += 1
for mirror in self.mirrors:
if self.count == 1:
for men in range(self.mens):
self.pos.append(self.pos[men])
self.count = 1
self.count = 0
for men in self.pos:
men.mirrorise(self.mirrors[self.count])
self.count += 1
if self.mirrors[self.count-1] == self.mirrors[-1]:
self.count = 0
class mirror:
def __init__(self, x, y, x1, y1, type):
self.x = x
self.y = y
self.x1 = x1
self.y1 = y1
self.type = type
After in code I call person object called I and two mirror objects called mirr and mirr2 with type teleportx. When I write:
I.mirrored([mirr, mirr2])
it changes x for all objects in I.pos. If I write
I.pos[3].mirrorise(mirr)
it still changes all x. Even if I write:
I.pos[3].x -= (I.pos[3].x-(mirr2.x+mirr.x1/2))*2
it changes all values. So, is it some Python rule or I have mistake?
You are adding references to your one original obj() instance:
self.pos.append(self.pos[men])
That's not a copy; that's just another reference to the same object.
Create a new obj() instance instead:
self.pos.append(obj(self.pos[men].x, self.pos[men].y))

Categories

Resources