本文转自:http://eyehere.net/2011/python-pygame-novice-professional-10/

有时候无聊在网上翻翻小说看看,绝大多数那叫一个无聊。比如说修炼的境界分几种,都有个名字,然后每种境界再有几层,这不就是变相的打怪练级么?文笔也不咋样,故事情节的驾驭能力更是让我瞠目结舌,想到这些类小说盛行,不觉感到悲从中来。感觉看这些小说,就想在看别人打游戏一般,崩溃到极点。游戏和小说的最大区别,除了声色以外,最不同的就是玩家可以沉入进去,通过自己的双手来参与;而好的游戏,更是可以通过玩家的选择,完全掌控游戏的发展,这是传统的故事媒介无法做到的事情。

很自然的,我们讲述了游戏中视觉上的种种,现在开始就要学习一下游戏中的用户输入。同样我们也要探讨一下如何让用户的输入更为顺畅,换个词就是,如果让游戏的手感更好一些。

游戏设备

玩过游戏的都知道鼠标和键盘是游戏的不可或缺的输入设备。键盘可以控制有限的方向和诸多的命令操作,而鼠标更是提供了全方位的方向和位置操作。不过这两个设备并不是为游戏而生,专业的游戏手柄给玩家提供了更好的操作感,加上力反馈等技术,应该说游戏设备越来越丰富,玩家们也是越来越幸福。

键盘设备

我们先从最广泛的键盘开始讲起。

现在使用的键盘,基本都是QWERTY键盘(看看字幕键盘排布的左上就知道了),尽管这个世界上还有其他种类的键盘,比如AZERTY啥的,反正我是没见过,如果你能在写游戏的时候考虑到这些特殊用户自然是最好,个人感觉是问题不大吧。

以前第二部分也稍微使用了一下键盘,那时候是用了pygame.event.get()获取所有的事件,当event.type == KEYDOWN的时候,在判断event.key的种类,而各个种类也使用K_a,K_b……等判断。这里再介绍一个pygame.key.get_pressed()来获得所有按下的键值,它会返回一个元组。这个元组的索引就是键值,对应的就是是否按下,比如说:

  1. pressed_keys = pygame.key.get_pressed()
  2. if pressed_keys[K_SPACE]:
  3. # Space key has been pressed
  4. fire()pressed_keys = pygame.key.get_pressed()

当然key模块下还有很多函数:

  • key.get_focused —— 返回当前的pygame窗口是否激活
  • key.get_pressed —— 刚刚解释过了
  • key.get_mods —— 按下的组合键(Alt, Ctrl, Shift)
  • key.set_mods —— 你也可以模拟按下组合键的效果(KMOD_ALT, KMOD_CTRL, KMOD_SHIFT)
  • key.set_repeat —— 无参数调用设置pygame不产生重复按键事件,二参数(delay, interval)调用设置重复事件发生的时间
  • key.name —— 接受键值返回键名

注:感谢xumaomao朋友的倾情指正!

使用键盘控制方向

有了上一章向量的基础,只需一幅图就能明白键盘如何控制方向:

很多游戏也使用ASDW当做方向键来移动,我们来看一个实际的例子:

  1. background_image_filename = 'sushiplate.jpg'
  2. sprite_image_filename = 'fugu.png'
  3. import pygame
  4. from pygame.locals import *
  5. from sys import exit
  6. from gameobjects.vector2 import Vector2
  7. pygame.init()
  8. screen = pygame.display.set_mode((640, 480), 0, 32)
  9. background = pygame.image.load(background_image_filename).convert()
  10. sprite = pygame.image.load(sprite_image_filename).convert_alpha()
  11. clock = pygame.time.Clock()
  12. sprite_pos = Vector2(200, 150)
  13. sprite_speed = 300.
  14. while True:
  15. for event in pygame.event.get():
  16. if event.type == QUIT:
  17. exit()
  18. pressed_keys = pygame.key.get_pressed()
  19. key_direction = Vector2(0, 0)
  20. if pressed_keys[K_LEFT]:
  21. key_direction.x = -1
  22. elif pressed_keys[K_RIGHT]:
  23. key_direction.x = +1
  24. if pressed_keys[K_UP]:
  25. key_direction.y = -1
  26. elif pressed_keys[K_DOWN]:
  27. key_direction.y = +1
  28. key_direction.normalize()
  29. screen.blit(background, (0,0))
  30. screen.blit(sprite, sprite_pos)
  31. time_passed = clock.tick(30)
  32. time_passed_seconds = time_passed / 1000.0
  33. sprite_pos+= key_direction * sprite_speed * time_passed_seconds
  34. pygame.display.update()

