对比python学julia(第三章:游戏编程)--(第一节)初识游戏库(3)
1.1. 键盘和鼠标控制
在游戏应用程序中,通常使用键盘和鼠标作为游戏的操作设备。游戏的窗口都能接收来自键盘和鼠标设备的输人。当用户在键盘上按下按建或释放按键时,会产生相应的键盘事件;当用户移动鼠标、拖动鼠标、按下鼠标按键或者是滚动鼠鼠标滚轮,会产生相应的鼠标事件。在游戏程序中,需要编写相应的事件处理代码来响应这些事件,进行游戏功能的开发。Python游戏库Pyglet和Julia游戏库GameZero都定义了键盘和鼠标事件的处理函数。
1.处理键盘事件
在Pyglet里,基本的键盘事件是0n_key_Press(),而在GameZero里,基本的键盘事件是on_key_down(),他们之间有很多相似之处。在键盘按下时触发该事件:
Pyglet:
def 0n_key_Press (symbol,modifiers)
pass
GameZero:
function on_key_down() .... end
function on_key_down(g) .... end
function on_key_down(g, key) .... end
function on_key_down(g, key, keymod) .... end
我们可以注意到,on_key_down有三个可选函数,其中key传入键盘被按键的ASCII码。
以下代码展示了对键盘按下事件on_key_down()的处理方法,当用户按下键盘上的回车键、方向键、字母键、数字键、控制键等按键时,在Shell 窗口中会打印出相关信息。
function on_key_down(g,key)
#print(Keys.1)
if key == Keys.SPACE
println("空格键被按下")
elseif key==Keys.RETURN
println("回车键被按下")
elseif key==Keys.LEFT
println("左方向键被按下")
elseif key==Keys.A
println("字母键A被按下")
elseif key==Keys.LCTRL
println("左侧Ctrl键被按下")
elseif key==49
println("数字键1被按下")
end
end
2.跟踪键盘按键状态
on_key_down事件只在键盘被按下时触发一次,针对不断按住键盘按键不放的情况,比如移动某个游戏对象时,GameZero在update事件中提供对键盘按键的跟踪。例如:
1 txt = TextActor("Hello World","chiller",font_size=24, color=Int[0,0,0,255])#
2 txt.pos = (0,0)
3
4 function draw(g::Game)
5 clear()
6 draw(txt)
7 end
8
9 function update(g::Game,dt)
10 if g.keyboard.DOWN
11 txt.position.y+= 400 * dt
12 elseif g.keyboard.UP
13 txt.position.y-= 400 * dt
14 elseif g.keyboard.LEFT
15 txt.position.x -= 400 * dt
16 elseif g.keyboard.RIGHT
17 txt.position.x += 400 * dt
18 end
19 end
上面的代码演示了分别按住上、下、左、右方向键时,txt对象朝相应方向移动的场景。
3.处理鼠标事件
GameZero提供on_Mouse_move函数来跟踪鼠标移动事件,鼠标在移动过程中,会不断触发这个事件。函数的输入是游戏对象和鼠标位置(一个数字元组)。
function on_mouse_move(g::Game, pos) .... end
需要说明的是,鼠标按钮button是一个枚举值,
LEFT = 1
MIDDLE = 2
RIGHT = 3
WHEEL_UP = 4
WHEEL_DOWN = 5
这个鼠标事件的典型应用是控制窗口中的角色随着鼠标指针一起移动。例如,在原书的示例程序28-9中展示了让玩家用鼠标控制一架飞机在窗口中自由移动。现将其改写为julia代码:
1 plane =Actor("plane.png")
2 plane.pos=0, 0
3
4 function draw(g::Game)
5 clear()
6 draw(plane)
7 end
8
9 function on_mouse_move(g::Game, pos)
10 plane.pos=pos
11 end
在上面的代码中,通过在 on_mouse_move ()方法中设定飞机角色 plane 的坐标为鼠标指针的当前坐标,从而使鼠标指针移动时,飞机精能角色跟着一起移动。在 on_mouse_move ( )方法中 ,pos 参数给出鼠标指针相对于窗口左上角的坐标(python的Pyglet是左下角)。 还记得吗? GameZero窗口左上角的坐标为(0,0).
对于鼠标按键按下和松开,使用on_mouse_down()和on_mouse_up()函数跟踪鼠标点击事件,函数将游戏对象、鼠标位置和鼠标按钮作为输入参数。
function on_mouse_down(g::Game, pos, button) .... end
function on_mouse_up(g::Game, pos, button) .... end
下方代码展示了这几个鼠标事件的基本用法:
function on_mouse_down(g::Game, pos, button)
if button==MouseButtons.LEFT
println("在窗口'$pos'处按下左键")
end
end function on_mouse_up(g::Game, pos, button)
if button==MouseButtons.LEFT
println("在窗口'$pos'处松开左键")
end
end
1.1. 播放音频
要播放音效,可以调用play_sound函数。要在循环中播放音乐,可调用play_music函数。这两种功能都可以加载wav、mp3和ogg文件。注意sound和music文件,必须放在声音(sounds)和音乐(music)两个文件夹中。
1.2. 计划任务
在游戏程序中,经常需要按照一定的时间隔去执行某个任务。 例如,让一个角色以指定的速度在屏幕上平滑移动,定时检测某个角色是否披击中,给游戏增加倒计时功能,等等。在 GameZero 的 timer模块中提供实现计划任务的一些方法,常用的有 pyglet' schedule_once()方法和schedule_interval()方法,它们都是按照指定的时间间隔调用一个函数。不过前者只调用一次。例如:
schedule_once(move, 1/10)
schedule_interval(move,1/10,1)
在上面代码中,schedule_once( f::Function, interval)方法时提供了两个参数值: move 是一个已经定义的函数(称为回调函数)的名字; 1/10是时间间隔(单位= S)。GameZero会按照这个时间间隔调用 move()函一次。而schedule_interval(f::Function, interval, first_interval=interval)提供了三个参数,前两个参数与schedule_once()相同,第三个为可选参数,是第一次调用move函数前间隔的时间,即1秒之后开始执行计划。GameZero会按照第二个参数定义的时间间隔反复调用move函数。
原书示例程序 28_11中演示了 Pyglet 计划任务的用法,让一个显示 hello, world 的文本标签在窗口底部水平移动到 x 坐标为 300 的位置。现将其改写为julia代码:
1 txt = TextActor("Hello World","chiller",font_size=24, col-or=Int[0,0,0,255])#
2 txt.pos = (0,0)
3 dt=0.5
4 function draw(g::Game)
5 clear()
6 draw(txt)
7 end
8
9 function move()
10 global dt
11 txt.x += Int(100 * dt)
12 end
13
14 schedule_interval(move,1/10)
15 #schedule_once(move, 1)
16 function update(g::Game,dt)
17 if txt.x > 300
18 unschedule(move)
19 end
20 end
值得注意的是,原书的间隔时间是1/60s,但是在GameZero中会报溢出错误,可见在GameZero中间隔时间不能太小,这也许是GameZero的一个bug吧。另外要从计划任务列表中删除一个已存在的计划任务,可用unschedule()方法,不过在GameZero中,该方法如果写在回调函数内部调用,不会被执行,但也不会报错。所以这里将其改到update方法中执行。
1.1. 模拟动画
GameZero目前不能象Pyglet那样播放gif动画或视频,只能通过一些技巧模拟动画,比如通过定时或循环更换角色的图片来模拟动画。例如:
function shoot_animation()
global shoot_frame
if shoot_frame < 16
space_pod.image = "space_pod_shoot" * string(shoot_frame) * ".png"
shoot_frame += 1
schedule_once(shoot_animation, 1/16)
else
space_pod.image = "space_pod.png"
end
end
具体可去这个地址:https://github.com/SquidSinker/GZExamples查看Spaceship这个示例。
通过以上几节,我们了解了GameZero在游戏编程中的一些技术,并对比了Python游戏库Pyglet的游戏编程,读者朋友可以两相对照,运行一下各自的代码,比较异同。后续会将原书的一些游戏,用GameZero实现,并放出。敬请期待!
对比python学julia(第三章:游戏编程)--(第一节)初识游戏库(3)的更多相关文章
- python学习心得第三章
python学习心得第三章 1.三元运算 变量=值1 if 条件 else 值2 由图如果条件成立则赋值1给变量,如果条件不成立则赋值2给变量. 2.数据类型 集合:set() class set(o ...
- Objective-C 基础教程第三章,面向对象编程基础知
目录 Objective-C 基础教程第三章,面向对象编程基础知 0x00 前言 0x01 间接(indirection) 0x02 面向对象编程中使用间接 面向过程编程 面向对象编程 0x03 OC ...
- 路飞学城-Python爬虫集训-第三章
这个爬虫集训课第三章的作业讲得是Scrapy 课程主要是使用Scrapy + Redis实现分布式爬虫 惯例贴一下作业: Python爬虫可以使用Requests库来进行简单爬虫的编写,但是Reque ...
- python学习笔记——第三章 串
第三章 字符串学习 1.字符串不灵活, 它不能被分割符值 >>> format = "hello, %s. %s enough for ya?" >> ...
- 《零压力学Python》 之 第三章知识点归纳
第三章(第一个程序)知识点归纳 编程犹如写剧本.Python函数与剧本差别不大,你可以反复调用函数,而它每次都执行预定的“脚本”(脚本也可以指整个程序). 在Python IDLE中,真正的编程是从编 ...
- Python for Infomatics 第12章 网络编程一(译)
注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 本书中的许多例子关注的是读取文件 ...
- VSTO开发指南(VB2013版) 第三章 Excel编程
通过前两章的内容,有了一定的基础,但进入第三章,实例的步骤非常多,并且随着VS版本的升级,部分功能菜单界面发生了很大变化,所以,第三章的案例我将逐步编写! 实例3.1的目标就是给Excel写一个加载宏 ...
- Python开发【第三章】:Python的文件操作
一.文件操作模式概述 1.打开文件的模式: r, 只读模式[默认] w,只写模式[不可读:不存在则创建:存在则删除内容:] a, 追加模式[不可读:不存在则创建:存在则只追加内容:] 2." ...
- Python开发【第三章】:文件操作
一.文件操作模式概述 1.打开文件的模式: r, 只读模式[默认] w,只写模式[不可读:不存在则创建:存在则删除内容:] a, 追加模式[不可读:不存在则创建:存在则只追加内容:] 2." ...
- python基础教程-第三章-使用字符串
本章将会介绍如何使用字符串何世华其他的值(如打印特殊格式的字符串),并简单了解下利用字符串的分割.联接.搜索等方法能做些什么 3.1 基本字符串操作 所有标准的序列操作(索引.分片.乘法.判断成员资格 ...
随机推荐
- itest(爱测试) 紧急 BUG 修复版(4.5.6)发布,,开源BUG 跟踪管理 & 敏捷测试管理&极简项目管理软件
itest 简介 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理4合1,又有丰富的统计分析.可按测试包分配测试用例执行,也可建测试迭代(含任务, ...
- C#.NET 操作FTP
工具类: using System; using System.Collections.Generic; using System.IO; using System.Net; namespace Co ...
- Vue学习:16.组件通信
组件通信就是指组件之间的数据传递.由于组件的数据是独立的,无法直接访问其他组件的数据,所以想要使用其他组件数据必须通过 组件通信! 在Vue.js中,组件之间的通信可以通过多种方式实现,包括 prop ...
- shiro有哪些组件?
a.Authentication:身份认证/登录,验证用户是不是拥有相应的身份: b.Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限:即判断用户是否能做事情,常见的 ...
- win10系统,磁盘出现惊叹号和一把锁符号如何关闭去掉
如标题描述,图标如下 解决方法如下:搜索cmd -> 以管理员身份运行 输入命令如下 根据c,d,e盘符的文件量大小执行时间有些差异. manage-bde -off c:就可以解密c盘,成为b ...
- 只听过 Python 做爬虫?不瞒你说 Java 也很强
网络爬虫技术,早在万维网诞生的时候,就已经出现了,今天我们就一起来揭开它神秘的面纱! 一.摘要 说起网络爬虫,相信大家都不陌生,又俗称网络机器人,指的是程序按照一定的规则,从互联网上抓取网页,然后从中 ...
- 文件系统(八):Linux JFFS2文件系统工作原理、优势与局限
liwen01 2024.06.23 前言 在嵌入式Linux设备中,经常使用jffs2文件系统来作为参数区的文件系统格式.至于为什么要使用jffs2来作为参数区的文件系统,我猜大部分人都没有做过多的 ...
- openfoam 修改 src 库经验记录
遇到一个问题,要把 sprayFoam 求解器的蒸发模型修改为自定义蒸发模型. sprayFoam 求解器本身没有实现蒸发模型,而是调用 $FOAM_SRC/lagrangian/intermedia ...
- javaApi,mapreduce,awk,scala四种方式实现词频统计
awk方式实现词频统计: 方式一: vi wordcount.awk { for (i = 1; i <=NF;i++) //NF 表示的是浏览记录的域的个数 freq[$i]++ } END{ ...
- 转-查看Linux CPU个数,核心,线程数
CPU 个数 grep 'physical id' /proc/cpuinfo | sort -u CPU 核心数 grep 'core id' /proc/cpuinfo | sort -u | w ...