Pygame - Python游戏编程入门(1)

前言

  在上一篇中,我们初步熟悉了pygame的控制流程,但这对于一个游戏而言是远远不够的。所以在这一篇中,我们的任务是添加一架飞机(玩家),并且能够控制它进行移动,这样我们就又离目标进了一步了~ε=ε=(ノ≧∇≦)ノ

 

正片开始!

1. 把我们的战斗机搬上屏幕

  在正式上代码以前,有一点需要说明的,我们可以看到,所有屏幕上出现的元素都在资源文件(resources/image/shoot.png)中,那我们要怎么做才能把一只飞机给裁剪出来呢?在pygame中,所有在屏幕上显示的元素都可以视为一个surface,利用这个特点,我们可以把资源文件导入(load()函数),然后用surface.subsurface()函数把shoot.png中我们想要的元素裁剪出来,这样问题就解决了~(tips:怎样才知道shoot.png中飞机的准确坐标呢?在resources/image/shoot.pack文件中已经详细记录了每个屏幕元素的左上角坐标以及它的宽和高了)

  先上代码:(在注释# == new add ==之间的代码为新加入代码)

 1 import pygame                   # 导入pygame库
 2 from pygame.locals import *     # 导入pygame库中的一些常量
 3 from sys import exit            # 导入sys库中的exit函数
 4 
 5 # 定义窗口的分辨率
 6 SCREEN_WIDTH = 480
 7 SCREEN_HEIGHT = 640
 8 
 9 # 计数ticks == new add ==
10 ticks = 0
11 # 计数ticks == new add ==
12   
13 # 初始化游戏
14 pygame.init()                   # 初始化pygame
15 screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])     # 初始化窗口
16 pygame.display.set_caption('This is my first pygame-program')       # 设置窗口标题
17 
18 # 载入背景图
19 background = pygame.image.load('resources/image/background.png')
20 
21 # 载入资源图片 == new add ==
22 shoot_img = pygame.image.load('resources/image/shoot.png')
23 # 用subsurface剪切读入的图片
24 hero1_rect = pygame.Rect(0, 99, 102, 126)
25 hero2_rect = pygame.Rect(165, 360, 102, 126)
26 hero1 = shoot_img.subsurface(hero1_rect)
27 hero2 = shoot_img.subsurface(hero2_rect)
28 hero_pos = [200, 500]
29 # 载入资源图片 == new add ==
30 
31 # 事件循环(main loop)
32 while True:
33 
34     # 绘制背景
35     screen.blit(background, (0, 0))
36     
37     # 绘制飞机 == new add ==
38     if ticks % 50 < 25:
39         screen.blit(hero1, hero_pos)
40     else:
41         screen.blit(hero2, hero_pos)
42     ticks += 1
43     # 绘制飞机  == new add ==
44     
45     # 更新屏幕
46     pygame.display.update()                                         
47     
48     # 处理游戏退出
49     # 从消息队列中循环取
50     for event in pygame.event.get():
51         if event.type == pygame.QUIT:
52             pygame.quit()
53             exit()

不妨运行一下:

  

