Commits

Anonymous committed b016ae4

Added wading in water, and made the bug AI prefer not to about-face.

  • Participants
  • Parent commits c407892

Comments (0)

Files changed (4)

roguelike/Character Cat Girl In Water.png

Added
New image

roguelike/DEPENDENCIES.txt

+this app requires:
+
+Python 3.2: http://www.python.org/download/releases/3.2.5/
+pygame-1.9.2a0.win32-py3.2: http://pygame.org/download.shtml

roguelike/main.py

 '''
 Created: Aug 4, 2013
-Last modified: Aug 10, 2013 
+Last modified: Aug 11, 2013 
 '''
 
 import pygame
 
 def scale2d(vec, scalar):
 	return (vec[0] * scalar, vec[1] * scalar)
+def basic_product_2d(a, b):
+	return (a[0] * b[0], a[1] * b[1])
+def negate2d(vec):
+	return (-vec[0], -vec[1])
+
+def negate3d(vec):
+	return (-vec[0], -vec[1], -vec[2])
 
 
 EVENT_DRAW = 100
 	#| pygame.DOUBLEBUF
 	#| pygame.HWSURFACE
 )
-pygame.display.set_caption('Roguelike v0.0.5')
+pygame.display.set_caption('Roguelike v0.0.6')
 
 
 class AppEvent:
 colorDebug1 = pygame.Color(150, 0, 0)
 colorDebugToggleOn = pygame.Color(20, 170, 20)
 colorDebugToggleOff = pygame.Color(160, 0, 0)
-colorHud = pygame.Color(255, 255, 255)
-colorHudOutline = pygame.Color(0, 0, 0)
+color_HUD = pygame.Color(255, 255, 255)
+color_HUD_outline = pygame.Color(0, 0, 0)
 
 joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())]
 for joy in joysticks:
 		#yield from position_to_blocklist[position]
 		for block in position_to_blocklist[position]:
 			yield block
+def is_block_type_at(position, block_type):
+	#for a in get_block_types_at(position):
+	#	if a == block_type:
+	#		return True
+	#return False
+	return block_type in get_block_types_at(position)
 	
 def move_player(block, delta):
 	def is_obstacle_type(block_type):
 	if can_bug_move(block, delta):
 		move_block(block, delta)
 
-def ai_bug(block):
-	if block[2] == BlockType.BUG_DEAD: return
+#def ai_bug(block):
+#	if block[2] == BlockType.BUG_DEAD: return
+#	
+#	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 make_bug(position):
+	last_move = None
+	def do_ai(event):
+		nonlocal last_move
+		
+		if block[2] == BlockType.BUG_DEAD: return
+		
+		deltas = [(1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 0, -1)]
+		
+		reverse_move = (None if last_move == None else negate3d(last_move))
+		if last_move != None:
+			deltas.remove(reverse_move) ### avoid about-face when possible 
+		
+		options = [x for x in deltas if can_bug_move(block, x)]
+		if len(options) > 0:
+			option = random.choice(options)
+			move_bug(block, option)
+			last_move = option
+		else:
+			### attempt about-face when all else fails
+			if reverse_move != None and can_bug_move(block, reverse_move):
+				move_bug(block, reverse_move)
+				last_move = reverse_move
+		
+		
+		
 	
-	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))
+	block = make_block(position, tile_bug, BlockType.BUG)
+	on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, do_ai)
+	### TODO: Remove event binding when bug-death event fires
 
 
 #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())
+#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_gray = (pygame.image.load('Plain Block.png').convert_alpha(), (50, 90), 100, True, 0, False)
 tile_dirt = (pygame.image.load('Dirt Block.png').convert_alpha(), (50, 90), 100, True, 0, False)
 tile_grass = (pygame.image.load('Grass Block.png').convert_alpha(), (50, 90), 100, True, 0, False)
-tile_water = (pygame.image.load('Water Block.png').convert_alpha(), (50, 90), 100, True, 0, False)
+tile_water = (pygame.image.load('Water Block.png').convert_alpha(), (50, 90), 100, True, -1, False)
 tile_rock = (pygame.image.load('Rock.png').convert_alpha(), (50, 90), 100, False, 0, False)
 tile_tree = (pygame.image.load('Tree Tall.png').convert_alpha(), (50, 90), 100, False, 0, False)
 tile_player = (pygame.image.load('Character Cat Girl.png').convert_alpha(), (50, 90), 100, False, 0, False)
