Crossin的编程教室

标题: 【Pygame 第7课】 多变的宿敌 [打印本页]

作者: crossin先生    时间: 2013-8-29 23:45
标题: 【Pygame 第7课】 多变的宿敌
在游戏中,一般都有个宿敌什么的。在我们这个打飞机小游戏中,宿敌就是不断从天而降的敌机。它与本机、子弹构成了这个游戏的三个要素:



这节课就来创造这个宿敌。

同样,为敌机创建一个类:Enemy,类的内容大致与Bullet相似。
  1. class Enemy:
  2.     def __init__(self):
  3.         self.x = 200
  4.         self.y = -50
  5.         self.image = pygame.image.load('enemy.png').convert_alpha()

  6.     def move(self):
  7.         if self.y < 800:
  8.             self.y += 0.3
  9.         else:
  10.             self.y = -50
复制代码
让敌机在屏幕上方外部靠中间的位置产生,并且在每一次循环中都向下移动,当飞出屏幕下方后,就回到屏幕上方重新开始。

和bullet一样,我们创建一个Bullet对象,然后在循环中调用它的move方法,并且绘制在屏幕上。
  1. enemy = Enemy()

  2. while True:
  3.     ###
  4.     enemy.move()
  5.     screen.blit(enemy.image, (enemy.x, enemy.y))
复制代码
运行程序。敌机开始在屏幕中部周而复始地自上向下运动。

这宿敌也太呆了吧!
这样的游戏谁要玩!

所以我们要加点随机性。

让敌机的出现位置有变化,让它的速度有变化。

给Enemy增加一个restart方法:
  1. def restart(self):
  2.     self.x = random.randint(50, 400)
  3.     self.y = random.randint(-200, -50)
  4.     self.speed = random.random() + 0.1
复制代码
它的作用是,给敌机在屏幕上方的一定范围内随机一个初始位置,然后再给它增加一个叫做speed的随机量,作为它的速度,在move函数中被使用。这样,它的行为开始有了变化。这里用到了random模块,记得在程序开头import它。

restart在__init__函数以及飞出屏幕下方时调用。后面,在敌机被击中的时候,也会要调用它。

再次运行程序,看上去有那么点意思了。如果敌机再多一点,子弹再多一点,就更好了。这个,留在下节课中说。

7game.png
7-1.png

7-2.png

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

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

enemy.png (5.88 KB, 下载次数: 1606)

enemy.png


作者: Victor    时间: 2013-8-30 08:27
沙发hiahia~~~早上先打一把飞机~~
作者: xiaotong125    时间: 2013-8-30 09:22
帅呆了
作者: piaoxu    时间: 2013-8-31 09:40
早上好~~~~
作者: jpjlqone    时间: 2013-9-1 15:12
游戏已经可以玩了,但计分有问题
  1.    
  2.     text = font.render('Score: '+str(score),1,(50,50,100))
  3.     textpos = text.get_rect()
  4.     textpos.center = bg.get_rect().center
  5.     bg.blit(text, textpos)        

  6.     screen.blit(plane,(x, y))
  7.     pygame.display.update()
