对比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 基本字符串操作 所有标准的序列操作(索引.分片.乘法.判断成员资格 ... 
随机推荐
- 算法金 | 再见,PCA 主成分分析!
			大侠幸会,在下全网同名[算法金] 0 基础转 AI 上岸,多个算法赛 Top [日更万日,让更多人享受智能乐趣] 1. 概念:数据降维的数学方法 定义 主成分分析(PCA)是一种统计方法,通过正交变 ... 
- Python缺失值处理实现
			在数据处理相关工作中,读取的数据中常常会有缺失值的情况,为顺利进行后续的操作,需要首先对缺失值进行处理,处理的方式一般为删除或填充,Python中提供了专门的工具包,可以方便地进行实现.读取操作可 ... 
- react做购物车的功能
			父组件 import React, { Component } from 'react' import Lists from '../components/Lists' export default ... 
- webpack js兼容处理
			webpack在不需要引入任何loader可以对于js进行打包处理,但是它不会对于js兼容性进行任务的处理,而我们编写的项目是需要在不同的浏览器中运行的,此时就需要对于js的兼容性在打包过程中进行对应 ... 
- 深入剖析C++多态的实现与原理-详解
			目录 多态基础 虚函数 虚函数的继承 虚类/虚基类 重写/覆盖 条件: 概念: 多态的条件 其他的多态行为 多态中子类可以不写virtual 协变 代码举例 继承遗留问题解决 析构函数 具体解决方式: ... 
- 基于 Easysearch kNN 搭建即时图片搜索服务
			环境准备 启动 Easysearch 服务: # Make sure your vm.max_map_count meets the requirement sudo sysctl -w vm.max ... 
- 使用命令行(powershell)压缩(7Z RAR)指定日期文件
			使用命令行(powershell)压缩(7Z RAR)指定日期文件,powershell ,7z. WINDOWS命令行是无法按时间过滤文件的,我们通过powershell 里的Get-ChildIt ... 
- Exception:kylin构建cube, Cannot modify mapReduce.queue.name at runtime
			Failed to open new session: java.lang.IllegalArgumentException: Cannot modify tez.queue.name at runt ... 
- 06-Linux用户和组管理
			关于用户和组的知识 家目录 用户都有家目录:root用户家目录为/root.其他用户的家目录在/home/,如user1的家目录为/home/user1 当我们创建用户时,系统就会自动创建该用户的家目 ... 
- ansible(1)---师傅领进门
			背景 在企业里,运维需要配合开发进行产品上架,说白了就是把写好的代码上服务器.那么,就会出现这样的问题:需要运维人员配置好系统,配置好环境,配置好网络,配置好程序,配置好所有所有的依赖环境. ... 
