现在开始进入计算机图形学的领域~在这里,我们将重新认识Allegro--一个图像引擎.从这个例子开始,将是一段艰难的旅程!所以,别掉队了~
http://wiki.allegro.cc/AllegroExamples 以上是英文例子站点。
Shawn Hargreaves,allegro的作者
目录: 1 Allegro 例子
1.1 exhello
1.2 exmem
1.3 expat
1.4 expal
1.5 exflame
1.6 exbuf
1.7 exflip
1.8 exfixed
1.9 exfont
1.10exmouse
1.11extimer
1.12exkeys
1.16exgui
1.17excustoms
1.21exconfig
1.23exsprite
/*
* Example program for the Allegro library, by Grzegorz Ludorowski.
*
* 这个例子展示了如何使用datafile,以及一些绘制精灵的方法。
* 并且通过消除闪烁来完美展现画面.
*
* 为什么animate()函数会那样编写?
* 可能你已经知道了,读取显存要比读取内存慢的多,
* 所以明智的做法是尽可能少的使用VRAM blits.
* 在(存储在VRAM中的)“屏幕”上绘制精灵并用一个背景来清理它
* 是很慢的.这个例子使用了一种不同的方法,但是要快的多,
* 只不过它需要申请一些额外的内存.
*
* 首先位图指针被清理(这是内存位图),然后将精灵画在上面,
* 当绘制完成, 这个指针将立即被复制到屏幕上.
* 最后的结果就是,我们仅使用了VRAM blit一步,省略了清理、blitting背景、
* 在上面绘制精灵(3步).当你不得不重新装载背景的时候,这也是一种好方法.
* 当然,这种方法完全消除了闪烁效果.
*
* 当使用很大的位图空间 (ie. 800x600的背景) 并且在上面绘制时,
* 明智的做法是在内存中创建一个背景的副本,然后重新装载这个
* 虚拟背景.在SVGA模式下,使用VRAM来做这个事,它很可能做例行测试,
* 以便确定哪里有位置来放置这个位图空间,我想我不需要提醒那会
* 慢成什么鬼样子.
*
* 注意,在现代系统中,上面的情况也不一定正确,
* 通常你会把VRAM中的特效放到超高速缓存中,
* 这样只需要做VRAM->VRAM的blits,从而获得极佳的性能
* 这样的话,根本就不需要RAM->VRAM的转换了.
* 通常这样的转换(VRAM->VRAM)会很好的以并行的方式在GPU中运行,
* 因此实际上完全不占用CPU的时间
* 例子exaccel就是这样的情况.
*/
#include <math.h>
#include <allegro.h>
#include "running.h"
#define FRAMES_PER_SECOND 30
/*为动画设置一个计时器 */
volatile int ticks = 0;
void ticker(void)
{
ticks++;
}
END_OF_FUNCTION(ticker)
/* pointer to data file */
DATAFILE *running_data;
/*桢和当前桢 */
int frame, frame_number = 0;
/*一个指向精灵的指针 */
BITMAP *sprite_buffer;
/*这是关于控制演示例程的 */
int next;
void animate(void)
{
/* 等待动画计时器. */
while (frame > ticks) {
/* 空的等待. */
rest(1);
}
/* 为了更完美的显示,我们应该为一个多桢的动画速度
*设置刷新率监视器,从而代替使用计时器.
* 并且通过垂直扫描来同步 - 来获得完全平滑的动画
* 但是这种方法不适合于所有的设置模式(e.g. in X11 windowed modes),
* 因此首先应该做一些测试,或者让用户自己来设置.
* 这样的例子太多了 (实际上这个例子并没有使用垂直扫描同步,
* 这里的文字只是告诉我们存在着更好的方法)
*/
frame++;
/*向屏幕绘制精灵 */
blit(sprite_buffer, screen, 0, 0, (SCREEN_W - sprite_buffer->w) / 2,
(SCREEN_H - sprite_buffer->h) / 2, sprite_buffer->w, sprite_buffer->h);
/*清除精灵指针 */
clear_bitmap(sprite_buffer);
/*如果有按键按下则进入下一步演示*/
if (keypressed())
next = TRUE;
else
next = FALSE;
if (frame_number == 0)
play_sample(running_data[SOUND_01].dat, 128, 128, 1000, FALSE);
/* 递增桢数,如果等于9,则将它归0*/
if (frame_number == 9)
frame_number = 0;
else
frame_number++;
}
int main(int argc, char *argv[])
{
char datafile_name[256];
int angle = 0;
int x, y;
int text_y;
int color;
if (allegro_init() != 0)
return 1;
install_keyboard();
install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
install_timer();
LOCK_FUNCTION(ticker);
LOCK_VARIABLE(ticks);
install_int_ex(ticker, BPS_TO_TIMER(30));
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Unable to set any graphic mode\n%s\n",
allegro_error);
return 1;
}
}
/*读取datafile并用用户存储在其中的调色板初始化 */
replace_filename(datafile_name, argv[0], "running.dat",
sizeof(datafile_name));
running_data = load_datafile(datafile_name);
if (!running_data) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Error loading %s!\n", datafile_name);
return 1;
}
/* select the palette which was loaded from the datafile */
set_palette(running_data[PALETTE_001].dat);
/* 创建和清理一个精灵位图,
* 要足够大,应该是对角线的长度,以便在旋转时不会丢失画面*/
sprite_buffer = create_bitmap((int)(82 * sqrt(2) + 2),
(int)(82 * sqrt(2) + 2));
clear_bitmap(sprite_buffer);
x = (sprite_buffer->w - 82) / 2;
y = (sprite_buffer->h - 82) / 2;
color = makecol(0, 80, 0);
text_y = SCREEN_H - 10 - text_height(font);
frame = ticks;
/*在屏幕上写明当前的精灵绘制方法 */
textout_centre_ex(screen, font, "Press a key for next part...",
SCREEN_W / 2, 10, palette_color[1], -1);
textout_centre_ex(screen, font, "Using draw_sprite",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y + 82, sprite_buffer->w - 1, color);
draw_sprite(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Using draw_sprite_h_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y + 82, sprite_buffer->w - 1, color);
draw_sprite_h_flip(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Using draw_sprite_v_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y - 1, sprite_buffer->w - 1, color);
draw_sprite_v_flip(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Using draw_sprite_vh_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y - 1, sprite_buffer->w - 1, color);
draw_sprite_vh_flip(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Now with rotating - pivot_sprite",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
/* pivot_sprite()的最后一个参数是fixed类型,
*因此我必须使用itofix()来转换(int 转 fixe).
*/
circle(sprite_buffer, x + 41, y + 41, 47, color);
pivot_sprite(sprite_buffer, running_data[frame_number].dat, sprite_buffer->w / 2,
sprite_buffer->h / 2, 41, 41, itofix(angle));
animate();
angle -= 4;
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Now using pivot_sprite_v_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
/* pivot_sprite_v_flip() 的最后一个参数是fixed类型,
*因此我必须使用itofix()来转换(int 转 fixed).
*/
circle(sprite_buffer, x + 41, y + 41, 47, color);
pivot_sprite_v_flip(sprite_buffer, running_data[frame_number].dat,
sprite_buffer->w / 2, sprite_buffer->h / 2, 41, 41, itofix(angle));
animate();
angle += 4;
} while (!next);
unload_datafile(running_data);
destroy_bitmap(sprite_buffer);
return 0;
}
END_OF_MAIN()
----------------------------------------------------------------------------------------------------------------------------
小节二十三:
1、精灵 sprite
其实就是子画面,是动画技术中最常使用的一种方法。再以后的例子中,我会采用“子画面”来称呼它。
2、巾贞 frame
这是一个字-_-#。还记得胶卷式电影带吧,一个桢就对应于一格画面。按一定顺序快速的显示这些桢就会产生动画的效果。一般来说超过24桢/秒(fps)人的眼睛就以为是连续的了。电视机一般为30fps。对应于这个概念,需要设置至少2个参数。当前桢、桢总数。
3、/* 创建和清理一个精灵位图,
* 要足够大,应该是对角线的长度,以便在旋转时不会丢失画面*/
sprite_buffer = create_bitmap((int)(82 * sqrt(2) + 2),(int)(82 * sqrt(2) + 2));
想像一下,以一个矩形的中心为圆点,把矩形旋转360度,矩形的4个顶点的运动轨迹将形成一个圆,这个圆的半径就是对角线的长度。对角线长=sqrt(长^2 + 宽^2), 在这里,将单位换算成了sqrt(2)了,因为位图是正方形,并且位图边长为82,所以对角线就是82*sqrt(2)。这是很简单的数学知识。
4、同步 这个知识点有点难于理解。我将例子中关于同步的代码摘出来放在一起,便于分析。
volatile int ticks = 0;
void ticker(void)
{
ticks++;
}
END_OF_FUNCTION(ticker)
main()
{
install_int_ex(ticker, BPS_TO_TIMER(30));
frame = ticks;
do{
while (frame > ticks) {
rest(1);
}
frame++;
}while(!next)
}
我将animation()函数中关于同步的部分直接替换到了do-while(!next)循环中。这样可以更好的理解这个过程。
1、参与同步的2个变量是frame 和 ticks。
2、 ticks第1次改变是在install_int_ex(ticker, BPS_TO_TIMER(30));执行完毕的时候。这个时候ticks将以每秒30次的速度递增(通过ticker()),并且这种递增速率是不受系统时钟干扰的。
3、第1次同步的时候发生在 frame= ticks。从这里开始,就会神奇将整个图像显示的速度设置为30fps。
4、为了达到30fps的效果,加入了
while (frame > ticks) {
rest(1);
}
frame++;
这段神奇的代码。
执行main()函数是依照系统时钟,
而执行ticks递增则是按照install_int_ex(ticker, BPS_TO_TIMER(30))定义的30fps时钟。
因此这个时候frame++(在main()中)可能会比ticks++(ticker()中)先执行,
为了不让程序执行的太快导致图像显示速度不正常,
因此需要让main() 等一等 ticker()的时钟,也就是在main() 中执行rest(1)。
上面那段就是公式化代码。
当然,在main()的最大fps<定义的fps时,frame>ticks 恒为false,因此如果发生那样的情况的话,没必要添加此同步机制。
或者你可以在自定义时钟里运行rest(1),从而改变参照物--以前是30fps,现在是自定义时钟 = maxfps of main()。但是千万不要这么做,至少在DOS下这样会引起一系列异常。
5、基本绘图函数
hline
circle
绘制子画面函数
draw_sprite
draw_sprite_vh_flip
pivot_sprite
pivot_sprite_v_flip
这些可以参看帮助手册来获得更详细的使用方法。
分享到:
相关推荐
Allegro学习笔记之7_焊盘设计 Allegro学习笔记之7_焊盘设计是Cadence软件设计教程的一部分,主要介绍Allegro系统中的焊盘设计。焊盘设计是PCB设计的重要组成部分,涉及到零件的管脚(Pin)和焊盘的设计。 在...
Allegro学习笔记主要围绕如何在使用Cadence Allegro软件进行PCB设计后,导出Gerber文件和钻孔数据文件,以供PCB制造厂商使用。Gerber文件是PCB制造业的标准光绘文件格式,而钻孔数据文件则用于指导PCB钻孔的过程。 ...
Allegro学习笔记系列 Allegro学习笔记系列是为初学者准备的一系列学习笔记,旨在帮助初学者快速掌握Allegro软件的使用和pcb设计的基础知识。本系列笔记中,我们将从基础的Gerber文件格式开始,逐步深入到Allegro...
《ALLEGRO学习笔记》 在电子设计自动化领域,ALLEGRO是一款广泛应用的PCB设计软件,由Cadence公司开发。这是一份集多年经验于一体的ALLEGRO学习笔记,旨在帮助初学者快速掌握这款强大的工具。 首先,我们从第一章...
总结来说,Cadence Allegro的学习笔记涵盖了软件使用过程中的关键环节,包括焊盘设计、操作选取、敷铜设置、文件格式等重要知识点。通过对比Protel等其他制板软件,记录了Allegro在封装制作、操作逻辑、敷铜操作和...
Orcad_Capture CIS_Allegro学习笔记 Orcad_Capture CIS_Allegro是一款专业的PCB设计软件,旨在帮助用户快速设计和开发电子电路板。下面是Orcad_Capture CIS_Allegro学习笔记中涉及的一些重要知识点: 1. Q&A:...
### Allegro学习笔记之6——热风焊盘 #### 知识点一:焊盘的基本概念 在电子设计自动化(EDA)软件中,焊盘(Pad)是连接元器件引脚与电路板的重要组成部分。在Protel这类软件中,定义焊盘较为简单,只需要设置...
总之,Allegro 16.2的学习涵盖了PCB设计的全过程,从基础的封装创建到复杂的布局布线,都是工程师必备的技能。通过这份笔记,你可以逐步掌握Allegro的各项功能,为高效、高质量的PCB设计打下坚实基础。
Cadence Allegro 16.3 学习笔记 本资源为 Cadence Allegro 16.3 的学习笔记,涵盖了该软件的主要功能和工具。Cadence Allegro 16.3 是一款功能强大的 PCB 设计软件,提供了诸多新功能和改进的界面。 1. Allegro ...
### Allegro层叠详解 #### 一、层叠的基本概念 在电子设计自动化(EDA)领域,Allegro是一款广泛使用的PCB设计软件,尤其在复杂电路板设计方面表现出色。随着电路复杂度的增加,单层或双层PCB往往无法满足设计需求...
以下将从Allegro16.6学习笔记中提炼的关键信息,对知识点进行详细说明。 首先,正片(Positive Image)和负片(Negative Image)是PCB设计中的两个概念。在正片中,设计的图形为铜层,即设计中所见即为铜皮,而在...
Allegro是一款强大的PCB设计软件,用于创建和编辑电路板布局。在电子组装和PCB制造行业中,Gerber文件是至关重要的,因为它们包含了电路板的所有层信息,可供制造商用来制作精确的印刷电路板。以下是对Allegro中导出...
这份Allegro 16.6的入门学习笔记详细记载了学习期间的重要步骤以及注意点,对初次接触Allegro的设计师而言,提供了极具价值的学习资源和实践指南。通过逐章的介绍,可以对整个PCB设计流程有全面的认识,从基础的封装...
《Allegro 16.2学习笔记》是关于电路设计软件Cadence Allegro 16.2的详细教程,涵盖了从基础操作到高级应用的多个方面。以下是对该学习笔记主要内容的概述: 1. **建封装** - **焊盘创建**:焊盘是元器件与PCB板...
### Cadence Allegro 学习应用笔记 #### Cadence软件基础概述 本章节重点介绍了Cadence软件的基础操作,包括安装过程、OrCAD原理图设计以及Allegro PCB设计等内容。这些知识点对于初学者来说非常重要,因为它们是...
二、学习笔记 学习笔记通常包含了用户在实践过程中总结的经验和技巧,是快速理解和记忆Allegro操作的重要资料。你可以从中学习到如何设置工作环境、创建项目、导入原理图、放置元器件、进行布线等基础操作,同时也会...
本篇笔记主要介绍了如何使用Allegro软件设计0603表面贴装封装的过程。 首先,我们需要了解0603封装的基本信息。0603封装是一种常见的贴片元件尺寸,常用于电阻器和电容器,其尺寸为0.6mm x 0.3mm。在设计过程中,...
在Allegro学习笔记中,提到了如何将颜色设置得更为人性化,尤其是将TOP层设为红色,BOTTOM层设为蓝色,以模拟Protel的色彩布局。 首先,要更改颜色设置,可以通过点击工具栏的相应按钮、使用快捷键Ctrl+F5或者选择...
自己的学习心得,给初学allegro的同鞋们一点参考,自己的做的笔记,比找资料要来的快一些。
Allegro学习笔记通常由经验丰富的设计师编写,包含他们在实际工作中遇到的问题和解决方案,以及一些高级技巧和最佳实践。这些笔记可以作为官方文档的补充,帮助读者深入理解Allegro的复杂功能,如高级布线策略、规则...