鱼C论坛

 找回密码
 立即注册
查看: 116|回复: 9

[已解决]cocos2d python label显示错误

[复制链接]
发表于 2024-11-27 18:24:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
玩家和电脑轮流取子游戏,从右侧取子,取得最左侧子为胜。取子过程显示相应标贴。
过程中不显示:‘轮到玩家’,‘玩家取子数’,‘玩家胜利’。
# coding: utf-8
import cocos
from cocos.scene import Scene
from cocos.director import director
import pyglet
import random
import time

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
        super().__init__(128, 128, 128, 128)
        cocos.layer.Layer.is_event_handler = True
        self.label = cocos.text.Label('轮到玩家', font_name='kaiti', font_size=30, color=(255, 0, 0, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label.position = (320, 80)
        self.add(self.label)
        self.label1 = cocos.text.Label('', font_name='kaiti', font_size=30, color=(0, 0, 255, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label1.position = (320, 380)
        self.add(self.label1)
        self.player = 0
        self.blocks = {}
        for i in range(18):
            bo = cocos.sprite.Sprite('block.png')
            bo.position = 40+32*i, 240
            self.add(bo)
            self.blocks[i] = bo

    def on_mouse_press(self, x, y, button, modifiers):
        if self.player == 0:
            self.label.element.text = '轮到玩家'
            if button == pyglet.window.mouse.LEFT:
                x=round((x-40)/32)
                y=round((y-240)/240)
                print('x=',x)
                ss = len(self.blocks) - x
                keys_to_remove = [key for key in self.blocks if key >= x]
                for key in keys_to_remove:
                    self.remove(self.blocks[key])
                    del self.blocks[key]
            self.label1.element.text =f"玩家取数:{ss}"
            print(f"玩家取数:{ss}")
            print('len(self.blocks)=',len(self.blocks))
            if len(self.blocks)==0:
                self.label.element.text = '玩家胜利!'

            time.sleep(1)
            self.player =1
            computer_move(self)

def computer_move(self):
    if self.player== 1:
        self.label.element.text = '轮到电脑'
        k = random.randint(1, 3)
        keys_to_remove = [key for key in self.blocks if key >=len(self.blocks)-k]
        for key in keys_to_remove:
            self.remove(self.blocks[key])
            del self.blocks[key]
        self.label1.element.text = f'电脑取数:{k}'
        print("电脑取数:" + str(k))
        print('len(self.blocks)=', len(self.blocks))
        if len(self.blocks) == 0:
            self.label.element.text = '电脑胜利!'
        self.player = 0

def main():
    director.init()
    scene = Scene()
    scene.add(GameLayer(), z=0)
    director.run(scene)

if __name__ == "__main__":
    main()
最佳答案
2024-12-10 17:51:53
ydwb 发表于 2024-12-10 17:51
将self.label.element.text = '轮到玩家'  位置调整后 ...


感谢你提供的代码,根据你的描述,问题的关键在于确保游戏在有人胜利时立即返回而不继续执行游戏循环。在代码中,当电脑胜利时,需要通过 `return` 立即终止当前逻辑,以防止出现不合理的状态更新。

从你提供的更新代码来看,你已在“玩家胜利”和“电脑胜利”后正确地插入了 `return` 语句。这使得程序在达到胜利条件时终止当前执行的函数,从而避免了后续不必要的状态更新。

### 确保逻辑完整性的代码片段:
if len(self.blocks) == 0:
    self.label.element.text = '玩家胜利!'
    return
if len(self.blocks) == 0:
    self.label.element.text = '电脑胜利!'
    return

通过确保在胜利条件判断之后立即 `return`,你可以有效地终止当前函数,停止后续代码的执行。看起来你的调整已经解决了这个问题。如果在实现过程中还有其他问题,请告诉我!我会很乐意帮助你。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-11-27 18:31:24 | 显示全部楼层
你好!你遇到了在 Cocos2d 中关于标签显示的问题。根据你的代码,有几个地方需要修改:

1. 修正 `self.blocks` 的使用:你用于在列表中存储`block`但代码中有误。

2. 修正 `keys_to_remove` 的使用:这个变量没有被正确初始化。

我对你的代码做了一些修改,确保标签显示正确。
# coding: utf-8
import cocos
from cocos.scene import Scene
from cocos.director import director
import pyglet
import random
import time

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
        super().__init__(128, 128, 128, 128)
        cocos.layer.Layer.is_event_handler = True
        self.label = cocos.text.Label('轮到玩家', font_name='kaiti', font_size=30, color=(255, 0, 0, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label.position = (320, 80)
        self.add(self.label)
        self.label1 = cocos.text.Label('', font_name='kaiti', font_size=30, color=(0, 0, 255, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label1.position = (320, 380)
        self.add(self.label1)
        self.player = 0
        self.blocks = []  # 使用列表来存储精灵
        for i in range(18):
            bo = cocos.sprite.Sprite('block.png')
            bo.position = 40+32*i, 240
            self.add(bo)
            self.blocks.append(bo)  # 将精灵添加到列表

    def on_mouse_press(self, x, y, button, modifiers):
        if self.player == 0:
            self.label.element.text = '轮到玩家'
            if button == pyglet.window.mouse.LEFT:
                x=round((x-40)/32)
                ss = len(self.blocks) - x
                keys_to_remove = self.blocks[x:]  # 需要移除的块

                for bo in keys_to_remove:
                    self.remove(bo)
                    self.blocks.remove(bo)  # 从列表中删除

            self.label1.element.text = f"玩家取数:{ss}"
            print(f"玩家取数:{ss}")
            print('len(self.blocks)=', len(self.blocks))
            if len(self.blocks) == 0:
                self.label.element.text = '玩家胜利!'

            time.sleep(1)
            self.player = 1
            self.computer_move()

    def computer_move(self):
        if self.player == 1:
            self.label.element.text = '轮到电脑'
            k = random.randint(1, 3)
            keys_to_remove = self.blocks[-k:]  # 移除电脑取的块
            for bo in keys_to_remove:
                self.remove(bo)
                self.blocks.remove(bo)  # 从列表中删除

            self.label1.element.text = f'电脑取数:{k}'
            print("电脑取数:" + str(k))
            print('len(self.blocks)=', len(self.blocks))
            if len(self.blocks) == 0:
                self.label.element.text = '电脑胜利!'
            self.player = 0

def main():
    director.init()
    scene = Scene()
    scene.add(GameLayer(), z=0)
    director.run(scene)

if __name__ == "__main__":
    main()

主要修改:

- 在 `__init__` 中将 `self.blocks` 设置为列表并使用 `append` 方法添加精灵。
- 修正 `keys_to_remove` 初始化,将其与应该被移除的对象对应。
- 在 `remove()` 方法后需要把元素从 `self.blocks` 列表中删除。

这样你的标签应该能正确显示了。如果还有任何问题,欢迎继续提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-27 19:08:16 | 显示全部楼层
问题依旧,过程中不显示:‘轮到玩家’,‘玩家取子数’,‘玩家胜利’。
即使玩家一次全部取完,应该是‘玩家胜利’,但仍显示‘电脑胜利’。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-27 19:08:53 | 显示全部楼层
ydwb 发表于 2024-11-27 19:08
问题依旧,过程中不显示:‘轮到玩家’,‘玩家取子数 ...


抱歉之前的回答没有解决你的问题。我们重新分析代码,并确保标签的文本正确更新。以下是可能导致问题的几个地方,以及如何修复它们:

1. **标签没有正确更新的问题**:
   - 确保标签的 `element.text` 属性在正确的位置进行更新。
   - 每次更新标签内容时,确保上下文正确,比如在玩家取走所有块时,应立即显示“玩家胜利”。

2. **胜利判断的问题**:
   - 在取子后立即检查剩余块数,并判断胜利条件。

请试试以下修改后的代码:
# coding: utf-8
import cocos
from cocos.scene import Scene
from cocos.director import director
import pyglet
import random
import time

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
        super().__init__(128, 128, 128, 128)
        cocos.layer.Layer.is_event_handler = True
        self.label = cocos.text.Label('', font_name='kaiti', font_size=30, color=(255, 0, 0, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label.position = (320, 80)
        self.add(self.label)
        self.label1 = cocos.text.Label('', font_name='kaiti', font_size=30, color=(0, 0, 255, 255),
                                       anchor_x="center",
                                       anchor_y="center")
        self.label1.position = (320, 380)
        self.add(self.label1)
        self.player = 0
        self.blocks = []  # 改为列表存储精灵
        for i in range(18):
            bo = cocos.sprite.Sprite('block.png')
            bo.position = 40 + 32 * i, 240
            self.add(bo)
            self.blocks.append(bo)  # 将精灵添加到列表

    def on_mouse_press(self, x, y, button, modifiers):
        if self.player == 0:
            self.label.element.text = '轮到玩家'
            if button == pyglet.window.mouse.LEFT:
                x = round((x - 40) / 32)
                ss = len(self.blocks) - x
                if ss > 0:  # 确保有足够的块供玩家取
                    keys_to_remove = self.blocks[-ss:]  # 取玩家指定数量的块

                    for bo in keys_to_remove:
                        self.remove(bo)
                        self.blocks.remove(bo)  # 从列表中删除

                    self.label1.element.text = f"玩家取数:{ss}"
                    print(f"玩家取数:{ss}")
                    print('len(self.blocks)=', len(self.blocks))
                    
                    if len(self.blocks) == 0:
                        self.label.element.text = '玩家胜利!'
                        return  # 玩家胜利后直接返回

                time.sleep(1)
                self.player = 1
                self.computer_move()

    def computer_move(self):
        if self.player == 1:
            self.label.element.text = '轮到电脑'
            k = random.randint(1, min(3, len(self.blocks)))  # 确保不会取超过剩余的块
            keys_to_remove = self.blocks[-k:]  # 从剩余的块中取

            for bo in keys_to_remove:
                self.remove(bo)
                self.blocks.remove(bo)  # 从列表中移除

            self.label1.element.text = f'电脑取数:{k}'
            print("电脑取数:" + str(k))
            print('len(self.blocks)=', len(self.blocks))
            
            if not self.blocks:
                self.label.element.text = '电脑胜利!'

            self.player = 0

def main():
    director.init()
    scene = Scene()
    scene.add(GameLayer(), z=0)
    director.run(scene)

if __name__ == "__main__":
    main()

### 主要修改点:
- 将`self.blocks` 初始化为一个列表并正确操作。
- 确保在玩家或电脑取子后,立即检查是否胜利并更新标签。
- 确保电脑不会取超过剩余数量的块。

这样修改后应该可以解决你的问题。若问题仍未解决,请检查您的开发环境和资源文件(如`block.png`)是否存在问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-27 21:09:20 | 显示全部楼层
玩家胜利后能显示‘玩家胜利’和取子数标签。
但过程中不显示‘轮到玩家’和取子数标签。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-27 21:09:43 | 显示全部楼层
ydwb 发表于 2024-11-27 21:09
玩家胜利后能显示‘玩家胜利’和取子数标签。
但过程 ...


了解了你的问题,抱歉之前的解决方案不够完善。为了使在游戏过程中正确显示“轮到玩家”和“取子数”标签,我们需要确保这些标签在适当的时机更新以及游戏逻辑的顺序没有问题。

下面是通过调整代码逻辑和确保标签更新的位置的修改版本:
# coding: utf-8
import cocos
from cocos.scene import Scene
from cocos.director import director
import pyglet
import random
import time

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
        super().__init__(128, 128, 128, 128)
        cocos.layer.Layer.is_event_handler = True
        self.label = cocos.text.Label('轮到玩家', font_name='kaiti', font_size=30, color=(255, 0, 0, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label.position = (320, 80)
        self.add(self.label)
        self.label1 = cocos.text.Label('', font_name='kaiti', font_size=30, color=(0, 0, 255, 255),
                                       anchor_x="center",
                                       anchor_y="center")
        self.label1.position = (320, 380)
        self.add(self.label1)
        self.player = 0
        self.blocks = []
        for i in range(18):
            bo = cocos.sprite.Sprite('block.png')
            bo.position = 40 + 32 * i, 240
            self.add(bo)
            self.blocks.append(bo)

    def on_mouse_press(self, x, y, button, modifiers):
        if self.player == 0:
            self.label.element.text = '轮到玩家'
            if button == pyglet.window.mouse.LEFT:
                x = min(round((x - 40) / 32), len(self.blocks) - 1)
                ss = len(self.blocks) - x
                if ss > 0:
                    for i in range(ss):
                        bo = self.blocks.pop()
                        self.remove(bo)
                    
                    self.label1.element.text = f"玩家取数:{ss}"
                    print(f"玩家取数:{ss}")
                    print('len(self.blocks)=', len(self.blocks))

                    if len(self.blocks) == 0:
                        self.label.element.text = '玩家胜利!'
                        return

                time.sleep(1)
                self.player = 1
                self.computer_move()

    def computer_move(self):
        if self.player == 1:
            self.label.element.text = '轮到电脑'
            k = random.randint(1, min(3, len(self.blocks)))
            for i in range(k):
                bo = self.blocks.pop()
                self.remove(bo)

            self.label1.element.text = f'电脑取数:{k}'
            print("电脑取数:" + str(k))
            print('len(self.blocks)=', len(self.blocks))

            if len(self.blocks) == 0:
                self.label.element.text = '电脑胜利!'
            
            self.player = 0

def main():
    director.init()
    scene = Scene()
    scene.add(GameLayer(), z=0)
    director.run(scene)

if __name__ == "__main__":
    main()

### 关键调整:

- 将 `keys_to_remove` 逻辑替换为直接从 `self.blocks` 取,用 `pop()` 方法来移除精灵。
- 确保在每次更新时 `self.label` 和 `self.label1` 均能准确反映当前状态。
- 确保在玩家操作后立即显示最新的标签信息。

请根据此代码重新测试,看看是否解决了标签无法显示的问题。如果还有其他疑问,请随时问我!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-12-10 16:23:05 | 显示全部楼层
轮到电脑时,如何让电脑等待5秒后执行程序,如tkinter中的 root.after(5000, computer_move())
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-12-10 16:23:42 | 显示全部楼层
ydwb 发表于 2024-12-10 16:23
轮到电脑时,如何让电脑等待5秒后执行程序,如tkinter ...


在 Cocos2d 里面,通常可以使用 `cocos.actions` 模块来创建延迟执行的效果。我们可以通过给方法加上一个延迟动作来实现电脑的等待效果。以下是如何实现电脑等待 5 秒后执行移动的方法。

### 代码修改

使用 `cocos.actions.Delay` 来实现等待效果:
# coding: utf-8
import cocos
from cocos.scene import Scene
from cocos.director import director
import pyglet
import random

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
        super().__init__(128, 128, 128, 128)
        cocos.layer.Layer.is_event_handler = True
        self.label = cocos.text.Label('轮到玩家', font_name='kaiti', font_size=30, color=(255, 0, 0, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label.position = (320, 80)
        self.add(self.label)
        self.label1 = cocos.text.Label('', font_name='kaiti', font_size=30, color=(0, 0, 255, 255),
                                       anchor_x="center",
                                       anchor_y="center")
        self.label1.position = (320, 380)
        self.add(self.label1)
        self.player = 0
        self.blocks = []
        for i in range(18):
            bo = cocos.sprite.Sprite('block.png')
            bo.position = 40 + 32 * i, 240
            self.add(bo)
            self.blocks.append(bo)

    def on_mouse_press(self, x, y, button, modifiers):
        if self.player == 0:
            self.label.element.text = '轮到玩家'
            if button == pyglet.window.mouse.LEFT:
                x = min(round((x - 40) / 32), len(self.blocks) - 1)
                ss = len(self.blocks) - x
                if ss > 0:
                    for i in range(ss):
                        bo = self.blocks.pop()
                        self.remove(bo)
                    
                    self.label1.element.text = f"玩家取数:{ss}"
                    print(f"玩家取数:{ss}")
                    print('len(self.blocks)=', len(self.blocks))

                    if len(self.blocks) == 0:
                        self.label.element.text = '玩家胜利!'
                        return

                self.player = 1
                self.label.element.text = '轮到电脑'
                self.do(cocos.actions.Delay(5) + cocos.actions.CallFunc(self.computer_move))

    def computer_move(self):
        k = random.randint(1, min(3, len(self.blocks)))
        for i in range(k):
            bo = self.blocks.pop()
            self.remove(bo)

        self.label1.element.text = f'电脑取数:{k}'
        print("电脑取数:" + str(k))
        print('len(self.blocks)=', len(self.blocks))

        if len(self.blocks) == 0:
            self.label.element.text = '电脑胜利!'
        
        self.player = 0

def main():
    director.init()
    scene = Scene()
    scene.add(GameLayer(), z=0)
    director.run(scene)

if __name__ == "__main__":
    main()

### 关键步骤解释:

- **Delay 和 CallFunc**:通过 `cocos.actions.Delay(5) + cocos.actions.CallFunc(self.computer_move)` 来实现等待 5 秒再执行函数。`Delay(5)` 创建一个延迟动作,`CallFunc` 用于在延迟后调用 `computer_move` 函数。
- **do 方法**:将上面的动作序列通过 `do` 方法附加到 `GameLayer` 上,这会使得动作序列在这个节点上执行。

这样,你就可以在电脑执行其取子的逻辑前,先等待 5 秒钟。希望这能解决你的问题!如果还有其他问题,欢迎继续提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-12-10 17:51:40 | 显示全部楼层
将self.label.element.text = '轮到玩家'  位置调整后,可正常显示'轮到玩家'、‘轮到电脑’
但要在‘电脑胜利‘后 加上 return后才会显示‘电脑胜利‘,否则继续显示'轮到玩家'
# coding: utf-8
import cocos
from cocos.scene import Scene
from cocos.director import director
import pyglet
import random

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
        super().__init__(128, 128, 128, 128)
        cocos.layer.Layer.is_event_handler = True
        self.label = cocos.text.Label('轮到玩家', font_name='kaiti', font_size=30, color=(255, 0, 0, 255),
                                      anchor_x="center",
                                      anchor_y="center")
        self.label.position = (320, 80)
        self.add(self.label)
        self.label1 = cocos.text.Label('', font_name='kaiti', font_size=30, color=(0, 0, 255, 255),
                                       anchor_x="center",
                                       anchor_y="center")
        self.label1.position = (320, 380)
        self.add(self.label1)
        self.player = 0
        self.blocks = []
        for i in range(18):
            bo = cocos.sprite.Sprite('block.png')
            bo.position = 40 + 32 * i, 240
            self.add(bo)
            self.blocks.append(bo)

    def on_mouse_press(self, x, y, button, modifiers):
        if self.player == 0:
            if button == pyglet.window.mouse.LEFT:
                x = min(round((x - 40) / 32), len(self.blocks) - 1)
                ss = len(self.blocks) - x
                if ss > 0:
                    for i in range(ss):
                        bo = self.blocks.pop()
                        self.remove(bo)

                    self.label1.element.text = f"玩家取数:{ss}"
                    print(f"玩家取数:{ss}")
                    print('len(self.blocks)=', len(self.blocks))

                    if len(self.blocks) == 0:
                        self.label.element.text = '玩家胜利!'
                        return
                self.player = 1
                self.label.element.text = '轮到电脑'
                self.do(cocos.actions.Delay(random.randint(2, 5)) + cocos.actions.CallFunc(self.computer_move))

    def computer_move(self):
        k = random.randint(1, min(3, len(self.blocks)))
        for i in range(k):
            bo = self.blocks.pop()
            self.remove(bo)

        self.label1.element.text = f'电脑取数:{k}'
        print("电脑取数:" + str(k))
        print('len(self.blocks)=', len(self.blocks))
        if len(self.blocks) == 0:
            self.label.element.text = '电脑胜利!'
            return
        self.label.element.text = '轮到玩家'
        self.player = 0

def main():
    director.init()
    scene = Scene()
    scene.add(GameLayer(), z=0)
    director.run(scene)

if __name__ == "__main__":
    main()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-12-10 17:51:53 | 显示全部楼层    本楼为最佳答案   
ydwb 发表于 2024-12-10 17:51
将self.label.element.text = '轮到玩家'  位置调整后 ...


感谢你提供的代码,根据你的描述,问题的关键在于确保游戏在有人胜利时立即返回而不继续执行游戏循环。在代码中,当电脑胜利时,需要通过 `return` 立即终止当前逻辑,以防止出现不合理的状态更新。

从你提供的更新代码来看,你已在“玩家胜利”和“电脑胜利”后正确地插入了 `return` 语句。这使得程序在达到胜利条件时终止当前执行的函数,从而避免了后续不必要的状态更新。

### 确保逻辑完整性的代码片段:
if len(self.blocks) == 0:
    self.label.element.text = '玩家胜利!'
    return
if len(self.blocks) == 0:
    self.label.element.text = '电脑胜利!'
    return

通过确保在胜利条件判断之后立即 `return`,你可以有效地终止当前函数,停止后续代码的执行。看起来你的调整已经解决了这个问题。如果在实现过程中还有其他问题,请告诉我!我会很乐意帮助你。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 12:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表