Commits

Flaise  committed c407892

Added vertical camera scrolling, map loading, and an attempt at procedural map
generation.

  • Participants
  • Parent commits 0659ba3

Comments (0)

Files changed (3)

File roguelike/Tree Ugly.png

Added
New image

File roguelike/main.py

 import random
 
 
-
 ######################################################################## engine
 
 def get_stick(joy, axisX, axisY):
 		
 		callback(event)
 	
-	def remove():
+	def remove(): ### TODO: Use linked list
 		nonlocal removed
-		
 		if removed: return
 		removed = True
-		#raise Exception('on_event()~~>remove() not implemented')
-		### This requires a linked list or something similar
 		
-		#event_handlers[index] = None
 		next_event_handlers.remove(handler)
 	
 	handler = (predicate, invoke)
-	#index = len(event_handlers)
 	next_event_handlers.append(handler)
 	return remove
 
 	stop = on_event(predicate, lambda a: (callback(a), stop()))
 
 
-
-
-
-
-
-
-
 ########################################################################### app
 
 pygame.init()
 	#| pygame.DOUBLEBUF
 	#| pygame.HWSURFACE
 )
-pygame.display.set_caption('Roguelike v0.0.4')
+pygame.display.set_caption('Roguelike v0.0.5')
 
 
 class AppEvent:
-	#NORTH, EAST, SOUTH, WEST,
 	INPUT_DIRECTION, BLOCK_MOVED = range(1000, 1002)
 class Direction:
 	NORTH, EAST, SOUTH, WEST = range(4)
 
