• 对比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实现,并放出。敬请期待!

     
  • 相关阅读:
    c语言动态申请内存(malloc与calloc)
    二维数组的指针
    二分查找(用c语言实现)
    Docker一篇从入门到实战
    MyBatisPlus一篇从入门到实战
    MyBatis一篇从入门到实战
    MySQL一篇从入门到实战
    Nginx一篇从入门到实战
    day04_02逻辑运算符
    day4_01循环引用带来的内存泄露问题
  • 原文地址:https://www.cnblogs.com/zjzkiss/p/16463117.html
Copyright © 2020-2023  润新知