设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 78622|回复: 60
打印 上一主题 下一主题

【Pygame 第5课】 游戏中的运动

[复制链接]

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

跳转到指定楼层
#
发表于 2013-8-27 21:36:08 |只看该作者 |正序浏览
本来,在上一次pygame的教程中,我只是顺手拿了微信“打飞机”里的图来演示用鼠标控制图片位置的操作。后来觉得,这个游戏还算比较适合用来做例子,也有朋友反馈说想做这个游戏,那不如就以“打飞机”为例来说python游戏开发好了。

今天,就再进一步:既然要打飞机,那得能发射子弹才行。所以从最简单的做起,来给游戏加上“一颗”子弹。

上次的背景图和飞机图,我自己稍微处理了下,包括这一课要用到的子弹图片,都放在论坛上,需要的自行下载。

大体的思路是这样的:
  • 用之前在屏幕上绘制飞机的方法,再绘制一张很小的子弹图片。补充一下:当你需要绘制一张带透明部分的图片时,要用convert_alpha()替代之前的convert(),具体用法参见代码中。
  • 子弹被发射的位置是飞机的位置,也就是鼠标的位置。注意,要让它们的中心点对齐,而不是左上角对齐,处理方法我们已经说过。
  • 让这个子弹往上运动。还记得我在第2课《游戏的本质》里面说的吗:在游戏主循环中,要处理物理运动。所以在程序中要做的就是,每次循环里,把子弹图片的y坐标减少一个量(因为屏幕左上角的坐标是(0,0))。为了能记住子弹上一次循环中的位置,要有变量专门来记录子弹的坐标值。
  • 当子弹移动到屏幕上方外部之后(y坐标小于0),再把它的位置重置回发射的位置。这样看上去就是又一颗子弹被发射出来了,尽管我们一直是在操作同一张图片。游戏中经常会使用到诸如此类的小技巧,来欺骗你的视觉,这也是我觉得开发游戏很有意思的一个地方,好像是在变魔术。
  • 为了看起来更符合常理,你得把子弹的图片放在飞机的图片下面,这样看上去才会是从飞机上发射出去,而不是凭空冒出来的。在程序中,就是先绘制子弹,再绘制飞机,像是画油画,后画的会覆盖掉先画的。
  • 我在一开始就将子弹的位置设到屏幕上方之外,这样它就会自动被循环内的条件判断给重置位置,而不需要我再额外手动去初始化它的位置。


理清了如上的思路之后,能不能搞定代码了?如果能的话,就先别往下看,试着在程序里写写看。

以下是我的实现代码:
  1. # -*- coding: utf-8 -*-
  2. import pygame
  3. from sys import exit
  4. pygame.init()
  5. screen = pygame.display.set_mode((450, 800), 0, 32)
  6. pygame.display.set_caption("Hello, World!")
  7. background = pygame.image.load('back.jpg').convert()
  8. plane = pygame.image.load('plane.png').convert_alpha()
  9. bullet = pygame.image.load('bullet.png').convert_alpha()
  10. #加载子弹图像
  11. bullet_x = 0
  12. bullet_y = -1
  13. #初始化子弹位置
  14. while True:
  15.     for event in pygame.event.get():
  16.         if event.type == pygame.QUIT:
  17.             pygame.quit()
  18.             exit()
  19.     screen.blit(background, (0,0))
  20.     x, y = pygame.mouse.get_pos()
  21.     if bullet_y < 0:
  22.         #如果子弹位置超出了屏幕上端
  23.         bullet_x = x - bullet.get_width() / 2
  24.         bullet_y = y - bullet.get_height() / 2
  25.         #把子弹的中心位置设为鼠标坐标
  26.     else:
  27.         bullet_y -= 5
  28.         #子弹的位置往上移
  29.     screen.blit(bullet, (bullet_x, bullet_y))
  30.     #把子弹画到屏幕上
  31.     x-= plane.get_width() / 2
  32.     y-= plane.get_height() / 2
  33.     screen.blit(plane, (x, y))
  34.     pygame.display.update()
复制代码
5-2.png

5-1.png

#==== Crossin的编程教室 ====#
微信ID:crossincode
论坛:http://crossin.me
QQ群:312723402

面向零基础初学者的编程课
每天5分钟,轻松学编程




back.jpg (17.86 KB, 下载次数: 2128)

back.jpg

bullet.png (308 Bytes, 下载次数: 2327)

bullet.png

plane.png (9.18 KB, 下载次数: 2279)

plane.png

#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

1

好友

34

积分

新手上路

Rank: 1

60#
发表于 2019-12-17 16:32:02 |只看该作者
crossin先生 发表于 2019-12-17 16:06
screen.blit(background, (0, 0))

这句话的缩进不对,导致背景没有重绘制

gotta,谢谢~
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

