Jimon

This game is a recreation of the famous game Simon. In the game there are four colors which form a sequence that is expanding every cycle. The aim of the game is to memorize said sequence as far as possible.
For more information on the Simon game visit this Wikipedia entry.

Controls

  • Click on the colored buttons to press them

The first example The second example The third example


# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 24th of June, 2016

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

""" CLASSES """
class Screen():
	def __init__(self):
		pass

	def swap(self):
		pass

	def render(self, surface):
		pass

	def tick(self):
		pass

	def handle(self, event):
		pass

class Button():
	def __init__(self, pos, color):
		self.pos = pos
		self.color = [0, 0, 0]
		self.destcolor = color

	def render(self, surface):
		pygame.draw.rect(surface, self.color, [self.pos[0], self.pos[1], 200, 200])

	def tick(self):
		for _ in [0, 1, 2]:
			self.color[_] += (self.destcolor[_] - self.color[_]) / 15.

	def activate(self):
		self.color = [255, 255, 255]

	def pressed(self, pos):
		if pos[0] >= self.pos[0] and pos[0] <= self.pos[0] + 200: if pos[1] >= self.pos[1] and pos[1] <= self.pos[1] + 200:
				return True

		return False

# game screeb
class mainScreen(Screen):
	def __init__(self):
		Screen.__init__(self)

		self.buttons = [
			Button([20, 20], [0, 255, 0]),
			Button([20+200+20, 20], [255, 0, 0]),
			Button([20, 20+200+20], [255, 255, 0]),
			Button([20+200+20, 20+200+20], [0, 0, 255])
		]

		self.reset()

	# reset game
	def reset(self):
		self.score = -1
		self.canclick = False
		self.sequence = []
		self.success = True

		self.showindex = 0
		self.showtimer = 20

		self.index = 0

		for b in self.buttons:
			b.color = [0, 0, 0]

	# tick
	def tick(self):
		# extend sequence and reset
		if self.success:
			self.score += 1
			self.canclick = False
			self.sequence.append(random.randint(0, 3))
			self.showindex = 0
			self.showtimer = 20
			self.success = False
			self.index = 0
		
		self.showtimer -= 1

		# activate a button
		if self.showtimer <= 0 and not self.canclick: self.showtimer = 20 if self.showindex + 1 > len(self.sequence):
				self.canclick = True
			else:
				self.buttons[self.sequence[self.showindex]].activate()

			self.showindex += 1

		for b in self.buttons:
			b.tick()

	# handle
	def handle(self, event):
		if self.canclick:
			if event.type == pygame.MOUSEBUTTONDOWN:
				if event.button == 1:
					w = -1
					for b in self.buttons:
						w += 1
						if b.pressed(pygame.mouse.get_pos()):
							b.activate()


							if self.sequence[self.index] == w:
								
								self.index += 1
								if self.index + 1 > len(self.sequence):
									self.success = True
									
							else:
								self.reset()

	# render
	def render(self, surface):
		# render buttons
		for b in self.buttons:
			b.render(surface)

		# blit score
		s = segment7(self.score)
		r = s.get_rect()
		s = pygame.transform.scale(s, [r.right*10, r.bottom*10])
		r = s.get_rect()
		surface.blit(s, [(400 + 20*3 - r.right)/2, 400 + 20*3])

""" THREADS """
# thread class
class Thread(threading.Thread):
	def __init__(self):
		# init thread
		threading.Thread.__init__(self)
		
		# deamon thread
		#self.daemon = True

	# run function
	def run(self):
		pass

""" FUNCTIONS """
# validates a color integer
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
def getcirclepos(p, r, phi):
	return [p[0] + r * math.cos(phi * (math.pi/180.)), p[1] + r * math.sin(phi * (math.pi/180.))]

# returns an integer version of given position
def intpos(_pos):
	return [int(_pos[0]), int(_pos[1])]

