Jeakout

Continuing with my arcade game replicas, I programmed Breakout.
This version is fairly simple. Your lives will be displayed at the lower right corner, your points in the screen’s caption. There also is a computer implementation, which – as in Jong – cannot lose.

Usage

  • Left arrow key moves the hitter to the left
  • Right arrow key moves the hitter to the right
  • Space toggles computer play

Computer at its play Fresh game Somebody lost...


# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 14th of June, 2015
#         edited 27th of July, 2015

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

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

# ball class
class ball():
	def __init__(self, _startpos):
		self.startpos = _startpos
		self.color = [0, 255, 0]
		
		self.respawn()
	
	# respawns the ball
	def respawn(self):
		self.pos = self.startpos[:]
		if random.randint(0, 1) == 0:
			self.velocity = [-1, -1]
		else:
			self.velocity = [1, -1]
		self.respawntime = 20
	
	# tick
	def tick(self):
		if self.respawntime <= 0:
			# swap velocity
			if self.pos[0] <= 0: 				self.velocity[0] *= -1 			if self.pos[0] >= main.WIDTH - 1:
				self.velocity[0] *= -1
			
			if self.pos[1] <= 0: 				self.velocity[1] *= -1 			if self.pos[1] >= main.HEIGHT - 1:
				self.velocity[1] *= -1
				self.respawn()
				return False
			
			# check for bricks
			for dim in range(0, 2):
				for _ in main.BRICKS:
					if not _.touched:
						if _.pos[not dim] == self.pos[not dim]:
							if self.pos[dim] + self.velocity[dim] == _.pos[dim]:
								self.velocity[dim] *= -1
								_.touch()
				
				if dim == 0:
					if self.pos[1] == main.HITTER.pos[1]:
						if self.pos[0] + self.velocity[0] >= main.HITTER.pos[0] and self.pos[0] + self.velocity[0] <= main.HITTER.pos[0] + main.HITTER.size - 1: 							self.velocity[0] *= -1 				 				elif dim == 1: 					if self.pos[0] >= main.HITTER.pos[0] and self.pos[0] <= main.HITTER.pos[0] + main.HITTER.size - 1: 						if self.pos[1] + self.velocity[1] == main.HITTER.pos[1]: 							self.velocity[1] *= -1 			 				self.pos[dim] += self.velocity[dim] 		 		else: 			self.respawntime -= 1 		 		return True 	 	# render 	def render(self, _surface): 		_surface.set_at(self.pos, self.color) # brick class class brick(): 	def __init__(self, _pos, _color): 		self.pos = _pos 		self.color = _color 		 		self.touched = False 	 	def render(self, _surface): 		_surface.set_at(self.pos, self.color) 	 	# if brick gets touched 	def touch(self): 		self.touched = True 		main.POINTS += 1 		 		if main.POINTS == 1: 			pygame.display.set_caption(main.CAPTION + " (" + str(main.POINTS) + " point)") 		else: 			pygame.display.set_caption(main.CAPTION + " (" + str(main.POINTS) + " points)") # hitter class class hitter(): 	def __init__(self, _pos): 		self.pos = _pos 		self.color = [255, 0, 0] 		self.size = 15 	 	# tick 	def tick(self): 		if main.COM: 			if self.pos[0] + self.size/2 > main.BALL.pos[0]:
				self.pos[0] -= 1
			elif self.pos[0] + self.size/2 < main.BALL.pos[0]:
				self.pos[0] += 1
		else:
			# move hitter
			if pygame.K_LEFT in main.KEYSDOWN:
				self.pos[0] -= 1
			if pygame.K_RIGHT in main.KEYSDOWN:
				self.pos[0] += 1
		
		# fix pos
		if self.pos[0] < 0: 			self.pos[0] = 0 		if self.pos[0] + self.size - 1 > main.WIDTH-1:
			self.pos[0] = main.WIDTH - self.size
		
	def render(self, _surface):
		pygame.draw.line(_surface, self.color, self.pos, [self.pos[0] + self.size - 1, self.pos[1]])

""" FUNCTIONS """
# 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

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

# restarts the game
def restart():
	main.BALL = ball(main.CENTER)
	main.HITTER = hitter([0, main.HEIGHT - 4])
	main.BRICKS = []
	for y in range(0, 5):
		for x in range(0, main.WIDTH):
			c = [
				colorValid( 255. / 5 * y ),
				0,
				255 / 2
			]
			main.BRICKS.append(brick([x, y], c))
	
	main.POINTS = 0
	main.LIVES = 3
	main.GAMEOVER = False
	main.GAMEOVERVISTICKS = -1
	
	# set cpation
	pygame.display.set_caption(main.CAPTION)


""" TICK; RENDER """
# tick function
def tick():
	# handle events
	for event in pygame.event.get():
		# quit
		if event.type == pygame.QUIT:
			quit()
		
		# 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)
			
			# restart game
			if event.key == pygame.K_ESCAPE:
				restart()
			
			# toggle COM
			if event.key == pygame.K_SPACE:
				main.COM = not main.COM
	
	# game tick
	if not main.GAMEOVER:
		main.HITTER.tick()
		if not main.BALL.tick():
			main.LIVES -= 1
		
		# remove touched bricks
		for _ in main.BRICKS:
			if _.touched:
				main.BRICKS.remove(_)
		
		# gameover...
		if main.LIVES < 0: 			main.GAMEOVER = True 		 # render function def render(): 	# gameover rendering 	if main.GAMEOVER: 		#main.SURF.set_at([random.randint(0, main.WIDTH - 1), random.randint(0, main.HEIGHT - 1)], [0, 0, 0]) 		 		main.GAMEOVERVISTICKS += 2 		pygame.draw.line(main.SURF, [0, 0, 0], [0, main.GAMEOVERVISTICKS], [main.GAMEOVERVISTICKS, 0]) 	 	# normal rendering 	else: 		main.SURF.fill(main.COLOR) 		 		for _ in main.BRICKS: 			_.render(main.SURF) 		main.HITTER.render(main.SURF) 		main.BALL.render(main.SURF) 		 		for _ in range(0, main.LIVES): 			main.SURF.set_at([main.WIDTH - 2 - _*2, main.HEIGHT - 2], main.BALL.color) 		 	# blit and flip 	main.SCREEN.blit(pygame.transform.scale(main.SURF, main.SCALEDSIZE), [0, 0]) 	pygame.display.flip() """ INIT """ # initialize program def init(): 	main.WIDTH, main.HEIGHT = 1080/10, 720/10 	main.SIZE = [main.WIDTH, main.HEIGHT] 	main.CENTER = [main.WIDTH / 2, main.HEIGHT / 2] 	main.SURF = pygame.Surface(main.SIZE) 	 	main.SCALEDSIZE = [1080, 720] 	main.SCREEN = pygame.display.set_mode(main.SCALEDSIZE) 	 	main.CAPTION = "Jeakout" 	main.COLOR = [50, 50, 50] 	main.TICKS = 0 	main.KEYSDOWN = [] 	 	main.COM = False 	 	# functions 	restart() """ 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 >= 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

# 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