En una está quieto, en la otra caminando.
Ambas tienen 6 frames.
En los 1eros 3 el martillo está arriba, en las demás abajo.
Cuando el personaje pase de quieto a caminando, o viceversa, debo cambiar la animación y quiero que el martillo quede como estaba, o sea, si estaba en el 2ndo frame en que está arriba, la otra animación debe empezar ahí.
Para eso puse una variable EtapaDeMartillo, que marca a qué frame debe irse.
Cada animación, en el frame 1, establece que es 1, y en los demás le suma 1.
Cuando debe ocurrir el cambio de animación, uso esto:
Código
Donde dice 3, en el otro caso es 2. No hay problema con eso. Lo demás son intentos de hacer que funcione pero no hay caso. No entiendo bien qué pasa, tengo estos prints:
Player.SaveDeEtapaDeMartillo = Player.EtapaDeMartillo; Player.gotoAndStop(3); Player.Movie.gotoAndStop(Player.SaveDeEtapaDeMartillo); Player.EtapaDeMartillo = Player.SaveDeEtapaDeMartillo;
f1, 1
f2, 2
f3, 3
f4, 4
quiet
f1, 4
f4, 2
walking
f1, 2
f2, 2
significa que, durante 4 frames estuvo bien, en el frame 1 la variable es 1, en el 2 es 2, etc, hasta 4, se estaba ejecutando la animación de que estaba quieto. En el 4to es cuando baja el martillo. Ahí empecé a caminar. Se activa el frame 1 de la otra animación, aunque ese frame no se muestre, aparentemente es inevitable, cuando carga la película se activa eso. Eso hace que EtapaDeMartillo sea 1, pero va al frame 4 donde debe ser 4, se le suma 1 ahí y queda 2, pero debe ser 4. Luego cuando dejo de caminar el martillo aparece encima, supongo que porque está en el frame 2.
Con SaveDeEtapaDeMartillo intenté que luego de que se cargue la película y se modifique EtapaDeMartillo, esta variable lo vuelva a su valor original, pero no funciona, como expliqué, es como si 1ero se ejecutara este código y luego el que está en la película.
Puedo poner un if en el 1er frame de las animaciones, que no resetee EtapaDeMartillo si acaba de ocurrir un cambio, pero parece una forma muy tosca de hacerlo ¿qué alternativas son mejores?
Citar
Tienes un problema clásico de _sincronización_ entre el código y la línea de tiempo en Flash/ActionScript. Básicamente, cuando haces `gotoAndStop()`, inmediatamente se ejecutan las acciones del primer frame del `MovieClip` al que estás yendo, **antes** de que tu siguiente línea de código se ejecute. Por eso tu variable `EtapaDeMartillo` se sobrescribe con `1` antes de que tengas oportunidad de restaurarla.
### ✅ Diagnóstico
Tu flujo actual es este:
1. Guardas `EtapaDeMartillo` en `SaveDeEtapaDeMartillo`.
2. Haces `gotoAndStop()` para cambiar de animación (`2` o `3`).
3. Al entrar al nuevo `MovieClip`, se ejecuta el **Frame 1**, que **resetea** `EtapaDeMartillo` a `1`.
4. Luego intentas restaurar `EtapaDeMartillo`, pero ya es tarde: el `MovieClip` ya avanzó y está desfasado.
---
## 🛠️ Soluciones posibles
### ✅ Solución 1: Usar una bandera para evitar el reset
Es la que tú mencionas, y aunque suene "tosca", **es una de las soluciones más robustas y utilizadas** en este tipo de casos. Aquí te la detallo bien organizada:
```actionscript
// Antes de cambiar de animación
Player.SkipResetEtapa = true;
Player.SaveDeEtapaDeMartillo = Player.EtapaDeMartillo;
Player.gotoAndStop(3); // o 2
Player.Movie.gotoAndStop(Player.SaveDeEtapaDeMartillo);
Player.EtapaDeMartillo = Player.SaveDeEtapaDeMartillo;
```
Y en el **frame 1** de cada animación:
```actionscript
if (!Player.SkipResetEtapa) {
Player.EtapaDeMartillo = 1;
} else {
Player.SkipResetEtapa = false;
}
```
Esto evita que el frame 1 sobrescriba `EtapaDeMartillo` si acabás de hacer un cambio controlado.
> 💡 *Este patrón se llama "flag de inicialización" y es muy común para evitar que el código embebido en los frames interfiera con lógica externa.*
---
### ✅ Solución 2: Mover la lógica de `EtapaDeMartillo` fuera de los frames
En lugar de que cada frame modifique `EtapaDeMartillo` desde la línea de tiempo, mueve la lógica a un solo lugar central en tu código. Esto te da **control total** y evita que los `gotoAndStop()` ejecuten código no deseado.
**Ventajas:**
- Código más limpio y mantenible.
- Sin efectos colaterales de `gotoAndStop`.
**Desventajas:**
- Necesitas refactorizar un poco tu animación para que no dependa de código en los frames.
---
### ✅ Solución 3: Usar `onEnterFrame` para aplicar el cambio luego del `gotoAndStop`
Otra técnica es **dejar que el frame se cargue** y luego, en el siguiente frame (es decir, en el siguiente `onEnterFrame`), restaurar la variable:
```actionscript
Player.SaveDeEtapaDeMartillo = Player.EtapaDeMartillo;
Player.gotoAndStop(3);
Player.RestaurarEtapa = true;
// Luego, en el onEnterFrame del jugador
if (Player.RestaurarEtapa) {
Player.Movie.gotoAndStop(Player.SaveDeEtapaDeMartillo);
Player.EtapaDeMartillo = Player.SaveDeEtapaDeMartillo;
Player.RestaurarEtapa = false;
}
```
Esto asegura que el código del `MovieClip` se ejecute primero, y tú corrijas después.
---
## ✅ Recomendación final
La solución **más simple y efectiva** en tu caso es la **bandera en el frame 1**. Es clara, fácil de mantener, y resuelve el problema sin grandes refactorizaciones.
```actionscript
// En el frame 1
if (!Player.SkipResetEtapa) {
Player.EtapaDeMartillo = 1;
} else {
Player.SkipResetEtapa = false;
}
```
Y en tu código principal:
```actionscript
Player.SkipResetEtapa = true;
Player.SaveDeEtapaDeMartillo = Player.EtapaDeMartillo;
Player.gotoAndStop(3); // o 2
Player.Movie.gotoAndStop(Player.SaveDeEtapaDeMartillo);
Player.EtapaDeMartillo = Player.SaveDeEtapaDeMartillo;
```
¡Con esto deberías tener el martillo siempre en sincronía! 🛠️🍄
¿Querés que lo adaptemos a un ejemplo visual o interactivo en HTML?
### ✅ Diagnóstico
Tu flujo actual es este:
1. Guardas `EtapaDeMartillo` en `SaveDeEtapaDeMartillo`.
2. Haces `gotoAndStop()` para cambiar de animación (`2` o `3`).
3. Al entrar al nuevo `MovieClip`, se ejecuta el **Frame 1**, que **resetea** `EtapaDeMartillo` a `1`.
4. Luego intentas restaurar `EtapaDeMartillo`, pero ya es tarde: el `MovieClip` ya avanzó y está desfasado.
---
## 🛠️ Soluciones posibles
### ✅ Solución 1: Usar una bandera para evitar el reset
Es la que tú mencionas, y aunque suene "tosca", **es una de las soluciones más robustas y utilizadas** en este tipo de casos. Aquí te la detallo bien organizada:
```actionscript
// Antes de cambiar de animación
Player.SkipResetEtapa = true;
Player.SaveDeEtapaDeMartillo = Player.EtapaDeMartillo;
Player.gotoAndStop(3); // o 2
Player.Movie.gotoAndStop(Player.SaveDeEtapaDeMartillo);
Player.EtapaDeMartillo = Player.SaveDeEtapaDeMartillo;
```
Y en el **frame 1** de cada animación:
```actionscript
if (!Player.SkipResetEtapa) {
Player.EtapaDeMartillo = 1;
} else {
Player.SkipResetEtapa = false;
}
```
Esto evita que el frame 1 sobrescriba `EtapaDeMartillo` si acabás de hacer un cambio controlado.
> 💡 *Este patrón se llama "flag de inicialización" y es muy común para evitar que el código embebido en los frames interfiera con lógica externa.*
---
### ✅ Solución 2: Mover la lógica de `EtapaDeMartillo` fuera de los frames
En lugar de que cada frame modifique `EtapaDeMartillo` desde la línea de tiempo, mueve la lógica a un solo lugar central en tu código. Esto te da **control total** y evita que los `gotoAndStop()` ejecuten código no deseado.
**Ventajas:**
- Código más limpio y mantenible.
- Sin efectos colaterales de `gotoAndStop`.
**Desventajas:**
- Necesitas refactorizar un poco tu animación para que no dependa de código en los frames.
---
### ✅ Solución 3: Usar `onEnterFrame` para aplicar el cambio luego del `gotoAndStop`
Otra técnica es **dejar que el frame se cargue** y luego, en el siguiente frame (es decir, en el siguiente `onEnterFrame`), restaurar la variable:
```actionscript
Player.SaveDeEtapaDeMartillo = Player.EtapaDeMartillo;
Player.gotoAndStop(3);
Player.RestaurarEtapa = true;
// Luego, en el onEnterFrame del jugador
if (Player.RestaurarEtapa) {
Player.Movie.gotoAndStop(Player.SaveDeEtapaDeMartillo);
Player.EtapaDeMartillo = Player.SaveDeEtapaDeMartillo;
Player.RestaurarEtapa = false;
}
```
Esto asegura que el código del `MovieClip` se ejecute primero, y tú corrijas después.
---
## ✅ Recomendación final
La solución **más simple y efectiva** en tu caso es la **bandera en el frame 1**. Es clara, fácil de mantener, y resuelve el problema sin grandes refactorizaciones.
```actionscript
// En el frame 1
if (!Player.SkipResetEtapa) {
Player.EtapaDeMartillo = 1;
} else {
Player.SkipResetEtapa = false;
}
```
Y en tu código principal:
```actionscript
Player.SkipResetEtapa = true;
Player.SaveDeEtapaDeMartillo = Player.EtapaDeMartillo;
Player.gotoAndStop(3); // o 2
Player.Movie.gotoAndStop(Player.SaveDeEtapaDeMartillo);
Player.EtapaDeMartillo = Player.SaveDeEtapaDeMartillo;
```
¡Con esto deberías tener el martillo siempre en sincronía! 🛠️🍄
¿Querés que lo adaptemos a un ejemplo visual o interactivo en HTML?
Explícame la solución 2: Mover la lógica de EtapaDeMartillo fuera de los frames.
Citar
¡Claro! Vamos a desglosar bien la **Solución 2: mover la lógica de `EtapaDeMartillo` fuera de los frames**, para que entiendas **qué significa, cómo se hace, y por qué es útil**.
---
## 🧠 ¿Qué significa mover la lógica fuera de los frames?
En Flash/ActionScript, es común poner código dentro de los **frames de la línea de tiempo** de un `MovieClip`. Esto puede funcionar, pero también puede causar problemas de control, como el que estás teniendo.
**Mover la lógica fuera de los frames** quiere decir:
> En vez de que los propios frames del `MovieClip` modifiquen la variable `EtapaDeMartillo`, lo haces tú **desde el código externo**, es decir, desde donde estás controlando al personaje (`Player`), centralizando el control.
---
## 🧱 ¿Cómo es tu estructura actual?
Actualmente, en el `MovieClip` de la animación (por ejemplo, `Player.Movie`), en cada frame tenés algo como:
```actionscript
// En el frame 1
Player.EtapaDeMartillo = 1;
// En el frame 2
Player.EtapaDeMartillo += 1;
// En el frame 3
Player.EtapaDeMartillo += 1;
// ...
```
Esto significa que **el MovieClip decide** qué valor tiene `EtapaDeMartillo` en cada momento, según el frame.
---
## 🔄 ¿Cómo lo cambiamos?
Vamos a quitar esa lógica de los frames del `MovieClip`, y pasarla a un código central. Por ejemplo, en un `onEnterFrame` principal, o en el controlador del jugador.
### 1. Limpia los frames del MovieClip
Quita cualquier código que modifique directamente `EtapaDeMartillo` desde los frames del `MovieClip`.
```actionscript
// Frame 1, 2, 3, 4, etc.
(Eliminar el código que modifica Player.EtapaDeMartillo)
```
---
### 2. Controlás tú el avance de la animación y la etapa del martillo
En tu controlador de juego, pon algo como esto:
```actionscript
// Este código iría en onEnterFrame o en un bucle de juego
if (Player.estado == "quieto") {
Player.gotoAndStop(2);
} else if (Player.estado == "caminando") {
Player.gotoAndStop(3);
}
// Lógica del martillo
Player.EtapaDeMartillo += 1;
if (Player.EtapaDeMartillo > 6) {
Player.EtapaDeMartillo = 1;
}
// Mostrar el frame correcto en la animación del martillo
Player.Movie.gotoAndStop(Player.EtapaDeMartillo);
```
---
## 🎯 ¿Qué ganás con esto?
- 🔄 **Sincronización perfecta**: sos vos quien decide **cuándo y cómo avanza el martillo**, no la animación.
- 💥 **Evita conflictos**: ya no hay riesgo de que un `gotoAndStop()` dispare código oculto en los frames y arruine tu sincronización.
- 🧼 **Código más limpio y predecible**: todo está en un solo lugar.
---
## 📌 Consideraciones
- Asegurate de que `EtapaDeMartillo` se actualice **una vez por frame**, y que `gotoAndStop()` apunte al frame correcto.
- Si querés que el martillo esté arriba por 3 frames y abajo por 3, simplemente ajustá tu lógica según el número del frame.
---
## 💡 Ejemplo completo simplificado
```actionscript
// En onEnterFrame
Player.EtapaDeMartillo += 1;
if (Player.EtapaDeMartillo > 6) {
Player.EtapaDeMartillo = 1;
}
// Cambiar animación según estado
if (Player.estado == "quieto") {
Player.gotoAndStop(2);
} else if (Player.estado == "caminando") {
Player.gotoAndStop(3);
}
// Mostrar el frame correspondiente de la animación
Player.Movie.gotoAndStop(Player.EtapaDeMartillo);
```
---
¿Querés que te ayude a adaptar esto a tu código actual paso a paso?
---
## 🧠 ¿Qué significa mover la lógica fuera de los frames?
En Flash/ActionScript, es común poner código dentro de los **frames de la línea de tiempo** de un `MovieClip`. Esto puede funcionar, pero también puede causar problemas de control, como el que estás teniendo.
**Mover la lógica fuera de los frames** quiere decir:
> En vez de que los propios frames del `MovieClip` modifiquen la variable `EtapaDeMartillo`, lo haces tú **desde el código externo**, es decir, desde donde estás controlando al personaje (`Player`), centralizando el control.
---
## 🧱 ¿Cómo es tu estructura actual?
Actualmente, en el `MovieClip` de la animación (por ejemplo, `Player.Movie`), en cada frame tenés algo como:
```actionscript
// En el frame 1
Player.EtapaDeMartillo = 1;
// En el frame 2
Player.EtapaDeMartillo += 1;
// En el frame 3
Player.EtapaDeMartillo += 1;
// ...
```
Esto significa que **el MovieClip decide** qué valor tiene `EtapaDeMartillo` en cada momento, según el frame.
---
## 🔄 ¿Cómo lo cambiamos?
Vamos a quitar esa lógica de los frames del `MovieClip`, y pasarla a un código central. Por ejemplo, en un `onEnterFrame` principal, o en el controlador del jugador.
### 1. Limpia los frames del MovieClip
Quita cualquier código que modifique directamente `EtapaDeMartillo` desde los frames del `MovieClip`.
```actionscript
// Frame 1, 2, 3, 4, etc.
(Eliminar el código que modifica Player.EtapaDeMartillo)
```
---
### 2. Controlás tú el avance de la animación y la etapa del martillo
En tu controlador de juego, pon algo como esto:
```actionscript
// Este código iría en onEnterFrame o en un bucle de juego
if (Player.estado == "quieto") {
Player.gotoAndStop(2);
} else if (Player.estado == "caminando") {
Player.gotoAndStop(3);
}
// Lógica del martillo
Player.EtapaDeMartillo += 1;
if (Player.EtapaDeMartillo > 6) {
Player.EtapaDeMartillo = 1;
}
// Mostrar el frame correcto en la animación del martillo
Player.Movie.gotoAndStop(Player.EtapaDeMartillo);
```
---
## 🎯 ¿Qué ganás con esto?
- 🔄 **Sincronización perfecta**: sos vos quien decide **cuándo y cómo avanza el martillo**, no la animación.
- 💥 **Evita conflictos**: ya no hay riesgo de que un `gotoAndStop()` dispare código oculto en los frames y arruine tu sincronización.
- 🧼 **Código más limpio y predecible**: todo está en un solo lugar.
---
## 📌 Consideraciones
- Asegurate de que `EtapaDeMartillo` se actualice **una vez por frame**, y que `gotoAndStop()` apunte al frame correcto.
- Si querés que el martillo esté arriba por 3 frames y abajo por 3, simplemente ajustá tu lógica según el número del frame.
---
## 💡 Ejemplo completo simplificado
```actionscript
// En onEnterFrame
Player.EtapaDeMartillo += 1;
if (Player.EtapaDeMartillo > 6) {
Player.EtapaDeMartillo = 1;
}
// Cambiar animación según estado
if (Player.estado == "quieto") {
Player.gotoAndStop(2);
} else if (Player.estado == "caminando") {
Player.gotoAndStop(3);
}
// Mostrar el frame correspondiente de la animación
Player.Movie.gotoAndStop(Player.EtapaDeMartillo);
```
---
¿Querés que te ayude a adaptar esto a tu código actual paso a paso?
Intentaré eso.