mirror of
https://github.com/bendtherules/pyFun.git
synced 2026-08-18 22:02:25 +00:00
summer update
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
class A(object):
|
||||
|
||||
"""docstring for A"""
|
||||
a = 2
|
||||
pass
|
||||
|
||||
|
||||
class B(object):
|
||||
|
||||
"""docstring for A"""
|
||||
pass
|
||||
b = A.a
|
||||
|
||||
print("Run completed")
|
||||
@@ -0,0 +1,443 @@
|
||||
import pygame
|
||||
from math_utils import distance
|
||||
import math
|
||||
import base
|
||||
import inspect
|
||||
import sprite_types
|
||||
from utils import remove_from_list, rect_to_pygame_rect
|
||||
|
||||
|
||||
class Circle(object):
|
||||
map_class = "Circle"
|
||||
|
||||
def __init__(self, center=(None, None), radius=None, color=None, container_obj=None):
|
||||
if not (len(center) == 2):
|
||||
raise AttributeError("Center must be (x,y)")
|
||||
x = center[0]
|
||||
y = center[1]
|
||||
if (radius is None):
|
||||
raise AttributeError("radius must be provided")
|
||||
self.radius = radius
|
||||
self.color = color
|
||||
if not container_obj:
|
||||
if (x is None) or (y is None):
|
||||
raise AttributeError("Center=(x,y) must be provided")
|
||||
else:
|
||||
self.container_obj = None
|
||||
self.center = (x, y)
|
||||
else:
|
||||
self.container_obj = container_obj # Use weakrefs
|
||||
|
||||
@property
|
||||
def center(self):
|
||||
if self.container_obj:
|
||||
return (self.container_obj.x, self.container_obj.y)
|
||||
else:
|
||||
return self._center
|
||||
|
||||
@center.setter
|
||||
def center(self, val):
|
||||
if self.container_obj:
|
||||
self.container_obj.x, self.container_obj.y = val
|
||||
else:
|
||||
self._center = val
|
||||
|
||||
@classmethod
|
||||
def from_container_obj(cls, container_obj, radius, color=None):
|
||||
return cls(radius=radius, color=color, container_obj=container_obj)
|
||||
|
||||
@property
|
||||
def center_x(self):
|
||||
return self.center[0]
|
||||
|
||||
@property
|
||||
def center_y(self):
|
||||
return self.center[1]
|
||||
|
||||
@center_x.setter
|
||||
def center_x(self, new_x):
|
||||
self.center[0] = new_x
|
||||
|
||||
@center_y.setter
|
||||
def center_y(self, new_y):
|
||||
self.center[1] = new_y
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self.center_x
|
||||
|
||||
@x.setter
|
||||
def x(self, val):
|
||||
self.center_x = val
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self.center_y
|
||||
|
||||
@y.setter
|
||||
def y(self, val):
|
||||
self.center_y = val
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
# left = self.center_x - self.radius
|
||||
# top = self.center_y - self.radius
|
||||
width = height = self.radius * 2
|
||||
return sprite_types.Rect(self.center, (width, height))
|
||||
# todo: remember about the colour. document - center is list unlike tuple
|
||||
# in case of rect.
|
||||
|
||||
def __repr__(self):
|
||||
return "{0.__class__}( center={0.center}, radius={0.radius}, color={0.color})".format(self)
|
||||
|
||||
def __copy__(self):
|
||||
return self.__class__(self.center, self.radius, self.color)
|
||||
|
||||
def move(self, move_x, move_y):
|
||||
return Circle((self.center_x + move_x, self.center_y + move_y), self.radius, self.color)
|
||||
|
||||
def move_ip(self, move_x, move_y):
|
||||
self.center_x += move_x
|
||||
self.center_y += move_y
|
||||
return self
|
||||
|
||||
def inflate(self, inflate_radius):
|
||||
# check if resultant radius is -ve
|
||||
return Circle(self.center, self.radius + inflate_radius, self.color)
|
||||
|
||||
def inflate_ip(self, inflate_radius):
|
||||
self.radius += inflate_radius
|
||||
return self
|
||||
|
||||
def is_inside(self, another_circle):
|
||||
''' Checks if this circle is fully inside another_circle '''
|
||||
if self.radius >= another_circle.radius:
|
||||
return None
|
||||
else:
|
||||
bigger_circle = another_circle
|
||||
smaller_circle = self
|
||||
return distance(bigger_circle.center, smaller_circle.center) + smaller_circle.radius < bigger_circle.radius
|
||||
|
||||
def is_inside_mutual(self, another_circle):
|
||||
''' Checks if this circle is fully inside another_circle or the opposite.'''
|
||||
radius_diff = self.radius - another_circle.radius
|
||||
if radius_diff > 0:
|
||||
bigger_circle = self
|
||||
smaller_circle = another_circle
|
||||
elif radius_diff == 0:
|
||||
# None of them can be inside the other
|
||||
return None
|
||||
else:
|
||||
smaller_circle = self
|
||||
bigger_circle = another_circle
|
||||
return distance(bigger_circle.center, smaller_circle.center) + smaller_circle.radius < bigger_circle.radius
|
||||
|
||||
def collide(self, other_obj, moved_center=(None, None), from_container_obj=False):
|
||||
''' Collision handler for any type of obj'''
|
||||
# todo: handle game_class=="all"
|
||||
# todo: point class
|
||||
if not hasattr(other_obj, "__class__"):
|
||||
raise AttributeError(
|
||||
"other_obj must be a class or instance")
|
||||
|
||||
# Handle instances
|
||||
if isinstance(other_obj, Circle):
|
||||
return self.collide_circle(other_obj, moved_center, from_container_obj)
|
||||
elif isinstance(other_obj, sprite_types.Rect):
|
||||
return self.collide_rect(other_obj, moved_center, from_container_obj)
|
||||
elif isinstance(other_obj, sprite_types.Img):
|
||||
return self.collide_img(other_obj, moved_center, from_container_obj)
|
||||
else:
|
||||
pass
|
||||
|
||||
# Handle classes
|
||||
if inspect.isclass(other_obj):
|
||||
if issubclass(other_obj, Circle):
|
||||
return self.collide_list_circle(other_obj.list_instance, moved_center, from_container_obj)
|
||||
elif issubclass(other_obj, sprite_types.Rect):
|
||||
return self.collide_list_rect(other_obj.list_instance, moved_center, from_container_obj)
|
||||
elif issubclass(other_obj, sprite_types.Img):
|
||||
return self.collide_list_img(other_obj.list_instance, moved_center, from_container_obj)
|
||||
else:
|
||||
pass
|
||||
|
||||
# Handle fun_Game and fun_Class or their instances
|
||||
if isinstance(other_obj, base.fun_Game) or (inspect.isclass(other_obj) and issubclass(other_obj, base.fun_Game)):
|
||||
def instance_collide(other_obj):
|
||||
return self.collide(other_obj.sprite, moved_center, from_container_obj=True)
|
||||
to_return = other_obj.for_all_instance(
|
||||
instance_collide, flatten="level-class")
|
||||
remove_from_list(to_return, self.container_obj)
|
||||
remove_from_list(to_return, None, recursive=True)
|
||||
remove_from_list(to_return, False, recursive=True)
|
||||
return to_return
|
||||
if inspect.isclass(other_obj) and issubclass(other_obj, base.fun_Class):
|
||||
def instance_collide(other_obj):
|
||||
return self.collide(other_obj.sprite, moved_center, from_container_obj=True)
|
||||
to_return = other_obj.for_all_instance(
|
||||
instance_collide, flatten=False)
|
||||
remove_from_list(to_return, self.container_obj)
|
||||
remove_from_list(to_return, None, recursive=True)
|
||||
remove_from_list(to_return, False, recursive=True)
|
||||
return to_return
|
||||
if isinstance(other_obj, base.fun_Class):
|
||||
other_obj_sprite = other_obj.sprite
|
||||
to_return = self.collide(
|
||||
other_obj_sprite, moved_center, from_container_obj=True)
|
||||
# doesnt return list, so prev. case operations not done
|
||||
return to_return
|
||||
|
||||
def collide_img(self, another_img, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle intersects with another_img. '''
|
||||
|
||||
does_collide = self.collide(
|
||||
another_img.col_shape, moved_center, from_container_obj=False)
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_img.container_obj
|
||||
else:
|
||||
to_return = another_img
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_list_img(self, list_img, moved_center=(None, None), from_container_obj=False):
|
||||
list_collided_img = []
|
||||
for each_img in list_img:
|
||||
if self.collide_img(each_img, moved_center, from_container_obj):
|
||||
# Collide_img itself takes container_obj into account, so no
|
||||
# need of post-processing
|
||||
list_collided_img.append(each_img)
|
||||
else: # else of the for loop
|
||||
return False
|
||||
return list_collided_img
|
||||
|
||||
def collide_circle(self, another_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle intersects with another_circle. '''
|
||||
if not (len(moved_center) == 2):
|
||||
raise AttributeError("moved_center must be of the form (x,y)")
|
||||
_center = self.center
|
||||
moved_center = list(moved_center)
|
||||
if moved_center[0] is None:
|
||||
moved_center[0] = _center[0]
|
||||
if moved_center[1] is None:
|
||||
moved_center[1] = _center[1]
|
||||
# temporarily move self to moved_center and shift back later
|
||||
self.center = moved_center
|
||||
does_collide = (distance(self.center, another_circle.center) <= (
|
||||
self.radius + another_circle.radius))
|
||||
self.center = _center
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_circle.container_obj
|
||||
else:
|
||||
to_return = another_circle
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_point(self, (point_x, point_y)):
|
||||
''' Checks if (point_x, point_y) is inside this circle. '''
|
||||
does_collide = (
|
||||
distance(self.center, (point_x, point_y)) <= self.radius)
|
||||
if does_collide:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def collide_list_circle(self, list_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns list of circles in list_circle which intersects with this circle. '''
|
||||
list_collided_circle = []
|
||||
for circle in list_circle:
|
||||
if self.collide_circle(circle, moved_center, from_container_obj):
|
||||
# Collide_circle itself takes container_obj into account, so no
|
||||
# need of post-processing
|
||||
list_collided_circle.append(circle)
|
||||
else: # else of the for loop
|
||||
return False
|
||||
return list_collided_circle
|
||||
|
||||
def collide_list_any_circle(self, list_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle intersects with any of the circles in circle_list. '''
|
||||
for circle in list_circle:
|
||||
if self.collide_circle(circle, moved_center, from_container_obj):
|
||||
return True
|
||||
else: # else of the for loop
|
||||
return False
|
||||
|
||||
def collide_list_all_circle(self, list_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle intersects with all of the circles in circle_list. '''
|
||||
for circle in list_circle:
|
||||
if not self.collide_circle(circle, moved_center, from_container_obj):
|
||||
return False
|
||||
else: # else of the for loop
|
||||
return True
|
||||
|
||||
def collide_rect(self, another_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle collides with another_rect. '''
|
||||
if not (len(moved_center) == 2):
|
||||
print "moved_center must be of the form (x,y)"
|
||||
_center = self.center
|
||||
moved_center = list(moved_center)
|
||||
if moved_center[0] is None:
|
||||
moved_center[0] = _center[0]
|
||||
if moved_center[1] is None:
|
||||
moved_center[1] = _center[1]
|
||||
|
||||
self.center = moved_center
|
||||
does_collide = not ((self.center_x + self.radius) < another_rect.left or (self.center_x - self.radius) > another_rect.right or (
|
||||
self.center_y + self.radius) < another_rect.top or (self.center_y - self.radius) > another_rect.bottom)
|
||||
self.center = _center
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_rect.container_obj
|
||||
else:
|
||||
to_return = another_rect
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_list_rect(self, list_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns list of rect in list_rect which intersects with this circle. '''
|
||||
list_collided_rect = []
|
||||
for rect in list_rect:
|
||||
if self.collide_rect(rect, moved_center, from_container_obj):
|
||||
list_collided_rect.append(rect)
|
||||
else: # else of the for loop
|
||||
return False
|
||||
return list_collided_rect
|
||||
|
||||
def collide_list_any_rect(self, list_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns True if collides with any of the rect in the list. '''
|
||||
for temp_rect in list_rect:
|
||||
if self.collide_rect(self, temp_rect, moved_center, from_container_obj):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def collide_list_all_rect(self, list_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns True if collides with all the rect in the list. '''
|
||||
for temp_rect in list_rect:
|
||||
if not self.collide_rect(self, temp_rect, moved_center, from_container_obj):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def get_circumcircle_from_rect(cls, another_rect):
|
||||
# create a circle with same center and radius=sqrt(w^2+h^2)/2
|
||||
return cls(another_rect.center, math.sqrt(another_rect.width ** 2 + another_rect.height ** 2) / 2)
|
||||
|
||||
@classmethod
|
||||
def get_incircle_from_rect(cls, another_rect):
|
||||
# radius of incircle is same as the (min of width and height)/2 (as it's not a
|
||||
# square)
|
||||
return cls(another_rect.center, min(another_rect.width, another_rect.height) / 2)
|
||||
|
||||
# union -needs to be a circle *within* which the union of the bounding box of all the circles can be fit.
|
||||
# warning about all the union functions: The circles returned are not
|
||||
# necessarily the most optimum union circle, but it will surely contain
|
||||
# the others.
|
||||
def _union(self, circle_1, circle_2):
|
||||
''' ??? self.__union((new_center_x,new_center_y),new_radius) -> ([x,y],radius) which are the resultant values. '''
|
||||
return self.circumcircle_from_rect(circle_1.bbox.union(circle_2.bbox))
|
||||
|
||||
def union(self, new_circle):
|
||||
''' Returns a new circle which is the union of these two circles '''
|
||||
return self._union(self, new_circle)
|
||||
|
||||
def union_ip(self, new_circle):
|
||||
''' Turns this circle into a circle which is a union of these two circles. '''
|
||||
temp_circle = self._union(self, new_circle)
|
||||
self.center, self.radius = temp_circle.center, temp_circle.radius
|
||||
return self
|
||||
|
||||
# list_circle_params : [((x1,y1),radius_1), ((x2,y2),radius_2), ...]
|
||||
def _unionall(self, circle_1, seq_circle):
|
||||
''' returns ([x,y],radius) for the resultant union of all circles.
|
||||
sequence_circle must be a sequence of circles. '''
|
||||
return self.circumcircle_from_rect(circle_1.bbox.unionall([temp_circle.bbox for temp_circle in seq_circle]))
|
||||
|
||||
def unionall(self, seq_circle): # seq_circle: sequence of circles
|
||||
return self._unionall(self, seq_circle)
|
||||
|
||||
def unionall_ip(self, seq_circle):
|
||||
''' Turns this circle into a circle which is a union of this circles with all circles in seq_circle'''
|
||||
temp_circle = self._unionall(self, seq_circle)
|
||||
self.center, self.radius = temp_circle.center, temp_circle.radius
|
||||
return self
|
||||
|
||||
# draw functions
|
||||
def blit(self, surface, (x, y)=(None, None), color=None, clip_rect=None, width=1, use_antialiasing=False):
|
||||
''' Draws this Circle on surface. It must be of width and height greater than or equal to its bbox.
|
||||
(x,y)->co-ordinates whether the center of the Circle should be drawn on the surface.
|
||||
width argument doesnt work with antialiasing. width=0 makes it filled.
|
||||
antialiasing may break in later versions as the backend pygame.gfxdraw is experimental.
|
||||
color falls back first to Circle.color (if present) and then to blue color.'''
|
||||
if (x, y) == (None, None):
|
||||
(x, y) = self.center
|
||||
# pygame.Rect does this, which is used in clear_rect
|
||||
x, y = int(x), int(y)
|
||||
if not color:
|
||||
if self.color:
|
||||
color = self.color
|
||||
else:
|
||||
color = pygame.Color("blue")
|
||||
|
||||
if clip_rect:
|
||||
# Set clip region
|
||||
surface.set_clip(clip_rect)
|
||||
|
||||
if not use_antialiasing:
|
||||
pygame.draw.circle(surface, color, (x, y), self.radius, width)
|
||||
else:
|
||||
pygame.gfxdraw.aacircle(surface, x, y, self.radius, color)
|
||||
|
||||
if clip_rect:
|
||||
# Remove clip region
|
||||
surface.set_clip(None)
|
||||
|
||||
def draw(self):
|
||||
tmp_dirty_sprite = {
|
||||
"sprite": self,
|
||||
# later shape may be used for matching insted of sprites, as sprite
|
||||
# may be subclassed, changing "sprite" obj
|
||||
"shape": "Circle",
|
||||
# Very IMP: If using Rect for bbox, use rect_to_pygame_rect like
|
||||
# below.
|
||||
"bbox": rect_to_pygame_rect(self.bbox),
|
||||
"config": {
|
||||
"center": self.center,
|
||||
"radius": self.radius,
|
||||
"color": self.color
|
||||
}
|
||||
}
|
||||
for tmp_old_sprite in self.container_obj.list_rendered_sprite:
|
||||
# if any of them is eqv. to new dirty sprite, mark old one as
|
||||
# still_valid
|
||||
if tmp_old_sprite == tmp_dirty_sprite:
|
||||
# puts "still_valid" entry in the old_dirty_sprite_dict
|
||||
# quite good approach, wont match with anything again
|
||||
# but "still_valid" should be removed, before next step (tick), to allow
|
||||
# checks later
|
||||
tmp_old_sprite["still_valid"] = True
|
||||
break
|
||||
else:
|
||||
# i.e. if no match found, list it as dirty sprite
|
||||
self.container_obj.list_dirty_sprite.append(tmp_dirty_sprite)
|
||||
|
||||
def get_surface(self, surface=None, flags=0):
|
||||
''' Returns a new surface with dimensions of (Circle.bbox.width,Circle.bbox.width) and other properties as surface.
|
||||
This Circle can be safely drawn on it.'''
|
||||
if surface:
|
||||
return pygame.Surface((self.bbox.width, self.bbox.height), flags, surface)
|
||||
else:
|
||||
return pygame.Surface((self.bbox.width, self.bbox.height), flags)
|
||||
|
||||
def get_surface_drawn(self, (x, y)=(None, None), color=None, width=1, use_antialiasing=False, surface=None, flags=0):
|
||||
''' Returns a surface which has the tiltedRect drwan on it. '''
|
||||
temp_surf = self.get_surface(surface, flags)
|
||||
self.draw(temp_surf, (x, y), color, width, use_antialiasing)
|
||||
return temp_surf
|
||||
|
||||
# end of Circle class
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,422 @@
|
||||
import pygame
|
||||
import sprite_types
|
||||
import inspect
|
||||
import base
|
||||
from utils import remove_from_list
|
||||
|
||||
|
||||
class Img(object):
|
||||
|
||||
map_class = "Img"
|
||||
|
||||
def __init__(self, center=(None, None), file_name_or_obj=None, namehint="", collision_shape=None, container_obj=None):
|
||||
|
||||
if not (len(center) == 2):
|
||||
raise TypeError("Center must be (x,y)")
|
||||
x = center[0]
|
||||
y = center[1]
|
||||
if not container_obj:
|
||||
if (x is None) or (y is None):
|
||||
raise TypeError("Center=(x,y) must be provided")
|
||||
else:
|
||||
self.container_obj = None
|
||||
self.center = (x, y)
|
||||
else:
|
||||
self.container_obj = container_obj # Use weakrefs
|
||||
|
||||
if (file_name_or_obj is None):
|
||||
raise TypeError(
|
||||
"file_name_or_obj must be filename, file_obj or surface")
|
||||
|
||||
if not isinstance(file_name_or_obj, pygame.Surface):
|
||||
if namehint == "":
|
||||
self.surf = pygame.image.load(file_name_or_obj)
|
||||
else:
|
||||
self.surf = pygame.image.load(file_name_or_obj, namehint)
|
||||
else:
|
||||
# From surface
|
||||
# Todo: Some param for caching
|
||||
self._surf = file_name_or_obj
|
||||
|
||||
if collision_shape:
|
||||
self._col_shape = collision_shape
|
||||
else:
|
||||
self._col_shape = self.bbox
|
||||
|
||||
@property
|
||||
def col_shape(self):
|
||||
return self._col_shape
|
||||
|
||||
@col_shape.setter
|
||||
def col_shape(self, value):
|
||||
self._col_shape = value
|
||||
|
||||
def sync_col_shape(self):
|
||||
self.col_shape.center = self.center
|
||||
|
||||
@property
|
||||
def center(self):
|
||||
if self.container_obj:
|
||||
return (self.container_obj.x, self.container_obj.y)
|
||||
else:
|
||||
return self._center
|
||||
|
||||
@center.setter
|
||||
def center(self, val):
|
||||
if self.container_obj:
|
||||
self.container_obj.x, self.container_obj.y = val
|
||||
else:
|
||||
self._center = val
|
||||
self.sync_col_shape()
|
||||
|
||||
@classmethod
|
||||
def from_container_obj(cls, container_obj, file_name_or_obj, namehint=""):
|
||||
return cls(file_name_or_obj=file_name_or_obj, namehint=namehint, container_obj=container_obj)
|
||||
|
||||
@classmethod
|
||||
def from_surface(cls, center, surf):
|
||||
return cls(center=center, file_name_or_obj=surf)
|
||||
|
||||
@property
|
||||
def surf(self):
|
||||
return self._surf
|
||||
|
||||
@surf.setter
|
||||
def surf(self, value):
|
||||
if isinstance(value, pygame.Surface):
|
||||
self._surf = value
|
||||
else:
|
||||
return TypeError("surf can only be set to anther pygame.Surface")
|
||||
|
||||
@property
|
||||
def center_x(self):
|
||||
return self.center[0]
|
||||
|
||||
@property
|
||||
def center_y(self):
|
||||
return self.center[1]
|
||||
|
||||
@center_x.setter
|
||||
def center_x(self, new_x):
|
||||
self.center[0] = new_x
|
||||
|
||||
@center_y.setter
|
||||
def center_y(self, new_y):
|
||||
self.center[1] = new_y
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self.center_x
|
||||
|
||||
@x.setter
|
||||
def x(self, val):
|
||||
self.center_x = val
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self.center_y
|
||||
|
||||
@y.setter
|
||||
def y(self, val):
|
||||
self.center_y = val
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
'''Returns sprite_types.Rect copy of bounding box'''
|
||||
surf_rect = self.get_rect()
|
||||
return sprite_types.Rect.from_rect(surf_rect)
|
||||
|
||||
def get_rect(self):
|
||||
'''Returns pygame.Rect copy of bounding box'''
|
||||
return self.surf.get_rect(center=self.center)
|
||||
|
||||
def get_surface(self):
|
||||
''' Returns a copy of internal surface '''
|
||||
return self.surf.copy()
|
||||
|
||||
def __repr__(self):
|
||||
return "{0.__class__}( center={0.center}, size={0.size})".format(self)
|
||||
|
||||
def __copy__(self):
|
||||
return self.__cls__.from_surface(self.center, self.surf.copy())
|
||||
|
||||
def save_to_disk(self, filename):
|
||||
pygame.image.save(self.get_surface(), filename)
|
||||
return True
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self.surf.get_size()
|
||||
|
||||
@size.setter
|
||||
def size(self, value):
|
||||
raise NotImplementedError(
|
||||
"Setting size is ambiguous, so not implemented")
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
return self.get_width()
|
||||
|
||||
@width.setter
|
||||
def width(self, value):
|
||||
raise NotImplementedError(
|
||||
"Setting width is ambiguous, so not implemented")
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
return self.get_height()
|
||||
|
||||
@height.setter
|
||||
def height(self, value):
|
||||
raise NotImplementedError(
|
||||
"Setting height is ambiguous, so not implemented")
|
||||
|
||||
@property
|
||||
def w(self):
|
||||
return self.width
|
||||
|
||||
@w.setter
|
||||
def w(self, value):
|
||||
self.width = value
|
||||
|
||||
@property
|
||||
def h(self):
|
||||
return self.height
|
||||
|
||||
@h.setter
|
||||
def h(self, value):
|
||||
self.height = value
|
||||
|
||||
# Surface methods not provided, apply on self.surf
|
||||
def blit(self, surface, (x, y)=(None, None), clip_rect=None):
|
||||
|
||||
if (x, y) == (None, None):
|
||||
(x, y) = self.center
|
||||
# pygame.Rect does this, which is used in clear_rect
|
||||
x, y = int(x), int(y)
|
||||
|
||||
if clip_rect:
|
||||
# Set clip region
|
||||
surface.set_clip(clip_rect)
|
||||
|
||||
surface.blit(self.surf, self.bbox.topleft)
|
||||
|
||||
if clip_rect:
|
||||
# Remove clip region
|
||||
surface.set_clip(None)
|
||||
|
||||
def draw(self):
|
||||
tmp_dirty_sprite = {
|
||||
"sprite": self,
|
||||
# later shape may be used for matching insted of sprites, as sprite
|
||||
# may be subclassed, changing "sprite" obj
|
||||
"shape": "Img",
|
||||
"bbox": self.get_rect(),
|
||||
"config": {
|
||||
"center": self.center,
|
||||
"file_name_or_obj": self.surf
|
||||
}
|
||||
}
|
||||
for tmp_old_sprite in self.container_obj.list_rendered_sprite:
|
||||
# if any of them is eqv. to new dirty sprite, mark old one as
|
||||
# still_valid
|
||||
if tmp_old_sprite == tmp_dirty_sprite:
|
||||
# puts "still_valid" entry in the old_dirty_sprite_dict
|
||||
# quite good approach, wont match with anything again
|
||||
# but "still_valid" should be removed, before next step (tick), to allow
|
||||
# checks later
|
||||
tmp_old_sprite["still_valid"] = True
|
||||
break
|
||||
else:
|
||||
# i.e. if no match found, list it as dirty sprite
|
||||
self.container_obj.list_dirty_sprite.append(tmp_dirty_sprite)
|
||||
|
||||
# collide func
|
||||
def collide(self, other_obj, moved_center=(None, None), from_container_obj=False):
|
||||
''' Collision handler for any type of obj'''
|
||||
|
||||
if not hasattr(other_obj, "__class__"):
|
||||
raise AttributeError(
|
||||
"other_obj must be a class or instance")
|
||||
|
||||
# Handle instances
|
||||
if isinstance(other_obj, sprite_types.Circle):
|
||||
return self.collide_circle(other_obj, moved_center, from_container_obj)
|
||||
elif isinstance(other_obj, sprite_types.Rect):
|
||||
return self.collide_rect(other_obj, moved_center, from_container_obj)
|
||||
elif isinstance(other_obj, Img):
|
||||
# Todo: add img collision
|
||||
return self.collide_img(other_obj, moved_center, from_container_obj)
|
||||
else:
|
||||
pass
|
||||
|
||||
# Handle classes
|
||||
if inspect.isclass(other_obj):
|
||||
if issubclass(other_obj, sprite_types.Circle):
|
||||
return self.collide_list_circle(other_obj.list_instance, moved_center, from_container_obj)
|
||||
elif issubclass(other_obj, sprite_types.Rect):
|
||||
return self.collide_list_rect(other_obj.list_instance, moved_center, from_container_obj)
|
||||
elif issubclass(other_obj, Img):
|
||||
# Todo: add img collision
|
||||
return self.collide_list_img(other_obj.list_instance, moved_center, from_container_obj)
|
||||
else:
|
||||
pass
|
||||
|
||||
# Handle fun_Game and fun_Class or their instances
|
||||
if isinstance(other_obj, base.fun_Game) or (inspect.isclass(other_obj) and issubclass(other_obj, base.fun_Game)):
|
||||
def instance_collide(other_obj):
|
||||
return self.collide(other_obj.sprite, moved_center, from_container_obj=True)
|
||||
to_return = other_obj.for_all_instance(
|
||||
instance_collide, flatten="level-class")
|
||||
remove_from_list(to_return, self.container_obj)
|
||||
remove_from_list(to_return, None, recursive=True)
|
||||
remove_from_list(to_return, False, recursive=True)
|
||||
return to_return
|
||||
if inspect.isclass(other_obj) and issubclass(other_obj, base.fun_Class):
|
||||
def instance_collide(other_obj):
|
||||
return self.collide(other_obj.sprite, moved_center, from_container_obj=True)
|
||||
to_return = other_obj.for_all_instance(
|
||||
instance_collide, flatten=False)
|
||||
remove_from_list(to_return, self.container_obj)
|
||||
remove_from_list(to_return, None, recursive=True)
|
||||
remove_from_list(to_return, False, recursive=True)
|
||||
return to_return
|
||||
if isinstance(other_obj, base.fun_Class):
|
||||
other_obj_sprite = other_obj.sprite
|
||||
to_return = self.collide(
|
||||
other_obj_sprite, moved_center, from_container_obj=True)
|
||||
# doesnt return list, so prev. case operations not done
|
||||
return to_return
|
||||
|
||||
def collide_img(self, another_img, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this img intersects with another_img. '''
|
||||
|
||||
does_collide = self.collide(
|
||||
another_img.col_shape, moved_center, from_container_obj=False)
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_img.container_obj
|
||||
else:
|
||||
to_return = another_img
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_list_img(self, list_img, moved_center=(None, None), from_container_obj=False):
|
||||
list_collided_img = []
|
||||
for each_img in list_img:
|
||||
if self.collide_img(each_img, moved_center, from_container_obj):
|
||||
# Collide_img itself takes container_obj into account, so no
|
||||
# need of post-processing
|
||||
list_collided_img.append(each_img)
|
||||
else: # else of the for loop
|
||||
return False
|
||||
return list_collided_img
|
||||
|
||||
def collide_circle(self, another_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle intersects with another_circle. '''
|
||||
if not (len(moved_center) == 2):
|
||||
raise AttributeError("moved_center must be of the form (x,y)")
|
||||
_center = self.center
|
||||
moved_center = list(moved_center)
|
||||
if moved_center[0] is None:
|
||||
moved_center[0] = _center[0]
|
||||
if moved_center[1] is None:
|
||||
moved_center[1] = _center[1]
|
||||
# temporarily move self to moved_center and shift back later
|
||||
self.center = moved_center
|
||||
does_collide = another_circle.collide_img(self)
|
||||
self.center = _center
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_circle.container_obj
|
||||
else:
|
||||
to_return = another_circle
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_point(self, (point_x, point_y)):
|
||||
''' Checks if (point_x, point_y) is inside this circle. '''
|
||||
does_collide = self.col_shape.collide_point((point_x, point_y))
|
||||
if does_collide:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def collide_list_circle(self, list_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns list of circles in list_circle which intersects with this circle. '''
|
||||
list_collided_circle = []
|
||||
for circle in list_circle:
|
||||
if self.collide_circle(circle, moved_center, from_container_obj):
|
||||
# Collide_circle itself takes container_obj into account, so no
|
||||
# need of post-processing
|
||||
list_collided_circle.append(circle)
|
||||
else: # else of the for loop
|
||||
return False
|
||||
return list_collided_circle
|
||||
|
||||
def collide_list_any_circle(self, list_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle intersects with any of the circles in circle_list. '''
|
||||
for circle in list_circle:
|
||||
if self.collide_circle(circle, moved_center, from_container_obj):
|
||||
return True
|
||||
else: # else of the for loop
|
||||
return False
|
||||
|
||||
def collide_list_all_circle(self, list_circle, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle intersects with all of the circles in circle_list. '''
|
||||
for circle in list_circle:
|
||||
if not self.collide_circle(circle, moved_center, from_container_obj):
|
||||
return False
|
||||
else: # else of the for loop
|
||||
return True
|
||||
|
||||
def collide_rect(self, another_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this circle collides with another_rect. '''
|
||||
if not (len(moved_center) == 2):
|
||||
print "moved_center must be of the form (x,y)"
|
||||
_center = self.center
|
||||
moved_center = list(moved_center)
|
||||
if moved_center[0] is None:
|
||||
moved_center[0] = _center[0]
|
||||
if moved_center[1] is None:
|
||||
moved_center[1] = _center[1]
|
||||
|
||||
self.center = moved_center
|
||||
does_collide = another_rect.collide_img(self)
|
||||
self.center = _center
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_rect.container_obj
|
||||
else:
|
||||
to_return = another_rect
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_list_rect(self, list_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns list of rect in list_rect which intersects with this circle. '''
|
||||
list_collided_rect = []
|
||||
for rect in list_rect:
|
||||
if self.collide_rect(rect, moved_center, from_container_obj):
|
||||
list_collided_rect.append(rect)
|
||||
else: # else of the for loop
|
||||
return False
|
||||
return list_collided_rect
|
||||
|
||||
def collide_list_any_rect(self, list_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns True if collides with any of the rect in the list. '''
|
||||
for temp_rect in list_rect:
|
||||
if self.collide_rect(self, temp_rect, moved_center, from_container_obj):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def collide_list_all_rect(self, list_rect, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns True if collides with all the rect in the list. '''
|
||||
for temp_rect in list_rect:
|
||||
if not self.collide_rect(self, temp_rect, moved_center, from_container_obj):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
+258
File diff suppressed because one or more lines are too long
@@ -0,0 +1,641 @@
|
||||
import pygame
|
||||
from utils import remove_from_list
|
||||
import base
|
||||
import sprite_types
|
||||
import inspect
|
||||
|
||||
|
||||
class Rect(object):
|
||||
|
||||
"""Pythonic rect wrapper, using in-built Rect for speed"""
|
||||
|
||||
map_class = "Rect"
|
||||
|
||||
def __init__(self, center=(None, None), size=(None, None), color=None, container_obj=None):
|
||||
if not (len(center) == 2):
|
||||
raise AttributeError("Center must be (x,y)")
|
||||
x = center[0]
|
||||
y = center[1]
|
||||
if (not (len(size) == 2)) or (None in size):
|
||||
raise AttributeError(
|
||||
"size must be provided and is of format (w,h)")
|
||||
self.color = color
|
||||
if not container_obj:
|
||||
if (x is None) or (y is None):
|
||||
raise AttributeError("Center=(x,y) must be provided")
|
||||
else:
|
||||
self.container_obj = None
|
||||
self.center = (x, y)
|
||||
else:
|
||||
self.container_obj = container_obj # Use weakrefs
|
||||
|
||||
tmp_left = self.center[0] - size[0] / 2
|
||||
tmp_top = self.center[1] - size[1] / 2
|
||||
self._rect = pygame.Rect((tmp_left, tmp_top), size)
|
||||
self.sync_self()
|
||||
|
||||
@classmethod
|
||||
def from_rect(cls, rect):
|
||||
# Doesnt use the same rect, effectively makes a copy
|
||||
# As rects cant have extra props, it shouldnt impose any limitations.
|
||||
return cls(rect.center, rect.size)
|
||||
|
||||
@classmethod
|
||||
def from_top_left(cls, top_left=(None, None), size=(None, None), color=None, container_obj=None):
|
||||
if not (None in top_left):
|
||||
tmp_center = top_left[0] + size[0] / 2, top_left[1] + size[1] / 2
|
||||
else:
|
||||
tmp_center = top_left
|
||||
return cls(tmp_center, size, color, container_obj)
|
||||
|
||||
@property
|
||||
def center(self):
|
||||
if self.container_obj:
|
||||
return (self.container_obj.x, self.container_obj.y)
|
||||
else:
|
||||
return self._center
|
||||
|
||||
@center.setter
|
||||
def center(self, val):
|
||||
if self.container_obj:
|
||||
self.container_obj.x, self.container_obj.y = val
|
||||
else:
|
||||
self._center = val
|
||||
|
||||
@classmethod
|
||||
def from_container_obj(cls, container_obj, size, color=None):
|
||||
return cls(size=size, color=color, container_obj=container_obj)
|
||||
|
||||
@property
|
||||
def center_x(self):
|
||||
return self.center[0]
|
||||
|
||||
@property
|
||||
def center_y(self):
|
||||
return self.center[1]
|
||||
|
||||
@center_x.setter
|
||||
def center_x(self, new_x):
|
||||
self.center[0] = new_x
|
||||
|
||||
@center_y.setter
|
||||
def center_y(self, new_y):
|
||||
self.center[1] = new_y
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self.center_x
|
||||
|
||||
@x.setter
|
||||
def x(self, val):
|
||||
self.center_x = val
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self.center_y
|
||||
|
||||
@y.setter
|
||||
def y(self, val):
|
||||
self.center_y = val
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
return self.inner_rect.copy()
|
||||
|
||||
@property
|
||||
def inner_rect(self):
|
||||
self.sync_inner_rect()
|
||||
return self._rect
|
||||
|
||||
def sync_inner_rect(self):
|
||||
self._rect.center = self.center
|
||||
|
||||
def sync_self(self):
|
||||
self.center = self._rect.center
|
||||
|
||||
# misc. methods
|
||||
|
||||
def __repr__(self):
|
||||
return "{0.__class__}( center={0.center}, size={0.size}, color={0.color})".format(self)
|
||||
|
||||
def __copy__(self):
|
||||
return self.__class__(**self.get_props())
|
||||
|
||||
def get_props(self):
|
||||
''' Returns all of the constructor params, reqd for creationg a copy '''
|
||||
return {
|
||||
"center": self.center,
|
||||
"size": self.size,
|
||||
"color": self.color,
|
||||
"container_obj": self.container_obj,
|
||||
}
|
||||
|
||||
def __eq__(self, another_rect):
|
||||
if self.get_props() == another_rect.get_props():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# draw and blit func
|
||||
|
||||
def blit(self, surface, (x, y)=(None, None), color=None, clip_rect=None, width=1, use_antialiasing=False):
|
||||
|
||||
if (x, y) == (None, None):
|
||||
(x, y) = self.center
|
||||
# pygame.Rect does this, which is used in clear_rect
|
||||
x, y = int(x), int(y)
|
||||
if not color:
|
||||
if self.color:
|
||||
color = self.color
|
||||
else:
|
||||
color = pygame.Color("blue")
|
||||
|
||||
if clip_rect:
|
||||
# Set clip region
|
||||
surface.set_clip(clip_rect)
|
||||
|
||||
if not use_antialiasing:
|
||||
pygame.draw.rect(
|
||||
surface, color, self.bbox, width)
|
||||
else:
|
||||
# do later
|
||||
pass
|
||||
|
||||
if clip_rect:
|
||||
# Remove clip region
|
||||
surface.set_clip(None)
|
||||
|
||||
def draw(self):
|
||||
tmp_dirty_sprite = {
|
||||
"sprite": self,
|
||||
# later shape may be used for matching insted of sprites, as sprite
|
||||
# may be subclassed, changing "sprite" obj
|
||||
"shape": "Rect",
|
||||
# Very IMP: If using Rect for bbox, use rect_to_pygame_rect like
|
||||
# below.
|
||||
"bbox": self.bbox,
|
||||
"config": {
|
||||
"center": self.center,
|
||||
"size": self.size,
|
||||
"color": self.color
|
||||
}
|
||||
}
|
||||
for tmp_old_sprite in self.container_obj.list_rendered_sprite:
|
||||
# if any of them is eqv. to new dirty sprite, mark old one as
|
||||
# still_valid
|
||||
if tmp_old_sprite == tmp_dirty_sprite:
|
||||
# puts "still_valid" entry in the old_dirty_sprite_dict
|
||||
# quite good approach, wont match with anything again
|
||||
# but "still_valid" should be removed, before next step (tick), to allow
|
||||
# checks later
|
||||
tmp_old_sprite["still_valid"] = True
|
||||
break
|
||||
else:
|
||||
# i.e. if no match found, list it as dirty sprite
|
||||
self.container_obj.list_dirty_sprite.append(tmp_dirty_sprite)
|
||||
|
||||
# collide func
|
||||
def collide(self, other_obj, moved_center=(None, None), from_container_obj=False):
|
||||
''' Collision handler for any type of obj'''
|
||||
# todo: handle game_class=="all"
|
||||
# todo: point class
|
||||
if not hasattr(other_obj, "__class__"):
|
||||
raise AttributeError(
|
||||
"other_obj must be a class or instance")
|
||||
|
||||
# Handle instances
|
||||
if isinstance(other_obj, sprite_types.Circle):
|
||||
return self.collide_circle(other_obj, moved_center, from_container_obj)
|
||||
elif isinstance(other_obj, Rect):
|
||||
return self.collide_rect(other_obj, moved_center, from_container_obj)
|
||||
elif isinstance(other_obj, sprite_types.Img):
|
||||
return self.collide_img(other_obj, moved_center, from_container_obj)
|
||||
else:
|
||||
pass
|
||||
|
||||
# Handle classes
|
||||
if inspect.isclass(other_obj):
|
||||
if issubclass(other_obj, sprite_types.Circle):
|
||||
return self.collide_list_circle(other_obj.list_instance, moved_center, from_container_obj)
|
||||
elif issubclass(other_obj, Rect):
|
||||
return self.collide_list_rect(other_obj.list_instance, moved_center, from_container_obj)
|
||||
elif issubclass(other_obj, sprite_types.Img):
|
||||
return self.collide_list_img(other_obj.list_instance, moved_center, from_container_obj)
|
||||
else:
|
||||
pass
|
||||
|
||||
# Handle fun_Game and fun_Class or their instances
|
||||
if isinstance(other_obj, base.fun_Game) or (inspect.isclass(other_obj) and issubclass(other_obj, base.fun_Game)):
|
||||
def instance_collide(other_obj):
|
||||
return self.collide(other_obj.sprite, moved_center, from_container_obj=True)
|
||||
to_return = other_obj.for_all_instance(
|
||||
instance_collide, flatten="level-class")
|
||||
remove_from_list(to_return, self.container_obj)
|
||||
remove_from_list(to_return, None, recursive=True)
|
||||
remove_from_list(to_return, False, recursive=True)
|
||||
return to_return
|
||||
if inspect.isclass(other_obj) and issubclass(other_obj, base.fun_Class):
|
||||
def instance_collide(other_obj):
|
||||
return self.collide(other_obj.sprite, moved_center, from_container_obj=True)
|
||||
to_return = other_obj.for_all_instance(
|
||||
instance_collide, flatten=False)
|
||||
remove_from_list(to_return, self.container_obj)
|
||||
remove_from_list(to_return, False, recursive=True)
|
||||
remove_from_list(to_return, None, recursive=True)
|
||||
remove_from_list(to_return, False, recursive=True)
|
||||
return to_return
|
||||
if isinstance(other_obj, base.fun_Class):
|
||||
other_obj_sprite = other_obj.sprite
|
||||
to_return = self.collide(
|
||||
other_obj_sprite, moved_center, from_container_obj=True)
|
||||
# doesnt return list, so prev. case operations not done
|
||||
return to_return
|
||||
|
||||
# Rest are all synced props and methods
|
||||
# w, h, width, height
|
||||
# top, left, bottom, right
|
||||
# topleft, bottomleft, topright, bottomright
|
||||
# midtop, midleft, midbottom, midright
|
||||
# size
|
||||
# Getters first
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
return self.bbox.width
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
return self.bbox.height
|
||||
|
||||
@property
|
||||
def w(self):
|
||||
return self.bbox.w
|
||||
|
||||
@property
|
||||
def h(self):
|
||||
return self.bbox.h
|
||||
|
||||
@property
|
||||
def top(self):
|
||||
return self.bbox.top
|
||||
|
||||
@property
|
||||
def left(self):
|
||||
return self.bbox.left
|
||||
|
||||
@property
|
||||
def bottom(self):
|
||||
return self.bbox.bottom
|
||||
|
||||
@property
|
||||
def right(self):
|
||||
return self.bbox.right
|
||||
|
||||
@property
|
||||
def topleft(self):
|
||||
return self.bbox.topleft
|
||||
|
||||
@property
|
||||
def bottomleft(self):
|
||||
return self.bbox.bottomleft
|
||||
|
||||
@property
|
||||
def topright(self):
|
||||
return self.bbox.topright
|
||||
|
||||
@property
|
||||
def bottomright(self):
|
||||
return self.bbox.bottomright
|
||||
|
||||
@property
|
||||
def midtop(self):
|
||||
return self.bbox.midtop
|
||||
|
||||
@property
|
||||
def midleft(self):
|
||||
return self.bbox.midleft
|
||||
|
||||
@property
|
||||
def midbottom(self):
|
||||
return self.bbox.midbottom
|
||||
|
||||
@property
|
||||
def midright(self):
|
||||
return self.bbox.midright
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self.bbox.size
|
||||
|
||||
# Then setters
|
||||
@width.setter
|
||||
def width(self, val):
|
||||
self.inner_rect.width = val
|
||||
self.sync_self()
|
||||
|
||||
@height.setter
|
||||
def height(self, val):
|
||||
self.inner_rect.height = val
|
||||
self.sync_self()
|
||||
|
||||
@w.setter
|
||||
def w(self, val):
|
||||
self.inner_rect.w = val
|
||||
self.sync_self()
|
||||
|
||||
@h.setter
|
||||
def h(self, val):
|
||||
self.inner_rect.h = val
|
||||
self.sync_self()
|
||||
|
||||
@top.setter
|
||||
def top(self, val):
|
||||
self.inner_rect.top = val
|
||||
self.sync_self()
|
||||
|
||||
@left.setter
|
||||
def left(self, val):
|
||||
self.inner_rect.left = val
|
||||
self.sync_self()
|
||||
|
||||
@bottom.setter
|
||||
def bottom(self, val):
|
||||
self.inner_rect.bottom = val
|
||||
self.sync_self()
|
||||
|
||||
@right.setter
|
||||
def right(self, val):
|
||||
self.inner_rect.right = val
|
||||
self.sync_self()
|
||||
|
||||
@topleft.setter
|
||||
def topleft(self, val):
|
||||
self.inner_rect.topleft = val
|
||||
self.sync_self()
|
||||
|
||||
@bottomleft.setter
|
||||
def bottomleft(self, val):
|
||||
self.inner_rect.bottomleft = val
|
||||
self.sync_self()
|
||||
|
||||
@topright.setter
|
||||
def topright(self, val):
|
||||
self.inner_rect.topright = val
|
||||
self.sync_self()
|
||||
|
||||
@bottomright.setter
|
||||
def bottomright(self, val):
|
||||
self.inner_rect.bottomright = val
|
||||
self.sync_self()
|
||||
|
||||
@midtop.setter
|
||||
def midtop(self, val):
|
||||
self.inner_rect.midtop = val
|
||||
self.sync_self()
|
||||
|
||||
@midleft.setter
|
||||
def midleft(self, val):
|
||||
self.inner_rect.midleft = val
|
||||
self.sync_self()
|
||||
|
||||
@midbottom.setter
|
||||
def midbottom(self, val):
|
||||
self.inner_rect.midbottom = val
|
||||
self.sync_self()
|
||||
|
||||
@midright.setter
|
||||
def midright(self, val):
|
||||
self.inner_rect.midright = val
|
||||
self.sync_self()
|
||||
|
||||
@size.setter
|
||||
def size(self, val):
|
||||
self.inner_rect.size = val
|
||||
self.sync_self()
|
||||
|
||||
# in-place methods
|
||||
|
||||
def move_ip(self, *args, **kwargs):
|
||||
self.inner_rect.move_ip(*args, **kwargs)
|
||||
self.sync_self()
|
||||
return self
|
||||
|
||||
def inflate_ip(self, *args, **kwargs):
|
||||
self.inner_rect.inflate_ip(*args, **kwargs)
|
||||
self.sync_self()
|
||||
return self
|
||||
|
||||
def clamp_ip(self, *args, **kwargs):
|
||||
self.inner_rect.clamp_ip(*args, **kwargs)
|
||||
self.sync_self()
|
||||
return self
|
||||
|
||||
def normalize_ip(self):
|
||||
self.inner_rect.normalize()
|
||||
self.sync_self()
|
||||
return self
|
||||
|
||||
def union_ip(self, *args, **kwargs):
|
||||
self.inner_rect.union_ip(*args, **kwargs)
|
||||
self.sync_self()
|
||||
return self
|
||||
|
||||
def unionall_ip(self, *args, **kwargs):
|
||||
self.inner_rect.unionall_ip(*args, **kwargs)
|
||||
self.sync_self()
|
||||
return self
|
||||
|
||||
# non in-place methods
|
||||
|
||||
def copy(self, *args, **kwargs):
|
||||
return self.bbox.copy(*args, **kwargs)
|
||||
|
||||
def move(self, *args, **kwargs):
|
||||
return self.bbox.move(*args, **kwargs)
|
||||
|
||||
def inflate(self, *args, **kwargs):
|
||||
return self.bbox.inflate(*args, **kwargs)
|
||||
|
||||
def clamp(self, another_rect):
|
||||
if hasattr(another_rect, "bbox"):
|
||||
tmp_rect = another_rect.bbox
|
||||
else:
|
||||
tmp_rect = another_rect
|
||||
|
||||
return self.bbox.clamp(tmp_rect)
|
||||
|
||||
def clip(self, another_rect):
|
||||
if hasattr(another_rect, "bbox"):
|
||||
tmp_rect = another_rect.bbox
|
||||
else:
|
||||
tmp_rect = another_rect
|
||||
return self.bbox.clip(tmp_rect)
|
||||
|
||||
def union(self, another_rect):
|
||||
if hasattr(another_rect, "bbox"):
|
||||
tmp_rect = another_rect.bbox
|
||||
else:
|
||||
tmp_rect = another_rect
|
||||
return self.bbox.union(tmp_rect)
|
||||
|
||||
def unionall(self, rect_sequence):
|
||||
new_rect_seq = []
|
||||
for another_rect in rect_sequence:
|
||||
if hasattr(another_rect, "bbox"):
|
||||
tmp_rect = another_rect.bbox
|
||||
else:
|
||||
tmp_rect = another_rect
|
||||
new_rect_seq.append(tmp_rect)
|
||||
return self.bbox.unionall(new_rect_seq)
|
||||
|
||||
def fit(self, another_rect):
|
||||
if hasattr(another_rect, "bbox"):
|
||||
tmp_rect = another_rect.bbox
|
||||
else:
|
||||
tmp_rect = another_rect
|
||||
return self.bbox.fit(tmp_rect)
|
||||
|
||||
def contains(self, another_rect):
|
||||
if hasattr(another_rect, "bbox"):
|
||||
tmp_rect = another_rect.bbox
|
||||
else:
|
||||
tmp_rect = another_rect
|
||||
return self.bbox.contains(tmp_rect)
|
||||
|
||||
def collide_point(self, *args, **kwargs):
|
||||
''' collide_point(x,y) -> return bool
|
||||
collide_point((x,y)) -> return bool '''
|
||||
return self.bbox.collidepoint(*args, **kwargs)
|
||||
|
||||
def collide_rect(self, another_rect, moved_center=(None, None), from_container_obj=False):
|
||||
|
||||
if not (len(moved_center) == 2):
|
||||
print "moved_center must be of the form (x,y)"
|
||||
_center = self.center
|
||||
moved_center = list(moved_center)
|
||||
if moved_center[0] is None:
|
||||
moved_center[0] = _center[0]
|
||||
if moved_center[1] is None:
|
||||
moved_center[1] = _center[1]
|
||||
|
||||
self.center = moved_center
|
||||
|
||||
# Real collision code starts
|
||||
if hasattr(another_rect, "bbox"):
|
||||
tmp_rect = another_rect.bbox
|
||||
else:
|
||||
tmp_rect = another_rect
|
||||
does_collide = self.bbox.colliderect(tmp_rect)
|
||||
# Ends
|
||||
|
||||
self.center = _center
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_rect.container_obj
|
||||
else:
|
||||
to_return = another_rect
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_list_rect(self, rect_sequence, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns a list of rects, which collide; else empty list '''
|
||||
return_list = []
|
||||
for each_rect in rect_sequence:
|
||||
if self.collide_rect(each_rect, moved_center, from_container_obj):
|
||||
return_list.append(each_rect)
|
||||
return return_list
|
||||
|
||||
def collide_list_all_rect(self, rect_sequence, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns True if all rects in rect_sequence which collide,
|
||||
else False '''
|
||||
for each_rect in rect_sequence:
|
||||
if not self.collide_rect(each_rect, moved_center, from_container_obj):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def collide_list_any_rect(self, rect_sequence, moved_center=(None, None), from_container_obj=False):
|
||||
'''Returns the first rect which collides, else False'''
|
||||
for each_rect in rect_sequence:
|
||||
if self.collide_rect(each_rect, moved_center, from_container_obj):
|
||||
return each_rect
|
||||
else:
|
||||
return False
|
||||
|
||||
def collide_circle(self, another_circle, moved_center=(None, None), from_container_obj=False):
|
||||
|
||||
if not (len(moved_center) == 2):
|
||||
print "moved_center must be of the form (x,y)"
|
||||
_center = self.center
|
||||
moved_center = list(moved_center)
|
||||
if moved_center[0] is None:
|
||||
moved_center[0] = _center[0]
|
||||
if moved_center[1] is None:
|
||||
moved_center[1] = _center[1]
|
||||
|
||||
self.center = moved_center
|
||||
|
||||
# Collision code (uses Circles collision method) starts
|
||||
does_collide = another_circle.collide_rect(self)
|
||||
# Ends
|
||||
|
||||
self.center = _center
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_circle.container_obj
|
||||
else:
|
||||
to_return = another_circle
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_list_circle(self, circle_sequence, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns a list of Circles, which collide; else empty list '''
|
||||
return_list = []
|
||||
for each_circle in circle_sequence:
|
||||
if self.collide_circle(each_circle, moved_center, from_container_obj):
|
||||
return_list.append(each_circle)
|
||||
return return_list
|
||||
|
||||
def collide_list_all_circle(self, circle_sequence, moved_center=(None, None), from_container_obj=False):
|
||||
''' Returns True if all circles in circle_sequence which collide,
|
||||
else False '''
|
||||
for each_circle in circle_sequence:
|
||||
if not self.collide_circle(each_circle, moved_center, from_container_obj):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def collide_list_any_circle(self, circle_sequence, moved_center=(None, None), from_container_obj=False):
|
||||
'''Returns the first circle which collides, else False'''
|
||||
for each_circle in circle_sequence:
|
||||
if self.collide_circle(each_circle, moved_center, from_container_obj):
|
||||
return each_circle
|
||||
else:
|
||||
return False
|
||||
|
||||
def collide_img(self, another_img, moved_center=(None, None), from_container_obj=False):
|
||||
''' Checks if this rect intersects with another_img. '''
|
||||
|
||||
does_collide = self.collide(
|
||||
another_img.col_shape, moved_center, from_container_obj=False)
|
||||
if does_collide:
|
||||
if from_container_obj:
|
||||
to_return = another_img.container_obj
|
||||
else:
|
||||
to_return = another_img
|
||||
else:
|
||||
to_return = False
|
||||
return to_return
|
||||
|
||||
def collide_list_img(self, list_img, moved_center=(None, None), from_container_obj=False):
|
||||
list_collided_img = []
|
||||
for each_img in list_img:
|
||||
if self.collide_img(each_img, moved_center, from_container_obj):
|
||||
# Collide_img itself takes container_obj into account, so no
|
||||
# need of post-processing
|
||||
list_collided_img.append(each_img)
|
||||
else: # else of the for loop
|
||||
return False
|
||||
return list_collided_img
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
import pygame
|
||||
from math_utils import distance
|
||||
import math
|
||||
import base
|
||||
from Circle import Circle
|
||||
|
||||
# start of Rotated_Rect class
|
||||
|
||||
|
||||
class Rotated_Rect(pygame.Rect):
|
||||
# make a metaclass which wraps a lot of functions just like move is defined below.
|
||||
# functions to be wrapped - move,inflate
|
||||
# Think about them - clamp,clip,union,fit,contains,collide
|
||||
# the metaclass can probably also change the __str__ of the class.
|
||||
# About drawing - use pygame.transform.rotate to get a rotated surface to
|
||||
# be drawed.
|
||||
|
||||
def __init__(self, leftTop_or_center, w_h, angle, centered_coords=False, color=None):
|
||||
''' Angle in degrees.
|
||||
leftTop_or_center, w_h -> both are 2-element tuples or list
|
||||
centered_coords -> whether the (left,top) is actually intended to be (center_x,center_y) or not.
|
||||
I.e. if centered_coords==True the (left,top) co-ordinates are used as (center_x,center_y) co-ordinates of the Rotated_Rect'''
|
||||
self.angle = angle
|
||||
self.color = color
|
||||
try:
|
||||
left = leftTop_or_center[0]
|
||||
top = leftTop_or_center[1]
|
||||
except:
|
||||
raise AttributeError(
|
||||
"leftTop_or_center must be of format (left,top)")
|
||||
try:
|
||||
width = w_h[0]
|
||||
height = w_h[1]
|
||||
except:
|
||||
raise AttributeError("w_h must be of format (width,height)")
|
||||
|
||||
if centered_coords:
|
||||
left = left - width / 2
|
||||
top = top - height / 2
|
||||
super(Rotated_Rect, self).__init__((left, top), (width, height))
|
||||
|
||||
def __copy__(self):
|
||||
return Rotated_Rect((self.left, self.top), (self.width, self.height), self.angle)
|
||||
|
||||
def __repr__(self):
|
||||
return "{0.__class__.__name__}((top={0.top}, left={0.left}), (width={0.width}, height={0.height}), angle={0.angle}, color={0.color})".format(self)
|
||||
|
||||
@classmethod
|
||||
def create_from_rect(cls, another_rect, angle):
|
||||
return cls((another_rect.left, another_rect.top), (another_rect.width, another_rect.height), angle)
|
||||
|
||||
def get_rect(self):
|
||||
return pygame.Rect((self.left, self.top), (self.width, self.height))
|
||||
|
||||
# most in_place versions retained from super-class
|
||||
|
||||
def move(self, x, y):
|
||||
return self.__copy__().move_ip(x, y)
|
||||
|
||||
def inflate(self, x, y):
|
||||
return self.__copy__().inflate_ip(x, y)
|
||||
|
||||
def normalize(self):
|
||||
# not sure what this one does - ask others
|
||||
return self.__copy__().normalize_ip()
|
||||
|
||||
def rotate_ip(self, some_angle):
|
||||
self.angle += some_angle
|
||||
|
||||
def rotate(self, some_angle):
|
||||
return self.__copy__().rotate_ip(some_angle)
|
||||
|
||||
# generalise the parameters to accept x1,y1,x2,y2,rot_angle
|
||||
def rotate_point_about_center(self, x, y, theta=None):
|
||||
''' x,y -> Absolute co-ords of the point to be rotated wrt to the rectangles center.
|
||||
self.centerx,self.centery are internally substracted from them.
|
||||
theta -> angle (in degrees) by which the point is to be rotated. Default value is self.angle.
|
||||
Returns absolute positions of the points after rotation. '''
|
||||
if theta is None:
|
||||
theta = self.angle
|
||||
return self.rotate_point(x, y, self.centerx, self.centery, theta)
|
||||
|
||||
@staticmethod
|
||||
# to be allowed as rotate_point(class)
|
||||
def rotate_point(x, y, origin_x, origin_y, theta):
|
||||
''' x,y -> Absolute co-ords of the point to be rotated. origin_x,origin_y are internally substracted from them.
|
||||
(origin_x,origin_y) -> Absolute co-ords of the origin wrt to which the point will be rotated
|
||||
theta -> angle (in degrees) by which the point is to be rotated.
|
||||
Returns absolute positions of the points after rotation. '''
|
||||
import math
|
||||
x_diff = x - origin_x
|
||||
y_diff = y - origin_y
|
||||
# -y_diff because of the inverted nature of y co-ordinate system in pygame
|
||||
y_diff = -y_diff
|
||||
r = math.sqrt(x_diff ** 2 + y_diff ** 2)
|
||||
initial_angle = math.atan2(y_diff, x_diff)
|
||||
final_angle = initial_angle + math.radians(theta)
|
||||
rotated_x_diff = r * math.cos(final_angle)
|
||||
rotated_y_diff = r * math.sin(final_angle)
|
||||
rotated_y_diff = -rotated_y_diff # - used for same reason as above
|
||||
rotated_x = rotated_x_diff + origin_x
|
||||
rotated_y = rotated_y_diff + origin_y
|
||||
return (rotated_x, rotated_y)
|
||||
|
||||
def rotate_point_polar(self, r, initial_angle, theta=None):
|
||||
''' theta and initial_angle in radians.
|
||||
initial_angle ->angle r makes with horizontal.
|
||||
theta -> angle to be rotated by. '''
|
||||
if theta is None:
|
||||
theta = self.angle
|
||||
final_angle = initial_angle + theta
|
||||
rotated_x = r * math.cos(final_angle)
|
||||
rotated_y = r * math.sin(final_angle)
|
||||
return (rotated_x, rotated_y)
|
||||
|
||||
@property
|
||||
def bottomleft_rotated(self):
|
||||
temp = self.bottomleft
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
@property
|
||||
def topleft_rotated(self):
|
||||
temp = self.topleft
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
@property
|
||||
def bottomright_rotated(self):
|
||||
temp = self.bottomright
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
@property
|
||||
def topright_rotated(self):
|
||||
temp = self.topright
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
@property
|
||||
def midleft_rotated(self):
|
||||
temp = self.midleft
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
@property
|
||||
def midright_rotated(self):
|
||||
temp = self.midright
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
@property
|
||||
def midtop_rotated(self):
|
||||
temp = self.midtop
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
@property
|
||||
def midbottom_rotated(self):
|
||||
temp = self.midbottom
|
||||
return self.rotate_point_about_center(temp[0], temp[1])
|
||||
|
||||
# related to bounding box
|
||||
@property
|
||||
def bbox(self):
|
||||
list_x = [self.topleft_rotated[0], self.topright_rotated[0],
|
||||
self.bottomleft_rotated[0], self.bottomright_rotated[0]]
|
||||
list_y = [self.topleft_rotated[1], self.topright_rotated[1],
|
||||
self.bottomleft_rotated[1], self.bottomright_rotated[1]]
|
||||
min_x = math.floor(min(list_x))
|
||||
max_x = math.ceil(max(list_x))
|
||||
min_y = math.floor(min(list_y))
|
||||
max_y = math.ceil(max(list_y))
|
||||
return pygame.Rect((min_x, min_y), (max_x - min_x, max_y - min_y))
|
||||
# corners
|
||||
|
||||
@property
|
||||
def corners(self):
|
||||
''' List of actual (rotated) corners. '''
|
||||
return [self.topleft_rotated, self.topright_rotated, self.bottomright_rotated, self.bottomleft_rotated]
|
||||
|
||||
@property
|
||||
def corners_relative(self):
|
||||
return [(temp[0] - self.centerx, temp[1] - self.centery) for temp in self.corners]
|
||||
|
||||
# circles related to the rect
|
||||
def get_circumcircle(self):
|
||||
Circle.get_circumcircle_from_rect(self.bbox)
|
||||
|
||||
def get_incircle(self):
|
||||
# get_rect used as incircle doesnt depend upon theta, same for rot and
|
||||
# non-rot rect
|
||||
Circle.get_incircle_from_rect(self.get_rect())
|
||||
|
||||
# collision events
|
||||
def collide_point(self, *args):
|
||||
''' collidepoint(x,y) ->
|
||||
collidepoint((x,y)) -> '''
|
||||
temp_len = len(args)
|
||||
temp_x = None
|
||||
temp_y = None
|
||||
if temp_len == 2:
|
||||
temp_x = args[0]
|
||||
temp_y = args[1]
|
||||
elif temp_len == 1:
|
||||
if len(args[0]) == 2:
|
||||
temp_x, temp_y = args[0]
|
||||
else:
|
||||
raise TypeError("Arguments are of incorrect type")
|
||||
else:
|
||||
raise TypeError("Arguments are of incorrect type")
|
||||
if temp_x is None or temp_y is None:
|
||||
raise TypeError("argument must contain two numbers")
|
||||
return self.get_rect().collidepoint(self.rotate_point_about_center(temp_x, temp_y, -self.angle))
|
||||
|
||||
def collide_rect(self, rect):
|
||||
''' Tests if it collides with rect, which should be instance of rect class. '''
|
||||
# First test:whether bbox collides with rect. If not, no collision.
|
||||
if not self.bbox.colliderect(rect):
|
||||
return False
|
||||
else:
|
||||
# Todo: Else sure test: Need to do line class first. Test if any line
|
||||
# of titedRect collides with any line of (instead, the whole) rect.
|
||||
pass
|
||||
|
||||
# draw functions
|
||||
def blit(self, surface, (x, y)=(None, None), color=None, clip_rect=None, width=1, use_antialiasing=False, blend=True):
|
||||
''' Draws this Circle on surface. It must be of width and height greater than or equal to its bbox.
|
||||
(x,y)->co-ordinates whether the center of the Rotated_Rect should be drawn on the surface.
|
||||
width argument doesnt work with antialiasing. width=0 makes it filled.
|
||||
antialiasing may break in later versions as the backend pygame.gfxdraw is experimental.
|
||||
color falls back first to Circle.color (if present) and then to blue color.'''
|
||||
if not ((x, y) == (None, None)):
|
||||
sprite_to_draw = self.__copy__()
|
||||
sprite_to_draw.center = (x, y)
|
||||
else:
|
||||
sprite_to_draw = self
|
||||
# pygame.Rect does this, which is used in clear_rect
|
||||
x, y = int(x), int(y)
|
||||
if not color:
|
||||
if self.color:
|
||||
color = self.color
|
||||
else:
|
||||
color = pygame.Color("blue")
|
||||
|
||||
if clip_rect:
|
||||
# Set clip region
|
||||
surface.set_clip(clip_rect)
|
||||
|
||||
iter_corners = [(temp[0] + x, temp[1] + y)
|
||||
for temp in sprite_to_draw.corners_relative]
|
||||
if not use_antialiasing:
|
||||
pygame.draw.polygon(surface, color, iter_corners, width)
|
||||
else:
|
||||
pygame.draw.aalines(surface, color, True, iter_corners, blend)
|
||||
|
||||
if clip_rect:
|
||||
# Remove clip region
|
||||
surface.set_clip(None)
|
||||
|
||||
def draw(self):
|
||||
tmp_dirty_sprite = {
|
||||
"sprite": self,
|
||||
"shape": "Rotated_Rect",
|
||||
"bbox": self.bbox,
|
||||
"config": {
|
||||
"leftTop_or_center": (self.left, self.top),
|
||||
"w_h": (self.w, self.h),
|
||||
"angle": self.angle,
|
||||
"color": self.color
|
||||
}
|
||||
}
|
||||
for tmp_old_sprite in self.container_obj.list_rendered_sprite:
|
||||
# if any of them is eqv. to new dirty sprite, mark old one as
|
||||
# still_valid
|
||||
if tmp_old_sprite == tmp_dirty_sprite:
|
||||
# puts "still_valid" entry in the old_dirty_sprite_dict
|
||||
tmp_old_sprite["still_valid"] = True
|
||||
break
|
||||
else:
|
||||
# i.e. if no match found, list it as dirty sprite
|
||||
self.container_obj.list_dirty_sprite.append(tmp_dirty_sprite)
|
||||
|
||||
def get_surface(self, surface=None, flags=0):
|
||||
''' Returns a new surface with dimensions of (Rotated_Rect.bbox.width,Rotated_Rect.bbox.width) and other properties as surface.
|
||||
This Rotated_Rect can be safely drawn on it.'''
|
||||
if surface:
|
||||
return pygame.Surface((self.bbox.width, self.bbox.height), flags, surface)
|
||||
else:
|
||||
return pygame.Surface((self.bbox.width, self.bbox.height), flags)
|
||||
|
||||
def get_surface_drawn(self, (x, y)=(None, None), color=None, width=1, use_antialiasing=False, blend=True, surface=None, flags=0):
|
||||
''' Returns a surface which has the Rotated_Rect drwan on it. '''
|
||||
temp_surf = self.get_surface(surface, flags)
|
||||
self.draw(temp_surf, (x, y), color, width, use_antialiasing, blend)
|
||||
return temp_surf
|
||||
|
||||
def collide_Rotated_Rect(self, another_Rotated_Rect):
|
||||
'''Checks whether this Rotated_Rect collides with another_titltedrect, which must be a instance of titledRect. '''
|
||||
# Rotates both Rotated_Rect by -another_Rotated_Rect.angle. So, another_Rotated_Rect becomes a Rect called temp_Rect.
|
||||
# Then check if the rotated version of this Rotated_Rect
|
||||
# (temp_Rotated_Rect) collides with the obtained Rect.
|
||||
temp_Rotated_Rect = self.rotate(-another_Rotated_Rect.angle)
|
||||
temp_Rect = another_Rotated_Rect.get_rect()
|
||||
return temp_Rotated_Rect.colliderect(temp_Rect)
|
||||
@@ -0,0 +1,21 @@
|
||||
class UncasedDict(dict):
|
||||
|
||||
def __getitem__(self, key):
|
||||
for each_key in self:
|
||||
if each_key.upper() == key.upper():
|
||||
return super(UncasedDict, self).__getitem__(each_key)
|
||||
else:
|
||||
return super(UncasedDict, self).__getitem__(key)
|
||||
|
||||
def has_key(self, key):
|
||||
return self.__contains__(key)
|
||||
|
||||
def get(self, key):
|
||||
return self.__getitem__(key)
|
||||
|
||||
def __contains__(self, key):
|
||||
for each_key in self:
|
||||
if each_key.upper() == key.upper():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
Binary file not shown.
+40
@@ -0,0 +1,40 @@
|
||||
# Using metaclass and decorator to allow class access during class creation time
|
||||
from functools import partial
|
||||
import inspect
|
||||
|
||||
class meta(type):
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
methods=inspect.getmembers(temp_cls,inspect.ismethod)
|
||||
for (method_name,method_obj) in methods:
|
||||
tmp_spec=inspect.getargspec(method_obj)
|
||||
if "main_func" in tmp_spec.args:
|
||||
what_to_do,main_func=tmp_spec.defaults
|
||||
f=method_obj.im_func
|
||||
f.func_code,f.func_defaults,f.func_dict,f.func_doc,f.func_name=main_func.func_code, main_func.func_defaults,main_func.func_dict,main_func.func_doc,main_func.func_name
|
||||
what_to_do(method_obj)
|
||||
|
||||
return temp_cls
|
||||
|
||||
def do_it(what_to_do, main_func=None):
|
||||
if main_func is None:
|
||||
return partial(do_it,what_to_do)
|
||||
def whatever(what_to_do=what_to_do,main_func=main_func):
|
||||
pass
|
||||
return whatever
|
||||
|
||||
def original_decorator(func):
|
||||
func.im_class.a.append("so cool")
|
||||
print "Calling original decorator"
|
||||
|
||||
|
||||
class A(object):
|
||||
__metaclass__=meta
|
||||
a=[]
|
||||
@do_it(original_decorator)
|
||||
def some_method(self,a=5):
|
||||
''' hello'''
|
||||
print "Calling original method"
|
||||
|
||||
print("A.a is %s"%A.a)
|
||||
print(inspect.getargspec(A().some_method))
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
from functools import partial
|
||||
import inspect
|
||||
|
||||
def sync_func(func1, func2):
|
||||
'''Makes the 1st param (func) equivalent to 2nd param (func).'''
|
||||
func1.func_code = func2.func_code
|
||||
func1.func_defaults = func2.func_defaults
|
||||
func1.func_dict = func2.func_dict
|
||||
func1.func_doc = func2.func_doc
|
||||
func1.func_name = func2.func_name
|
||||
|
||||
|
||||
class meta(type):
|
||||
# Using metaclass and decorator to allow class access during class creation time
|
||||
# No method defined within the class should have "_process_meta" as arg
|
||||
# Potential problems: Using closures, function.func_globals is read-only
|
||||
# Doesnt get appropiate globals, maybe pass it (or the reqd global vars) as param on func defn
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
methods = inspect.getmembers(temp_cls, inspect.ismethod)
|
||||
for (method_name, method_obj) in methods:
|
||||
tmp_spec = inspect.getargspec(method_obj)
|
||||
if "__process_meta" in tmp_spec.args:
|
||||
what_to_do, main_func = tmp_spec.defaults[:-1]
|
||||
f = method_obj.im_func
|
||||
sync_func(f, main_func)
|
||||
mod_func = what_to_do(temp_cls, f)
|
||||
sync_func(f, mod_func)
|
||||
|
||||
return temp_cls
|
||||
|
||||
|
||||
def do_it(what_to_do, main_func=None):
|
||||
if main_func is None:
|
||||
return partial(do_it, what_to_do)
|
||||
|
||||
def whatever(what_to_do=what_to_do, main_func=main_func, __process_meta=True):
|
||||
pass
|
||||
return whatever
|
||||
def run_it(run_func):
|
||||
def what_to_do(cls, func):
|
||||
func(cls)
|
||||
return func
|
||||
return do_it(what_to_do=what_to_do,main_func=run_func)
|
||||
|
||||
|
||||
def original_classmethod_decorator(cls, func):
|
||||
# append default arg values to class variable "a"
|
||||
func_defaults = inspect.getargspec(func).defaults
|
||||
cls.a.append(func_defaults)
|
||||
func.__doc__ = "This is a class method"
|
||||
print "Calling original classmethod decorator"
|
||||
return func
|
||||
|
||||
|
||||
def original_method_decorator(cls, func):
|
||||
# append default arg values to class variable "a"
|
||||
func_defaults = inspect.getargspec(func).defaults
|
||||
cls.a.append(func_defaults)
|
||||
func.__doc__ = "This is a instance method" # Can change func properties
|
||||
print "Calling original method decorator"
|
||||
return func
|
||||
|
||||
|
||||
def decorator_to_classmethod(cls, func):
|
||||
cls.original_classmethod_decorator = classmethod(
|
||||
original_classmethod_decorator)
|
||||
return func
|
||||
|
||||
b=[]
|
||||
|
||||
class A(object):
|
||||
__metaclass__ = meta
|
||||
a = []
|
||||
## original_classmethod_decorator = classmethod(
|
||||
## original_classmethod_decorator)
|
||||
## original_method_decorator = classmethod(original_method_decorator)
|
||||
|
||||
@classmethod
|
||||
@do_it(original_classmethod_decorator)
|
||||
def some_method(cls, x=1):
|
||||
''' hello'''
|
||||
print "Calling original class method"
|
||||
|
||||
@classmethod
|
||||
@run_it
|
||||
def register_class(cls):
|
||||
b.append(cls)
|
||||
|
||||
|
||||
##
|
||||
# @classmethod
|
||||
# @do_it(decorator_to_classmethod)
|
||||
# def original_classmethod_decorator(cls):
|
||||
# pass
|
||||
|
||||
# @classmethod
|
||||
# @do_it(decorator_to_classmethod)
|
||||
# def original_method_decorator(cls):
|
||||
# pass
|
||||
|
||||
@do_it(original_method_decorator)
|
||||
def some_method_2(self, y=2):
|
||||
''' hello again'''
|
||||
print "Calling original method"
|
||||
|
||||
# signature preserved
|
||||
print(inspect.getargspec(A.some_method))
|
||||
print(inspect.getargspec(A.some_method_2))
|
||||
@@ -0,0 +1,81 @@
|
||||
# Using metaclass and decorator to allow class access during class creation time
|
||||
# No method defined within the class should have "_process_meta" as arg
|
||||
# Potential problems: Using closures, function.func_globals is read-only
|
||||
# => may cause problem
|
||||
from functools import partial
|
||||
import inspect
|
||||
|
||||
|
||||
def sync_func(func1, func2):
|
||||
'''Makes the 1st param (func) equivalent to 2nd param (func).'''
|
||||
func1.func_code = func2.func_code
|
||||
func1.func_defaults = func2.func_defaults
|
||||
func1.func_dict = func2.func_dict
|
||||
func1.func_doc = func2.func_doc
|
||||
func1.func_name = func2.func_name
|
||||
|
||||
|
||||
class meta(type):
|
||||
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
methods = inspect.getmembers(temp_cls, inspect.ismethod)
|
||||
for (method_name, method_obj) in methods:
|
||||
tmp_spec = inspect.getargspec(method_obj)
|
||||
if "__process_meta" in tmp_spec.args:
|
||||
what_to_do, main_func = tmp_spec.defaults[:-1]
|
||||
# is_classmethod=False
|
||||
# if method_obj.__self__==temp_cls:
|
||||
# is_classmethod=True
|
||||
f = method_obj.im_func
|
||||
sync_func(f, main_func)
|
||||
mod_func = what_to_do(temp_cls, f)
|
||||
sync_func(f, mod_func)
|
||||
|
||||
return temp_cls
|
||||
|
||||
|
||||
def do_it(what_to_do, main_func=None):
|
||||
if main_func is None:
|
||||
return partial(do_it, what_to_do)
|
||||
|
||||
def whatever(what_to_do=what_to_do, main_func=main_func, __process_meta=True):
|
||||
pass
|
||||
return whatever
|
||||
|
||||
|
||||
def original_classmethod_decorator(cls, func):
|
||||
# append default arg values to class variable "a"
|
||||
func_defaults = inspect.getargspec(func).defaults
|
||||
cls.a.append(func_defaults)
|
||||
func.__doc__ = "This is a class method"
|
||||
print "Calling original classmethod decorator"
|
||||
return func
|
||||
|
||||
|
||||
def original_method_decorator(cls, func):
|
||||
# append default arg values to class variable "a"
|
||||
func_defaults = inspect.getargspec(func).defaults
|
||||
cls.a.append(func_defaults)
|
||||
func.__doc__ = "This is a instance method"
|
||||
print "Calling original method decorator"
|
||||
return func
|
||||
|
||||
|
||||
class A(object):
|
||||
__metaclass__ = meta
|
||||
a = []
|
||||
|
||||
@classmethod
|
||||
@do_it(original_classmethod_decorator)
|
||||
def some_method(cls, x=1):
|
||||
''' hello'''
|
||||
print "Calling original class method"
|
||||
|
||||
@do_it(original_method_decorator)
|
||||
def some_method_2(self, y=2):
|
||||
''' hello again'''
|
||||
print "Calling original method"
|
||||
|
||||
print(inspect.getargspec(A.some_method))
|
||||
print(inspect.getargspec(A.some_method_2))
|
||||
+539
@@ -0,0 +1,539 @@
|
||||
# only for python 2.x
|
||||
# VERY IMP: Use weakrefs instead of list for fun_Game.list_class,\
|
||||
# fun_Class.list_instance and fun_Class.list_update_func
|
||||
|
||||
from uniquelist import uniquelist # imports uniquelist
|
||||
import pygame
|
||||
from pygame.locals import * # imports the constants
|
||||
import math
|
||||
from utils import register_class, meta_accessor_class, register_event, selfie, KW_EVENTS_IB, sort_events, append_user_events, fuzzy_match_event_name, KW_EVENTS_ALL, rect_to_pygame_rect
|
||||
# import utils
|
||||
from functools import partial
|
||||
from sprite_types import Circle, Rect
|
||||
import logging
|
||||
from copy import deepcopy
|
||||
from math_utils import atan2_inv
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
IS_TEST_MODE = True
|
||||
|
||||
# Mouse constants
|
||||
B_LEFT_CLICK = 1
|
||||
B_RIGHT_CLICK = 3
|
||||
B_MIDDLE_CLICK = 2
|
||||
B_SCROLLUP = 4
|
||||
B_SCROLLDOWN = 5
|
||||
|
||||
# Direction constants
|
||||
TOP = 1
|
||||
LEFT = 2
|
||||
BOTTOM = 3
|
||||
RIGHT = 4
|
||||
|
||||
|
||||
class fun_Game(object):
|
||||
list_class = uniquelist()
|
||||
list_event = [] # event_list of this step
|
||||
list_event_old = [] # event_list of the previous step
|
||||
# A sequence of boolean representing the state of every key
|
||||
list_state_all_buttons = []
|
||||
# A sequence of boolean representing the state of every key of previous
|
||||
# step
|
||||
list_state_all_buttons_old = []
|
||||
|
||||
def __init__(self, width, height, fps=30):
|
||||
pygame.init()
|
||||
self.fps = fps
|
||||
self.clock = pygame.time.Clock()
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.test_init()
|
||||
|
||||
@property
|
||||
def w(self):
|
||||
return self.width
|
||||
|
||||
@w.setter
|
||||
def w(self, val):
|
||||
self.width = val
|
||||
|
||||
@property
|
||||
def h(self):
|
||||
return self.height
|
||||
|
||||
@h.setter
|
||||
def h(self, val):
|
||||
self.height = val
|
||||
|
||||
# @classmethod
|
||||
# def _register_class_(cls, class_to_register):
|
||||
# ''' Registers class_to_register to its list_class '''
|
||||
# cls.list_class.append(class_to_register)
|
||||
@classmethod
|
||||
def register_class(cls, cls_to_register):
|
||||
cls.list_class.append(cls_to_register)
|
||||
|
||||
@classmethod
|
||||
def update_all_class(cls):
|
||||
for tmp_cls in cls.list_class:
|
||||
tmp_cls.update_instances(cls.list_event)
|
||||
|
||||
@classmethod
|
||||
def process_event_list(cls, list_event_):
|
||||
append_user_events(list_event_)
|
||||
cls.list_event.sort(sort_events)
|
||||
|
||||
@classmethod
|
||||
def _cache_event_list(cls):
|
||||
''' Cache event_list in every step.
|
||||
All events in fun_Game.list_event have a "type" property which are the usual constants. '''
|
||||
cls.list_event_old = cls.list_event # move current list to old list
|
||||
cls.list_state_all_buttons_old = cls.list_state_all_buttons
|
||||
|
||||
cls.list_event = pygame.event.get()
|
||||
cls.process_event_list(cls.list_event)
|
||||
# Returns a sequence of boolean representing the state of every key.
|
||||
# Use key constant values for indexing.
|
||||
cls.list_state_all_buttons = pygame.key.get_pressed()
|
||||
# print cls.list_event # debug message
|
||||
# control access to list_event
|
||||
# with getter, do something crazy for filtering
|
||||
# or a filtering function
|
||||
|
||||
@classmethod
|
||||
def for_all_instance(cls, func_to_run, flatten):
|
||||
''' Note: flatten can be "level-instance" or "level-class" or False'''
|
||||
return_list = []
|
||||
for tmp_cls in cls.list_class:
|
||||
return_item = tmp_cls.for_all_instance(
|
||||
func_to_run, flatten=flatten)
|
||||
if flatten == "level-instance" or flatten == "level-class":
|
||||
return_list.extend(return_item)
|
||||
else:
|
||||
return_list.append(return_item)
|
||||
return return_list
|
||||
|
||||
@classmethod
|
||||
def for_all_class(cls, func_to_run, flatten):
|
||||
''' Note: flatten can be True or False'''
|
||||
return_list = []
|
||||
for tmp_class in cls.list_class:
|
||||
return_item = func_to_run(tmp_class)
|
||||
if flatten:
|
||||
return_list.extend(return_item)
|
||||
else:
|
||||
return_list.append(return_item)
|
||||
return return_list
|
||||
|
||||
@staticmethod
|
||||
def collect_self_clear_rect(self):
|
||||
_list_clear_rect = []
|
||||
_list_rendered_sprite = []
|
||||
# perf hog: search for better way to remove list items iteratively
|
||||
for tmp_old_sprite in self.list_rendered_sprite:
|
||||
if (not tmp_old_sprite.get("still_valid")):
|
||||
# returns bbox of all list_rendered_sprite that are not still_valid, after removing them from that list
|
||||
# so, list now contains only of the older sprites still_valid
|
||||
tmp_clear_rect_bbox = tmp_old_sprite["bbox"]
|
||||
_list_clear_rect.append(tmp_clear_rect_bbox)
|
||||
else:
|
||||
_list_rendered_sprite.append(tmp_old_sprite)
|
||||
if ("still_valid" in tmp_old_sprite):
|
||||
tmp_old_sprite.pop("still_valid")
|
||||
|
||||
# in next step :
|
||||
# _list_rendered_sprite.append(self.list_dirty_sprite)
|
||||
# self.list_dirty_sprite=[]
|
||||
self.list_rendered_sprite = _list_rendered_sprite
|
||||
return _list_clear_rect
|
||||
|
||||
@staticmethod
|
||||
def collect_self_rendered_sprite(self):
|
||||
return self.list_rendered_sprite
|
||||
|
||||
@staticmethod
|
||||
def collect_self_dirty_sprite(self):
|
||||
return self.list_dirty_sprite
|
||||
|
||||
@staticmethod
|
||||
def move_dirty_to_rendered(self):
|
||||
self.list_rendered_sprite.extend(self.list_dirty_sprite)
|
||||
self.list_dirty_sprite = []
|
||||
return None
|
||||
|
||||
def blit_all_class(self):
|
||||
# step 1: collect all clear rects
|
||||
# i.e. remove last_rendered_rects which are not still_valid and return them
|
||||
# also move to_be_rendered_sprites into that list and clear dirty list
|
||||
list_clear_rect = self.for_all_instance(
|
||||
self.collect_self_clear_rect, flatten="level-instance")
|
||||
list_rendered_sprite = self.for_all_instance(
|
||||
self.collect_self_rendered_sprite, flatten="level-instance")
|
||||
list_dirty_sprite = self.for_all_instance(
|
||||
self.collect_self_dirty_sprite, flatten="level-instance")
|
||||
|
||||
# step 2: check if any clear_rect intersects with last_rendered_rects,
|
||||
# return a list of dirty overlay for those last_rendered_rects.
|
||||
# also if it is contained (totally within), mark clear_rect for removal
|
||||
list_dirty_overlay_sprite = []
|
||||
list_cancelled_clear_rect = []
|
||||
for tmp_old_sprite in list_rendered_sprite:
|
||||
for tmp_clear_rect in list_clear_rect:
|
||||
tmp_intersect_rect = tmp_clear_rect.clip(
|
||||
tmp_old_sprite["bbox"])
|
||||
if tmp_intersect_rect.w > 0 and tmp_intersect_rect.h > 0:
|
||||
# make blit funcs capable of taking a clip rect, will be appplied before blitting
|
||||
## print("explicit blit")
|
||||
copy_old_sprite = deepcopy(tmp_old_sprite)
|
||||
copy_old_sprite["clip_rect"] = tmp_intersect_rect
|
||||
list_dirty_overlay_sprite.append(copy_old_sprite)
|
||||
|
||||
if tmp_old_sprite["bbox"].contains(tmp_clear_rect):
|
||||
# Cancel clear rect
|
||||
list_cancelled_clear_rect.append(tmp_clear_rect)
|
||||
|
||||
else:
|
||||
# No explicit blit
|
||||
pass
|
||||
# step 3: for every clear_rect not marked for removal, do the
|
||||
# clear_rects.
|
||||
# print "Clear_rects= ",len(list_clear_rect)-len(list_cancelled_clear_rect)
|
||||
i = 0
|
||||
for tmp_clear_rect in list_clear_rect:
|
||||
# convert to pygame rect
|
||||
if not (tmp_clear_rect in list_cancelled_clear_rect):
|
||||
self.screen.fill(pygame.Color(0, 0, 0, 1), tmp_clear_rect)
|
||||
i += 1
|
||||
print "i=", i
|
||||
|
||||
# step 4: do blit for all dirty_sprite and dirty_overlay
|
||||
for tmp_dirty_sprite in list_dirty_sprite:
|
||||
tmp_dirty_sprite["sprite"].blit(self.screen)
|
||||
|
||||
# print "Dirty_overlays= ",len(list_dirty_overlay_sprite)
|
||||
# print list_dirty_overlay_sprite
|
||||
for tmp_overlay_sprite in list_dirty_overlay_sprite:
|
||||
new_overlay_sprite = tmp_overlay_sprite[
|
||||
"sprite"].__class__(**tmp_overlay_sprite["config"])
|
||||
new_overlay_sprite.blit(
|
||||
self.screen, clip_rect=tmp_overlay_sprite["clip_rect"])
|
||||
|
||||
# step 5: update display
|
||||
list_display_update = [tmp_dirty_sprite["bbox"]
|
||||
for tmp_dirty_sprite in list_dirty_sprite] + list_clear_rect
|
||||
pygame.display.update(list_display_update)
|
||||
# if not (list_dirty_sprite[0]["sprite"].bbox in list_display_update):
|
||||
# print("problem")
|
||||
|
||||
# step 6: cleaning jobs
|
||||
self.for_all_instance(self.move_dirty_to_rendered, flatten=False)
|
||||
# pygame.display.flip()
|
||||
|
||||
def test_init(self):
|
||||
''' Empty function to be overloaded for extra init on test mode. '''
|
||||
pass
|
||||
|
||||
def test_update(self):
|
||||
''' Empty function to be overloaded for extra draw on test mode. '''
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
self.screen = pygame.display.set_mode([self.width, self.height])
|
||||
frame_no = 0
|
||||
while True:
|
||||
# Todo: Always exit on event_close : make it default behavior,
|
||||
# although override-able
|
||||
frame_no += 1
|
||||
# print frame_no
|
||||
self._cache_event_list()
|
||||
self.update_all_class()
|
||||
self.blit_all_class()
|
||||
self.test_update()
|
||||
# VERY IMPORTANT: Do a spare first step so that every variable / list gets initialized well.
|
||||
# Start instant creation and execution from second step.
|
||||
# IMPORTANT: First do all fun_Game related stuff before dealing
|
||||
# with game objects.
|
||||
self.clock.tick(self.fps)
|
||||
|
||||
# Todo - Add crazy functions to allow other objects and instances finding
|
||||
# like GM
|
||||
# Todo - Easy way to take screenshot and save it as pic
|
||||
# Todo: Game testing module. Lets you compare screenshots and compare values with pixelarray or surface.get_at
|
||||
# Also allows accessing different config values.
|
||||
|
||||
|
||||
# class fun_Game ends here
|
||||
# print(fun_Game)
|
||||
|
||||
# global register_event cached,as it will also be used as classmethod
|
||||
# should use register_event=_register_event at end of all class defn
|
||||
|
||||
meta_fun_Class = meta_accessor_class
|
||||
|
||||
|
||||
@register_class(fun_Game)
|
||||
class fun_Class(object):
|
||||
# think about this: priority_order and depth
|
||||
# by default, depends on "when class was defined"
|
||||
# cls.priority_order = cls.depth = len(fun_Game.list_class)
|
||||
__metaclass__ = meta_fun_Class
|
||||
|
||||
# Below lines moved to meta_fun_Class
|
||||
# list_instance = uniquelist()
|
||||
# list_check_func = uniquelist()
|
||||
# dict_action_func -> dict of action funcs, key=event_numb like KEYDOWN
|
||||
# dict_action_func = {}
|
||||
|
||||
sprite_defaults = {
|
||||
"type": Rect,
|
||||
"params": {
|
||||
"size": (40, 40),
|
||||
"color": None
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, x=None, y=None):
|
||||
# use sprite as a general term, img->one kind of sprite, rect, circle
|
||||
self.x_start = x
|
||||
self.y_start = y
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.x_prev = x
|
||||
self.y_prev = y
|
||||
self.vel_x, self.vel_y, self.accln_x, self.accln_y = 0, 0, 0, 0
|
||||
|
||||
if (self.sprite_defaults and self.sprite_defaults.get("type")):
|
||||
if (x is None) or (y is None):
|
||||
raise AttributeError(
|
||||
"fun_Class with sprite_defaults must have x,y")
|
||||
|
||||
self.sprite = self.sprite_defaults.get("type").from_container_obj(
|
||||
container_obj=self, **self.sprite_defaults["params"])
|
||||
self.list_dirty_sprite = []
|
||||
# list_rendered_sprite => sprites that are effectively on the
|
||||
# screen now
|
||||
self.list_rendered_sprite = []
|
||||
else:
|
||||
self.sprite = None
|
||||
self.list_instance.append(self)
|
||||
# think about self.action_create()
|
||||
|
||||
@property
|
||||
def vel(self):
|
||||
return math.sqrt(self.vel_x ** 2 + self.vel_y ** 2)
|
||||
|
||||
@vel.setter
|
||||
def vel(self, val):
|
||||
self.vel_x = val * math.cos(math.radians(self.vel_direction))
|
||||
self.vel_y = val * math.sin(math.radians(self.vel_direction))
|
||||
|
||||
@property
|
||||
def vel_direction(self):
|
||||
return atan2_inv(self.vel_y, self.vel_x)
|
||||
|
||||
@vel_direction.setter
|
||||
def vel_direction(self, val):
|
||||
self.vel_x = self.vel * math.cos(math.radians(val))
|
||||
self.vel_y = self.vel * math.sin(math.radians(val))
|
||||
|
||||
@property
|
||||
def accln(self):
|
||||
return math.sqrt(self.accln_x ** 2 + self.accln_y ** 2)
|
||||
|
||||
@accln.setter
|
||||
def accln(self, val):
|
||||
self.accln_x = val * math.cos(math.radians(self.accln_direction))
|
||||
self.accln_y = val * math.sin(math.radians(self.accln_direction))
|
||||
|
||||
@property
|
||||
def accln_direction(self):
|
||||
return atan2_inv(self.accln_y, self.accln_x)
|
||||
|
||||
@accln_direction.setter
|
||||
def accln_direction(self, val):
|
||||
self.accln_x = self.accln * math.cos(math.radians(val))
|
||||
self.accln_y = self.accln * math.sin(math.radians(val))
|
||||
|
||||
@classmethod
|
||||
def update_instances(cls, list_event):
|
||||
'''calls update_self for all instances.'''
|
||||
for tmp_instance in cls.list_instance:
|
||||
tmp_instance.update_self(list_event)
|
||||
|
||||
def update_self(self, list_event):
|
||||
# print list_event
|
||||
for each_ev in list_event:
|
||||
# print self.dict_action_func
|
||||
if each_ev.type in self.dict_action_func:
|
||||
for each_action in self.dict_action_func[each_ev.type]:
|
||||
# similar as self.action_step()
|
||||
each_action(self, each_ev)
|
||||
|
||||
@classmethod
|
||||
def _check_event(cls, ev_name_or_type, new_or_old):
|
||||
''' ev_name_or_type => name_or_type(numb)_of_event
|
||||
new_or_old => current_event_list or old_event_list '''
|
||||
matched_events = []
|
||||
if new_or_old == "new":
|
||||
list_to_check = cls.game_class.list_event
|
||||
elif new_or_old == "old":
|
||||
list_to_check = cls.game_class.list_event_old
|
||||
else:
|
||||
raise AttributeError("new_or_old must be 'new' or 'old'.")
|
||||
if type(ev_name_or_type) is int:
|
||||
ev_type = ev_name_or_type
|
||||
elif type(ev_name_or_type) is str:
|
||||
ev_name = fuzzy_match_event_name(ev_name_or_type, "event")
|
||||
ev_type = KW_EVENTS_ALL[ev_name]
|
||||
for ev in list_to_check:
|
||||
if ev.type == ev_type:
|
||||
matched_events.append(ev)
|
||||
return matched_events
|
||||
|
||||
@classmethod
|
||||
def check_event(cls, ev_name_or_type):
|
||||
return cls._check_event(ev_name_or_type, "new")
|
||||
|
||||
@classmethod
|
||||
def check_event_old(cls, ev_name_or_type):
|
||||
return cls._check_event(ev_name_or_type, "old")
|
||||
|
||||
@classmethod
|
||||
def register_event(cls, event_name=None, func_to_register=None):
|
||||
global register_event
|
||||
register_event(event_name, func_to_register, cls)
|
||||
|
||||
@classmethod
|
||||
def for_all_instance(cls, func_to_run, flatten):
|
||||
return_list = []
|
||||
for tmp_instance in cls.list_instance:
|
||||
return_item = func_to_run(tmp_instance)
|
||||
if flatten == "level-instance":
|
||||
return_list.extend(return_item)
|
||||
else:
|
||||
return_list.append(return_item)
|
||||
return return_list
|
||||
|
||||
def collide(self, *args, **kwargs):
|
||||
return self.sprite.collide(*args, **kwargs)
|
||||
|
||||
# always use selfie,not selfie_depreceated most compatible
|
||||
# make this classmethod,selfie-ridden register_events as test
|
||||
# @register_event()
|
||||
def action_end_step_default(self, ev):
|
||||
if not(self.x is None) and not(self.y is None):
|
||||
# Set x_prev, y_prev
|
||||
self.x_prev = self.x
|
||||
self.y_prev = self.y
|
||||
# Accelerate velocity
|
||||
self.vel_x += self.accln_x
|
||||
self.vel_y += self.accln_y
|
||||
# Move x and y
|
||||
self.x += self.vel_x
|
||||
self.y += self.vel_y
|
||||
|
||||
def action_begin_step(self, ev):
|
||||
# print "Calling begin_step"
|
||||
pass
|
||||
|
||||
def action_JOY_BUTTON_UP(self, ev):
|
||||
print "calling JOY_BUTTON_UP"
|
||||
|
||||
def action_key_down(self, ev):
|
||||
print "Calling key_down"
|
||||
|
||||
def action_end_step(self, ev):
|
||||
# print "Calling end step"
|
||||
pass
|
||||
|
||||
def action_draw_default(self, ev):
|
||||
# print "Drawing"
|
||||
self.sprite.draw()
|
||||
# end of fun_Class
|
||||
# Other classes
|
||||
|
||||
|
||||
# functions outside all classes
|
||||
|
||||
|
||||
# list_to_get is attached to a constant list here
|
||||
def get_event_list(event_types=None, further_check_variable_name=None, further_check_value=None, list_to_get=None):
|
||||
''' Get the required events from the event_list.
|
||||
get_event_list([event_types],[further_check_variable_name],further_check_value=None,list_to_get=fun_Game.list_event):
|
||||
event_types (optional): event_name|list[event_name]
|
||||
get_event_list() -> returns whole event_list(to be precise, list_to_get)
|
||||
get_event_list(events) -> returns event_list(to be precise, list_to_get) filtered to contain only "events"
|
||||
get_event_list([events],further_check_variable_name="var_name",further_check_value=value) ->
|
||||
returns sub-list containing those elements of get_event_list([events]) for which var_name=value
|
||||
Potential candidates for list_to_get ->
|
||||
fun_Game.list_event, fun_Game.list_event_old, fun_Game.list_state_all_buttons, fun_Game.list_state_all_buttons_old'''
|
||||
if list_to_get is None:
|
||||
list_to_get = fun_Game.list_event_old
|
||||
if further_check_variable_name:
|
||||
further_check_enabled = True
|
||||
else:
|
||||
further_check_enabled = False
|
||||
if event_types:
|
||||
if not hasattr(event_types, "__iter__"):
|
||||
# if not iterable, make a list out of it
|
||||
event_types = [event_types]
|
||||
|
||||
def func_filter():
|
||||
list_return = []
|
||||
if not event_types:
|
||||
return list_to_get
|
||||
# all events in fun_Game.list_event have a "type" property
|
||||
for temp_1 in list_to_get:
|
||||
for temp_2 in event_types:
|
||||
if temp_1.type == temp_2:
|
||||
list_return.append(temp_1)
|
||||
return list_return
|
||||
|
||||
# returns part of temp_list which passes further_check
|
||||
def further_check_filter(temp_list):
|
||||
list_return = []
|
||||
if further_check_enabled:
|
||||
for temp in temp_list:
|
||||
# may raise error if further_check_variable_name is not present
|
||||
# for all members of the list
|
||||
if getattr(temp, further_check_variable_name) == further_check_value:
|
||||
list_return.append(temp)
|
||||
else:
|
||||
list_return = temp_list
|
||||
return list_return
|
||||
# returns elements common in fun_Game.list_events and events which are
|
||||
# accepted after further_check
|
||||
return further_check_filter(func_filter())
|
||||
# end of get_event_list()
|
||||
|
||||
# Todo: see below
|
||||
# Collision helper event_collision funcs (Done, for circle)
|
||||
# Allow collision with "all"
|
||||
# More collision func like GM
|
||||
# More extended draw funcs
|
||||
# Make img sprite
|
||||
# Use rects retuned from blit to display.update
|
||||
#
|
||||
# 1. (Think) Allow rect-like and circle-like constructs wherever rect and circle are expected.
|
||||
# 2. Do all sort of type-checking.
|
||||
# 3. Use sprites and groups in pygame as containers
|
||||
# Imp: Allow debugging with event handlers and others with @debug
|
||||
|
||||
# Design tips I will use later
|
||||
# use weakrefs as much as possible
|
||||
# IMP: always derive classes from object. Else, in python 2.x, they become old-style class which sucks.
|
||||
# use tuples instead of lists wherver possible because they are usually faster to create
|
||||
# learn about generators
|
||||
# named tuples, arrays are better. use more of them. named tuples can be accessed.
|
||||
# refactor code into proper modules as-well-as use better named functions and variables
|
||||
# use enumerate() for getting the index and value of elements while looping through lists. This mistake done atleast 1 time.
|
||||
# use xrange instead of range. It produces one at a time. range is replaced by xrange in python 3.x
|
||||
# use reversed() for backward loops, sorted() for sorted order.
|
||||
# instead of zip(), use izip().
|
||||
# use key instead of comparator
|
||||
# use iter(iter_type,sentinel_value) instead of for loops
|
||||
# partial() makes a function with more number of argument to less number of argument
|
||||
# use for/else instead of exit based on flags
|
||||
# look at dict.iteritems() and dict.setdefaults
|
||||
# learn defaultdicts and collections module
|
||||
Binary file not shown.
+1005
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
import inspect
|
||||
|
||||
def original_decorator(func):
|
||||
# need to access class here
|
||||
# for eg, to append the func itself to class variable "a", to register itself
|
||||
# or say, append their default arg values to class variable "a"
|
||||
return func
|
||||
|
||||
class A(object):
|
||||
a=[]
|
||||
|
||||
@classmethod
|
||||
@original_decorator
|
||||
def some_method(self,a=5):
|
||||
''' hello'''
|
||||
print "Calling some_method"
|
||||
@original_decorator
|
||||
def some_method_2(self):
|
||||
''' hello again'''
|
||||
print "Calling some_method_2"
|
||||
|
||||
##print("A.a is %s"%A.a)
|
||||
##print(inspect.getargspec(A.some_method))
|
||||
@@ -0,0 +1,38 @@
|
||||
from functools import partial
|
||||
import inspect
|
||||
|
||||
class meta(type):
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
methods=inspect.getmembers(temp_cls,inspect.ismethod)
|
||||
print methods
|
||||
print "inspecting.."
|
||||
for tmp in methods:
|
||||
method=tmp[1]
|
||||
tmp_spec=inspect.getargspec(method)
|
||||
if "main_func" in tmp_spec.args:
|
||||
main_func=tmp_spec.defaults[1]
|
||||
tmp_spec.defaults[0]()
|
||||
main_func(50)
|
||||
f=method.im_func
|
||||
print f
|
||||
f.func_code,f.func_defaults,f.func_dict,f.func_doc,f.func_name=main_func.func_code, main_func.func_defaults,main_func.func_dict,main_func.func_doc,main_func.func_name
|
||||
return temp_cls
|
||||
|
||||
def doit(what_to_do, main_func):
|
||||
def asd(what_to_do=what_to_do,main_func=main_func):
|
||||
pass
|
||||
return asd
|
||||
|
||||
def pr5():
|
||||
print 5
|
||||
|
||||
do_pr5=partial(doit,pr5)
|
||||
|
||||
class A(object):
|
||||
__metaclass__=meta
|
||||
a=[]
|
||||
@do_pr5
|
||||
def abc(self,a=5):
|
||||
''' hello'''
|
||||
print a+1
|
||||
@@ -0,0 +1,27 @@
|
||||
import pygame
|
||||
w,h=800,200
|
||||
fps=60
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode([w, h])
|
||||
color=pygame.Color("white")
|
||||
clock=pygame.time.Clock()
|
||||
radius=40
|
||||
x,y=800,100
|
||||
def get_bbox(x,y):
|
||||
left = x - radius
|
||||
top = y - radius
|
||||
width = radius * 2
|
||||
height = radius * 2
|
||||
return pygame.Rect((left, top), (width, height))
|
||||
|
||||
while True:
|
||||
pygame.event.pump()
|
||||
old_x=x
|
||||
x-=5
|
||||
screen.fill(pygame.Color("black"),get_bbox(old_x,y))
|
||||
pygame.draw.circle(screen, color, (x, y), radius, 1)
|
||||
pygame.display.update([get_bbox(x,y),get_bbox(old_x,y)])
|
||||
## pygame.display.flip()
|
||||
clock.tick(fps)
|
||||
## time_passed=clock.get_time()
|
||||
## print(time_passed)
|
||||
@@ -0,0 +1,517 @@
|
||||
import pygame
|
||||
import pygame.locals as pygame_consts
|
||||
from UncasedDict import UncasedDict
|
||||
|
||||
DICT_EVENT_IB = {
|
||||
"QUIT": pygame_consts.QUIT,
|
||||
"ACTIVE_EVENT": pygame_consts.ACTIVEEVENT,
|
||||
"KEY_DOWN": pygame_consts.KEYDOWN,
|
||||
"KEY_UP": pygame_consts.KEYUP,
|
||||
"MOUSE_MOTION": pygame_consts.MOUSEMOTION,
|
||||
"MOUSE_BUTTON_UP": pygame_consts.MOUSEBUTTONUP,
|
||||
"MOUSE_BUTTON_DOWN": pygame_consts.MOUSEBUTTONDOWN,
|
||||
"JOY_AXIS_MOTION": pygame_consts.JOYAXISMOTION,
|
||||
"JOY_BALL_MOTION": pygame_consts.JOYBALLMOTION,
|
||||
"JOY_HAT_MOTION": pygame_consts.JOYHATMOTION,
|
||||
"JOY_BUTTON_UP": pygame_consts.JOYBUTTONUP,
|
||||
"JOY_BUTTOND_OWN": pygame_consts.JOYBUTTONDOWN,
|
||||
"VIDEO_RESIZE": pygame_consts.VIDEORESIZE,
|
||||
"VIDEO_EXPOSE": pygame_consts.VIDEOEXPOSE,
|
||||
# "USER_EVENT": pygame_consts.USEREVENT,
|
||||
# think of begin_step, step and end_step
|
||||
}
|
||||
|
||||
|
||||
DICT_KEYS = {
|
||||
r"BACKSPACE": pygame_consts.K_BACKSPACE,
|
||||
r"TAB": pygame_consts.K_TAB,
|
||||
r"CLEAR": pygame_consts.K_CLEAR,
|
||||
r"RETURN": pygame_consts.K_RETURN,
|
||||
r"PAUSE": pygame_consts.K_PAUSE,
|
||||
r"ESCAPE": pygame_consts.K_ESCAPE,
|
||||
r"SPACE": pygame_consts.K_SPACE,
|
||||
r"EXCLAIM": pygame_consts.K_EXCLAIM,
|
||||
r"QUOTEDBL": pygame_consts.K_QUOTEDBL,
|
||||
r"HASH": pygame_consts.K_HASH,
|
||||
r"DOLLAR": pygame_consts.K_DOLLAR,
|
||||
r"AMPERSAND": pygame_consts.K_AMPERSAND,
|
||||
r"QUOTE": pygame_consts.K_QUOTE,
|
||||
r"LEFTPAREN": pygame_consts.K_LEFTPAREN,
|
||||
r"RIGHTPAREN": pygame_consts.K_RIGHTPAREN,
|
||||
r"ASTERISK": pygame_consts.K_ASTERISK,
|
||||
r"PLUS": pygame_consts.K_PLUS,
|
||||
r"COMMA": pygame_consts.K_COMMA,
|
||||
r"MINUS": pygame_consts.K_MINUS,
|
||||
r"PERIOD": pygame_consts.K_PERIOD,
|
||||
r"SLASH": pygame_consts.K_SLASH,
|
||||
r"0": pygame_consts.K_0,
|
||||
r"1": pygame_consts.K_1,
|
||||
r"2": pygame_consts.K_2,
|
||||
r"3": pygame_consts.K_3,
|
||||
r"4": pygame_consts.K_4,
|
||||
r"5": pygame_consts.K_5,
|
||||
r"6": pygame_consts.K_6,
|
||||
r"7": pygame_consts.K_7,
|
||||
r"8": pygame_consts.K_8,
|
||||
r"9": pygame_consts.K_9,
|
||||
r"COLON": pygame_consts.K_COLON,
|
||||
r"SEMICOLON": pygame_consts.K_SEMICOLON,
|
||||
r"LESS": pygame_consts.K_LESS,
|
||||
r"EQUALS": pygame_consts.K_EQUALS,
|
||||
r"GREATER": pygame_consts.K_GREATER,
|
||||
r"QUESTION": pygame_consts.K_QUESTION,
|
||||
r"AT": pygame_consts.K_AT,
|
||||
r"LEFTBRACKET": pygame_consts.K_LEFTBRACKET,
|
||||
r"BACKSLASH": pygame_consts.K_BACKSLASH,
|
||||
r"RIGHTBRACKET": pygame_consts.K_RIGHTBRACKET,
|
||||
r"CARET": pygame_consts.K_CARET,
|
||||
r"UNDERSCORE": pygame_consts.K_UNDERSCORE,
|
||||
r"BACKQUOTE": pygame_consts.K_BACKQUOTE,
|
||||
r"a": pygame_consts.K_a,
|
||||
r"b": pygame_consts.K_b,
|
||||
r"c": pygame_consts.K_c,
|
||||
r"d": pygame_consts.K_d,
|
||||
r"e": pygame_consts.K_e,
|
||||
r"f": pygame_consts.K_f,
|
||||
r"g": pygame_consts.K_g,
|
||||
r"h": pygame_consts.K_h,
|
||||
r"i": pygame_consts.K_i,
|
||||
r"j": pygame_consts.K_j,
|
||||
r"k": pygame_consts.K_k,
|
||||
r"l": pygame_consts.K_l,
|
||||
r"m": pygame_consts.K_m,
|
||||
r"n": pygame_consts.K_n,
|
||||
r"o": pygame_consts.K_o,
|
||||
r"p": pygame_consts.K_p,
|
||||
r"q": pygame_consts.K_q,
|
||||
r"r": pygame_consts.K_r,
|
||||
r"s": pygame_consts.K_s,
|
||||
r"t": pygame_consts.K_t,
|
||||
r"u": pygame_consts.K_u,
|
||||
r"v": pygame_consts.K_v,
|
||||
r"w": pygame_consts.K_w,
|
||||
r"x": pygame_consts.K_x,
|
||||
r"y": pygame_consts.K_y,
|
||||
r"z": pygame_consts.K_z,
|
||||
r"DELETE": pygame_consts.K_DELETE,
|
||||
r"KP0": pygame_consts.K_KP0,
|
||||
r"KP1": pygame_consts.K_KP1,
|
||||
r"KP2": pygame_consts.K_KP2,
|
||||
r"KP3": pygame_consts.K_KP3,
|
||||
r"KP4": pygame_consts.K_KP4,
|
||||
r"KP5": pygame_consts.K_KP5,
|
||||
r"KP6": pygame_consts.K_KP6,
|
||||
r"KP7": pygame_consts.K_KP7,
|
||||
r"KP8": pygame_consts.K_KP8,
|
||||
r"KP9": pygame_consts.K_KP9,
|
||||
r"KP_PERIOD": pygame_consts.K_KP_PERIOD,
|
||||
r"KP_DIVIDE": pygame_consts.K_KP_DIVIDE,
|
||||
r"KP_MULTIPLY": pygame_consts.K_KP_MULTIPLY,
|
||||
r"KP_MINUS": pygame_consts.K_KP_MINUS,
|
||||
r"KP_PLUS": pygame_consts.K_KP_PLUS,
|
||||
r"KP_ENTER": pygame_consts.K_KP_ENTER,
|
||||
r"KP_EQUALS": pygame_consts.K_KP_EQUALS,
|
||||
r"UP": pygame_consts.K_UP,
|
||||
r"DOWN": pygame_consts.K_DOWN,
|
||||
r"RIGHT": pygame_consts.K_RIGHT,
|
||||
r"LEFT": pygame_consts.K_LEFT,
|
||||
r"INSERT": pygame_consts.K_INSERT,
|
||||
r"HOME": pygame_consts.K_HOME,
|
||||
r"END": pygame_consts.K_END,
|
||||
r"PAGEUP": pygame_consts.K_PAGEUP,
|
||||
r"PAGEDOWN": pygame_consts.K_PAGEDOWN,
|
||||
r"F1": pygame_consts.K_F1,
|
||||
r"F2": pygame_consts.K_F2,
|
||||
r"F3": pygame_consts.K_F3,
|
||||
r"F4": pygame_consts.K_F4,
|
||||
r"F5": pygame_consts.K_F5,
|
||||
r"F6": pygame_consts.K_F6,
|
||||
r"F7": pygame_consts.K_F7,
|
||||
r"F8": pygame_consts.K_F8,
|
||||
r"F9": pygame_consts.K_F9,
|
||||
r"F10": pygame_consts.K_F10,
|
||||
r"F11": pygame_consts.K_F11,
|
||||
r"F12": pygame_consts.K_F12,
|
||||
r"F13": pygame_consts.K_F13,
|
||||
r"F14": pygame_consts.K_F14,
|
||||
r"F15": pygame_consts.K_F15,
|
||||
r"NUMLOCK": pygame_consts.K_NUMLOCK,
|
||||
r"CAPSLOCK": pygame_consts.K_CAPSLOCK,
|
||||
r"SCROLLOCK": pygame_consts.K_SCROLLOCK,
|
||||
r"RSHIFT": pygame_consts.K_RSHIFT,
|
||||
r"LSHIFT": pygame_consts.K_LSHIFT,
|
||||
r"RCTRL": pygame_consts.K_RCTRL,
|
||||
r"LCTRL": pygame_consts.K_LCTRL,
|
||||
r"RALT": pygame_consts.K_RALT,
|
||||
r"LALT": pygame_consts.K_LALT,
|
||||
r"RMETA": pygame_consts.K_RMETA,
|
||||
r"LMETA": pygame_consts.K_LMETA,
|
||||
r"LSUPER": pygame_consts.K_LSUPER,
|
||||
r"RSUPER": pygame_consts.K_RSUPER,
|
||||
r"MODE": pygame_consts.K_MODE,
|
||||
r"HELP": pygame_consts.K_HELP,
|
||||
r"PRINT": pygame_consts.K_PRINT,
|
||||
r"SYSREQ": pygame_consts.K_SYSREQ,
|
||||
r"BREAK": pygame_consts.K_BREAK,
|
||||
r"MENU": pygame_consts.K_MENU,
|
||||
r"POWER": pygame_consts.K_POWER,
|
||||
r"EURO": pygame_consts.K_EURO,
|
||||
}
|
||||
|
||||
LIST_EVENTS_GAME_PRE = ["BEGIN_STEP"]
|
||||
# Custom events to be registered here
|
||||
LIST_EVENTS_GAME_POST = ["STEP", "DRAW", "END_STEP"]
|
||||
LIST_EVENTS_CUSTOM = [
|
||||
"KEY_PRESS", "MOUSE_PRESS", "Instance_Create", "Instance_Destroy"]
|
||||
|
||||
|
||||
dict_event_name = UncasedDict()
|
||||
list_event = []
|
||||
list_event_old = []
|
||||
list_state_key = []
|
||||
list_state_key_old = []
|
||||
list_state_mouse, list_state_mouse_old = [], []
|
||||
|
||||
|
||||
def register_event_name(ev_name, ev_id=None):
|
||||
if (ev_name in dict_event_name):
|
||||
raise TypeError(
|
||||
"ev_name={0} is already registered".format(ev_name))
|
||||
if (ev_id is None):
|
||||
ev_id = max(
|
||||
pygame_consts.USEREVENT + 1, max(dict_event_name.values()) + 1)
|
||||
dict_event_name[ev_name] = ev_id
|
||||
|
||||
|
||||
def add_each_event(ev):
|
||||
if not (ev.ev_name in dict_event_name):
|
||||
return TypeError("ev_name not registered")
|
||||
else:
|
||||
# make list_event_accessible
|
||||
list_event.append(ev)
|
||||
|
||||
|
||||
def add_returned_events(ev_or_ev_list):
|
||||
# fix below cond
|
||||
if hasattr(ev_or_ev_list, "__iter__"):
|
||||
# list of events
|
||||
for each_ev in ev_or_ev_list:
|
||||
add_each_event(each_ev)
|
||||
else:
|
||||
# single event
|
||||
add_each_event(ev_or_ev_list)
|
||||
|
||||
|
||||
def get_event_name(ev_id):
|
||||
for ev_name in dict_event_name:
|
||||
if dict_event_name[ev_name] == ev_id:
|
||||
return ev_name
|
||||
|
||||
|
||||
def get_event_id(ev_name):
|
||||
return dict_event_name.get(ev_name)
|
||||
|
||||
|
||||
def get_key_name(key_id):
|
||||
for key_name in DICT_KEYS:
|
||||
if DICT_KEYS[key_name] == key_id:
|
||||
return key_name
|
||||
|
||||
|
||||
def get_key_id(key_name):
|
||||
return DICT_KEYS.get(key_name)
|
||||
|
||||
|
||||
def get_mouse_btn_name(btn_id):
|
||||
# btn_id can be 0, 1 or 2
|
||||
if btn_id == 0:
|
||||
return "left"
|
||||
elif btn_id == 1:
|
||||
return "middle"
|
||||
elif btn_id == 2:
|
||||
return "right"
|
||||
else:
|
||||
raise ValueError("btn_id must be 0, 1 or 2")
|
||||
|
||||
# No sort_events, event_generators should be pushed in correct order
|
||||
|
||||
|
||||
def fuzzy_match_event_name(string_, event_or_action):
|
||||
str_upper = string_.upper()
|
||||
if not (str_upper in dict_event_name):
|
||||
event_or_action = event_or_action.lower()
|
||||
if event_or_action == "event" or event_or_action == "action":
|
||||
# STR_STARTER becomes event_ or action_
|
||||
STR_STARTER = event_or_action.upper() + "_"
|
||||
else:
|
||||
raise TypeError(
|
||||
"event_or_action arg must be 'event' or 'action'.")
|
||||
str_normalized = str_upper[
|
||||
str_upper.find(STR_STARTER) + len(STR_STARTER):]
|
||||
for tmp_event_name in dict_event_name:
|
||||
# tmp event is the event_name, keys of KW_EVENTS
|
||||
tmp_event_name_normalized = tmp_event_name.upper().replace("_", "")
|
||||
if str_normalized.startswith(tmp_event_name) or str_normalized.startswith(tmp_event_name_normalized):
|
||||
return tmp_event_name
|
||||
else:
|
||||
return str_upper
|
||||
|
||||
|
||||
def add_ev_name_GAME_PRE():
|
||||
for ev_name in LIST_EVENTS_GAME_PRE:
|
||||
register_event_name(ev_name)
|
||||
|
||||
|
||||
def add_ev_name_IB():
|
||||
for ev_name in DICT_EVENT_IB:
|
||||
register_event_name(ev_name, DICT_EVENT_IB[ev_name])
|
||||
|
||||
|
||||
def add_ev_name_GAME_POST():
|
||||
for ev_name in LIST_EVENTS_GAME_POST:
|
||||
register_event_name(ev_name)
|
||||
|
||||
|
||||
def add_ev_name_CUSTOM():
|
||||
for ev_name in LIST_EVENTS_CUSTOM:
|
||||
register_event_name(ev_name)
|
||||
|
||||
# event_generators
|
||||
|
||||
|
||||
def gen_event_GAME_PRE():
|
||||
return [Event(ev_name) for ev_name in LIST_EVENTS_GAME_PRE]
|
||||
|
||||
|
||||
def gen_event_IB():
|
||||
# move current list to old list
|
||||
list_event_IB = pygame.event.get()
|
||||
# Above list contains pygame_events, cant be modified
|
||||
# But need to replace type with ev_name
|
||||
new_list_ev = []
|
||||
for each_ev in list_event_IB:
|
||||
ev_name = get_event_name(each_ev.type)
|
||||
tmp_ev = Event(ev_name, each_ev.dict)
|
||||
new_list_ev.append(tmp_ev)
|
||||
|
||||
return new_list_ev
|
||||
|
||||
|
||||
def gen_event_GAME_POST():
|
||||
return [Event(ev_name) for ev_name in LIST_EVENTS_GAME_POST]
|
||||
|
||||
|
||||
def gen_event_KEY_PRESS():
|
||||
global list_state_key, list_state_key_old
|
||||
list_state_key_old = list_state_key
|
||||
list_state_key = pygame.key.get_pressed()
|
||||
list_key_press_event = []
|
||||
for tmp_key_id, bool_pressed in enumerate(list_state_key):
|
||||
if bool_pressed:
|
||||
tmp_key_name = get_key_name(tmp_key_id)
|
||||
list_key_press_event.append(
|
||||
Event("KEY_PRESS", {"key_name": tmp_key_name.lower(), "key_id": tmp_key_id}))
|
||||
return list_key_press_event
|
||||
|
||||
|
||||
def gen_event_MOUSE_PRESS():
|
||||
global list_state_mouse, list_state_mouse_old
|
||||
list_state_mouse_old = list_state_mouse
|
||||
list_state_mouse = pygame.mouse.get_pressed()
|
||||
list_mouse_press_event = []
|
||||
for tmp_mouse_btn_id, bool_pressed in enumerate(list_state_mouse):
|
||||
if bool_pressed:
|
||||
tmp_btn_name = get_mouse_btn_name(tmp_mouse_btn_id)
|
||||
list_mouse_press_event.append(
|
||||
Event("MOUSE_PRESS", {"btn_name": tmp_btn_name.lower(), "btn_id": tmp_mouse_btn_id}))
|
||||
return list_mouse_press_event
|
||||
|
||||
# pygame.mouse.get_pressed
|
||||
|
||||
# add ev_names
|
||||
# Ordered list of name adders
|
||||
LIST_ADDER_EV_NAME = [
|
||||
add_ev_name_IB, add_ev_name_GAME_PRE, add_ev_name_GAME_POST, add_ev_name_CUSTOM]
|
||||
for each_adder_func in LIST_ADDER_EV_NAME:
|
||||
each_adder_func()
|
||||
|
||||
|
||||
# add event generators
|
||||
# Ordered list of generators
|
||||
list_ordered_custom_generator = [gen_event_KEY_PRESS, gen_event_MOUSE_PRESS]
|
||||
|
||||
list_ordered_generators = [
|
||||
gen_event_GAME_PRE, gen_event_IB, list_ordered_custom_generator, gen_event_GAME_POST]
|
||||
|
||||
|
||||
def register_custom_event_generator(ev_func):
|
||||
''' ev_func will be run in each step before step event and after begin step event and should return a / a list of dicts
|
||||
each with ev_name (to be registered beforehand) and other props'''
|
||||
global list_ordered_custom_generator
|
||||
list_ordered_custom_generator.append(ev_func)
|
||||
|
||||
|
||||
def get_event_generators():
|
||||
return_list = []
|
||||
for gen_or_list in list_ordered_generators:
|
||||
if hasattr(gen_or_list, "__iter__"):
|
||||
return_list.extend(gen_or_list)
|
||||
else:
|
||||
return_list.append(gen_or_list)
|
||||
return return_list
|
||||
|
||||
|
||||
# Todo: Howto programatically register at the right position of generator list
|
||||
# Event collector
|
||||
|
||||
|
||||
def collect_events():
|
||||
# First, clear the old ev list
|
||||
global list_event, list_event_old
|
||||
list_event_old = list_event
|
||||
list_event = []
|
||||
for each_gen in get_event_generators():
|
||||
add_returned_events(each_gen())
|
||||
|
||||
# Event dispatcher
|
||||
# To be used by appr. classes
|
||||
|
||||
|
||||
def dispatch_events_class(cls):
|
||||
# cls.list_class must be available
|
||||
for each_class in cls.list_class:
|
||||
each_class.dispatch_events_instance(list_event)
|
||||
|
||||
|
||||
def dispatch_events_instance(cls, list_event):
|
||||
for each_instance in cls.list_instance:
|
||||
each_instance.dispatch_events_self(list_event)
|
||||
|
||||
|
||||
def dispatch_events_self(self, list_event):
|
||||
for each_ev in list_event:
|
||||
if each_ev.ev_name.upper() in self.dict_action_func:
|
||||
self.dispatch_events_local()
|
||||
for each_action in self.dict_action_func[each_ev.ev_name]:
|
||||
# similar as self.action_step(each_ev)
|
||||
each_action(self, each_ev)
|
||||
|
||||
|
||||
def dispatch_events_local(self):
|
||||
for each_ev in self.list_event_local:
|
||||
if each_ev.ev_name.upper() in self.dict_action_func:
|
||||
for each_action in self.dict_action_func[each_ev.ev_name]:
|
||||
# similar as self.action_step(each_ev)
|
||||
each_action(self, each_ev)
|
||||
self.clear_event_local()
|
||||
|
||||
|
||||
def push_event_local(self, ev_or_ev_list):
|
||||
if hasattr(ev_or_ev_list, "__iter__"):
|
||||
# list of events
|
||||
for each_ev in ev_or_ev_list:
|
||||
self._push_event_local_single(each_ev)
|
||||
else:
|
||||
# single event
|
||||
self._push_event_local_single(ev_or_ev_list)
|
||||
|
||||
|
||||
def clear_event_local(self):
|
||||
self.list_event_local = []
|
||||
|
||||
|
||||
def _push_event_local_single(self, ev):
|
||||
self.list_event_local.append(ev)
|
||||
|
||||
|
||||
class Event(object):
|
||||
|
||||
def __init__(self, ev_name, dict_=None):
|
||||
super(Event, self).__init__()
|
||||
self.ev_name = ev_name
|
||||
self.dict = dict_
|
||||
|
||||
|
||||
def _check_event(ev_name, new_or_old):
|
||||
''' ev_name_or_type => name_or_type(numb)_of_event
|
||||
new_or_old => current_event_list or old_event_list '''
|
||||
global list_event, list_event_old
|
||||
matched_events = []
|
||||
if new_or_old == "new":
|
||||
list_to_check = list_event
|
||||
elif new_or_old == "old":
|
||||
list_to_check = list_event_old
|
||||
else:
|
||||
raise AttributeError("new_or_old must be 'new' or 'old'.")
|
||||
|
||||
ev_name = fuzzy_match_event_name(ev_name, "event")
|
||||
|
||||
for ev in list_to_check:
|
||||
if ev.ev_name == ev_name:
|
||||
matched_events.append(ev)
|
||||
return matched_events
|
||||
|
||||
|
||||
def check_event(ev_name):
|
||||
return _check_event(ev_name, "new")
|
||||
|
||||
|
||||
def check_event_old(ev_name):
|
||||
return _check_event(ev_name, "old")
|
||||
|
||||
|
||||
def _get_key_press(key_name=None, new_or_old=None):
|
||||
''' Returns list of dict with key_name and key_id, if key_name matches.
|
||||
If key_name is None, all key preeses are allowed.'''
|
||||
global list_state_key, list_state_key_old
|
||||
if new_or_old == "new":
|
||||
list_to_check = list_state_key
|
||||
elif new_or_old == "old":
|
||||
list_to_check = list_state_key_old
|
||||
else:
|
||||
raise TypeError("new_or_old must be 'new' or 'old', CANT be None")
|
||||
list_key_press_event = []
|
||||
for tmp_key_id, bool_pressed in enumerate(list_to_check):
|
||||
if bool_pressed:
|
||||
tmp_key_name = get_key_name(tmp_key_id)
|
||||
if (key_name is None) or (tmp_key_name.lower() == key_name.lower()):
|
||||
# Todo: Cant match event_name directly, need a fuzzy key name
|
||||
# search func
|
||||
list_key_press_event.append(
|
||||
{"key_name": tmp_key_name.lower(), "key_id": tmp_key_id})
|
||||
return list_key_press_event
|
||||
|
||||
|
||||
def _get_mouse_press(btn_name=None, new_or_old=None):
|
||||
global list_state_mouse, list_state_mouse_old
|
||||
if new_or_old == "new":
|
||||
list_to_check = list_state_mouse
|
||||
elif new_or_old == "old":
|
||||
list_to_check = list_state_mouse_old
|
||||
else:
|
||||
raise TypeError("new_or_old must be 'new' or 'old', CANT be None")
|
||||
|
||||
list_mouse_press_event = []
|
||||
for tmp_mouse_btn_id, bool_pressed in enumerate(list_to_check):
|
||||
if bool_pressed:
|
||||
tmp_btn_name = get_mouse_btn_name(tmp_mouse_btn_id)
|
||||
if (btn_name is None) or (btn_name.lower() == tmp_btn_name.lower()):
|
||||
list_mouse_press_event.append(
|
||||
{"btn_name": tmp_btn_name.lower(), "btn_id": tmp_mouse_btn_id})
|
||||
return list_mouse_press_event
|
||||
|
||||
|
||||
def get_key_press(key_name=None):
|
||||
return _get_key_press(key_name, "new")
|
||||
|
||||
|
||||
def get_key_press_old(key_name=None):
|
||||
return _get_key_press(key_name, "old")
|
||||
|
||||
|
||||
def get_mouse_press(btn_name=None):
|
||||
return _get_mouse_press(btn_name, "new")
|
||||
|
||||
|
||||
def get_mouse_press_old(btn_name=None):
|
||||
return _get_mouse_press(btn_name, "old")
|
||||
@@ -0,0 +1,43 @@
|
||||
import inspect
|
||||
def tryit(func):
|
||||
print func
|
||||
try:
|
||||
print func.im_class
|
||||
except:
|
||||
print("Failed")
|
||||
try:
|
||||
print func.im_func
|
||||
except:
|
||||
print("Failed")
|
||||
try:
|
||||
print func.im_self
|
||||
except:
|
||||
print("Failed")
|
||||
try:
|
||||
func.asd=8
|
||||
except:
|
||||
print("Failed again")
|
||||
return func
|
||||
|
||||
class meta_fun_Class(type):
|
||||
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_class = type.__new__(cls, name, base, clsdict)
|
||||
temp_class.__class__=cls
|
||||
l=inspect.getmembers(temp_class,inspect.ismethod)
|
||||
for l1 in l:
|
||||
l1[1].asd=4
|
||||
return temp_class
|
||||
|
||||
class A(object):
|
||||
__metaclass__=meta_fun_Class
|
||||
def b(cls):
|
||||
pass
|
||||
@classmethod
|
||||
def c(cls):
|
||||
pass
|
||||
@staticmethod
|
||||
def d(cls):
|
||||
pass
|
||||
|
||||
|
||||
+19
-15
@@ -1,25 +1,29 @@
|
||||
import pyFun
|
||||
|
||||
|
||||
class pong(pyFun.fun_Game):
|
||||
|
||||
class bat(pyFun.fun_Class):
|
||||
def __init__(self,up_key,down_key,*args,**kwargs):
|
||||
super(bat,self).__init__(*args,**kwargs)
|
||||
self.up_key=up_key
|
||||
self.down_key=down_key
|
||||
self.img=pyFun.shapes.rect(w=24,h=96)
|
||||
|
||||
def __init__(self, up_key, down_key, *args, **kwargs):
|
||||
super(bat, self).__init__(*args, **kwargs)
|
||||
self.up_key = up_key
|
||||
self.down_key = down_key
|
||||
self.img = pyFun.shapes.rect(w=24, h=96)
|
||||
|
||||
def action_create(self):
|
||||
self.move_step=3
|
||||
self.move_step = 3
|
||||
|
||||
def action_key_press(self,key):
|
||||
if key==self.up_key:
|
||||
self.y-=self.move_step
|
||||
if key==self.down_key:
|
||||
self.y+=self.move_step
|
||||
def action_key_press(self, key):
|
||||
if key == self.up_key:
|
||||
self.y -= self.move_step
|
||||
if key == self.down_key:
|
||||
self.y += self.move_step
|
||||
|
||||
def action_touch_room_boundary(self):
|
||||
self.y=self.y_prev
|
||||
self.y = self.y_prev
|
||||
|
||||
game=pong(width=760,height=640,fps=60)
|
||||
game.bat(up_key=k_up,down_key=k_down,x=80,y=game.h/2)
|
||||
game.bat(up_key=k_w,down_key=k_s,x=game.w-80,y=game.h/2)
|
||||
game = pong(width=760, height=640, fps=60)
|
||||
game.bat(up_key=k_up, down_key=k_down, x=80, y=game.h / 2)
|
||||
game.bat(up_key=k_w, down_key=k_s, x=game.w - 80, y=game.h / 2)
|
||||
game.run()
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
import importlib
|
||||
import sys
|
||||
import os
|
||||
import inspect
|
||||
import room_sprite_panel
|
||||
import json
|
||||
|
||||
dict_shape_panel = room_sprite_panel.CanvasPanel.dict_sprite_panel
|
||||
|
||||
|
||||
def create_fake_cls(cls_name):
|
||||
class fake_cls(object):
|
||||
pass
|
||||
|
||||
# cls_name is unicode, so str() it
|
||||
fake_cls.__name__ = str(cls_name)
|
||||
return fake_cls
|
||||
|
||||
|
||||
class obj_ext(object):
|
||||
pass
|
||||
|
||||
|
||||
def append_filepath(filepath):
|
||||
if filepath:
|
||||
sys.path.append(filepath)
|
||||
|
||||
|
||||
def import_module(filename, filepath=None):
|
||||
append_filepath(filepath)
|
||||
module_ = importlib.import_module(filename)
|
||||
return module_
|
||||
|
||||
|
||||
def import_file(filename, filepath=None):
|
||||
if not (filepath is None):
|
||||
full_filename = os.path.join(filepath, filename)
|
||||
print full_filename
|
||||
else:
|
||||
full_filename = filename
|
||||
file_ = open(full_filename, "r")
|
||||
return file_
|
||||
|
||||
|
||||
def filter_class_with_panel(module_):
|
||||
list_class = inspect.getmembers(module_, inspect.isclass)
|
||||
list_filtered_cls = []
|
||||
for (cls_name, cls_obj) in list_class:
|
||||
if hasattr(cls_obj, "sprite_defaults"):
|
||||
tmp_sprite = cls_obj.sprite_defaults["type"]
|
||||
if tmp_sprite.map_class in dict_shape_panel.keys():
|
||||
cls_obj.sprite_defaults["panel"] = dict_shape_panel[
|
||||
tmp_sprite.map_class]
|
||||
list_filtered_cls.append(cls_obj)
|
||||
|
||||
return list_filtered_cls
|
||||
|
||||
|
||||
def load_module(filename_or_module, filepath=None):
|
||||
if isinstance(filename_or_module, str) or isinstance(filename_or_module, unicode):
|
||||
module_ = import_module(filename_or_module, filepath)
|
||||
elif inspect.ismodule(filename_or_module):
|
||||
if filepath is None:
|
||||
module_ = filename_or_module
|
||||
else:
|
||||
raise TypeError("filepath must be None if first param is module")
|
||||
|
||||
return filter_class_with_panel(module_)
|
||||
|
||||
|
||||
def load_json(filename_or_file, filepath=None):
|
||||
if isinstance(filename_or_file, str) or isinstance(filename_or_file, unicode):
|
||||
file_ = import_file(filename_or_file, filepath)
|
||||
elif isinstance(filename_or_file, file):
|
||||
file_ = filename_or_file
|
||||
|
||||
data_json = json.load(file_)
|
||||
if isinstance(file_, file):
|
||||
file_.close()
|
||||
|
||||
list_class_data = data_json["class_data"]
|
||||
list_inst_data = data_json["instance_data"]
|
||||
list_loaded_cls = []
|
||||
|
||||
for each_cls in list_class_data:
|
||||
tmp_cls = create_fake_cls(each_cls["game_class"])
|
||||
|
||||
tmp_type = obj_ext()
|
||||
tmp_type.map_class = each_cls["game_shape_class"]
|
||||
tmp_cls.sprite_defaults = {
|
||||
# "panel": each_cls["pygame_class"],
|
||||
"params": each_cls["params"],
|
||||
"type": tmp_type
|
||||
}
|
||||
|
||||
# add panel to sprite_defaults
|
||||
if each_cls["game_shape_class"] in dict_shape_panel.keys():
|
||||
tmp_cls.sprite_defaults["panel"] = dict_shape_panel[
|
||||
each_cls["game_shape_class"]]
|
||||
|
||||
list_loaded_cls.append(tmp_cls)
|
||||
|
||||
return (list_loaded_cls, list_inst_data)
|
||||
Binary file not shown.
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"instance_data": [
|
||||
{
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
121,
|
||||
183
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
175,
|
||||
76
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
62,
|
||||
182
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
54,
|
||||
137
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
120,
|
||||
144
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
104,
|
||||
88
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
72,
|
||||
224
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
177,
|
||||
169
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}
|
||||
],
|
||||
"class_data": [
|
||||
{
|
||||
"game_class": "wall",
|
||||
"params": {
|
||||
"color": null,
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
},
|
||||
{
|
||||
"game_class": "ball",
|
||||
"params": {
|
||||
"color": null,
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}
|
||||
]
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"instance_data": [{
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
121,
|
||||
183
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
175,
|
||||
76
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
62,
|
||||
182
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
61,
|
||||
144
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "wall",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
120,
|
||||
144
|
||||
],
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
104,
|
||||
88
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
72,
|
||||
224
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "ball",
|
||||
"config": {
|
||||
"color": null,
|
||||
"center": [
|
||||
177,
|
||||
169
|
||||
],
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}],
|
||||
"class_data": [{
|
||||
"game_class": "wall",
|
||||
"params": {
|
||||
"color": null,
|
||||
"size": [
|
||||
60,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}, {
|
||||
"game_class": "ball",
|
||||
"params": {
|
||||
"color": null,
|
||||
"size": [
|
||||
80,
|
||||
40
|
||||
]
|
||||
},
|
||||
"game_shape_class": "Rect"
|
||||
}]
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
|
||||
# Maybe make a non-square rooted function for comparison (faster)
|
||||
from uniquelist import uniquelist
|
||||
import math
|
||||
|
||||
|
||||
def atan2_inv(y_diff, x_diff):
|
||||
'''Returns atan2 in inverted y-axis in degrees'''
|
||||
return math.degrees(math.atan2(-y_diff, x_diff))
|
||||
# following constants are required for the next function
|
||||
|
||||
|
||||
def distance(point_1, point_2):
|
||||
''' distance between point_1 and point_2, where both are 2 member iterable'''
|
||||
if (not len(point_1) == 2) or (not len(point_2) == 2):
|
||||
raise TypeError("point_1 and point_2 both must be 2 member iterable")
|
||||
diff_x = point_2[0] - point_1[0]
|
||||
diff_y = point_2[1] - point_1[1]
|
||||
return math.hypot(diff_x, diff_y)
|
||||
|
||||
|
||||
def vel_add(vel_1, vel_2):
|
||||
''' vel_1 and vel_2 both must be in (magnitude,direction_in_degree) format.
|
||||
Returns in same format.'''
|
||||
if (not len(vel_1) == 2) or (not len(vel_2) == 2):
|
||||
raise TypeError("vel_1 and vel_2 both must be 2 member iterable")
|
||||
|
||||
vel_1_x = vel_1[0] * math.cos(math.radians(vel_1[1]))
|
||||
vel_1_y = -vel_1[0] * math.sin(math.radians(vel_1[1]))
|
||||
|
||||
vel_2_x = vel_2[0] * math.cos(math.radians(vel_2[1]))
|
||||
vel_2_y = -vel_2[0] * math.sin(math.radians(vel_2[1]))
|
||||
|
||||
vel_tot_x = vel_1_x + vel_2_x
|
||||
vel_tot_y = vel_1_y + vel_2_y
|
||||
|
||||
vel_tot = (
|
||||
math.hypot(vel_tot_x, vel_tot_y), atan2_inv(vel_tot_y, vel_tot_x))
|
||||
|
||||
return vel_tot
|
||||
|
||||
|
||||
def direction(point_1, point_2):
|
||||
if (not len(point_1) == 2) or (not len(point_2) == 2):
|
||||
raise TypeError("point_1 and point_2 both must be 2 member iterable")
|
||||
diff_x = point_2[0] - point_1[0]
|
||||
diff_y = point_2[1] - point_1[1]
|
||||
return atan2_inv(diff_y, diff_x)
|
||||
|
||||
UNION = 1
|
||||
INTERSECTION = 2
|
||||
DIFFERENCE = 3
|
||||
ADD = 4
|
||||
# for each member (usually objects) in the list, it is replaced by one of
|
||||
# its variables
|
||||
MAKE_IT_VARIABLE_LIST = 5
|
||||
|
||||
|
||||
def operation_on_lists(operation, list1, list2=None, variable_name=None):
|
||||
''' operation_on_lists(operation, list1, list2) -> list
|
||||
Does operation involving list1 and list2.
|
||||
variable_name is required only for MAKE_IT_VARIABLE_LIST operation. It is a string representing the variable name
|
||||
Valid operations are UNION, INTERSECTION, DIFFERENCE, ADD, MAKE_IT_VARIABLE_list '''
|
||||
def intersection():
|
||||
if list2 is None:
|
||||
raise TypeError("second argument i.e. list2 should be a list")
|
||||
list_return = []
|
||||
for temp1 in list1:
|
||||
for temp2 in list2:
|
||||
if temp1 == temp2:
|
||||
list_return.append(temp1)
|
||||
return list_return
|
||||
|
||||
def union():
|
||||
if list2 is None:
|
||||
raise TypeError("second argument i.e. list2 should be a list")
|
||||
list_return = uniquelist()
|
||||
list_return.extend(list1)
|
||||
list_return.extend(list2)
|
||||
return list_return
|
||||
|
||||
def add():
|
||||
if list2 is None:
|
||||
raise TypeError("second argument i.e. list2 should be a list")
|
||||
list_return = []
|
||||
list_return.append(list1)
|
||||
list_return.append(list2)
|
||||
return list_return
|
||||
|
||||
def difference():
|
||||
if list2 is None:
|
||||
raise TypeError("second argument i.e. list2 should be a list")
|
||||
list_return = []
|
||||
list_intersection = intersection()
|
||||
for temp1 in list1:
|
||||
if temp1 not in list_intersection:
|
||||
list_return.append(temp1)
|
||||
return list_return
|
||||
|
||||
# for each member (usually objects) in the list, it is replaced by one of
|
||||
# its variables
|
||||
def make_it_variable_list():
|
||||
if variable_name is None:
|
||||
raise TypeError("variable_name should be a string")
|
||||
if not list2 is None:
|
||||
raise TypeError("list2 should be None")
|
||||
return_list = [getattr(temp, variable_name) for temp in list1]
|
||||
|
||||
if operation == UNION:
|
||||
return union()
|
||||
elif operation == INTERSECTION:
|
||||
return intersection()
|
||||
elif operation == DIFFERENCE:
|
||||
return difference()
|
||||
elif operation == ADD:
|
||||
return add()
|
||||
elif operation == MAKE_IT_VARIABLE_LIST:
|
||||
return make_it_variable_list()
|
||||
else:
|
||||
raise ValueError(
|
||||
"Invalid operation name. Valid operations are UNION, INTERSECTION, DIFFERENCE.")
|
||||
# end of operation_on_lists()
|
||||
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"follow_symlinks": true,
|
||||
"path": "."
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+219
@@ -0,0 +1,219 @@
|
||||
#!/bin/env python
|
||||
import wx
|
||||
import json
|
||||
import load_map
|
||||
import os
|
||||
import room_sprite_panel as sprite_panel
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
class MyFrame(wx.Frame):
|
||||
|
||||
def __init__(self):
|
||||
self.size = (500, 300)
|
||||
wx.Frame.__init__(self, None, -1, "My Frame", size=self.size)
|
||||
|
||||
self.create_panel_ctrl_canvas()
|
||||
|
||||
self.create_box_sizer()
|
||||
|
||||
self.bind_events_default()
|
||||
|
||||
self.load_saved_json()
|
||||
# todo: make load_module_py func
|
||||
|
||||
def load_saved_json(self):
|
||||
# Load map
|
||||
wildcard_py = "Python source (*.py)|*.py|" \
|
||||
"Compiled Python (*.pyc)|*.pyc|" \
|
||||
"All files (*.*)|*.*"
|
||||
wildcard_json = "Json file (*.json)|*.json"
|
||||
dialog_file = wx.FileDialog(None, "Choose game.py file", os.getcwd(),
|
||||
"", wildcard_json, wx.OPEN)
|
||||
if dialog_file.ShowModal() == wx.ID_OK:
|
||||
tmp_path = dialog_file.GetPath()
|
||||
filename = os.path.basename(tmp_path)
|
||||
# filename_without_ext = filename[:filename.rfind(".")]
|
||||
filepath = os.path.dirname(tmp_path)
|
||||
list_loaded_cls, data_loaded_inst = load_map.load_json(
|
||||
filename, filepath)
|
||||
self.dict_loaded_cls = {}
|
||||
for each_cls in list_loaded_cls:
|
||||
self.dict_loaded_cls[each_cls.__name__] = each_cls
|
||||
## del list_loaded_cls
|
||||
else:
|
||||
raise TypeError("Enter a filename to proceed")
|
||||
|
||||
self.sync_panel_ctrl(self.dict_loaded_cls.keys())
|
||||
self.generate_loaded_inst(data_loaded_inst)
|
||||
dialog_file.Destroy()
|
||||
|
||||
def create_panel_ctrl_canvas(self):
|
||||
# create the list control
|
||||
self.panel_ctrl = wx.Panel(
|
||||
self, -1, size=(-2, -1))
|
||||
self.panel_ctrl.SetBackgroundColour("aquamarine")
|
||||
self.panel_ctrl.SetMaxSize((250, -1))
|
||||
|
||||
self.panel_ctrl.list_ctrl = wx.ListCtrl(
|
||||
self.panel_ctrl, -1, style=wx.LC_LIST, size=(200, 180))
|
||||
self.list_shape = []
|
||||
|
||||
self.panel_canvas = wx.Panel(
|
||||
self, -1, size=(-3, -1))
|
||||
self.panel_canvas.SetBackgroundColour("light blue")
|
||||
|
||||
def create_box_sizer(self):
|
||||
bxszr = wx.BoxSizer(wx.HORIZONTAL)
|
||||
bxszr.Add(self.panel_ctrl, 2, flag=wx.EXPAND)
|
||||
bxszr.Add(self.panel_canvas, 3, flag=wx.EXPAND)
|
||||
self.SetSizer(bxszr)
|
||||
# self.Fit()
|
||||
|
||||
def generate_loaded_inst(self, list_):
|
||||
print(len(list_))
|
||||
for each_inst in list_:
|
||||
self.create_shape_panel_from_str(
|
||||
each_inst["game_class"], each_inst["config"])
|
||||
|
||||
def sync_panel_ctrl(self, list_str):
|
||||
for index, str_ in enumerate(list_str):
|
||||
if index > self.panel_ctrl.list_ctrl.GetItemCount() - 1:
|
||||
method_ = self.panel_ctrl.list_ctrl.InsertStringItem
|
||||
else:
|
||||
method_ = self.panel_ctrl.list_ctrl.SetItemText
|
||||
# try:
|
||||
method_(index, str_)
|
||||
# self.panel_ctrl.list_ctrl.Refresh()
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def create_shape_panel_from_str(self, str_, params=None):
|
||||
tmp_game_cls = self.dict_loaded_cls[str_]
|
||||
return self.create_shape_panel(tmp_game_cls, params)
|
||||
|
||||
def create_shape_panel(self, game_cls, params=None):
|
||||
tmp_dict = deepcopy(game_cls.sprite_defaults)
|
||||
tmp_panel = tmp_dict["panel"]
|
||||
if params is None:
|
||||
params = {}
|
||||
tmp_params = tmp_dict["params"]
|
||||
tmp_params.update(params)
|
||||
center = tmp_params.pop("center")
|
||||
|
||||
tmp_shape_panel = tmp_panel(
|
||||
self.panel_canvas, center=center, **tmp_params)
|
||||
tmp_shape_panel.user_data = {"class": game_cls.__name__}
|
||||
tmp_shape_panel.Show()
|
||||
self.panel_canvas.Refresh()
|
||||
self.list_shape.append(tmp_shape_panel)
|
||||
return tmp_shape_panel
|
||||
|
||||
def action_key_press(self, ev):
|
||||
print self.__class__
|
||||
keyCode = ev.GetKeyCode()
|
||||
try:
|
||||
keyText = chr(keyCode).upper()
|
||||
except:
|
||||
keyText = None
|
||||
print keyText
|
||||
|
||||
if keyText == "E":
|
||||
print self.export_data("map.json")
|
||||
|
||||
def bind_events_default(self):
|
||||
print "binding"
|
||||
self.panel_ctrl.list_ctrl.Bind(wx.EVT_KEY_DOWN, self.action_key_press)
|
||||
self.panel_canvas.Bind(wx.EVT_LEFT_DOWN, self.action_mouse_left_down)
|
||||
|
||||
def action_mouse_left_down(self, ev):
|
||||
focus_id = self.panel_ctrl.list_ctrl.FocusedItem
|
||||
if (focus_id == -1):
|
||||
focus_id = 0
|
||||
print "Setting focus"
|
||||
self.panel_ctrl.list_ctrl.Focus(focus_id)
|
||||
focus_id = self.panel_ctrl.list_ctrl.FocusedItem
|
||||
|
||||
focus_text = self.panel_ctrl.list_ctrl.GetItem(
|
||||
focus_id).GetText()
|
||||
pos = ev.GetPosition()
|
||||
tmp_panel = self.create_shape_panel_from_str(
|
||||
focus_text, {"center": pos})
|
||||
tmp_panel.SetFocus()
|
||||
|
||||
@staticmethod
|
||||
def for_all_panel_class(func_):
|
||||
return_list = []
|
||||
for tmp_panel_cls in sprite_panel.CanvasPanel.dict_sprite_panel.values():
|
||||
val_return = func_(tmp_panel_cls)
|
||||
return_list.append(val_return)
|
||||
|
||||
return return_list
|
||||
|
||||
@staticmethod
|
||||
def for_all_panel_inst(func_, flatten=False):
|
||||
# todo: use for_all_panel_class
|
||||
list_return = []
|
||||
for tmp_panel_cls in sprite_panel.CanvasPanel.dict_sprite_panel.values():
|
||||
tmp_list = []
|
||||
for tmp_panel_inst in tmp_panel_cls.list_panel_inst:
|
||||
val_return = func_(tmp_panel_inst)
|
||||
tmp_list.append(val_return)
|
||||
if flatten:
|
||||
list_return.extend(tmp_list)
|
||||
else:
|
||||
list_return.append(tmp_list)
|
||||
|
||||
return list_return
|
||||
|
||||
@staticmethod
|
||||
def export_game_cls(game_cls):
|
||||
dict_return = {}
|
||||
dict_return["game_class"] = game_cls.__name__
|
||||
|
||||
tmp_sprite_defaults = deepcopy(game_cls.sprite_defaults)
|
||||
dict_return["game_shape_class"] = tmp_sprite_defaults["type"].map_class
|
||||
dict_return["params"] = tmp_sprite_defaults["params"]
|
||||
|
||||
return dict_return
|
||||
|
||||
def for_all_game_cls(self, func_):
|
||||
list_return = []
|
||||
for tmp_game_cls in self.get_all_loaded_cls():
|
||||
val_return = func_(tmp_game_cls)
|
||||
list_return.append(val_return)
|
||||
return list_return
|
||||
|
||||
def get_all_loaded_cls(self):
|
||||
return self.dict_loaded_cls.values()
|
||||
|
||||
def export_data(self, file_=None, pprint_=True):
|
||||
|
||||
class_data = self.for_all_game_cls(
|
||||
lambda game_cls: self.export_game_cls(game_cls))
|
||||
instance_data = self.for_all_panel_inst(
|
||||
lambda panel_inst: panel_inst.get_props(), flatten=True)
|
||||
|
||||
data = {"class_data": class_data, "instance_data": instance_data}
|
||||
if pprint_:
|
||||
jsoned_data = json.dumps(data, indent=4)
|
||||
print jsoned_data
|
||||
else:
|
||||
jsoned_data = json.dumps(data)
|
||||
|
||||
if file_ is None:
|
||||
return jsoned_data
|
||||
elif isinstance(file_, str):
|
||||
file_ = open(file_, "w")
|
||||
|
||||
if isinstance(file_, file):
|
||||
file_.write(jsoned_data)
|
||||
file_.close()
|
||||
else:
|
||||
raise TypeError("file_ parameter must be of file or str type.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = wx.PySimpleApp()
|
||||
frame = MyFrame()
|
||||
frame.Show(True)
|
||||
app.MainLoop()
|
||||
@@ -0,0 +1,189 @@
|
||||
#!/bin/env python
|
||||
import wx
|
||||
import json
|
||||
import load_map
|
||||
import os
|
||||
import room_sprite_panel as sprite_panel
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
class MyFrame(wx.Frame):
|
||||
|
||||
def __init__(self):
|
||||
self.size = (500, 300)
|
||||
wx.Frame.__init__(self, None, -1, "My Frame", size=self.size)
|
||||
|
||||
self.panel_ctrl = wx.Panel(
|
||||
self, -1, size=(-2, -1))
|
||||
self.panel_ctrl.SetBackgroundColour("aquamarine")
|
||||
self.panel_ctrl.SetMaxSize((250, -1))
|
||||
|
||||
# load some images into an image list
|
||||
il = wx.ImageList(16, 16, True)
|
||||
il.Add(wx.EmptyBitmap(16, 16))
|
||||
|
||||
# create the list control
|
||||
self.panel_ctrl.list_ctrl = wx.ListCtrl(
|
||||
self.panel_ctrl, -1, style=wx.LC_LIST, size=(200, 180))
|
||||
# self.list_shape = []
|
||||
# Load map
|
||||
wildcard_py = "Python source (*.py)|*.py|" \
|
||||
"Compiled Python (*.pyc)|*.pyc|" \
|
||||
"All files (*.*)|*.*"
|
||||
dialog_file = wx.FileDialog(None, "Choose game.py file", os.getcwd(),
|
||||
"", wildcard_py, wx.OPEN)
|
||||
if dialog_file.ShowModal() == wx.ID_OK:
|
||||
self.module_path = dialog_file.GetPath()
|
||||
filename = os.path.basename(self.module_path)
|
||||
filename_without_ext = filename[:filename.rfind(".")]
|
||||
filepath = os.path.dirname(self.module_path)
|
||||
list_loaded_cls = load_map.load_module(
|
||||
filename_without_ext, filepath)
|
||||
self.dict_loaded_cls = {}
|
||||
for each_cls in list_loaded_cls:
|
||||
self.dict_loaded_cls[each_cls.__name__] = each_cls
|
||||
del list_loaded_cls
|
||||
else:
|
||||
raise TypeError("Enter a filename to proceed")
|
||||
|
||||
self.sync_panel_ctrl(self.dict_loaded_cls.keys())
|
||||
|
||||
dialog_file.Destroy()
|
||||
# assign the image list to it
|
||||
# self.panel_ctrl.list_ctrl.AssignImageList(il, wx.IMAGE_LIST_SMALL)
|
||||
self.panel_canvas = wx.Panel(
|
||||
self, -1, size=(-3, -1))
|
||||
self.panel_canvas.SetBackgroundColour("light blue")
|
||||
|
||||
bxszr = wx.BoxSizer(wx.HORIZONTAL)
|
||||
bxszr.Add(self.panel_ctrl, 2, flag=wx.EXPAND)
|
||||
bxszr.Add(self.panel_canvas, 3, flag=wx.EXPAND)
|
||||
self.SetSizer(bxszr)
|
||||
# self.Fit()
|
||||
|
||||
self.bind_events_default()
|
||||
|
||||
def sync_panel_ctrl(self, list_str):
|
||||
for index, str_ in enumerate(list_str):
|
||||
if index > self.panel_ctrl.list_ctrl.GetItemCount() - 1:
|
||||
method_ = self.panel_ctrl.list_ctrl.InsertStringItem
|
||||
else:
|
||||
method_ = self.panel_ctrl.list_ctrl.SetItemText
|
||||
# try:
|
||||
method_(index, str_)
|
||||
# self.panel_ctrl.list_ctrl.Refresh()
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def create_shape_panel(self, str_, default_center):
|
||||
tmp_game_cls = self.dict_loaded_cls[str_]
|
||||
tmp_dict = tmp_game_cls.sprite_defaults
|
||||
|
||||
if "center" in tmp_dict:
|
||||
center = tmp_dict["center"]
|
||||
else:
|
||||
center = default_center
|
||||
|
||||
tmp_shape_panel = tmp_dict["panel"](
|
||||
self.panel_canvas, center=center, **tmp_dict["params"])
|
||||
tmp_shape_panel.user_data = {"class": tmp_game_cls.__name__}
|
||||
tmp_shape_panel.Show()
|
||||
self.panel_canvas.Refresh()
|
||||
# self.list_shape.append(tmp_shape_panel)
|
||||
|
||||
def action_key_press(self, ev):
|
||||
print self.__class__
|
||||
keyCode = ev.GetKeyCode()
|
||||
try:
|
||||
keyText = chr(keyCode).upper()
|
||||
except:
|
||||
keyText = None
|
||||
print keyText
|
||||
|
||||
if keyText == "\r":
|
||||
focus_id = self.panel_ctrl.list_ctrl.FocusedItem
|
||||
focus_text = self.panel_ctrl.list_ctrl.GetItem(focus_id).GetText()
|
||||
self.create_shape_panel(focus_text, (0, 0))
|
||||
if keyText == "E":
|
||||
print self.export_data("map.json")
|
||||
|
||||
def bind_events_default(self):
|
||||
print "binding"
|
||||
self.panel_ctrl.list_ctrl.Bind(wx.EVT_KEY_DOWN, self.action_key_press)
|
||||
|
||||
@staticmethod
|
||||
def for_all_panel_class(func_):
|
||||
return_list = []
|
||||
for tmp_panel_cls in sprite_panel.CanvasPanel.dict_sprite_panel.values():
|
||||
val_return = func_(tmp_panel_cls)
|
||||
return_list.append(val_return)
|
||||
|
||||
return return_list
|
||||
|
||||
@staticmethod
|
||||
def for_all_panel_inst(func_, flatten=False):
|
||||
# todo: use for_all_panel_class
|
||||
list_return = []
|
||||
for tmp_panel_cls in sprite_panel.CanvasPanel.dict_sprite_panel.values():
|
||||
tmp_list = []
|
||||
for tmp_panel_inst in tmp_panel_cls.list_panel_inst:
|
||||
val_return = func_(tmp_panel_inst)
|
||||
tmp_list.append(val_return)
|
||||
if flatten:
|
||||
list_return.extend(tmp_list)
|
||||
else:
|
||||
list_return.append(tmp_list)
|
||||
|
||||
return list_return
|
||||
|
||||
@staticmethod
|
||||
def export_game_cls(game_cls):
|
||||
dict_return = {}
|
||||
dict_return["game_class"] = game_cls.__name__
|
||||
|
||||
tmp_sprite_defaults = deepcopy(game_cls.sprite_defaults)
|
||||
dict_return["game_shape_class"] = tmp_sprite_defaults["type"].map_class
|
||||
dict_return["params"] = tmp_sprite_defaults["params"]
|
||||
|
||||
return dict_return
|
||||
|
||||
def for_all_game_cls(self, func_):
|
||||
list_return = []
|
||||
for tmp_game_cls in self.get_all_loaded_cls():
|
||||
val_return = func_(tmp_game_cls)
|
||||
list_return.append(val_return)
|
||||
return list_return
|
||||
|
||||
def get_all_loaded_cls(self):
|
||||
return self.dict_loaded_cls.values()
|
||||
|
||||
def export_data(self, file_=None, pprint_=True):
|
||||
|
||||
class_data = self.for_all_game_cls(
|
||||
lambda game_cls: self.export_game_cls(game_cls))
|
||||
instance_data = self.for_all_panel_inst(
|
||||
lambda panel_inst: panel_inst.get_props(), flatten=True)
|
||||
|
||||
data = {"class_data": class_data, "instance_data": instance_data}
|
||||
if pprint_:
|
||||
jsoned_data = json.dumps(data, indent=4)
|
||||
print jsoned_data
|
||||
else:
|
||||
jsoned_data = json.dumps(data)
|
||||
|
||||
if file_ is None:
|
||||
return jsoned_data
|
||||
elif isinstance(file_, str):
|
||||
file_ = open(file_, "w")
|
||||
|
||||
if isinstance(file_, file):
|
||||
file_.write(jsoned_data)
|
||||
file_.close()
|
||||
else:
|
||||
raise TypeError("file_ parameter must be of file or str type.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = wx.PySimpleApp()
|
||||
frame = MyFrame()
|
||||
frame.Show(True)
|
||||
app.MainLoop()
|
||||
@@ -0,0 +1,291 @@
|
||||
import wx
|
||||
|
||||
|
||||
def register_sprite_panel(sprite_panel):
|
||||
CanvasPanel.dict_sprite_panel[sprite_panel.game_shape_class] = sprite_panel
|
||||
return sprite_panel
|
||||
|
||||
|
||||
class CanvasPanel(wx.Panel):
|
||||
|
||||
"""Parent canvas panel"""
|
||||
|
||||
dict_sprite_panel = {}
|
||||
|
||||
def __init__(self, *arg, **kwargs):
|
||||
super(CanvasPanel, self).__init__(*arg, **kwargs)
|
||||
self.create_internal()
|
||||
self.init_start_var()
|
||||
self.perc = 5.0 / 100
|
||||
self.update = False
|
||||
self.delta = None
|
||||
|
||||
self.bind_events_default()
|
||||
|
||||
def init_start_var(self):
|
||||
if not hasattr(self, "_start_w"):
|
||||
self._start_w = self.w
|
||||
if not hasattr(self, "_start_h"):
|
||||
self._start_h = self.h
|
||||
if not hasattr(self, "_start_left"):
|
||||
self._start_left = self.left
|
||||
if not hasattr(self, "_start_top"):
|
||||
self._start_top = self.top
|
||||
|
||||
def create_internal(self):
|
||||
self.w, self.h = self.GetSizeTuple()
|
||||
self.left, self.top = self.GetPositionTuple()
|
||||
size = self.GetClientSize()
|
||||
self.buffer = wx.EmptyBitmap(max(1, size.width), max(1, size.height))
|
||||
|
||||
def bind_events_default(self):
|
||||
self.Bind(wx.EVT_KEY_DOWN, self.action_move)
|
||||
self.Bind(wx.EVT_CHAR_HOOK, self.action_inflate)
|
||||
self.Bind(wx.EVT_IDLE, self.action_idle)
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.action_mouse_left_down)
|
||||
self.Bind(wx.EVT_LEFT_UP, self.action_mouse_left_up)
|
||||
self.Bind(wx.EVT_SET_FOCUS, self.action_unfocused)
|
||||
self.Bind(wx.EVT_KILL_FOCUS, self.action_unfocused)
|
||||
self.Bind(wx.EVT_MOTION, self.action_dragged)
|
||||
|
||||
def action_mouse_left_up(self, ev):
|
||||
if self.HasCapture():
|
||||
self.ReleaseMouse()
|
||||
self.delta = None
|
||||
|
||||
def action_dragged(self, ev):
|
||||
if ev.Dragging() and ev.LeftIsDown() and self.delta:
|
||||
pos_wrt_self = ev.GetPosition()
|
||||
pos_wrt_screen = self.ClientToScreen(pos_wrt_self)
|
||||
pos_wrt_parent = self.GetParent().ScreenToClient(pos_wrt_screen)
|
||||
pos = pos_wrt_parent
|
||||
|
||||
newPos = (pos.x - self.delta.x, pos.y - self.delta.y)
|
||||
self.Move(newPos)
|
||||
self.left, self.top = self.GetPositionTuple()
|
||||
self.update = True
|
||||
|
||||
def action_move(self, ev):
|
||||
keyText = chr(ev.GetUnicodeKey()).upper()
|
||||
# print "keyText= " + str(keyText)
|
||||
if keyText == "W":
|
||||
self.top -= 5
|
||||
print "moving up"
|
||||
if keyText == "A":
|
||||
self.left -= 5
|
||||
print "moving left"
|
||||
if keyText == "S":
|
||||
self.top += 5
|
||||
print "moving down"
|
||||
if keyText == "D":
|
||||
self.left += 5
|
||||
print "moving right"
|
||||
|
||||
self.update = True
|
||||
ev.Skip()
|
||||
return True
|
||||
|
||||
def action_inflate(self, ev):
|
||||
keyText = ev.GetKeyCode() # .upper()
|
||||
|
||||
# print "char= " + str(keyText)
|
||||
tmp_perc = None
|
||||
if keyText == wx.WXK_ADD or keyText == wx.WXK_NUMPAD_ADD:
|
||||
tmp_perc = self.perc
|
||||
print "Inflating"
|
||||
if keyText == wx.WXK_SUBTRACT or keyText == wx.WXK_NUMPAD_SUBTRACT:
|
||||
tmp_perc = -self.perc
|
||||
print "Deflating"
|
||||
|
||||
if not (tmp_perc is None):
|
||||
new_w = self.w * (1 + tmp_perc)
|
||||
new_h = self.h * (1 + tmp_perc)
|
||||
new_left = self.left - (new_w - self.w) / 2
|
||||
new_top = self.top - (new_h - self.h) / 2
|
||||
print "old_w, old_h" + str((self.w, self.h))
|
||||
print "new_w, new_h" + str((new_w, new_h))
|
||||
print "old_left, old_top" + str((self.left, self.top))
|
||||
print "new_left, new_top" + str((new_left, new_top))
|
||||
print ""
|
||||
self.left, self.top = new_left, new_top
|
||||
self.w, self.h = new_w, new_h
|
||||
|
||||
self.update = True
|
||||
ev.Skip()
|
||||
return True
|
||||
|
||||
@property
|
||||
def center(self):
|
||||
return (self.left + self.w / 2), (self.top + self.h / 2)
|
||||
|
||||
def action_idle(self, ev):
|
||||
if self.update:
|
||||
self.SetPosition((self.left, self.top))
|
||||
self.SetSizeWH(self.w, self.h)
|
||||
size = self.GetClientSize()
|
||||
self.buffer = wx.EmptyBitmap(
|
||||
max(1, size.width), max(1, size.height))
|
||||
self.GetParent().Refresh()
|
||||
self.update = False
|
||||
|
||||
def action_mouse_left_down(self, ev):
|
||||
self.SetFocus()
|
||||
self.CaptureMouse()
|
||||
pos_wrt_self = ev.GetPosition()
|
||||
pos_wrt_screen = self.ClientToScreen(pos_wrt_self)
|
||||
pos_wrt_parent = self.GetParent().ScreenToClient(pos_wrt_screen)
|
||||
pos = pos_wrt_parent
|
||||
origin = self.GetPosition()
|
||||
self.delta = wx.Point(pos.x - origin.x, pos.y - origin.y)
|
||||
|
||||
def action_focused(self, ev):
|
||||
self.Refresh()
|
||||
|
||||
def action_unfocused(self, ev):
|
||||
self.Refresh()
|
||||
|
||||
|
||||
@register_sprite_panel
|
||||
class RectPanel(CanvasPanel):
|
||||
|
||||
"""docstring for RectPanel"""
|
||||
|
||||
game_shape_class = "Rect"
|
||||
list_panel_inst = []
|
||||
|
||||
def __init__(self, *arg, **kwargs):
|
||||
tmp_center = kwargs["center"]
|
||||
tmp_size = kwargs["size"]
|
||||
kwargs.pop("center")
|
||||
kwargs.pop("color")
|
||||
kwargs["pos"] = (
|
||||
(tmp_center[0] - tmp_size[0] / 2), (tmp_center[1] - tmp_size[1] / 2))
|
||||
super(RectPanel, self).__init__(*arg, **kwargs)
|
||||
self.brush = wx.Brush("Green")
|
||||
self.list_panel_inst.append(self)
|
||||
|
||||
def get_props(self):
|
||||
return {
|
||||
"game_class": self.user_data["class"],
|
||||
"game_shape_class": self.game_shape_class,
|
||||
"config": {
|
||||
"center": self.center,
|
||||
"size": (self.w, self.h),
|
||||
"color": None,
|
||||
}
|
||||
}
|
||||
|
||||
def bind_events_default(self):
|
||||
super(RectPanel, self).bind_events_default()
|
||||
self.Bind(wx.EVT_PAINT, self.action_paint_rect)
|
||||
self.Bind(wx.EVT_ERASE_BACKGROUND, self.action_clear_none)
|
||||
|
||||
@property
|
||||
def pen_focused(self):
|
||||
if not hasattr(self, "_pen_focused"):
|
||||
self._pen_focused = wx.Pen(
|
||||
"Blue", width=3, style=wx.PENSTYLE_LONG_DASH)
|
||||
self._pen_focused.SetCap(wx.CAP_BUTT)
|
||||
self._pen_focused.SetJoin(wx.JOIN_ROUND)
|
||||
return self._pen_focused
|
||||
|
||||
@pen_focused.setter
|
||||
def pen_focused(self, val):
|
||||
self._pen_focused = val
|
||||
|
||||
def action_paint_rect(self, ev):
|
||||
dc = wx.BufferedPaintDC(self, self.buffer)
|
||||
dc.SetBackground(wx.Brush(wx.Colour(150, 150, 150, 100)))
|
||||
dc.Clear()
|
||||
if self.HasFocus():
|
||||
self.pen = self.pen_focused
|
||||
else:
|
||||
self.pen = wx.NullPen
|
||||
|
||||
dc.SetBrush(self.brush)
|
||||
dc.SetPen(self.pen)
|
||||
|
||||
dc.DrawRectangle(0, 0, self.w, self.h)
|
||||
# self.SetBackgroundColour("green")
|
||||
|
||||
def action_clear_none(self, ev):
|
||||
wx.BufferedDC(None, self.buffer)
|
||||
|
||||
|
||||
@register_sprite_panel
|
||||
class CirclePanel(CanvasPanel):
|
||||
|
||||
"""docstring for CirclePanel"""
|
||||
|
||||
game_shape_class = "Circle"
|
||||
list_panel_inst = []
|
||||
|
||||
def __init__(self, *arg, **kwargs):
|
||||
tmp_center = kwargs["center"]
|
||||
tmp_radius = kwargs["radius"]
|
||||
kwargs.pop("color")
|
||||
kwargs["pos"] = (
|
||||
(tmp_center[0] - tmp_radius), (tmp_center[1] - tmp_radius))
|
||||
kwargs.pop("center")
|
||||
kwargs["size"] = (tmp_radius * 2, tmp_radius * 2)
|
||||
kwargs.pop("radius")
|
||||
super(CirclePanel, self).__init__(*arg, **kwargs)
|
||||
self.brush = wx.Brush("Green")
|
||||
self.list_panel_inst.append(self)
|
||||
|
||||
def bind_events_default(self):
|
||||
super(CirclePanel, self).bind_events_default()
|
||||
self.Bind(wx.EVT_PAINT, self.action_paint_circle)
|
||||
self.Bind(wx.EVT_ERASE_BACKGROUND, self.action_clear_none)
|
||||
|
||||
@property
|
||||
def pen_focused(self):
|
||||
if not hasattr(self, "_pen_focused"):
|
||||
self._pen_focused = wx.Pen(
|
||||
"Blue", width=3, style=wx.PENSTYLE_LONG_DASH)
|
||||
self._pen_focused.SetCap(wx.CAP_BUTT)
|
||||
self._pen_focused.SetJoin(wx.JOIN_ROUND)
|
||||
return self._pen_focused
|
||||
|
||||
@pen_focused.setter
|
||||
def pen_focused(self, val):
|
||||
self._pen_focused = val
|
||||
|
||||
def action_paint_circle(self, ev):
|
||||
dc = wx.BufferedPaintDC(self, self.buffer)
|
||||
dc.SetBackground(wx.Brush(wx.Colour(150, 150, 150, 100)))
|
||||
dc.Clear()
|
||||
if self.HasFocus():
|
||||
self.pen = self.pen_focused
|
||||
else:
|
||||
self.pen = wx.NullPen
|
||||
|
||||
dc.SetBrush(self.brush)
|
||||
dc.SetPen(self.pen)
|
||||
|
||||
dc.DrawCircle(self.w / 2, self.h / 2, self.w / 2)
|
||||
|
||||
def action_clear_none(self, ev):
|
||||
wx.BufferedDC(None, self.buffer)
|
||||
|
||||
def get_props(self):
|
||||
return {
|
||||
"class": self.user_data["class"],
|
||||
"game_shape_class": self.game_shape_class,
|
||||
"config": {
|
||||
"center": self.center,
|
||||
"radius": self.w / 2,
|
||||
"color": None,
|
||||
}
|
||||
}
|
||||
|
||||
def get_start_props(self):
|
||||
return {
|
||||
"class": self.user_data["class"],
|
||||
"game_shape_class": self.game_shape_class,
|
||||
"config": {
|
||||
"center": (self._start_left + self._start_w / 2, self._start_top + self._start_h / 2),
|
||||
"radius": self._start_w / 2,
|
||||
"color": None,
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,24 @@
|
||||
import Circle
|
||||
import Rect
|
||||
import Img
|
||||
|
||||
# try..except saves from AttributeError during import
|
||||
# => means import, -> means running line within that file
|
||||
# why : sprite_types => Circle => sprite_types -> Circle.Circle
|
||||
# this raises error, as Circle class not yet defined in Circle
|
||||
# but when __main__ runs, after all successful imports, Circle.Circle is defined
|
||||
|
||||
try:
|
||||
Circle = Circle.Circle
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
Rect = Rect.Rect
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
Img = Img.Img
|
||||
except:
|
||||
pass
|
||||
Binary file not shown.
@@ -0,0 +1,79 @@
|
||||
from copy import deepcopy
|
||||
from uniquelist import uniquelist
|
||||
|
||||
|
||||
class StateClass(object):
|
||||
|
||||
"""State engine implementation"""
|
||||
|
||||
def __init__(self):
|
||||
super(StateClass, self).__init__()
|
||||
self._list_state = uniquelist()
|
||||
self._current_state = None
|
||||
self._dict_switch_func = []
|
||||
self._current_dict = {}
|
||||
|
||||
def __getattribute__(self, name):
|
||||
try:
|
||||
return self._current_dict[name]
|
||||
except KeyError:
|
||||
raise AttributeError("'{self_class}' object has no attribute '{attr_name}'".format(
|
||||
self_class=self.__class__, attr_name=name))
|
||||
|
||||
def __setattr__(self, name, val):
|
||||
self._current_dict[name] = val
|
||||
|
||||
def add_state(self, state_name):
|
||||
self._list_state.append(str(state_name))
|
||||
|
||||
def has_state(self, state_name):
|
||||
return str(state_name) in self._list_state
|
||||
|
||||
def remove_state(self, state_name):
|
||||
state_name = str(state_name)
|
||||
self.check_state(state_name)
|
||||
|
||||
self._list_state.remove(state_name)
|
||||
|
||||
def check_state(self, state_name_or_list):
|
||||
if isinstance(state_name_or_list, list):
|
||||
for state_name in state_name_or_list:
|
||||
self.check_state(state_name)
|
||||
else:
|
||||
state_name = state_name_or_list
|
||||
|
||||
if self.has_state(state_name):
|
||||
return state_name
|
||||
else:
|
||||
raise ValueError("state {state_name} not registered".format(
|
||||
state_name=state_name))
|
||||
|
||||
def add_switch_func(self, from_, to_, func_):
|
||||
from_, to_ = str(from_), str(to_)
|
||||
self.check_state([from_, to_])
|
||||
|
||||
if (from_, to_) not in self._dict_switch_func:
|
||||
self._dict_switch_func[(from_, to_)] = []
|
||||
|
||||
self._dict_switch_func[(from_, to_)].append(func_)
|
||||
|
||||
def get_switch_func(self, from_, to_):
|
||||
from_, to_ = str(from_), str(to_)
|
||||
self.check_state([from_, to_])
|
||||
|
||||
return self._dict_switch_func.get((from_, to_))
|
||||
|
||||
def switch_state(self, from_, to_, call_func=True):
|
||||
from_, to_ = str(from_), str(to_)
|
||||
self.check_state([from_, to_])
|
||||
|
||||
# do call_func
|
||||
if call_func:
|
||||
switch_func = self.get_switch_func(from_, to_)
|
||||
if switch_func:
|
||||
self._current_dict = switch_func(self._current_dict)
|
||||
else:
|
||||
self._current_dict = {}
|
||||
|
||||
self._current_state = to_
|
||||
# remove below
|
||||
@@ -0,0 +1,39 @@
|
||||
import base
|
||||
import random
|
||||
import sys
|
||||
from base import pygame
|
||||
|
||||
tmp_fill_color = (156, 27, 210)
|
||||
w = h = 200
|
||||
is_test_ok = None
|
||||
tmp_i = 0
|
||||
|
||||
|
||||
class test_Game(base.fun_Game):
|
||||
|
||||
def __init__(self, *arg, **kwarg):
|
||||
super(test_Game, self).__init__(*arg, **kwarg)
|
||||
self.fps = 100000 # max_fps
|
||||
|
||||
def test_update(self):
|
||||
self.screen.fill(tmp_fill_color)
|
||||
tmp_px_array = pygame.PixelArray(self.screen)
|
||||
is_test_ok = True
|
||||
global tmp_i
|
||||
if tmp_i < 1000:
|
||||
tmp_i += 1
|
||||
tmp_w = random.randrange(0, w)
|
||||
tmp_h = random.randrange(0, h)
|
||||
if tmp_px_array[tmp_w][tmp_h] != self.screen.map_rgb(tmp_fill_color):
|
||||
is_test_ok = False
|
||||
else:
|
||||
if is_test_ok:
|
||||
print "Test OK"
|
||||
else:
|
||||
print "Test Broken"
|
||||
sys.exit()
|
||||
|
||||
a = test_Game(w, h)
|
||||
a.run()
|
||||
|
||||
# Should display a purple window
|
||||
@@ -0,0 +1,42 @@
|
||||
import base
|
||||
import sys
|
||||
import random
|
||||
from base import pygame
|
||||
|
||||
tmp_fill_color = (156, 27, 210)
|
||||
w = random.randint(0, 1336)
|
||||
h = random.randint(0, 768)
|
||||
is_test_ok = None
|
||||
tmp_i = 0
|
||||
|
||||
|
||||
class test_Game(base.fun_Game):
|
||||
|
||||
def test_update(self):
|
||||
tmp_px_array = pygame.PixelArray(self.screen)
|
||||
is_test_ok = True
|
||||
global tmp_i
|
||||
self.screen.fill(tmp_fill_color)
|
||||
if tmp_i:
|
||||
for tmp_w in range(w):
|
||||
for tmp_h in range(h):
|
||||
tmp_i += 1
|
||||
if tmp_px_array[tmp_w][tmp_h] != self.screen.map_rgb(tmp_fill_color):
|
||||
is_test_ok = False
|
||||
break
|
||||
if not is_test_ok:
|
||||
break
|
||||
|
||||
print "Test run for %s pixels" % (tmp_i - 1)
|
||||
if is_test_ok:
|
||||
print "Test OK"
|
||||
else:
|
||||
print "Test Broken"
|
||||
sys.exit()
|
||||
tmp_i += 1
|
||||
|
||||
a = test_Game(w, h)
|
||||
a.run()
|
||||
|
||||
# Test made so that on first frame, screen is filled with purple.
|
||||
# Rest of the test loop occurs on second frame
|
||||
@@ -0,0 +1,39 @@
|
||||
import base
|
||||
import random
|
||||
import sys
|
||||
from base import pygame
|
||||
|
||||
tmp_fill_color = (156, 27, 210)
|
||||
w = h = 200
|
||||
is_test_ok = None
|
||||
tmp_i = 0
|
||||
|
||||
|
||||
class test_Game(base.fun_Game):
|
||||
|
||||
def test_update(self):
|
||||
tmp_px_array = pygame.PixelArray(self.screen)
|
||||
is_test_ok = True
|
||||
global tmp_i
|
||||
self.screen.fill(tmp_fill_color)
|
||||
if tmp_i:
|
||||
while tmp_i < 1000 and tmp_i:
|
||||
tmp_i += 1
|
||||
tmp_w = random.randrange(0, w)
|
||||
tmp_h = random.randrange(0, h)
|
||||
if tmp_px_array[tmp_w][tmp_h] != self.screen.map_rgb(tmp_fill_color):
|
||||
is_test_ok = False
|
||||
break
|
||||
|
||||
if is_test_ok:
|
||||
print "Test OK"
|
||||
else:
|
||||
print "Test Broken"
|
||||
sys.exit()
|
||||
tmp_i += 1
|
||||
|
||||
a = test_Game(w, h)
|
||||
a.run()
|
||||
|
||||
# Test made so that on first frame, screen is filled with purple.
|
||||
# Rest of the test loop occurs on second frame
|
||||
@@ -0,0 +1,12 @@
|
||||
import base
|
||||
|
||||
# make fun_class with some action handlers, who just print for debug
|
||||
|
||||
# move to test
|
||||
fun_Game.list_event.append(pygame.event.Event(KW_EVENTS_IB["JOY_BUTTON_UP"]))
|
||||
fun_Game.list_event.append(pygame.event.Event(KW_EVENTS_IB["KEY_UP"]))
|
||||
fun_Game.list_event.append(pygame.event.Event(KW_EVENTS_IB["KEY_DOWN"]))
|
||||
fun_Game.process_event_list(fun_Game.list_event)
|
||||
g = fun_Game(200, 200)
|
||||
c = fun_Class(0, 0)
|
||||
g.update_all_class()
|
||||
@@ -0,0 +1,76 @@
|
||||
from base import *
|
||||
import pygame.locals as pygame_const
|
||||
from sprite_types import Rect, Img, Circle
|
||||
import event
|
||||
|
||||
g = fun_Game(800, 200, fps=30)
|
||||
|
||||
event.register_event_name("trIal")
|
||||
|
||||
|
||||
def gen_TRIAL():
|
||||
return event.Event("trial", dict_={"haha": "hihi"})
|
||||
# event.register_custom_event_generator(gen_TRIAL)
|
||||
|
||||
|
||||
@register_class(fun_Game)
|
||||
class ball(fun_Class):
|
||||
|
||||
sprite_defaults = {
|
||||
"type": Rect,
|
||||
"params": {
|
||||
"size": (80, 40),
|
||||
"color": None
|
||||
# "file_name_or_obj":r"C:\Users\Machine\Pictures\Flight by Twitter_2.jpg"
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ball, self).__init__(*args, **kwargs)
|
||||
|
||||
def action_begin_step(self, ev):
|
||||
self.next_x, self.next_y = self.center
|
||||
|
||||
def action_key_press_right(self, ev):
|
||||
if ev.dict["key_name"] == "right":
|
||||
self.next_x += 5
|
||||
|
||||
if ev.dict["key_name"] == "left":
|
||||
self.next_x -= 5
|
||||
|
||||
if ev.dict["key_name"] == "up":
|
||||
self.next_y -= 5
|
||||
|
||||
if ev.dict["key_name"] == "down":
|
||||
self.next_y += 5
|
||||
|
||||
def action_end_step(self, ev):
|
||||
# if not self.collide(b, moved_center=(self.next_x, self.next_y)):
|
||||
# if hasattr(self, "next_x"):
|
||||
self.center = self.next_x, self.next_y
|
||||
|
||||
def action_key_press_p(self, ev):
|
||||
if ev.dict["key_name"] == "p":
|
||||
self.push_event_local(gen_TRIAL())
|
||||
|
||||
def action_trIal(self, ev):
|
||||
print ev.ev_name, ev.dict
|
||||
|
||||
def action_instance_create(self, ev):
|
||||
print "Instance created"
|
||||
|
||||
|
||||
@register_class(fun_Game)
|
||||
class wall(fun_Class):
|
||||
sprite_defaults = {
|
||||
"type": Rect,
|
||||
"params": {
|
||||
"size": (60, 40),
|
||||
"color": None
|
||||
}
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
a = ball(0, 80)
|
||||
b = wall(450, 60)
|
||||
g.run()
|
||||
Binary file not shown.
@@ -0,0 +1,141 @@
|
||||
from utils import KW_EVENTS, fuzzy_match_event_name
|
||||
from functools import partial
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
|
||||
class fun_Class(object):
|
||||
# dict_action_func -> dict of action funcs, key=event_numb like KEYDOWN
|
||||
dict_action_func = {}
|
||||
|
||||
@classmethod
|
||||
def register_event(cls, event_name=None, func_to_register=None):
|
||||
'''
|
||||
@fun_Class.register_event()
|
||||
def event_key_down(ev):
|
||||
pass
|
||||
OR
|
||||
@fun_Class.register_event(event_name) # event_name=KEYDOWN (or "key_down")
|
||||
def whatever(ev):
|
||||
pass
|
||||
OR
|
||||
fun_Class.register_event(event_name,func)
|
||||
'''
|
||||
if hasattr(func_to_register, "im_class"):
|
||||
print("im_class=")
|
||||
print func_to_register.im_class,func_to_register.imelf,
|
||||
if (event_name is None) and (func_to_register is None):
|
||||
# i.e No param passed, used as decorator (1st step of ex. 1)
|
||||
logging.info("Nothing passed")
|
||||
return cls.register_event
|
||||
elif (not(event_name is None)) and (func_to_register is None):
|
||||
# i.e. one param is passed, maybe func or (str or int)
|
||||
logging.info("Event Name only passed")
|
||||
if isinstance(event_name, int) or isinstance(event_name, str):
|
||||
# i.e. 1st parm-> str or int, is event name, acts as decorator
|
||||
# (2nd ex.)
|
||||
# dont hardcode func name- use metaclass
|
||||
logging.info("Event Name is event_name")
|
||||
return partial(cls.register_event, event_name)
|
||||
elif hasattr(event_name, "__call__"):
|
||||
# first param is func, actually func_to_register.
|
||||
# So get event_name from func_name (2nd step of 1st ex.)
|
||||
logging.info("Event Name is actually func")
|
||||
func_to_register = event_name
|
||||
event_name = fuzzy_match_event_name(func_to_register.func_name)
|
||||
return cls.register_event(event_name, func_to_register)
|
||||
else:
|
||||
raise TypeError("event_name must be (str or int) or func")
|
||||
else:
|
||||
# Both params present
|
||||
logging.info("Both param passed")
|
||||
|
||||
if isinstance(event_name, str):
|
||||
event_name = fuzzy_match_event_name(event_name)
|
||||
event_numb = KW_EVENTS[event_name]
|
||||
elif isinstance(event_name, int):
|
||||
event_numb = event_name
|
||||
else:
|
||||
raise TypeError("event_name should be str or int")
|
||||
|
||||
logging.info("Registering func")
|
||||
if not (event_numb in cls.dict_action_func):
|
||||
cls.dict_action_func[event_numb] = []
|
||||
cls.dict_action_func[event_numb].append(func_to_register)
|
||||
|
||||
# logging.debug(func_to_register)
|
||||
return func_to_register
|
||||
|
||||
|
||||
class child(fun_Class):
|
||||
pass
|
||||
|
||||
|
||||
@child.register_event("key_down")
|
||||
def ev_arbit(self):
|
||||
pass
|
||||
logging.info(fun_Class.dict_action_func)
|
||||
logging.info(child.dict_action_func)
|
||||
|
||||
|
||||
class child2(fun_Class):
|
||||
|
||||
@fun_Class.register_event("key_down")
|
||||
def ev_arbit_2(self):
|
||||
pass
|
||||
logging.info(fun_Class.dict_action_func)
|
||||
logging.info(child2.dict_action_func)
|
||||
|
||||
# Test 1
|
||||
|
||||
# logging.info("\nRunning Test 1")
|
||||
|
||||
|
||||
# @fun_Class.register_event("KEydown")
|
||||
# def ev_arbit():
|
||||
# pass
|
||||
# logging.info(ev_arbit)
|
||||
|
||||
# Test 1.1
|
||||
|
||||
# logging.info("\nRunning Test 1.1")
|
||||
|
||||
|
||||
# @fun_Class.register_event("KEydown")
|
||||
# def ev_arbit_2():
|
||||
# pass
|
||||
# logging.info(fun_Class.dict_action_func)
|
||||
# logging.info(ev_arbit_2)
|
||||
|
||||
# Test 2
|
||||
|
||||
# logging.info("\nRunning Test 2")
|
||||
|
||||
|
||||
# @fun_Class.register_event
|
||||
# def ev_key_up():
|
||||
# pass
|
||||
# logging.info(fun_Class.dict_action_func)
|
||||
# logging.info(ev_key_up)
|
||||
|
||||
# Test 3
|
||||
# logging.info("\nRunning Test 3")
|
||||
|
||||
|
||||
# def test_mousemotion():
|
||||
# pass
|
||||
# test_mousemotion = fun_Class.register_event(test_mousemotion)
|
||||
# logging.info(fun_Class.dict_action_func)
|
||||
# logging.info(test_mousemotion)
|
||||
|
||||
# Test 4
|
||||
|
||||
# logging.info("\nRunning Test 4")
|
||||
|
||||
|
||||
# def test_wat():
|
||||
# pass
|
||||
# test_wat = fun_Class.register_event("mousemotion", test_wat)
|
||||
# logging.info(fun_Class.dict_action_func)
|
||||
# logging.info(test_wat)
|
||||
@@ -0,0 +1,33 @@
|
||||
how @classmethod and @property works
|
||||
how to call in python shell for debugging (import pdb;pdb.set_trace())
|
||||
what are best-practises for writing classes that makes for better and flexible sub-classes
|
||||
how __get__ works
|
||||
|
||||
Learnt:
|
||||
1. Can define class functions and class properties (getter/setter) using metaclass.
|
||||
|
||||
IMP (Have to try):
|
||||
|
||||
import inspect
|
||||
|
||||
class meta(type):
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
methods=inspect.getmembers(temp_cls,inspect.ismethod)
|
||||
for method in methods:
|
||||
print inspect.getargspec(method[1])
|
||||
|
||||
class A(Object):
|
||||
__metaclass__=meta
|
||||
@doit(what_to_do)
|
||||
def abc():
|
||||
pass
|
||||
|
||||
def doit(what_to_do, main_func):
|
||||
def abc(what_to_do=what_to_do,main_func=main_func):
|
||||
pass
|
||||
return "pass" function containing both params (and a special param to indicate doit-processed func)\
|
||||
with default values set (default values are themself func).
|
||||
|
||||
What meta does ->
|
||||
Identify funcs processed with doit and return main_func after invoking what_to_do
|
||||
@@ -0,0 +1,114 @@
|
||||
dx,dy for sprites
|
||||
mouse.x,mouse.y
|
||||
mouse_collision_events
|
||||
is_focused func
|
||||
|
||||
(do) room
|
||||
(Done) move by wasd
|
||||
(Done) resize about center by +-
|
||||
(Done) ---- resize Working, but problem with ints, need internal floats
|
||||
(Done) show all instances
|
||||
add, delete button
|
||||
(Done) highlight on focus (?)
|
||||
(Done differently) make fake instances, not classes
|
||||
(Done) Create from game.py
|
||||
(Done) all prev actions with mouse
|
||||
|
||||
(Done) export to json
|
||||
** save ori game.py filename**
|
||||
(Done) save original size and other props, which should be restored while loading after populating loaded shapes
|
||||
(Done) Load from json, needs seperate inst creation logic
|
||||
() saved map cant depend upon original game.py, reduces portability
|
||||
needs some sort of update from existing map method, think later
|
||||
|
||||
Create map of certain dimension
|
||||
** extracted from game.py **
|
||||
|
||||
** menu - load, new, export **
|
||||
-- fake pygame module for faster map loading --
|
||||
** color conversion **
|
||||
-- Heavy code refactoring --
|
||||
** grid snapping **
|
||||
|
||||
Serialize pygame.color
|
||||
|
||||
LATER
|
||||
transparent panels
|
||||
|
||||
(think) timer
|
||||
|
||||
(later) UI
|
||||
panel-ish things where x,y is diff from whole screen
|
||||
panels dynamically resizable
|
||||
extra events for focus, mouse click, keyboard tabbing and value change stuff
|
||||
e.g. to have a score sidebar
|
||||
|
||||
(done for now) solve circular imports
|
||||
|
||||
DOWNLOAD pyqt/pyside books
|
||||
Todo: make set of excel funcs with pyxll
|
||||
dwnload sp1, vb book and ide
|
||||
|
||||
(drawing bug) with non-clearing rect aka contains condition
|
||||
|
||||
Use rects retuned from blit to display.update
|
||||
(imp) gen_event_IB filters - modify ev_name and dict, eg below
|
||||
IMP - learn how import works
|
||||
(later) actual bitmap collision.
|
||||
(later) move collisions to sep. module
|
||||
|
||||
INSTALL win32api and check boa
|
||||
DOWNLOAD Editors such as wxDesigner, wxrcedit, XRCed and wxWorkshop
|
||||
|
||||
(todo, add warning) pygame.locals has pygame.Rect. So, importing that may overload sprite_types.Rect. fix this in base.py
|
||||
state machine
|
||||
fix tiltedrect,img, line,ellipse,point,tri
|
||||
|
||||
filters:
|
||||
key_press - cnvrt "mod" to list,
|
||||
mouse - cnvrt btn_id to btn_name,
|
||||
mouse - mod get_btn_name to include 4 and 5 scroll ids.
|
||||
look for more
|
||||
|
||||
(imp) draw_ext
|
||||
add TEXT class, open all shape drawing and rect filling api
|
||||
(think) all in_place operators should return self, i.e. chainable
|
||||
(think) use from_container_obj classmethod for all sprite creation and cnstrctr for standalone use
|
||||
(think) move key and mouse funcs from event.py to seperate modules
|
||||
(think) asset management
|
||||
(think) views
|
||||
(think) physics
|
||||
(think) brython
|
||||
|
||||
(think) use key_names instead of id, sort it out
|
||||
(later) make fun_Game instances global
|
||||
(later) make fun_Game instance singleton (??) or maybe needs no instantiation (seems better, everything class,ethod and classprop)
|
||||
(later) some action plugins for common scenarios
|
||||
(later) unregister classes
|
||||
|
||||
(Done) distance and angle, motion_add funcs
|
||||
(Done, but draw-update rect solves both) blit at int(x),int(y)
|
||||
(Done) default action_close
|
||||
(Done) top-level custom event generator working
|
||||
(Done) event XXgeneratorXX / pushing at XX(class) [Not sure how to implement]XX and instance level
|
||||
(done) img - implement collision_mask with existing shapes,
|
||||
(done)mouse_press events
|
||||
(done) fix check_event-ish func (soln- moved to event), also old key_press_states
|
||||
(done) Fixed rect,circle.
|
||||
(done) *explicit blit print always showing, when more than 1 obj
|
||||
(done) *not implemented completely.
|
||||
knowing about others(Done)
|
||||
(done) more collision like GM
|
||||
(Done) in-built hspeed, vspeed, direction, speed,accln, x_prev, y_prev, x_start, y_start
|
||||
(Done) Circle(params).update for not still_valid old_rects -> optimize, maybe save bbox in list instead of creating for each old one
|
||||
(Done) fix putting "still_valid" within dict_update used for marking (added note, was actually a good idea, Done)
|
||||
|
||||
|
||||
why the heck 60fps flickering -> in-built recording mechanism?
|
||||
forum discussion=> display.flip fixes it
|
||||
|
||||
clear_rect+new_drawn_rect passed to update -> optimize? (for later, have to ask)
|
||||
|
||||
|
||||
|
||||
make graphical glitches by removing few updates_display :D
|
||||
+18
-6
@@ -1,20 +1,32 @@
|
||||
# move it to utils.py
|
||||
# also look at frozensets
|
||||
# look at import collections - lot of good data structures
|
||||
# learn about co-routines (returning generators from generators i.e. yield
|
||||
# statement)
|
||||
|
||||
|
||||
class uniquelist(list):
|
||||
|
||||
''' A list whose every value is unique.
|
||||
uniquelist.append(val) or __setitem__(pos,val) i.e. uniquelist[pos]=val is ignored if val is already in uniquelist.
|
||||
Returns True if the value is added, else returns False. '''
|
||||
def __setitem__(self,pos,val):
|
||||
|
||||
def __setitem__(self, pos, val):
|
||||
if val not in self:
|
||||
super(uniquelist,self).__setitem__(pos,val)
|
||||
super(uniquelist, self).__setitem__(pos, val)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def append(self,val):
|
||||
|
||||
def append(self, val):
|
||||
if val not in self:
|
||||
super(uniquelist,self).append(val)
|
||||
super(uniquelist, self).append(val)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def extend(self,iterable):
|
||||
for temp in iterable: # todo: use yield so that it is not copied into memory
|
||||
|
||||
def extend(self, iterable):
|
||||
# todo: use yield so that it is not copied into memory
|
||||
for temp in iterable:
|
||||
self.append(temp)
|
||||
# Todo: Allow for type checking by allowing a type_of_members to be set
|
||||
Binary file not shown.
@@ -0,0 +1,268 @@
|
||||
# Utility functions
|
||||
# ToDo: Put everything in a class as staticmethods when imported, if
|
||||
# name=__main__, keep them local
|
||||
from functools import partial
|
||||
import inspect
|
||||
import logging
|
||||
import types
|
||||
import event
|
||||
from uniquelist import uniquelist
|
||||
from UncasedDict import UncasedDict
|
||||
|
||||
|
||||
def register(list_to_register=None):
|
||||
''' Used as decorator: Adds the function (or anything else) to list_to_register '''
|
||||
def temp_func(what_to_register):
|
||||
list_to_register.append(what_to_register)
|
||||
return what_to_register
|
||||
return temp_func
|
||||
|
||||
|
||||
def fuzzy_match_event_name(string, event_or_action):
|
||||
str_upper = string.upper()
|
||||
if not (str_upper in event.dict_event_name):
|
||||
event_or_action = event_or_action.lower()
|
||||
if event_or_action.lower() == "event" or event_or_action.lower() == "action":
|
||||
# STR_STARTER becomes event_ or action_
|
||||
STR_STARTER = event_or_action.upper() + "_"
|
||||
else:
|
||||
raise AttributeError(
|
||||
"event_or_action arg must be 'event' or 'action'.")
|
||||
str_normalized = str_upper[
|
||||
str_upper.find(STR_STARTER) + len(STR_STARTER):]
|
||||
for tmp_event_name in event.dict_event_name:
|
||||
# tmp event is the event_name, keys of KW_EVENTS
|
||||
tmp_event_name = tmp_event_name.upper()
|
||||
tmp_event_name_normalized = tmp_event_name.replace("_", "")
|
||||
if str_normalized.startswith(tmp_event_name) or str_normalized.startswith(tmp_event_name_normalized):
|
||||
return tmp_event_name
|
||||
else:
|
||||
return str_upper
|
||||
|
||||
|
||||
class Action(object):
|
||||
|
||||
""" pygame.event.Action(type, dict): return Action
|
||||
pygame.Action.Action(type, **attributes): return Action
|
||||
"""
|
||||
|
||||
def __init__(self, type, *args, **kwargs):
|
||||
super(Action, self).__init__()
|
||||
self.type = type
|
||||
_dict = {}
|
||||
if len(args) == 1:
|
||||
_dict.update(args[0])
|
||||
elif len(args) > 1:
|
||||
raise TypeError(
|
||||
"Max one non-keyword argument allowed (which is set to dict)")
|
||||
if kwargs:
|
||||
_dict.update(kwargs)
|
||||
if _dict:
|
||||
self.dict = _dict
|
||||
|
||||
|
||||
def copy_func(f, name=None):
|
||||
return types.FunctionType(f.func_code, f.func_globals, name or f.func_name,
|
||||
f.func_defaults, f.func_closure)
|
||||
|
||||
|
||||
def selfie_depreceated(f):
|
||||
"""Decorate function `f` to pass a reference to the function
|
||||
as the first argument"""
|
||||
return partial(f, f)
|
||||
|
||||
|
||||
def selfie(f):
|
||||
"""Decorate function `f` to pass a reference to the function
|
||||
as the first argument"""
|
||||
return f.__get__(f, type(f))
|
||||
|
||||
|
||||
def sync_func(func1, func2):
|
||||
'''Makes the 1st param (func) equivalent to 2nd param (func).'''
|
||||
func1.func_code = func2.func_code
|
||||
func1.func_defaults = func2.func_defaults
|
||||
func1.func_dict = func2.func_dict
|
||||
func1.func_doc = func2.func_doc
|
||||
func1.func_name = func2.func_name
|
||||
|
||||
|
||||
class meta_accessor_class(type):
|
||||
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
temp_cls.list_instance = uniquelist()
|
||||
temp_cls.list_check_func = uniquelist()
|
||||
# dict_action_func -> dict of action funcs, key=event_numb like KEYDOWN
|
||||
temp_cls.dict_action_func = UncasedDict()
|
||||
methods = inspect.getmembers(temp_cls, inspect.ismethod)
|
||||
for (method_name, method_obj) in methods:
|
||||
if fuzzy_match_event_name(method_name, "action"):
|
||||
temp_cls.register_action(method_obj)
|
||||
return temp_cls
|
||||
|
||||
|
||||
@selfie
|
||||
def run_dec_on_meta(self, what_to_do):
|
||||
'''Runs decorator (what_to_do) passed to it during meta with args, cls=>class and func=>function which this is used on'''
|
||||
# make copies of this func and instead of params use .vars. Should accept
|
||||
# *args,*kwargs to main_func. Next step: multiple funcs, think.
|
||||
|
||||
def inter_run_dec_on_meta(*args, **kwargs):
|
||||
# this intermediate func is used to produce func_process_meta for each
|
||||
# time
|
||||
def func_process_meta(self, *args, **kwargs):
|
||||
if not hasattr(self, "_process_meta"):
|
||||
# changing own's state, should be restored at last step before
|
||||
# meta-return
|
||||
self._process_meta = False
|
||||
#(below) unneccesary here
|
||||
if not hasattr(self, "__old_args") and not hasattr(self, "__old_kwargs"):
|
||||
self.__old_args = None
|
||||
self.__old_kwargs = None
|
||||
if not self._process_meta:
|
||||
# as long as not being meta-processed
|
||||
# its not really main_func, really its just what_to_do's param
|
||||
if (self.__old_args or self.__old_kwargs):
|
||||
self.what_to_do = partial(
|
||||
self.what_to_do, *(self.__old_args), **(self.__old_kwargs))
|
||||
self.__old_args = args
|
||||
self.__old_kwargs = kwargs
|
||||
return selfie(self)
|
||||
else:
|
||||
self.main_func = self.__old_args[0]
|
||||
return self
|
||||
|
||||
func_process_meta.__old_args = args
|
||||
func_process_meta.__old_kwargs = kwargs
|
||||
func_process_meta.what_to_do = what_to_do
|
||||
func_process_meta.selfie = True
|
||||
func_process_meta = selfie(func_process_meta)
|
||||
return func_process_meta
|
||||
return inter_run_dec_on_meta
|
||||
|
||||
|
||||
def run_func_on_meta(run_func):
|
||||
'''Runs func (run_func) passed to it during meta with arg, cls.
|
||||
run_func remains a method of the class.'''
|
||||
run_func._run_meta = True
|
||||
return run_func
|
||||
|
||||
|
||||
def register_action(event_name=None, func_to_register=None, cls=None):
|
||||
'''
|
||||
@fun_Class.register_action() # @fun_Class.register_action === @fun_Class.register_action()
|
||||
def event_key_down(ev):
|
||||
pass
|
||||
OR
|
||||
# event_name=KEYDOWN (or "key_down")
|
||||
@fun_Class.register_action(event_name)
|
||||
def whatever(ev):
|
||||
pass
|
||||
OR
|
||||
fun_Class.register_action(event_name,func)
|
||||
'''
|
||||
if (event_name is None) and (func_to_register is None):
|
||||
# i.e No param passed, used as decorator (1st step of ex. 1)
|
||||
logging.info("Nothing passed")
|
||||
return register_action
|
||||
elif (not(event_name is None)) and (func_to_register is None):
|
||||
# i.e. one param is passed, maybe func or (str or int)
|
||||
logging.info("Event Name only passed")
|
||||
if isinstance(event_name, str):
|
||||
# i.e. 1st parm-> str , is event name, acts as decorator
|
||||
# (2nd ex.)
|
||||
# dont hardcode func name- use metaclass
|
||||
logging.info("Event Name is event_name")
|
||||
return partial(cls.register_action, event_name)
|
||||
elif hasattr(event_name, "__call__"):
|
||||
# first param is func, actually func_to_register.
|
||||
# So get event_name from func_name (2nd step of 1st ex.)
|
||||
logging.info("Event Name is actually func")
|
||||
func_to_register = event_name
|
||||
event_name = fuzzy_match_event_name(
|
||||
func_to_register.func_name, "action")
|
||||
return register_action(event_name=event_name, func_to_register=func_to_register, cls=cls)
|
||||
else:
|
||||
raise TypeError("event_name must be str or func")
|
||||
else:
|
||||
# Both params present
|
||||
logging.info("Both param passed")
|
||||
|
||||
if isinstance(event_name, str):
|
||||
event_name = fuzzy_match_event_name(event_name, "action")
|
||||
|
||||
logging.info("Registering func")
|
||||
if not (event_name in cls.dict_action_func):
|
||||
cls.dict_action_func[event_name] = []
|
||||
list_ = cls.dict_action_func[event_name]
|
||||
if not (func_to_register in list_):
|
||||
list_.append(func_to_register)
|
||||
else:
|
||||
raise Exception("func_to_register was already rgistered, skipping")
|
||||
|
||||
return func_to_register
|
||||
|
||||
|
||||
def register_class(game_class, cls=None):
|
||||
''' Register this class on mega_class.
|
||||
Calls _regitser_class_ on mega_class with arg cls'''
|
||||
if cls is None:
|
||||
return partial(register_class, game_class)
|
||||
game_class.register_class(cls)
|
||||
cls.game_obj = game_class
|
||||
return cls
|
||||
|
||||
|
||||
def remove_from_list(list_, val, recursive=False):
|
||||
if val in list_:
|
||||
list_.remove(val)
|
||||
if recursive:
|
||||
while (val in list_):
|
||||
list_.remove(val)
|
||||
return list_
|
||||
|
||||
|
||||
def rect_to_pygame_rect(rect):
|
||||
if hasattr(rect, "bbox"):
|
||||
rect = rect.bbox
|
||||
return rect
|
||||
|
||||
|
||||
class updater_list(list):
|
||||
|
||||
"""list which also calls a updater func on data change"""
|
||||
|
||||
def __init__(self, updater_func, *arg, **kwargs):
|
||||
super(updater_list, self).__init__(*arg, **kwargs)
|
||||
self.updater_func = updater_func
|
||||
|
||||
def insert(self, *arg, **kwargs):
|
||||
to_return = super(updater_list, self).insert(*arg, **kwargs)
|
||||
self.updater_func(self)
|
||||
return to_return
|
||||
|
||||
def pop(self, *arg, **kwargs):
|
||||
to_return = super(updater_list, self).pop(*arg, **kwargs)
|
||||
self.updater_func(self)
|
||||
return to_return
|
||||
|
||||
def append(self, *arg, **kwargs):
|
||||
to_return = super(updater_list, self).append(*arg, **kwargs)
|
||||
self.updater_func(self)
|
||||
return to_return
|
||||
|
||||
def extend(self, *arg, **kwargs):
|
||||
to_return = super(updater_list, self).extend(*arg, **kwargs)
|
||||
self.updater_func(self)
|
||||
return to_return
|
||||
|
||||
def __getitem__(self, *arg, **kwargs):
|
||||
to_return = super(updater_list, self).__getitem__(*arg, **kwargs)
|
||||
self.updater_func(self)
|
||||
return to_return
|
||||
|
||||
def __setitem__(self, *arg, **kwargs):
|
||||
to_return = super(updater_list, self).__setitem__(*arg, **kwargs)
|
||||
self.updater_func(self)
|
||||
return to_return
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
# Utility functions
|
||||
# ToDo: Put everything in a class as staticmethods when imported, if
|
||||
# name=__main__, keep them local
|
||||
from pygame import locals as pygame_consts
|
||||
from functools import partial
|
||||
import inspect
|
||||
import logging
|
||||
import types
|
||||
|
||||
|
||||
def register(list_to_register=None):
|
||||
''' Used as decorator: Adds the function (or anything else) to list_to_register '''
|
||||
def temp_func(what_to_register):
|
||||
list_to_register.append(what_to_register)
|
||||
return what_to_register
|
||||
return temp_func
|
||||
|
||||
KW_EVENTS = {
|
||||
"QUIT": pygame_consts.QUIT,
|
||||
"ACTIVE_EVENT": pygame_consts.ACTIVEEVENT,
|
||||
"KEY_DOWN": pygame_consts.KEYDOWN,
|
||||
"KEY_UP": pygame_consts.KEYUP,
|
||||
"MOUSE_MOTION": pygame_consts.MOUSEMOTION,
|
||||
"MOUSE_BUTTON_UP": pygame_consts.MOUSEBUTTONUP,
|
||||
"MOUSE_BUTTON_DOWN": pygame_consts.MOUSEBUTTONDOWN,
|
||||
"JOY_AXIS_MOTION": pygame_consts.JOYAXISMOTION,
|
||||
"JOY_BALL_MOTION": pygame_consts.JOYBALLMOTION,
|
||||
"JOY_HAT_MOTION": pygame_consts.JOYHATMOTION,
|
||||
"JOY_BUTTON_UP": pygame_consts.JOYBUTTONUP,
|
||||
"JOY_BUTTOND_OWN": pygame_consts.JOYBUTTONDOWN,
|
||||
"VIDEO_RESIZE": pygame_consts.VIDEORESIZE,
|
||||
"VIDEO_EXPOSE": pygame_consts.VIDEOEXPOSE,
|
||||
"USER_EVENT": pygame_consts.USEREVENT,
|
||||
# think of begin_step, step and end_step
|
||||
"BEGIN_STEP": pygame_consts.USEREVENT + 1,
|
||||
"STEP": pygame_consts.USEREVENT + 2,
|
||||
"END_STEP": pygame_consts.USEREVENT + 3
|
||||
}
|
||||
|
||||
|
||||
def fuzzy_match_event_name(string):
|
||||
# print(string)
|
||||
str_normalized = string.upper()
|
||||
for tmp_event in KW_EVENTS:
|
||||
# tmp event is the event_name, keys of KW_EVENTS
|
||||
tmp_event_normalized = tmp_event.replace("_", "")
|
||||
if (tmp_event in str_normalized) or (tmp_event_normalized in str_normalized):
|
||||
return tmp_event
|
||||
|
||||
|
||||
class Action(object):
|
||||
|
||||
""" pygame.event.Action(type, dict): return Action
|
||||
pygame.Action.Action(type, **attributes): return Action
|
||||
"""
|
||||
|
||||
def __init__(self, type, *args, **kwargs):
|
||||
super(Action, self).__init__()
|
||||
self.type = type
|
||||
_dict = {}
|
||||
if len(args) == 1:
|
||||
_dict.update(args[0])
|
||||
elif len(args) > 1:
|
||||
raise TypeError(
|
||||
"Max one non-keyword argument allowed (which is set to dict)")
|
||||
if kwargs:
|
||||
_dict.update(kwargs)
|
||||
if _dict:
|
||||
self.dict = _dict
|
||||
|
||||
|
||||
def copy_func(f, name=None):
|
||||
return types.FunctionType(f.func_code, f.func_globals, name or f.func_name,
|
||||
f.func_defaults, f.func_closure)
|
||||
|
||||
|
||||
def selfie_depreceated(f):
|
||||
"""Decorate function `f` to pass a reference to the function
|
||||
as the first argument"""
|
||||
return partial(f, f)
|
||||
|
||||
|
||||
def selfie(f):
|
||||
"""Decorate function `f` to pass a reference to the function
|
||||
as the first argument"""
|
||||
return f.__get__(f, type(f))
|
||||
|
||||
|
||||
def sync_func(func1, func2):
|
||||
'''Makes the 1st param (func) equivalent to 2nd param (func).'''
|
||||
func1.func_code = func2.func_code
|
||||
func1.func_defaults = func2.func_defaults
|
||||
func1.func_dict = func2.func_dict
|
||||
func1.func_doc = func2.func_doc
|
||||
func1.func_name = func2.func_name
|
||||
|
||||
|
||||
class meta_accessor_class(type):
|
||||
|
||||
''' This metaclass allows class access to any function (or as extended use, to metaclasses)'''
|
||||
# Using metaclass and decorator to allow class access during class creation time
|
||||
# No method defined within the class should have "_process_meta" as arg
|
||||
# Potential problems: Using closures, function.func_globals is read-only
|
||||
# Doesnt get appropiate globals, maybe pass it (or the reqd global vars)
|
||||
# as param on func defn
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
methods = inspect.getmembers(temp_cls, inspect.ismethod)
|
||||
for (method_name, method_obj) in methods:
|
||||
has_im_func = hasattr(method_obj, "im_func")
|
||||
has_func = hasattr(method_obj, "func")
|
||||
while has_im_func or has_func:
|
||||
if has_im_func:
|
||||
method_obj = method_obj.im_func
|
||||
if has_func:
|
||||
# cater for partials
|
||||
method_obj = method_obj.func
|
||||
has_im_func = hasattr(method_obj, "im_func")
|
||||
has_func = hasattr(method_obj, "func")
|
||||
|
||||
if hasattr(method_obj, "_process_meta"):
|
||||
method_obj._process_meta = True
|
||||
# method_obj should return itself after setting main_func
|
||||
if hasattr(method_obj,"selfie"):
|
||||
method_obj = method_obj(method_obj)
|
||||
else:
|
||||
method_obj = method_obj()
|
||||
what_to_do, main_func = method_obj.what_to_do, method_obj.main_func
|
||||
# as we have resolved all im_funcs in
|
||||
# partial,classmethod,boundmethods
|
||||
f = method_obj
|
||||
sync_func(f, main_func)
|
||||
# func_to_register hardcoded
|
||||
mod_func = what_to_do(f, cls=temp_cls)
|
||||
sync_func(f, mod_func)
|
||||
|
||||
return temp_cls
|
||||
|
||||
|
||||
@selfie
|
||||
def run_dec_on_meta(self, what_to_do):
|
||||
'''Runs decorator (what_to_do) passed to it during meta with args, cls=>class and func=>function which this is used on'''
|
||||
# must be deepcopied bcoz multiple versions will edit main func
|
||||
# syntax error to grab attention
|
||||
# make copies of this func and instead of params use .vars. Should accept
|
||||
# *args,*kwargs to main_func. Next step: multiple funcs, think.
|
||||
|
||||
def inter_run_dec_on_meta(*args,**kwargs):
|
||||
# this intermediate func is used to produce func_process_meta for each time
|
||||
def func_process_meta(self, *args, **kwargs):
|
||||
if not hasattr(self, "_process_meta"):
|
||||
# changing own's state, should be restored at last step before
|
||||
# meta-return
|
||||
self._process_meta = False
|
||||
#(below) unneccesary here
|
||||
if not hasattr(self,"__old_args") and not hasattr(self,"__old_kwargs"):
|
||||
self.__old_args = None
|
||||
self.__old_kwargs = None
|
||||
if not self._process_meta:
|
||||
# as long as not being meta-processed
|
||||
# its not really main_func, really its just what_to_do's param
|
||||
if (self.__old_args or self.__old_kwargs):
|
||||
self.what_to_do = partial(self.what_to_do, *(self.__old_args), **(self.__old_kwargs))
|
||||
self.__old_args = args
|
||||
self.__old_kwargs = kwargs
|
||||
return selfie(self)
|
||||
else:
|
||||
self.main_func = self.__old_args[0]
|
||||
return self
|
||||
|
||||
func_process_meta.__old_args = args
|
||||
func_process_meta.__old_kwargs = kwargs
|
||||
func_process_meta.what_to_do = what_to_do
|
||||
func_process_meta.selfie=True
|
||||
func_process_meta = selfie(func_process_meta)
|
||||
return func_process_meta
|
||||
return inter_run_dec_on_meta
|
||||
|
||||
def run_func_on_meta(run_func):
|
||||
'''Runs func (run_func) passed to it during meta with arg, cls.
|
||||
run_func remains a method of the class.'''
|
||||
def what_to_do(func, cls):
|
||||
func(cls=cls)
|
||||
return func
|
||||
return run_dec_on_meta(what_to_do=what_to_do, main_func=run_func)
|
||||
|
||||
|
||||
def register_event(event_name=None, func_to_register=None, cls=None):
|
||||
'''
|
||||
@fun_Class.register_event() # @fun_Class.register_event === @fun_Class.register_event()
|
||||
def event_key_down(ev):
|
||||
pass
|
||||
OR
|
||||
# event_name=KEYDOWN (or "key_down")
|
||||
@fun_Class.register_event(event_name)
|
||||
def whatever(ev):
|
||||
pass
|
||||
OR
|
||||
fun_Class.register_event(event_name,func)
|
||||
'''
|
||||
if (event_name is None) and (func_to_register is None):
|
||||
# i.e No param passed, used as decorator (1st step of ex. 1)
|
||||
logging.info("Nothing passed")
|
||||
return register_event
|
||||
elif (not(event_name is None)) and (func_to_register is None):
|
||||
# i.e. one param is passed, maybe func or (str or int)
|
||||
logging.info("Event Name only passed")
|
||||
if isinstance(event_name, int) or isinstance(event_name, str):
|
||||
# i.e. 1st parm-> str or int, is event name, acts as decorator
|
||||
# (2nd ex.)
|
||||
# dont hardcode func name- use metaclass
|
||||
logging.info("Event Name is event_name")
|
||||
return partial(cls.register_event, event_name)
|
||||
elif hasattr(event_name, "__call__"):
|
||||
# first param is func, actually func_to_register.
|
||||
# So get event_name from func_name (2nd step of 1st ex.)
|
||||
logging.info("Event Name is actually func")
|
||||
func_to_register = event_name
|
||||
event_name = fuzzy_match_event_name(func_to_register.func_name)
|
||||
return register_event(event_name=event_name, func_to_register=func_to_register, cls=cls)
|
||||
else:
|
||||
raise TypeError("event_name must be (str or int) or func")
|
||||
else:
|
||||
# Both params present
|
||||
logging.info("Both param passed")
|
||||
|
||||
if isinstance(event_name, str):
|
||||
event_name = fuzzy_match_event_name(event_name)
|
||||
event_numb = KW_EVENTS[event_name]
|
||||
elif isinstance(event_name, int):
|
||||
event_numb = event_name
|
||||
else:
|
||||
raise TypeError("event_name should be str or int")
|
||||
|
||||
logging.info("Registering func")
|
||||
if not (event_numb in cls.dict_action_func):
|
||||
cls.dict_action_func[event_numb] = []
|
||||
cls.dict_action_func[event_numb].append(func_to_register)
|
||||
|
||||
return func_to_register
|
||||
|
||||
|
||||
|
||||
##_register_event_ = register_event
|
||||
##del register_event
|
||||
# so that register event is actually delegated register
|
||||
##register_event = run_dec_on_meta(_register_event_)
|
||||
Binary file not shown.
+322
@@ -0,0 +1,322 @@
|
||||
# Utility functions
|
||||
# ToDo: Put everything in a class as staticmethods when imported, if
|
||||
# name=__main__, keep them local
|
||||
from pygame import locals as pygame_consts
|
||||
from functools import partial
|
||||
import inspect
|
||||
import logging
|
||||
import types
|
||||
import pygame
|
||||
from uniquelist import uniquelist
|
||||
|
||||
|
||||
def register(list_to_register=None):
|
||||
''' Used as decorator: Adds the function (or anything else) to list_to_register '''
|
||||
def temp_func(what_to_register):
|
||||
list_to_register.append(what_to_register)
|
||||
return what_to_register
|
||||
return temp_func
|
||||
|
||||
KW_EVENTS_IB = {
|
||||
"QUIT": pygame_consts.QUIT,
|
||||
"ACTIVE_EVENT": pygame_consts.ACTIVEEVENT,
|
||||
"KEY_DOWN": pygame_consts.KEYDOWN,
|
||||
"KEY_UP": pygame_consts.KEYUP,
|
||||
"MOUSE_MOTION": pygame_consts.MOUSEMOTION,
|
||||
"MOUSE_BUTTON_UP": pygame_consts.MOUSEBUTTONUP,
|
||||
"MOUSE_BUTTON_DOWN": pygame_consts.MOUSEBUTTONDOWN,
|
||||
"JOY_AXIS_MOTION": pygame_consts.JOYAXISMOTION,
|
||||
"JOY_BALL_MOTION": pygame_consts.JOYBALLMOTION,
|
||||
"JOY_HAT_MOTION": pygame_consts.JOYHATMOTION,
|
||||
"JOY_BUTTON_UP": pygame_consts.JOYBUTTONUP,
|
||||
"JOY_BUTTOND_OWN": pygame_consts.JOYBUTTONDOWN,
|
||||
"VIDEO_RESIZE": pygame_consts.VIDEORESIZE,
|
||||
"VIDEO_EXPOSE": pygame_consts.VIDEOEXPOSE,
|
||||
# "USER_EVENT": pygame_consts.USEREVENT,
|
||||
# think of begin_step, step and end_step
|
||||
}
|
||||
|
||||
# Make kw_events_user automatically
|
||||
|
||||
LIST_EVENTS_USER = ["BEGIN_STEP", "STEP", "DRAW", "END_STEP"]
|
||||
|
||||
KW_EVENTS_USER = {}
|
||||
KW_EVENTS_ALL = {}
|
||||
|
||||
|
||||
def populate_KW_EVENTS_USER(LIST_EVENTS_USER=LIST_EVENTS_USER):
|
||||
'''Populates KW_EVENTS_USER and also updates KW_EVENTS_ALL'''
|
||||
tmp_event_numb = pygame_consts.USEREVENT
|
||||
for tmp_event_name in LIST_EVENTS_USER:
|
||||
KW_EVENTS_USER[tmp_event_name] = tmp_event_numb
|
||||
tmp_event_numb += 1
|
||||
global KW_EVENTS_ALL
|
||||
KW_EVENTS_ALL = {}
|
||||
for tmp_event_name in KW_EVENTS_IB:
|
||||
KW_EVENTS_ALL[tmp_event_name] = KW_EVENTS_IB[tmp_event_name]
|
||||
for tmp_event_name in KW_EVENTS_USER:
|
||||
KW_EVENTS_ALL[tmp_event_name] = KW_EVENTS_USER[tmp_event_name]
|
||||
# populated by default, may be repopulated later
|
||||
populate_KW_EVENTS_USER()
|
||||
|
||||
CUE_EVENTS_IB = "unordered IB events here"
|
||||
LIST_EVENTS_ORDERED = [KW_EVENTS_USER["BEGIN_STEP"], CUE_EVENTS_IB, KW_EVENTS_USER["STEP"],
|
||||
KW_EVENTS_USER["DRAW"], KW_EVENTS_USER["END_STEP"]]
|
||||
|
||||
|
||||
def sort_events(ev1, ev2):
|
||||
ev_args = [ev1, ev2]
|
||||
args_pos = [None, None]
|
||||
# fix next line
|
||||
for tmp_index in range(len(ev_args)):
|
||||
tmp_ev = ev_args[tmp_index]
|
||||
if (tmp_ev.type in KW_EVENTS_IB.values()):
|
||||
args_pos[tmp_index] = LIST_EVENTS_ORDERED.index(CUE_EVENTS_IB)
|
||||
elif (tmp_ev.type in KW_EVENTS_USER.values()):
|
||||
args_pos[tmp_index] = LIST_EVENTS_ORDERED.index(tmp_ev.type)
|
||||
tmp_diff = args_pos[0] - args_pos[1]
|
||||
# convert -ve to -1, 0 to 0, +ve to +1
|
||||
if tmp_diff == 0:
|
||||
tmp_diff_unit = 0
|
||||
else:
|
||||
tmp_diff_unit = tmp_diff / abs(tmp_diff)
|
||||
return tmp_diff_unit
|
||||
|
||||
|
||||
def append_user_events(list_):
|
||||
for temp_ev_name in LIST_EVENTS_USER:
|
||||
temp_ev_numb = KW_EVENTS_USER[temp_ev_name]
|
||||
list_.append(pygame.event.Event(temp_ev_numb))
|
||||
return list_
|
||||
|
||||
|
||||
def fuzzy_match_event_name(string, event_or_action):
|
||||
str_upper = string.upper()
|
||||
if not (str_upper in KW_EVENTS_ALL):
|
||||
event_or_action = event_or_action.lower()
|
||||
if event_or_action.lower() == "event" or event_or_action.lower() == "action":
|
||||
# STR_STARTER becomes event_ or action_
|
||||
STR_STARTER = event_or_action.upper() + "_"
|
||||
else:
|
||||
raise AttributeError(
|
||||
"event_or_action arg must be 'event' or 'action'.")
|
||||
str_normalized = str_upper[
|
||||
str_upper.find(STR_STARTER) + len(STR_STARTER):]
|
||||
for tmp_event_name in KW_EVENTS_ALL:
|
||||
# tmp event is the event_name, keys of KW_EVENTS
|
||||
tmp_event_name_normalized = tmp_event_name.replace("_", "")
|
||||
if str_normalized.startswith(tmp_event_name) or str_normalized.startswith(tmp_event_name_normalized):
|
||||
return tmp_event_name
|
||||
else:
|
||||
return str_upper
|
||||
|
||||
|
||||
class Action(object):
|
||||
|
||||
""" pygame.event.Action(type, dict): return Action
|
||||
pygame.Action.Action(type, **attributes): return Action
|
||||
"""
|
||||
|
||||
def __init__(self, type, *args, **kwargs):
|
||||
super(Action, self).__init__()
|
||||
self.type = type
|
||||
_dict = {}
|
||||
if len(args) == 1:
|
||||
_dict.update(args[0])
|
||||
elif len(args) > 1:
|
||||
raise TypeError(
|
||||
"Max one non-keyword argument allowed (which is set to dict)")
|
||||
if kwargs:
|
||||
_dict.update(kwargs)
|
||||
if _dict:
|
||||
self.dict = _dict
|
||||
|
||||
|
||||
def copy_func(f, name=None):
|
||||
return types.FunctionType(f.func_code, f.func_globals, name or f.func_name,
|
||||
f.func_defaults, f.func_closure)
|
||||
|
||||
|
||||
def selfie_depreceated(f):
|
||||
"""Decorate function `f` to pass a reference to the function
|
||||
as the first argument"""
|
||||
return partial(f, f)
|
||||
|
||||
|
||||
def selfie(f):
|
||||
"""Decorate function `f` to pass a reference to the function
|
||||
as the first argument"""
|
||||
return f.__get__(f, type(f))
|
||||
|
||||
|
||||
def sync_func(func1, func2):
|
||||
'''Makes the 1st param (func) equivalent to 2nd param (func).'''
|
||||
func1.func_code = func2.func_code
|
||||
func1.func_defaults = func2.func_defaults
|
||||
func1.func_dict = func2.func_dict
|
||||
func1.func_doc = func2.func_doc
|
||||
func1.func_name = func2.func_name
|
||||
|
||||
|
||||
class meta_accessor_class(type):
|
||||
|
||||
''' This metaclass allows class access to any function (or as extended use, to metaclasses)'''
|
||||
# Using metaclass and decorator to allow class access during class creation time
|
||||
# No method defined within the class should have "_process_meta" as arg
|
||||
# Potential problems: Using closures, function.func_globals is read-only
|
||||
# Doesnt get appropiate globals, maybe pass it (or the reqd global vars)
|
||||
# as param on func defn
|
||||
def __new__(cls, name, base, clsdict):
|
||||
temp_cls = type.__new__(cls, name, base, clsdict)
|
||||
temp_cls.list_instance = uniquelist()
|
||||
temp_cls.list_check_func = uniquelist()
|
||||
# dict_action_func -> dict of action funcs, key=event_numb like KEYDOWN
|
||||
temp_cls.dict_action_func = {}
|
||||
methods = inspect.getmembers(temp_cls, inspect.ismethod)
|
||||
for (method_name, method_obj) in methods:
|
||||
if fuzzy_match_event_name(method_name, "action"):
|
||||
temp_cls.register_event(method_obj)
|
||||
return temp_cls
|
||||
|
||||
|
||||
@selfie
|
||||
def run_dec_on_meta(self, what_to_do):
|
||||
'''Runs decorator (what_to_do) passed to it during meta with args, cls=>class and func=>function which this is used on'''
|
||||
# make copies of this func and instead of params use .vars. Should accept
|
||||
# *args,*kwargs to main_func. Next step: multiple funcs, think.
|
||||
|
||||
def inter_run_dec_on_meta(*args, **kwargs):
|
||||
# this intermediate func is used to produce func_process_meta for each
|
||||
# time
|
||||
def func_process_meta(self, *args, **kwargs):
|
||||
if not hasattr(self, "_process_meta"):
|
||||
# changing own's state, should be restored at last step before
|
||||
# meta-return
|
||||
self._process_meta = False
|
||||
#(below) unneccesary here
|
||||
if not hasattr(self, "__old_args") and not hasattr(self, "__old_kwargs"):
|
||||
self.__old_args = None
|
||||
self.__old_kwargs = None
|
||||
if not self._process_meta:
|
||||
# as long as not being meta-processed
|
||||
# its not really main_func, really its just what_to_do's param
|
||||
if (self.__old_args or self.__old_kwargs):
|
||||
self.what_to_do = partial(
|
||||
self.what_to_do, *(self.__old_args), **(self.__old_kwargs))
|
||||
self.__old_args = args
|
||||
self.__old_kwargs = kwargs
|
||||
return selfie(self)
|
||||
else:
|
||||
self.main_func = self.__old_args[0]
|
||||
return self
|
||||
|
||||
func_process_meta.__old_args = args
|
||||
func_process_meta.__old_kwargs = kwargs
|
||||
func_process_meta.what_to_do = what_to_do
|
||||
func_process_meta.selfie = True
|
||||
func_process_meta = selfie(func_process_meta)
|
||||
return func_process_meta
|
||||
return inter_run_dec_on_meta
|
||||
|
||||
|
||||
def run_func_on_meta(run_func):
|
||||
'''Runs func (run_func) passed to it during meta with arg, cls.
|
||||
run_func remains a method of the class.'''
|
||||
run_func._run_meta = True
|
||||
return run_func
|
||||
|
||||
|
||||
def register_event(event_name=None, func_to_register=None, cls=None):
|
||||
'''
|
||||
@fun_Class.register_event() # @fun_Class.register_event === @fun_Class.register_event()
|
||||
def event_key_down(ev):
|
||||
pass
|
||||
OR
|
||||
# event_name=KEYDOWN (or "key_down")
|
||||
@fun_Class.register_event(event_name)
|
||||
def whatever(ev):
|
||||
pass
|
||||
OR
|
||||
fun_Class.register_event(event_name,func)
|
||||
'''
|
||||
if (event_name is None) and (func_to_register is None):
|
||||
# i.e No param passed, used as decorator (1st step of ex. 1)
|
||||
logging.info("Nothing passed")
|
||||
return register_event
|
||||
elif (not(event_name is None)) and (func_to_register is None):
|
||||
# i.e. one param is passed, maybe func or (str or int)
|
||||
logging.info("Event Name only passed")
|
||||
if isinstance(event_name, str):
|
||||
# i.e. 1st parm-> str , is event name, acts as decorator
|
||||
# (2nd ex.)
|
||||
# dont hardcode func name- use metaclass
|
||||
logging.info("Event Name is event_name")
|
||||
return partial(cls.register_event, event_name)
|
||||
elif hasattr(event_name, "__call__"):
|
||||
# first param is func, actually func_to_register.
|
||||
# So get event_name from func_name (2nd step of 1st ex.)
|
||||
logging.info("Event Name is actually func")
|
||||
func_to_register = event_name
|
||||
event_name = fuzzy_match_event_name(
|
||||
func_to_register.func_name, "action")
|
||||
return register_event(event_name=event_name, func_to_register=func_to_register, cls=cls)
|
||||
else:
|
||||
raise TypeError("event_name must be str or func")
|
||||
else:
|
||||
# Both params present
|
||||
logging.info("Both param passed")
|
||||
|
||||
if isinstance(event_name, str):
|
||||
event_name = fuzzy_match_event_name(event_name, "action")
|
||||
|
||||
logging.info("Registering func")
|
||||
if not (event_name in cls.dict_action_func):
|
||||
cls.dict_action_func[event_name] = []
|
||||
cls.dict_action_func[event_name].append(func_to_register)
|
||||
|
||||
return func_to_register
|
||||
|
||||
|
||||
def register_class(game_class, cls=None):
|
||||
''' Register this class on mega_class.
|
||||
Calls _regitser_class_ on mega_class with arg cls'''
|
||||
if cls is None:
|
||||
return partial(register_class, game_class)
|
||||
game_class.register_class(cls)
|
||||
cls.Game = game_class
|
||||
return cls
|
||||
|
||||
|
||||
def remove_from_list(list_, val, recursive=False):
|
||||
if val in list_:
|
||||
list_.remove(val)
|
||||
if recursive:
|
||||
while (val in list_):
|
||||
list_.remove(val)
|
||||
return list_
|
||||
|
||||
|
||||
def rect_to_pygame_rect(rect):
|
||||
if hasattr(rect, "bbox"):
|
||||
rect = rect.bbox
|
||||
return rect
|
||||
|
||||
|
||||
# _register_event_ = register_event
|
||||
# del register_event
|
||||
# so that register event is actually delegated register
|
||||
# register_event = run_dec_on_meta(_register_event_)
|
||||
|
||||
# Move to test
|
||||
##import pygame
|
||||
# pygame.init()
|
||||
##evs = []
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_IB["KEY_DOWN"]))
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_IB["JOY_AXIS_MOTION"]))
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_IB["KEY_UP"]))
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_IB["MOUSE_BUTTON_UP"]))
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_USER["DRAW"]))
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_USER["BEGIN_STEP"]))
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_USER["END_STEP"]))
|
||||
# evs.append(pygame.event.Event(KW_EVENTS_USER["STEP"]))
|
||||
# evs.sort(sort_events)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Reference in New Issue
Block a user