+tile_player_in_water = (pygame.image.load('Character Cat Girl In Water.png').convert_alpha(), (50, 90), 100, False, 0, False)
 tile_bug = (pygame.image.load('Enemy Bug.png').convert_alpha(), (50, 90), 100, False, 0, False)
 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)
 
 
 class BlockType:
-	PLAYER, BUG, ROCK, TREE, FILLER, BUG_DEAD, SPEECH = range(7)
+	PLAYER, BUG, ROCK, TREE, FILLER, BUG_DEAD, SPEECH, WATER = range(8)
 
 def make_block(position, tile, block_type):
 	if len(position) != 3: raise Exception()
 	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([(1, 0, 2), tile_gray, BlockType.FILLER])
-blocks.append([(0, 0, 0), tile_gray, BlockType.FILLER])
-blocks.append([(1, 0, 0), tile_gray, BlockType.FILLER])
-blocks.append([(3, 0, 2), tile_gray, BlockType.FILLER])
-blocks.append([(2, 0, 1), tile_dirt, 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([(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])
-blocks.append([(2, 2, 1), tile_tree, BlockType.TREE])
-blocks.append([(0, 1, -1), tile_gray, BlockType.FILLER])
-blocks.append([(-1, 2, -1), tile_gray, BlockType.FILLER])
-blocks.append([(-1, 1, -1), tile_gray, BlockType.FILLER])
-blocks.append([(-1, 0, -1), tile_gray, BlockType.FILLER])
-blocks.append([(-1, -1, 0), tile_dirt, BlockType.FILLER])
-blocks.append([(-1, -1, 1), tile_water, BlockType.FILLER])
-blocks.append([(0, -1, 1), tile_water, BlockType.FILLER])
-blocks.append([(2, 1, -1), tile_grass, BlockType.FILLER])
-blocks.append([(2, 0, 0), tile_dirt, BlockType.FILLER])
-blocks.append([(3, 0, 0), tile_dirt, BlockType.FILLER])
-blocks.append([(1, 0, -1), tile_dirt, BlockType.FILLER])
-blocks.append([(3, 1, 1), tile_gray, BlockType.FILLER])
-blocks.append([(3, 2, 1), tile_dirt, BlockType.FILLER])
-blocks.append([(3, 3, 1), tile_grass, BlockType.FILLER])
-blocks.append([(3, 2, 2), tile_grass, BlockType.FILLER])
-blocks.append([(3, 1, 2), tile_dirt, BlockType.FILLER])
-blocks.append([(3, 1, -1), tile_dirt, BlockType.FILLER])
-blocks.append([(1, 0, 3), tile_dirt, BlockType.FILLER])
-blocks.append([(0, 0, 3), tile_dirt, BlockType.FILLER])
-blocks.append([(2, 0, 3), tile_dirt, BlockType.FILLER])
-blocks.append([(-1, 1, -2), tile_wood, BlockType.FILLER])
-blocks.append([(-2, 0, 0), tile_grass, BlockType.FILLER])
-blocks.append([(-2, 1, -1), tile_wood, BlockType.FILLER])
-blocks.append([(-2, 1, -2), tile_wood, BlockType.FILLER])
-blocks.append([(4, 1, 0), tile_dirt, BlockType.FILLER])
-blocks.append([(4, 1, 1), tile_gray, BlockType.FILLER])
-blocks.append([(4, 1, 2), tile_gray, BlockType.FILLER])
-
-block_player = [(1, 1, 0), tile_player, BlockType.PLAYER]
-center_camera_on_block(block_player)
-blocks.append(block_player)
-
-block_bug_0 = [(1, 1, -1), tile_bug, BlockType.BUG]
-blocks.append(block_bug_0)
-on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, lambda a: ai_bug(block_bug_0))
-
-block_bug_1 = [(-1, 0, 0), tile_bug, BlockType.BUG]
-blocks.append(block_bug_1)
-on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, lambda a: ai_bug(block_bug_1))
-
-block_bug_2 = [(1, 2, 2), tile_bug, BlockType.BUG]
-blocks.append(block_bug_2)
-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)
+	
+	def center_camera_on_player():
+		move_camera_to(sum3d(block_player[0], (0, -1, 0)))
 	center_camera_on_player()
