""" 带上下左右和斜移动平台演示。 加载一张csv地图,它是用Tiled程序制作的。 本程序需要Arcade街机游戏模块支持,目前最新版本是2.00b4,(2019/2/28) 可在命令提示符下用户 pip install arcade==2.0.0b4安装,安装后在IDLE中用import arcade 如果提示缺少ffmpeg,则用pip继续安装它即可。以下代码来自官网,注释翻译与改编为lixingqiu """ import arcade import os SPRITE_SCALING = 0.5 SCREEN_WIDTH = 1000 SCREEN_HEIGHT = 600 SCREEN_TITLE = "带上下左右和斜移动平台演示,lixingqiu译" SPRITE_PIXEL_SIZE = 128 GRID_PIXEL_SIZE = (SPRITE_PIXEL_SIZE * SPRITE_SCALING) # 视口边距 VIEWPORT_MARGIN = SPRITE_PIXEL_SIZE * SPRITE_SCALING RIGHT_MARGIN = 4 * SPRITE_PIXEL_SIZE * SPRITE_SCALING # 物理常数设定 MOVEMENT_SPEED = 10 * SPRITE_SCALING JUMP_SPEED = 28 * SPRITE_SCALING GRAVITY = .9 * SPRITE_SCALING def get_map(): """加载逗号隔开的csv地图,返回二维数字表""" map_file = open("map.csv") map_array = [] for line in map_file: line = line.strip() map_row = line.split(",") for index, item in enumerate(map_row): map_row[index] = int(item) map_array.append(map_row) return map_array class MyGame(arcade.Window): """ 主要应用程序类,继承自窗口类 """ def __init__(self, width, height, title): """ 初始化方法,这里定义了一些变量。 """ super().__init__(width, height, title) # 定义一些列表 self.all_sprites_list = None self.all_wall_list = None self.static_wall_list = None self.moving_wall_list = None self.player_list = None self.coin_list = None # 给玩家角色定义一些变量 self.player_sprite = None self.physics_engine = None self.view_left = 0 self.view_bottom = 0 self.game_over = False def setup(self): """ 设置游戏,实例化一些变量. """ # 角色列表实例化 self.all_sprites_list = arcade.SpriteList() self.all_wall_list = arcade.SpriteList() self.static_wall_list = arcade.SpriteList() self.moving_wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() # 实例化玩家角色 self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING) self.player_sprite.center_x = 2 * GRID_PIXEL_SIZE self.player_sprite.center_y = 3 * GRID_PIXEL_SIZE self.player_list.append(self.player_sprite) map_array = get_map() # 地图像素长度 self.end_of_map = len(map_array[0]) * GRID_PIXEL_SIZE # 根据csv里的数字决定实例化的墙块的类型 for row_index, row in enumerate(map_array): for column_index, item in enumerate(row): if item == -1: continue elif item == 0: wall = arcade.Sprite("images/boxCrate_double.png", SPRITE_SCALING) elif item == 1: wall = arcade.Sprite("images/grassLeft.png", SPRITE_SCALING) elif item == 2: wall = arcade.Sprite("images/grassMid.png", SPRITE_SCALING) elif item == 3: wall = arcade.Sprite("images/grassRight.png", SPRITE_SCALING) wall.left = column_index * GRID_PIXEL_SIZE wall.top = (7 - row_index) * GRID_PIXEL_SIZE self.all_sprites_list.append(wall) self.all_wall_list.append(wall) self.static_wall_list.append(wall) # 创建左右移动的平台 wall = arcade.Sprite("images/grassMid.png", SPRITE_SCALING) wall.center_y = 3 * GRID_PIXEL_SIZE wall.center_x = 3 * GRID_PIXEL_SIZE wall.boundary_left = 2 * GRID_PIXEL_SIZE wall.boundary_right = 5 * GRID_PIXEL_SIZE wall.change_x = 2 * SPRITE_SCALING self.all_sprites_list.append(wall) self.all_wall_list.append(wall) self.moving_wall_list.append(wall) # C建左右移动的平台 wall = arcade.Sprite("images/grassMid.png", SPRITE_SCALING) wall.center_y = 3 * GRID_PIXEL_SIZE wall.center_x = 7 * GRID_PIXEL_SIZE wall.boundary_left = 5 * GRID_PIXEL_SIZE wall.boundary_right = 9 * GRID_PIXEL_SIZE wall.change_x = -2 * SPRITE_SCALING self.all_sprites_list.append(wall) self.all_wall_list.append(wall) self.moving_wall_list.append(wall) # 建上下移动的平台 wall = arcade.Sprite("images/grassMid.png", SPRITE_SCALING) wall.center_y = 5 * GRID_PIXEL_SIZE wall.center_x = 5 * GRID_PIXEL_SIZE wall.boundary_top = 8 * GRID_PIXEL_SIZE wall.boundary_bottom = 4 * GRID_PIXEL_SIZE wall.change_y = 2 * SPRITE_SCALING self.all_sprites_list.append(wall) self.all_wall_list.append(wall) self.moving_wall_list.append(wall) # 建斜向移动的平台 wall = arcade.Sprite("images/grassMid.png", SPRITE_SCALING) wall.center_y = 5 * GRID_PIXEL_SIZE wall.center_x = 8 * GRID_PIXEL_SIZE wall.boundary_left = 7 * GRID_PIXEL_SIZE wall.boundary_right = 9 * GRID_PIXEL_SIZE wall.boundary_top = 8 * GRID_PIXEL_SIZE wall.boundary_bottom = 4 * GRID_PIXEL_SIZE wall.change_x = 2 * SPRITE_SCALING wall.change_y = 2 * SPRITE_SCALING self.all_sprites_list.append(wall) self.all_wall_list.append(wall) self.moving_wall_list.append(wall) # 加载平台型的物理引擎 self.physics_engine = \ arcade.PhysicsEnginePlatformer(self.player_sprite, self.all_wall_list, gravity_constant=GRAVITY) # 设置背景颜色为亚马逊绿 arcade.set_background_color(arcade.color.AMAZON) # 设置视区初始值 self.view_left = 0 self.view_bottom = 0 self.game_over = False def on_draw(self): """ 每帧重画屏幕 """ # 重画所有对象之前要先调用下面的命令 arcade.start_render() # 画所有角色 self.static_wall_list.draw() self.moving_wall_list.draw() self.player_list.draw() # Put the text on the screen. # Adjust the text position based on the viewport so that we don't # scroll the text too. # 根据视区左下角坐标放置得分文本 distance = self.player_sprite.right output = f"Distance: {distance}" arcade.draw_text(output, self.view_left + 10, self.view_bottom + 20, arcade.color.WHITE, 14) if self.game_over: output = "Game Over" arcade.draw_text(output, self.view_left + 200, self.view_bottom + 200, arcade.color.WHITE, 30) def on_key_press(self, key, modifiers): """ 当键按下时调用此方法 """ if key == arcade.key.UP: if self.physics_engine.can_jump(): self.player_sprite.change_y = JUMP_SPEED elif key == arcade.key.LEFT: self.player_sprite.change_x = -MOVEMENT_SPEED elif key == arcade.key.RIGHT: self.player_sprite.change_x = MOVEMENT_SPEED def on_key_release(self, key, modifiers): """ 当键松开时调用此方法 """ if key == arcade.key.LEFT or key == arcade.key.RIGHT: self.player_sprite.change_x = 0 def update(self, delta_time): """ 移动角色们与游戏逻辑 """ if self.player_sprite.right >= self.end_of_map: self.game_over = True # 更新所有角色 if not self.game_over: self.physics_engine.update() changed = False # 视口左滚动 self.view_left是视口最左x坐标 left_boundary = self.view_left + VIEWPORT_MARGIN if self.player_sprite.left < left_boundary: self.view_left -= left_boundary - self.player_sprite.left # 视口往左移,弥补差 changed = True # Scroll right right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_MARGIN if self.player_sprite.right > right_boundary: self.view_left += self.player_sprite.right - right_boundary changed = True # Scroll up top_boundary = self.view_bottom + SCREEN_HEIGHT - VIEWPORT_MARGIN if self.player_sprite.top > top_boundary: self.view_bottom += self.player_sprite.top - top_boundary changed = True # Scroll down bottom_boundary = self.view_bottom + VIEWPORT_MARGIN if self.player_sprite.bottom < bottom_boundary: self.view_bottom -= bottom_boundary - self.player_sprite.bottom changed = True # 如果改变了重新设置视口 if changed: arcade.set_viewport(self.view_left, SCREEN_WIDTH + self.view_left, self.view_bottom, SCREEN_HEIGHT + self.view_bottom) def main(): """ Main method """ window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) window.setup() arcade.run() if __name__ == "__main__": main()
李兴球
李兴球的博客是Python创意编程原创博客