-#on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_UP, lambda a: proc_event(pygame.event.Event(AppEvent.NORTH)))
-#on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_DOWN, lambda a: proc_event(pygame.event.Event(AppEvent.SOUTH)))
-#on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_RIGHT, lambda a: proc_event(pygame.event.Event(AppEvent.EAST)))
-#on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_LEFT, lambda a: proc_event(pygame.event.Event(AppEvent.WEST)))
-
 on_event(
 	lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_UP,
 	lambda a: proc_event(pygame.event.Event(AppEvent.INPUT_DIRECTION, direction=Direction.NORTH))
 
 
 
-#camera = (0, 0, 6, 4) # (left, top, width, height)
-camera = (0, 0, 7) # (centerX, centerY, height) ~~~ width depends on screen
-def move_camera(delta):
+camera = ((0, 0, 0), 7) # ((x, y, z), view_height) ~~~ width depends on screen
+#def move_camera(delta):
+#	global camera
+#	camera = (sum3d(camera[0], delta), camera[1])
+### not used? ^
+
+def move_camera_to(dest):
+	if len(dest) != 3: raise Exception() 
 	global camera
-	camera = (camera[0] + delta[0], camera[1] + delta[1], camera[2])
-def move_camera_to(dest):
-	global camera
-	camera = (dest[0], dest[1], camera[2])
-def zoom_camera(delta):
-	global camera
-	camera = (camera[0], camera[1], max(1, camera[2] + delta))
+	camera = (dest, camera[1])
+#def zoom_camera(delta):
+#	global camera
+#	camera = (camera[0], max(1, camera[1] + delta))
 
 
 blocks = [] # contains: ((x, y, z), tile)
 	blocks.sort(key=lambda a: a[0][2] * 10000 + a[0][1] + a[1][4] + (100000000 if a[1][5] else 0))
 	position_to_blocklist.clear()
 	for block in blocks:
-		#position_to_blocklist[block[0]] = block
-		if block[0] not in position_to_blocklist:
-			position_to_blocklist[block[0]] = []
-		position_to_blocklist[block[0]].append(block)
+		position = block[0]
+		if position not in position_to_blocklist:
+			position_to_blocklist[position] = []
+		position_to_blocklist[position].append(block)
 
-"""def remove_block_at(position):
-	global blocks
-	for i, block in enumerate(blocks):
-		if block[0] == position:
-			blocks = blocks[:i] + blocks[i + 1:]
-			break
-	del position_to_blocklist[position]
-	#blocks.remove(value)
-"""
 def remove_block(block):
 	position_to_blocklist[block[0]].remove(block)
+	if len(position_to_blocklist[block[0]]) == 0:
+		del position_to_blocklist[block[0]]
 	blocks.remove(block)
 	proc_event(pygame.event.Event(AppEvent.BLOCK_MOVED, block=block, dest=None))
 	
 		
 		question = make_block(block[0], tile_question, BlockType.SPEECH)
 		on_event_once(lambda a: a.type == AppEvent.INPUT_DIRECTION, lambda a: remove_block(question))
-		#stop = on_event(
-		#	lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block,
-		#	lambda a: ( remove_block(bubble), stop() )
-		#)
 	
 	dest = sum3d(block[0], delta)
 	above = sum3d(dest, (0, 1, 0))
 
 def can_bug_move(block, delta):
 	if len(list(get_blocks_at(sum3d(block[0], (0, 1, 0))))) > 0: # something on top, usually another bug
-		return False # let it move off first so odd behavior doesn't commence
+		return False # let other bug move off first so odd behavior doesn't commence
 	
 	def is_obstacle(block_type):
 		return block_type in (BlockType.PLAYER, BlockType.BUG, BlockType.ROCK, BlockType.TREE, BlockType.FILLER)
 			return False
 	
 def move_bug(block, delta):
-	"""def is_obstacle_type(block_type):
-		return block_type in (BlockType.PLAYER, BlockType.BUG, BlockType.ROCK, BlockType.TREE, BlockType.FILLER)
-	def is_obstacle_at(position):
-		return len([x for x in get_block_types_at(position) if is_obstacle_type(x)]) > 0
-	
-	dest = sum3d(block[0], delta)
-	
-	if is_obstacle_at(dest):
-		return
-	else:
-		below = sum3d(dest, (0, -1, 0))
-		
-		for other_block in get_blocks_at(below):
-			block_type = other_block[2]
-			
-			if block_type in (BlockType.FILLER, BlockType.ROCK, BlockType.BUG):
-				move_block(block, delta)
-			elif not is_obstacle_type(block_type):
-				continue
-			return"""
 	if can_bug_move(block, delta):
 		move_block(block, delta)
 
 def ai_bug(block):
 	if block[2] == BlockType.BUG_DEAD: return
-	#move_bug(block, random.choice(((1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 0, -1))))
 	
 	options = [x for x in ((1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 0, -1)) if can_bug_move(block, x)]
 	if len(options) > 0:
 		move_bug(block, random.choice(options))
 
 
-def center_camera_on_block(block):
-	move_camera_to((block[0][0], block[0][2]))
-on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, lambda a: center_camera_on_block(block_player))
+#def center_camera_on_block(block):
+#	move_camera_to(block[0])
+def center_camera_on_player():
+	move_camera_to(sum3d(block_player[0], (0, -1, 0)))
+on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, lambda a: center_camera_on_player())
 
 
 TILE_W = 1
 tile_bug_dead = (pygame.image.load('Enemy Bug Squished.png').convert_alpha(), (50, 90), 100, False, -1, False)
 tile_speech = (pygame.image.load('SpeechBubble.png').convert_alpha(), (-35, 190), 100, False, 0, True)
 tile_wood = (pygame.image.load('Wood Block.png').convert_alpha(), (50, 90), 100, True, 0, False)
-tile_question = (pygame.image.load('Question.png').convert_alpha(), (-35, 190), 100, False, 1, True)
+tile_question = (pygame.image.load('Question.png').convert_alpha(), (-35, 190), 100, False, 1, True) ### Uses font Palatino Linotype
+tile_bush_0 = (pygame.image.load('Tree Short.png').convert_alpha(), (50, 90), 100, False, 0, False)
+tile_bush_1 = (pygame.image.load('Tree Ugly.png').convert_alpha(), (50, 90), 100, False, 0, False)
 
 shadow_e = (pygame.image.load('Shadow East.png'), (50, 90), 100)
 shadow_w = (pygame.image.load('Shadow West.png'), (50, 90), 100)
 	PLAYER, BUG, ROCK, TREE, FILLER, BUG_DEAD, SPEECH = range(7)
 
 def make_block(position, tile, block_type):