复制代码
每次得分都会在原来 的数字上面复写,而不是更新数字(就是1会直接写在0上面,2又会直接写在1和0上面,全部都重叠了)请教下。
作者: crossin先生    时间: 2013-9-1 22:46
jpjlqone 发表于 2013-9-1 15:12
游戏已经可以玩了,但计分有问题每次得分都会在原来 的数字上面复写,而不是更新数字(就是1会直接写在0上 ...

因为你是在bg上blit,就是把数字绘制在了背景上,每次都会不停往上绘制而不重新刷新。
你应该绘制在screen上。screen.blit
作者: jpjlqone    时间: 2013-9-1 23:15
crossin先生 发表于 2013-9-1 22:46
因为你是在bg上blit,就是把数字绘制在了背景上,每次都会不停往上绘制而不重新刷新。
你应该绘制在scree ...

对啊,这个怎么疏忽了,确实没经验。已经打包exe给女朋友玩啦哈哈
作者: crossin先生    时间: 2013-9-2 11:46
jpjlqone 发表于 2013-9-1 23:15
对啊,这个怎么疏忽了,确实没经验。已经打包exe给女朋友玩啦哈哈


作者: shallecker    时间: 2013-10-20 09:25
经典的教程。。
作者: 牵着蚂蚁遛达    时间: 2014-8-13 17:09
crossin先生 发表于 2013-9-2 11:46

麻烦问一下,self.y为啥初始化为-50呢?我把y设置成任何值效果都一样。。。。
作者: crossin先生    时间: 2014-8-14 14:19
牵着蚂蚁遛达 发表于 2014-8-13 17:09
麻烦问一下,self.y为啥初始化为-50呢?我把y设置成任何值效果都一样。。。。 ...

-50就是让敌机最开始的时候默认是在屏幕上方之外
作者: daiqifan    时间: 2015-10-12 16:07
老师 为啥我在ubantu环境下运行的情况, 自己的飞机每一次都是出现在最左上角。  我初始化一个坐标都不可以呢?
作者: daiqifan    时间: 2015-10-12 16:18
# -*- coding: utf-8 -*-
import pygame
from pygame import *
from sys import exit
import random

class Plane(object):
        def __init__(self):
                self.image = pygame.image.load('plane.png').convert_alpha()
                self.width = self.image.get_width()
                self.height = self.image.get_height()
                self.x = 225 - self.width / 2
                self.y = 700 - self.height / 2

        def move(self):
                mouseX, mouseY = pygame.mouse.get_pos()
                self.x = mouseX - self.width / 2
                self.y = mouseY - self.height / 2


class Bullet(object):
        def __init__(self):
                self.x = 0
                self.y = -1
                self.image = pygame.image.load('bullet.png').convert_alpha()
                self.width = self.image.get_width()
                self.height = self.image.get_height()

        def move(self):
                if self.y < 0:
                        mouseX, mouseY = pygame.mouse.get_pos()
                        self.x = mouseX - self.width / 2
                        self.y = mouseY - self.height / 2
                else:
                        self.y -= 8

class Enemy(object):
        def restart(self):
                self.x = random.randint(50, 400)
                self.y = random.randint(-200, -50)
                self.speed = random.random() + 0.1

        def __init__(self):
                self.restart()
                self.image = pygame.image.load('enemy.png').convert_alpha()

        def move(self):
                if self.y < 800:
                        self.y += self.speed
                else:
                        self.restart()

pygame.init()
screen = pygame.display.set_mode((450, 800), 0, 32)
pygame.display.set_caption("@Shoot__Plane@")
background = pygame.image.load('back.jpg').convert()


bullet = Bullet()
enemy = Enemy()
plane = Plane()

while True:
        for event in pygame.event.get():
                if event.type == pygame.QUIT:
                        pygame.quit()
                        exit()
        screen.blit(background,( 0,0))

        bullet.move()
        screen.blit(bullet.image, (bullet.x, bullet.y))

        enemy.move()
        screen.blit(enemy.image, (enemy.x, enemy.y))

        screen.blit(plane.image, (plane.x, plane.y))
        plane.move()

        pygame.display.update()


请教一下老师,我把 #plane.move()注释掉以后,发现我的飞机确实初始化在我想要的屏幕中间下方的位置,不知道为啥不注释的时候每次程序运行飞机都在屏幕最左上方。
作者: crossin先生    时间: 2015-10-13 13:43
daiqifan 发表于 2015-10-12 16:18
# -*- coding: utf-8 -*-
import pygame
from pygame import *

pygame.mouse.get_pos()
可能因为一开始这个值没有吧?你把move里面的数据打印出来看看是多少
作者: windgod    时间: 2016-6-13 23:33
大神好!我觉得这节课的内容,需要解释下,在程序最开始要加个“import random”,否则会错误
作者: crossin先生    时间: 2016-6-14 11:14
windgod 发表于 2016-6-13 23:33
大神好!我觉得这节课的内容,需要解释下,在程序最开始要加个“import random”,否则会错误 ...

嗯,提到了一句但没有特别强调。因为random在基础课程前面讲过,所以就一笔带过了。
作者: 江南小才子    时间: 2016-6-16 22:57
想问一下CROOSIN先生,为什么这一课的程序,实现后,必须移动鼠标才能发子弹,如果飞机不动,那么子弹和敌机都不会动,不知是何缘故?
作者: crossin先生    时间: 2016-6-17 09:52
江南小才子 发表于 2016-6-16 22:57
想问一下CROOSIN先生,为什么这一课的程序,实现后,必须移动鼠标才能发子弹,如果飞机不动,那么子弹和敌 ...

查看缩进,你是不是把 bullet.move 和 enemy.move 的代码写到事件的 for 循环里了
作者: 江南小才子    时间: 2016-6-28 21:16
crossin先生 发表于 2016-6-17 09:52
查看缩进,你是不是把 bullet.move 和 enemy.move 的代码写到事件的 for 循环里了 ...

是的,先生一语中的,感谢!!
作者: Yumiao_HyunMin    时间: 2016-7-8 13:27
请教一下先生,定义敌机速度时:self.speed = random.random() + 0.1
加0.1的意思是每一次重置速度时速度都要快0.1?
作者: crossin先生    时间: 2016-7-8 18:04
Yumiao_HyunMin 发表于 2016-7-8 13:27
请教一下先生,定义敌机速度时:self.speed = random.random() + 0.1
加0.1的意思是每一次重置速度时速度都 ...

对,避免随机出一个特别慢的值
作者: captainooo    时间: 2016-8-1 11:02
请教下,为啥我的结果显示全局变量random未定义,然后就跑不起来,,
作者: crossin先生    时间: 2016-8-1 11:35
captainooo 发表于 2016-8-1 11:02
请教下,为啥我的结果显示全局变量random未定义,然后就跑不起来,,

没有引用random,或者单词拼错了,还有可能你有文件命名成了random.py
作者: captainooo    时间: 2016-8-1 14:05
crossin先生 发表于 2016-8-1 11:35
没有引用random,或者单词拼错了,还有可能你有文件命名成了random.py

问题已解决,其中一处单词多了个字母。感谢~
作者: Phoestia    时间: 2016-9-13 12:44
cool!
  1. import pygame
  2. import random
  3. from sys import exit

  4. pygame.init()
  5. screen=pygame.display.set_mode((450,800),0,32)
  6. pygame.display.set_caption("plane game")
  7. background=pygame.image.load('back.jpg').convert()
  8. plane=pygame.image.load('plane.png').convert_alpha()

  9. class Bullet:
  10.     def __init__(self):
  11.         self.x=0
  12.         self.y=-1
  13.         self.image=pygame.image.load('bullet.png').convert_alpha()
  14.     def move(self):
  15.         if self.y<0:
  16.             mouseX,mouseY=pygame.mouse.get_pos()
  17.             self.x=mouseX-self.image.get_width()/2
  18.             self.y=mouseY-self.image.get_height()/2
  19.         else:
  20.             self.y-=5
  21. bullet = Bullet()

  22. class Enemy:
  23.     def restart(self):
  24.         self.x=random.randint(50,400)
  25.         self.y=random.randint(-200,-50)
  26.         self.speed=random.random()+0.1
  27.     def __init__(self):
  28.         self.restart()
  29.         self.image=pygame.image.load('enemy.png').convert_alpha()
  30.     def move(self):
  31.         if self.y<800:
  32.             self.y+=self.speed
  33.         else:
  34.             self.restart()
  35. enemy=Enemy()

  36. while True:
  37.     for event in pygame.event.get():
  38.         if event.type==pygame.QUIT:
  39.             pygame.quit()
  40.             exit()
  41.     screen.blit(background,(0,0))
  42.     bullet.move()
  43.     screen.blit(bullet.image,(bullet.x,bullet.y))
  44.     enemy.move()
  45.     screen.blit(enemy.image,(enemy.x,enemy.y))   
  46.     x,y=pygame.mouse.get_pos()
  47.     x-=plane.get_width()/2
  48.     y-=plane.get_height()/2
  49.     screen.blit(plane,(x,y))
  50.     pygame.display.update()


复制代码

作者: python_dino    时间: 2018-1-30 10:53
# -*- coding: utf-8 -*-
import pygame
from sys import exit
import random
from random import randint
class Bullet:
    def __init__(self):
        self.x = 0
        self.y = -1
        self.image = pygame.image.load('bullet.png').convert_alpha()
    def move(self):
        if self.y < 0:
            mouseX,mouseY = pygame.mouse.get_pos()
            self.x = mouseX - self.image.get_width()/2
            self.y = mouseY - self.image.get_height()/2
        else:
            self.y -= 5
class Enemy:
    def restart(self):
        self.x = random,randint(50,400)
        self.y = random.randint(-200,-50)
        self.speed = random.random() + 0.1
    def __init__(self):
        self.restart()
        self.image = pygame.image.load('enemy.png').convert_alpha()
    def move(self):
        if self.y < 800:
            self.y += self.speed
        else:
            self.restart()
pygame.init()
screen = pygame.display.set_mode((450,800), 0, 32)
pygame.display.set_caption("Hello, Queens!")
background = pygame.image.load('back.jpg').convert()
plane = pygame.image.load('plane.png').convert_alpha()
bullet = Bullet()
enemy = Enemy()
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
    screen.blit(background,(0,0))
    bullet.move()
    screen.blit(bullet.image,(bullet.x,bullet.y))
    enemy.move()
    screen.blit(enemy.image,(enemy.x,enemy.y))
    x,y = pygame.mouse.get_pos()
    x-=plane.get_width()/2
    y-=plane.get_height()/2
    screen.blit(plane,(x,y))
    pygame.display.update()

但是显示出错:    screen.blit(enemy.image,(enemy.x,enemy.y))
TypeError: invalid destination position for blit
请问先生
作者: crossin先生    时间: 2018-1-30 15:57
python_dino 发表于 2018-1-30 10:53
# -*- coding: utf-8 -*-
import pygame
from sys import exit

把 (enemy.x,enemy.y) 输出来调试
作者: 少年与猫.    时间: 2018-5-17 18:55
先生有个问题   就是有时候敌机下落的速度特别快   反应不过来   然后random.random()是在(0,1)里面产生的吗? 能不能再控制一下速度
作者: crossin先生    时间: 2018-5-17 22:44
少年与猫. 发表于 2018-5-17 18:55
先生有个问题   就是有时候敌机下落的速度特别快   反应不过来   然后random.random()是在(0,1)里面产生 ...

是0到1
嫌快你可以乘上 0.5
作者: 少年与猫.    时间: 2018-5-18 22:03
crossin先生 发表于 2018-5-17 22:44
是0到1
嫌快你可以乘上 0.5

我自己设了一个list..然后设了一些值在里面   我试试用乘的看看
作者: 简言    时间: 2018-11-26 06:49
c:\6.png
作者: crossin先生    时间: 2018-11-26 12:31
简言 发表于 2018-11-26 06:49

回复的时候点 高级模式,然后上传图片
作者: 简言    时间: 2018-11-26 17:30
crossin先生 发表于 2018-11-26 12:31
回复的时候点 高级模式,然后上传图片

只有部分飞机能消灭,老师  怎么回事呢
作者: 简言    时间: 2018-11-26 17:35
只有部分飞机可以被消灭

无标题.jpg (146.26 KB, 下载次数: 316)

无标题.jpg


作者: 简言    时间: 2018-11-26 18:24
简言 发表于 2018-11-26 17:35
只有部分飞机可以被消灭

解决了





欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5