这个例子很简单,就是使用方向键移动小鱼。使用的知识也都讲过了,相信大家都可以理解。不过这里并不是单纯的判断按下的键来获得方向,而是通过对方向的加减来获得最终的效果,这样可能会更简短一些,也需要一些技术;如果把方向写入代码,效率更高,不过明显通用性就要低一些。记得把力气花在刀刃上!当然这个例子也不是那么完美,看代码、实践一下都能看到,左方向键的优先级大于右方向键,而上则优于下,我们是否有更好的方法?……有兴趣的自己考虑~

这个例子我们可以看到,小鱼只能在八个方向移动,如何做到全方向?如果你游戏经验足一点或许可以想到,是的,先转向,再移动,尽管不是那么快捷,但毕竟达到了目标。我们看一下这样的代码怎么写:

  1. background_image_filename = 'sushiplate.jpg'
  2. sprite_image_filename = 'fugu.png'
  3. import pygame
  4. from pygame.locals import *
  5. from sys import exit
  6. from gameobjects.vector2 import Vector2
  7. from math import *
  8. pygame.init()
  9. screen = pygame.display.set_mode((640, 480), 0, 32)
  10. background = pygame.image.load(background_image_filename).convert()
  11. sprite = pygame.image.load(sprite_image_filename).convert_alpha()
  12. clock = pygame.time.Clock()
  13. sprite_pos = Vector2(200, 150) # 初始位置
  14. sprite_speed = 300. # 每秒前进的像素数(速度)
  15. sprite_rotation = 0. # 初始角度
  16. sprite_rotation_speed = 360. # 每秒转动的角度数(转速)
  17. while True:
  18. for event in pygame.event.get():
  19. if event.type == QUIT:
  20. exit()
  21. pressed_keys = pygame.key.get_pressed()
  22. rotation_direction = 0.
  23. movement_direction = 0.
  24. # 更改角度
  25. if pressed_keys[K_LEFT]:
  26. rotation_direction = +1.
  27. if pressed_keys[K_RIGHT]:
  28. rotation_direction = -1.
  29. # 前进、后退
  30. if pressed_keys[K_UP]:
  31. movement_direction = +1.
  32. if pressed_keys[K_DOWN]:
  33. movement_direction = -1.
  34. screen.blit(background, (0,0))
  35. # 获得一条转向后的鱼
  36. rotated_sprite = pygame.transform.rotate(sprite, sprite_rotation)
  37. # 转向后,图片的长宽会变化,因为图片永远是矩形,为了放得下一个转向后的矩形,外接的矩形势必会比较大
  38. w, h = rotated_sprite.get_size()
  39. # 获得绘制图片的左上角(感谢pltc325网友的指正)
  40. sprite_draw_pos = Vector2(sprite_pos.x-w/2, sprite_pos.y-h/2)
  41. screen.blit(rotated_sprite, sprite_draw_pos)
  42. time_passed = clock.tick()
  43. time_passed_seconds = time_passed / 1000.0
  44. # 图片的转向速度也需要和行进速度一样,通过时间来控制
  45. sprite_rotation += rotation_direction * sprite_rotation_speed * time_passed_seconds
  46. # 获得前进(x方向和y方向),这两个需要一点点三角的知识
  47. heading_x = sin(sprite_rotation*pi/180.)
  48. heading_y = cos(sprite_rotation*pi/180.)
  49. # 转换为单位速度向量
  50. heading = Vector2(heading_x, heading_y)
  51. # 转换为速度
  52. heading *= movement_direction
  53. sprite_pos+= heading * sprite_speed * time_passed_seconds
  54. pygame.display.update()

