ydwb 发表于 2025-1-15 18:01:39

cocos2d布子延时及一键清屏

五子棋演示必胜招法,要求每布一子延时1秒,显示动画效果。
布子完成后停留3秒,回到无子界面。或者一键清屏。
下面代码延时及清屏无效果。
import cocos
from cocos.scene import Scene
from cocos.director import director
from pyglet.window import key
qizi = []
bo = None
class GameLayer(cocos.layer.ColorLayer):
    global qizi, bo
    def __init__(self):
      super().__init__(22, 142, 202, 255)
      cocos.layer.Layer.is_event_handler = True
      bg = cocos.sprite.Sprite('bc55.jpg')
      bg.position = (350, 350)
      self.add(bg)

    def display(self):
      positions = [(9, 9), (10, 9), (8, 6), (9, 8), (6, 8), (8, 7), (7, 6), (11, 10),
                  (12, 11), (12, 9), (6, 6), (9, 6), (7, 7)]
      for i in range(13):
            if i % 2 == 0:
                bo = cocos.sprite.Sprite('3.png')
            else:
                bo = cocos.sprite.Sprite('4.png')
            bo.position = (35 + (positions) * 45, 35 + (positions) * 45)
            self.do(cocos.actions.Delay(1))
            self.add(bo)
            qizi.append(bo)

      self.do(cocos.actions.Delay(3))
      return

    def on_key_press(self, k, _):
      global qizi, bo
      if k == key.SPACE:
            self.display()

      if k == key.ENTER:
            self.remove(bo)
            qizi = []

director.init(800, 700, caption="五子棋")
mainscene = Scene()
mainscene.add(GameLayer(), z=1)
director.run(mainscene)

FishC 发表于 2025-1-15 18:02:09

以下是改进的代码和简要说明,确保延时和清屏功能有效:

import cocos
from cocos.scene import Scene
from cocos.director import director
from pyglet.window import key
from time import sleep

qizi = []
class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
      super().__init__(22, 142, 202, 255)
      cocos.layer.Layer.is_event_handler = True
      bg = cocos.sprite.Sprite('bc55.jpg')
      bg.position = (350, 350)
      self.add(bg)

    def display(self):
      positions = [(x, y) for x, y in zip(range(13), range(13))]
      for i, pos in enumerate(positions):
            if i % 2 == 0:
                sprite = cocos.sprite.Sprite('3.png')
            else:
                sprite = cocos.sprite.Sprite('4.png')
            sprite.position = (35 + pos * 45, 35 + pos * 45)
            self.add(sprite)
            qizi.append(sprite)

            # 延时 1 秒
            sleep(1)

      # 停留 3 秒
      sleep(3)

      # 回到无子界面(清屏)
      for piece in qizi:
            self.remove(piece)
      qizi.clear()

    def on_key_press(self, k, _):
      if k == key.SPACE:
            self.display()

      if k == key.ENTER:
            # 一键清屏
            for piece in qizi:
                self.remove(piece)
            qizi.clear()


director.init(800, 700, caption="五子棋")
mainscene = Scene()
mainscene.add(GameLayer(), z=1)
director.run(mainscene)

### 关键调整点:
1. **引入延时:**
   使用 `sleep()` 函数来实现布子后的延时操作。

2. **清屏逻辑:**
   每次清屏时,通过遍历 `qizi` 列表移除所有棋子,同时清空列表。

3. **移除无效动作:**
   你的代码中 `self.do(cocos.actions.Delay(1))` 和 `self.do(cocos.actions.Delay(3))` 对延时无效果,因此直接改为 `sleep()`。

4. **修复全局状态问题:**
   避免直接使用 `global` 修改全局变量,通过列表的 `append()` 和 `clear()` 操作管理棋子。

如果还有其他需求,可以继续提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

某一个“天” 发表于 2025-1-15 18:14:41

你在实现五子棋的动画效果和延时方面有一些问题。主要的原因在于 cocos.actions.Delay() 和 do() 方法的使用,以及 clear 和 remove 子对象时的实现。下面是修改过的代码,修复了延时和清屏效果。

问题分析:
延时问题:

cocos.actions.Delay(1) 仅仅是一个动作,do() 方法会立即执行后面的代码,而并不会等待延时。延时动作应该通过一个 Action 来实现,比如 Delay 和 CallFunc 配合使用。
清屏问题:

self.remove(bo) 只是删除了最后一个棋子,并没有清除所有棋子。你应该在清屏时通过遍历所有棋子对象并逐个删除。
一键清屏:

你可以在按 ENTER 时,删除所有棋子对象,而不仅仅是一个。
修改后的代码:
python
import cocos
from cocos.scene import Scene
from cocos.director import director
from pyglet.window import key
from pyglet import clock

qizi = []# 存储棋子
bo = None   # 当前棋子

