Beispiel #1
0
class Wall(Entity):
    defaults = {
        'width': config.block_width,
        'height': config.block_height,
        'collidable': True
    }

    attributes = {'color': RGB(255, 255, 255)}

    def init(self, **kwargs):
        self.shape = Rectangle(self.x,
                               self.y,
                               height=self.height,
                               width=self.width,
                               color=self.color,
                               batch=self.batch)

    def on_collision(self, obj):
        pass

    def take_damage(self, source, damage):
        pass

    def update(self):
        pass

    def draw(self):
        self.shape.draw()
Beispiel #2
0
class Button:
    def __init__(self, width, height, x, y, x_shift, y_shift, text, color, font_color):
        self.width = width
        self.height = height
        self.x = x
        self.y = y
        self.text = text
        self.org_color = color
        self.org_font_color = font_color
        self.color = color
        self.font_color = font_color
        self.x_shift = width / x_shift
        self.y_shift = height / y_shift

    def draw(self):
        self.rect = Rectangle(self.x, self.y, self.width, self.height, self.color)
        self.rect.draw()
        self.description = Label(self.text, self.x + self.x_shift, self.y + self.y_shift, self.font_color)
        self.description.draw()

    def hovered(self):
        self.inverse_colors()
        self.draw()
    
    def not_hovered(self):
        self.color = self.org_color
        self.font_color = self.org_font_color
        self.draw()

    def inverse_colors(self):
        self.color = (self.org_font_color[0], self.org_font_color[1], self.org_font_color[2])
        self.font_color = (self.org_color[0], self.org_color[1], self.org_color[2], 255)
class EndScreen:
    def __init__(self, window_width, window_height, score, kill_count,
                 total_enemies):
        self.win_width = window_width
        self.win_height = window_height
        self.score = score
        self.kill_count = kill_count
        self.button_width = 300
        self.button_height = 50
        self.x = (self.win_width / 2) - (self.button_width / 2)
        self.y = (self.win_height / 2) - (self.button_height / 2)
        self.pop_up = Rectangle(self.x - 100, self.y - 300, 500, 800,
                                (50, 50, 50))
        self.title = Label('G A M E   O V E R!', self.x + 5, self.y + 90,
                           (150, 1, 1, 255))
        self.info_label_score = Label(f'SCORE: {self.score}', self.x + 50,
                                      self.y, (60, 135, 50, 255))
        self.info_label_kills = Label(
            f'KILLS: {self.kill_count} / {total_enemies}', self.x + 15,
            self.y - 50, (60, 135, 50, 255))
        self.menu_button = Button(self.button_width, self.button_height,
                                  self.x, self.y - 150, 3.4, 5, 'M E N U',
                                  (1, 1, 1), (60, 235, 50, 255))

    def draw(self):
        self.pop_up.draw()
        self.info_label_score.draw()
        self.info_label_kills.draw()
        self.menu_button.draw()
        self.title.draw()

    def button_was_clicked(self, x, y, button):
        if (x >= int(button.x)) and (x <= int(button.x) + (self.button_width)):
            if (y >= int(button.y)) and (y <= int(button.y) +
                                         (self.button_height)):
                return True
        return False

    def button_was_touched(self, x, y, button):
        if (x >= int(button.x)) and (x <= int(button.x) + (self.button_width)):
            if (y >= int(button.y)) and (y <= int(button.y) +
                                         (self.button_height)):
                return True
        return False
Beispiel #4
0
def on_draw():
    #window.clear()
    #main_batch.draw()
    rec = Rectangle(x, y, 1, 1)
    rec.draw()
