Mint_21.3 drawing-area和goocanvas的FB笔记(六)

FreeBASIC gfx 基本 graphics 绘图

一、旧故事

DOS时代PC技术将各类硬插卡限制在 640K到1MB的空间范围内,BIOS负责在相关位置写读测试卡的存在,那时期的Color Video在0xB800,Monochrome Video在0xB000,这是显卡的内存地址,字符方式下通常用2个byte共16位显示一个字符,首字节是ASCII值,另外一个字节(8BIT)为属性字节,高4位表示背景色、低4位表示前景色。因为用4位颜色表示,0xF种色彩就是16种颜色,编号 0 - 15。

QuickBASIC示例 - 白字蓝底:
Color 15, 1: Locate 12, 32: Print "Hello World!"

二、FreeBASIC进化

随着视窗的发展,一些复杂的内存管理交给了CPU处理,不再是原来与卡密切相关的固定显存地址,取而代之的是可大可小的窗口。FreeBASIC保留了原有的13种显示模式,同时增加到了21种,达到1280x1024, 160列x128行,256K颜色。

除此之外,继续演进,增加了screenres 指令,可以任意定义窗口尺寸,比如: screenres 1920, 1080, 32, 5, 0, 0 或简写为 screenres 1920, 1080, 32 , 其它参数均为 default 值。它创建一个 1920x1080像素的屏幕(不是实际意义上的屏幕,但仍称其为screen,是个绘图用的surface而已),用32位颜色,5个页面(一个活动可见页面,其它的在内存中不可见,考贝到可见页即可见), 接着的0表示全屏或显示驱动的选择。由于相关定义变得复杂,此时编程需使用 gfxlib 支持。

三、屏幕变为窗口后的编程

1、示例一:屏幕变为窗口

screen 9是640x480标准模式。过去,设置完屏幕方式后即可print或line绘图; 现在,它是一个窗口,因此,可以设置它的标题 WindowTitle "FreeBASIC example program",还可加一句非常简便的无限等待 sleep 语句,直到有按键动作时退出。

Locate 和 Line 都是传统 QBasic 使用的绘图语句。

'' examples/manual/gfx/windowtitle.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'WINDOWTITLE'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgWindowtitle
'' --------
'' Modified: Mongnewer 9, March 2024

'Set screen mode 
Screen 9

'Set the window title
WindowTitle "FreeBASIC example program"

Locate 12, 35: Print "Hello World!"
line (200, 100) - (440, 220), 4, b

Sleep

2、绘图锁定与缩放

在屏幕绘图前先 screenlock, 绘图后 screenunlock, 并通过 window 函数改变座标系而circle本身的参数则无需变化。屏幕上显示一个连续缩放的黄色填充的圆形,锁定的目的是绘图完成后一次性显示到屏幕上,避免了绘制过程的拖慢效果。

'' examples/manual/gfx/window2.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'WINDOW'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgWindow
'' --------

'' The program shows how changing the view coordinates mapping for the current viewport changes the size of a figure drawn on the screen.
'' The effect is one of zooming in and out:
''   - As the viewport coordinates get smaller, the figure appears larger on the screen, until parts of it are finally clipped,
''        because they lie outside the window.
''   - As the viewport coordinates get larger, the figure appears smaller on the screen.
'' ---------------------------------
'' Modified: Mongnewer 9, March 2024

Declare Sub Zoom (ByVal X As Integer)
Dim As Integer X = 500, Xdelta = 50

Screen 12
Do
  Do While X < 525 And X > 50
	X += Xdelta                      '' Change window size.
	Zoom(X)
	If Inkey <> "" Then Exit Do, Do  '' Stop if key pressed.
	Sleep 100
  Loop
  X -= Xdelta
  Xdelta *= -1                       '' Reverse size change.
Loop

Sub Zoom (ByVal X As Integer)
  Window (-X,-X)-(X,X)               '' Define new window.
  ScreenLock
  Cls
  Circle (0,0), 60, 14, , , 0.7, F   '' Draw ellipse with x-radius 60.
  ScreenUnlock
End Sub

3 、view and window, draw string

view 是在screen窗口中创建视图区,而window 语句是视图区的新座标系、不带参数时取消所建立的座标系,Draw string 与 print 类似但又不同, 它不同按行显示字符串,是按 x, y 位置绘制字符串。