可以看到,我们的飞机动了,究竟是怎样实现动画效果的呢?在代码中,新加入的代码一共有三处,显示玩家飞机的那一段已经解释过了,现在我们来解释其余的两段新加入的代码。首先增加了一个计数变量ticks,在消息循环中,每循环一次就累加一次,可以理解为每一个周期就是1 tick,我们可以利用周期数来分隔不同的显示效果;我们读入了两张不同的玩家飞机图片,利用周期数实现每50个周期,前25个周期显示hero1,后25个周期显示hero2,这样就有了缓慢变化的动态效果。不过值得注意的是,这样每一次循环就计算判断一次ticks的做法明显不是好方法。还有!(╯°口°)╯(┴—┴,Python是木有自增表达式的,我试图++ticks结果报错了。

  战斗机已经准备就绪,该教会飞行员怎样操作了~(`・ω・´)

 

2. 用键盘控制飞机移动

  我们知道,每敲一下键盘都会产生一个事件,而这个事件能被Python检测到,既然知道了这个大前提,那控制飞机就很容易了。

  come on code~ ( °∀°)ノ

 1 import pygame                   # 导入pygame库
 2 from pygame.locals import *     # 导入pygame库中的一些常量
 3 from sys import exit            # 导入sys库中的exit函数
 4 
 5 # 定义窗口的分辨率
 6 SCREEN_WIDTH = 480
 7 SCREEN_HEIGHT = 640
 8 
 9 ticks = 0
10 # dict == new add ==
11 offset = {pygame.K_LEFT:0, pygame.K_RIGHT:0, pygame.K_UP:0, pygame.K_DOWN:0}
12 # dict == new add ==
13   
14 # 初始化游戏
15 pygame.init()                   # 初始化pygame
16 screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])     # 初始化窗口
17 pygame.display.set_caption('This is my first pygame-program')       # 设置窗口标题
18 
19 # 载入背景图
20 background = pygame.image.load('resources/image/background.png')
21 
22 # 载入飞机图片
23 shoot_img = pygame.image.load('resources/image/shoot.png')
24 # 用subsurface剪切读入的图片
25 hero1_rect = pygame.Rect(0, 99, 102, 126)
26 hero2_rect = pygame.Rect(165, 360, 102, 126)
27 hero1 = shoot_img.subsurface(hero1_rect)
28 hero2 = shoot_img.subsurface(hero2_rect)
29 hero_pos = [200, 500]
30 
31 # 事件循环(main loop)
32 while True:
33 
34     # 绘制背景
35     screen.blit(background, (0, 0))
36 
37     # 绘制飞机
38     if ticks % 50 < 25:
39         screen.blit(hero1, hero_pos)
40     else:
41         screen.blit(hero2, hero_pos)
42     ticks += 1 # python已略去自增运算符
43 
44     # 更新屏幕
45     pygame.display.update()                                         
46     
47     # 处理游戏退出
48     # 从消息队列中循环取
49     for event in pygame.event.get():
50         if event.type == pygame.QUIT:
51             pygame.quit()
52             exit()
53 
54         # Python中没有switch-case 多用字典类型替代
55         # 控制方向 == new add ==          
56         if event.type == pygame.KEYDOWN:
57             if event.key in offset:
58                 offset[event.key] = 3
59         elif event.type == pygame.KEYUP:
60             if event.key in offset:
61                 offset[event.key] = 0
62 
63         # part 1
64         #offset_x = offset[pygame.K_RIGHT] - offset[pygame.K_LEFT]
65         #offset_y = offset[pygame.K_DOWN] - offset[pygame.K_UP]
66         #hero_pos = [hero_pos[0] + offset_x, hero_pos[1] + offset_y]
67     # part 2
68     offset_x = offset[pygame.K_RIGHT] - offset[pygame.K_LEFT]
69     offset_y = offset[pygame.K_DOWN] - offset[pygame.K_UP]
70     hero_pos = [hero_pos[0] + offset_x, hero_pos[1] + offset_y]
71     # 控制方向 == new add ==          

新加入了两处,一个是字典类型的变量,一个是控制方向的代码。跟之前控制程序退出的代码一样,依然是从事件队列中取事件;当event.type为按键事件时,再判断event.key是否属于上下左右四个键位中的其中一个;最后在其相应方向上给一个偏移量,即完成判断的过程;松键的话该方向上的偏移量赋值为0,这样该键方向上就没有位移了;最后将偏移量加到飞机的pos上,下一轮刷新时自然就到移动到新地方了。(这里插播一个事,我以前写过c++和java,所以写到判断键盘键位时,很自然就想用switch-case语句,没想到竟然出错了(╯°口°)╯(┴—┴,后来才发现原来Python是没有switch-case语句的,switch-case语句多用字典数据结构代替,感觉这样的写法就更灵活了)

上面讲得都比较简单,现在我们要思考一个问题,上面的代码中,line 63-66和line 67-70的代码是一样的,但两部分代码的效果却是很不一样。part1代码使得我们要按一次键飞机才会动一次,而在part2代码中我们可以长按方向键来控制飞机,不禁感慨一下Python的缩进。part1是在for循环的影响下的,也就是说,事件队列中有事件才会执行part1的代码,假设我们长按方向左键(注意,击键一次只会产生一个pygame.KEYDOWN事件,所以长按也只触发一次),飞机也只会往左移3个像素点;而part2代码由于不在for循环内,所以每一tick就向左移3个像素点直到松开方向左键。

演示一下效果:

好的,控制飞机已经不成问题了,不过大家发现飞机有一个小问题了吗?它会穿到窗口的“外面”去!不过我们只要添加一个小小的限制就可以解决问题了,只要把line68-70换成以下边界判断代码就可以了。

 1     hero_x = hero_pos[0] + offset[pygame.K_RIGHT] - offset[pygame.K_LEFT]
 2     hero_y = hero_pos[1] + offset[pygame.K_DOWN] - offset[pygame.K_UP]
 3     if hero_x < 0:
 4         hero_pos[0] = 0
 5     elif hero_x > SCREEN_WIDTH - hero1_rect.width:
 6         hero_pos[0] = SCREEN_WIDTH - hero1_rect.width
 7     else:
 8         hero_pos[0] = hero_x
 9         
10     if hero_y < 0:
11         hero_pos[1] = 0
12     elif hero_y > SCREEN_HEIGHT - hero1_rect.height:
13         hero_pos[1] = SCREEN_HEIGHT - hero1_rect.height
14     else:
15         hero_pos[1] = hero_y

今天功能就完成到这里吧~(`・ω・´)

 

转载于:https://www.cnblogs.com/wuzhanpeng/p/4264267.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259422.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++字符输入getchar()和字符输出putchar()

转载&#xff1a;http://c.biancheng.net/cpp/biancheng/view/117.html C还保留了C语言中用于输入和输出单个字符的函数&#xff0c;使用很方便。其中最常用的有getchar函数和putchar函数。 putchar函数(字符输出函数) putchar函数的作用是向终端输出一个字符。例如&#xf…

linux实现shell,linux

4.5Mhttp://www.starbase-929.net/media/Calibre%20Library/Ken%20O.%20Bartch/Linux%20Shell%20Scription%20With%20Bash%20(1778)/Linux%20Shell%20Scription%20With%20Bash%20-%20Ken%20O.%20Bartch.pdfstarbase-929.net全网免费4.0Mhttp://www.myaitcampus.net/elibrary/im…

AQS浅析

2019独角兽企业重金招聘Python工程师标准>>> AQS的原理浅析 本文是《Java特种兵》的样章&#xff0c;本书即将由工业出版社出版 AQS的全称为&#xff08;AbstractQueuedSynchronizer&#xff09;&#xff0c;这个类也是在java.util.concurrent.locks下面。这个类似乎…

str045漏洞提权linux,Linux运维知识之CVE-2016-5195 Dirtycow: Linux内核提权漏洞

本文主要向大家介Linux运维知识之CVE-2016-5195 Dirtycow&#xff1a; Linux内核提权漏洞绍了&#xff0c;通过具体的内容向大家展现&#xff0c;希望对大家学习Linux运维知识有所帮助。CVE-2016-5195 Dirtycow&#xff1a; Linux内核提权漏洞以下都是github上找的源码&#xf…

编程如写作

昨晚似乎是个适合写作的夜&#xff0c;不论是自己还是朋友&#xff0c;都比平常更容易被触动。看着微博上朋友们的心路&#xff0c;想写点什么却似乎找不出非常值得大书特书的主题&#xff0c;只是歪坐在电脑旁&#xff0c;喝着咖啡&#xff0c;单曲循环着仓木麻衣的《time aft…

C++中cin、cin.get()、cin.getline()、getline()等函数的用法

转载&#xff1a;http://www.cnblogs.com/flatfoosie/archive/2010/12/22/1914055.html c输入流函数主要以下几个&#xff1a; 1、cin 2、cin.get() 3、cin.getline() 4、getline() 附:cin.ignore();cin.get()//跳过一个字符,例如不想要的回车,空格等字符 1、cin>>…

工作环境总结(1)开发环境搭建

1、安装git 安装文件&#xff1a;Git-2.12.0-64-bit.exe 下载地址&#xff1a;https://github.com/git-for-windows/git/releases/download/v2.12.0.windows.1/Git-2.12.0-64-bit.exe 在git bash中配置&#xff0c;git bash命令行中执行&#xff08;只有使用到egit时使用&…

c语言烟花百度云,C语言实现放烟花的程序

这是一个利用C语言编写放烟花的程序(同时也可以播放音乐)&#xff0c;供大家参考&#xff0c;具体内容如下代码如下#pragma once#include#include //图形界面库头文件#include //计算圆形的轨迹坐标#include#include#include#include#pragma comment(lib,"winmm.lib"…

决定人生的七条公式

1 .积跬步以致千里&#xff0c;积怠惰以致深渊 1.01^365 37.80.99^365 0.032.拖延症 U EV/ID U完成任务的程度 E对成功的信心 V 对任务的愉悦度 I 你的分心程度 D你多久会获得回报3.三天打鱼两天晒网&#xff0c;终将一无所获 1.01^3 x 0.99^2 < 1.01 4.爱因斯坦的成…

strncpy与strcpy的区别与注意事项

strncpy 是 C语言的库函数之一&#xff0c;来自 C语言标准库&#xff0c;定义于 string.h&#xff0c;char *strncpy(char *dest, char *src, int n)&#xff0c;把src所指字符串的前n个字节复制到dest所指的数组中&#xff0c;并返回指向dest的指针。 strcpy只是复制字符串&am…

使用ssh公钥实现免密码登录

ssh 无密码登录要使用公钥与私钥。linux下可以用用ssh-keygen生成公钥/私钥对&#xff0c;下面我以CentOS为例。 有机器A(192.168.1.155)&#xff0c;B(192.168.1.181)。现想A通过ssh免密码登录到B。 首先以root账户登陆为例。 1.在A机下生成公钥/私钥对。 [rootA ~]# ssh-keyg…

15款的视频处理软件免费下载

因为需要购买昂贵的视频处理软件和高性能图形计算机&#xff0c;所以视频处理是一项比较耗费金钱的技术活。正是由于这样&#xff0c;一部分人选择使用性能较好的免费在线编辑软件&#xff0c;无需太多视频处理知识便可在浏览器中剪切和编辑视频。然而&#xff0c;当我们无法连…

液位系统c语言程序,超声波自动测量物体液位系统的设计

超声波自动测量物体液位系统的设计(任务书,毕业论文15000字)摘要本系统以STC89C52单片机为核心&#xff0c;通过硬件电路连接和软件程序的编写实现通用型超声波自动测量物体液位系统的设计。其主要原理是由单片机控制超声波发射电路发射超声波&#xff0c;超声波接收电路接收遇…

android-sdk-windows版本号下载

Android SDK 4.0.3 开发环境配置及执行 近期又装了一次最新版本号的ADK环境 眼下最新版是Android SDK 4.0.3 本文的插图和文本尽管是Android2.2的 步骤都是一样的&#xff0c;假设安装的过程中遇到什么问题&#xff0c;能够留言&#xff0c;我会尽快回复&#xff01; 系统环境的…

string中c_str()、data()、copy(p,n)函数的用法

转载&#xff1a;http://www.cnblogs.com/qlwy/archive/2012/03/25/2416937.html 标准库的string类提供了3个成员函数来从一个string得到c类型的字符数组&#xff1a;c_str()、data()、copy(p,n)。 1. c_str()&#xff1a;生成一个const char*指针&#xff0c;指向以空字符终止…

POJ2402 Palindrome Numbers 回文数

题目链接: http://poj.org/problem?id2402 题目大意就是让你找到第n个回文数是什么. 第一个思路当然是一个一个地构造回文数直到找到第n个回文数为止(也许大部分人一开始都是这样的思路). 很明显找到第n个之前的所有操作都是浪费, 这也是这个方法的最大弱点. 抱着侥幸心理(谁知…

离散卷积的c语言编程实验,数字信号处理实验一离散卷积c语言编程.ppt

数字信号处理实验一离散卷积c语言编程实验一 离散卷积的C语言编程实验 DSP实验室 2005 实验性质 综合设计性实验 实验目的 1 了解和认识常用的各种信号&#xff1b; 2 掌握卷积的定义和计算方法&#xff1b; 3 掌握在计算机中生成以及绘制信号序列图的方法。 实验原理 离散时间…

async-await原理解析

在用async包裹的方法体中&#xff0c;可以使用await关键字以同步的方式编写异步调用的代码。那么它的内部实现原理是什么样的呢&#xff1f;我们是否可以自定义await以实现定制性的需求呢&#xff1f;先来看一个简单的例子&#xff1a; 1 class Test {2 public sta…

emacs-w3m查看html帮助手册

<?xml version"1.0" encoding"utf-8"?> emacs-w3m查看html帮助手册emacs-w3m查看html帮助手册 Table of Contents 1. 使用效果2. 为什么要用emacs-w3m来查看html的帮助手册&#xff1f;3. 什么是w3m?4. 配置5. 额外资源1 使用效果 使用快捷键C-c …

c语言生命游戏代码大全,c++生命游戏源码

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼glViewport( 0, 0, width, height );glMatrixMode( GL_PROJECTION );glLoadIdentity( );}//程序入口int main(int argc, char *argv[]){//随机生成细胞的状态MapRand();std::cout<//SDL初始化const SDL_VideoInfo* info NULL;i…