+	
+	def update_tile():
+		if is_block_type_at(block_player[0], BlockType.WATER):
+			block_player[1] = tile_player_in_water
+		else:
+			block_player[1] = tile_player
+	update_tile()
+	
+	
+	on_event(lambda a: a.type == AppEvent.BLOCK_MOVED and a.block == block_player, lambda a: (
+		center_camera_on_player(), update_tile()
+	))
 
-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):
 def make_wood_floor(position):
 	make_block(position, tile_wood, BlockType.FILLER)
 def make_water(position):
-	make_block(position, tile_water, BlockType.FILLER)
+	make_block(position, tile_water, BlockType.WATER)
 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) }
 def scale_surface_to(surface, dest_size):
 			
 		#draw_tile_fog(tile, position)
 		
-	#pygame.draw.rect(surface_screen, colorHud, pygame.Rect(300 - 2, 200 - 2, 4, 4)) # centered guide dot
+	#pygame.draw.rect(surface_screen, color_HUD, 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 == 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))
 
+def render_text(text, position, anchor, dest_surface, font, color_fill, color_outline):
+	surface = font.render(text, True, color_outline)
+	position = sum2d(position, negate2d(basic_product_2d(surface.get_size(), anchor)))
+	#pygame.Rect().size
+	
+	dest_surface.blit(surface, sum2d(position, (2, 0)))
+	dest_surface.blit(surface, sum2d(position, (-2, 0)))
+	dest_surface.blit(surface, sum2d(position, (0, 2)))
+	dest_surface.blit(surface, sum2d(position, (0, -2)))
+	
+	surface = font.render(text, True, color_fill)
+	dest_surface.blit(surface, position)
+
 
 fps_clock = pygame.time.Clock()
-gui_font = pygame.font.SysFont('Verdana', 18)
+gui_font = pygame.font.SysFont('Verdana', 28)
 def draw_fps(event):
 	fps_clock.tick()
-	
-	fps_string = 'FPS: ' + str(int(fps_clock.get_fps()))
-	
-	fps_surface = gui_font.render(fps_string, True, colorHudOutline)
-	#surface_screen.blit(fps_surface, (-2, 0))
-	#surface_screen.blit(fps_surface, (2, 0))
-	#surface_screen.blit(fps_surface, (0, 2))
-	#surface_screen.blit(fps_surface, (0, -2))
-	surface_screen.blit(fps_surface, (-1, -1))
-	surface_screen.blit(fps_surface, (1, 1))
-	surface_screen.blit(fps_surface, (-1, 1))
-	surface_screen.blit(fps_surface, (1, -1))
-	
-	fps_surface = gui_font.render(fps_string, True, colorHud)
-	surface_screen.blit(fps_surface, (0, 0))
+	render_text('FPS: ' + str(int(fps_clock.get_fps())), (0, 0), (0, 0), surface_screen, gui_font, color_HUD, color_HUD_outline)
 on_event(lambda a: a.type == EVENT_DRAW, draw_fps)
 
 
+def draw_instructions(event):
+	render_text('Use the arrow keys or d-pad to move.', (surface_screen.get_width(), 0), (1, 0), surface_screen, gui_font, color_HUD, color_HUD_outline)
+on_event(lambda a: a.type == EVENT_DRAW, draw_instructions)
+
 #################################################################### unit tests
 
 assert mag_scale_to_2d((1, 0), 2) == (2, 0)

roguelike/map_0.py

 
 
 
+dd
+dd
+dd
+dd
+^
+
+
+
+
 ~~
 ~~
 ~~dd
 ^
 
 
-
+    ss
 dd
    
   dd
   R dd
       s
 ^
-ggg
+gggg
 ggg
 ssg ~~
   ggggs
     gds
       R
 ^
-2RBTT
- T  dd
+2RBdT11
+ T ddd
 ss d  d
   1   R
     TTs
     2 s
 ^
 
-B  dddg
+B   ddg
 
    
       s