Beispiel #5
0
class Player(GameObject):
    def __init__(self,
                 x: int,
                 y: int,
                 frame: Frame,
                 grid: Grid,
                 renderbox: RenderBox,
                 name: str = 'Player1',
                 batch: Batch = None,
                 debug: bool = False):
        # Player Sprite Select Related
        self.player_res_list = [
            PlayerImages.p1, PlayerImages.p2, PlayerImages.p3
        ]
        self.player_select = 0
        self.player_res = self.player_res_list[self.player_select]

        # Initialize Base Class
        super().__init__(x=x,
                         y=y,
                         res=self.player_res.jump_right,
                         frame=frame,
                         grid=grid,
                         renderbox=renderbox,
                         name=name,
                         batch=batch,
                         usage='dynamic',
                         is_anchor_x_centered=True)

        # Movement Related
        self.BASE_WALKING_SPEED = 200
        self.BASE_JUMPING_SPEED = 300
        self.vx = 0.0
        self.vy = 0.0
        self.facing = 'right'
        self.status = 'jumping'
        self.arrow_key_buffer = ArrowKeyBuffer()

        # Grid Related
        self.up_contact_obj_list = cast(List[GridObject], [])
        self.down_contact_obj_list = cast(List[GridObject], [])
        self.left_contact_obj_list = cast(List[GridObject], [])
        self.right_contact_obj_list = cast(List[GridObject], [])

        # Debug
        self.debug = debug
        self.ref_point = Circle(x=self.camera_x,
                                y=self.camera_y,
                                radius=5,
                                color=(255, 0, 0))
        self.ref_rect = Rectangle(x=self.camera_x,
                                  y=self.camera_y,
                                  width=self.width,
                                  height=self.height,
                                  color=(0, 0, 255))
        self.ref_rect.anchor_x = self.ref_rect.width // 2

    @property
    def x(self) -> int:
        return super().x

    @x.setter
    def x(self, x: int):
        super().x = x
        if self.debug:
            self.ref_point.x = self.camera_x
            self.ref_rect.x = self.camera_x

    @property
    def y(self) -> int:
        return super().y

    @y.setter
    def y(self, y: int):
        super().y = y
        if self.debug:
            self.ref_point.y = self.camera_y
            self.ref_rect.y = self.camera_y

    def change_player(self, idx: int):
        self.player_res = self.player_res_list[idx]
        self.player_select = idx
        self.update_sprite()

    def toggle_player(self):
        self.change_player(
            (self.player_select + 1) % len(self.player_res_list))

    def toggle_debug(self):
        self.debug = not self.debug
        self.grid.show_contacts = not self.grid.show_contacts

    def change_sprite(self, image):
        self.sprite.image = image
        if self.debug:
            self.ref_rect.width = self.sprite.width
            self.ref_rect.height = self.sprite.height
            self.ref_rect.anchor_x = self.ref_rect.width // 2

    def update_sprite(self):
        if self.status == 'idle':
            if self.facing == 'right':
                self.change_sprite(self.player_res.idle_right.img)
            elif self.facing == 'left':
                self.change_sprite(self.player_res.idle_left.img)
            else:
                raise Exception
        elif self.status == 'jumping':
            if self.facing == 'right':
                self.change_sprite(self.player_res.jump_right.img)
            elif self.facing == 'left':
                self.change_sprite(self.player_res.jump_left.img)
            else:
                raise Exception
        elif self.status == 'walking':
            if self.facing == 'right':
                self.change_sprite(self.player_res.walk_right_anim.animation)
            elif self.facing == 'left':
                self.change_sprite(self.player_res.walk_left_anim.animation)
            else:
                raise Exception
        else:
            raise Exception

    @property
    def is_idle(self) -> bool:
        return self.status == 'idle'

    @property
    def is_walking(self) -> bool:
        return self.status == 'walking'

    @property
    def is_jumping(self) -> bool:
        return self.status == 'jumping'

    def face(self, direction: str):
        if direction == 'right':
            self.facing = 'right'
            self.update_sprite()
        elif direction == 'left':
            self.facing = 'left'
            self.update_sprite()
        else:
            raise Exception

    def start_walking(self, direction: str):
        if direction == 'right':
            self.vx = self.BASE_WALKING_SPEED
            self.facing = 'right'
            self.status = 'walking'
            self.update_sprite()
        elif direction == 'left':
            self.vx = -self.BASE_WALKING_SPEED
            self.facing = 'left'
            self.status = 'walking'
            self.update_sprite()
        else:
            raise Exception

    def stop_walking(self):
        self.status = 'idle'
        self.vx = 0
        self.update_sprite()

    def start_jumping(self):
        self.status = 'jumping'
        self.vy = self.BASE_JUMPING_SPEED
        self.update_sprite()

    def start_falling(self):
        self.status = 'jumping'
        self.update_sprite()

    def stop_jumping(self):
        self.status = 'idle'
        self.vy = 0
        self.update_sprite()

    def draw(self):
        if self.debug:
            self.ref_point.draw()
            self.ref_rect.draw()
        super().draw()

    def move(self, dx: int, dy: int):
        player_grid_obj = self.grid.contained_obj_list.get_obj_from_name(
            self.name)
        other_renderable_objects = self.renderbox.get_all_renderable_objects(
            exclude_names=[self.name])
        other_renderable_names = [
            other_renderable_object.name
            for other_renderable_object in other_renderable_objects
        ]
        other_grid_objects = self.grid.contained_obj_list.get_objects(
            include_names=other_renderable_names)
        all_grid_objects = self.grid.contained_obj_list.get_objects()

        self.up_contact_obj_list = []
        self.down_contact_obj_list = []
        self.left_contact_obj_list = []
        self.right_contact_obj_list = []
        self.grid.reset_contacts()

        # Move X
        proposed_player_occupied_spaces = player_grid_obj.get_occupied_spaces(
            dx=dx)
        collision = False
        for proposed_player_occupied_space in proposed_player_occupied_spaces:
            for other_grid_object in other_grid_objects:
                if proposed_player_occupied_space in other_grid_object.occupied_spaces:
                    other_grid_object.is_in_contact = True
                    if dx > 0:
                        self.right_contact_obj_list.append(other_grid_object)
                    elif dx < 0:
                        self.left_contact_obj_list.append(other_grid_object)
                    else:
                        raise Error(
                            f'Player got stuck in object in x direction.')
                    collision = True
        if not collision:
            self.set_x(x=self.x + dx, fix_camera=True)
            self.grid.move(dx=-dx)
        else:
            if len(self.left_contact_obj_list) > 0:
                dx_adjustment = self.left_contact_obj_list[
                    0].x_right + 1 - self.x_left
                self.set_x(x=self.x + dx_adjustment, fix_camera=True)
                self.grid.move(dx=-dx_adjustment)
            elif len(self.right_contact_obj_list) > 0:
                dx_adjustment = self.right_contact_obj_list[
                    0].x_left - self.x_right
                self.set_x(x=self.x + dx_adjustment, fix_camera=True)
                self.grid.move(dx=-dx_adjustment)
            else:
                raise Exception

        # Move Y
        proposed_player_occupied_spaces = player_grid_obj.get_occupied_spaces(
            dy=dy)
        collision = False
        for proposed_player_occupied_space in proposed_player_occupied_spaces:
            for other_grid_object in other_grid_objects:
                if proposed_player_occupied_space in other_grid_object.occupied_spaces:
                    other_grid_object.is_in_contact = True
                    if dy > 0:
                        self.up_contact_obj_list.append(other_grid_object)
                    elif dy < 0:
                        self.down_contact_obj_list.append(other_grid_object)
                    else:
                        raise Error(
                            f'Player got stuck in object in y direction.')
                    collision = True
        if not collision:
            self.set_y(y=self.y + dy, fix_camera=True)
            self.grid.move(dy=-dy)
            self.start_falling()
        else:
            self.vy = 0
            if len(self.down_contact_obj_list) > 0:
                dy_adjustment = self.down_contact_obj_list[
                    0].y_top - self.y_bottom
                self.set_y(y=self.y + dy_adjustment, fix_camera=True)
                self.grid.move(dy=-dy_adjustment)

                if self.is_jumping:
                    self.stop_jumping()
                    if self.arrow_key_buffer.is_pressed:
                        self.start_walking(
                            direction=self.arrow_key_buffer.buffer[-1])
                    else:
                        self.vx = 0
            elif len(self.up_contact_obj_list) > 0:
                dy_adjustment = self.up_contact_obj_list[
                    0].y_bottom - self.y_top
                self.set_y(y=self.y + dy_adjustment, fix_camera=True)
                self.grid.move(dy=-dy_adjustment)
            else:
                raise Exception