+	if len(position) != 3: raise Exception()
 	block = [position, tile, block_type]
 	blocks.append(block)
 	update_blocks()
 	return block
 
 
+"""###
 blocks.append([(1, 1, 2), tile_gray, BlockType.FILLER])
 blocks.append([(1, 1, 1), tile_gray, BlockType.FILLER])
 blocks.append([(1, 0, 1), tile_gray, BlockType.FILLER])
 blocks.append([(2, 0, 2), tile_dirt, BlockType.FILLER])
 blocks.append([(2, 1, 1), tile_grass, BlockType.FILLER])
 blocks.append([(2, 1, 2), tile_grass, BlockType.FILLER])
-#blocks.append([(1, 0, 3), tile_grass, BlockType.FILLER])
-#blocks.append([(1, 0, 4), tile_water, BlockType.FILLER])
-#blocks.append([(0, 0, 4), tile_water, BlockType.FILLER])
-#blocks.append([(1, 0, 5), tile_dirt, BlockType.FILLER])
-#blocks.append([(0, -1, 5), tile_dirt, BlockType.FILLER])
 blocks.append([(0, 0, -2), tile_dirt, BlockType.FILLER])
 blocks.append([(0, 0, 2), tile_dirt, BlockType.FILLER])
 blocks.append([(0, 1, 0), tile_rock, BlockType.ROCK])
 on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, lambda a: ai_bug(block_bug_2))
 
 update_blocks()
+###"""
 
