i am trying to write a code for the game pong but i am facing a problem when trying to control the range of the paddles positions , the question is that : is there a way in python to keep a variable inside a certain range (with a maximum value and minimum value )that when the variable changes (to be increasing ) it will stuck on the maximum value of that range , and when this variable decreases it will stuck on the minimum value ? .
i had written this code :
Range = range(HALF_PAD_HEIGHT, HEIGHT - HALF_PAD_HEIGHT)
if (paddle1_pos[1] in Range) and (paddle2_pos[1] in Range):
paddle1_pos[1] += paddle1_vel[1]
paddle2_pos[1] += paddle2_vel[1]
when the values of the paddles positions (paddle1_pos[1] and paddle2_pos[1] ) are going out off the range i am not able to update its position any more using the keyboard ( through the variables (paddle1_vel[1] and paddle2_val[2]) so , i am thinking that maybe exist something in python that allow me to update paddle_pos and when i reach one side of the range it keeps me on that side till i reverse the direction of updating .
hopefully the question is clear .
thanks
You could define your own "bounded" numeric type. For example if paddle1_pos[1]
was an integer value you could create a class like the following and use it instead
class BoundedInt(int):
def __new__(cls, *args, **kwargs):
lower, upper = bounds = kwargs.pop('bounds')
val = int.__new__(cls, *args, **kwargs) # supports all int() args
val = lower if val < lower else upper if val > upper else val
val = super(BoundedInt, cls).__new__(cls, val)
val._bounds = bounds
return val
def __add__(self, other):
return BoundedInt(int(self)+other, bounds=self._bounds)
__iadd__ = __add__
def __sub__(self, other):
return BoundedInt(int(self)-other, bounds=self._bounds)
__isub__ = __sub__
def __mul__(self, other):
return BoundedInt(int(self)*other, bounds=self._bounds)
__imul__ = __mul__
# etc, etc...
if __name__ == '__main__':
v = BoundedInt(100, bounds=(0, 100))
print type(v), v
v += 10
print type(v), v
w = v + 10
print type(w), w
x = v - 110
print type(x), x
Output:
<class '__main__.BoundedInt'> 100
<class '__main__.BoundedInt'> 100
<class '__main__.BoundedInt'> 100
<class '__main__.BoundedInt'> 0
For completeness here's another answer which shows how to programmatically add all the arithmetic methods that integers have to the custom class using a metaclass. Note it's unclear whether it makes sense in every case to return a BoundedInt with the same bounds as the operand. The code is also compatible with both Python 2 & 3.
class MetaBoundedInt(type):
# int arithmetic methods that return an int
_specials = ('abs add and div floordiv invert lshift mod mul neg or pos '
'pow radd rand rdiv rfloordiv rlshift rmod rmul ror rpow '
'rrshift rshift rsub rtruediv rxor sub truediv xor').split()
_ops = set('__%s__' % name for name in _specials)
def __new__(cls, name, bases, attrs):
classobj = type.__new__(cls, name, bases, attrs)
# create wrappers for specified arithmetic operations
for name, meth in ((n, m) for n, m in vars(int).items() if n in cls._ops):
setattr(classobj, name, cls._WrappedMethod(cls, meth))
return classobj
class _WrappedMethod(object):
def __init__(self, cls, func):
self.cls, self.func = cls, func
def __get__(self, obj, cls=None):
def wrapper(*args, **kwargs):
# convert result of calling self.func() to cls instance
return cls(self.func(obj, *args, **kwargs), bounds=obj._bounds)
for attr in '__module__', '__name__', '__doc__':
setattr(wrapper, attr, getattr(self.func, attr, None))
return wrapper
def with_metaclass(meta, *bases):
""" Py 2 & 3 compatible way to specifiy a metaclass. """
return meta("NewBase", bases, {})
class BoundedInt(with_metaclass(MetaBoundedInt, int)):
def __new__(cls, *args, **kwargs):
lower, upper = bounds = kwargs.pop('bounds')
val = int.__new__(cls, *args, **kwargs) # supports all int() args
val = super(BoundedInt, cls).__new__(cls, min(max(lower, val), upper))
val._bounds = bounds
return val
if __name__ == '__main__':
# all results should be BoundInt instances with values within bounds
v = BoundedInt('64', 16, bounds=(0, 100)) # 0x64 == 100
print('type(v)={}, value={}, bounds={}'.format(type(v).__name__, v, v._bounds))
v += 10
print('type(v)={}, value={}, bounds={}'.format(type(v).__name__, v, v._bounds))
w = v + 10
print('type(w)={}, value={}, bounds={}'.format(type(w).__name__, w, w._bounds))
x = v - 110
print('type(x)={}, value={}, bounds={}'.format(type(x).__name__, x, x._bounds))
Output:
type(v)=BoundedInt, value=100, bounds=(0, 100)
type(v)=BoundedInt, value=100, bounds=(0, 100)
type(w)=BoundedInt, value=100, bounds=(0, 100)
type(x)=BoundedInt, value=0, bounds=(0, 100)