python 实现超级玛丽游戏
作者:Mr-han11 发布时间:2023-10-10 09:38:38
标签:游戏,python,超级玛丽
开发需求
python 3.7+
pygame 1.9+
演示
项目地址
https://github.com/Mr-han11/PythonSuperMario-master
主要功能的代码实现
玩家
__author__ = 'marble_xu'
import os
import json
import pygame as pg
from .. import setup, tools
from .. import constants as c
from ..components import powerup
class Player(pg.sprite.Sprite):
def __init__(self, player_name):
pg.sprite.Sprite.__init__(self)
self.player_name = player_name
self.load_data()
self.setup_timer()
self.setup_state()
self.setup_speed()
self.load_images()
if c.DEBUG:
self.right_frames = self.big_fire_frames[0]
self.left_frames = self.big_fire_frames[1]
self.big = True
self.fire = True
self.frame_index = 0
self.state = c.WALK
self.image = self.right_frames[self.frame_index]
self.rect = self.image.get_rect()
def restart(self):
'''restart after player is dead or go to next level'''
if self.dead:
self.dead = False
self.big = False
self.fire = False
self.set_player_image(self.small_normal_frames, 0)
self.right_frames = self.small_normal_frames[0]
self.left_frames = self.small_normal_frames[1]
self.state = c.STAND
def load_data(self):
player_file = str(self.player_name) + '.json'
file_path = os.path.join('source', 'data', 'player', player_file)
f = open(file_path)
self.player_data = json.load(f)
def setup_timer(self):
self.walking_timer = 0
self.death_timer = 0
self.flagpole_timer = 0
self.transition_timer = 0
self.hurt_invincible_timer = 0
self.invincible_timer = 0
self.last_fireball_time = 0
def setup_state(self):
self.facing_right = True
self.allow_jump = True
self.allow_fireball = True
self.dead = False
self.big = False
self.fire = False
self.hurt_invincible = False
self.invincible = False
self.crouching = False
def setup_speed(self):
speed = self.player_data[c.PLAYER_SPEED]
self.x_vel = 0
self.y_vel = 0
self.max_walk_vel = speed[c.MAX_WALK_SPEED]
self.max_run_vel = speed[c.MAX_RUN_SPEED]
self.max_y_vel = speed[c.MAX_Y_VEL]
self.walk_accel = speed[c.WALK_ACCEL]
self.run_accel = speed[c.RUN_ACCEL]
self.jump_vel = speed[c.JUMP_VEL]
self.gravity = c.GRAVITY
self.max_x_vel = self.max_walk_vel
self.x_accel = self.walk_accel
def load_images(self):
sheet = setup.GFX['mario_bros']
frames_list = self.player_data[c.PLAYER_FRAMES]
self.right_frames = []
self.left_frames = []
self.right_small_normal_frames = []
self.left_small_normal_frames = []
self.right_big_normal_frames = []
self.left_big_normal_frames = []
self.right_big_fire_frames = []
self.left_big_fire_frames = []
for name, frames in frames_list.items():
for frame in frames:
image = tools.get_image(sheet, frame['x'], frame['y'],
frame['width'], frame['height'],
c.BLACK, c.SIZE_MULTIPLIER)
left_image = pg.transform.flip(image, True, False)
if name == c.RIGHT_SMALL_NORMAL:
self.right_small_normal_frames.append(image)
self.left_small_normal_frames.append(left_image)
elif name == c.RIGHT_BIG_NORMAL:
self.right_big_normal_frames.append(image)
self.left_big_normal_frames.append(left_image)
elif name == c.RIGHT_BIG_FIRE:
self.right_big_fire_frames.append(image)
self.left_big_fire_frames.append(left_image)
self.small_normal_frames = [self.right_small_normal_frames,
self.left_small_normal_frames]
self.big_normal_frames = [self.right_big_normal_frames,
self.left_big_normal_frames]
self.big_fire_frames = [self.right_big_fire_frames,
self.left_big_fire_frames]
self.all_images = [self.right_small_normal_frames,
self.left_small_normal_frames,
self.right_big_normal_frames,
self.left_big_normal_frames,
self.right_big_fire_frames,
self.left_big_fire_frames]
self.right_frames = self.small_normal_frames[0]
self.left_frames = self.small_normal_frames[1]
def update(self, keys, game_info, fire_group):
self.current_time = game_info[c.CURRENT_TIME]
self.handle_state(keys, fire_group)
self.check_if_hurt_invincible()
self.check_if_invincible()
self.animation()
def handle_state(self, keys, fire_group):
if self.state == c.STAND:
self.standing(keys, fire_group)
elif self.state == c.WALK:
self.walking(keys, fire_group)
elif self.state == c.JUMP:
self.jumping(keys, fire_group)
elif self.state == c.FALL:
self.falling(keys, fire_group)
elif self.state == c.DEATH_JUMP:
self.jumping_to_death()
elif self.state == c.FLAGPOLE:
self.flag_pole_sliding()
elif self.state == c.WALK_AUTO:
self.walking_auto()
elif self.state == c.END_OF_LEVEL_FALL:
self.y_vel += self.gravity
elif self.state == c.IN_CASTLE:
self.frame_index = 0
elif self.state == c.SMALL_TO_BIG:
self.changing_to_big()
elif self.state == c.BIG_TO_SMALL:
self.changing_to_small()
elif self.state == c.BIG_TO_FIRE:
self.changing_to_fire()
elif self.state == c.DOWN_TO_PIPE:
self.y_vel = 1
self.rect.y += self.y_vel
elif self.state == c.UP_OUT_PIPE:
self.y_vel = -1
self.rect.y += self.y_vel
if self.rect.bottom < self.up_pipe_y:
self.state = c.STAND
def check_to_allow_jump(self, keys):
if not keys[tools.keybinding['jump']]:
self.allow_jump = True
def check_to_allow_fireball(self, keys):
if not keys[tools.keybinding['action']]:
self.allow_fireball = True
def standing(self, keys, fire_group):
self.check_to_allow_jump(keys)
self.check_to_allow_fireball(keys)
self.frame_index = 0
self.x_vel = 0
self.y_vel = 0
if keys[tools.keybinding['action']]:
if self.fire and self.allow_fireball:
self.shoot_fireball(fire_group)
if keys[tools.keybinding['down']]:
self.update_crouch_or_not(True)
if keys[tools.keybinding['left']]:
self.facing_right = False
self.update_crouch_or_not()
self.state = c.WALK
elif keys[tools.keybinding['right']]:
self.facing_right = True
self.update_crouch_or_not()
self.state = c.WALK
elif keys[tools.keybinding['jump']]:
if self.allow_jump:
self.state = c.JUMP
self.y_vel = self.jump_vel
if not keys[tools.keybinding['down']]:
self.update_crouch_or_not()
def update_crouch_or_not(self, isDown=False):
if not self.big:
self.crouching = True if isDown else False
return
if not isDown and not self.crouching:
return
self.crouching = True if isDown else False
frame_index = 7 if isDown else 0
bottom = self.rect.bottom
left = self.rect.x
if self.facing_right:
self.image = self.right_frames[frame_index]
else:
self.image = self.left_frames[frame_index]
self.rect = self.image.get_rect()
self.rect.bottom = bottom
self.rect.x = left
self.frame_index = frame_index
def walking(self, keys, fire_group):
self.check_to_allow_jump(keys)
self.check_to_allow_fireball(keys)
if self.frame_index == 0:
self.frame_index += 1
self.walking_timer = self.current_time
elif (self.current_time - self.walking_timer >
self.calculate_animation_speed()):
if self.frame_index < 3:
self.frame_index += 1
else:
self.frame_index = 1
self.walking_timer = self.current_time
if keys[tools.keybinding['action']]:
self.max_x_vel = self.max_run_vel
self.x_accel = self.run_accel
if self.fire and self.allow_fireball:
self.shoot_fireball(fire_group)
else:
self.max_x_vel = self.max_walk_vel
self.x_accel = self.walk_accel
if keys[tools.keybinding['jump']]:
if self.allow_jump:
self.state = c.JUMP
if abs(self.x_vel) > 4:
self.y_vel = self.jump_vel - .5
else:
self.y_vel = self.jump_vel
if keys[tools.keybinding['left']]:
self.facing_right = False
if self.x_vel > 0:
self.frame_index = 5
self.x_accel = c.SMALL_TURNAROUND
self.x_vel = self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel, True)
elif keys[tools.keybinding['right']]:
self.facing_right = True
if self.x_vel < 0:
self.frame_index = 5
self.x_accel = c.SMALL_TURNAROUND
self.x_vel = self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel)
else:
if self.facing_right:
if self.x_vel > 0:
self.x_vel -= self.x_accel
else:
self.x_vel = 0
self.state = c.STAND
else:
if self.x_vel < 0:
self.x_vel += self.x_accel
else:
self.x_vel = 0
self.state = c.STAND
def jumping(self, keys, fire_group):
""" y_vel value: positive is down, negative is up """
self.check_to_allow_fireball(keys)
self.allow_jump = False
self.frame_index = 4
self.gravity = c.JUMP_GRAVITY
self.y_vel += self.gravity
if self.y_vel >= 0 and self.y_vel < self.max_y_vel:
self.gravity = c.GRAVITY
self.state = c.FALL
if keys[tools.keybinding['right']]:
self.x_vel = self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel)
elif keys[tools.keybinding['left']]:
self.x_vel = self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel, True)
if not keys[tools.keybinding['jump']]:
self.gravity = c.GRAVITY
self.state = c.FALL
if keys[tools.keybinding['action']]:
if self.fire and self.allow_fireball:
self.shoot_fireball(fire_group)
def falling(self, keys, fire_group):
self.check_to_allow_fireball(keys)
self.y_vel = self.cal_vel(self.y_vel, self.max_y_vel, self.gravity)
if keys[tools.keybinding['right']]:
self.x_vel = self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel)
elif keys[tools.keybinding['left']]:
self.x_vel = self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel, True)
if keys[tools.keybinding['action']]:
if self.fire and self.allow_fireball:
self.shoot_fireball(fire_group)
def jumping_to_death(self):
if self.death_timer == 0:
self.death_timer = self.current_time
elif (self.current_time - self.death_timer) > 500:
self.rect.y += self.y_vel
self.y_vel += self.gravity
def cal_vel(self, vel, max_vel, accel, isNegative=False):
""" max_vel and accel must > 0 """
if isNegative:
new_vel = vel * -1
else:
new_vel = vel
if (new_vel + accel) < max_vel:
new_vel += accel
else:
new_vel = max_vel
if isNegative:
return new_vel * -1
else:
return new_vel
def calculate_animation_speed(self):
if self.x_vel == 0:
animation_speed = 130
elif self.x_vel > 0:
animation_speed = 130 - (self.x_vel * 13)
else:
animation_speed = 130 - (self.x_vel * 13 * -1)
return animation_speed
def shoot_fireball(self, powerup_group):
if (self.current_time - self.last_fireball_time) > 500:
self.allow_fireball = False
powerup_group.add(powerup.FireBall(self.rect.right,
self.rect.y, self.facing_right))
self.last_fireball_time = self.current_time
self.frame_index = 6
def flag_pole_sliding(self):
self.state = c.FLAGPOLE
self.x_vel = 0
self.y_vel = 5
if self.flagpole_timer == 0:
self.flagpole_timer = self.current_time
elif self.rect.bottom < 493:
if (self.current_time - self.flagpole_timer) < 65:
self.frame_index = 9
elif (self.current_time - self.flagpole_timer) < 130:
self.frame_index = 10
else:
self.flagpole_timer = self.current_time
elif self.rect.bottom >= 493:
self.frame_index = 10
def walking_auto(self):
self.max_x_vel = 5
self.x_accel = self.walk_accel
self.x_vel = self.cal_vel(self.x_vel, self.max_x_vel, self.x_accel)
if (self.walking_timer == 0 or (self.current_time - self.walking_timer) > 200):
self.walking_timer = self.current_time
elif (self.current_time - self.walking_timer >
self.calculate_animation_speed()):
if self.frame_index < 3:
self.frame_index += 1
else:
self.frame_index = 1
self.walking_timer = self.current_time
def changing_to_big(self):
timer_list = [135, 200, 365, 430, 495, 560, 625, 690, 755, 820, 885]
# size value 0:small, 1:middle, 2:big
size_list = [1, 0, 1, 0, 1, 2, 0, 1, 2, 0, 2]
frames = [(self.small_normal_frames, 0), (self.small_normal_frames, 7),
(self.big_normal_frames, 0)]
if self.transition_timer == 0:
self.big = True
self.change_index = 0
self.transition_timer = self.current_time
elif (self.current_time - self.transition_timer) > timer_list[self.change_index]:
if (self.change_index + 1) >= len(timer_list):
# player becomes big
self.transition_timer = 0
self.set_player_image(self.big_normal_frames, 0)
self.state = c.WALK
self.right_frames = self.right_big_normal_frames
self.left_frames = self.left_big_normal_frames
else:
frame, frame_index = frames[size_list[self.change_index]]
self.set_player_image(frame, frame_index)
self.change_index += 1
def changing_to_small(self):
timer_list = [265, 330, 395, 460, 525, 590, 655, 720, 785, 850, 915]
# size value 0:big, 1:middle, 2:small
size_list = [0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
frames = [(self.big_normal_frames, 4), (self.big_normal_frames, 8),
(self.small_normal_frames, 8)]
if self.transition_timer == 0:
self.change_index = 0
self.transition_timer = self.current_time
elif (self.current_time - self.transition_timer) > timer_list[self.change_index]:
if (self.change_index + 1) >= len(timer_list):
# player becomes small
self.transition_timer = 0
self.set_player_image(self.small_normal_frames, 0)
self.state = c.WALK
self.big = False
self.fire = False
self.hurt_invincible = True
self.right_frames = self.right_small_normal_frames
self.left_frames = self.left_small_normal_frames
else:
frame, frame_index = frames[size_list[self.change_index]]
self.set_player_image(frame, frame_index)
self.change_index += 1
def changing_to_fire(self):
timer_list = [65, 195, 260, 325, 390, 455, 520, 585, 650, 715, 780, 845, 910, 975]
# size value 0:fire, 1:big green, 2:big red, 3:big black
size_list = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1]
frames = [(self.big_fire_frames, 3), (self.big_normal_frames, 3),
(self.big_fire_frames, 3), (self.big_normal_frames, 3)]
if self.transition_timer == 0:
self.change_index = 0
self.transition_timer = self.current_time
elif (self.current_time - self.transition_timer) > timer_list[self.change_index]:
if (self.change_index + 1) >= len(timer_list):
# player becomes fire
self.transition_timer = 0
self.set_player_image(self.big_fire_frames, 3)
self.fire = True
self.state = c.WALK
self.right_frames = self.right_big_fire_frames
self.left_frames = self.left_big_fire_frames
else:
frame, frame_index = frames[size_list[self.change_index]]
self.set_player_image(frame, frame_index)
self.change_index += 1
def set_player_image(self, frames, frame_index):
self.frame_index = frame_index
if self.facing_right:
self.right_frames = frames[0]
self.image = frames[0][frame_index]
else:
self.left_frames = frames[1]
self.image = frames[1][frame_index]
bottom = self.rect.bottom
centerx = self.rect.centerx
self.rect = self.image.get_rect()
self.rect.bottom = bottom
self.rect.centerx = centerx
def check_if_hurt_invincible(self):
if self.hurt_invincible:
if self.hurt_invincible_timer == 0:
self.hurt_invincible_timer = self.current_time
self.hurt_invincible_timer2 = self.current_time
elif (self.current_time - self.hurt_invincible_timer) < 2000:
if (self.current_time - self.hurt_invincible_timer2) < 35:
self.image.set_alpha(0)
elif (self.current_time - self.hurt_invincible_timer2) < 70:
self.image.set_alpha(255)
self.hurt_invincible_timer2 = self.current_time
else:
self.hurt_invincible = False
self.hurt_invincible_timer = 0
for frames in self.all_images:
for image in frames:
image.set_alpha(255)
def check_if_invincible(self):
if self.invincible:
if self.invincible_timer == 0:
self.invincible_timer = self.current_time
self.invincible_timer2 = self.current_time
elif (self.current_time - self.invincible_timer) < 10000:
if (self.current_time - self.invincible_timer2) < 35:
self.image.set_alpha(0)
elif (self.current_time - self.invincible_timer2) < 70:
self.image.set_alpha(255)
self.invincible_timer2 = self.current_time
elif (self.current_time - self.invincible_timer) < 12000:
if (self.current_time - self.invincible_timer2) < 100:
self.image.set_alpha(0)
elif (self.current_time - self.invincible_timer2) < 200:
self.image.set_alpha(255)
self.invincible_timer2 = self.current_time
else:
self.invincible = False
self.invincible_timer = 0
for frames in self.all_images:
for image in frames:
image.set_alpha(255)
def animation(self):
if self.facing_right:
self.image = self.right_frames[self.frame_index]
else:
self.image = self.left_frames[self.frame_index]
def start_death_jump(self, game_info):
self.dead = True
self.y_vel = -11
self.gravity = .5
self.frame_index = 6
self.state = c.DEATH_JUMP
敌人
__author__ = 'marble_xu'
import math
import pygame as pg
from .. import setup, tools
from .. import constants as c
ENEMY_SPEED = 1
def create_enemy(item, level):
dir = c.LEFT if item['direction'] == 0 else c.RIGHT
color = item[c.COLOR]
if c.ENEMY_RANGE in item:
in_range = item[c.ENEMY_RANGE]
range_start = item['range_start']
range_end = item['range_end']
else:
in_range = False
range_start = range_end = 0
if item['type'] == c.ENEMY_TYPE_GOOMBA:
sprite = Goomba(item['x'], item['y'], dir, color,
in_range, range_start, range_end)
elif item['type'] == c.ENEMY_TYPE_KOOPA:
sprite = Koopa(item['x'], item['y'], dir, color,
in_range, range_start, range_end)
elif item['type'] == c.ENEMY_TYPE_FLY_KOOPA:
isVertical = False if item['is_vertical'] == 0 else True
sprite = FlyKoopa(item['x'], item['y'], dir, color,
in_range, range_start, range_end, isVertical)
elif item['type'] == c.ENEMY_TYPE_PIRANHA:
sprite = Piranha(item['x'], item['y'], dir, color,
in_range, range_start, range_end)
elif item['type'] == c.ENEMY_TYPE_FIRE_KOOPA:
sprite = FireKoopa(item['x'], item['y'], dir, color,
in_range, range_start, range_end, level)
elif item['type'] == c.ENEMY_TYPE_FIRESTICK:
'''use a number of fireballs to stimulate a firestick'''
sprite = []
num = item['num']
center_x, center_y = item['x'], item['y']
for i in range(num):
radius = i * 21 # 8 * 2.69 = 21
sprite.append(FireStick(center_x, center_y, dir, color,
radius))
return sprite
class Enemy(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
def setup_enemy(self, x, y, direction, name, sheet, frame_rect_list,
in_range, range_start, range_end, isVertical=False):
self.frames = []
self.frame_index = 0
self.animate_timer = 0
self.gravity = 1.5
self.state = c.WALK
self.name = name
self.direction = direction
self.load_frames(sheet, frame_rect_list)
self.image = self.frames[self.frame_index]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.bottom = y
self.in_range = in_range
self.range_start = range_start
self.range_end = range_end
self.isVertical = isVertical
self.set_velocity()
self.death_timer = 0
def load_frames(self, sheet, frame_rect_list):
for frame_rect in frame_rect_list:
self.frames.append(tools.get_image(sheet, *frame_rect,
c.BLACK, c.SIZE_MULTIPLIER))
def set_velocity(self):
if self.isVertical:
self.x_vel = 0
self.y_vel = ENEMY_SPEED
else:
self.x_vel = ENEMY_SPEED *-1 if self.direction == c.LEFT else ENEMY_SPEED
self.y_vel = 0
def update(self, game_info, level):
self.current_time = game_info[c.CURRENT_TIME]
self.handle_state()
self.animation()
self.update_position(level)
def handle_state(self):
if (self.state == c.WALK or
self.state == c.FLY):
self.walking()
elif self.state == c.FALL:
self.falling()
elif self.state == c.JUMPED_ON:
self.jumped_on()
elif self.state == c.DEATH_JUMP:
self.death_jumping()
elif self.state == c.SHELL_SLIDE:
self.shell_sliding()
elif self.state == c.REVEAL:
self.revealing()
def walking(self):
if (self.current_time - self.animate_timer) > 125:
if self.direction == c.RIGHT:
if self.frame_index == 4:
self.frame_index += 1
elif self.frame_index == 5:
self.frame_index = 4
else:
if self.frame_index == 0:
self.frame_index += 1
elif self.frame_index == 1:
self.frame_index = 0
self.animate_timer = self.current_time
def falling(self):
if self.y_vel < 10:
self.y_vel += self.gravity
def jumped_on(self):
pass
def death_jumping(self):
self.rect.y += self.y_vel
self.rect.x += self.x_vel
self.y_vel += self.gravity
if self.rect.y > c.SCREEN_HEIGHT:
self.kill()
def shell_sliding(self):
if self.direction == c.RIGHT:
self.x_vel = 10
else:
self.x_vel = -10
def revealing(self):
pass
def start_death_jump(self, direction):
self.y_vel = -8
self.x_vel = 2 if direction == c.RIGHT else -2
self.gravity = .5
self.frame_index = 3
self.state = c.DEATH_JUMP
def animation(self):
self.image = self.frames[self.frame_index]
def update_position(self, level):
self.rect.x += self.x_vel
self.check_x_collisions(level)
if self.in_range and self.isVertical:
if self.rect.y < self.range_start:
self.rect.y = self.range_start
self.y_vel = ENEMY_SPEED
elif self.rect.bottom > self.range_end:
self.rect.bottom = self.range_end
self.y_vel = -1 * ENEMY_SPEED
self.rect.y += self.y_vel
if (self.state != c.DEATH_JUMP and
self.state != c.FLY):
self.check_y_collisions(level)
if self.rect.x <= 0:
self.kill()
elif self.rect.y > (level.viewport.bottom):
self.kill()
def check_x_collisions(self, level):
if self.in_range and not self.isVertical:
if self.rect.x < self.range_start:
self.rect.x = self.range_start
self.change_direction(c.RIGHT)
elif self.rect.right > self.range_end:
self.rect.right = self.range_end
self.change_direction(c.LEFT)
else:
collider = pg.sprite.spritecollideany(self, level.ground_step_pipe_group)
if collider:
if self.direction == c.RIGHT:
self.rect.right = collider.rect.left
self.change_direction(c.LEFT)
elif self.direction == c.LEFT:
self.rect.left = collider.rect.right
self.change_direction(c.RIGHT)
if self.state == c.SHELL_SLIDE:
enemy = pg.sprite.spritecollideany(self, level.enemy_group)
if enemy:
level.update_score(100, enemy, 0)
level.move_to_dying_group(level.enemy_group, enemy)
enemy.start_death_jump(self.direction)
def change_direction(self, direction):
self.direction = direction
if self.direction == c.RIGHT:
self.x_vel = ENEMY_SPEED
if self.state == c.WALK or self.state == c.FLY:
self.frame_index = 4
else:
self.x_vel = ENEMY_SPEED * -1
if self.state == c.WALK or self.state == c.FLY:
self.frame_index = 0
def check_y_collisions(self, level):
# decrease runtime delay: when enemey is on the ground, don't check brick and box
if self.rect.bottom >= c.GROUND_HEIGHT:
sprite_group = level.ground_step_pipe_group
else:
sprite_group = pg.sprite.Group(level.ground_step_pipe_group,
level.brick_group, level.box_group)
sprite = pg.sprite.spritecollideany(self, sprite_group)
if sprite and sprite.name != c.MAP_SLIDER:
if self.rect.top <= sprite.rect.top:
self.rect.bottom = sprite.rect.y
self.y_vel = 0
self.state = c.WALK
level.check_is_falling(self)
class Goomba(Enemy):
def __init__(self, x, y, direction, color, in_range,
range_start, range_end, name=c.GOOMBA):
Enemy.__init__(self)
frame_rect_list = self.get_frame_rect(color)
self.setup_enemy(x, y, direction, name, setup.GFX[c.ENEMY_SHEET],
frame_rect_list, in_range, range_start, range_end)
# dead jump image
self.frames.append(pg.transform.flip(self.frames[2], False, True))
# right walk images
self.frames.append(pg.transform.flip(self.frames[0], True, False))
self.frames.append(pg.transform.flip(self.frames[1], True, False))
def get_frame_rect(self, color):
if color == c.COLOR_TYPE_GREEN:
frame_rect_list = [(0, 34, 16, 16), (30, 34, 16, 16),
(61, 30, 16, 16)]
else:
frame_rect_list = [(0, 4, 16, 16), (30, 4, 16, 16),
(61, 0, 16, 16)]
return frame_rect_list
def jumped_on(self):
self.x_vel = 0
self.frame_index = 2
if self.death_timer == 0:
self.death_timer = self.current_time
elif (self.current_time - self.death_timer) > 500:
self.kill()
class Koopa(Enemy):
def __init__(self, x, y, direction, color, in_range,
range_start, range_end, name=c.KOOPA):
Enemy.__init__(self)
frame_rect_list = self.get_frame_rect(color)
self.setup_enemy(x, y, direction, name, setup.GFX[c.ENEMY_SHEET],
frame_rect_list, in_range, range_start, range_end)
# dead jump image
self.frames.append(pg.transform.flip(self.frames[2], False, True))
# right walk images
self.frames.append(pg.transform.flip(self.frames[0], True, False))
self.frames.append(pg.transform.flip(self.frames[1], True, False))
def get_frame_rect(self, color):
if color == c.COLOR_TYPE_GREEN:
frame_rect_list = [(150, 0, 16, 24), (180, 0, 16, 24),
(360, 5, 16, 15)]
elif color == c.COLOR_TYPE_RED:
frame_rect_list = [(150, 30, 16, 24), (180, 30, 16, 24),
(360, 35, 16, 15)]
else:
frame_rect_list = [(150, 60, 16, 24), (180, 60, 16, 24),
(360, 65, 16, 15)]
return frame_rect_list
def jumped_on(self):
self.x_vel = 0
self.frame_index = 2
x = self.rect.x
bottom = self.rect.bottom
self.rect = self.frames[self.frame_index].get_rect()
self.rect.x = x
self.rect.bottom = bottom
self.in_range = False
class FlyKoopa(Enemy):
def __init__(self, x, y, direction, color, in_range,
range_start, range_end, isVertical, name=c.FLY_KOOPA):
Enemy.__init__(self)
frame_rect_list = self.get_frame_rect(color)
self.setup_enemy(x, y, direction, name, setup.GFX[c.ENEMY_SHEET],
frame_rect_list, in_range, range_start, range_end, isVertical)
# dead jump image
self.frames.append(pg.transform.flip(self.frames[2], False, True))
# right walk images
self.frames.append(pg.transform.flip(self.frames[0], True, False))
self.frames.append(pg.transform.flip(self.frames[1], True, False))
self.state = c.FLY
def get_frame_rect(self, color):
if color == c.COLOR_TYPE_GREEN:
frame_rect_list = [(90, 0, 16, 24), (120, 0, 16, 24),
(330, 5, 16, 15)]
else:
frame_rect_list = [(90, 30, 16, 24), (120, 30, 16, 24),
(330, 35, 16, 15)]
return frame_rect_list
def jumped_on(self):
self.x_vel = 0
self.frame_index = 2
x = self.rect.x
bottom = self.rect.bottom
self.rect = self.frames[self.frame_index].get_rect()
self.rect.x = x
self.rect.bottom = bottom
self.in_range = False
self.isVertical = False
class FireKoopa(Enemy):
def __init__(self, x, y, direction, color, in_range,
range_start, range_end, level, name=c.FIRE_KOOPA):
Enemy.__init__(self)
frame_rect_list = [(2, 210, 32, 32), (42, 210, 32, 32),
(82, 210, 32, 32), (122, 210, 32, 32)]
self.setup_enemy(x, y, direction, name, setup.GFX[c.ENEMY_SHEET],
frame_rect_list, in_range, range_start, range_end)
# right walk images
self.frames.append(pg.transform.flip(self.frames[0], True, False))
self.frames.append(pg.transform.flip(self.frames[1], True, False))
self.frames.append(pg.transform.flip(self.frames[2], True, False))
self.frames.append(pg.transform.flip(self.frames[3], True, False))
self.x_vel = 0
self.gravity = 0.3
self.level = level
self.fire_timer = 0
self.jump_timer = 0
def load_frames(self, sheet, frame_rect_list):
for frame_rect in frame_rect_list:
self.frames.append(tools.get_image(sheet, *frame_rect,
c.BLACK, c.BRICK_SIZE_MULTIPLIER))
def walking(self):
if (self.current_time - self.animate_timer) > 250:
if self.direction == c.RIGHT:
self.frame_index += 1
if self.frame_index > 7:
self.frame_index = 4
else:
self.frame_index += 1
if self.frame_index > 3:
self.frame_index = 0
self.animate_timer = self.current_time
self.shoot_fire()
if self.should_jump():
self.y_vel = -7
def falling(self):
if self.y_vel < 7:
self.y_vel += self.gravity
self.shoot_fire()
def should_jump(self):
if (self.rect.x - self.level.player.rect.x) < 400:
if (self.current_time - self.jump_timer) > 2500:
self.jump_timer = self.current_time
return True
return False
def shoot_fire(self):
if (self.current_time - self.fire_timer) > 3000:
self.fire_timer = self.current_time
self.level.enemy_group.add(Fire(self.rect.x, self.rect.bottom-20, self.direction))
class Fire(Enemy):
def __init__(self, x, y, direction, name=c.FIRE):
Enemy.__init__(self)
frame_rect_list = [(101, 253, 23, 8), (131, 253, 23, 8)]
in_range, range_start, range_end = False, 0, 0
self.setup_enemy(x, y, direction, name, setup.GFX[c.ENEMY_SHEET],
frame_rect_list, in_range, range_start, range_end)
# right images
self.frames.append(pg.transform.flip(self.frames[0], True, False))
self.frames.append(pg.transform.flip(self.frames[1], True, False))
self.state = c.FLY
self.x_vel = 5 if self.direction == c.RIGHT else -5
def check_x_collisions(self, level):
sprite_group = pg.sprite.Group(level.ground_step_pipe_group,
level.brick_group, level.box_group)
sprite = pg.sprite.spritecollideany(self, sprite_group)
if sprite:
self.kill()
def start_death_jump(self, direction):
self.kill()
class Piranha(Enemy):
def __init__(self, x, y, direction, color, in_range,
range_start, range_end, name=c.PIRANHA):
Enemy.__init__(self)
frame_rect_list = self.get_frame_rect(color)
self.setup_enemy(x, y, direction, name, setup.GFX[c.ENEMY_SHEET],
frame_rect_list, in_range, range_start, range_end)
self.state = c.REVEAL
self.y_vel = 1
self.wait_timer = 0
self.group = pg.sprite.Group()
self.group.add(self)
def get_frame_rect(self, color):
if color == c.COLOR_TYPE_GREEN:
frame_rect_list = [(390, 30, 16, 24), (420, 30, 16, 24)]
else:
frame_rect_list = [(390, 60, 16, 24), (420, 60, 16, 24)]
return frame_rect_list
def revealing(self):
if (self.current_time - self.animate_timer) > 250:
if self.frame_index == 0:
self.frame_index += 1
elif self.frame_index == 1:
self.frame_index = 0
self.animate_timer = self.current_time
def update_position(self, level):
if self.check_player_is_on(level):
pass
else:
if self.rect.y < self.range_start:
self.rect.y = self.range_start
self.y_vel = 1
elif self.rect.bottom > self.range_end:
if self.wait_timer == 0:
self.wait_timer = self.current_time
elif (self.current_time - self.wait_timer) < 3000:
return
else:
self.wait_timer = 0
self.rect.bottom = self.range_end
self.y_vel = -1
self.rect.y += self.y_vel
def check_player_is_on(self, level):
result = False
self.rect.y -= 5
sprite = pg.sprite.spritecollideany(level.player, self.group)
if sprite:
result = True
self.rect.y += 5
return result
def start_death_jump(self, direction):
self.kill()
class FireStick(pg.sprite.Sprite):
def __init__(self, center_x, center_y, direction, color, radius, name=c.FIRESTICK):
'''the firestick will rotate around the center of a circle'''
pg.sprite.Sprite.__init__(self)
self.frames = []
self.frame_index = 0
self.animate_timer = 0
self.name = name
rect_list = [(96, 144, 8, 8), (104, 144, 8, 8),
(96, 152, 8, 8), (104, 152, 8, 8)]
self.load_frames(setup.GFX[c.ITEM_SHEET], rect_list)
self.animate_timer = 0
self.image = self.frames[self.frame_index]
self.rect = self.image.get_rect()
self.rect.x = center_x - radius
self.rect.y = center_y
self.center_x = center_x
self.center_y = center_y
self.radius = radius
self.angle = 0
def load_frames(self, sheet, frame_rect_list):
for frame_rect in frame_rect_list:
self.frames.append(tools.get_image(sheet, *frame_rect,
c.BLACK, c.BRICK_SIZE_MULTIPLIER))
def update(self, game_info, level):
self.current_time = game_info[c.CURRENT_TIME]
if (self.current_time - self.animate_timer) > 100:
if self.frame_index < 3:
self.frame_index += 1
else:
self.frame_index = 0
self.animate_timer = self.current_time
self.image = self.frames[self.frame_index]
self.angle += 1
if self.angle == 360:
self.angle = 0
radian = math.radians(self.angle)
self.rect.x = self.center_x + math.sin(radian) * self.radius
self.rect.y = self.center_y + math.cos(radian) * self.radius
来源:https://github.com/Mr-han11/PythonSuperMario-master/tree/master/PythonSuperMario-master
0
投稿
猜你喜欢
- 1. 场景大家好,我是J哥。前段时间有人私信我,说自己辛辛苦苦剪辑的短视频,上传到某平台后,由于播放量太大,收到 降权 的通知,直接导致这个
- Delphi连接MySQL真麻烦,研究了一天,从网上找了无数文章,下载了无数插件都没解决。最后返璞归真,老老实实用ADO来连接,发现也不是很
- 什么是数据库镜像?Robidoux:数据库镜像是将数据库事务处理从一个SQL Server数据库移动到不同SQL Server环境中的另一个
- MySQL字符集多种多样,下面为列举了其中三种最常见的字符集查看方法,该方法供您参考,希望对学习MySQL数据库能有所启迪。一、查看MySQ
- 如下图所示:单击Edit Code打开Code信息如下:经查Data at the root level is invalid是XML文件的
- 想必大家都知道MSSQL中SA权限是什么,可以说是至高无上。今天我就它的危害再谈点儿,我所讲的是配合NBSI上传功能得到WebShell。在
- 1.线性与非线性回归线性回归 Linear Regression:两个变量之间的关系是一次函数关系的—&mdas
- 一般打印就用window.print();就OK了 但是一般都是选择性打印所以会调用方法: function preview() { bdh
- 前言在我们实际开发中,经常需要将一组数据存储起来,以便使用。如果学习了其他的语言可能知道数组(Array)这个数据结构,它就可以将多个数据进
- 1. 导入包我们这次的任务是随机生成一些离散的点,然后用直线(y = w *x + b )去拟合首先看一下我们需要导入的包有torch 包为
- 作为课代表,经常要做的两件事是:帮忙发作业和帮忙收作业,而且很多时候是通过邮件来完成的,如果手动一封一封的收取和发送就很浪费时间——人生苦短
- 前言今天在开发时发现一个奇怪的问题,我手动改完数据库竟然不生效,反复确认环境无误后猜测是缓存的问题,因为是新接手的项目,代码还不熟悉,仔细一
- 比较简单的一个页面,类似csdn论坛在ns下的左边列表 描述: 1. 数据名:tree.mdb 表名:tree 表结构:id(自编)&nbs
- 来由:最近的工作一直是学校设计教程的开发,都是自己根据理论知识加一些实际工作经验相结合写的教程,所以不会咬文嚼字,文笔也不一定非常专业和流畅
- 本文实例讲述了php将textarea数据提交到mysql出现很多空格的解决方法。分享给大家供大家参考。具体分析如下:有一些朋友可能会发现我
- 很多时候我们写的程序,会花上一分钟甚至几分钟时间。为了使软件使用者能够耐心的等待程序的执行,我们经常会希望有一个进度条来表示程序执行的状态。
- 2。date_default_timezone_set("PRC"); 3。PHP&
- 一、get//get请求function getUrl($url, $header = []){ $ch = cu
- 前言在写 python 程序的时候,经常会用到引入其他文件夹里的 py 文件,要是都在同目录下直接 import 就好了,可是有的不在同一个
- BeautifulSoup简介Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:Beautif