Python街机模块键盘操作的双棍射击游戏示例

Python海龟宝典含200多个原创的用turtle模块制作的创意程序,原名《Python趣味编程200例》。准备参加全国创意编程与智能设计大赛的同学们可以用来做参考。

"""
键盘操作的双棍射击游戏示例
双棍就是街机游戏厅里的操作角色方向的那两根杆子,由于没有双棍,所以把相关的代码去掉了。

"""
import arcade
import random
import math
import os
import pprint

SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 768
SCREEN_TITLE = "Python街机模块键盘操作的双棍射击游戏示例,译者:李兴球"
MOVEMENT_SPEED = 4
BULLET_SPEED = 10
BULLET_COOLDOWN_TICKS = 10
ENEMY_SPAWN_INTERVAL = 1
ENEMY_SPEED = 1 

  
class Player(arcade.sprite.Sprite):
    def __init__(self, filename):
        super().__init__(filename=filename, scale=0.4, center_x=SCREEN_WIDTH/2, center_y=SCREEN_HEIGHT/2)
        self.shoot_up_pressed = False
        self.shoot_down_pressed = False
        self.shoot_left_pressed = False
        self.shoot_right_pressed = False


class Enemy(arcade.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__(filename='images/bumper.png', scale=0.5, center_x=x, center_y=y)

    def follow_sprite(self, player_sprite):
        """
        本函数会让敌人朝玩家角色的方向移动

        We use the 'min' function here to get the sprite to line up with
        the target sprite, and not jump around if the sprite is not off
        an exact multiple of ENEMY_SPEED.
        """
        # 如果敌人的y坐标小于飞船的y坐标,那么就让它向上移动。每次移动的最大距离是ENEMY_SPEED
        if self.center_y < player_sprite.center_y:
            self.center_y += min(ENEMY_SPEED, player_sprite.center_y - self.center_y)
        elif self.center_y > player_sprite.center_y:
            self.center_y -= min(ENEMY_SPEED, self.center_y - player_sprite.center_y)
        # 如果敌人在玩家左边,就让它向右移动,每次移动的最大距离是ENEMY_SPEED
        if self.center_x < player_sprite.center_x:
            self.center_x += min(ENEMY_SPEED, player_sprite.center_x - self.center_x)
        elif self.center_x > player_sprite.center_x:
            self.center_x -= min(ENEMY_SPEED, self.center_x - player_sprite.center_x)


class MyGame(arcade.Window):
    def __init__(self, width, height, title):
        super().__init__(width, height, title)

        # 设置游戏工作目录,如果用python -m启动时需要,否则不需要
        file_path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(file_path)

        arcade.set_background_color(arcade.color.DARK_MIDNIGHT_BLUE)
        self.game_over = False
        self.score = 0
        self.tick = 0
        self.bullet_cooldown = 0
        self.player = Player("images/playerShip2_orange.png") # 新建玩家角色
        self.bullet_list = arcade.SpriteList()                # 子弹列表
        self.enemy_list = arcade.SpriteList()                 # 敌人列表
        arcade.window_commands.schedule(self.spawn_enemy, ENEMY_SPAWN_INTERVAL)# 计划安排定时任务
 

    def spawn_enemy(self, elapsed):
        """生成敌人"""
        if self.game_over:
            return
        x = random.randint(0, SCREEN_WIDTH)
        y = random.randint(0, SCREEN_HEIGHT)
        self.enemy_list.append(Enemy(x, y))

    def update(self, delta_time):
        self.tick += 1
        if self.game_over:
            return

        self.bullet_cooldown += 1             # 这是计数器,用来限制发射击子弹不要太快

        for enemy in self.enemy_list:         # 每个敌人都朝向玩家移动
            enemy.follow_sprite(self.player)


        # Keyboard input - shooting
        if self.player.shoot_right_pressed and self.player.shoot_up_pressed:
            self.spawn_bullet(0+45)
        elif self.player.shoot_up_pressed and self.player.shoot_left_pressed:
            self.spawn_bullet(90+45)
        elif self.player.shoot_left_pressed and self.player.shoot_down_pressed:
            self.spawn_bullet(180+45)
        elif self.player.shoot_down_pressed and self.player.shoot_right_pressed:
            self.spawn_bullet(270+45)
        elif self.player.shoot_right_pressed:
            self.spawn_bullet(0)
        elif self.player.shoot_up_pressed:
            self.spawn_bullet(90)
        elif self.player.shoot_left_pressed:
            self.spawn_bullet(180)
        elif self.player.shoot_down_pressed:
            self.spawn_bullet(270)

        self.enemy_list.update()
        self.player.update()
        self.bullet_list.update()
        # 玩家和敌人组的碰撞检测
        ship_death_hit_list = arcade.check_for_collision_with_list(self.player, self.enemy_list)
        if len(ship_death_hit_list) > 0: # 碰到任一个这个列表长度都是大于0,所以游戏结束了
            self.game_over = True
        for bullet in self.bullet_list:  # 每颗子弹和敌人组的碰撞检测
            bullet_killed = False
            enemy_shot_list = arcade.check_for_collision_with_list(bullet, self.enemy_list)
            # 遍历碰到的每个敌人,删除它们.
            for enemy in enemy_shot_list:
                enemy.kill()
                bullet.kill()
                bullet_killed = True
                self.score += 1
            if bullet_killed:
                continue

    def on_key_press(self, key, modifiers):
        if key == arcade.key.W:
            self.player.change_y = MOVEMENT_SPEED
            self.player.angle = 0
        elif key == arcade.key.A:
            self.player.change_x = -MOVEMENT_SPEED
            self.player.angle = 90
        elif key == arcade.key.S:
            self.player.change_y = -MOVEMENT_SPEED
            self.player.angle = 180
        elif key == arcade.key.D:
            self.player.change_x = MOVEMENT_SPEED
            self.player.angle = 270
        elif key == arcade.key.RIGHT:
            self.player.shoot_right_pressed = True
        elif key == arcade.key.UP:
            self.player.shoot_up_pressed = True
        elif key == arcade.key.LEFT:
            self.player.shoot_left_pressed = True
        elif key == arcade.key.DOWN:
            self.player.shoot_down_pressed = True

    def on_key_release(self, key, modifiers):
        if key == arcade.key.W:
            self.player.change_y = 0
        elif key == arcade.key.A:
            self.player.change_x = 0
        elif key == arcade.key.S:
            self.player.change_y = 0
        elif key == arcade.key.D:
            self.player.change_x = 0
        elif key == arcade.key.RIGHT:
            self.player.shoot_right_pressed = False
        elif key == arcade.key.UP:
            self.player.shoot_up_pressed = False
        elif key == arcade.key.LEFT:
            self.player.shoot_left_pressed = False
        elif key == arcade.key.DOWN:
            self.player.shoot_down_pressed = False

    def spawn_bullet(self, angle_in_deg):
        # self.bullet_cooldown的值没有到达TICKS值是直接返回
        if self.bullet_cooldown < BULLET_COOLDOWN_TICKS:
            return
        self.bullet_cooldown = 0

        bullet = arcade.Sprite("images/laserBlue01.png", 0.75)

        # 把子弹放到飞船坐标
        start_x = self.player.center_x
        start_y = self.player.center_y
        bullet.center_x = start_x
        bullet.center_y = start_y

        #  
        bullet.angle = angle_in_deg
        angle_in_rad = math.radians(angle_in_deg)

        # 设置子弹移动方向
        bullet.change_x = math.cos(angle_in_rad) * BULLET_SPEED
        bullet.change_y = math.sin(angle_in_rad) * BULLET_SPEED

        # 增加子弹到相应的列表
        self.bullet_list.append(bullet)

    def on_draw(self):
        # 重量所有角色
        arcade.start_render()

        
        self.bullet_list.draw()
        self.enemy_list.draw()
        self.player.draw()

        # 画文本,把得分情况放到屏幕上
        output = f"Score: {self.score}"
        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)

        # 结束语
        if self.game_over:
            arcade.draw_text("Game Over", SCREEN_WIDTH/2, SCREEN_HEIGHT/2, arcade.color.WHITE, 100, width=SCREEN_WIDTH,
                             align="center", anchor_x="center", anchor_y="center")


