老游戏新写之Jetpac重返地球

主人公流落外星球,遇到一群不讲道理的外星人。想跑路,载具又摔得七零八落。

任务:​顶着外星人的进攻,把宇宙飞船的零件都找回来组装好,然后为其添加燃料。最后安全逃离,重返地球。

这是由Chris和Tim Stamper兄弟于1983年创建的8位机游戏Jetpac里的剧情,也是其工作室Ultimate Play the Game出品的首批热门游戏之一。

8位ZX Spectrum电脑上的Jetpac

而当一个宇航员和Ultimate Play the Game的徽标在屏幕上出现时,你知道之前的等待是值得的(八十年代能有这么个游戏玩已经很激动)。

游戏的角色是不幸的宇航员杰特曼,他必须收集四处散落的零件,制造火箭并为其添加燃料,同时还要与成群的致命外星人战斗。

本文提供的代码片段包含收集火箭零件和燃料,以便杰特曼搭载火箭起飞的技巧。

在此之前,先向大家介绍一个游戏框架:pgzero。

该框架全名Pygame Zero,是一个基于Pygame的游戏编程框架。它可以更容易地编辑游戏,无需模板、不用编写事件循环,也无需学习复杂的Pygame API,而且支持树莓派。

安装:
pip install pgzero

我们可以对所有屏幕元素和Actor碰撞例程使用内置的Pygame Zero Actor对象,以便处理重力并拾取物品。

首先,我们需要初始化Actor。

我们需要游戏中的主人公杰特曼,地面,火箭的三个零件,还有火箭发动机所需的一些燃料。

每个Actor的行为方式将由一组列表决定。我们有一个重力对象列表,每帧绘制的对象,平台列表,碰撞对象列表以及可以拾取的对象列表。

杰特曼跳进火箭,回家了。欢呼!

我们的draw()函数很简单,因为它循环遍历绘制列表中的项目列表,然后再绘制几个条件元素。

该update()功能是所有动作发生的地方:我们检查键盘输入来移动杰特曼,将重力应用于重力列表上的所有项目,检查与平台列表的碰撞,如果杰特曼触摸它,则拾取这个项目(对象),应用对杰特曼的任何推力,并移动杰特曼持有的任何物品随他一起移动。

完成所有操作后,我们可以检查添加的燃料量是否已达到火箭可升空的程度。

如果查看辅助函数checkCollisions()和checkTouching(),你会发现它们使用了不同的碰撞检测方法,第一种方法是检查与指定点的碰撞,以便我们可以检测到与actor顶部或底部的碰撞以及触摸冲突是矩形或边界框的冲突,因此如果两个Actor的边界框相交,则会记录一个冲突。

另一个辅助函数applyGravity()使重力列表中的所有元素向下移动,直到Actor的底部撞到碰撞列表上的某物为止。

目前的程序主要就是组装一枚火箭,加满燃料,然后升空。你后续要添加的是一群讨厌的外星人,以及一种用激光枪摧毁它们的方法。

完整代码如下所示:

import random
import time
t0 = time.clock()
jetman = Actor('jetmanl',(400,500))
ground = Actor('ground',(400,550))
platform1 = Actor('platform1',(400,350))
platform2 = Actor('platform2',(200,200))
platform3 = Actor('platform3',(650,200))
rocket1 = Actor('rocket1',(520,500))
rocket2 = Actor('rocket2',(400,300))
rocket3 = Actor('rocket3',(200,150))
rocketFire = Actor('rocketfire',(521,0))
fuel = Actor('fuel',(50,-50))
gravityList = [jetman,rocket1,rocket2,rocket3,fuel]
drawList = [rocket1,rocket2,rocket3,ground,platform1,platform2,platform3,fuel]
platformList = [ground,platform1,platform2,platform3]
collideList = [rocket1,rocket2,rocket3]
pickupList = [rocket2,rocket3,fuel,0,fuel,0,fuel,0,0]
gravity = 1.5
jetman.thrust = jetman.holding = jetman.item = gameState = fuelLevel = timeElapsed = 0
jetman.dir = "l"

def draw():
    global timeElapsed
    screen.clear()
    for i in range(0, len(drawList)):
        drawList[i].draw()
    if gameState == 0:
        jetman.draw()
        timeElapsed = int(time.clock() - t0)
    else:
        rocketFire.draw()
        screen.draw.text("MISSION ACCOMPLISHED", center = (400, 300), owidth=0.5, ocolor=(255,255,255), color=(0,0,255) , fontsize=80)
    screen.draw.text("TIME:"+str(timeElapsed), center= (400, 20), owidth=0.5, ocolor=(255,255,255), color=(255,0,0) , fontsize=40)

def update():
    global gameState, fuelLevel
    burn = ""
    if gameState == 0:
        if keyboard.up:
            jetman.thrust = limit(jetman.thrust+0.3,0,5)
            burn = "f"
        if keyboard.left:
            jetman.dir = "l"
            jetman.x -= 1
        if keyboard.right:
            jetman.dir = "r"
            jetman.x += 1
        applyGravity()
        coll = checkCollisions(platformList,(jetman.x,jetman.y-32))
        if coll == False:
            jetman.y -= jetman.thrust
        if pickupList[jetman.item] != 0:
            if checkTouching(pickupList[jetman.item], jetman):
                jetman.holding = pickupList[jetman.item]
        jetman.thrust = limit(jetman.thrust-0.1,0,5)
        jetman.image = "jetman" + jetman.dir + burn
        if jetman.holding != 0 :
            jetman.holding.pos = jetman.pos
            if jetman.holding.x == rocket1.x and jetman.holding.y < 440:
                jetman.holding = 0
                jetman.item += 1
        if fuel.x == rocket1.x and fuel.y+16 > rocket3.y-32 and jetman.holding == 0:
            fuelLevel += 1
            if fuelLevel < 4:
                jetman.item += 1
                if fuelLevel < 3 :
                    fuel.pos = (random.randint(50, 750),-50)
                else:
                    fuel.pos = (0,650)
                gravityList[fuelLevel].image = "rocket"+str(fuelLevel)+"f"
        if fuelLevel == 3 and jetman.x == rocket1.x and jetman.y > rocket3.y:
            gameState = 1
    if gameState == 1:
        rocket1.y -= 1
        rocket2.y -= 1
        rocket3.y -= 1
        rocketFire.y = rocket1.y + 50

def limit(n, minn, maxn):
    return max(min(maxn, n), minn)

def checkCollisions(cList, point):
    for i in range(0, len(cList)):
        if cList[i].collidepoint(point):
            return True
    return False

def checkTouching(a1,a2):
    if a1.colliderect(a2): return True
    return False

def applyGravity():
    for i in range(0, len(gravityList)):
        if checkCollisions(platformList,(gravityList[i].x,gravityList[i].y+(gravityList[i].height/2))) == False and checkCollisions(collideList,(gravityList[i].x,gravityList[i].y+(gravityList[i].height/2))) == False:
            gravityList[i].y += gravity

以上就是Mark的Jetpac代码,你可以在这里下载。

https://github.com/IoToutpost/P

 安装:
pip install pgzero


PS:若要全面系统学习Pygame Zero可以参考《趣学Python游戏编程》一书,该书通过十个经典游戏案例,深入浅出地介绍了游戏编程的基本原理,以及Pygame Zero的具体使用方法。相信学完这本书后你也能开发出如此精彩的小游戏。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值