接上篇文章继续解绍arcade游戏编程的基本知识。角色的旋转射击,如坦克可以键盘控制旋转的方向及按角度前进与后退
精灵类的基本角度,是以朝上为0的,如调用第一种图片,会出现很奇怪的角度前进方向,可自己试试,通过初始设置为# self.player_sprite.angle=0或90都不可以成功的。
# 角色初始,图片正上方的角度为0
self.score = 0
self.player_sprite = ShipSprite("images/坦克.png", 1)
self.player_sprite_list.append(self.player_sprite)
self.lives = 3
def on_key_press(self, symbol, modifiers):
if symbol == arcade.key.LEFT:
self.player_sprite.change_angle = 3
elif symbol == arcade.key.RIGHT:
self.player_sprite.change_angle = -3
def on_key_release(self, symbol, modifiers):
if symbol == arcade.key.LEFT:
self.player_sprite.change_angle = 0
elif symbol == arcade.key.RIGHT:
self.player_sprite.change_angle = 0
def __init__(self, filename, scale):
# 调用图片
super().__init__(filename, scale)
# 前进的信息
# 角度自动从父类传入。
self.thrust = 0 # 前进动力,一直按键时,前进动力的增加
self.speed = 0 # 速度
self.max_speed = 4 # 最大速度,防止一直增加
self.drag = 0.05 # 摩擦力
def on_key_press(self, symbol, modifiers):
if symbol == arcade.key.LEFT:
…
elif symbol == arcade.key.UP:
self.player_sprite.thrust = 0.15
elif symbol == arcade.key.DOWN:
self.player_sprite.thrust = -.2
def on_key_release(self, symbol, modifiers):
…
elif symbol == arcade.key.UP:
self.player_sprite.thrust = 0
elif symbol == arcade.key.DOWN:.
self.player_sprite.thrust = 0
核心代码:self.change_x = -math.sin(math.radians(self.angle)) * self.speed
self.change_y = math.cos(math.radians(self.angle)) * self.speed
def update(self):
if self.speed > 0:
self.speed -= self.drag
if self.speed < 0:
self.speed = 0
if self.speed < 0:
self.speed += self.drag
if self.speed > 0:
self.speed = 0
self.speed += self.thrust
if self.speed > self.max_speed:
self.speed = self.max_speed
if self.speed < -self.max_speed:
self.speed = -self.max_speed
self.change_x = -math.sin(math.radians(self.angle)) * self.speed
self.change_y = math.cos(math.radians(self.angle)) * self.speed
self.center_x += self.change_x
self.center_y += self.change_y
# 过界处理
....
""" 调用父类update """
super().update()
# 炮台口位置
self.paokou = 0, 0
不计算炮口位置,直接引用坦克中心位置,修改画面会制顺序,先给制子弹,再绘制角色,看其来正好从炮口位置发射。
if not self.player_sprite.respawning and symbol == arcade.key.SPACE:
bullet_sprite = TurningSprite(":resources:images/space_shooter/"
"laserBlue01.png",
SCALE)
bullet_sprite.guid = "Bullet"
bullet_speed = 13
bullet_sprite.change_y = \
math.cos(math.radians(self.player_sprite.angle)) * bullet_speed
bullet_sprite.change_x = \
-math.sin(math.radians(self.player_sprite.angle)) \
* bullet_speed
bullet_sprite.center_x = self.player_sprite.center_x
bullet_sprite.center_y = self.player_sprite.center_y
bullet_sprite.update()
self.bullet_list.append(bullet_sprite)
arcade.play_sound(self.laser_sound, speed=random.random() * 3 + 0.5)
"""
键盘控制角色任意角度旋转及前进后退
"""
import math
import arcade
SCREEN_width = 800
SCREEN_height = 650
SCREEN_title = "旋转角色"
class ShipSprite(arcade.Sprite):
"""
旋转角色类
"""
def __init__(self, filename, scale):
# 调用图片
super().__init__(filename, scale)
# 前进的信息
# 角度自动从父类传入。
self.thrust = 0 # 前进动力,一直按键时,前进动力的增加
self.speed = 0 # 速度
self.max_speed = 4 # 最大速度,防止一直增加
self.drag = 0.05 # 摩擦力
# 炮台口位置
self.paokou = 0, 0
# 重生
self.respawning = 0 # 重生计时器
self.respawn()
def respawn(self):
"""
死而复生画面
'respawning'重生计时器.
"""
# 如果我们正在重生,这不能为零
self.respawning = 1
self.center_x = SCREEN_width / 2
self.center_y = SCREEN_height / 2
self.angle = 0
def update(self):
# 死后复生
if self.respawning:
self.respawning += 1
self.alpha = self.respawning
if self.respawning > 250:
self.respawning = 0
self.alpha = 255
if self.speed > 0:
self.speed -= self.drag
if self.speed < 0:
self.speed = 0
if self.speed < 0:
self.speed += self.drag
if self.speed > 0:
self.speed = 0
self.speed += self.thrust
if self.speed > self.max_speed:
self.speed = self.max_speed
if self.speed < -self.max_speed:
self.speed = -self.max_speed
self.change_x = -math.sin(math.radians(self.angle)) * self.speed
self.change_y = math.cos(math.radians(self.angle)) * self.speed
self.center_x += self.change_x
self.center_y += self.change_y
# 过界处理
if self.right < 0:
self.left = SCREEN_width
if self.left > SCREEN_width:
self.right = 0
if self.bottom < 0:
self.top = SCREEN_height
if self.top > SCREEN_height:
self.bottom = 0
""" 调用父类update """
super().update()
class MyGame(arcade.Window):
def __init__(self):
super().__init__(SCREEN_width, SCREEN_height, SCREEN_title)
self.game_over = False
# 坦克及子弹列表
self.player_sprite_list = arcade.SpriteList()
self.bullet_list = arcade.SpriteList()
# 坦克
self.score = 0
self.player_sprite = None
self.lives = 3
# Sounds
self.laser_sound = arcade.load_sound(":resources:sounds/hurt5.wav")
self.hit_sound1 = arcade.load_sound(":resources:sounds/explosion1.wav")
self.hit_sound2 = arcade.load_sound(":resources:sounds/explosion2.wav")
self.hit_sound3 = arcade.load_sound(":resources:sounds/hit1.wav")
self.hit_sound4 = arcade.load_sound(":resources:sounds/hit2.wav")
# Text
self.text_score = None
self.text_asteroid_count = None
def start_new_game(self):
self.game_over = False
# 列表
self.player_sprite_list = arcade.SpriteList()
self.bullet_list = arcade.SpriteList()
# 角色初始,图片正上方的角度为0
self.score = 0
self.player_sprite = ShipSprite("images/坦克.png", 1)
self.player_sprite_list.append(self.player_sprite)
self.lives = 3
# self.player_sprite.angle=0
# Create new text objects with initial values
self.text_score = arcade.Text(
f"角色角度: {self.player_sprite.angle}",
start_x=10,
start_y=70,
font_size=13,
)
def on_draw(self):
self.clear()
# Draw all the sprites.
# self.asteroid_list.draw()
# self.ship_life_list.draw()
self.bullet_list.draw()
self.player_sprite_list.draw()
# Draw the text
self.text_score.draw()
# self.text_asteroid_count.draw()
def on_key_press(self, symbol, modifiers):
if symbol == arcade.key.LEFT:
self.player_sprite.change_angle = 3
elif symbol == arcade.key.RIGHT:
self.player_sprite.change_angle = -3
elif symbol == arcade.key.UP:
self.player_sprite.thrust = 0.15
elif symbol == arcade.key.DOWN:
self.player_sprite.thrust = -.2
def on_key_release(self, symbol, modifiers):
if symbol == arcade.key.LEFT:
self.player_sprite.change_angle = 0
elif symbol == arcade.key.RIGHT:
self.player_sprite.change_angle = 0
elif symbol == arcade.key.UP:
self.player_sprite.thrust = 0
elif symbol == arcade.key.DOWN:
self.player_sprite.thrust = 0
def on_update(self, x):
""" Move everything """
if not self.game_over:
# self.asteroid_list.update()
self.bullet_list.update()
self.player_sprite_list.update()
# Update the text objects
self.text_score.text = f"角色角度: {self.player_sprite.angle}",
# self.text_asteroid_count.text = f"Asteroid Count: {len(self.asteroid_list)}"
def main():
""" Start the game """
window = MyGame()
window.start_new_game()
arcade.run()
if __name__ == "__main__":
main()
可关注博主后,私聊博主免费获取
需要技术指导,育娃新思考,企业软件合作等更多服务请联系博主
今天是以此模板持续更新此育儿专栏的第 19/50次。
可以关注我,点赞我、评论我、收藏我啦。