Sand

This program lets you watch grains of sand fall. The grains shift in color, according to the color algorithm assigned. You also can build bridges to change the sand’s falling behavior.

Controls

  • Left clicking spawns in new grains of sand
  • Right clicking draws a bridge
  • Space saves a screenshot

Black and white piles Differently shaded piles A randomly colored pile


# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 4th of October

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

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

""" FUNCTIONS """
# gets the mouse position
def mousepos():
	p = pygame.mouse.get_pos()
	return [p[0] / main.SCALEX, p[1] / main.SCALEY]

# 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 $gt; n:
		if int(newColor / n) % 2 == 0:
			newColor = newColor % n
		else:
			newColor = n - (newColor % n)
	
	return int(newColor) + _min

# quits the program
def quit():
	sys.exit()

""" TICK; RENDER """
# tick function
def tick():
	# handle events
	for event in pygame.event.get():
		# quit
		if event.type == pygame.QUIT:
			quit()
		
		# keydown
		if event.type == pygame.KEYDOWN:
			if pygame.K_SPACE:
				try:
					path = os.getcwd() + "/out/"
					if not os.path.exists(path):
						os.mkdir(path)

					pygame.image.save(main.SURF2, path + "img" + str(len(os.listdir(path))) + ".png")
				except:
					pass

		if event.type == pygame.MOUSEBUTTONUP:
			main.LAST = None

	p = mousepos()
	x, y = p[0], p[1]
	if pygame.mouse.get_pressed()[0]:
		for _ in range(0, 10):
			#c = [255, 255, 255]
			#c = [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]
			#c = [colorValid(main.GRAINCOUNT/10), colorValid(main.GRAINCOUNT/100), colorValid(main.GRAINCOUNT/200)]
			c = [0, colorValid(main.GRAINCOUNT/100, 50), 0]
			#C = colorValid(main.GRAINCOUNT, 50);c = [C, C, C]
			main.GRAINS.append([[x + random.randint(-10, 10), y + random.randint(-10, 10)], c])
			main.GRAINCOUNT += 1

	if pygame.mouse.get_pressed()[2]:
		if main.LAST != None:
			pygame.draw.line(main.SURF, [50, 50, 50], main.LAST, p)
		main.LAST = p

	for _ in range(0, 10):
		for _ in main.GRAINS:
			if _[0][1] $gt;= 0 and _[0][1] $lt; main.HEIGHT - 1 and _[0][0] $gt; 0 and _[0][0] $lt; main.WIDTH-1:
				if main.SURF.get_at([_[0][0], _[0][1] + 1]) == (0, 0, 0, 255):
					_[0][1] += 1
				elif _[0][0] $gt; 0 and main.SURF.get_at([_[0][0] - 1, _[0][1]]) == (0, 0, 0, 255) and main.SURF.get_at([_[0][0] - 1, _[0][1] + 1]) == (0, 0, 0, 255):
					_[0][0] -= 1
				elif _[0][0] $lt; main.WIDTH-1 and main.SURF.get_at([_[0][0] + 1, _[0][1]]) == (0, 0, 0, 255) and main.SURF.get_at([_[0][0] + 1, _[0][1] + 1]) == (0, 0, 0, 255):
					_[0][0] += 1
				else:
					main.SURF.set_at(_[0], _[1])
					main.GRAINS.remove(_)
			else:
				main.SURF.set_at(_[0], _[1])
				main.GRAINS.remove(_)


# render function
def render():
	# blit and flip
	main.SURF2.blit(main.SURF, [0, 0])

	for _ in main.GRAINS:
		main.SURF2.set_at(_[0], _[1])

	main.SCREEN.blit(pygame.transform.scale(main.SURF2, main.SCREENSIZE), [0, 0])
	pygame.display.flip()

""" INIT """
# initialize program
def init():
	main.SCREENWIDTH, main.SCREENHEIGHT = 1080, 720
	main.SCREENSIZE = [main.SCREENWIDTH, main.SCREENHEIGHT]
	main.SCREEN = pygame.display.set_mode(main.SCREENSIZE)

	main.WIDTH, main.HEIGHT = 1080, 720
	main.SIZE = [main.WIDTH, main.HEIGHT]
	main.SURF = pygame.Surface(main.SIZE)
	main.SURF2 = pygame.Surface(main.SIZE)
	
	main.SCALEX, main.SCALEY = main.SCREENWIDTH / main.WIDTH, main.SCREENHEIGHT / main.HEIGHT

	main.CAPTION = "Sand"
	main.TICKS = 0

	main.GRAINS = []
	main.GRAINCOUNT = 0
	main.LAST = None
	
	# functions
	pygame.display.set_caption(main.CAPTION)

""" RUN """
# 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 $gt;= 1:
			ticks += 1
			main.TICKS += 1
			tick()
			delta -= 1
			shouldRender = True
		
		if shouldRender:
			frames += 1
			render()
		
		if time.time() * 1000 - lastTimer $gt;= 1000:
			lastTimer += 1000
			
			# debug
			# print("Frames: " + str(frames) + ", ticks: " + str(ticks))
			
			frames = 0
			ticks = 0

# main variable
main = dummy()
init()

# 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