'' examples/manual/gfx/window.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'WINDOW'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgWindow
'' --------

Screen 13

'' define clipping area
View ( 10, 10 ) - ( 310, 150 ), 1, 15    

'' set view coordinates
Window ( -1, -1 ) - ( 1, 1 )             

'' Draw X axis
Line (-1,0)-(1,0),7
Draw String ( 0.8, -0.1 ), "X"

'' Draw Y axis
Line (0,-1)-(0,1),7
Draw String ( 0.1, 0.8 ), "Y"

Dim As Single x, y, s

'' compute step size (corresponds to a step of 1 pixel on x coordinate)
s = 2 / PMap( 1, 0 )

'' plot the function
For x = -1 To 1 Step s
  y = x ^ 3
  PSet( x, y ), 14
Next x

'' revert to screen coordinates
Window

'' remove the clipping area
View

'' draw title
Draw String ( 120, 160 ), "Y = X ^ 3"

Sleep

4、在内存中绘像素后显示在屏幕窗口

image pixel , 简写 ip,ip = ImageCreate(64, 64),在内存中创建一个64x64像素的像素块,ip是它的指针。

QBasic原有的PSet后面带上参数 ip, 表示在 ip 内存块pset像素点

screensync 是等待场同步信号,在换场的间隙中把图显示在屏幕窗口上,从而最大限度地减小抖动发生(这个语句的受限点是变换速度被限定在了场频之内),在等待场同步时screenlock后绘图,绘好后screenunlock,将图显示到屏幕上,最后要imagedestroy(ip)销毁创建的像素块。因为在蓝框内有个view, 在view中显示的像素块。

'' examples/manual/gfx/view.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'VIEW (GRAPHICS)'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgViewgraphics
'' --------

Screen 12
Dim ip As Any Ptr
Dim As Integer x, y

'simple sprite
ip = ImageCreate(64,64)
For y = 0 To 63
  For x = 0 To 63
	PSet ip, (x, y), (x\4) Xor (y\4)
  Next x
Next y

'viewport with blue border
Line (215,135)-(425,345), 1, bf
View (220,140)-(420,340)

'move sprite around the viewport
Do

  x = 100*Sin(Timer*2.0)+50
  y = 100*Sin(Timer*2.7)+50
  
  ScreenSync
  ScreenLock
  
  'clear viewport and put image
  Cls 1
  Put (x, y), ip, PSet
	
  ScreenUnlock

Loop While Inkey = ""

ImageDestroy(ip)

5、显示内存的考贝

screenres 创建屏幕窗口。screenset 1, 0 设置工作页为1页(0页为正在显示的画面)。screensync等待场同步信号。screencopy 将工作页面1考贝到显示页面0,完成显示一个移动的红方块。如果将一个跑步者的不同像素块放在不同的工作页面,然后随场同步显示,则是一幅跑步画面。

'' examples/manual/gfx/screenset.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'SCREENSET'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgScreenset
'' --------

' Open graphics screen (320*200, 8bpp) with 2 pages
ScreenRes 320, 200, 8, 2

' Work on page 1 while displaying page 0
ScreenSet 1, 0

Dim As Integer x = -40

Do
	'' Clear the screen, draw a box, update x
	Cls
	Line (x, 80)-Step(39, 39), 4, BF
	x += 1: If (x > 319) Then x = -40
	
	' Wait for vertical sync: only used to control refresh rate, can be put anywhere in the Do loop
	ScreenSync
	
	' Copy work page to visible page
	ScreenCopy
	
Loop While Inkey = ""

6、显示窗口指针

一个正在显示的窗口,实际是一张像素块,它有对应的内存,而内存地址就是显示窗口的指针,在freebasic中用screenptr获得。screeninfo w, h, , bypp, pitch获得屏幕窗口的长、宽、色彩模式和一行的像素数(因此才能知道什么时候换行),在cairo绘图时也会看到这个参数的使用。移动指针、放置数据,即得到欲显示的图像。

'' examples/manual/gfx/screenptr2.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'SCREENPTR'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgScreenptr
'' --------

'Const SCREEN_WIDTH = 256, SCREEN_HEIGHT = 256
Const SCREEN_WIDTH = 1024, SCREEN_HEIGHT = 768
Dim As Long w, h, bypp, pitch