+block_player = None
+def make_player(position):
+	global block_player
+	block_player = make_block(position, tile_player, BlockType.PLAYER)
+	center_camera_on_player()
+
+def make_bug(position):
+	block = make_block(position, tile_bug, BlockType.BUG)
+	on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, lambda a: ai_bug(block))
+	### TODO: Remove event binding when bug-death event fires
+	
+	
+def make_grass(position):
+	make_block(position, tile_grass, BlockType.FILLER)
+def make_stone(position):
+	make_block(position, tile_gray, BlockType.FILLER)
+def make_boulder(position):
+	make_block(position, tile_rock, BlockType.ROCK)
+def make_tree(position):
+	make_block(position, tile_tree, BlockType.TREE)
+def make_bush_0(position):
+	make_block(position, tile_bush_0, BlockType.TREE)
+def make_bush_1(position):
+	make_block(position, tile_bush_1, BlockType.TREE)
+def make_wood_floor(position):
+	make_block(position, tile_wood, BlockType.FILLER)
+def make_water(position):
+	make_block(position, tile_water, BlockType.FILLER)
+def make_dirt(position):
+	make_block(position, tile_dirt, BlockType.FILLER)
+
+"""###
+def generate_column(xz, player_spawn):
+	def get_blocks_in_column(xz):
+		#for block in blocks:
+		#	if block[0][0] == xz[0] and block[0][2] == xz[1]:
+		#		yield block
+		
+		#for block in [x for x in blocks if x[0][0] == xz[0] and x[0][2] == xz[1]]:
+		#	yield block
+		return [x for x in blocks if x[0][0] == xz[0] and x[0][2] == xz[1]]
+				
+	def get_highest_filler_in_column(xz):
+		highest = None
+		for block in get_blocks_in_column(xz):
+			if block[1] != BlockType.FILLER: continue
+			if highest == None or block[0][1] > highest[0][1]:
+				highest = block
+		return highest
+	
+	def get_all_nearby_heights():
+		heights = []
+		for other_col in ((1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (1, -1), (-1, 1), (-1, -1)):
+			highest = get_highest_filler_in_column(sum2d(xz, other_col))
+			if highest != None:
+				heights.append(highest[0][1])
+		return heights
+	
+	def get_average_nearby_height():
+		heights = get_all_nearby_heights()
+		if len(heights) == 0: return 0
+		
+		average = 0
+		for i in heights:
+			average += i
+		average /= len(heights)
+		return round(average)
+	
+	def get_lowest_nearby_height():
+		heights = get_all_nearby_heights()
+		if len(heights) == 0: return 0
+		
+		lowest = None
+		for height in heights:
+			if lowest == None or height < lowest:
+				lowest = height
+		
+		average = 0
+		for i in heights:
+			average += i
+		average /= len(heights)
+		return round(average)
+	
+	next_position = (xz[0], get_average_nearby_height() + random.choice([0, 0, -1, 1]), xz[1])
+	def advance_position():
+		nonlocal next_position
+		next_position = sum3d(next_position, (0, -1, 0))
+	def prevance_position(): ### for surface objects that aren't fillers
+		nonlocal next_position
+		next_position = sum3d(next_position, (0, 1, 0))
+	
+	def make_player():
+		global block_player
+		block_player = make_block(next_position, tile_player, BlockType.PLAYER)
+		center_camera_on_block(block_player)
+		advance_position()
+	def make_rock():
+		make_block(next_position, tile_rock, BlockType.ROCK)
+		advance_position()
+		make_block(next_position, random.choice([tile_grass, tile_dirt, tile_gray]), BlockType.FILLER)
+		advance_position()
+	def make_tree():
+		make_block(next_position, random.choice([tile_tree, tile_bush_0, tile_bush_1]), BlockType.TREE)
+		advance_position()
+		make_block(next_position, random.choice([tile_grass, tile_dirt]), BlockType.FILLER)
+		advance_position()
+	def make_filler():
+		make_block(next_position, random.choice([tile_wood, tile_grass, tile_dirt, tile_gray]), BlockType.FILLER)
+		advance_position()
+	
+	def make_passable_surface():
+		random.choice([make_rock, make_filler, make_filler])()
+	def make_any_surface():
+		random.choice([make_rock, make_tree, make_filler, make_filler, make_filler, make_filler])()
+	
+	
+	if player_spawn:
+		if random.choice([True, False, False, False]):
+			prevance_position()
+			prevance_position()
+			make_player()
+			make_rock()
+			make_filler()
+		else:
+			prevance_position()
+			make_player()
+			make_filler()
+	else:
+		#make_any_surface()
+		if random.choice([True, False, False, False, False]):
+			prevance_position()
+			random.choice([make_rock, make_tree, make_tree])()
+			make_filler()
+		else:
+			make_filler()
+	
+	lowest = get_lowest_nearby_height()
+	while lowest != None and lowest < next_position[1]:
+		make_filler()
+	
+	make_filler()
+	make_filler()
+	make_filler()
+###"""
+
+"""generate_column((0, 0), True)
+generate_column((1, 0), False)
+generate_column((1, -1), False)
+generate_column((1, 1), False)
+generate_column((-1, 0), False)
+generate_column((-1, -1), False)
+generate_column((-1, 1), False)
+generate_column((0, 1), False)
+generate_column((0, -1), False)"""
+
+#for x in range(-4, 5):
+#	for z in range(-4, 5):
+#		generate_column((x, z), ((x, z) == (0, 0)))
 
 
 scale_cache = {} # { surface: ((x, y), result_surface) }
 	tile_surface = tile[0]
 	tile_reg_width = tile[2]
 	
