Setup
Input
Movement
Minimap

We are now writing a check for the input

main.py

import time

from bearlibterminal import terminal

from Config.sleep_time import sleep_time
from Input.inputHandle import InputHandle
from Input.keyEnum import keyEnum


def make_terminal():

	terminalConfig =  "input: filter=[keyboard+, mouse+], alt-functions = false;"
	terminalConfig = terminalConfig + "window: size=40x40;"

	terminal.open()
	terminal.set(terminalConfig);
	terminal.refresh()

def display_input_status(input_status):

	mouse = input_status['Mouse']
	keyboard = input_status['Keyboard']

	tile_x = mouse['TileX']
	tile_y = mouse['TileY']

	left_format = "{0:>7}"
	mid_format = "{0:>7}"
	leftmid_format = "{0:>25}"
	right_format = "{0:>7}"

	terminal.printf(0, 0, left_format.format("Moved") +  mid_format.format(mouse['MoveAction']))

	terminal.printf(0, 1, left_format.format("Mouse") + mid_format.format(tile_x) + right_format.format(tile_y))

	terminal.printf(0, 2, left_format.format("Left") + mid_format.format(mouse['Left'] == 1) + right_format.format(
	mouse['LeftClick']))
	terminal.printf(0, 3, left_format.format("Mid") + mid_format.format(mouse['Middle'] == 1) + right_format.format(
	mouse['MiddleClick']))
	terminal.printf(0, 4, left_format.format("Right") + mid_format.format(mouse['Right'] == 1) + right_format.format(
	mouse['RightClick']))

	terminal.printf(0, 5, left_format.format("Scroll") + mid_format.format(mouse["Scroll"]))

	i = 0

	for key in keyboard:
		keyboardStr = right_format.format(keyboard[key])
		keypressStr = right_format.format(keypress[key])

		terminal.printf(0, i+7, leftmid_format.format(str(key)) + keyboardStr + keypressStr)

		i = i + 1


def main():
	make_terminal()
	input_handle = InputHandle();
	input_status = input_handle.get_status()

	while(not input_status["Exit"] ):
		oldClock = time.process_time()

		input_handle.handle_action()
		input_status = input_handle.get_status()

		terminal.clear()

		display_input_status(input_status)

		terminal.refresh()


		dif = time.process_time() - oldClock


		if (dif < sleep_time() ):

			time.sleep(sleep_time()  - dif)


if __name__ == '__main__':
    main()

Input/__init__.py

Empty File
  

Input/inputHandle.py

import time
from bearlibterminal import terminal

from Config.keyConfig import game_keys

from Config.timer import keyBounce

from Input.keyEnum import keyEnum

class InputHandle:

	mouse = {}
	keyboard = {}
	keypress = {}
	keytime = {}

	exit = False

	key_bounce = 0

	def __init__(self):

		self.gamekeys = game_keys()

		self.key_bounce = keyBounce()

		self.mouse = {
			"MoveAction": False,
			"ScollAction": False,
			"Left":False,
			"Right": False,
			"Middle": False,
			"LeftClick":False,
			"RightClick": False,
			"MiddleClick": False,
			"TileX":0,
			"TileY":0,
			"Scroll":0
		}

		for i in keyEnum:
			self.keyboard[i] = False
			self.keypress[i] = False

		self.keypress["Any"] = False

		pass

	def reset_status(self):

		self.mouse["LeftClick"] = False
		self.mouse["RightClick"] = False
		self.mouse["MiddleClick"] = False

		self.mouse["MoveAction"] = False
		self.mouse["ScollAction"] = False

		self.mouse["Scroll"] = 0

		self.exit = False

		self.keypress["Any"] = False

	def handle_action(self):

		self.reset_status()

		while terminal.has_input():

			input_event = terminal.read()

			if input_event == terminal.TK_CLOSE:
				self.exit = True
				continue

			if self.handle_mouse(input_event):
				continue

		self.handle_keyboard()

	def handle_mouse(self,key):

		action_done = False

		if key == terminal.TK_MOUSE_MOVE:
			self.mouse["MoveAction"] = True
			action_done = True

		if key == terminal.TK_MOUSE_SCROLL:
			self.mouse["ScollAction"] = True
			self.mouse["Scroll"] = self.mouse["Scroll"] + terminal.state(terminal.TK_MOUSE_WHEEL)
			action_done = True


		self.mouse["TileX"] = terminal.state(terminal.TK_MOUSE_X)
		self.mouse["TileY"] = terminal.state(terminal.TK_MOUSE_Y)

		self.mouse["Left"] = terminal.state(terminal.TK_MOUSE_LEFT)
		self.mouse["Right"] = terminal.state(terminal.TK_MOUSE_RIGHT)
		self.mouse["Middle"] = terminal.state(terminal.TK_MOUSE_MIDDLE)

		released = (key & terminal.TK_KEY_RELEASED == terminal.TK_KEY_RELEASED)


		if (key & ~terminal.TK_KEY_RELEASED) == terminal.TK_MOUSE_LEFT:
			action_done = True
			self.mouse["LeftClick"] = released

		if (key & ~terminal.TK_KEY_RELEASED) == terminal.TK_MOUSE_RIGHT:
			action_done = True
			self.mouse["RightClick"] =  released

		if (key & ~terminal.TK_KEY_RELEASED) == terminal.TK_MOUSE_MIDDLE:
			action_done = True
			self.mouse["MiddleClick"] = released

		return action_done



	def get_status(self):
		return {

			"Mouse" : self.mouse,
			"Keyboard": self.keyboard,
			"KeyPress": self.keypress,
			"Exit": self.exit,
			"Anything": self.keypress["Any"] or self.mouse["LeftClick"] or self.mouse["RightClick"] or self.mouse["MiddleClick"] or self.exit,
		}


	def handle_keyboard(self):


		for i in keyEnum:
			self.keypress[i] = False
			self.keyboard[i] = False

		for i in self.gamekeys:

			if( terminal.state(i) ):
				self.keyboard[self.gamekeys[i]] = True

				if i not in self.keytime:
					self.keypress[self.gamekeys[i]] = True
					self.keytime[i] = time.clock()

				else:
					dif =  time.clock()-self.keytime[i]

					if dif> self.key_bounce:
						self.keypress[self.gamekeys[i]] = True
						self.keytime[i] = time.clock()
			else:
				if i in self.keytime:
					del(self.keytime[i])


  