# turn a number into 7-segment font
def segment7(number):
	number = str(number)

	segments = [
		[[1, 0], [2, 0]],
		[[3, 1], [3, 2]],
		[[3, 4], [3, 5]],
		[[1, 6], [2, 6]],
		[[0, 4], [0, 5]],
		[[0, 1], [0, 2]],
		[[1, 3], [2, 3]]
	]

	numbers = [
		[0, 1, 2, 3, 4, 5],
		[1, 2],
		[0, 1, 6, 4, 3],
		[0, 1, 6, 2, 3],
		[5, 6, 1, 2],
		[0, 5, 6, 2, 3],
		[0, 5, 6, 2, 3, 4],
		[0, 1, 2],
		[0, 1, 2, 3, 4, 5, 6],
		[0, 1, 6, 5, 2, 3]
	]

	surface = pygame.Surface([5*len(number)-1, 7])
	x = 0
	for digit in str(number):
		for n in numbers[int(digit)]:
			for s in segments[n]:
				surface.set_at([s[0] + x, s[1]], [255, 255, 255])

		x += 5

	return surface

""" GAME """
# game class
class Game():
	def __init__(self):
		# screen (class)
		self.screenname = "main"
		self.screens = {
			"main": mainScreen()
		}

		# screen (window)
		n = 400 + 20*3
		self.Width, self.Height = n, n + 100
		self.Size = [self.Width, self.Height]
		self.Screen = pygame.display.set_mode(self.Size)

		# running variables
		self.ticks = 0
		self.running = True

		# functions
		pygame.display.set_caption("Jimon")
	
	# further initialization
	def init(self):
		pass

	# get the screen based on name
	def screen(self):
		if self.screenname in self.screens:
			return self.screens[self.screenname]
		else:
			return Screen()

	# swao the current screen
	def swapscreen(self, name = ""):
		self.screenname = name
		self.screen().swap()

	# tick function
	def tick(self):
		# handle events
		for event in pygame.event.get():
			
			# quit when window is closed
			if event.type == pygame.QUIT:
				self.quit()

			# handle key presses
			if event.type == pygame.KEYDOWN:
				# F12 quits
				if event.key == pygame.K_F12:
					self.quit()

				# F1 screenshots
				if event.key == pygame.K_F1:
					self.screenshot()

			# handle screen
			self.screen().handle(event)

		# tick screen
		self.screen().tick()

	# render function
	def render(self):
		# fill
		self.Screen.fill([0, 0, 0])
		
		#render screen
		self.screen().render(self.Screen)
		
		# flip
		pygame.display.flip()
	
	# quits
	def quit(self):
		self.running = False

	# takes a screenshot
	def screenshot(self):
		# define path
		path = os.getcwd() + "/out/"
		
		# try to save
		try:
			# create path
			if not os.path.isdir(path):
				os.mkdir(path)
			
			# define name
			name = "img" + str(len(os.listdir(path))) + ".png"

			# save image
			pygame.image.save(self.Screen, path + name)
		
		# save failed somehow
		except:
			pass

	# run function (uses tick() and render())
	def run(self):
		ticksPerSecond = 60
		lastTime = time.time() * 1000000000
		nsPerTick =  1000000000.0 / float(ticksPerSecond)
	
		ticks = 0
		frames = 0
	
		lastTimer = time.time() * 1000
		delta = 0.0
		
		while self.running:
			now = time.time() * 1000000000
			delta += float(now - lastTime) / float(nsPerTick)
			lastTime = now
			shouldRender = False
					
			while delta >= 1:
				ticks += 1
				self.ticks += 1
				self.tick()
				delta -= 1
				shouldRender = True
			
			if shouldRender:
				frames += 1
				self.render()
			
			if time.time() * 1000 - lastTimer >= 1000:
				lastTimer += 1000
			
				frames = 0
				ticks = 0

# start game
G = Game()
G.init()
G.run()
Advertisements

One thought on “Jimon

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