class Ball:
def __init__(self,pos,vel):
self.pos = Vector(pos.x,pos.y)
self.vel = Vector(vel.x,vel.y)
def curx(self):
return (self.pos.x + self.vel.x)
def cury(self):
return (self.pos.y + self.vel.y)
def forcex(velx):
self.vel.deltax(velx)
def forcey(vely):
self.vel.deltay(vely)
class Vector:
def __init__(self,x,y):
self.x = x
self.y = y
def x(self):
return self.x
def y(self):
return self.y
def delx(self,deltax):
self.x = self.x + deltax
def dely(self,deltay):
self.y = self.y + deltay
Here are my two classes, but when I initialize and try to get curx or cury back from ball:
ball = Ball(Vector(0,0),Vector(0,0))
print ball.curx
I get: <bound method Ball.curx of <__main__.Ball instance at 0x1142fd0>>
I feel like there should be a fairly simple answer to this and I'm just not getting it.
curx is a method of Ball. So, you have to invoke it:
print ball.curx()
Edit:
#user2357112 has noticed two more problems:
The definitions of Ball.forcex and Ball.forcey are missing their self parameters.
Vector.x and Vector.y are entirely useless methods. You already have x and y as attributes of Vector through self.x and self.y. So, you should just remove the methods altogether.
Here is how the code should be:
class Ball:
def __init__(self,pos,vel):
self.pos = Vector(pos.x,pos.y)
self.vel = Vector(vel.x,vel.y)
def curx(self):
return (self.pos.x + self.vel.x)
def cury(self):
return (self.pos.y + self.vel.y)
def forcex(self, velx):
self.vel.deltax(velx)
def forcey(self, vely):
self.vel.deltay(vely)
class Vector:
def __init__(self,x,y):
self.x = x
self.y = y
def delx(self,deltax):
self.x = self.x + deltax
def dely(self,deltay):
self.y = self.y + deltay
ball = Ball(Vector(0,0),Vector(0,0))
print ball.curx()
Related
I have the following class which I made:
import math
class Point:
"""Two-Dimensional Point(x, y)"""
def __init__(self, x=0, y=0):
# Initialize the Point instance
self.x = x
self.y = y
def __iter__(self):
yield self.x
yield self.y
def __add__(self, other):
addedx = self.x + other.x
addedy = self.y + other.y
return Point(addedx, addedy)
def __mul__(self, other):
mulx = self.x * other
muly = self.y * other
return Point(mulx, muly)
def __rmul__(self, other):
mulx = self.x * other
muly = self.y * other
return Point(mulx, muly)
#classmethod
def from_tuple(cls, tup):
x, y = tup
return cls(x, y)
def loc_from_tuple(self, tup):
self.x, self.y = tup
#property
def magnitude(self):
# """Return the magnitude of vector from (0,0) to self."""
return math.sqrt(self.x ** 2 + self.y ** 2)
def distance(self, self2):
return math.sqrt((self2.x - self.x) ** 2 + (self2.y - self.y) ** 2)
def __str__(self):
return 'Point at ({}, {})'.format(self.x, self.y)
def __repr__(self):
return "Point(x={},y={})".format(self.x, self.y)
I don't exactly know how to explain it but I basically want to be able to maintain a points id despite mathematical operations. For example:
point1 = Point(2, 3)
point2 = Point(4, 5)
id1 = id(point1)
point1 += point2
print(point1)
Point(x=6, y=8)
print(id1 == id(point1))
True
print(point2)
Point(x=4, y=5)
Is there a reason this doesn't happen in my code. It says False during the id part in mine.
The id is basically the memory address. If you make a new object, it will probably have a different id. If you want a mutable Point object for some reason consider the __iadd__ (and friends) methods instead, which can do the update in-place.
I want to create both a Vector class and a Point class and have a function inside the Vector class that is able to add a Vector object and a Point object, but I don't understand how I have to operate with the internal variables of the classes. This is the code I have right now:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def AddVector(self, point):
point2 = Point(0, 0)
point.x + self.x = point2.x
point.y + self.y = point2.y
return point2
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p1 = Point(2,3)
v1 = Vector(4,7)
def main():
Vector.AddVector(p1,v1)
print(point2.x, point2.y)
main()
First, don't use global variables. It is a bad habit. Move them into main.
Then, the main problem, call method on the instances (p1 and v1) and not on classes (Vector and Point). Third, use the returned variable. Therefore:
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1.AddVector(v1)
print(p2.x, p2.y)
The next problem is, this is invalid syntax:
point.x + self.x = point2.x
The correct way to assign is the other way around:
point2.x = point.x + self.x
Then, you have AddVector method on Vector. It should be on a Point and it should receive a Vector as argument.
All together:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def AddVector(self, v):
point2 = Point(0, 0)
point2.x = self.x + v.x
point2.y = self.y + v.y
return point2
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1.AddVector(v1)
print(p2.x, p2.y)
main()
Of course, it could be nicer, this is more advanced, but here it is for completeness:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Vector({}, {})'.format(self.x, self.y)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, v):
return Point(self.x + v.x, self.y + v.y)
def __repr__(self):
return 'Point({}, {})'.format(self.x, self.y)
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1 + v1
print(p2)
main()
It's my first time with classes in python and I quickly wrote a simple class which lets you move rocket by coordinates. I don't know though how to make a function called let's say "distance" that would return distance between two different instances(rockets). Just to be clear, I know how to calculate the distance, I don't know how to build a function
class Rocket:
def __init__(self , start = (0, 0)):
self.start = start
self.x = self.start[0]
self.y = self.start[1]
if not self.crash():
self.start = (0,0)
print("You crashed!! Your position has been restarted to (0,0)")
def __repr__(self):
return "tbd"
def get_position(self):
return "Your curret posiiton is {}".format(self.start)
def move_side(self,x):
self.x += x
self.start = (self.x, self.y)
def move_up(self,y):
self.y += y
self.start = (self.x, self.y)
if not self.crash():
self.start = (0,0)
print("You crashed!! Your position has been restarted to (0,0)")
def move(self,x,y):
self.x += x
self.y += y
self.start = (self.x,self.y)
def land_rocket(self):
self.y = 0
self.start = (self.x,self.y)
def crash(self):
if self.y >= 0:
return True
return False
def distance(self,other):
return "???"
You need to define a class method that takes an extra argument, which is the object from which you want to calculate the distance.
To apply the cartesian distance formula, know that ** stands for exponentiation and that you can import math.sqrt for square root.
import math
class Rocket:
...
def distance(self, other):
return math.sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2)
The above code only requires other to have x and y attributes, it does not need to be a Rocket instance.
I'd like to overload a method move in a class Point
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, other_point):
...
def move(self, x, y):
...
The following way is not meaningful because x will be a Point object if y is not provided.
def move(self, x, y=None):
if y is None:
other = x
self.x += other.x
self.y += other.y
else:
self.x += x
self.y += y
I'm not happy with the parameter name in the following way either.
def move(self, *param):
if len(p) == 1:
other = param[0]
self.x += other.x
self.y += other.y
else:
self.x += param[0]
self.y += param[1]
What is the best way to overload the method move?
As far as design goes, I recommend against overloading. It is cleaner to have to separate methods:
def move_to_coordinate(self, x, y):
# Do something
def move_to_point(self, other):
self.move_to_coordinate(other.x, other.y)
This way, each function is clearly defined, easy to understand, easy to test. If you insist in overloading:
def move(self, x=None, y=None, other_point=None):
# Validate: (x, y) and other_point should be mutually exclusive
if (x is not None and y is not None) == bool(other_point is not None):
raise ValueError('Specify either (x, y) or other_point')
# Do something
Use keyword arguments:
def move(self, **kwargs):
if 'point' in kwargs:
self.x += kwargs['point'].x
self.y += kwargs['point'].y
elif 'x' in kwargs and 'y' in kwargs:
self.x += float(kwargs['x'])
self.y += float(kwargs['y'])
else:
raise KeyError("Either 'point' or 'x' and 'y' must be present")
I'm trying to build some micro "3d engine" as to understand the basics of this field.
Everything works quite fine except for rotations. I use the standard rotation matrices to do this, yet all 3 of the possible rotations not only rotate the points, they also scale them down. This behaviour is not intended or wished for.
Following is the relevant part of the code (I think):
class Point:
def __init__(self, x, y, z, ui):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
self.ui = ui
def subtractVectorFromPoint(self, vector):
self.x -= vector.x
self.y -= vector.y
self.z -= vector.z
return self
def subtractPointFromPoint(self, point):
TempVector = Vector(0, 0, 0)
TempVector.x = self.x - point.x
TempVector.y = self.y - point.y
TempVector.z = self.z - point.z
return TempVector
def setPointToPoint(self, point):
self.x = point.x
self.y = point.y
self.z = point.z
return self
class Vector:
def __init__(self, x, y ,z):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
#rotate xy plane by 15 degrees on pressing r
if event.key == pygame.K_r:
origin = Vector(0, 0, 0)
UI.draw_background()
for point in pointList:
tempVector = point.subtractPointFromPoint(origin)
point.setPointToPoint(origin)
point.addVectorToPoint(tempVector.rotateXY(15))
point.drawPoint()
That should be all you need I think. Any pointers to where I went wrong are welcome.
I know the classes miss an indent in the example here, I suck at the layout on this website :)
p.s. I tried using the "mpf()" function to increase the precision but this had 0 result.
The problem is in this part:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
self.y is being calculated using a self.x that is already adjusted, resulting in given problem.
A fix for this is using a temp variable like this:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
tempX = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
self.x = tempX
return self