# Shaper

Playing around with randomness I came up with this program which randomly generates various shapes. It starts off with one point in the center which will start randomly moving. By clicking on the screen you can generate new points or remove previous ones. If the number of points gets higher than 2, a monochrome polygon will be displayed (using the pygame.polygon() function).

#### Usage

• Left-clicking generates a new point
• Right-clicking removes a previous point

``````# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 8th of May, 2015``````

``````# gets the scaled mouse position
def getMousePos():
p = pygame.mouse.get_pos()
return [
p[0] / main.SCALE, p[1] / main.SCALE
]

# gets the distance between two points
def getDistance(p1, p2):
return int(
math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)
)

# easy vector functions
def convertVec(p1, p2):
return [p2[0] - p1[0], p2[1] - p1[1]]
def getLength(vec):
return math.sqrt( (vec[0]**2) + (vec[1]**2) )
def multiplyVec(vec, n):
return [vec[0] * n, vec[1] * n]
def getPoint(vec, point):
return [point[0] + vec[0], point[1] + vec[1]]

# validates color integer
# extra feature: _min and _max implementation
def colorValid(_color, _min = 0, _max = 255):
newColor = math.fabs(_color)
n = _max - _min
if newColor > n:
if int(newColor / n) % 2 == 0:
newColor = newColor % n
else:
newColor = n - (newColor % n)

return int(newColor) + _min

# gets the position on a circle
# circle center                           : '_pos'
# circle radius                           : '_radius'
# angle from center to point on the circle: '_angle'
def getCirclePos(_pos, _radius, _angle):
return [
int(_pos[0] + _radius * math.cos(math.radians(_angle))),
int(_pos[1] + _radius * math.sin(math.radians(_angle)))
]

def intPos(_pos):
return [int(_pos[0]), int(_pos[1])]

# swaps a boolean
def boolSwap(_bool):
if _bool:
return False
else:
return True

# point class
class point():
# init
def __init__(self, _startPos):
self.startPos = _startPos
self.pos = self.startPos[:]
self.destination = self.pos[:]

# tick
def tick(self):
# changes destination every 100 ticks
if main.TICKS % 100 == 0:
self.destination = [random.randint(0, main.WIDTH), random.randint(0, main.HEIGHT)]

# calculate distance to destination (for smooth movement)
dist = [
self.destination[0] - self.pos[0],
self.destination[1] - self.pos[1]
]
# move to destination (/ 5.0 defines the speed)
self.pos[0] += dist[0] / 5.0
self.pos[1] += dist[1] / 5.0

# tick function
def tick():
# handle events
for event in pygame.event.get():
# quit
if event.type == pygame.QUIT:
sys.exit()

# keyup
if event.type == pygame.KEYUP:
# handle 'main.KEYSDOWN'
if event.key in main.KEYSDOWN:
main.KEYSDOWN.remove(event.key)

# keydown
if event.type == pygame.KEYDOWN:
# handle 'main.KEYSDOWN'
if event.key not in main.KEYSDOWN:
main.KEYSDOWN.append(event.key)

# mousebuttondown
if event.type == pygame.MOUSEBUTTONDOWN:
# add point
if event.button == 1:
main.POINTS.append(point(getMousePos()))

# remove point
elif event.button == 3:
if len(main.POINTS) > 1:
main.POINTS.pop(-1)

# tick all points
for _ in main.POINTS:
_.tick()

# render function
def render():
# fill
main.SCREEN.fill(main.BACKGROUNDCOLOR)
if main.FILL:
main.SURF.fill(main.COLOR)

# renders all the points
thick = 10
last = None
polCol = [
colorValid(main.TICKS / 1., 50, 100),
colorValid(main.TICKS / 1., 50, 100),
colorValid(main.TICKS / 1., 50, 100)
]

# render polygon
if len(main.POINTS) > 2:
p = []
for _ in main.POINTS:
p.append(_.pos)
pygame.draw.polygon(main.SURF, polCol, p)

# render points and connections
for _ in main.POINTS:
pygame.draw.circle(main.SURF, [0, 0, 0], intPos(_.pos), thick)
if last != None:
pygame.draw.line(main.SURF, [0, 0, 0], last, _.pos, thick)
last = _.pos[:]

# render last connection (first point to last point)
if len(main.POINTS) > 1:
pygame.draw.line(main.SURF, [0, 0, 0], main.POINTS[0].pos, last, thick)

# blit and flip
main.SCREEN.blit(pygame.transform.scale(main.SURF, [int(main.WIDTH * main.SCALE), int(main.HEIGHT * main.SCALE)]), [0, 0])
pygame.display.flip()

# run function (uses tick() and render())
def run():
ticksPerSecond = 60
lastTime = time.time() * 1000000000
nsPerTick =  1000000000.0 / float(ticksPerSecond)

ticks = 0
frames = 0

lastTimer = time.time() * 1000
delta = 0.0

while True:
now = time.time() * 1000000000
delta += float(now - lastTime) / float(nsPerTick)
lastTime = now
shouldRender = False

while delta >= 1:
ticks += 1
main.TICKS += 1
tick()
delta -= 1
shouldRender = True

if shouldRender:
frames += 1
render()

if time.time() * 1000 - lastTimer >= 1000:
lastTimer += 1000

# debug
#print("Frames: " + str(frames) + ", ticks: " + str(ticks))

frames = 0
ticks = 0

# dummy class for global variables
class dummy():
pass

# importing needed modules
import pygame, sys, time, math, os, random

# main dummy
main = dummy()
main.TICKS = 0

main.RES = 1
main.WIDTH = 1080 / main.RES
main.HEIGHT = 720 / main.RES
main.SIZE = [main.WIDTH, main.HEIGHT]
main.CENTER = [main.WIDTH / 2, main.HEIGHT / 2]
main.CENTERFLOAT = [main.WIDTH / 2.0, main.HEIGHT / 2.0]

main.SCALE = 1 * main.RES
main.SCALEDSIZE = [int(main.WIDTH * main.SCALE), int(main.HEIGHT * main.SCALE)]
main.SCALEDSIZEFLOAT = [main.WIDTH * main.SCALE, main.HEIGHT * main.SCALE]

main.SURF = pygame.Surface(main.SIZE)

main.SCREEN = pygame.display.set_mode(main.SCALEDSIZE)
pygame.display.set_caption("shaper")

main.BACKGROUNDCOLOR = [0, 0, 0]
main.COLOR = [150, 0, 0]
main.FILL = True

main.KEYSDOWN = []
main.POINTS = [point(main.CENTERFLOAT[:])]

# start program
run()``````
Advertisements

This site uses Akismet to reduce spam. Learn how your comment data is processed.