added boids stuff

This commit is contained in:
2019-10-22 14:24:00 +02:00
parent 9339e8d441
commit 1b64f98f31
6 changed files with 364 additions and 197 deletions
@@ -1,22 +1,39 @@
from mymanager import Manager
from myabstract import Vector
from myabstract import Vector, Form
from mymotion import Motion
from mymaterial import Material
from mybody import MaterialBody
import mycolors
import random
import math
class Boid(Material):
def __init__(self, motion=Motion(n=3, d=2), form=):
class Boid(MaterialBody):
@classmethod
def random(cls):
"""Create a boid with a random motion."""
p=10*Vector.random()
#v=Vector(0,random.uniform(0,10),color=mycolors.BLUE)
v=5*Vector.random(color=mycolors.BLUE)
a=Vector.null()
m=Motion(p,v,a)
return cls(m)
def __init__(self, motion=Motion(n=3, d=2)):
"""Create a boid."""
self.motion = motion
self.form = form
self.anatomy = Form.createFromTuples([(0,1),(1,-1),(0,0),(-1,-1)])
self.anatomy.rotate(-math.pi/2)
self.anatomy.area_color=mycolors.RED
self.anatomy.fill=True
self.discipline = 0.1
def update(self):
"""Update the boid."""
self.motion.update()
def adjustVelocity(self,neighbours):
"""Adjust the boid velocity to the one of its neighbours."""
neighbours_velocities=[n.velocity for n in neighbours]
average_velocity=Vector.average(neighbours_velocities)
self.acceleration.set((average_velocity-self.velocity)*self.discipline)
def show(self):
"""Show the boid."""
self.form.show(self.context)
class BoidGroup:
@@ -29,6 +46,7 @@ class BoidGroup:
def __init__(self, boids):
"""Create a boid group using boids."""
self.boids = boids
self.neighbours_number = 3
def show(self, context):
"""Show the object."""
@@ -37,9 +55,39 @@ class BoidGroup:
def update(self, dt=1):
"""Update the object."""
self.adjustVelocities()
self.updateEach(dt)
def updateEach(self,dt):
"""Update each boid individually."""
for boid in self.boids:
boid.update(dt)
def follow(self,point):
"""Follow the given point."""
for boid in self.boids:
boid.follow(point)
def adjustVelocities(self):
"""Adjust the velocity of each boid to the one of its neighbours."""
for i in range(len(self.boids)):
neighbours=self.getNeighbours(i)
self.boids[i].adjustVelocity(neighbours)
def getNeighbours(self,j):
"""Return the neighbours of the b-th boid."""
proximity=[(self.distance(i,j),i) for i in range(len(self.boids))]
proximity.sort(key=lambda x:x[0])
proximity=proximity[:self.neighbours_number]
neighbours=[self.boids[p[1]] for p in proximity]
return neighbours
def distance(self,i,j):
"""Return the distance between the boids i and j."""
p1=self.boids[i].position
p2=self.boids[j].position
return (p1-p2).norm
class Simulation(Manager):
def random(n=10, **kwargs):
@@ -54,6 +102,7 @@ class Simulation(Manager):
def update(self):
"""Update the boid group."""
self.boid_group.update(self.dt)
#self.boid_group.follow(self.context.point())
def show(self):
"""Show the boid group."""
@@ -61,5 +110,5 @@ class Simulation(Manager):
if __name__ == "__main__":
s = Simulation()
s = Simulation.random(n=50,dt=1)
s()
+16 -2
View File
@@ -378,6 +378,10 @@ class Vector:
self.width=width
self.arrow=arrow
def set(self,v):
"""Set a vector to the values of another without changing its color, with or arrow."""
self.components=v.components
def setNull(self):
"""Set the components of the vector to zero."""
self.components=[0 for i in range(len(self.components))]
@@ -538,8 +542,18 @@ class Vector:
"""Sub two vector together."""
return Vector([c1-c2 for (c1,c2) in zip(self.components,other.components)])
__iadd__=__radd__=__add__
__isub__=__rsub__=__sub__
def __iadd__(self,other):
"""Add a vector to another."""
self.components=[c1+c2 for (c1,c2) in zip(self.components,other.components)]
return self
def __isub__(self,other):
"""Substract a vector to another."""
self.components=[c1-c2 for (c1,c2) in zip(self.components,other.components)]
return self
__radd__=__add__
__rsub__=__sub__
def rotate(self,angle):
"""Rotate a vector using the angle of rotation."""
+81 -1
View File
@@ -138,7 +138,7 @@ class PhysicalBody(Physics, Body):
self.velocity.angle = v.angle
class SimpleBody(Physics):
class NewBody(Physics):
"""
A simple body is composed of its motion and its anatomy.
An atomy must have:
@@ -226,6 +226,86 @@ class SimpleBody(Physics):
absolute = property(getAbsolute)
class MaterialBody(Material):
"""Unlike the other bodies, the material body only has one motion."""
def __init__(self,anatomy,motion):
"""Create a material body from its anatomy and its motion."""
self.anatomy = anatomy
self.motion = motion
@classmethod
def createFromAbsolute(cls, absolute, motion):
"""Create a simple body from its absolute anatomy and its motion."""
return cls(anatomy, motion)
@classmethod
def random(cls,nv=2,d=2):
"""Return a random simple body."""
motion = Motion.random(n=nv,d=d)
anatomy = Form.random(n=5)
return cls(anatomy, motion)
def __init__(self, anatomy, motion):
"""Create a simple body."""
self.motion = motion
self.anatomy = anatomy
self.center()
def __str__(self):
"""Return the string representation of the body."""
return "b(" + str(self.anatomy) + "," + str(",".join(map(str,self.motions))) + ")"
def center(self):
"""Center the anatomy."""
c=self.anatomy.center
v=-Vector(*c)
self.anatomy.position.set(v)
def show(self, context):
"""Show the simple body on the context."""
self.showAbsolute(context)
self.showMotion(context)
def showAnatomy(self, context):
"""Show the anatomy on the context."""
self.anatomy.show(context)
def showAbsolute(self, context):
"""Show the body on the context."""
self.getAbsolute().show(context)
def showMotion(self, context):
"""Show the motion of the body on the context."""
self.velocity.show(context,self.position)
self.acceleration.show(context,self.position)
def update(self, dt=1):
"""Update the simple body."""
self.motion.update(dt)
def follow(self, position):
"""Follow the cursor."""
a=Vector(*position)
b=self.position
v=Vector(a-b)
self.velocity.angle=v.angle
#self.velocity.norm=min(v.norm,1)
def __contains__(self, other):
"""Determine if the object other is in the absolute anatomy."""
return other in self.getAbsolute()
def getAbsolute(self):
"""Return the absolute anatomy of the body which means its form after
changing the position depending on its motion."""
anatomy = deepcopy(self.anatomy)
anatomy.position=self.motion.position # change its position
anatomy.rotate(self.velocity.angle) # change its rotation
return anatomy
absolute = property(getAbsolute)
if __name__ == "__main__":
from mycontext import Context
context = Context(fullscreen=False)
+3 -2
View File
@@ -50,9 +50,10 @@ class Motion:
vector.show(context)
#Updating the motion
def update(self,t=1):
def update(self,dt=1):
"""Update the motion according to physics."""
self.vectors[:-1]=[v+d*t for (v,d) in zip(self.vectors[:-1],self.vectors[1:])]
for i in range(len(self.vectors)-1):
self.vectors[i]+=self.vectors[i+1]*dt
#Representation
def __str__(self):
@@ -5,13 +5,13 @@ from myforce import Force
from mymanager import Manager
from pygame.locals import K_f
#from playsound import playsound
# from playsound import playsound # Doesn't work on macos
import mycolors
import random
import math
G = 6.67408e-11
G = 6.67408e-11 # gravity constant of international system of units
ud = 1 # unit distance for computing
um = 1 # unit mass for computing
udd = 10e-10 # unit distance for visualizing
@@ -282,23 +282,26 @@ class Neptune(Planet):
class SystemManager(Manager):
"""Manage a space system. Note that all the values are in si units."""
def __init__(self):
"""Create a system manager."""
super().__init__()
self.system = self.getSolarSystem()
#self.system = self.getRandomSystem()
self.dt = 3600 # 1 hour in seconds
self.generateStars()
def getSolarSystem(self):
"""Create a representation of the true solar system with the true values."""
@classmethod
def createSolarSystem(cls, **kwargs):
"""Create the solar system."""
astres = [Sun(), Mercury(), Venus(), Earth(), Mars(),
Jupiter(), Saturn(), Uranus(), Neptune()]
return System(astres)
system = System(astres)
return cls(system, **kwargs)
def getRandomSystem(self, n=50):
@classmethod
def createRandomSystem(cls, n=50, **kwargs):
"""Create a random system."""
return System.random(n=n)
system = System.random(n=n)
return cls(system, **kwargs)
def __init__(self, system, **kwargs):
"""Create a system manager."""
super().__init__(**kwargs)
self.system = system
self.dt = 3600 # 1 hour in seconds
self.generateStars()
def setup(self):
"""Play the sound."""
@@ -342,5 +345,5 @@ class SystemManager(Manager):
if __name__ == "__main__":
sm = SystemManager()
sm = SystemManager.createRandomSystem()
sm()
+184 -164
View File
@@ -2,9 +2,9 @@
#Credits#
#-------#
__author__="Marc Partensky"
__license__="Marc Partensky Company"
__game__="Snake"
__author__ = "Marc Partensky"
__license__ = "Marc Partensky Company"
__game__ = "Snake"
"""This game is available on every computer device that has Python installed."""
@@ -12,56 +12,71 @@ __game__="Snake"
#Dependencies#
#------------#
import os
os.system("pip2.7 install pygame")
import pygame
from pygame.locals import *
import math
import random
import numpy as np
import time
import math
import sys
import os
v=sys.version[:3]
try:
DIRECTORY="/Users/olivierpartensky/Programs/Python/Games/Snake/"
os.chdir(DIRECTORY)
finally:
pass
import numpy as np
except:
print("Installing numpy dependency.")
os.system("pip"+v+" install numpy")
import numpy as np
try:
from pygame.locals import *
import pygame
except:
print("Installing pygame dependency.")
os.system("pip"+v+" install pygame")
from pygame.locals import *
import pygame
#DIRECTORY=os.getcwd()
#print("Your current directory is:",DIRECTORY)
#os.chdir(DIRECTORY)
#---------#
#Variables#
#---------#
BLUE = ( 0, 0,255)
RED = (255, 0, 0)
GREEN = ( 0,255, 0)
YELLOW = (255,255, 0)
BLACK = ( 0, 0, 0)
WHITE = (255,255,255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RIGHT = 0
UP = 1
LEFT = 2
DOWN = 3
UP = 1
LEFT = 2
DOWN = 3
#-------#
#Classes#
#-------#
class Window:
def __init__(self,background,title="Snake"):
self.title=title
self.opened=True
def __init__(self, background, title="Snake"):
self.title = title
self.opened = True
pygame.init()
info = pygame.display.Info()
s=max(info.current_w//2,info.current_h//2)
self.size=(s,s)
self.screen=pygame.display.set_mode(self.size)
s = max(info.current_w // 2, info.current_h // 2)
self.size = (s, s)
self.screen = pygame.display.set_mode(self.size)
pygame.display.set_caption(self.title)
self.background=pygame.transform.scale(background,self.size)
self.drawPicture(self.background,(0,0))
self.background = pygame.transform.scale(background, self.size)
self.drawPicture(self.background, (0, 0))
def direction(self):
keys=pygame.key.get_pressed()
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
return LEFT
if keys[K_RIGHT]:
@@ -74,216 +89,220 @@ class Window:
def check(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.opened=False
self.opened = False
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
self.opened=False
self.opened = False
def select(self):
while not self.closed():
for event in pygame.event.get():
if event.type == MOUSEBUTTONDOWN and event.button == 1:
return (event.pos[0],event.pos[1])
return (event.pos[0], event.pos[1])
def flip(self):
pygame.display.flip()
def drawPicture(self,picture,position):
def drawPicture(self, picture, position):
self.screen.blit(picture, position)
def draw(self,color,coordonnates,size):
x,y=coordonnates
sx,sy=size
pygame.draw.rect(self.screen, color, (x,y,sx,sy), 0)
def draw(self, color, coordonnates, size):
x, y = coordonnates
sx, sy = size
pygame.draw.rect(self.screen, color, (x, y, sx, sy), 0)
def kill(self):
pygame.quit()
class Map:
def __init__(self,background_directory,size=[20,20],color_line=BLACK):
self.size=size
self.board=np.zeros(self.size)
self.color_line=color_line
self.background_directory=background_directory
self.background=pygame.image.load(self.background_directory)
def __init__(self, background_directory, size=[20, 20], color_line=BLACK):
self.size = size
self.board = np.zeros(self.size)
self.color_line = color_line
self.background_directory = background_directory
self.background = pygame.image.load(self.background_directory)
def oldshow(self,window):
def oldshow(self, window):
window.screen.fill(self.color_background)
mx,my=self.size
wx,wy=window.size
cx,cy=wx/mx,wy/my
mx, my = self.size
wx, wy = window.size
cx, cy = wx / mx, wy / my
for x in range(mx):
for y in range(my):
window.draw(self.color_case,(cx*x+1,cy*y+1),(cx-1,cy-1))
window.draw(self.color_case, (cx * x + 1,
cy * y + 1), (cx - 1, cy - 1))
def show(self,window):
mx,my=self.size
wx,wy=window.size
cx,cy=wx/mx,wy/my
def show(self, window):
mx, my = self.size
wx, wy = window.size
cx, cy = wx / mx, wy / my
for x in range(mx):
window.draw(self.color_line,(cx*x,0),(1,wy))
window.draw(self.color_line, (cx * x, 0), (1, wy))
for y in range(my):
window.draw(self.color_line,(0,cy*y),(wx,1))
window.draw(self.color_line, (0, cy * y), (wx, 1))
class Snake:
def __init__(self,picture_directory,size=4):
self.picture=pygame.image.load(picture_directory)
self.size=size
self.food_eaten=0
self.alive=False
def __init__(self, picture_directory, size=4):
self.picture = pygame.image.load(picture_directory)
self.size = size
self.food_eaten = 0
self.alive = False
def loadTexture(self,map,window):
mx,my=map.size
wx,wy=window.size
cx,cy=wx/mx,wy/my
self.texture=pygame.transform.scale(self.picture,(cx,cy))
def loadTexture(self, map, window):
mx, my = map.size
wx, wy = window.size
cx, cy = wx // mx, wy // my
self.texture = pygame.transform.scale(self.picture, (cx, cy))
def spawn(self,map):
self.alive=True
self.direction=random.randint(0,3)
mx,my=map.size
self.head=[random.randint(0,mx-1-self.size),random.randint(0,my-1-self.size)]
self.body=[self.head]
x,y=self.head
r=self.direction
for i in range(self.size-1):
if r==LEFT:
part=[x+i,y]
if r==RIGHT:
part=[x-i,y]
if r==UP:
part=[x,y+i]
if r==DOWN:
part=[x,y-i]
def spawn(self, map):
self.alive = True
self.direction = random.randint(0, 3)
mx, my = map.size
self.head = [random.randint(
0, mx - 1 - self.size), random.randint(0, my - 1 - self.size)]
self.body = [self.head]
x, y = self.head
r = self.direction
for i in range(self.size - 1):
if r == LEFT:
part = [x + i, y]
if r == RIGHT:
part = [x - i, y]
if r == UP:
part = [x, y + i]
if r == DOWN:
part = [x, y - i]
self.body.append(part)
self.tail=self.body[-1]
self.tail = self.body[-1]
def eat(self,food,map):
self.food_eaten+=1
def eat(self, food, map):
self.food_eaten += 1
self.body.append(self.tail)
food.spawn(map)
def move(self):
x,y=self.head
if self.direction==RIGHT:
x+=1
if self.direction==LEFT:
x-=1
if self.direction==UP:
y-=1
if self.direction==DOWN:
y+=1
self.head=[x,y]
self.tail=self.body[-1]
self.body=[self.head]+self.body[:-1]
x, y = self.head
if self.direction == RIGHT:
x += 1
if self.direction == LEFT:
x -= 1
if self.direction == UP:
y -= 1
if self.direction == DOWN:
y += 1
self.head = [x, y]
self.tail = self.body[-1]
self.body = [self.head] + self.body[:-1]
def bodyChanges(self):
for part in self.body[1:]:
if part==self.head:
self.alive=False
if part == self.head:
self.alive = False
def borderChanges(self,map):
x,y=self.head
mx,my=map.size
sx,sy=mx-1,my-1
if x<0:
x=sx
if x>sx:
x=0
if y<0:
y=sy
if y>sy:
y=0
self.head=x,y
def borderChanges(self, map):
x, y = self.head
mx, my = map.size
sx, sy = mx - 1, my - 1
if x < 0:
x = sx
if x > sx:
x = 0
if y < 0:
y = sy
if y > sy:
y = 0
self.head = x, y
def foodChanges(self,food,map):
if self.head==food.coordonnates:
self.eat(food,map)
def foodChanges(self, food, map):
if self.head == food.coordonnates:
self.eat(food, map)
def show(self,map,window):
mx,my=map.size
wx,wy=window.size
cx,cy=wx/mx,wy/my
X,Y=self.head
def show(self, map, window):
mx, my = map.size
wx, wy = window.size
cx, cy = wx // mx, wy // my
X, Y = self.head
for part in self.body:
x,y=part
window.drawPicture(self.texture,(x*cx,y*cy))
x, y = part
window.drawPicture(self.texture, (x * cx, y * cy))
def opposite(self,direction):
return direction==(self.direction+2)%4
def opposite(self, direction):
return direction == (self.direction + 2) % 4
def lead(self,window):
direction=window.direction()
def lead(self, window):
direction = window.direction()
if direction is not None and not self.opposite(direction):
self.direction=direction
self.direction = direction
def play(self,map,window,food):
def play(self, map, window, food):
self.lead(window)
self.move()
self.bodyChanges()
self.borderChanges(map)
self.foodChanges(food,map)
self.foodChanges(food, map)
def win(self,map):
mx,my=map.size
return (self.size==mx*my)
def win(self, map):
mx, my = map.size
return (self.size == mx * my)
class Food:
def __init__(self,picture_directory):
self.picture=pygame.image.load(picture_directory)
def __init__(self, picture_directory):
self.picture = pygame.image.load(picture_directory)
def loadTexture(self,map,window):
mx,my=map.size
wx,wy=window.size
cx,cy=wx/mx,wy/my
self.texture=pygame.transform.scale(self.picture,(cx,cy))
def loadTexture(self, map, window):
mx, my = map.size
wx, wy = window.size
cx, cy = wx // mx, wy // my
self.texture = pygame.transform.scale(self.picture, (cx, cy))
def spawn(self,map):
mx,my=map.size
self.coordonnates=(random.randint(0,mx-1),random.randint(0,my-1))
def spawn(self, map):
mx, my = map.size
self.coordonnates = (random.randint(0, mx - 1),
random.randint(0, my - 1))
def show(self,map,window):
x,y=self.coordonnates
mx,my=map.size
wx,wy=window.size
cx,cy=wx/mx,wy/my
window.drawPicture(self.texture,(x*cx,y*cy))
def show(self, map, window):
x, y = self.coordonnates
mx, my = map.size
wx, wy = window.size
cx, cy = wx / mx, wy / my
window.drawPicture(self.texture, (x * cx, y * cy))
#----------#
#Main class#
#----------#
class Game:
def __init__(self):
self.loadPictures()
self.loadEntities()
self.loadTextures()
self.speed=0.01
self.speed = 0.05
self.main()
def loadEntities(self):
self.map=Map(self.background_directory)
self.window=Window(self.map.background)
self.snake=Snake(self.snake_body_picture)
self.food=Food(self.food_picture)
self.map = Map(self.background_directory)
self.window = Window(self.map.background)
self.snake = Snake(self.snake_body_picture)
self.food = Food(self.food_picture)
def loadPictures(self):
self.background_directory="Pictures/red space.jpg"
self.snake_body_picture="Pictures/snake.jpg"
self.food_picture="Pictures/potato.png"
self.background_directory = "Pictures/red space.jpg"
self.snake_body_picture = "Pictures/snake.jpg"
self.food_picture = "Pictures/potato.png"
def loadTextures(self):
self.snake.loadTexture(self.map,self.window)
self.food.loadTexture(self.map,self.window)
self.snake.loadTexture(self.map, self.window)
self.food.loadTexture(self.map, self.window)
def show(self):
self.window.drawPicture(self.window.background,(0,0))
self.window.drawPicture(self.window.background, (0, 0))
self.map.show(self.window)
self.food.show(self.map,self.window)
self.snake.show(self.map,self.window)
self.food.show(self.map, self.window)
self.snake.show(self.map, self.window)
self.window.flip()
def play(self):
@@ -293,7 +312,7 @@ class Game:
while not self.snake.win(self.map) and self.window.opened and self.snake.alive:
self.window.check()
time.sleep(self.speed)
self.snake.play(self.map,self.window,self.food)
self.snake.play(self.map, self.window, self.food)
self.show()
def main(self):
@@ -305,4 +324,5 @@ class Game:
#Actions#
#-------#
game=Game()
game = Game()