'' Make 32-bit screen.
ScreenRes SCREEN_WIDTH, SCREEN_HEIGHT, 32

'' Get screen info (w and h should match the constants above, bypp should be 4)
ScreenInfo w, h, , bypp, pitch

'' Get the address of the frame buffer. An Any Ptr 
'' is used here to allow simple pointer arithmetic
Dim buffer As Any Ptr = ScreenPtr()
If (buffer = 0) Then
	Print "Error: graphics screen not initialized."
	Sleep
	End -1
End If

'' Lock the screen to allow direct frame buffer access
ScreenLock()
	
	'' Set row address to the start of the buffer
	Dim As Any Ptr row = buffer
	
	'' Iterate over all the pixels in the screen:
	
	For y As Integer = 0 To h - 1
		
		'' Set pixel address to the start of the row
		'' It's a 32-bit pixel, so use a ULong Ptr
		Dim As ULong Ptr pixel = row
		
		For x As Integer = 0 To w - 1
			
			'' Set the pixel value
			*pixel = RGB(x, x Xor y, y) 
			
			'' Get the next pixel address 
			'' (ULong Ptr will increment by 4 bytes)
			pixel += 1
			
		Next x
		
		'' Go to the next row
		row += pitch
		
	Next y

'' Unlock the screen.
ScreenUnlock()

'' Wait for the user to press a key before closing the program
Sleep

7、获得鼠标和键盘事件

需要 fbgfx.bi 支持,event 是freebasic中的一个type类,它含有事件的名称和附带参数。 Dim e as event 定义 e 为 event 类 ;  if (screenEvent(@e)) then 是如果有事件发生; e.type 是查看发生的事件。 e.scancode 是查看键盘扫描码; e.ascii 是按下键的ascii值; e.dx, e.dy是鼠标的位置; e.button是按的左键或右键, 如果左右键同时按,被视为中间键。

'' examples/manual/gfx/screenevent.bas
''
'' Example extracted from the FreeBASIC Manual
'' from topic 'SCREENEVENT'
''
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgScreenevent
'' --------

'' include fbgfx.bi for some useful definitions
#include "fbgfx.bi"
#if __FB_LANG__ = "fb"
Using fb '' constants and structures are stored in the FB namespace in lang fb
#endif

Dim e As Event

ScreenRes 640, 480
Do
	If (ScreenEvent(@e)) Then
		Select Case e.type
		Case EVENT_KEY_PRESS
			If (e.scancode = SC_ESCAPE) Then
				End
			End If
			If (e.ascii > 0) Then
				Print "'" & e.ascii & "'";
			Else
				Print "unknown key";
			End If
			Print " was pressed (scancode " & e.scancode & ")"
		Case EVENT_KEY_RELEASE
			If (e.ascii > 0) Then
				Print "'" & e.ascii & "'";
			Else
				Print "unknown key";
			End If
			Print " was released (scancode " & e.scancode & ")"
		Case EVENT_KEY_REPEAT
			If (e.ascii > 0) Then
				Print "'" & e.ascii & "'";
			Else
				Print "unknown key";
			End If
			Print " is being repeated (scancode " & e.scancode & ")"
		Case EVENT_MOUSE_MOVE
			Print "mouse moved to " & e.x & "," & e.y & " (delta " & e.dx & "," & e.dy & ")"
		Case EVENT_MOUSE_BUTTON_PRESS
			If (e.button = BUTTON_LEFT) Then
				Print "left";
			ElseIf (e.button = BUTTON_RIGHT) Then
				Print "right";
			Else
				Print "middle";
			End If
			Print " button pressed"
		Case EVENT_MOUSE_BUTTON_RELEASE
			If (e.button = BUTTON_LEFT) Then
				Print "left";
			ElseIf (e.button = BUTTON_RIGHT) Then
				Print "right";
			Else
				Print "middle";
			End If
			Print " button released"
		Case EVENT_MOUSE_DOUBLE_CLICK
			If (e.button = BUTTON_LEFT) Then
				Print "left";
			ElseIf (e.button = BUTTON_RIGHT) Then
				Print "right";
			Else
				Print "middle";
			End If
			Print " button double clicked"
		Case EVENT_MOUSE_WHEEL
			Print "mouse wheel moved to position " & e.z
		Case EVENT_MOUSE_ENTER
			Print "mouse moved into program window"
		Case EVENT_MOUSE_EXIT
			Print "mouse moved out of program window"
		Case EVENT_WINDOW_GOT_FOCUS
			Print "program window got focus"
		Case EVENT_WINDOW_LOST_FOCUS
			Print "program window lost focus"
		Case EVENT_WINDOW_CLOSE
			End
		Case EVENT_MOUSE_HWHEEL
			Print "horizontal mouse wheel moved to position " & e.w
		End Select
	End If

	Sleep 1