Beispiel #6
0
class Game(pyglet.window.Window):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 窗口是否捕获鼠标
        self.exclusive = False
        # 玩家
        self.player = Player()
        # 拓展功能
        self.debug = {}
        self.debug['debug'] = False
        self.debug['enable'] = False
        self.debug['running'] = False
        # rotation = (水平角 x, 俯仰角 y)
        self.player['rotation'] = (0, 0)
        # 玩家所处的区域
        self.sector = None
        # 这个十字在屏幕中央
        self.reticle = None
        # 显示在 debug 区域的 info
        self._info_ext = []
        self._info_ext.append('pyglet' + pyglet.version)
        # 玩家可以放置的方块, 使用数字键切换
        self.inventory = ['grass', 'dirt', 'log', 'brick', 'leaf', 'plank', 'craft_table', 'glass']
        # 数字键列表
        self.num_keys = [
            key._1, key._2, key._3, key._4, key._5,
            key._6, key._7, key._8, key._9, key._0]
        # 这个标签在画布的上方显示
        self.label = {}
        self.label['top'] = pyglet.text.Label('',
            x=2, y=self.height - 5, width=self.width // 2, multiline=True,
            anchor_x='left', anchor_y='top', font_size=12, font_name='minecraftia')
        self.is_init = True
        # 设置图标
        self.set_icon(image.load(os.path.join(path['texture'], 'icon.png')))
        # 这个标签在画布正中偏上显示
        self.label['center'] = pyglet.text.Label('',
            x=self.width // 2, y=self.height // 2 + 50, anchor_x='center',
            anchor_y='center', font_name='minecraftia')
        # 死亡信息
        self.die_info = pyglet.text.Label('', color=(255, 255, 255, 255),
            x=self.width // 2, y=self.height // 2, anchor_x='center',
            anchor_y='center', font_size=24, font_name='minecraftia')
        # 这个标签在画布正中偏下显示
        self.label['actionbar'] = pyglet.text.Label('',
                x=self.width // 2, y=self.height // 2 - 100, anchor_x='center', anchor_y='center', font_name='minecraftia')
        # 加载窗口
        self.loading = Loading()
        # 覆盖屏幕的矩形
        self.full_screen = Rectangle(0, 0, self.width, self.height)
        # 聊天区
        self.dialogue = Dialogue()
        # 将 self.upgrade() 方法每 1.0 / TICKS_PER_SEC 调用一次, 它是游戏的主事件循环
        pyglet.clock.schedule_interval(self.update, 1.0 / TICKS_PER_SEC)
        # 检测玩家是否应该死亡
        pyglet.clock.schedule_interval(self.check_die, 1.0 / TICKS_PER_SEC)
        # 每10秒更新一次方块数据
        pyglet.clock.schedule_interval(self.update_status, 0.1)
        # 每30秒保存一次进度
        pyglet.clock.schedule_interval(self.save, 30.0)
        # 天空颜色变换
        pyglet.clock.schedule_interval(change_sky_color, 7.5)
        log_info('welcome %s' % player['name'])
        for lib in libs:
            if hasattr(lib, 'init'):
                lib.init()

    def can_place(self, block, position):
        """
        检测坐标是否能够放置方块

        :param: block 方块坐标
        :param: position 玩家坐标
        """
        if block != normalize(position):
            position = position[0], position[1] - 1, position[2]
            if block != normalize(position):
                return True
            else:
                return False
        else:
            return False

    def add_info_ext(self, s):
        self._info_ext.append(s)

    def check_die(self, dt):
        """
        这个函数被 pyglet 计时器反复调用

        :param: dt 距上次调用的时间
        """
        return
        if not self.player['die']:
            if self.player['position'][1] < -64:
                self.player['die_reason'] = get_lang('game.text.die.fall_into_void') % player['name']
                self.player['die'] = True
                self.dialogue.add_dialogue(self.player['die_reason']) 
            elif self.player['position'][1] > 512:
                self.player['die_reason'] = get_lang('game.text.die.no_oxygen') % player['name']
                self.player['die'] = True
            if self.player['die']:
                log_info('%s die: %s' % (player['name'], self.player['die_reason']))
                self.dialogue.add_dialogue(self.player['die_reason'])
                self.set_exclusive_mouse(False)

    def init_player(self):
        # 初始化玩家
        self.hud = {}
        # E 键打开的背包
        self.hud['bag'] = Bag()
        # 生命值
        self.hud['heart'] = Heart(batch=self.world.batch2d)
        # 饥饿值
        self.hud['hunger'] = Hunger(batch=self.world.batch2d)
        # 工具栏
        self.hud['hotbar'] = HotBar()
        self.hud['hotbar'].set_index(self.block)
        self.hud['hotbar'].set_all(self.inventory)
        # 经验条
        self.hud['xpbar'] = XPBar()
        # 菜单
        self.menu = {}
        self.menu['pause'] = PauseMenu(self)
        self.menu['pause'].frame.enable(True)
        self.menu['chat'] = Chat(self)
        
    def save(self, dt):
        """
        这个函数被 pyglet 计时器反复调用

        :param: dt 距上次调用的时间
        """
        archiver.save_block(self.name, self.world.change)
        archiver.save_player(self.name, self.player['position'], self.player['respawn_position'],
                normalize(self.player['rotation']), self.player['block'])
        archiver.save_info(self.name, 0, get_time())

    def set_exclusive_mouse(self, exclusive):
        # 如果 exclusive 为 True, 窗口会捕获鼠标. 否则忽略之
        super(Game, self).set_exclusive_mouse(exclusive)
        self.exclusive = exclusive 
        
    def set_name(self, name):
        # 设置游戏存档名
        self.name = name
        self.world = World(name)
        # self.world_gen_thread = Thread(target=self.world.init_world, name='WorldGen')
        # self.world_gen_thread.start()
        # 读取玩家位置和背包
        data = archiver.load_player(self.name)
        self.player['position'] = data['position']
        self.player['respawn_position'] = data['respawn']
        if len(self.player['position']) != 3:
            if archiver.load_info(self.name)['type'] == 'flat':
                self.player['position'] = self.player['respawn_position'] = (0, 8, 0)
            else:
                self.player['position'] = self.player['respawn_position'] = (0, self.world.simplex.noise2d(x=0, y=0) * 5 + 13, 0)
        self.sector = sectorize(self.player['position'])
        self.player['rotation'] = tuple(data['rotation'])
        self.block = data['now_block']
        # 读取世界数据
        self.world_info = archiver.load_info(self.name)
        set_time(self.world_info['time'])

    def set_cursor(self, cursor=None):
        # 设置光标形状
        if cursor is None:
            self.set_mouse_cursor(None)
        else:
            self.set_mouse_cursor(self.get_system_mouse_cursor(cursor))

    def run_command(self, s):
        # 运行命令
        command = s.split(' ')[0]
        if command not in commands:
            self.dialogue.add_dialogue('Command not found')
        else:
            try:
                cmd = commands[command](self, self.player['position'], s)
            except ValueError:
                pass
            else:
                cmd.run() 

    def update(self, dt):
        """
        这个方法被 pyglet 计时器反复调用

        :param: dt 距上次调用的时间
        """
        self.world.process_queue()
        self.dialogue.update()
        sector = sectorize(self.player['position'])
        if sector != self.sector:
            self.world.change_chunk(self.sector, sector)
            if self.sector is None:
                self.world.process_entire_queue()
            self.sector = sector
        m = 8
        dt = min(dt, 0.2)
        for _ in range(m):
            self._update(dt / m) 

    def update_status(self, dt):
        # 这个函数定时改变世界状态
        for sector in self.world.sectors.values():
            blocks = random.choices(sector, k=3)
            for block in blocks:
                self.world.get(block).on_ticking(self, block)
 
    def _update(self, dt):
        """
        update() 方法的私有实现, 刷新 
        
        :param: dt 距上次调要用的时间
        """
        # 移动速度
        if self.player['flying']:
            speed = FLYING_SPEED
        elif self.player['running'] or self.debug['running']:
            speed = RUNNING_SPEED
        elif self.player['stealing']:
            speed = STEALING_SPEED
        else:
            speed = WALKING_SPEED
        # 一个游戏刻玩家经过的距离
        d = dt * speed
        dx, dy, dz = self.player.get_motion_vector()
        # 玩家新的位置
        dx, dy, dz = dx * d, dy * d, dz * d
        # 重力
        if not self.player['die']:
            if not self.player['flying']:
                self.player['dy'] -= dt * GRAVITY
                self.player['dy'] = max(self.player['dy'], -TERMINAL_VELOCITY)
                dy += self.player['dy'] * dt
            if not self.player['in_hud']:
                # 碰撞检测
                x, y, z = self.player['position']
                if self.player['gamemode'] != 1:
                    x, y, z = self.player.collide((x + dx, y + dy, z + dz))
                else:
                    x, y, z = x + dx, y + dy, z + dz
                self.player['position'] = (x, y, z) 

    def on_close(self):
        # 当玩家关闭窗口时调用
        archiver.save_window(self.width, self.height)
        pyglet.app.exit()

    def on_mouse_press(self, x, y, button, modifiers):
        """
        当玩家按下鼠标按键时调用
  
        :param: x, y 鼠标点击时的坐标, 如果被捕获的话总是在屏幕中央
        :param: button 哪个按键被按下: 1 = 左键, 4 = 右键
        :param: modifiers 表示单击鼠标按钮时按下的任何修改键的数字
        """
        for menu in self.menu.values():
            if menu.frame.on_mouse_press(x, y, button, modifiers):
                return
        self.player.on_mouse_press(x, y, button, modifiers)
        
    def on_mouse_release(self, x, y, button, modifiers):
        for menu in self.menu.values():
            menu.frame.on_mouse_release(x, y, button, modifiers)

    def on_mouse_motion(self, x, y, dx, dy):
        """
        当玩家移动鼠标时调用

        :param: x, y 鼠标点击时的坐标, 如果被捕获的话它们总是在屏幕中央
        :param: dx, dy 鼠标移动的距离
        """
        for menu in self.menu.values():
            menu.frame.on_mouse_motion(x, y, dx, dy)
        self.player.on_mouse_motion(x, y, dx, dy)

    def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
        """
        当鼠标滚轮滚动时调用

        :param: scroll_x, scroll_y 鼠标滚轮滚动(scroll_y 为1时向上, 为-1时向下)
        """
        self.player.on_mouse_scroll(x, y, scroll_x, scroll_y)

    def on_key_press(self, symbol, modifiers):
        """
        当玩家按下一个按键时调用

        :param: symbol 按下的键
        :param: modifiers 同时按下的修饰键
        """
        self.player.on_key_press(symbol, modifiers)

    def on_key_release(self, symbol, modifiers):
        """
        当玩家释放一个按键时调用
        
        :param: symbol 释放的键
        """
        self.player.on_key_release(symbol, modifiers)
        

    def on_resize(self, width, height):
        # 当窗口被调整到一个新的宽度和高度时调用
        # 标签
        self.label['top'].x = 2
        self.label['top'].y = self.height - 5
        self.label['top'].width = self.width // 2
        self.label['center'].x = self.width // 2
        self.label['center'].y = self.height // 2 + 50
        self.die_info.x = self.width // 2
        self.die_info.y =self.height // 2
        self.label['actionbar'].x = self.width // 2
        self.label['actionbar'].y = self.height // 2 - 100
        # 加载窗口
        self.loading.resize(self.width, self.height)
        # 窗口中央的十字线
        if self.reticle:
            self.reticle.delete()
        x, y = self.width // 2, self.height // 2
        n = 12
        self.reticle = pyglet.graphics.vertex_list(4,
            ('v2i', (x - n, y, x + n, y, x, y - n, x, y + n))
        )
        # 覆盖屏幕的矩形
        self.full_screen.position = (0, 0)
        self.full_screen.width = self.width
        self.full_screen.height = self.height
        # 聊天区
        self.dialogue.resize(self.width, self.height)
        # HUD
        # 在第一次调用该函数时, 所有存储 HUD 的变量都没有定义
        if not self.is_init:
            self.hud['bag'].resize(self.width, self.height)
            self.hud['heart'].resize(self.width, self.height)
            self.hud['hunger'].resize(self.width, self.height)
            self.hud['hotbar'].resize(self.width, self.height)
            self.hud['xpbar'].resize(self.width, self.height)
            for menu in self.menu.values():
                menu.frame.on_resize(width, height)

    def set_2d(self):
        # 使 OpenGL 绘制二维图形
        width, height = self.get_size()
        glDisable(GL_DEPTH_TEST)
        viewport = self.get_viewport_size()
        glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, max(1, width), 0, max(1, height), -1, 1)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def set_3d(self):
        # 使 OpenGL 绘制三维图形
        width, height = self.get_size()
        glEnable(GL_DEPTH_TEST)
        viewport = self.get_viewport_size()
        glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(self.player['fov'], width / float(height), 0.1, 60.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        x, y = self.player['rotation']
        glRotatef(x, 0, 1, 0)
        glRotatef(-y, math.cos(math.radians(x)), 0, math.sin(math.radians(x)))
        x, y, z = self.player['position']
        glTranslatef(-x, -y + (0.1 if self.player['stealing'] else 0), -z)

    def on_draw(self):
        # 当 pyglet 在画布上绘图时调用
        self.clear()
        if not self.is_init:
            self.set_3d()
            glColor3d(1, 1, 1)
            self.world.draw()
            self.draw_focused_block()
            self.set_2d()
            if not self.player['die'] and not self.player['hide_hud']:
                self.world.batch2d.draw()
                self.hud['hotbar'].draw()
                self.hud['xpbar'].draw()
                self.draw_reticle()
                if not self.player['in_hud'] and not self.exclusive:
                    self.full_screen.color = (0, 0, 0)
                    self.full_screen.opacity = 100
                    self.full_screen.draw()
                    if not self.player['in_chat']:
                        self.menu['pause'].frame.draw()
                    else:
                        self.menu['chat'].frame.draw()
                if self.player['in_hud'] or not self.exclusive:
                    self.full_screen.color = (0, 0, 0)
                    self.full_screen.opacity = 100
                    self.full_screen.draw()
                    if self.player['show_bag']:
                        self.hud['bag'].draw()
            elif self.player['die']:
                self.full_screen.color = (200, 0, 0)
                self.full_screen.opacity = 100
                self.full_screen.draw()
        self.set_2d()
        if not self.player['hide_hud']:
            self.draw_label()
        if self.is_init:
            self.world.init_world()
            self.init_player()
            self.is_init = False

    def on_text(self, text):
        for menu in self.menu.values():
            menu.frame.on_text(text)

    def on_text_motion(self, motion):
        for menu in self.menu.values():
            menu.frame.on_text_motion(motion)

    def on_text_motion_select(self, motion):
        for menu in self.menu.values():
            menu.frame.on_text_motion_select(motion)

    def draw_focused_block(self):
        # 在十字线选中的方块绘制黑边
        vector = self.player.get_sight_vector()
        block = self.world.hit_test(self.player['position'], vector)[0]
        if block and self.player['gamemode'] != 1:
            x, y, z = block
            vertex_data = cube_vertices(x, y, z, 0.5001)
            glColor4f(1.0, 1.0, 1.0, 0.2)
            glDisable(GL_CULL_FACE)
            pyglet.graphics.draw(24, GL_QUADS, ('v3f/static', vertex_data))
            glEnable(GL_CULL_FACE)
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    def draw_label(self):
        if not self.is_init:
            if self.exclusive:
                self.dialogue.draw()
            if self.player['die']:
                # 玩家死亡
                self.die_info.text = get_lang('game.text.die')
                self.label['actionbar'].text = self.player['die_reason']
                self.die_info.draw()
                self.label['actionbar'].draw()
            elif self.debug['debug'] and self.exclusive:
                x, y, z = self.player['position']
                rx, ry = self.player['rotation']
                mem = round(psutil.Process(os.getpid()).memory_full_info()[0] / 1048576, 2)
                fps = pyglet.clock.get_fps()
                info_ext = []
                self.label['top'].text = '\n'.join(get_lang('game.text.debug')) % (VERSION['str'],
                        ', '.join(self._info_ext), x, y, z, rx, ry, mem, fps)
                self.label['top'].draw()
        else:
            # 初始化屏幕
            self.loading.draw()

    def draw_reticle(self):
        # 在屏幕中央画十字线
        if not self.is_init and not self.player['in_hud'] and self.exclusive:
            glColor3f(1.0, 1.0, 1.0)
            glLineWidth(3.0)
            self.reticle.draw(GL_LINES)
            glLineWidth(1.0)
Beispiel #7
0
class DialogueEntry(Widget):

    def __init__(self):
        win_width, win_height = get_size()
        self.batch = Batch()
        self._doc = pyglet.text.document.UnformattedDocument('')
        self._doc.set_style(0, len(self._doc.text), dict(color=(255, 255, 255, 255)))
        font = self._doc.get_font()
        self.text_height = font.ascent - font.descent
        self.pad = 2
        self._outline = Rectangle(5 - self.pad, 20 - self.pad,
                get_size()[0] + self.pad - 5, self.text_height + self.pad, color=(0, 0, 0))
        self._outline.opacity = 150
        self._layout = IncrementalTextLayout(self._doc, get_size()[0] + self.pad - 5, self.text_height,
                multiline=False, batch=self.batch)
        self._caret = Caret(self._layout, color=(255, 255, 255))
        self._caret.visible = False
        self._layout.x = 5
        self._layout.y = 20
        self._focus = False
        self._press = False
        self.last_char = ''
        super().__init__(5, 20, get_size()[0] + self.pad - 5, self.text_height)

    def draw(self):
        self._outline.draw()
        self.batch.draw()

    def text(self, text):
        self._doc.text = text

    def _set_focus(self, value):
        self._focus = value
        self._caret.visible = value

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if self._focus:
            self._caret.on_mouse_drag(x, y, dx, dy, buttons, modifiers)

    def on_mouse_motion(self, x, y, dx, dy):
        if self.check_hit(x, y):
            get_game().set_cursor('text')
        else:
            get_game().set_cursor()

    def on_mouse_press(self, x, y, buttons, modifiers):
        if self.check_hit(x, y):
            self._press = True
            self._set_focus(True)
            self._caret.on_mouse_press(x, y, buttons, modifiers)
        else:
            self._set_focus(False)

    def on_mouse_release(self, x, y, buttons, modifiers):
        if self._press:
            self._press = False

    def on_resize(self, width, height):
        self.width = width - self.pad - 5
        self._outline.width = width - self.pad - 5
        self._layout.width = width - self.pad - 5

    def on_text(self, text):
        if text == self.last_char:
            self.last_char = ''
            return
        else:
            self.last_char = text
        if self._focus:
            if text in ('\r', '\n'):
                self.dispatch_event('on_commit', self._layout.document.text)
                self._set_focus(False)
                return
            self._caret.on_text(text)

    def on_text_motion(self, motion):
        if self._focus:
            self._caret.on_text_motion(motion)

    def on_text_motion_select(self, motion):
        if self._focus:
            self._caret.on_text_motion_select(motion)

    def on_commit(self, text):
        pass
Beispiel #8
0
class DialogueEntry(Widget):
    def __init__(self):
        win_width, win_height = get_size()
        self.batch = Batch()
        self._doc = pyglet.text.document.UnformattedDocument('')
        self._doc.set_style(0, len(self._doc.text),
                            dict(color=(255, 255, 255, 255)))
        font = self._doc.get_font()
        self.text_height = font.ascent - font.descent
        self.pad = 2
        self._outline = Rectangle(5,
                                  5 + self.pad,
                                  get_size()[0] - self.pad - 10,
                                  self.text_height + self.pad,
                                  color=(0, 0, 0))
        self._outline.opacity = 150
        self._layout = IncrementalTextLayout(self._doc,
                                             get_size()[0] - 14,
                                             self.text_height,
                                             multiline=False,
                                             batch=self.batch)
        self._caret = Caret(self._layout, color=(255, 255, 255))
        self._caret.visible = False
        self._layout.x = 5
        self._layout.y = 5 + self.pad
        self._focus = False
        self._press = False
        self.last_press = [0, 0]
        super().__init__(5, 5 + self.pad,
                         get_size()[0] - self.pad - 10,
                         self.text_height + self.pad)

    def draw(self):
        self._outline.draw()
        self.batch.draw()

    def text(self, text):
        self._doc.text = text

    def _set_focus(self, value):
        self._focus = value
        self._caret.visible = value

    def on_key_press(self, symbol, modifiers):
        if symbol == key.PAGEUP:
            if self.last_press[0] == 1:
                self.last_press[0] = 0
                return
            else:
                self.last_press[0] = 1
                self.text('')
                self.text(
                    get_game().dialogue.history[get_game().dialogue.pointer])
                if get_game().dialogue.pointer != 0:
                    get_game().dialogue.pointer -= 1
        elif symbol == key.PAGEDOWN:
            if self.last_press[1] == 1:
                self.last_press[1] = 0
                return
            else:
                self.last_press[1] = 1
                if get_game().dialogue.pointer != len(
                        get_game().dialogue.history) - 1:
                    get_game().dialogue.pointer += 1
                    self.text('')
                    self.text(get_game().dialogue.history[
                        get_game().dialogue.pointer])
                else:
                    self.text('')

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if self._focus:
            self._caret.on_mouse_drag(x, y, dx, dy, buttons, modifiers)

    def on_mouse_motion(self, x, y, dx, dy):
        if self.check_hit(x, y):
            get_game().set_cursor('text')
        else:
            get_game().set_cursor()

    def on_mouse_press(self, x, y, buttons, modifiers):
        if self.check_hit(x, y):
            self._press = True
            self._set_focus(True)
            self._caret.on_mouse_press(x, y, buttons, modifiers)
        else:
            self._set_focus(False)

    def on_mouse_release(self, x, y, buttons, modifiers):
        if self._press:
            self._press = False

    def on_resize(self, width, height):
        self.width = width - self.pad - 10
        self._outline.width = width - self.pad - 10
        self._layout.width = width - self.pad - 10

    def on_text(self, text):
        if self._focus:
            if text in ('\r', '\n'):
                self.dispatch_event('on_commit', self._layout.document.text)
                self._set_focus(False)
                return
            self._caret.on_text(text)

    def on_text_motion(self, motion):
        if self._focus:
            self._caret.on_text_motion(motion)

    def on_text_motion_select(self, motion):
        if self._focus:
            self._caret.on_text_motion_select(motion)

    def on_commit(self, text):
        pass
Beispiel #9
0
class TextEntry(Widget):
    def __init__(self, text, color, x, y, width):
        win_width, win_height = get_size()
        self.batch = Batch()
        self._doc = pyglet.text.document.UnformattedDocument(text)
        self._doc.set_style(
            0, len(self._doc.text),
            dict(color=(255, 255, 255, 255), font_name='minecraftia'))
        font = self._doc.get_font()
        height = font.ascent - font.descent
        pad = 2
        self._outline = Rectangle(x - pad,
                                  y - pad,
                                  width + pad,
                                  height + pad,
                                  color=color[:3])
        self._outline.opacity = color[-1]
        self._layout = IncrementalTextLayout(self._doc,
                                             width,
                                             height,
                                             multiline=False,
                                             batch=self.batch)
        self._caret = Caret(self._layout, color=(255, 255, 255))
        self._caret.visible = False
        self._layout.x = x
        self._layout.y = y
        self._focus = False
        self._press = False
        super().__init__(x, y, width, height)
        self.last_char = ''

    def draw(self):
        self._outline.draw()
        self.batch.draw()

    def text(self, text):
        self._doc.text = text

    def _set_focus(self, value):
        self._focus = value
        self._caret.visible = value

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if self._focus:
            self._caret.on_mouse_drag(x, y, dx, dy, buttons, modifiers)

    def on_mouse_press(self, x, y, buttons, modifiers):
        if self.check_hit(x, y):
            self._press = True
            self._set_focus(True)
            self._caret.on_mouse_press(x, y, buttons, modifiers)
        else:
            self._set_focus(False)

    def on_mouse_release(self, x, y, buttons, modifiers):
        if self._press:
            self._press = False

    def on_text(self, text):
        if text == self.last_char:
            self.last_char = ''
            return
        else:
            self.last_char = text
        if self._focus:
            if text in ('\r', '\n'):
                self.dispatch_event('on_commit', self._layout.document.text)
                self._set_focus(False)
                return
            self._caret.on_text(text)

    def on_text_motion(self, motion):
        if self._focus:
            self._caret.on_text_motion(motion)

    def on_text_motion_select(self, motion):
        if self._focus:
            self._caret.on_text_motion_select(motion)

    def on_commit(self, text):
        pass
Beispiel #10
0
class ItemSlot(Widget):
    def __init__(self, x, y, index=None):
        y = get_size()[1] - y
        super().__init__(x, y, 32, 32)
        self._index = index
        self._on = False
        self._item = self._item_name = None
        self._state = {'set': True, 'get': True}
        self._rect = Rectangle(self.x,
                               get_size()[1] - self.y - 32,
                               32,
                               32,
                               color=(255, ) * 3)
        self._rect.opacity = 100

    def _update(self):
        self._rect.position = self.x, get_size()[1] - self.y - 32
        if self._item is not None:
            self._item.position = self.x, get_size()[1] - self.y - 32

    def on_mouse_motion(self, x, y, dx, dy):
        if self.check_hit(x, get_size()[1] - y):
            self._on = True
        else:
            self._on = False

    def on_mouse_press(self, x, y, buttons, modifiers):
        if not self._on:
            return
        if buttons == mouse.LEFT:
            i1, i2 = self._item_name, get_game().get_active_item()
            if all(self._state.values()):
                self.set_item(i2)
                get_game().set_active_item(i1)
            elif self._state['set']:
                if get_game().get_active_item() is not None:
                    self.set_item(i2)
                    get_game().set_active_item(i1)
            elif self._state['get']:
                if get_game().get_active_item() is None:
                    self.set_item()
                    get_game().set_active_item(i1)
        elif buttons == mouse.MIDDLE:
            get_game().set_active_item(self._item_name)
        if hasattr(self, 'on_change'):
            self.on_change(buttons, modifiers, self._index)

    def set_item(self, item=None):
        if item is None:
            self._item_name = self._item = None
        else:
            self._item_name = item
            self._item = Sprite(get_block_icon(blocks[item], 32),
                                x=self.x,
                                y=get_size()[1] - self.y - 32)

    def set_state(self, set_=True, get=True):
        self._state['set'] = set_
        self._state['get'] = get

    def get_item(self):
        return self._item_name

    def draw(self):
        if self._item is not None:
            self._item.draw()
        if self._on:
            self._rect.draw()
Beispiel #11
0
class Game():
    def __init__(self):
        self.batch = Batch()
        self.background = Rectangle(0, 0, 0, 0)
        self.window = Window()
        self.window.push_handlers(self)
        self.on_resize(self.window.width, self.window.height)
        clock.schedule_interval(self.update, 1 / 60)
        clock.schedule_interval(self.log, 1)
        self.sounds = {
            'fail': media.load('resources/failure.mp3', streaming=False),
            'jump': media.load('resources/jump.wav', streaming=False),
            'score': media.load('resources/score.wav', streaming=False),
        }
        self.reset()

    def log(self, delta):
        logging.info('Current speed: {}'.format(self.speed))
        logging.info('Current score: {}'.format(self.points))

    def reset(self):
        self.pipes = []
        self.points = 0
        self.speed = 2
        self.player = Player(batch=self.batch)
        self.create_pipe()
        self.create_pipe(x=(Grid.columns / 2) + (Pipe.WIDTH / 2))

    def fail(self):
        self.sounds['fail'].play()
        self.reset()

    def create_pipe(self, *args, **kwargs):
        kwargs['batch'] = kwargs.get('batch', self.batch)
        self.pipes.append(Pipe(*args, **kwargs))

    def update(self, delta):
        self.player.update(delta)
        self.speed += delta * 0.1
        delta_x = delta * Grid.x() * self.speed
        if self.player.is_offscreen():
            self.fail()
            return
        for pipe in self.pipes:
            pipe.scroll(delta_x)
            if pipe.is_offscreen():
                self.pipes.remove(pipe)
                self.create_pipe()
            if pipe.collides(self.player.center):
                self.fail()
            if self.player.cleared(pipe):
                self.score()

    def score(self):
        self.sounds['score'].play()
        self.points += 1

    def jump(self):
        logging.info('jumping')
        self.sounds['jump'].play()
        self.player.jump()

    def on_key_press(self, symbol, modifiers):
        self.jump()

    def on_mouse_press(self, x, y, button, modifiers):
        self.jump()

    def on_draw(self):
        self.window.clear()
        self.background.draw()
        self.batch.draw()

    def on_resize(self, width, height):
        Grid.update_factor(width, height)
        self.background.width, self.background.height = width, height
        if getattr(self, 'player', None):
            self.player.resize()
def on_draw():
    global pos
    #window.clear()
    #main_batch.draw()
    rec = Rectangle(pos[0], pos[1], 1, 1)
    rec.draw()