我们通过上下控制前进/后退,而左右控制转向。我们通过pygame.transform.rotate()来获得了转向后的图片,具体参数可以参考代码。各条语句的作用也可以参考注释。

下次讲解使用鼠标控制游戏。

如何用Pygame写游戏(十)相关推荐

  1. 如何用Pygame写游戏(一)

    转载地址:http://eyehere.net/2011/python-pygame-novice-professional-1/ Pygame的历史  Pygame是一个利用SDL库的写就的游戏 ...

  2. 如何用Pygame写游戏(二十二)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-22/ 辛苦啦~ 这次是我们系统的pygame理论学习的最后一章了,把这次 ...

  3. 如何用Pygame写游戏(十九)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-19/ 3D世界 让我们现在开始写一个3D的程序,巩固一下这几次学习的东西 ...

  4. 如何用Pygame写游戏(十八)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-18/ 3D是非常酷的技术,同时也就意味着更多的工作,上次的简单介绍之后, ...

  5. 如何用Pygame写游戏(十六)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-16/ 经历了长年的艰苦卓绝的披星戴月的惨绝人寰的跋山涉水,我们终于接近了 ...

  6. 如何用Pygame写游戏(十四)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-14/ 上一次稍微说了一下AI,为了更好的理解它,我们必须明白什么是状态机 ...

  7. 如何用Pygame写游戏(二十)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-20/ 声音是游戏中必要的元素之一,音效可以给予用户良好的反馈体验.赛车的 ...

  8. 如何用Pygame写游戏(十五)

    本文转自: http://eyehere.net/2011/python-pygame-novice-professional-15/ 在继续我们的AI之旅前,分享一个在煎蛋上看到的有趣新闻,能通过读 ...

  9. 如何用Pygame写游戏(九)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-9/ 上次我们说到了向量,不得不说向量是一个伟大的发明,在单纯的数字运算之 ...

最新文章

  1. 微生物组-宏基因组分析专题研讨会(2022.5)
  2. @ImportResource-SpringBoot使用xml配置Bean
  3. android读取raw文件示例
  4. RFID系统集成公司
  5. 为什么企业需关心DDoS攻击?—Vecloud微云
  6. python中的列表是采用链式结构实现的_Python数据结构与算法之列表(链表,linked list)简单实现...
  7. 10种可提升Android应用程序运行效果的技巧
  8. 64位win7使用debug的方法
  9. Android开发笔记(七十三)代码混淆与反破解
  10. python netsnmp与pysnmp
  11. SpringCloud实战(四)Sentinel自定义降级异常实战
  12. 关于数据库方言MySQLDialect、MySQL5Dialect、MySQL55Dialect、MySQL57Dialect、MySQL8Dialect之间的区别与联系
  13. 微信小程序开发——调用免费天气api接口(高德、天气API)
  14. 平衡小车PID,就该这么调!!!
  15. Vue-DataV 数据可视化工具
  16. 计算机网络的常见面试题
  17. 4G模组通信配置相关概念及流程
  18. 【编译原理】语义分析
  19. QT注册登录以及安装问题
  20. 苏州企业拿到商标注册证后,需要注意哪些事项?

热门文章

  1. post python爬虫_小白学 Python 爬虫(17):Requests 基础使用
  2. 机器学习--弹性网络(Elastic-Net Regression)
  3. IDEA自动勾选显示类型(specify type)
  4. for oracle中pivot_oracle关键字pivot行转列【坑爹的三小时,动脑经真累 】 | 学步园...
  5. phpcms搜索功能(案例一)- 代码剥离篇
  6. Any-Proxy在线反向代理源码
  7. html引入png不显示透明北京,解决在网页上显示PNG图片底色不透明的方法
  8. oracle 10g db_file,oracle 10g的db_file_multiblock_read_count参数
  9. python3 音乐播放器_Python3——MP3播放器
  10. 响应式建筑设计类dedecms模板