Loop

至此,应该可以写个简单的石头剪刀布游戏了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/446407.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法学习之动态规划DP——背包问题

一、01背包问题 &#xff08;一&#xff09;题目 有 N 件物品和一个容量是 V的背包。每件物品只能使用一次。 第i件物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值…

前后端交互理解 简易表白墙(servlet)

前后端交互理解 简易表白墙&#xff08;servlet&#xff09; 文章目录 前后端交互理解 简易表白墙&#xff08;servlet&#xff09;后端核心内容前后端交互接口约定后端代码展示 上期介绍过 Servlet API &#xff0c;本篇文章目的是借助 servlet 做出一个完整的网站。在一个网站…

51单片机基础篇系列-人人都能学会单片机

&#x1f308;个人主页: 会编程的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 什么是单片机 在一片集成电路芯片上集成计算机所有基 本部分&#xff08;中央处理器CPU、存储器RAM、ROM、 定时计数器T/C&#xff0c;输入输出接口IO、中断系 统&#xff09;都集成…

【UVM_phase objection_2024.03.08

phase 棕色&#xff1a;function phase 不消耗仿真时间 绿色&#xff1a;task phase 消耗仿真时间 run_phase与右边的phase并行执行&#xff0c;右边的phase&#xff08;run_time phase&#xff09;依次执行&#xff1a; List itemreset_phase对DUT进行复位&#xff0c;初始…

Elastic Stack--07--JavaAPI----文档(新增 、修改 、 查询 、 删除)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 JavaAPI-文档1.新增 Insert2.修改 Update3.查询 Get4.删除 Delete5.批量操作 BulkRequest批量新增批量删除 高级查询1.查询所有索引数据2.条件查询3.分页查询4.查询…

代码随想录算法训练营Day39 || leetCode 762.不同路径 || 63. 不同路径 II

