对比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 基本字符串操作 所有标准的序列操作(索引.分片.乘法.判断成员资格 ...
随机推荐
- windows隐藏文件如何查看
1.组织 2.查看 3.显示隐藏文件
- jquery中封装了三种ajax请求方式
// jQuery中封装了3种 ajax 请求方式 // 1, get请求方式 // 2, post请求方式 // 3, 综合请求方式 ...
- vue局部注册
只能在当前注册它的vue实例中使用,通过某个 Vue 实例/组件的实例选项 components 注册仅在其作用域中可用的组件 var Child = { template: '<div> ...
- C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 文件夹体积很大
现象:大量调用.p12证书时,C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 文件夹变得越来越大. 调用代码: X509Certificate2 x50 ...
- STM32 + RT-Thread + LVGL
一.基本信息 MCU:STM32F103ZET6 RT-Thread:5.0.2 LVGL:8.3.11 LCD:ST7735s 编译环境:RTThread studio 二.LVGL 移植要求 16 ...
- 手写LRU热点缓存数据结构
引言 LRU是开发过程中设计缓存的常用算法,在此基础上,如何设计一个高效的缓存呢?本文就带大家分析并手撸一个LRUCache. LRU算法 LRU(Least recently used,最近最少使用 ...
- Linux实时查看Java接口数据
1.Linux实时查看Java接口数据的方法 在Linux系统中实时查看Java接口数据通常涉及几个步骤: (1)编写Java应用程序:首先,我们需要有一个Java应用程序,它暴露了一个或多个HTTP ...
- Linux命令行配置RIAD5
环境准备: 系统: redhat6.9 硬盘:300G*3 SAS MegaCli是一款管理维护硬件RAID软件,可以用来查看raid信息等 1. 安装MegaCli rpm -ivh Lib_Uti ...
- 格式化显示JSON数据
测试JSON {"took":1,"timed_out":false,"_shards":{"total":1,&quo ...
- selenium的各种操作
import time from selenium.webdriver import Edge from selenium.webdriver.common.by import By from sel ...