if __name__ == "__main__":
    game = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
    arcade.run()

 

本站所有作品,教程等皆为原创,版权所有。只供个人及单位内部研究使用,对外展示或传播必需经本站同意,且注明来自本站。培训机构等用本站资源培训学生,需经本站授权。一旦付款,表示同意本站知识付费原则:数字商品,不支持退款。亦可直接向微信号scratch8付款购买。入住QQ群:225792826 和爱好者共同交流,并且能下载免费提供的Python资源(需提供真实姓名才可入群)
李兴球的博客_Python创意编程技术前沿_pygame » Python街机模块键盘操作的双棍射击游戏示例

李兴球Python微信公众号文章列表

Python游戏海龟模块教程说明书与案例若干免费发放

爱的纪念_Python创意情景动画源代码解析

少儿Python编程到底学些什么?这些代码或许回答了问题.

Python编程家长会花絮_萍乡中小学Python家长会现场

火星路上等着你_少儿从小学什么最好呢?

国家大力整顿教育培训机构,Scratch或Python少儿编程还有得教吗?

鸿蒙系统支持Python开发_可视化编程特别兴趣小组

Scratch作品转Python作品_小猴接桃

python海龟数据可视化。第七次全国人口普查历年数据图表

你的孩子Python编程学到哪个阶段了?给孩子报编程的家长,务必仔细一读。