62.不同路径 每一位的结果等于上方与左侧结果和 class Solution { public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m,vector(n,0));for (int i 0; i < m; i) dp[i][0] 1;for (int j 0; j < n; j) dp[0][j] 1;for (int i 1; i < m; …

基于raft的kvDB

1 raft共识算法 raft是强leader模型&#xff0c;通过选举leader来实现一致性&#xff0c;leader拥有完全的能力来管理复制日志。leader从客户端获取日志条目&#xff0c;复制到其他的服务器中&#xff0c;告诉他们什么时候应用这个日志到状态机是安全的。 leader这个角色简化…

实现“ 字体逐渐展现 ”程序

本期介绍&#x1f356; 主要介绍&#xff1a;如何实现在屏幕上从两边向中间逐渐打印字符串。 题目&#xff1a;编写字体逐渐展现程序&#xff0c;功能是&#xff1a;多个字符从两端向中逐渐间显现&#xff0c;直到全部显示为止。举个例子&#xff0c;要逐渐显示“hello world ”…

MEMTO: Memory-guided Transformer for Multivariate Time Series Anomaly Detection

目录 一、问题与思路1.1 现存问题1.2 解决思路 二、模型与方法2.1 模型概览2.2 Encoder and decoder2.3 门控存储器模块2.3.1 门控存储器更新阶段2.3.2 查询更新阶段2.3.3 损失函数2.3.4 初始化内存项2.3.5 异常评分2.3.6 阈值设定 三、实验与分析3.1 模型结果3.2 消融实验3.3 …

宝塔一键迁移报错创建失败问题完美解决

很多站长朋友在使用宝塔面板迁移的时候总是出错&#xff0c;如图&#xff1a; 遇到这样的问题不要慌&#xff0c;我们已经完美处理&#xff0c;详细解决教程&#xff1a;宝塔一键迁移报错问题完美解决教程

深入理解操作系统Operator System(2)

目录 操作系统对上的管理 系统调用接口 用户操作接口&#xff08;库函数&#xff09; 系统调用和库函数的概念 结构层次示意图 总结 为什么要有操作系统❓ 上次主要介绍了操作系统的"管理"和操作系统对下的管理。本篇主要是对上的管理。 操作系统对上的管理 …

Linux智能网关结合Node-RED实现实时工业数据采集

工业4.0的发展&#xff0c;物联网技术在制造业中的应用越来越广泛。其中&#xff0c;基于Linux系统的工业物联网智能网关因其开放性、稳定性和安全性而备受青睐。这类智能网关创新性地集成了开源工具Node-RED&#xff0c;为从各种工业设备&#xff08;如PLC&#xff09;中高效收…

安装torch以及版本对应问题

首先查看cuda版本&#xff1a;winR 输入&#xff1a;nvidia -smi 我的cuda版本12.2&#xff0c;安装的torch版本要小于12.2 我的pip/conda源都改成清华源了&#xff0c;torch2.0以上的版本截止到2024年3月10日也没有。 pytorch官网&#xff1a;https://pytorch.org/ 寻找匹配…

关于比特币的AI对话

【ChatGPT】 比特币源码开源吗&#xff1f; 是的&#xff0c;比特币的源码是开源的。比特币项目是在MIT许可证下发布的&#xff0c;这意味着任何人都可以查看、修改、贡献和分发代码。比特币的源码托管在GitHub上&#xff0c;可以通过下面的链接进行访问&#xff1a; https://g…

注意!!墙裂推荐几个好用的实用小工具!一定会用到的!

前言 在开发的世界里&#xff0c;面对各种挑战和问题时&#xff0c;拥有一套合适的工具箱至关重要。这不仅能提升我们的工作效率&#xff0c;还能让复杂的任务变得简单&#xff0c;甚至在解决棘手问题的同时&#xff0c;还能让我们的心情略微舒畅。众所周知&#xff0c;有用的…

【EtherCAT实践篇】九、EtherCAT增加变量示例:增加浮点数输入变量

目的&#xff1a;在EtherCAT开发板上IO程序基础上进行修改&#xff0c;将原来的16位整数型数据Analog input改为32位浮点数&#xff0c;基于STM32F405底板。 1、XML配置修改 1.1 更改数据类型 ETG1020基础数据中包括浮点数 REAL&#xff0c;可以直接使用浮点数。 这里在xml…

MySQL索引+常见问题详解

网络上的讲述MySQL索引的文章太多了&#xff0c;我打算换个角度来说。我们尝试着从设计者的角度思考&#xff0c;索引为什么这么设计。 假如你是索引的设计者&#xff0c;你会如何设计索引。我们不妨以新华字典为例。如果我们要查询汉字爱是什么意思&#xff0c;我们有如下操作…

【读书笔记】针对ICS的ATTCK矩阵详解(一)

Techniques - ICS | MITRE ATT&CKhttps://attack.mitre.org/techniques/ics/ 一、初始访问&#xff08;Initial Access&#xff09; 该阶段&#xff1a;攻击者正在尝试进入ICS环境。 初始访问包括攻击者可能用作入口向量&#xff0c;从而可以在 ICS 环境中获得初始立足点的…

怎么在学习强国网上发布文章,学习强国投稿发稿方法途径,附学习强国多少钱价格明细表

学习强国是一款受用户欢迎的学习软件&#xff0c;许多人希望在其平台上发布自己的文章&#xff0c;以分享和传播自己的学习成果和心得体会。那么&#xff0c;怎么在学习强国网上发布文章呢&#xff1f;接下来&#xff0c;我们将介绍一些投稿发稿的方法和途径。 首先&#xff0c…

PLC的FC与FB模块程序的功能解析

前文讲了在西门子系列的PLC中四个程序模块的描述&#xff0c;从S7-1200PLC开始就有FC和FB程序块了&#xff0c;但在使用的时候&#xff0c;一些使用者还是不好理解&#xff0c;以至于不知道该如何选择。今天&#xff0c;我们就用大白话的方式给大家讲解FC与FB的功能。 1、FC与…