-	scale_world2screen = surface_screen.get_height() / (camera[2] * TILE_L)
+	scale_world2screen = surface_screen.get_height() / (camera[1] * TILE_L)
 	scale_image2tile = tile_surface.get_width() / tile_reg_width
 	
 	dest_w = scale_world2screen * scale_image2tile
 			sum2d(
 				### camera position
 				scale2d(
-					(TILE_W * (-camera[0]), TILE_L * (-camera[1] )), 
+					(TILE_W * -camera[0][0], TILE_H * camera[0][1] - TILE_L * camera[0][2]), 
 					scale_world2screen
 				),
 				(surface_screen.get_width() / 2, surface_screen.get_height() / 2)
 	#pygame.draw.rect(surface_screen, colorHud, pygame.Rect(300 - 2, 200 - 2, 4, 4)) # centered guide dot
 on_event(lambda a: a.type == EVENT_DRAW, draw_environment)
 
-
-
-
 on_event(lambda a: a.type == AppEvent.INPUT_DIRECTION and a.direction == Direction.NORTH, lambda a: move_player(block_player, (0, 0, -1)))
 on_event(lambda a: a.type == AppEvent.INPUT_DIRECTION and a.direction == Direction.SOUTH, lambda a: move_player(block_player, (0, 0, 1)))
 on_event(lambda a: a.type == AppEvent.INPUT_DIRECTION and a.direction == Direction.EAST, lambda a: move_player(block_player, (1, 0, 0)))
 on_event(lambda a: a.type == AppEvent.INPUT_DIRECTION and a.direction == Direction.WEST, lambda a: move_player(block_player, (-1, 0, 0)))
 
-on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_EQUALS, lambda a: zoom_camera(-1))
-on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_MINUS, lambda a: zoom_camera(1))
+#on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_EQUALS, lambda a: zoom_camera(-1))
+#on_event(lambda a: a.type == pygame.KEYDOWN and a.key == pygame.K_MINUS, lambda a: zoom_camera(1))
 
 
 fps_clock = pygame.time.Clock()
 assert mag_scale_to_2d((1, 1), 1) == (1 / math.sqrt(2), 1 / math.sqrt(2))
 
 
+######################################################################### begin
 
-
-
-
-
-
-
-
-
+import map_0
+map_0.make(make_player, make_bug, make_grass, make_stone, make_boulder, make_tree, make_bush_0, make_bush_1, make_wood_floor, make_water, make_dirt)
 
 
 event_loop()
-

File roguelike/map_0.py

+'''
+Created: Aug 10, 2013
+Last modified: Aug 10, 2013 
+'''
+
+def make(make_player, make_bug, make_grass, make_stone, make_boulder, make_tree, make_bush_0, make_bush_1, make_wood_floor, make_water, make_dirt):
+	#make_grass((0, 0, 0))
+	#make_dirt((1, 0, 0))
+	#make_player((0, 1, 0))
+	
+	cursor = (0, 0, 0)
+	
+	def advance_row(a):
+		nonlocal cursor
+		cursor = (0, cursor[1], cursor[2] + 1)
+	def advance_one():
+		nonlocal cursor
+		cursor = (cursor[0] + 1, cursor[1], cursor[2])
+	def advance_layer(a):
+		nonlocal cursor
+		cursor = (0, cursor[1] + 1, 0)
+		
+	
+	#char_to_maker = [make_player, make_bug, make_grass, make_stone, make_boulder, make_tree, make_bush_0, make_bush_1]
+	char_to_maker = {
+		'P': make_player,
+		'B': make_bug,
+		'g': make_grass,
+		's': make_stone,
+		'R': make_boulder,
+		'T': make_tree,
+		'1': make_bush_0,
+		'2': make_bush_1,
+		'w': make_wood_floor,
+		'~': make_water,
+		'd': make_dirt,
+		'\n': advance_row,
+		'^': advance_layer,
+		' ': lambda a: None
+	}
+	
+	#data = 
+	"""
+^
+
+
+
+   s
+    ss
+    ~~
+    ~~
+^
+
+
+ gg
+ ggs
+ gddss
+ ddd
+   d
+^
+d
+ggdd
+d12
+  Bd s
+gR Rs
+ P
+^
+
+   Rdd
+   gTg
+s  gds
+^
+
+      g
+     1
+    dd
+"""
+
+
+
+
+
+
+	data = """
+^
+
+
+
+
+~~
+~~
+~~dd
+~~dddds
+^
+
+
+
+dd
+   
+  dd
+  R dd
+      s
+^
+ggg
+ggg
+ssg ~~
+  ggggs
+  ggdd
+   Pdd
+    gds
+      R
+^
+2RBTT
+ T  dd
+ss d  d
+  1   R
+    TTs
+     Bs
+    2 s
+^
+
+B  dddg
+
+   
+      s
+      s
+      s
+^
+"""
+	
+	for char in data:
+		char_to_maker[char](cursor)
+		advance_one()