五一神女来对话,看看她们聊什么?赠Python教案等。

五一快乐有大礼,告诉大家我是如何上Python课的。

Python名堂多,趣味到处有,劈开机械手,帧帧是图片。速算达人之猫狮大战正在进行。 逐字动画不独享,自动生成皆有它。2行代码自动生成字幕gif动画。 Python之潮来临,我在安源区教师科技创新能力的Python讲座

小心你的Python程序,它会是你的一面镜子。小方块闯迷宫.py源代码简析。送Scratch算法集。?

铃儿响钉铛_音效怎能忘_Python配音之Pygame混音器

人面桃花相映红_winsound模块简介

《Python昨晚我想你了》_开源的游戏海龟模块实例案例浅析

《八猫联动初体验》_来自游戏海龟模块的问候

喜爱春天的人儿啊 心地纯洁的人_Python逐行像素显示

旋转之三叶炫彩扇_蟒蛇与海龟的表演

彩虹欢迎字幕_三模合体滚图形

《Python海龟宝典》简介

100%错误的算法还在用,明明没有错别字,说我有11个错别字

奇怪的Python代码,谁能帮我解释一下??

人造地球系统让人类文明充满整个宇宙之Python32768版

深夜,是什么把你的大脑搞成一团浆糊!再谈少儿编程!

5线城市萍乡的少儿Python寒假班学的是什么内容?

关于纯少儿编程课程进化的自然选择

Python海龟画图经典作品_国庆中秋双重喜庆源代码免费下载

海龟为什么要自杀!turtle制作游戏秘籍之一

朋友,你是否知道我在仰望着你_Python神笔马良案例集

酷酷的爆炸效果_Python海龟画图不仅仅是画图

虫子满屏爬_三bug多线程示例程序浅析 少儿Python视频课程A级简介

给的gif图片加文字水印_拆帧与合帧(免费下载180个Python创意源码

用Python制作酷炫图形之如意金箍棒_颜色增加模块应用

简单的用Python做酷炫图形与动画

sb3转exe,sb3素材提取器,编程小子apk, 未公开的pygame游戏集/scratch/python少儿编程免费下载集合

夜幕下的霓虹

学本领,探索更大的世界!

李兴球博客 风火轮编程主页
error: Content is protected !!