小学生python游戏编程arcade----可旋转炮台的坦克
前言
接上篇文章继续解绍arcade游戏编程的基本知识。
带炮台的坦克
1、可旋转炮台的坦克实现
1.1坦克由两部分组成
1.2 组装坦克
# 组装坦克
self.tank = arcade.Sprite(TANK_BODY,image_x=0,image_y=0,image_width=132,image_height=243,scale=1)
self.tank.position = SCREEN_MIDDLE
self.barrel = RotatingSprite(TANK_BARREL, image_x=150,image_y=43,image_width=86,image_height=200,scale=1)
self.barrel.position =\
SCREEN_MIDDLE[0], SCREEN_MIDDLE[1] - TANK_panli
1.3 效果图
炮台随鼠标可以转动
围绕点的精灵旋转,带炮台的坦克,游戏通常包括朝向目标旋转的元素。常见的例如,车辆和塔楼上的炮塔。在2D游戏中,这些旋转部件通常被实现为移动的精灵相对于他们所依附的任何东西。
这有一个问题:你必须围绕它们的附着点而不是精灵的中心。否则旋转看起来不对!为了说明区别,本例使用了一个可控制的播放器有一个跟在鼠标后面的坦克。
1.正确,枪管后部紧靠坦克中心
2.错误的是,围绕枪管中心,将其固定在坦克上
1.4 代码实现
import arcade
import math
TANK_SPEED_PIXELS =64# 坦克每秒移动多少像素
TANK_TURN_SPEED_DEGREES =70# 坦克车身转动的速度# 这是炮台精灵旋转中心位置与坦克中心的偏离差。# 我们使用它来确保炮台的后部位于坦克的中间
TANK_panli =40
SCREEN_WIDTH =800
SCREEN_HEIGHT =600
SCREEN_MIDDLE =(SCREEN_WIDTH //2, SCREEN_HEIGHT //2)
SCREEN_TITLE ="上下旋转的坦克"# These paths are built-in resources included with arcade
TANK_BODY ="images/坦克1.png"
TANK_BARREL ="images/坦克1.png"classRotatingSprite(arcade.Sprite):"""
可以围绕一个点旋转的精灵子类。这个版本的类总是改变精灵的角度。
其他游戏可能不会旋转精灵。例如,移动平台成型机中的平台不会旋转。
"""defrotate_around_point(self, point: arcade.Point, degrees:float):# 使精灵在其位置移动时旋转
self.angle += degrees
# 沿着以传递点为中心的圆移动精灵
self.position = arcade.rotate_point(
self.center_x, self.center_y,
point[0], point[1], degrees)classExampleWindow(arcade.Window):def__init__(self):super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)# 设置背景色
self.background_color = arcade.csscolor.SEA_GREEN
# 组装坦克
self.tank = arcade.Sprite(TANK_BODY,image_x=0,image_y=0,image_width=132,image_height=243,scale=1)
self.tank.position = SCREEN_MIDDLE
self.barrel = RotatingSprite(TANK_BARREL, image_x=150,image_y=43,image_width=86,image_height=200,scale=1)
self.barrel.position =\
SCREEN_MIDDLE[0], SCREEN_MIDDLE[1]- TANK_panli
self.tank_direction =0.0# # 前进和后退油门
self.tank_turning =0.0# 向左或向右转的力度
self.mouse_pos =0,0
self.tank_sprite_list = arcade.SpriteList()
self.tank_sprite_list.extend([self.tank, self.barrel])
self.control_text = arcade.Text("WASD 键移动坦克, 鼠标移动炮台指向",
SCREEN_MIDDLE[0],15,
anchor_x='center')defon_draw(self):
self.clear()
self.tank_sprite_list.draw()
self.control_text.draw()defon_update(self, delta_time:float):
self.move_tank(delta_time)defmove_tank(self, delta_time):# 在不改变位置的情况下将罐体旋转到位,我们将在更新整个坦克的x轴和y轴后旋转枪管
self.tank.angle += TANK_TURN_SPEED_DEGREES\
* self.tank_turning * delta_time
#计算应向前或向后移动多少
move_magnitude = self.tank_direction * TANK_SPEED_PIXELS * delta_time
x_dir = math.cos(self.tank.radians - math.pi /2)* move_magnitude
y_dir = math.sin(self.tank.radians - math.pi /2)* move_magnitude
# 移动坦克底盘
self.tank.position =\
self.tank.center_x + x_dir,\
self.tank.center_y + y_dir
#移动炮台
self.barrel.position =\
self.barrel.center_x + x_dir,\
self.barrel.center_y + y_dir
# 计算坦克与鼠标的角度
mouse_angle = arcade.get_angle_degrees(
self.tank.center_y, self.tank.center_x,
self.mouse_pos[1], self.mouse_pos[0])# 补偿原始图片的垂直方向,如果图片朝右,则可以跳过此操作
mouse_angle +=90
angle_change = mouse_angle - self.barrel.angle
self.barrel.rotate_around_point(self.tank.position, angle_change)defon_key_press(self, symbol:int, modifiers:int):if symbol == arcade.key.W:
self.tank_direction +=1elif symbol == arcade.key.S:
self.tank_direction -=1elif symbol == arcade.key.A:
self.tank_turning +=1elif symbol == arcade.key.D:
self.tank_turning -=1elif symbol == arcade.key.P:passdefon_key_release(self, symbol:int, modifiers:int):if symbol == arcade.key.W:
self.tank_direction -=1elif symbol == arcade.key.S:
self.tank_direction +=1elif symbol == arcade.key.A:
self.tank_turning -=1elif symbol == arcade.key.D:
self.tank_turning +=1defon_mouse_motion(self, x:int, y:int, dx:int, dy:int):
self.mouse_pos = x, y
defmain():
window = ExampleWindow()
window.run()if __name__ =='__main__':
main()
2、以上示例改为类,便于集成游戏中
2.1 常量 存于seting文件中
坦克属性
TANK_body = “images/坦克1.png”
TANK_barrel = “images/坦克1.png”
TANK_pos = (SCREEN_width// 2, SCREEN_height // 2)
TANK_pianli = 15
TANK_speed_pixels = 64 #坦克每秒移动多少像素
TANK_turn_speed_degrees = 70 #坦克车身转动的速度
2.2 坦克类
from arcadegame.seting import *
import arcade
import math
class RotatingSprite(arcade.Sprite):
“”" 可以围绕一个点旋转的精灵子类。 “”"
def rotate_around_point(self, point: arcade.Point, degrees: float):
使精灵在其位置移动时旋转
self.angle += degrees
# 沿着以传递点为中心的圆移动精灵
self.position = arcade.rotate_point(
self.center_x, self.center_y,
point[0], point[1], degrees)
class Tanke(RotatingSprite):
def init(self):
super().init()
The tank and barrel sprite
self.tank = arcade.Sprite(TANK_body,image_x=0,image_y=0,image_width=132,image_height=243,scale=0.5)
self.tank.position = TANK_pos
self.barrel = RotatingSprite(TANK_barrel, image_x=150,image_y=0,image_width=89,image_height=243,scale=0.5)
self.barrel.position =\
TANK_pos[0], TANK_pos[1] - TANK_pianli
def move_tank(self, delta_time,tank_turning,tank_direction,mouse_pos):
# 在不改变位置的情况下将罐体旋转到位,我们将在更新整个坦克的x轴和y轴后旋转枪管
self.tank.angle += TANK_turn_speed_degrees\
* tank_turning * delta_time
#计算应向前或向后移动多少
move_magnitude = tank_direction * TANK_speed_pixels * delta_time
x_dir = math.cos(self.tank.radians - math.pi / 2) * move_magnitude
y_dir = math.sin(self.tank.radians - math.pi / 2) * move_magnitude
# 移动坦克底盘
self.tank.position =\
self.tank.center_x + x_dir,\
self.tank.center_y + y_dir
#移动炮台
self.barrel.position =self.barrel.center_x + x_dir, self.barrel.center_y + y_dir
# 计算坦克与鼠标的角度
mouse_angle = arcade.get_angle_degrees(
self.tank.center_y, self.tank.center_x,
mouse_pos[1], mouse_pos[0])
# 补偿炮台的垂直方向如果朝右,则可以跳过此操作
mouse_angle += 90
angle_change = mouse_angle - self.barrel.angle
self.barrel.rotate_around_point(self.tank.position, angle_change)
2.3 Tank类的使用效果图
2.4 代码实现
"""
围绕点的精灵旋转,带坦克
游戏通常包括朝向目标旋转的元素。常见的例如,车辆和塔楼上的炮塔。在2D游戏中,
这些旋转部件通常被实现为移动的精灵相对于他们所依附的任何东西。
这有一个问题:你必须围绕它们的附着点而不是精灵的中心。否则旋转看起来不对!
为了说明区别,本例使用了一个可控制的播放器
有一个跟在鼠标后面的坦克。您可以按P切换
在两种旋转的方式之间:
1.正确,枪管后部紧靠坦克中心
2.错误的是,围绕枪管中心,将其固定在坦克上
"""from arcadegame.tank import*
SCREEN_WIDTH =800
SCREEN_HEIGHT =600
SCREEN_MIDDLE =(SCREEN_WIDTH //2, SCREEN_HEIGHT //2)
SCREEN_TITLE ="上下旋转的坦克"classExampleWindow(arcade.Window):def__init__(self):super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)# Set Background to be green
self.background_color = arcade.csscolor.SEA_GREEN
self.tk =None
self.tank_direction =0.0# # 前进和后退油门
self.tank_turning =0.0# 向左或向右转的力度
self.mouse_pos=0,0
self.scene =None
self.control_text = arcade.Text("WASD 键移动坦克, 鼠标移动炮台指向",
SCREEN_MIDDLE[0],15,
anchor_x='center')defsetup(self):# 坦克
self.tk = Tanke()# self.tank_sprite_list = arcade.SpriteList()# self.tank_sprite_list.extend([self.tk.tank, self.tk.barrel])# 初始化场景
map_name =f"地图\家2.json"# jia{self.level}.json"# 层属性
layer_options ={
LAYER_platforms:{"use_spatial_hash":True,},
LAYER_tree:{"use_spatial_hash":False,},'fz':{"use_spatial_hash":True,},# 'tizi': {# "use_spatial_hash": True,# },'Enemies':{"use_spatial_hash":True,},}# 读地图文件
self.tile_map = arcade.load_tilemap(map_name, TILE_Scaling, layer_options)# 使用我们的TileMap初始化场景,这将自动添加所有层,以正确的顺序在场景中显示为SpriteList。
self.scene = arcade.Scene.from_tilemap(self.tile_map)
self.scene.add_sprite("tanke", self.tk.tank)
self.scene.add_sprite("tanke", self.tk.barrel)defon_draw(self):
self.clear()# self.tank_sprite_list.draw()
self.scene.draw()
self.control_text.draw()defon_update(self, delta_time:float):
self.tk.move_tank(delta_time,self.tank_turning,self.tank_direction,self.mouse_pos)defon_key_press(self, symbol:int, modifiers:int):if symbol == arcade.key.W:
self.tank_direction +=1elif symbol == arcade.key.S:
self.tank_direction -=1elif symbol == arcade.key.A:
self.tank_turning +=1elif symbol == arcade.key.D:
self.tank_turning -=1elif symbol == arcade.key.P:passdefon_key_release(self, symbol:int, modifiers:int):if symbol == arcade.key.W:
self.tank_direction -=1elif symbol == arcade.key.S:
self.tank_direction +=1elif symbol == arcade.key.A:
self.tank_turning -=1elif symbol == arcade.key.D:
self.tank_turning +=1defon_mouse_motion(self, x:int, y:int, dx:int, dy:int):
self.mouse_pos = x, y
defmain():
window = ExampleWindow()
window.setup()
window.run()if __name__ =='__main__':
main()
源码获取
可关注博主后,私聊博主免费获取
需要技术指导,育娃新思考,企业软件合作等更多服务请联系博主
今天是以此模板持续更新此育儿专栏的第 17/50次。
可以关注我,点赞我、评论我、收藏我啦。
版权归原作者 信息化未来 所有, 如有侵权,请联系我们删除。