59#
发表于 2019-12-17 16:06:56 |只看该作者
PMCoding 发表于 2019-12-17 14:31
看了前面的同学反馈,好像是帧率的问题,运行其他同学的双发子弹的代码,子弹射出来很顺畅,我的代码原地 ...

screen.blit(background, (0, 0))

这句话的缩进不对,导致背景没有重绘制
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

1

好友

34

积分

新手上路

Rank: 1

58#
发表于 2019-12-17 14:31:24 |只看该作者
PMCoding 发表于 2019-12-17 14:08
先生教我,
问题:子弹太长了。。。。求教,原因出在哪里
[/img]

看了前面的同学反馈,好像是帧率的问题,运行其他同学的双发子弹的代码,子弹射出来很顺畅,我的代码原地射出来就是一条线,换个地方之前的子弹那条线还在
回复

使用道具 举报

0

主题

1

好友

34

积分

新手上路

Rank: 1

57#
发表于 2019-12-17 14:08:38 |只看该作者
先生教我,
问题:子弹太长了。。。。求教,原因出在哪里
[img][/img] 问题图片.png

代码:
# -*- coding: utf-8 -*-
import pygame
#导入pygame
from sys import exit
import time
#sys模块借一个exit函数用来退出程序
pygame.init()
#初始化pygame,为使用硬件做准备
screen = pygame.display.set_mode((600, 419), 0, 32)
#创建了一个窗口,窗口大小和背景图片大小一样
pygame.display.set_caption("Hello, hahaha!")
#设置窗口标题
pic_a='pygame_pic.png'
pic_b='pygame_pic2.png'
pic_c='pygame_pic3.jpg'
pic_all=[pic_a,pic_b,pic_c]
pic_num=3
background = pygame.image.load(pic_all[pic_num%3]).convert()
plane = pygame.image.load('plane.png').convert_alpha()
bullet=pygame.image.load('bullet.png').convert_alpha()
x_bullet = 0
y_bullet = -1
while True:
#游戏主循环

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            pic_num+=1
            background = pygame.image.load(pic_all[pic_num%3]).convert()
            width=background.get_width()
            height=background.get_height()
            screen = pygame.display.set_mode((width, height), 0, 32)
        screen.blit(background, (0, 0))
    x, y = pygame.mouse.get_pos()
    # 获取鼠标位置
    # 计算飞机的左上角位置
    if y_bullet < 0:
        x_bullet = int(x - bullet.get_width()/2)
        y_bullet = int(y - bullet.get_height()/2)
    else:
        y_bullet -= 0.2
    screen.blit(bullet, (x_bullet, y_bullet))  # 把子弹画到屏幕上
    x -= int(plane.get_width() / 2)
    y -= int(plane.get_height() / 2)
    screen.blit(plane, (x, y))  # 将背景图画上去
    #加载并转换图像
    pygame.display.update()#刷新一下画面
回复

使用道具 举报

6

主题

0

好友

166

积分

注册会员

Rank: 2

56#
发表于 2018-11-14 15:25:44 |只看该作者
crossin先生 发表于 2018-11-13 20:23
else:
        bullet_y -= 5
        bullet_y -= 5

粗心了
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

55#
发表于 2018-11-13 20:23:35 |只看该作者
东东哥 发表于 2018-11-13 16:59
老师,为什么我左右两边的子弹的射速不一样,左边的快

    else:
        bullet_y -= 5
        bullet_y -= 5
        #子弹位置上移

写错了吧

既然左右子弹不一样,就找代码里关于左右子弹的代码查
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

6

主题

0

好友

166

积分

注册会员

Rank: 2

