通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏04之跳跃

简介: 通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏04之跳跃

配套视频教程


配套视频教程

本节最终效果:


image.png

向上弹跳其实很简单,按下空格触发时,只要把y轴速度给一个向上的速度即可。

调用该方法,会使方块具有向上20px的速度,然后由于重力依然在起作用,所以二者结合,就会形成向上弹跳的效果。

main.py


image.png


sprites.py新增jump方法。

def jump(self):
        # jump only if standing on a platform
        self.rect.x += 1
        hits = pg.sprite.spritecollide(self, self.game.platforms, False)
        self.rect.x -= 1
        if hits:
            self.vel.y = -20

上面冲突检测的代码是保证只有站在挡板上才可以起跳,否则可以在空中连跳。


多加一些挡板


settings.py


image.png


main.py的new方法修改如下:


image.png

一个遗留问题


运行程序,发现一个问题:向上跳时,如果上方有档板,永远不可能跳过档板,只要一接近档板,就自动吸附上去了。

是因为main.py中,一直在检测碰撞,向上跳的过程中,如果头顶有档板,一碰到档板,代码逻辑就强制把方块固定在档板上了(即:认为方块落在档板上了)。改进方法:仅在下降过程中,才做碰撞检测,update方法修改如下:


image.png

相比之前,加了一个碰撞检测判断,如果不加这个条件,就会出现以下现象:


其他一些小改动


image.png


image.png

完整代码:

settings.py

# game options/settings
TITLE = "Jumpy!"
WIDTH = 480
HEIGHT = 600
FPS = 60
# Player properties
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.8
# Starting platforms
PLATFORM_LIST = [(0, HEIGHT - 40, WIDTH, 40),
                 (WIDTH / 2 - 50, HEIGHT * 3 / 4, 100, 20),
                 (125, HEIGHT - 350, 100, 20),
                 (350, 200, 100, 20),
                 (175, 100, 50, 20)]
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
LIGHTBLUE = (0, 155, 155)

main.py

import pygame as pg
import random
from settings import *
from sprites import *
class Game:
    def __init__(self):
        # initialize game window, etc
        pg.init()
        pg.mixer.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        self.running = True
    def new(self):
        # start a new game
        self.all_sprites = pg.sprite.Group()
        self.platforms = pg.sprite.Group()
        self.player = Player(self)
        self.all_sprites.add(self.player)
        for plat in PLATFORM_LIST:
            p = Platform(*plat)
            self.all_sprites.add(p)
            self.platforms.add(p)
        self.run()
    def run(self):
        # Game Loop
        self.playing = True
        while self.playing:
            self.clock.tick(FPS)
            self.events()
            self.update()
            self.draw()
    def update(self):
        # Game Loop - Update
        self.all_sprites.update()
        # check if player hits a platform - only if falling
        # if self.player.vel.y > 0:
        hits = pg.sprite.spritecollide(self.player, self.platforms, False)
        if hits:
            self.player.pos.y = hits[0].rect.top
            self.player.vel.y = 0
    def events(self):
        # Game Loop - events
        for event in pg.event.get():
            # check for closing window
            if event.type == pg.QUIT:
                if self.playing:
                    self.playing = False
                self.running = False
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_SPACE:
                    self.player.jump()
    def draw(self):
        # Game Loop - draw
        self.screen.fill(BLACK)
        self.all_sprites.draw(self.screen)
        # *after* drawing everything, flip the display
        pg.display.flip()
    def show_start_screen(self):
        # game splash/start screen
        pass
    def show_go_screen(self):
        # game over/continue
        pass
g = Game()
g.show_start_screen()
while g.running:
    g.new()
    g.show_go_screen()
pg.quit()

sprites.py

# Sprite classes for platform game
import pygame as pg
from settings import *
vec = pg.math.Vector2
class Player(pg.sprite.Sprite):
    def __init__(self, game):
        pg.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pg.Surface((30, 40))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.rect.center = (WIDTH / 2, HEIGHT / 2)
        self.pos = vec(WIDTH / 2, HEIGHT / 2)
        self.vel = vec(0, 0)
        self.acc = vec(0, 0)
    def jump(self):
        # jump only if standing on a platform
        self.rect.x += 1
        hits = pg.sprite.spritecollide(self, self.game.platforms, False)
        self.rect.x -= 1
        if hits:
            self.vel.y = -20
    def update(self):
        self.acc = vec(0, PLAYER_GRAV)
        keys = pg.key.get_pressed()
        if keys[pg.K_LEFT]:
            self.acc.x = -PLAYER_ACC
        if keys[pg.K_RIGHT]:
            self.acc.x = PLAYER_ACC
        # apply friction
        self.acc.x += self.vel.x * PLAYER_FRICTION
        # equations of motion
        self.vel += self.acc
        self.pos += self.vel + 0.5 * self.acc
        # wrap around the sides of the screen
        if self.pos.x > WIDTH:
            self.pos.x = 0
        if self.pos.x < 0:
            self.pos.x = WIDTH
        self.rect.midbottom = self.pos
class Platform(pg.sprite.Sprite):
    def __init__(self, x, y, w, h):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((w, h))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y


目录
相关文章
|
1月前
|
索引 Python
python-类属性操作
【10月更文挑战第11天】 python类属性操作列举
18 1
|
1月前
|
Java C++ Python
Python基础---类
【10月更文挑战第10天】Python类的定义
21 2
|
1月前
|
设计模式 开发者 Python
Python类里引用其他类
Python类里引用其他类
|
1月前
|
设计模式 开发者 Python
Python 类中引用其他类的实现详解
Python 类中引用其他类的实现详解
36 1
WK
|
1月前
|
Python
Python类命名
在Python编程中,类命名至关重要,影响代码的可读性和维护性。建议使用大写驼峰命名法(如Employee),确保名称简洁且具描述性,避免使用内置类型名及单字母或数字开头,遵循PEP 8风格指南,保持项目内命名风格一致。
WK
13 0
|
1月前
|
程序员 开发者 Python
深度解析Python中的元编程:从装饰器到自定义类创建工具
【10月更文挑战第5天】在现代软件开发中,元编程是一种高级技术,它允许程序员编写能够生成或修改其他程序的代码。这使得开发者可以更灵活地控制和扩展他们的应用逻辑。Python作为一种动态类型语言,提供了丰富的元编程特性,如装饰器、元类以及动态函数和类的创建等。本文将深入探讨这些特性,并通过具体的代码示例来展示如何有效地利用它们。
37 0
|
1月前
|
Python
Python中的类(一)
Python中的类(一)
|
1月前
|
Python
Python中的类(一)
Python中的类(一)
|
1月前
|
Python
Python中的类(二)
Python中的类(二)
|
1月前
|
开发者 Python
Python类和子类的小示例:建模农场
Python类和子类的小示例:建模农场