This module simulates the ‘conio’ and ‘curses’ libraries to create text interfaces with color and cursor.
Project description
kurses.py
This module uses SDL2 (or Pygame) to emulate the functions of the conio and curses libraries, which are used to create text-based user interfaces. You can control the color and cursor of the text, as well as the position and size of the window, the bit depth, typography and text styles (underline, bold, italic and strikethrough).
It is designed to offer a cross-platform solution for creating text-based applications, independent of the system where they run.
How to install it?
You can install from pip:
pip install kurses-py
Or from GitHub repository:
pip install git+https://github.com/SealtielFreak/kurses.py.git
Dependencies
At the moment it is only implemented to work with SDL2 (PySDL2).
pip install pysdl2 pysdl2-dll
Examples
hello_world.py
# load module
from kurses import VirtualTerminal
# instance Virtual console
term = VirtualTerminal(font_filename="ModernDOS8x16.ttf") # load font resources
stream = term.stream # get main buffer console
# define loop function
def loop():
stream.resetall() # restore default attributes in the buffer console
# set attributes of first string
stream.gotoxy(0, 0) # go to position x: 0, y: 0
stream.set_background_color((255, 255, 255)) # set background color characters
stream.set_foreign_color((0, 0, 0)) # set foreign color
stream.print("Hello\n") # print into buffer console
# set attributes of second string
stream.gotoxy(5, 1) # go to position x: 5, y: 1
stream.italic(True) # set true italic
stream.print("world!") # print into buffer console, again
# set loop function
term.set_target(loop)
# run all program
term.main_loop()
audio_demo.py
# load module
from kurses import VirtualTerminal, Effect, Music
# instance Virtual console
term = VirtualTerminal(font_filename="ModernDOS8x16.ttf", sound_enabled=True) # load font resources
stream = term.stream # get main buffer console
buzzer = term.buzzer # get main buzzer console
# Create tracks for buzzer
buzzer.record(0, [(440, 200), (493, 200), (523, 200), (587, 400)])
# Load sound effect
effect = Effect(filename="laser.mp3")
effect.volume(10)
# Load music
music = Music(filename="win95.mp3")
music.volume(15)
music.play(2)
music.fadeout(5)
# define loop function
def loop():
stream.resetall() # restore default attributes in the buffer console
# set attributes of first string
stream.gotoxy(0, 0) # go to position x: 0, y: 0
stream.set_background_color((255, 255, 255)) # set background color characters
stream.set_foreign_color((0, 0, 0)) # set foreign color
stream.print("Sounds\n") # print into buffer console
# set attributes of second string
stream.gotoxy(5, 1) # go to position x: 5, y: 1
stream.italic(True) # set true italic
stream.print("in Kurses!") # print into buffer console, again
keys = term.keyspressed()
if "space" in keys:
effect.play(2)
if "w" in keys:
buzzer.play(0, 25)
if "s" in keys:
buzzer.beep(440, 25, 25)
# set loop function
term.set_target(loop)
# run all program
term.main_loop()
keypressed.py
# load modules
import random
from kurses import VirtualTerminal
# instance Virtual console
console = VirtualTerminal("ModernDOS8x16.ttf")
buffer = console.stream # get buffer console
# define global variables
x, y = 0, 0
# define loop function
def loop():
global x, y
buffer.clrscr()
buffer.resetall() # restore default attributes in the buffer console
# check key pressed
if "w" in console.keyspressed():
y -= 1
elif "s" in console.keyspressed():
y += 1
if "a" in console.keyspressed():
x -= 1
elif "d" in console.keyspressed():
x += 1
# all draw events of string with random colors
_x = x
for _c in "Random color":
buffer.set_foreign_color(tuple(random.randint(0, 255) for _ in range(3)))
buffer.set_background_color(tuple(random.randint(0, 255) for _ in range(3)))
buffer.gotoxy(_x, y) # set position
buffer.cputs(_c) # print character into buffer console
_x += 1
# set loop function
console.set_target(loop)
# run all program
console.main_loop()
asteroids.py
import random
import time
import kurses.stream
from kurses import VirtualTerminal, StreamBuffer
from kurses.font_resources import QualityFont
SHIP = """\
|
/0\\
"""
def draw_ship(x, y, buffer):
buffer.gotoxy(x, y)
buffer.set_foreign_color((255, 0, 255))
buffer.print(SHIP)
buffer.resetall()
def random_asteroid(_x=(0, 80), _y=(0, 30)):
return (
random.randint(*_x),
random.randint(*_y),
random.randint(1, 2),
random.sample([(255, 255, 255), (255, 255, 0), (0, 0, 255), (0, 255, 255), (255, 0, 0), (0, 255, 0)], 1)[0],
random.sample("*", 1)[0],
)
console = VirtualTerminal(font_filename="ModernDOS8x16.ttf", quality=QualityFont.LCD)
main_buffer = console.stream
score_buffer = StreamBuffer(40, 15, sx=2, sy=2, type_cursor=kurses.stream.TypeCursor.RECT)
score_buffer.x = 0
score_buffer.y = 0
score_buffer.type_cursor = kurses.stream.TypeCursor.EMPTY
asteroids = [random_asteroid() for _ in range(5)]
x_ship, y_ship = random.randint(0, 70), random.randint(0, 30)
life, score = 100, 0
shoots = []
def loop():
global x_ship, y_ship, life, score
rows, columns = main_buffer.buffersize
time.sleep(0.025)
for stream in console.streams:
stream.clrscr()
if life > 0:
if score >= 10:
_msg = "You win!"
main_buffer.bold(True)
main_buffer.cputsxy(40 - (len(_msg) // 2), 15, _msg)
main_buffer.resetall()
_msg = "Press SPACE for play again"
main_buffer.set_foreign_color((255, 255, 0))
main_buffer.cputsxy(40 - (len(_msg) // 2), 16, _msg)
main_buffer.resetall()
if "space" in console.keyspressed():
life = 100
else:
if "w" in console.keyspressed() and y_ship >= 0:
y_ship -= 1
elif "s" in console.keyspressed() and y_ship <= rows - 3:
y_ship += 1
if "a" in console.keyspressed() and x_ship >= 0:
x_ship -= 1
elif "d" in console.keyspressed() and x_ship <= columns - 3:
x_ship += 1
if "space" in console.keyspressed():
if len(shoots) == 0:
shoots.append((x_ship, y_ship))
draw_ship(x_ship, y_ship, main_buffer)
for i, (_x, _y, speed, color, c) in enumerate(asteroids):
main_buffer.set_foreign_color(color)
main_buffer.putchxy(_x, _y, c)
main_buffer.resetall()
_y += speed
if _y > rows:
_x = random.randint(0, columns)
_y = 0
if _x in range(x_ship, x_ship + 3) and _y in range(y_ship, y_ship + 3):
if c == '.':
score += 1
else:
life -= 5
asteroids.remove(asteroids[i])
asteroids.append(random_asteroid(_y=(0, 0)))
else:
asteroids[i] = _x, _y, speed, color, c
for i, (_x, _y) in enumerate(shoots):
_y -= 1
main_buffer.set_foreign_color((0, 255, 0))
main_buffer.putchxy(_x, _y, '0')
main_buffer.resetall()
if _y < 0:
shoots.remove(shoots[i])
else:
shoots[i] = _x, _y
for i, (_x, _y) in enumerate(shoots):
for j, (_xx, _yy, speed, color, c) in enumerate(asteroids):
if _x == _xx and _y == _yy:
asteroids.remove(asteroids[j])
score += 1
_msg = f"life: {life}"
score_buffer.gotoxy(0, 0)
score_buffer.bold(True)
score_buffer.set_background_color((255, 0, 0))
score_buffer.set_foreign_color((255, 255, 0))
score_buffer.print(_msg)
score_buffer.resetall()
_msg = f"score: {score}"
score_buffer.gotoxy(40 - len(_msg), 0)
score_buffer.bold(True)
score_buffer.set_background_color((0, 0, 255))
score_buffer.set_foreign_color((255, 255, 255))
score_buffer.print(_msg)
score_buffer.resetall()
else:
_msg = "You lost!"
main_buffer.bold(True)
main_buffer.cputsxy(40 - (len(_msg) // 2), 15, _msg)
main_buffer.resetall()
_msg = "Press SPACE for play again"
main_buffer.set_foreign_color((255, 0, 0))
main_buffer.cputsxy(40 - (len(_msg) // 2), 16, _msg)
main_buffer.resetall()
if "space" in console.keyspressed():
life = 100
if __name__ == '__main__':
console.streams.append(score_buffer)
console.title = "Asteroids"
console.set_target(loop)
console.main_loop()
runtime_target_example.py
import random
import typing
from kurses import VirtualTerminal
from kurses.events import EventTargetRuntime
term = VirtualTerminal(font_filename="ModernDOS8x16.ttf")
stream = term.stream
class MyTarget(EventTargetRuntime):
def __init__(self):
self.position = 0, 0
def load(self):
term.resizable = True
stream.resetall()
def update(self, dt):
x, y = self.position
stream.clrscr()
stream.gotoxy(x, y)
stream.set_foreign_color(tuple(random.randint(0, 255) for _ in range(3)))
stream.set_background_color(tuple(random.randint(0, 255) for _ in range(3)))
stream.print("Hello\n")
stream.gotoxy(x + 5, y + 1)
stream.italic(True)
stream.print("world!")
def key_down(self, key: chr):
print(f"Key down: {key}")
def key_up(self, key: chr):
print(f"Key up: {key}")
def mouse(self, position: typing.Tuple[int, int], click: int):
self.position = position
def exit(self):
stream.resetall()
stream.gotoxy(0, 0)
stream.set_foreign_color((255, 255, 255))
stream.print("Goodbye")
if __name__ == "__main__":
term.set_runtime(MyTarget)
term.main_loop()
battery_demo.py
# load module
from kurses import VirtualTerminal
# instance Virtual console
term = VirtualTerminal(font_filename="ModernDOS8x16.ttf") # load font resources
stream = term.stream # get main buffer console
# define loop function
def loop():
bat_status, bat_value = term.battery()
stream.resetall() # restore default attributes in the buffer console
# set attributes of first string
stream.gotoxy(0, 0) # go to position x: 0, y: 0
stream.set_background_color((255, 255, 255)) # set background color characters
stream.set_foreign_color((0, 0, 0)) # set foreign color
stream.print(f"Battery status: {bat_status}") # print info
# set attributes of second string
stream.gotoxy(0, 1) # go to position x: 0, y: 1
stream.italic(True) # set true italic
stream.print(f"Battery value: {bat_value}%") # print battery value
# set title of terminal
term.title = "Battery demo"
# set loop function
term.set_target(loop)
# run all program
term.main_loop()
sensor_demo.py
# load module
from kurses import VirtualTerminal
# instance Virtual console
term = VirtualTerminal(font_filename="ModernDOS8x16.ttf") # load font resources
stream = term.stream # get main buffer console
# define loop function
def loop():
gyro = term.gyroscope()
acce = term.accelerometer()
stream.resetall()
stream.set_background_color((255, 255, 255))
stream.set_foreign_color((0, 0, 0))
stream.gotoxy(0, 0)
stream.print(f"Gyroscope: {gyro}")
stream.gotoxy(0, 1)
stream.print(f"Accelerometer: {acce}")
# set title of terminal
term.title = "Sensors demo (Gyroscope and accelerometer)"
# set loop function
term.set_target(loop)
# run all program
term.main_loop()
bitmap_demo.py
from kurses import VirtualTerminal
from kurses.term import Rendering
term = VirtualTerminal(font_filename="./ModernDOS8x16.ttf", rendering=Rendering.SOFTWARE, bitmap_enabled=False)
stream = term.stream
graphics = term.graphics
stream.cputsxy(40, 20, "Hello World")
def loop():
state, _, (x, y) = term.mouse()
width, height = term.size
graphics.circle(0, 0, 59, (255, 0, 0), filled=True)
graphics.polygon([400, 100, 500, 300, 300, 300], (255, 0, 255), filled=True)
graphics.line([0, 0], [width, height], (255, 0, 0), thickness=10)
graphics.circle(x, y, 15, (255, 255, 0), filled=False)
graphics.rect(0, 0, (10, 10), (0, 255, 0), filled=True)
graphics.rect(10, 10, (10, 10), (0, 255, 0), filled=False)
term.purge()
if __name__ == "__main__":
term.title = "Primitives graphics"
term.set_target(loop)
term.main_loop()
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kurses_py-0.1.2.0.tar.gz.
File metadata
- Download URL: kurses_py-0.1.2.0.tar.gz
- Upload date:
- Size: 215.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47020845195af3acfcf484c592c64318f4053546643666b98ed2fc861e418b31
|
|
| MD5 |
8e557588b7342f5f777e89639ba958dd
|
|
| BLAKE2b-256 |
6c995efbbe314930116cd2e011c0514f1f6dace865eb861b3deacecff85399fb
|
Provenance
The following attestation bundles were made for kurses_py-0.1.2.0.tar.gz:
Publisher:
publish.yml on SealtielFreak/kurses.py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kurses_py-0.1.2.0.tar.gz -
Subject digest:
47020845195af3acfcf484c592c64318f4053546643666b98ed2fc861e418b31 - Sigstore transparency entry: 1007976329
- Sigstore integration time:
-
Permalink:
SealtielFreak/kurses.py@9279eed9acd8e3572a39af7f9eefe467a20d8348 -
Branch / Tag:
refs/tags/0.1.2.0 - Owner: https://github.com/SealtielFreak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9279eed9acd8e3572a39af7f9eefe467a20d8348 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kurses_py-0.1.2.0-py3-none-any.whl.
File metadata
- Download URL: kurses_py-0.1.2.0-py3-none-any.whl
- Upload date:
- Size: 241.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
682c73fcc89ac5b137647d474670b893f91e9a50c45ea94b8d974dc7964dea25
|
|
| MD5 |
8c59e472c47190b456ed5a62c66ce4b0
|
|
| BLAKE2b-256 |
d9aee53a3ca9c7547207962f0f7bc949c833d53804e931702550647c86eded3a
|
Provenance
The following attestation bundles were made for kurses_py-0.1.2.0-py3-none-any.whl:
Publisher:
publish.yml on SealtielFreak/kurses.py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kurses_py-0.1.2.0-py3-none-any.whl -
Subject digest:
682c73fcc89ac5b137647d474670b893f91e9a50c45ea94b8d974dc7964dea25 - Sigstore transparency entry: 1007976360
- Sigstore integration time:
-
Permalink:
SealtielFreak/kurses.py@9279eed9acd8e3572a39af7f9eefe467a20d8348 -
Branch / Tag:
refs/tags/0.1.2.0 - Owner: https://github.com/SealtielFreak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9279eed9acd8e3572a39af7f9eefe467a20d8348 -
Trigger Event:
release
-
Statement type: