ASCII - Asciimatics - 如何在代码中实现效果/屏幕

2024-06-18

几篇文章之前,有人建议我研究一下 Python 的 Asciimatics 库。我正在尝试使用以下方法来解决它:

  • 样品-https://github.com/peterbrittain/asciimatics/tree/master/samples https://github.com/peterbrittain/asciimatics/tree/master/samples
  • 文档 -https://asciimatics.readthedocs.io/en/stable/ https://asciimatics.readthedocs.io/en/stable/

然而,由于我是新手,我对其中的一些非常基本的东西仍然有点困惑。我知道,通过使用效果数组,您可以创建代码层,这些代码层将根据它们在数组中的位置覆盖屏幕上的信息。它们的索引号越小,来自它们的信息就越少(不可见)。

我想在代码中使用它。目标是将墙壁和脚印放在顶层,将蓝色圆圈放在底部。该代码部分有效,因此您仍然可以欣赏我的可视化效果:

# Programs generate exit point along the wall, then spawn bot in random location. 
#He will move around and look for the exit, using different tools. 
#7.0 - Program randomly moves from starting point and makes 9 different steps. 
#It is forbidden for it to step in same place more than one.
#7.1 - Program not only moves, but also interact with the walls. 
#It will not move on any wall or other forbidden point that can be added to the list.
#7.2 - Added circle around the bot that travels with him

from asciimatics.screen import Screen
import os
import random
import math
import time

os.system('mode con: cols=51')


def exit_point():
    ''' Randomly select the wall, where exit point will be.
    Then select one random point along the line(wall) and create there exit point'''
    global exitX
    global exitY

    wall = random.randint(1,4)

    if wall == 1:
        exitX = random.randint(1,49)
        exitY = 0
    elif wall == 2:
        exitX = 49
        exitY = random.randint(1,49)
    elif wall == 3:
        exitX = random.randint(1,49)
        exitY = 49
    elif wall == 4:
        exitX = 0
        exitY = random.randint(1,49)


def start_point():
    ''' Select coordinates for starting point inside the wall zone,
    which is smaller by one then wall size, so it will not spawn it on the wall.'''
    global startX
    global startY

    startX = random.randint(2,48)
    startY = random.randint(2,48)


def setup(screen):
    ''' Creates wall image from #.  Red # represents Exit. 
    Then create starting point and spawn our hero @.'''
    screen.fill_polygon([[(0, 0), (50, 0), (50, 50), (0, 50)],[(1, 1), (49, 1), (49, 49), (1, 49)]])
    exit_point()
    screen.print_at("#", exitX, exitY, 1, 1)
    start_point()
    screen.print_at("@", startX, startY, 2, 1)
    screen.refresh()
    input()


def move(screen):
    ''' - First program will re-create walls, exit point and spawn our hero @.
        - Then the wall is defined as array of points. Points are added to big, 
        global list of forbidden points, where no move can be made
        - To the same list, starting point is added
        - '''

    #bring back setup screen, waste of code but more intuiative
    screen.fill_polygon([[(0, 0), (50, 0), (50, 50), (0, 50)],[(1, 1), (49, 1), (49, 49), (1, 49)]])
    screen.print_at("#", exitX, exitY, 1, 1)
    screen.print_at("@", startX, startY, 2, 1)

    #list of points where new point can not be created
    forbidden_place = []
    wall = []
    for i in range(49):
        point = [i,0]
        wall.append(point)          #wall no. 1
        point = [49,i]          
        wall.append(point)          #wall no. 2
        point = [i,49]          
        wall.append(point)          #wall no. 3
        point = [0,i]           
        wall.append(point)          #wall no. 4

    forbidden_place = wall

    #Add starting point to the forbidden points list
    point = [startX,startY]
    forbidden_place.append(point)

    #moves and looking around animation
    moves = 1
    while moves < 500:  

        #radius around our here where it will see things. Right now it's nothing else like visualisatios. 
        radius = 10
        for i in range(radius):
            XL = -(round(math.sqrt(radius*radius-i*i)))     #XL - X left, for X points on left side of the circle.
            XR =  (round(math.sqrt(radius*radius-i*i)))     #XR - X right, for X points on right side of the circle.
            Y = i                                           #iterated after Y coordinate and calculate X for left and right

            YU =  (round(math.sqrt(radius*radius-i*i)))     #YU - Y up, for Y points on the topside of the circle.
            YD = -(round(math.sqrt(radius*radius-i*i)))     #YD - Y down, for Y points on the downside of the circle.
            X = i                                           #iterated after X coordinate and calculate Y for top and bottom


            if moves > 1:           
                #if is here, otherwise it will use exit point and delete points in circle around it 
                #this part inide the if will clear last points of the radius light, 
                #by using point where hero was one move before
                screen.print_at(" ",  XR + forbidden_place[-2][0], Y  + forbidden_place[-2][1], 4, 1)
                screen.print_at(" ",  XL + forbidden_place[-2][0], Y  + forbidden_place[-2][1], 4, 1)
                #fill all holes after first two lines of the code, by making same circle, but rotated by 90deg
                screen.print_at(" ",  X + forbidden_place[-2][0],  YU + forbidden_place[-2][1], 4, 1)
                screen.print_at(" ",  X + forbidden_place[-2][0],  YD + forbidden_place[-2][1], 4, 1)

                screen.print_at(" ",  XR + forbidden_place[-2][0], -Y  + forbidden_place[-2][1], 4, 1)
                screen.print_at(" ",  XL + forbidden_place[-2][0], -Y  + forbidden_place[-2][1], 4, 1)
                #fill all holes after first two lines of the code, by making same circle, but rotated by 90deg
                screen.print_at(" ", -X + forbidden_place[-2][0],   YU + forbidden_place[-2][1], 4, 1)
                screen.print_at(" ", -X + forbidden_place[-2][0],   YD + forbidden_place[-2][1], 4, 1)  

            screen.print_at("+",  XR + forbidden_place[-1][0], Y  + forbidden_place[-1][1], 4, 1)
            screen.print_at("+",  XL + forbidden_place[-1][0], Y  + forbidden_place[-1][1], 4, 1)       
            screen.print_at("+",  X + forbidden_place[-1][0],  YU + forbidden_place[-1][1], 4, 1)
            screen.print_at("+",  X + forbidden_place[-1][0],  YD + forbidden_place[-1][1], 4, 1)

            screen.print_at("+",  XR + forbidden_place[-1][0], -Y  + forbidden_place[-1][1], 4, 1)
            screen.print_at("+",  XL + forbidden_place[-1][0], -Y  + forbidden_place[-1][1], 4, 1)      
            screen.print_at("+", -X + forbidden_place[-1][0],   YU + forbidden_place[-1][1], 4, 1)
            screen.print_at("+", -X + forbidden_place[-1][0],   YD + forbidden_place[-1][1], 4, 1)      

        #refresh wall visualisation, otherwise it would be 'eaten' by light. 
        #This part will be deleted after I learn how to use effects/scenes
        screen.fill_polygon([[(0, 0), (50, 0), (50, 50), (0, 50)],[(1, 1), (49, 1), (49, 49), (1, 49)]])
        screen.print_at("#", exitX, exitY, 1, 1)    

        #this part will generate movement points for our here. 
        #It will do it's best to not step in same place twice. So here will most likely stuck at some point. 
        #In future, there will be more logic that will allow him to move over his steps, if no other way is possible.
        moveX = forbidden_place[-1][0] + random.randint(-1,1)
        if moveX == forbidden_place[-1][0]:     
            moveY = forbidden_place[-1][1] + random.randrange(-1,2,2)   #select between -1 and 1, but not 0
        else:
            moveY = forbidden_place[-1][1] + random.randint(-1,1)       #select between -1 and 1, including 0
        point = [moveX,moveY]
        if point not in forbidden_place: 
            forbidden_place.append(point)
            screen.print_at(".", forbidden_place[-2][0], forbidden_place[-2][1], 2, 1) #footprint of the hero
            screen.print_at("@", moveX, moveY , 3, 1)                                  #hero's current position
            moves = moves + 1
        else:
            moveX = forbidden_place[-1][0]  #if point is already on the list, to prevent it overwrite variable moveX and moveY
            moveY = forbidden_place[-1][1]  #the program will clear it, by assigning it to last legit value from trace list,
        time.sleep(0.1)
        screen.refresh()
    input()

Screen.wrapper(setup)
Screen.wrapper(move)
input()

这完全取决于您如何实现新效果...... 简而言之,您需要一个清除旧图像的策略。

为应用程序添加动画效果的最佳方法是使用双缓冲 https://en.m.wikipedia.org/wiki/Multiple_buffering#Double_buffering_in_computer_graphics然后重新绘制每个新图像。这是 asciimatics 内部使用的技术,用于防止重画屏幕时出现伪影。不幸的是,当您交换缓冲区(刷新时)时,它不会清除屏幕,因此您需要自己执行此操作(在 v1.x 中)。完成此操作后,您可以根据需要绘制叠加层,如果有帮助的话,可以使用单独的效果。

例如,如果您将墙壁设置为底部效果,并在绘制墙壁的同时清除整个屏幕,那么您的其他效果只需绘制当前图像而无需清除旧图像。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASCII - Asciimatics - 如何在代码中实现效果/屏幕 的相关文章

随机推荐

  • 使用 Beautifulsoup 抓取多个网站

    我想知道为什么列出all links and all titles不想接收列表中的任何记录titles and links 我也尝试过 extend 方法 但没有帮助 import requests from bs4 import Beau
  • 泛型和系统集合

    迁移到 NET 2 0 后 是否还有理由继续使用 systems Collections 命名空间 除了维护遗留代码之外 是否应该始终使用泛型命名空间 在大多数情况下 泛型集合的执行速度比非泛型集合更快 并且为您带来强类型集合的好处 比较
  • 挂钩 jQuery 验证消息更改

    我想在工具提示中显示 jQuery 验证消息 为了实现这一目标 我首先将以下 CSS 规则添加到我的样式表中 fieldset field validation error display none fieldset field valid
  • 使用通配符分割字符串

    我有一个变量字符串 其中包含我需要的值和拆分器 问题是 字符串的长度是可变的 分割器的类型也是可变的 它们通过 XML 文件到达 字符串将如下所示 1 20 51 2 name jpg 但也可以是 1 20 51 name jpg 坚实的因
  • 如何使用 Clang 编译器和 CMake 进行分析

    Question 1 What output我应该期待当我想使用进行分析时clang编译器 2 我该怎么办profiling for a C project它使用clang作为编译器andCMake 作为构建工具 重新分析我所使用的内容 1
  • cellForRowAtIndexPath 中的框架没有变化

    我想改变x位置框架view细胞内的cellForRowAtIndexPath对于某些条件 我使用了以下代码 但并不改变看法x position frame void viewDidLoad super viewDidLoad UINib n
  • Android WebView视频关闭全屏视图后,webview自动滚动

    我在用WebView显示包含文本和视频内容的网页 它按预期正确加载和显示视频 但是当我进入视频的全屏视图时 我按照给定的方式实现了全屏视频视图here https github com akhgupta WebviewVideo 然后回到W
  • Opencv C++ 检测并裁剪图像上的白色区域

    我在网上搜索过 已经找到了一些方法来完成我想要的事情 但是与我需要的相比 这些方法的效率较低 我有一个 kinect 使用 Microsoft SDK 当前正在获取一个移除背景的人 将结果保存在 3 通道 Mat 中 并将该人从背景中移除
  • Python,Pandas:每两行一起平均

    非常基本的问题 但想知道 在 pandas Dataframe 中对每 2 行进行平均的 正确 方法是什么 因此最终只有一半的行数 请注意 这与rolling mean 不同 因为它减少了条目数 一种快速的方法 gt gt gt s pd
  • 为什么 HTML5 DOCTYPE 会扰乱我的填充?

    我有一个带有导航栏的 html5 页面 完全从头开始编码 我最近刚刚向该项目添加了一个文档类型 现在我在导航栏下获得了额外的空间 如果我删除文档类型声明 它就会恢复正常 我已经完全重置了所有内容的填充 边距等 并将其缩减为说明问题的少量代码
  • 寻找两个框架之间的变换

    我有来自视频源的两个连续帧 并且我使用 FAST 算法检测这两个帧的关键点 我使用平方差之和法 SSD 来匹配关键点 所以基本上我已经匹配了两个框架之间的关键点 现在我想根据匹配的关键点集计算两个帧之间的仿射变换 缩放 旋转 平移 我知道如
  • 如何在表格单元格中插入输入字段?

    抱歉 新手问题 我想创建一个包含输入字段的表 如果需要 可以在其中添加新字段 但我不知道如何在已经存在另一个输入字段的单元格内添加另一个输入字段 我的代码是 var par obj parentNode while par nodeName
  • JavaScript 闭包

    我读到闭包末尾的 会立即执行它 那么 这两者有什么区别呢 我在一些代码中看到了第一个用法 thanks for var a selectsomeobj i 0 len a length i
  • 如何将 SPA 嵌入 ASP.NET Core 库并从路径提供服务

    Szenario 我想构建一个 aspnetcore 库 模块includes一个小的SPA前端 IE html js css 文件应与 dll 一起提供 SPA 应从特定路径提供服务 即 some module does not需要可配置
  • 再次返回使用 Rails 3 中的 Rails 2.3.5

    最近 我看到有关Rails 3 0 beta的信息 我想尝试一下 所以我使用gem update并安装了这个版本 但现在 我需要回到 Rails 2 3 5 我怎样才能做到呢 我正在考虑这两个解决方案 卸载 Rails 3 我读到有人使用
  • 在 IntelliJ 中运行 Spark 字数统计

    我花了几个小时浏览 You Tube 视频和教程 试图了解如何在 Scala 中运行 Spark 字数统计程序 并将其转换为 jar 文件 我现在完全糊涂了 我运行了 Hello World 并且了解了如何在 Apache spark sp
  • 使用不包含 Bloc 的上下文调用 BlocProvider.of() - 即使它包含

    首先 我确实知道 BLoC 是如何运作的 它背后的想法 我知道两者之间的区别BlocProvider and BlocProvider value 构造函数 为简单起见 我的应用程序有 3 个页面 其中有一个小部件树 如下所示 App gt
  • 如何在 WinRT XAML Toolkit 折线图中设置轴边距?

    Answer 最后我用这个解决了我的答案 LineSeries MyChart Series 0 IndependentAxis new LinearAxis Minimum 1 Maximum 5 Orientation AxisOrie
  • Java ArrayList 实现中的类型擦除

    我正在阅读这篇文章Java 泛型 http www ibm com developerworks library j jtp01255 index html那里提到了一个构造函数ArrayList看起来有点像这样 class ArrayLi
  • ASCII - Asciimatics - 如何在代码中实现效果/屏幕

    几篇文章之前 有人建议我研究一下 Python 的 Asciimatics 库 我正在尝试使用以下方法来解决它 样品 https github com peterbrittain asciimatics tree master sample