Pygame模仿Ketchapp的Rush Hero

Rush Hero by ketchapp
模仿对象: Rush Hero by Ketchapp
规则:天空中会随机掉落物块,玩家需要控制“英雄”左右移动来躲避这些物块。每个物块砸中地面时玩家都会得1分。


1. 代码开始

import pygame, sys, random, time

class GameObj(pygame.sprite.Sprite):
    def __init__(self, size, location, color):
        pygame.sprite.Sprite.__init__(self)
        self.size = size
        image_surface = pygame.surface.Surface([self.size, self.size])
        image_surface.fill(color)
        self.image = image_surface.convert()
        self.rect = self.image.get_rect()
        self.rect.left = location[0]
        self.rect.top = location[1]

    def display(self):
        screen.blit(self.image, self.rect)

screenW = 800
screenH = 600

pygame.init()
screen = pygame.display.set_mode([screenW, screenH])
screen.fill([0,0,50])

pygame.display.flip()

while True:
	time.sleep(0.02)
    screen.fill([0,0,50])
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    pygame.display.flip()

这里创建了一个长800高600的窗口,并且用[0, 0, 50]这样一个深蓝色来填充背景。帧数设定为50。
此处还定义了GameObj精灵类。出于简化程序的目的,此游戏中的每一个gameobject都是正方形的。display方法用于渲染。


2. Player

class Player(GameObj):
    def __init__(self):
        global screenW
        global screenH
        size = 40
        GameObj.__init__(self, size, [0, screenH - size], (255,0,0))

Player类继承了GameObj类,将其位置设定在整个窗口的左下角。边长为40,可以根据个人喜好来改动这个属性。

player = Player()

while True:
	time.sleep(0.02)    time.sleep(0.02)
    screen.fill([0,0,50])
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEMOTION:
            player.rect.centerx = event.pos[0]

    screen.fill([0,0,50])
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEMOTION:
            player.rect.centerx = event.pos[0]

在初始化中创建player实例并在事件检测中加入对光标的检测,player的水平位置和光标的水平位置一致。


3. Ball

class Ball(GameObj):
    def __init__(self):
        global screenW
        global screenH

        size = random.randint(100, 150)
        location = [random.choice([-size, screenW]), screenH - 400]
        GameObj.__init__(self, size, location, (255,255,255))

        self.direction = -1
        if location[0] < 0:
            self.direction = 1

        self.speed = [random.randint(1,3) * self.direction, 0]
        self.g = 0.1

此处我们给球(其实这里是个方块)一个随机的边长,初始位置随机给定在窗口的左侧或者右侧,高度则是一个固定值。
接下来我们根据球的水平位置来判读它是要向左移动还是向右移动。如果球在屏幕左侧,则向右移动,反之亦然。
方向是用正负1来表示,这个主要是用于下面一行对其移动速度的定义。
球的重力加速度设为0.1

def gravity(self):
        global screenH
        global score
        global score_text
        self.speed[1] += self.g
        self.rect.left += self.speed[0]
        self.rect.top += self.speed[1]

        if self.rect.bottom >= screenH:
            self.speed[1] = -5

这里使用物理公式模拟平抛运动,之所以说是平抛是因为球本身是有水平速度的。
当球碰到窗口底部时会反弹,这里我并没有直接将垂直速度取反,而是直接赋值-5,这一来是为了调整球的反弹高度,进而调整游戏难度,二来是为了确保球不会因为计算问题而越蹦越高。


4. 初始化

player = Player()
balls = pygame.sprite.Group()
pygame.time.set_timer(pygame.USEREVENT, 1500)

创建player实例和balls精灵组。并定义一个定时器用于生成球。

5. 生成球

#每隔1.5妙生成一个球并添加至精灵组
elif event.type == pygame.USEREVENT:
            newBall = Ball()
            balls.add(newBall)

将上述代码加入事件检测中

6. 球的移动,所有GameObj的渲染

for i in balls:
        i.gravity()
        i.display()
        if i.out():
            balls.remove(i)

    player.display()
    pygame.display.flip()

这里出现了一个out方法,是用于判断球是否是已经离开了窗口,如果已经离开那么就删除掉这个球。

def out(self):
        global screenW
        if self.rect.right <= 0 or self.rect.left >= screenW:
            return True
        return False
#这个是添加在Ball类中的方法

7. 碰撞检测

检测player是否和某一个球相撞

if pygame.sprite.spritecollide(player, balls, False):
	init()

init()是用于暂停整个游戏的,当玩家按下R时,整个游戏初始化并重新开始。

def init():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    player.__init__()
                    for i in balls:
                        balls.remove(i)

8. 完整代码(加入了得分)

import pygame, sys, random, time

class GameObj(pygame.sprite.Sprite):
    def __init__(self, size, location, color):
        pygame.sprite.Sprite.__init__(self)
        self.size = size
        image_surface = pygame.surface.Surface([self.size, self.size])
        image_surface.fill(color)
        self.image = image_surface.convert()
        self.rect = self.image.get_rect()
        self.rect.left = location[0]
        self.rect.top = location[1]

    def display(self):
        screen.blit(self.image, self.rect)

class Player(GameObj):
    def __init__(self):
        global screenW
        global screenH
        size = 40
        GameObj.__init__(self, size, [0, screenH - size], (255,0,0))

class Ball(GameObj):
    def __init__(self):
        global screenW
        global screenH

        size = random.randint(100, 150)
        location = [random.choice([-size, screenW]), screenH - 400]
        GameObj.__init__(self, size, location, (255,255,255))

        self.direction = -1
        if location[0] < 0:
            self.direction = 1

        self.speed = [random.randint(1,3) * self.direction, 0]
        self.g = 0.1

    def gravity(self):
        global screenH
        global score
        global score_text
        self.speed[1] += self.g
        self.rect.left += self.speed[0]
        self.rect.top += self.speed[1]

        if self.rect.bottom >= screenH:
            self.speed[1] = -5
            score += 1
            score_text = font.render(str(score), 1, (255,255,255))

    def out(self):
        global screenW
        if self.rect.right <= 0 or self.rect.left >= screenW:
            return True
        return False

def init():
    global score
    global score_text
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    player.__init__()
                    for i in balls:
                        balls.remove(i)
                    score = 0
                    score_text = font.render(str(score), 1, (255,255,255))
                    return 0

screenW = 800
screenH = 600

pygame.init()
screen = pygame.display.set_mode([screenW, screenH])
screen.fill([0,0,50])

player = Player()
balls = pygame.sprite.Group()
score = 0
font = pygame.font.Font(None, 50)
score_text = font.render(str(score), 1, (255,255,255))

pygame.time.set_timer(pygame.USEREVENT, 1500)

pygame.display.flip()

while True:
    time.sleep(0.02)
    screen.fill([0,0,50])
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEMOTION:
            player.rect.centerx = event.pos[0]
        elif event.type == pygame.USEREVENT:
            newBall = Ball()
            balls.add(newBall)

    if pygame.sprite.spritecollide(player, balls, False):
        init()

    for i in balls:
        i.gravity()
        i.display()
        if i.out():
            balls.remove(i)

    player.display()
    screen.blit(score_text, [10,10])
    pygame.display.flip()

效果
Rush Hero by Alpaca_Max


9. 后记

可以通过修改一下属性来修改游戏难度:

Player

  • player.size

Ball

  • size = random.randint(X, Y)
  • Ball.speed #包括gravity方法中的
  • Ball.g

猜你喜欢

转载自blog.csdn.net/qq_37225652/article/details/85465276