Input/keyEnum.py

from enum import Enum

class keyEnum(Enum):
	MOVE_UP= 0,
	MOVE_DOWN= 1,
	MOVE_LEFT= 2,
	MOVE_RIGHT= 3,
	MOVE_UPLEFT= 4,
	MOVE_UPRIGHT= 5,
	MOVE_DOWNLEFT= 6,
	MOVE_DOWNRIGHT= 7,
	MOVE_WAIT =8,

	CONFIRM = 9,

	ESCAPE = 999
	EXIT = 1000

  

Config/__init__.py

Empty File
  

Config/keyConfig.py

from bearlibterminal import terminal

from Input.keyEnum import keyEnum


def game_keys():
	return {
		terminal.TK_UP: keyEnum.MOVE_UP,
		terminal.TK_DOWN: keyEnum.MOVE_DOWN,
		terminal.TK_RIGHT: keyEnum.MOVE_RIGHT,
		terminal.TK_LEFT: keyEnum.MOVE_LEFT,

		terminal.TK_KP_7: keyEnum.MOVE_UPLEFT,
		terminal.TK_KP_8: keyEnum.MOVE_UP,
		terminal.TK_KP_9: keyEnum.MOVE_UPRIGHT,
		terminal.TK_KP_4: keyEnum.MOVE_LEFT,
		terminal.TK_KP_5: keyEnum.MOVE_WAIT,
		terminal.TK_KP_6: keyEnum.MOVE_RIGHT,
		terminal.TK_KP_1: keyEnum.MOVE_DOWNLEFT,
		terminal.TK_KP_2: keyEnum.MOVE_DOWN,
		terminal.TK_KP_3: keyEnum.MOVE_DOWNRIGHT,


		terminal.TK_ESCAPE: keyEnum.ESCAPE,

		terminal.TK_ENTER: keyEnum.CONFIRM,
		terminal.TK_KP_ENTER: keyEnum.CONFIRM,

	}
  

Config/sleep_time.py

def sleep_time():
	return .05
  

Config/timer.py

def keyBounce():
	return 0.25
  

You should now have a screen that looks like this.


Now that it is running we can look at each section of the code individually.

Input handling

keyEnum

from enum import Enum

class keyEnum(Enum):
	MOVE_UP= 0,
	MOVE_DOWN= 1,
	MOVE_LEFT= 2,
	MOVE_RIGHT= 3,
	MOVE_UPLEFT= 4,
	MOVE_UPRIGHT= 5,
	MOVE_DOWNLEFT= 6,
	MOVE_DOWNRIGHT= 7,
	MOVE_WAIT =8,

	CONFIRM = 9,

	ESCAPE = 999
	EXIT = 1000	

