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

The First ExampleThe Second ExampleThe Third Example


# 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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s