python玛丽冒险_超级玛丽的 python 实现
超級瑪麗的 python 實現
在經過三四天的摸索,參考了Github上的一個大神的代碼的前提下,也算是初步搭建起了自己的超級瑪麗,下面就給大家分享一些自己踩的坑。
這里是
推薦一下Github上一個pygame的
推薦一本《python和pygame游戲開發指南》,想要深入研究的朋友可以去翻閱一下
關于 pygame 模塊可以查看
在開始之前你需要:掌握 python 的基本語法
熟悉 pygame 模塊的基本使用
由于pygame游戲的基本入門在之前一篇博客中有見過這里就不再贅述
1. 畫面和角色的導入
創建屏幕、從圖片中導入Mario
# 屏幕創建和初始化參數
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
self.rect = self.screen.get_rect()
pygame.display.set_caption(TITLE)
# 加載關卡圖片
self.background = load_image('level.png')
self.back_rect = self.background.get_rect()
# 這里載入圖片需要乘上特定的系數來適配屏幕的尺寸
self.background = pygame.transform.scale(self.background,
(int(self.back_rect.width * BACKGROUND_SIZE),
int(self.back_rect.height * BACKGROUND_SIZE))).convert()
# 導入Mario
self.sheet = load_image('mario.png')
# 這里由于Mario會有奔跑和跳躍的速度,所以需要導入一整張圖片再裁剪使用。
self.load_from_sheet()
# 初始化角色的一些基本常量
self.rect = self.image.get_rect()
self.pos = vec(WIDTH * 0.5, GROUND_HEIGHT - 70)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
2. 角色的落地、跳躍和移動
在這之前要解決一下Mario如何才能站在我們定義的地面上
self.acc = vec(0, GRAVITY)
if GROUND_HEIGHT < self.mario.pos.y:
# 如果Mario低于我們定義的地面,就之間將他的所有速度加速度都置零,之間放在我們的地面上
# 如果速度和加速度不值零,可能會出現Mario卡在地面上抖動的情況,由于y值的不斷變化
self.mario.acc.y = 0
self.mario.vel.y = 0
self.mario.pos.y = self.ground_collide.rect.top
self.mario.landing = True
正如之前那一篇文章所說,角色的移動如果只是單純的實現以像素為單位向左向右移動,無疑會很影響玩家的游戲體驗正如以下
可以明顯感覺到兩個方向的運動的不同體驗,下面是兩個方向的代碼作為比對
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
# 向右
self.pos.x += 5 # ------------------------簡單的改變位置
elif keys[pygame.K_LEFT]:
# 向左
if self.vel.x < 0:
# 這里很細節的加入了一個轉向的速度控制
self.acc.x = -TURNAROUND
if self.vel.x >= 0: # ------------------------改變加速度來改變運動
self.acc.x = -ACC
# 這里加入了一個最大速度限制
if abs(self.vel.x) < MAX_SPEED:
self.vel.x += self.acc.x
elif keys[pygame.K_LEFT]:
self.vel.x = -MAX_SPEED
elif keys[pygame.K_RIGHT]:
self.vel.x = MAX_SPEED
# 這里對加速度和速度進行計算得出位移并在下一幀時改變Mario的位置
self.acc.x += self.vel.x * FRICTION
# 同時還要引用一個 摩擦力 的概念,隨著速度的增大而增大
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
self.rect.midbottom = self.pos
對于角色的跳躍,一定要對其狀態加以限制,讓其必須在 "落地" 的狀態下才能開始跳躍,不然就會產生下面的情況
為了避免這種情況,我們引入了一個self.landing狀態,只有但其在為true的時候才能響應跳躍事件
if keys[pygame.K_SPACE]:
if self.landing:
# 這里跳躍的參數,只是給Mario一個向上的速度,類似于物理中的上拋運動
self.vel.y = -JUMP
這里以上的所有大寫常量參數都是定義在單獨的配置文件中,方便修改。其參數的大小可以自行調節找出最合適的一組
對于這些運動的參數大家可以自己去調試調試,嘗試一下不同的操作體驗,也可以去文末的代碼自尋
3. 角色的動作圖片的切換
在提供的素材中是張表如圖,我們需要自行裁剪下我們所需要的圖片
這里可以在工具類中定義一個加載圖片的方法
def load_image(filename):
src = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(src, 'resources', 'graphics', filename)
return pygame.image.load(path)
從sheet中裁切圖片
# 裁切方法
def get_image(self, x, y, width, height):
image = pg.Surface([width, height])
rect = image.get_rect()
image.blit(self.sheet, (0, 0), (x, y, width, height))
image.set_colorkey(BLACK)
image = pg.transform.scale(image,
(int(rect.width * MARIO_SIZE),
int(rect.height * MARIO_SIZE)))
return image
?
# 裁切并加入容器
def load_from_sheet(self):
self.right_frames = []
self.left_frames = []
?
self.right_frames.append(
self.get_image(178, 32, 12, 16)) # 站立
self.right_frames.append(
self.get_image(80, 32, 15, 16)) # 跑 1
self.right_frames.append(
self.get_image(96, 32, 16, 16)) # 跑 2
self.right_frames.append(
self.get_image(112, 32, 16, 16)) # 跑 3
self.right_frames.append(
self.get_image(144, 32, 16, 16)) # 跳
?
# 將向右的圖片水平翻轉就是向左的圖片了
for frame in self.right_frames:
new_image = pg.transform.flip(frame, True, False)
self.left_frames.append(new_image)
?
# 最后全部加入容器方便我們之間通過下標
self.frames = self.right_frames + self.left_frames
圖片的切換,一開始我是采用一幀換一張圖片的方向,下面是代碼
# 定義一個方法來通過運動方向更換圖片
def walk(self, facing):
if facing == 'right':
if self.image_index > 3:
self.image_index = 0
if facing == 'left':
if self.image_index > 8:
self.image_index = 5
if self.image_index < 5:
self.image_index = 5
self.image_index += 1
但后來在運行的時候我發現了一個讓人懵逼的效果
后來發現這是由于我的圖片是每幀一換,快的讓人反應不過來,產生了這種讓人苦笑不得的效果。
后來在參考大神的源碼的時候,發現了一種控制圖片切換速度的方法。不得不說大神還是很細節的,引入的一些常量系數和時間戳,通過Mario的移動速度來控制圖片切換,讓其更加自然平滑。下面是代碼
# 改進后的代碼
def walk(self, facing):
if self.image_index == 0:
self.image_index += 1
# 加入一個時間戳
self.walking_timer = pg.time.get_ticks()
else:
# 比較時間變化和當前的Mario的速度
if (pg.time.get_ticks() - self.walking_timer >
self.calculate_animation_speed()):
self.image_index += 1
self.walking_timer = pg.time.get_ticks()
if facing == 'right':
if self.image_index > 3:
self.image_index = 0
if facing == 'left':
if self.image_index > 8:
self.image_index = 5
if self.image_index < 5:
self.image_index = 5
# 計算速度的方法
def calculate_animation_speed(self):
if self.vel.x == 0:
animation_speed = 130
elif self.vel.x > 0:
animation_speed = 130 - (self.vel.x * 12)
else:
animation_speed = 130 - (self.vel.x * 12 * -1)
4. 背景圖片的滾動
本來背景的移動還是比較簡單的,一如飛機大戰和之前的那個jumpy的游戲: 只需要當角色的位置超過屏幕參數的某個值(如2/3)時,角色的位置不再相對的移動,而是將角色是位移反向的加到背景上,通過背景的后退就可以實現角色的相對移動。
當在超級瑪麗中很明顯是不適用的,因為整個關卡上定位了很多磚塊,管道和階梯,背景的后退只能改變Mario相對的坐標,但絕對的坐標是不發生任何變化的,這就很大程度上影響了Mario和一些物體的位置的碰撞的判斷。
在這里就需要用到一種暫且稱為鏡頭移動的技術,也就是對surface類的blit方法的參數的調整
# 先定義好 鏡頭的位置移動規則 即self.viewpoint
if self.level.mario.pos.x < self.viewpoint.x + 15:
self.level.mario.pos.x -= self.level.mario.vel.x
if self.level.mario.vel.x > 0:
if self.level.mario.pos.x > WIDTH * 0.55 + self.viewpoint.x:
# 1.1 這個系數是為了屏幕的順滑后期加上去的
self.viewpoint.x += int(self.level.mario.vel.x * 1.1)
# self.viewpoint是一個根據Mario的移動而改變參數的矩形
self.screen.blit(self.background, (0, 0), self.viewpoint)
self.all_group.draw(self.screen)
讓我們來看一下上面兩端代碼的執行效果
很明顯背景也移動了,Mario也移動了,但看上去好像是背景移動的太慢了追不上Mario。但在調整了Mario的速度后發現問題根本不是出在這里。
問題的根源在于: 我們將背景繪制在屏幕上,再將Mario繪制在屏幕上,這樣Mario就是相對于屏幕的速度,那么他是肯定會永遠超過屏幕的。這里我們需要做的是將Mario繪制到背景上,再將背景繪制到屏幕上
那么這就又出現了一個很魔性的效果,問題出現的根源就是我們每一幀都將Mario的狀態繪制到背景上,每一幀都被我們背景保留了下來。不過這驗證了我們之前的想法,至少我們的屏幕滾動跟上了
即然是這樣,那我們就每次都弄一個新背景不就好了!一開始我是采用每一次都導入背景,新建并放大到屏幕大小,但這樣工作量太大就會產生我們游戲中一個很討厭的情景:掉幀。那么我們就可以用pygame.Surface.copy()這個方法,只在加載游戲的時候加載背景,每一幀只需要對背景進行拷貝一份就可以了
下面就是問題的解決方法
def draw(self):
pg.display.flip()
# 每次都將背景拷貝一份,并且每一次都繪制在新的背景上,那么之前的就會被覆蓋
self.background_clean = self.background.copy()
self.all_group.draw(self.background_clean)
self.screen.blit(self.background, (0, 0), self.viewpoint)
self.all_group.draw(self.screen)
5. 項目的重構
在完成了大部分的基礎的工作之后,就不得不需要考慮一下整個項目的重新架構了,畢竟這個項目在我們開始著手之后才發現他的邏輯還是比較繁雜的,重新的構架可以幫我們更好的模塊解耦,方便閱覽可增加新的板塊。
原項目的代碼估計得有三四千行吧,他的項目構建可以說是很細致,大致劃分了十幾個文件。我這邊也給代碼大致分了一下類,理一下整個游戲的思路main.py:整個游戲的主入口,控制整個游戲的循環
sprites.py:定義整個游戲的所有精靈類及其所有方法
level.py:規范整個關卡,創建所有精靈實體類,規定管道,臺階,磚塊等物體的位置,對各種事件的判斷
settings.py:規定所有參數,方便調整
tools.py:工具類,定義一些必要的方法,例如圖片、聲音、背景音樂的載入
6. 地面、管道和臺階
雖然在整個背景中存在這三樣東西,但我們并沒有他們的數據,也就不能進行碰撞檢測等操作
這里我們定義了一個類來創建這三個實例對象,獲得他們的矩形邊框參數
class Collider(pg.sprite.Sprite):
def __init__(self, x, y, width, height):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((width, height)).convert()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
然后在level.py中創建他們的實例并加入精靈組
def set_ground(self):
ground_rect1 = Collider(0, GROUND_HEIGHT, 2953, 60)
# 其余的省略
self.ground_group = pg.sprite.Group(ground_rect1,
ground_rect2,
ground_rect3,
ground_rect4)
def set_pipes(self):
pipe1 = Collider(1202, 452, 83, 80)
# 其余的省略
self.pipe_group = pg.sprite.Group(pipe1, pipe2,
pipe3, pipe4,
pipe5, pipe6)
def set_steps(self):
step1 = Collider(5745, 495, 40, 44)
# 其余的省略
self.step_group = pg.sprite.Group(step1, step2,
step3, step4,
step5, step6,
step7, step8,
step9, step10,
step11, step12,
step13, step14,
step15, step16,
step17, step18,
step19, step20,
step21, step22,
step23, step24,
step25, step26,
step27)
7. 碰撞的檢測和處理
先創建一個方法來對三種精靈對象和Mario的碰撞檢測
def check_collide(self):
self.ground_collide = pg.sprite.spritecollideany(self.mario, self.ground_group)
self.pipe_collide = pg.sprite.spritecollideany(self.mario, self.pipe_group)
self.step_collide = pg.sprite.spritecollideany(self.mario, self.step_group)
然后就是對檢測到的碰撞進行處理
這里的處理過程是比較復雜的,所以分為兩個方向分別處理
# 處理 x 方向上的碰撞
def adjust_x(self):
if self.pipe_collide:
if self.mario.pos.y > self.pipe_collide.rect.y + 10:
if self.mario.vel.x > 0:
self.mario.pos.x -= 5
self.mario.vel.x = 0
if self.mario.vel.x < 0:
self.mario.pos.x = 5
self.mario.vel.x = 0
if self.step_collide:
if self.mario.pos.y > self.step_collide.rect.y + 10:
if self.mario.vel.x > 0:
self.mario.pos.x -= 5
self.mario.vel.x = 0
if self.mario.vel.x < 0:
self.mario.pos.x = 5
self.mario.vel.x = 0
# 處理 y 方向上的碰撞
def adjust_y(self):
if self.ground_collide:
if self.ground_collide.rect.top < self.mario.pos.y:
self.mario.acc.y = 0
self.mario.vel.y = 0
self.mario.pos.y = self.ground_collide.rect.top
self.mario.landing = True
else:
self.mario.landing = False
if self.pipe_collide:
if self.mario.vel.y > 0:
if self.pipe_collide.rect.top < self.mario.pos.y:
self.mario.acc.y = 0
self.mario.vel.y = 0
self.mario.pos.y = self.pipe_collide.rect.top
self.mario.landing = True
if self.step_collide:
if self.mario.vel.y > 0:
if self.step_collide.rect.top < self.mario.pos.y:
self.mario.acc.y = 0
self.mario.vel.y = 0
self.mario.pos.y = self.step_collide.rect.top
self.mario.landing = True
碰撞的處理是十分講究細節的,這里就不過多的贅述,如果沒有處理好就會產生很多奇怪的的東西如
8. 最后
到了這里相信大家已經搭建好了整個游戲的框架和基本邏輯,對于磚塊、金幣、蘑菇和烏龜,還有變大變小和火球效果這邊就不贅述了,接著填入框架里就行了。
有了這些基礎就可以進一步完善自己的超級瑪麗了,你甚至可以對其進行魔改一番,來體驗一下上帝視角的快樂
也可以將其改的十分刁鉆,如之前的 貓里奧 游戲
最后可以用pyinstaller打成exe文件來分享給你的朋友們
9. 代碼
這里我貼一下自己的源代碼,因為很多細節都在之前提到了,這里就不加注釋了
圖片文件我這里貼兩張,還有更多需要可以去Github自取,這里還推薦一個2D游戲的
大神的代碼可以之間去我文章開頭貼的鏈接去自取
main.py
from level import *
from sprites import *
class Game:
def __init__(self):
pg.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
self.rect = self.screen.get_rect()
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.playing = True
self.all_group = pg.sprite.Group()
self.viewpoint = self.rect
def new(self):
self.level_surface = pg.Surface((WIDTH, HEIGHT)).convert()
self.background = load_image('level.png')
self.back_rect = self.background.get_rect()
self.background = pg.transform.scale(self.background,
(int(self.back_rect.width * BACKGROUND_SIZE),
int(self.back_rect.height * BACKGROUND_SIZE))).convert()
self.level = Level()
self.all_group.add(self.level.mario)
def run(self):
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
def update(self):
self.all_group.update()
self.level.update()
if self.level.mario.pos.x < self.viewpoint.x + 15:
self.level.mario.pos.x -= self.level.mario.vel.x
if self.level.mario.vel.x > 0:
if self.level.mario.pos.x > WIDTH * 0.55 + self.viewpoint.x:
self.viewpoint.x += int(self.level.mario.vel.x * 1.1)
if self.level.mario.dead:
self.playing = False
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.playing = False
def draw(self):
pg.display.flip()
self.background_clean = self.background.copy()
self.all_group.draw(self.background_clean)
self.screen.blit(self.background, (0, 0), self.viewpoint)
self.all_group.draw(self.screen)
def show_start_screen(self):
pass
def show_end_screen(self):
pass
game = Game()
game.show_start_screen()
game.new()
game.run()
game.show_end_screen()
sprites.py
import random
from tools import *
from settings import *
vec = pg.math.Vector2
class Mario(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.sheet = load_image('mario.png')
self.load_from_sheet()
self.walking_timer = pg.time.get_ticks()
self.image_index = 4
self.image = self.frames[0]
self.rect = self.image.get_rect()
self.pos = vec(WIDTH * 0.5, GROUND_HEIGHT - 70)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
self.landing = False
self.dead = False
def update(self):
self.acc = vec(0, GRAVITY)
keys = pg.key.get_pressed()
if keys[pg.K_RIGHT]:
self.walk('right')
if self.vel.x > 0:
self.acc.x = TURNAROUND
if self.vel.x <= 0:
self.acc.x = ACC
self.pos.x += 5
elif keys[pg.K_LEFT]:
self.walk('left')
if self.vel.x < 0:
self.acc.x = -TURNAROUND
if self.vel.x >= 0:
self.acc.x = -ACC
else:
self.image_index = 0
if abs(self.vel.x) < MAX_SPEED:
self.vel.x += self.acc.x
elif keys[pg.K_LEFT]:
self.vel.x = -MAX_SPEED
elif keys[pg.K_RIGHT]:
self.vel.x = MAX_SPEED
if keys[pg.K_SPACE]:
if self.landing:
self.vel.y = -JUMP
if not self.landing:
self.image_index = 4
self.image = self.frames[self.image_index]
self.acc.x += self.vel.x * FRICTION
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
self.rect.midbottom = self.pos
def calculate_animation_speed(self):
if self.vel.x == 0:
animation_speed = 130
elif self.vel.x > 0:
animation_speed = 130 - (self.vel.x * 12)
else:
animation_speed = 130 - (self.vel.x * 12 * -1)
return animation_speed
def walk(self, facing):
if self.image_index == 0:
self.image_index += 1
self.walking_timer = pg.time.get_ticks()
else:
if (pg.time.get_ticks() - self.walking_timer >
self.calculate_animation_speed()):
self.image_index += 1
self.walking_timer = pg.time.get_ticks()
if facing == 'right':
if self.image_index > 3:
self.image_index = 0
if facing == 'left':
if self.image_index > 8:
self.image_index = 5
if self.image_index < 5:
self.image_index = 5
def load_from_sheet(self):
self.right_frames = []
self.left_frames = []
self.right_frames.append(
self.get_image(178, 32, 12, 16))
self.right_frames.append(
self.get_image(80, 32, 15, 16))
self.right_frames.append(
self.get_image(96, 32, 16, 16))
self.right_frames.append(
self.get_image(112, 32, 16, 16))
self.right_frames.append(
self.get_image(144, 32, 16, 16))
for frame in self.right_frames:
new_image = pg.transform.flip(frame, True, False)
self.left_frames.append(new_image)
self.frames = self.right_frames + self.left_frames
def get_image(self, x, y, width, height):
image = pg.Surface([width, height])
rect = image.get_rect()
image.blit(self.sheet, (0, 0), (x, y, width, height))
image.set_colorkey(BLACK)
image = pg.transform.scale(image,
(int(rect.width * MARIO_SIZE),
int(rect.height * MARIO_SIZE)))
return image
class Collider(pg.sprite.Sprite):
def __init__(self, x, y, width, height):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((width, height)).convert()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
level.py
from sprites import *
class Level(pg.sprite.Sprite):
def __init__(self):
self.set_mario()
self.set_ground()
self.set_pipes()
self.set_steps()
self.set_group()
def set_group(self):
self.ground_step_pipe_group = pg.sprite.Group(self.ground_group,
self.pipe_group,
self.step_group)
def update(self):
self.check_collide()
self.adjust_x()
self.adjust_y()
self.check_dead()
print(self.mario.pos)
def set_mario(self):
self.mario = Mario()
def set_ground(self):
ground_rect1 = Collider(0, GROUND_HEIGHT, 2953, 60)
ground_rect2 = Collider(3048, GROUND_HEIGHT, 635, 60)
ground_rect3 = Collider(3819, GROUND_HEIGHT, 2735, 60)
ground_rect4 = Collider(6647, GROUND_HEIGHT, 2300, 60)
self.ground_group = pg.sprite.Group(ground_rect1,
ground_rect2,
ground_rect3,
ground_rect4)
def set_pipes(self):
pipe1 = Collider(1202, 452, 83, 80)
pipe2 = Collider(1631, 409, 83, 140)
pipe3 = Collider(1973, 366, 83, 170)
pipe4 = Collider(2445, 366, 83, 170)
pipe5 = Collider(6989, 452, 83, 82)
pipe6 = Collider(7675, 452, 83, 82)
self.pipe_group = pg.sprite.Group(pipe1, pipe2,
pipe3, pipe4,
pipe5, pipe6)
def set_steps(self):
step1 = Collider(5745, 495, 40, 44)
step2 = Collider(5788, 452, 40, 88)
step3 = Collider(5831, 409, 40, 132)
step4 = Collider(5874, 366, 40, 176)
step5 = Collider(6001, 366, 40, 176)
step6 = Collider(6044, 408, 40, 40)
step7 = Collider(6087, 452, 40, 40)
step8 = Collider(6130, 495, 40, 40)
step9 = Collider(6345, 495, 40, 40)
step10 = Collider(6388, 452, 40, 40)
step11 = Collider(6431, 409, 40, 40)
step12 = Collider(6474, 366, 40, 40)
step13 = Collider(6517, 366, 40, 176)
step14 = Collider(6644, 366, 40, 176)
step15 = Collider(6687, 408, 40, 40)
step16 = Collider(6728, 452, 40, 40)
step17 = Collider(6771, 495, 40, 40)
step18 = Collider(7760, 495, 40, 40)
step19 = Collider(7803, 452, 40, 40)
step20 = Collider(7845, 409, 40, 40)
step21 = Collider(7888, 366, 40, 40)
step22 = Collider(7931, 323, 40, 40)
step23 = Collider(7974, 280, 40, 40)
step24 = Collider(8017, 237, 40, 40)
step25 = Collider(8060, 194, 40, 40)
step26 = Collider(8103, 194, 40, 360)
step27 = Collider(8488, 495, 40, 40)
self.step_group = pg.sprite.Group(step1, step2,
step3, step4,
step5, step6,
step7, step8,
step9, step10,
step11, step12,
step13, step14,
step15, step16,
step17, step18,
step19, step20,
step21, step22,
step23, step24,
step25, step26,
step27)
def check_collide(self):
self.ground_collide = pg.sprite.spritecollideany(self.mario, self.ground_group)
self.pipe_collide = pg.sprite.spritecollideany(self.mario, self.pipe_group)
self.step_collide = pg.sprite.spritecollideany(self.mario, self.step_group)
def adjust_x(self):
if self.pipe_collide:
if self.mario.pos.y > self.pipe_collide.rect.y + 10:
if self.mario.vel.x > 0:
self.mario.pos.x -= 5
self.mario.vel.x = 0
if self.mario.vel.x < 0:
self.mario.pos.x = 5
self.mario.vel.x = 0
if self.step_collide:
if self.mario.pos.y > self.step_collide.rect.y + 10:
if self.mario.vel.x > 0:
self.mario.pos.x -= 5
self.mario.vel.x = 0
if self.mario.vel.x < 0:
self.mario.pos.x = 5
self.mario.vel.x = 0
def adjust_y(self):
if self.ground_collide:
if self.ground_collide.rect.top < self.mario.pos.y:
self.mario.acc.y = 0
self.mario.vel.y = 0
self.mario.pos.y = self.ground_collide.rect.top
self.mario.landing = True
else:
self.mario.landing = False
if self.pipe_collide:
if self.mario.vel.y > 0:
if self.pipe_collide.rect.top < self.mario.pos.y:
self.mario.acc.y = 0
self.mario.vel.y = 0
self.mario.pos.y = self.pipe_collide.rect.top
self.mario.landing = True
if self.step_collide:
if self.mario.vel.y > 0:
if self.step_collide.rect.top < self.mario.pos.y:
self.mario.acc.y = 0
self.mario.vel.y = 0
self.mario.pos.y = self.step_collide.rect.top
self.mario.landing = True
def check_dead(self):
if self.mario.pos.y > GROUND_HEIGHT + 50:
self.mario.dead = True
tools.py
import os
import pygame as pg
def load_image(filename):
src = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(src, 'resources', 'graphics', filename)
return pg.image.load(path)
settings.py
# 標題和窗口大小
TITLE = 'Mario'
WIDTH = 800
HEIGHT = 600
?
FPS = 60
?
# 定義顏色
GRAY = (100, 100, 100)
BLACK = (0, 0, 0)
?
# 圖片縮放比例
MARIO_SIZE = 2.5
BACKGROUND_SIZE = 2.679
?
# Mario 運動系數
ACC = 0.3
GRAVITY = 1
FRICTION = -0.12
JUMP = 20
TURNAROUND = 0.7
MAX_SPEED = 6
?
# 地面高度
GROUND_HEIGHT = HEIGHT - 66
總結
以上是生活随笔為你收集整理的python玛丽冒险_超级玛丽的 python 实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成为华尔街金融巨鳄第三课: Pandas
- 下一篇: 我的谷歌音乐播放器简介