class GameLayer(cocos.layer.ColorLayer):
    global qizi, bo

    def __init__(self):
      super().__init__(22, 142, 202, 255)
      cocos.layer.Layer.is_event_handler = True# 开启事件监听
      bg = cocos.sprite.Sprite('bc55.jpg')
      bg.position = (350, 350)
      self.add(bg)
      self.schedule(self.update)# 每帧更新

      self.displaying = False# 控制棋子展示是否进行

    def display(self):
      # 棋子的布局
      positions = [
            (9, 9), (10, 9), (8, 6), (9, 8), (6, 8), (8, 7), (7, 6), (11, 10),
            (12, 11), (12, 9), (6, 6), (9, 6), (7, 7)
      ]

      # 布置棋子
      for i in range(len(positions)):
            bo = cocos.sprite.Sprite('3.png' if i % 2 == 0 else '4.png')
            bo.position = (35 + positions * 45, 35 + positions * 45)
            self.add(bo)
            qizi.append(bo)

      # 更新布置的棋子
      self.displaying = True
      self.delay_time = 1# 每个棋子的延时
      self.index = 0# 当前处理的棋子索引

    def update(self, dt):
      """ 每帧调用一次,逐个显示棋子 """
      if self.displaying:
            if self.index < len(qizi):
                bo = qizi
                bo.do(cocos.actions.Delay(self.delay_time))# 延时显示
                self.index += 1
            else:
                self.displaying = False# 完成棋子的显示,停止更新

    def on_key_press(self, k, _):
      global qizi, bo
      if k == key.SPACE:
            self.display()# 按空格键开始显示棋子

      if k == key.ENTER:
            # 按回车键清空棋盘
            self.clear_board()

    def clear_board(self):
      """ 清空棋盘上的所有棋子 """
      for q in qizi:
            self.remove(q)
      qizi = []# 清空棋子列表

director.init(800, 700, caption="五子棋")
mainscene = Scene()
mainscene.add(GameLayer(), z=1)
director.run(mainscene)
关键改动:
延时显示棋子:

使用 self.schedule(self.update) 让 update 方法每帧调用一次,逐个显示棋子。在 display() 中,依次创建棋子并将其添加到列表 qizi。
每个棋子显示时都有 Delay 动作,延时展示。
清除棋子:

通过 clear_board() 方法遍历 qizi 列表并删除所有棋子,清空 qizi 列表。
标志位控制:

增加了 self.displaying 标志位来控制棋子是否正在显示,如果已经显示完所有棋子,就停止进一步的显示。
按键操作:

空格键 (SPACE) 开始展示棋子。
回车键 (ENTER) 清空棋盘。
运行效果:
按下空格键,棋子按顺序依次出现,每个棋子延时 1 秒。
布子完成后,停留 3 秒后自动停止。
按下回车键清空棋盘,重新开始。
希望这可以帮助你实现预期的五子棋动画效果!

ydwb 发表于 2025-1-15 19:14:15

以上两个答案都实现了一键清屏的效果,但都未实现按顺序依次出现的效果。

ydwb 发表于 2025-1-16 07:40:22

想到了一个办法。因为单用Delay无延时效果,各子总是同时出现。
那就分两步走,先让各子同时出现在一个不显眼位置,再用Delay+Place
组合,分别延时,就让各子按顺序出现在预定位置。import cocos
from cocos.scene import Scene
from cocos.director import director
from pyglet.window import key
from cocos.actions import *

qizi = []
bo = None

class GameLayer(cocos.layer.ColorLayer):
    def __init__(self):
      super().__init__(22, 142, 202, 255)
      cocos.layer.Layer.is_event_handler = True
      bg = cocos.sprite.Sprite('bc55.jpg')
      bg.position = (350, 350)
      self.add(bg)

    def display(self):
      positions = [(9, 9), (10, 9), (8, 6), (9, 8), (6, 8), (8, 7), (7, 6), (11, 10),
                  (12, 11), (12, 9), (6, 6), (9, 6), (7, 7)]
      for i in range(13):
            if i % 2 == 0:
                bo = cocos.sprite.Sprite('3.png')
            else:
                bo = cocos.sprite.Sprite('4.png')
            bo.position = (0, 0)
            self.add(bo)
            bo.do(Delay(i * 3) + Place((35 + (positions) * 45, 35 + (positions) * 45)))
            qizi.append(bo)

    def on_key_press(self, k, _):
      if k == key.SPACE:
            self.display()

      if k == key.ENTER:
            for piece in qizi:
                self.remove(piece)
            qizi.clear()

director.init(800, 700, caption="五子棋")
mainscene = Scene()
game = GameLayer()
mainscene.add(game, z=1)
director.run(mainscene)
页: [1]
查看完整版本: cocos2d布子延时及一键清屏