Compare commits
15 Commits
Author | SHA1 | Date |
---|---|---|
Shadow15510 | bb382622bc | |
Shadow15510 | 28d9eb5231 | |
Shadow15510 | 77d99659a9 | |
Shadow15510 | f2c74bbea5 | |
Shadow15510 | 1b0a3a3500 | |
Shadow15510 | a2e02f3030 | |
Shadow15510 | a42aceeeab | |
Shadow15510 | af27d031be | |
Shadow15510 | bf7bad73b7 | |
Shadow15510 | 2d670448b2 | |
Shadow15510 | a8e0d374ac | |
Shadow15510 | 3ad286dd5a | |
Shadow15510 | 088c29a6e3 | |
Shadow15510 | 0fb38d9fd7 | |
Shadow15510 | 7a3388fa76 |
|
@ -18,7 +18,7 @@ Tout le projet est soumis à la licence GNU General Public Licence v3.0.
|
|||
|
||||
### Utilisation
|
||||
|
||||
Tout est détaillé dans [le wiki du projet](https://gitea.planet-casio.com/Shadow15510/Asci/wiki/Cr%C3%A9ation-d%27un-jeu-de-r%C3%B4le-avec-Asci).
|
||||
Tout est détaillé dans [le wiki du projet](https://gitea.planet-casio.com/Shadow15510/Asci/wiki/Home).
|
||||
|
||||
### Exemples
|
||||
|
||||
|
|
177
asci.py
177
asci.py
|
@ -1,7 +1,12 @@
|
|||
# Asci (1.8.1)
|
||||
# Asci (1.9.3)
|
||||
from math import floor, ceil
|
||||
|
||||
SCREEN_WIDTH = 21
|
||||
SCREEN_HEIGHT = 7
|
||||
|
||||
|
||||
class Asci:
|
||||
def __init__(self, maps, entities, events_mapping, keys_mapping, behaviors=None, screen_width=21, screen_height=6):
|
||||
def __init__(self, maps, entities, events_mapping, keys_mapping, behaviors=None):
|
||||
# Load maps and entities
|
||||
self.maps = [Map(*i) for i in maps]
|
||||
self.entities = {}
|
||||
|
@ -25,7 +30,7 @@ class Asci:
|
|||
for i in behaviors: self._behaviors[i] = behaviors[i]
|
||||
|
||||
# Screen initialisation
|
||||
self.screen = Screen(screen_width, screen_height)
|
||||
self.screen = Screen()
|
||||
self.current_map = None
|
||||
|
||||
def _looked_case(self, direction):
|
||||
|
@ -155,7 +160,7 @@ class Asci:
|
|||
return entity.entity_id
|
||||
|
||||
# Mainloop
|
||||
def mainloop(self, end_game, stat=None, data=None, routine=None, player="@", door="^", walkable=" ", exit_key=9, multi_move="."):
|
||||
def mainloop(self, end_game, stat=None, data=None, routine=None, low_bar=None, player="@", door="^", walkable=" ", exit_key=9, multi_move="."):
|
||||
if exit_key in self._game_keys_mapping:
|
||||
raise ValueError("'{}' is already assigned to a function.".format(exit_key))
|
||||
|
||||
|
@ -182,13 +187,15 @@ class Asci:
|
|||
data_copy = self.data[:]
|
||||
for entity in self.current_map.entities.values():
|
||||
self._behaviors[entity.behavior](entity, data_copy, self.stat, self.screen, walkable)
|
||||
if entity.map_id == self.data[1] and (0 <= entity.pos_x - self.data[2] + 10 < self.screen.screen_width) and (0 <= entity.pos_y - self.data[3] + 3 < self.screen.screen_height):
|
||||
if entity.map_id == self.data[1] and (0 <= entity.pos_x - self.data[2] + self.screen.pos_player[0] < SCREEN_WIDTH) and (0 <= entity.pos_y - self.data[3] + self.screen.pos_player[1] < SCREEN_HEIGHT):
|
||||
self.screen.set_cell(entity.pos_x, entity.pos_y, entity.symbol)
|
||||
|
||||
self.screen.set_cell(self.data[2], self.data[3], player)
|
||||
|
||||
# Display map, get the key and update key buffer
|
||||
key = convert(self.screen.display())
|
||||
# Display map, low bar, get the key and update key buffer
|
||||
if low_bar: bar = low_bar(self.data[:], self.stat[:])
|
||||
else: bar = None
|
||||
key = convert(self.screen.display(low_bar=bar))
|
||||
if not key: key = self.data[4]
|
||||
else: self.data[4] = key
|
||||
|
||||
|
@ -215,11 +222,10 @@ class Asci:
|
|||
|
||||
# Classes used by Asci
|
||||
class Screen:
|
||||
def __init__(self, screen_width=21, screen_height=6):
|
||||
def __init__(self):
|
||||
# Screen configuration
|
||||
self.screen_width = screen_width
|
||||
self.screen_height = screen_height
|
||||
self._on_screen = [[" " for _ in range(screen_width)] for _ in range(screen_height)]
|
||||
self.pos_player = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
|
||||
self._on_screen = [[" " for _ in range(SCREEN_WIDTH)] for _ in range(SCREEN_HEIGHT)]
|
||||
self._asci_data = []
|
||||
|
||||
def load_data(self, data):
|
||||
|
@ -234,23 +240,27 @@ class Screen:
|
|||
self.map_height = len(self._world)
|
||||
|
||||
def set_screen(self):
|
||||
x = self._asci_data[2] - 10 ; y = self._asci_data[3] - 3
|
||||
for x_map in range(x, x + self.screen_width):
|
||||
for y_map in range(y, y + self.screen_height):
|
||||
x = self._asci_data[2] - self.pos_player[0] ; y = self._asci_data[3] - self.pos_player[1]
|
||||
for x_map in range(x, x + SCREEN_WIDTH):
|
||||
for y_map in range(y, y + SCREEN_HEIGHT):
|
||||
self._on_screen[y_map - y][x_map - x] = " "
|
||||
if 0 <= x_map < self.map_width and 0 <= y_map < self.map_height:
|
||||
try: self._on_screen[y_map - y][x_map - x] = self._world[y_map][x_map]
|
||||
except: pass
|
||||
|
||||
|
||||
def display(self, return_input=True):
|
||||
for line in self._on_screen:
|
||||
print("".join(line))
|
||||
|
||||
if return_input: return input(">")
|
||||
def display(self, return_input=True, low_bar=None):
|
||||
for line_no in range(len(self._on_screen)):
|
||||
line = "".join(self._on_screen[line_no])
|
||||
if line_no + 1 == SCREEN_HEIGHT and return_input:
|
||||
if not low_bar: line = line[:-6] + ">"
|
||||
else: line = low_bar + ">"
|
||||
print(line, end="")
|
||||
return input()
|
||||
else:
|
||||
print(line)
|
||||
|
||||
def clear(self):
|
||||
print("\n" * self.screen_height)
|
||||
print("\n" * SCREEN_HEIGHT)
|
||||
|
||||
def display_text(self, string):
|
||||
paragraphs = [i for i in text_formater(string) if i]
|
||||
|
@ -262,18 +272,19 @@ class Screen:
|
|||
else: input()
|
||||
|
||||
def set_cell(self, x, y, value):
|
||||
x = x - (self._asci_data[2] - 10)
|
||||
y = y - (self._asci_data[3] - 3)
|
||||
if 0 <= x < self.screen_width and 0 <= y < self.screen_height:
|
||||
x = x - (self._asci_data[2] - self.pos_player[0])
|
||||
y = y - (self._asci_data[3] - self.pos_player[1])
|
||||
if 0 <= x < SCREEN_WIDTH and 0 <= y < SCREEN_HEIGHT:
|
||||
self._on_screen[y][x] = value
|
||||
|
||||
def get_cell(self, x, y):
|
||||
x = x - (self._asci_data[2] - 10)
|
||||
y = y - (self._asci_data[3] - 3)
|
||||
if 0 <= x < self.screen_width and 0 <= y < self.screen_height:
|
||||
x = x - (self._asci_data[2] - self.pos_player[0])
|
||||
y = y - (self._asci_data[3] - self.pos_player[1])
|
||||
if 0 <= x < SCREEN_WIDTH and 0 <= y < SCREEN_HEIGHT:
|
||||
return self._on_screen[y][x]
|
||||
else: return " "
|
||||
|
||||
|
||||
class Event:
|
||||
def __init__(self, xp, text, answer=0, *stat):
|
||||
self.xp = xp
|
||||
|
@ -299,11 +310,13 @@ class Entity:
|
|||
self.behavior = behavior
|
||||
self.args = list(args)
|
||||
|
||||
def change_behavior(self, new_behavior):
|
||||
if self.behavior != "permanent": self.behavior = new_behavior
|
||||
def change_behavior(self, new_behavior, *args):
|
||||
if self.behavior != "permanent":
|
||||
self.behavior = new_behavior
|
||||
self.args = list(args)
|
||||
|
||||
def teleport(self, map_id, x, y):
|
||||
if self.behavio != "permanent": self.map_id, self.pos_x, self.pos_y = map_id, x, y
|
||||
if self.behavior != "permanent": self.map_id, self.pos_x, self.pos_y = map_id, x, y
|
||||
|
||||
|
||||
# Functions used by Asci
|
||||
|
@ -314,34 +327,35 @@ def convert(string, force_int=False):
|
|||
else: return string
|
||||
|
||||
|
||||
def text_formater(string, screen_width=21, screen_height=6):
|
||||
def text_formater(string):
|
||||
screen_displayable_height = SCREEN_HEIGHT - 1
|
||||
|
||||
def line_formater(string, screen_width):
|
||||
def line_formater(string):
|
||||
string_result = ""
|
||||
while len(string) > screen_width:
|
||||
stop_index = screen_width
|
||||
while len(string) > SCREEN_WIDTH:
|
||||
stop_index = SCREEN_WIDTH
|
||||
while stop_index > 0 and not string[stop_index].isspace(): stop_index -= 1
|
||||
if not stop_index: stop_index = screen_width
|
||||
if not stop_index: stop_index = SCREEN_WIDTH
|
||||
|
||||
string_result += string[:stop_index].strip() + "\n"
|
||||
string = string[stop_index:].strip()
|
||||
|
||||
return string_result + string
|
||||
|
||||
def paragraph_formater(lines, screen_height):
|
||||
def paragraph_formater(lines):
|
||||
paragraphs = ""
|
||||
while len(lines) >= screen_height:
|
||||
paragraphs += "\n".join(lines[:screen_height]) + "\n\n"
|
||||
lines = lines[screen_height:]
|
||||
while len(lines) >= screen_displayable_height:
|
||||
paragraphs += "\n".join(lines[:screen_displayable_height]) + "\n\n"
|
||||
lines = lines[screen_displayable_height:]
|
||||
|
||||
return paragraphs + "\n".join(lines)
|
||||
|
||||
lines = []
|
||||
for line in string.split("\n"):
|
||||
for formated_line in line_formater(line, screen_width).split("\n"):
|
||||
for formated_line in line_formater(line).split("\n"):
|
||||
lines.append(formated_line)
|
||||
|
||||
return paragraph_formater(lines, screen_height).split("\n\n")
|
||||
return paragraph_formater(lines).split("\n\n")
|
||||
|
||||
|
||||
def read_event(data, event, quest):
|
||||
|
@ -378,29 +392,11 @@ def get_multi_move(key):
|
|||
return [(convert(k), 1) for k in key]
|
||||
|
||||
|
||||
|
||||
# Extra functions
|
||||
def print_text(text, min_value=0, max_value=0, default_value=0):
|
||||
paragraphs = [i for i in text_formater(text) if i]
|
||||
nb = len(paragraphs)
|
||||
for index in range(nb):
|
||||
print("\n" * 7)
|
||||
print(paragraphs[index])
|
||||
|
||||
if index + 1 == nb and (min_value or max_value or default_value) and min_value <= max_value:
|
||||
result = input(">")
|
||||
try: result = int(result)
|
||||
except: result = default_value
|
||||
if not (min_value <= result <= max_value): result = default_value
|
||||
|
||||
return result
|
||||
|
||||
else: input()
|
||||
|
||||
|
||||
# Motions functions
|
||||
def stand_by(entity, data, stat, screen, walkable):
|
||||
pass
|
||||
|
||||
|
||||
def permanent(entity, data, stat, screen, walkable):
|
||||
pass
|
||||
|
||||
|
@ -410,10 +406,26 @@ def follow(entity, data, stat, screen, walkable):
|
|||
entity.pos_x, entity.pos_y = data[2], data[3]
|
||||
|
||||
elif data[4] in (1, 2, 3, 5):
|
||||
direction = (data[4] - 1) if data[4] != 5 else 3
|
||||
|
||||
if entity.args: walkable += entity.args[0]
|
||||
cases = ((data[2] + 1, data[3]), (data[2], data[3] - 1), (data[2] - 1, data[3]), 0, (data[2], data[3] + 1))[data[4] - 1]
|
||||
if not (0 <= cases[0] < screen.map_width and 0 <= cases[1] < screen.map_height): entity.pos_x, entity.pos_y = data[2], data[3]
|
||||
elif screen.get_cell(cases[0], cases[1]) in walkable: entity.pos_x, entity.pos_y = cases
|
||||
|
||||
cases = [(data[2] + 1, data[3]), (data[2], data[3] - 1), (data[2] - 1, data[3]), (data[2], data[3] + 1)]
|
||||
pos = cases[direction]
|
||||
|
||||
if not (0 <= pos[0] < screen.map_width and 0 <= pos[1] < screen.map_height) or (not screen.get_cell(pos[0], pos[1]) in walkable):
|
||||
find = False
|
||||
cases.remove(cases[(direction + 2) % 4])
|
||||
for pos in cases:
|
||||
if (0 <= pos[0] < screen.map_width and 0 <= pos[1] < screen.map_height) and (screen.get_cell(pos[0], pos[1]) in walkable):
|
||||
find = True
|
||||
entity.pos_x, entity.pos_y = pos
|
||||
break
|
||||
if not find:
|
||||
entity.pos_x, entity.pos_y = data[2], data[3]
|
||||
|
||||
else:
|
||||
entity.pos_x, entity.pos_y = pos
|
||||
|
||||
|
||||
def walk_between(entity, data, stat, screen, walkable):
|
||||
|
@ -421,11 +433,12 @@ def walk_between(entity, data, stat, screen, walkable):
|
|||
new_x, new_y = _walk_engine(entity, frame)
|
||||
if screen.get_cell(new_x, new_y) in walkable:
|
||||
entity.pos_x, entity.pos_y = new_x, new_y
|
||||
entity.args[0] = frame
|
||||
if (entity.pos_x, entity.pos_y) == entity.args[1][frame]: entity.args[0] = frame
|
||||
|
||||
|
||||
def walk_to(entity, data, stat, screen, walkable):
|
||||
frame = entity.args[0]
|
||||
print(frame, len(entity.args[1]), entity.args)
|
||||
if len(entity.args[1]) == frame:
|
||||
entity.behavior = "stand by"
|
||||
entity.args = []
|
||||
|
@ -435,7 +448,7 @@ def walk_to(entity, data, stat, screen, walkable):
|
|||
|
||||
if screen.get_cell(new_x, new_y) in walkable:
|
||||
entity.pos_x, entity.pos_y = new_x, new_y
|
||||
entity.args[0] += 1
|
||||
if (entity.pos_x, entity.pos_y) == entity.args[1][frame]: entity.args[0] += 1
|
||||
|
||||
|
||||
def follow_by_player(entity, data, stat, screen, walkable):
|
||||
|
@ -458,4 +471,34 @@ def _walk_engine(entity, frame):
|
|||
new_y = entity.pos_y
|
||||
if delta_x: new_x += abs(delta_x) // delta_x
|
||||
if delta_y: new_y += abs(delta_y) // delta_y
|
||||
return new_x, new_y
|
||||
return new_x, new_y
|
||||
|
||||
|
||||
# Extra functions
|
||||
def print_text(text, min_value=0, max_value=0, default_value=0):
|
||||
paragraphs = [i for i in text_formater(text) if i]
|
||||
nb = len(paragraphs)
|
||||
for index in range(nb):
|
||||
print("\n" * 7)
|
||||
print(paragraphs[index])
|
||||
|
||||
if index + 1 == nb and (min_value or max_value or default_value) and min_value <= max_value:
|
||||
result = input(">")
|
||||
try: result = int(result)
|
||||
except: result = default_value
|
||||
if not (min_value <= result <= max_value): result = default_value
|
||||
|
||||
return result
|
||||
|
||||
else: input()
|
||||
|
||||
|
||||
def center(string, total_length, symbol):
|
||||
left = floor((total_length - len(string)) / 2)
|
||||
right = ceil((total_length - len(string)) / 2)
|
||||
|
||||
return left * symbol + string + right * symbol
|
||||
|
||||
|
||||
def enumerate(data):
|
||||
return [(i, data[i]) for i in range(len(data))]
|
Loading…
Reference in New Issue