54#
发表于 2018-11-13 16:59:55 |只看该作者
  1. # !/usr/bin/python
  2. import pygame
  3. from sys import exit

  4. pygame.init()
  5. screen = pygame.display.set_mode((450,800),0,32)
  6. pygame.display.set_caption('plane')

  7. background = pygame.image.load('back.jpg').convert()
  8. plane = pygame.image.load('plane.png').convert_alpha()
  9. bullet = pygame.image.load('bullet.png').convert_alpha()
  10. bullet1=bullet
  11. #加载子弹图像

  12. width=plane.get_width()/2
  13. height=plane.get_height()/2

  14. bullet_x=0
  15. bullet_y=-1
  16. bullet1_x=0
  17. bullet1_y=-1

  18. #初始化子弹位置
  19. while True:
  20.     for event in pygame.event.get():
  21.         if event.type == pygame.QUIT:
  22.             pygame.quit()
  23.             exit()
  24.     screen.blit(background, (0,0))

  25.     x, y = pygame.mouse.get_pos()
  26.     if bullet_y <0:
  27.         #如果子弹位置超出了屏幕上端
  28.         bullet_x = x - bullet.get_width() / 2 -23
  29.         bullet_y = y - bullet.get_height() / 2
  30.         bullet1_x = x - bullet.get_width() / 2 + 25
  31.         bullet1_y = y - bullet.get_height() / 2
  32.         #把子弹的中心位置设为鼠标坐标
  33.     else:
  34.         bullet_y -= 5
  35.         bullet_y -= 5
  36.         #子弹位置上移
  37.     screen.blit(bullet,(bullet_x,bullet_y))
  38.     screen.blit(bullet1,(bullet1_x,bullet1_y))
  39.     #把子弹画到屏幕上
  40.     if y>=800-height:
  41.         if x<width:
  42.             screen.blit(plane,(0,800-2*height))
  43.         elif x>450-width:
  44.             screen.blit(plane,(450-2*width,800-2*height))
  45.         else:
  46.             screen.blit(plane,(x-width,800-2*height))
  47.     elif y<height:
  48.         if x<width:
  49.             screen.blit(plane,(0,0))
  50.         elif x>450-width:
  51.             screen.blit(plane,(450-2*width,0))
  52.         else:
  53.             screen.blit(plane,(x-width,0))
  54.     else:
  55.         if x<width:
  56.             screen.blit(plane,(0,y-height))
  57.         elif x>450-width:
  58.             screen.blit(plane,(450-2*width,y-height))
  59.         else:
  60.             screen.blit(plane,(x-width,y-height))  
  61.     pygame.display.update()
复制代码
老师,为什么我左右两边的子弹的射速不一样,左边的快
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

53#
发表于 2018-1-18 11:10:24 |只看该作者
calf_in_cup 发表于 2018-1-17 15:45
飞机对打

有意思
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

28

积分

新手上路

Rank: 1

52#
发表于 2018-1-17 15:45:26 |只看该作者
飞机对打
  1. # -*- coding:utf-8 -*-
  2. from sys import exit

  3. import pygame

  4. pygame.init()
  5. screen = pygame.display.set_mode((450, 800), 0, 32)
  6. pygame.display.set_caption("Hello, World!")
  7. sky = pygame.image.load('back.jpg').convert()
  8. plane = pygame.image.load('plane.png').convert_alpha()
  9. bullet = pygame.image.load('bullet.png').convert_alpha()
  10. # 加载子弹图像

  11. plane_enemy = pygame.image.load('plane_rev.png').convert_alpha()
  12. # 加载敌军战机图像
  13. bullet_enemy = pygame.image.load('bullet_rev.png').convert_alpha()
  14. # 加载敌军子弹图像


  15. bullet_x = 0
  16. bullet_y = -1
  17. # 设置我方子弹初始位置

  18. bullet_enemy_x = 225-bullet.get_width() / 2
  19. bullet_enemy_y = 801
  20. # 设置敌方子弹初始位置

  21. plane_enemy_x = 225-plane_enemy.get_width() / 2
  22. plane_enemy_y = 0
  23. # 设置敌方战机初始位置

  24. while True:
  25.     for event in pygame.event.get():
  26.         if event.type == pygame.QUIT:
  27.             pygame.quit()
  28.             exit()
  29.     screen.blit(sky, (0, 0))
  30.     screen.blit(plane_enemy, (plane_enemy_x, plane_enemy_y))
  31.     # 把敌方战机画到屏幕上
  32.     x, y = pygame.mouse.get_pos()
  33.     # 我方战机运动情况
  34.     if bullet_y < 0:
  35.         # 如果子弹位置超出了屏幕上端
  36.         bullet_x = x - bullet.get_width() / 2
  37.         bullet_y = y - bullet.get_height() / 2
  38.         # 把子弹位置往上移
  39.     else:
  40.         bullet_y -= 5
  41.     screen.blit(bullet, (bullet_x, bullet_y))
  42.     # 把子弹画到屏幕上
  43.     x -= plane.get_width() / 2
  44.     y -= plane.get_height() / 2
  45.     screen.blit(plane, (x, y))

  46.     # 敌方战机运动情况
  47.     if bullet_enemy_y > 800:
  48.         # 如果敌方子弹超出了屏幕下方
  49.         bullet_enemy_x = 225 - bullet.get_width() / 2
  50.         bullet_enemy_y = 0 - bullet.get_height() / 2
  51.     else:
  52.         bullet_enemy_y += 5
  53.     screen.blit(bullet_enemy,(bullet_enemy_x,bullet_enemy_y))
  54.     #把敌方子弹画到屏幕上


  55.     pygame.display.update()
复制代码

TIM截图20180117154309.jpg (19.66 KB, 下载次数: 671)

TIM截图20180117154309.jpg

回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

51#
发表于 2018-1-8 16:19:28 |只看该作者
语法错误,肯定是抄错了,少了括号之类,或者用了中文符号
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-11-22 11:26 , Processed in 0.019877 second(s), 28 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部