This is a list of actions that you want the user to be able to do. (Notice that their is only one confirm for everything, not one for use item, drop item, use stairs.

keyConfig

from bearlibterminal import terminal

from Input.keyEnum import keyEnum

def game_keys():
	return {
		terminal.TK_UP: keyEnum.MOVE_UP,
		terminal.TK_DOWN: keyEnum.MOVE_DOWN,
		terminal.TK_RIGHT: keyEnum.MOVE_RIGHT,
		terminal.TK_LEFT: keyEnum.MOVE_LEFT,

		terminal.TK_KP_7: keyEnum.MOVE_UPLEFT,
		terminal.TK_KP_8: keyEnum.MOVE_UP,
		terminal.TK_KP_9: keyEnum.MOVE_UPRIGHT,
		terminal.TK_KP_4: keyEnum.MOVE_LEFT,
		terminal.TK_KP_5: keyEnum.MOVE_WAIT,
		terminal.TK_KP_6: keyEnum.MOVE_RIGHT,
		terminal.TK_KP_1: keyEnum.MOVE_DOWNLEFT,
		terminal.TK_KP_2: keyEnum.MOVE_DOWN,
		terminal.TK_KP_3: keyEnum.MOVE_DOWNRIGHT,


		terminal.TK_ESCAPE: keyEnum.ESCAPE,

		terminal.TK_ENTER: keyEnum.CONFIRM,
		terminal.TK_KP_ENTER: keyEnum.CONFIRM,

	}

This is a list of keys and which actions you want to associate with each key. Key things to notice are the two enters both go to the same action and their is no keyEnum.EXIT
The List of key codes

InputHandle

This is the major code for this step. It is responsible for converting the input events into something that is eaiser to use.

class InputHandle:

	mouse = {}
	keyboard = {}
	keypress = {}
	keytime = {}

	exit = False

	key_bounce = 0

	def __init__(self):

		self.gamekeys = game_keys()

		self.key_bounce = keyBounce()

		self.mouse = {
			"MoveAction": False,
			"ScollAction": False,
			"Left":False,
			"Right": False,
			"Middle": False,
			"LeftClick":False,
			"RightClick": False,
			"MiddleClick": False,
			"TileX":0,
			"TileY":0,
			"Scroll":0
		}

		for i in keyEnum:
			self.keyboard[i] = False
			self.keypress[i] = False

		self.keypress["Any"] = False

		pass
Setting up our variables for holding onto the status of everything we are intrested in.

	def reset_status(self):

		self.mouse["LeftClick"] = False
		self.mouse["RightClick"] = False
		self.mouse["MiddleClick"] = False

		self.mouse["MoveAction"] = False
		self.mouse["ScollAction"] = False

		self.mouse["Scroll"] = 0

		self.exit = False

		self.keypress["Any"] = False
		
At the start of the frame set all the click and presses to none.

	def handle_action(self):

		self.reset_status()  #Reset what needs to be reset

		while terminal.has_input():
			#For every input in the queue handle it
			
			input_event = terminal.read() #Get the input in question

			if input_event == terminal.TK_CLOSE:
				#The user has clicked to close
				self.exit = True
				continue
				

			if self.handle_mouse(input_event):
				#Handle a mouse event
				continue

		#Handle all the keyboard status in one go
		self.handle_keyboard()
		
		

	def handle_mouse(self,key):

		action_done = False #This is not a mouse event yet

		if key == terminal.TK_MOUSE_MOVE:
			self.mouse["MoveAction"] = True
			action_done = True

		if key == terminal.TK_MOUSE_SCROLL:
			self.mouse["ScollAction"] = True
			
			self.mouse["Scroll"] = self.mouse["Scroll"] + terminal.state(terminal.TK_MOUSE_WHEEL)
			#Keep track of how far we have scrolled this frame
			
			action_done = True

		#Grab the state of the mouse
		self.mouse["TileX"] = terminal.state(terminal.TK_MOUSE_X)
		self.mouse["TileY"] = terminal.state(terminal.TK_MOUSE_Y)

		self.mouse["Left"] = terminal.state(terminal.TK_MOUSE_LEFT)
		self.mouse["Right"] = terminal.state(terminal.TK_MOUSE_RIGHT)
		self.mouse["Middle"] = terminal.state(terminal.TK_MOUSE_MIDDLE)

		
		#Bitwise check to see if the mouse button was released
		released = (key & terminal.TK_KEY_RELEASED == terminal.TK_KEY_RELEASED)


		#Check to see which button was pushed and if was a release event
		
		if (key & ~terminal.TK_KEY_RELEASED) == terminal.TK_MOUSE_LEFT:
			action_done = True
			self.mouse["LeftClick"] = released

		if (key & ~terminal.TK_KEY_RELEASED) == terminal.TK_MOUSE_RIGHT:
			action_done = True
			self.mouse["RightClick"] =  released

		if (key & ~terminal.TK_KEY_RELEASED) == terminal.TK_MOUSE_MIDDLE:
			action_done = True
			self.mouse["MiddleClick"] = released

		return action_done
	def get_status(self):
		return {

			"Mouse" : self.mouse,
			"Keyboard": self.keyboard,
			"KeyPress": self.keypress,
			"Exit": self.exit,
			"Anything": self.keypress["Any"] or self.mouse["LeftClick"] or self.mouse["RightClick"] or self.mouse["MiddleClick"] or self.exit,
		}
Return the status of everyting to the program to deal with it their.
Notice the Anything status. This acts like the "Press any key to contiune"

	def handle_keyboard(self):

		
		#Set everthing to False until we check it.
		for i in keyEnum:
			self.keypress[i] = False
			self.keyboard[i] = False
			
		#Check every key we are intrested in.
		for i in self.gamekeys:

			if( terminal.state(i) ):
				#The key is currently down.
			
				self.keyboard[self.gamekeys[i]] = True

				if i not in self.keytime:
					#The user has just pushed it, set the press to true and set the clock to now.
					self.keypress[self.gamekeys[i]] = True
					self.keytime[i] = time.clock()

				else:
					#The user has held the key down. Do we need to trigger a repeat push 
					dif =  time.clock()-self.keytime[i]

					if dif> self.key_bounce:
						self.keypress[self.gamekeys[i]] = True
						self.keytime[i] = time.clock()
			else:
				#The user has released the key. We are no longer intrested in tracking it.
				if i in self.keytime:
					del(self.keytime[i])


  

Main.py

from bearlibterminal import terminal


def make_terminal():

	#keyboard+ is required to allow both press and released to be read.
	terminalConfig =  "input: filter=[keyboard+, mouse+], alt-functions = false;"
	terminalConfig = terminalConfig + "window: size=40x40;"

	terminal.open()
	terminal.set(terminalConfig);
	terminal.refresh()

	

This is how to create a window to draw in.

Configuration has the full list of optionas avaliable if you want to have a look for later in the tutorial.

	def display_input_status(input_status):

	#Grab the two kinds of status we are intrested in.
	mouse = input_status['Mouse']
	keyboard = input_status['Keyboard']

	#Where is the pointer.
	tile_x = mouse['TileX']
	tile_y = mouse['TileY']

	#Format strings to align the input statuses.
	left_format = "{0:>7}"
	mid_format = "{0:>7}"
	leftmid_format = "{0:>25}"
	right_format = "{0:>7}"

	terminal.printf(0, 0, left_format.format("Moved") +  mid_format.format(mouse['MoveAction']))

	terminal.printf(0, 1, left_format.format("Mouse") + mid_format.format(tile_x) + right_format.format(tile_y))

	terminal.printf(0, 2, left_format.format("Left") + mid_format.format(mouse['Left'] == 1) + right_format.format(
	mouse['LeftClick']))
	terminal.printf(0, 3, left_format.format("Mid") + mid_format.format(mouse['Middle'] == 1) + right_format.format(
	mouse['MiddleClick']))
	terminal.printf(0, 4, left_format.format("Right") + mid_format.format(mouse['Right'] == 1) + right_format.format(
	mouse['RightClick']))

	terminal.printf(0, 5, left_format.format("Scroll") + mid_format.format(mouse["Scroll"]))

	i = 0

	#Loop over the keyboard and show if it is pressed/ clicked.
	for key in keyboard:
		keyboardStr = right_format.format(keyboard[key])
		keypressStr = right_format.format(keypress[key])

		terminal.printf(0, i+7, leftmid_format.format(str(key)) + keyboardStr + keypressStr)

		i = i + 1


def main():
	make_terminal() #Make our terminal.
	
	#Setup the input handling.
	input_handle = InputHandle();
	input_status = input_handle.get_status()

	#Keep looping until the user clicks the x button.
	while(not input_status["Exit"] ):
		oldClock = time.process_time()

		#Handle the action queue and then get the status.
		input_handle.handle_action()
		input_status = input_handle.get_status()

		#Reset the display .
		terminal.clear()

		display_input_status(input_status)

		#Show the current display.
		terminal.refresh()


		#If we are running fast, sleep for a bit to reduce the load on the cpu.
		
		dif = time.process_time() - oldClock
		if (dif < sleep_time() ):

			time.sleep(sleep_time()  - dif)


The biggest thing to be aware of here is the terminal.refresh() line. Without this code you will not get inputs. You could put the reresh in the loop but the way we are going to write the input handler will cause it to go into a loop that it can't get out of.