elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: Security Series.XSS. [Cross Site Scripting]


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Cuando las cartas tienen opciones.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Cuando las cartas tienen opciones.  (Leído 2,474 veces)
Tachikomaia


Desconectado Desconectado

Mensajes: 1.682


Hackentifiko!


Ver Perfil
Cuando las cartas tienen opciones.
« en: 1 Julio 2025, 04:49 am »

En mi proyecto de juego en Macromedia Flash 5, se le daba una carta al jugador, se le decía cual, y había una pausa hasta que presionara A. Sólo tiene 1 carta.

Quisiera que cuando la carta tiene opciones (causar un efecto u otro), eso se diga al jugador y haya una pausa hasta que presione arriba, o abajo, u otra tecla según cuántas opciones sean.

Parece claro que se puede hacer creando, para cada carta, una variable que marque si la carta tiene opciones o no, y poniendo un if para que dependiendo de eso ponga la pausa básica o la pausa con opciones.

Mi duda es si hay una mejor forma de hacerlo porque no me gusta crear tantas variables ni usar un if cada vez que se obtiene la carta.

Se me ocurre:
- Cuando se obtiene, se busca el valor de una variable llamada Opciones, por ejemplo si se obtiene la carta DKMario se busca una variable llamada DKMarioOpciones.
- Si no tiene valor es que no existe, no tiene opciones, hace la pausa normal. Sino, hace la pausa con opciones.

Eso usa un if pero en vez de crear variables para todas las cartas, crea sólo para las que tienen opciones.

El tema de las pausas también se complica un poco, yo tenía:
// Frame 1: La IA recibe una carta, el humano también.
// F2: Un objeto repite TurnoDeHumano hasta que se presione A.
// F3: Pequeña pausa.
// F4: Turno de la IA.
...ahora debería ser:
// Frame 1: La IA recibe una carta, el humano también.
// F2: Si la carta no tiene opciones, se inserta un objeto que genera la pausa normal. Sino otro que genera la pausa con opciones.
...el resto igual.
Supongo que eso es mejor que crear un frame para la pausa normal y otro para la otra y que vaya para un frame u otro según el caso.

¿Se les ocurre algo mejor?

Uno pregunta porque tiene la esperanza de hallar una respuesta, pero ahora me pregunto para qué preguntar si probablemente no entienda la respuesta:
Citar
Tu razonamiento es **muy sólido** y demuestra una buena comprensión de cómo organizar lógica condicional en Flash 5, que tiene sus limitaciones. Vamos a analizar tu enfoque y ver cómo mejorarlo o refinarlo con el menor número de variables y frames posibles.

---

## 🎯 Objetivo

- Tienes cartas que pueden o no tener múltiples opciones.
- Quieres pausar el juego hasta que el jugador elija una opción (una tecla).
- No quieres crear una variable por cada carta.
- No quieres duplicar frames innecesariamente.

---

## ✅ Lo Bueno de Tu Enfoque

Tu idea de usar una **nomenclatura dinámica** como `DKMarioOpciones` es muy buena para evitar crear estructuras repetitivas o usar `if` para cada carta. En Flash 5 (ActionScript 1.0), puedes usar esta técnica:

```actionscript
var opcionesVar = this[NombreDeCarta + "Opciones"];
```

Si `opcionesVar` es `undefined`, entonces no hay opciones.

Esto te permite tener una lista como:

```actionscript
DKMarioOpciones = ["Arriba", "Abajo"];
CartaFuegoOpciones = ["Izquierda", "Derecha", "Abajo"];
```

Y no necesitas definir ninguna variable para cartas que no tienen opciones. Perfecto.

---

## 💡 Mejora Propuesta: Usar una Sola Función y el Mismo Frame

Si quieres evitar duplicar frames o insertar objetos distintos según el tipo de carta, puedes hacer esto:

### 1. Un solo objeto/clip de pausa
En el frame 2, insertas **siempre el mismo clip** llamado `PausaCarta`.

Ese clip tiene el siguiente código en su `onClipEvent(enterFrame)`:

```actionscript
onClipEvent(enterFrame) {
    var opciones = _root[_root.NombreDeCarta + "Opciones"];
   
    if (opciones == undefined) {
        // No hay opciones, esperar tecla A
        if (Key.isDown(Key.A)) {
            _root.gotoAndPlay(3);
        }
    } else {
        // Hay opciones, mostrar opciones y esperar tecla válida
        if (_root.mostrandoOpciones != true) {
            _root.mostrandoOpciones = true;
            // Mostrar texto de opciones o lo que quieras
            for (var i = 0; i < opciones.length; i++) {
                trace("Opción " + (i+1) + ": " + opciones);
            }
        }

        // Aquí podrías detectar teclas según cantidad de opciones
        if (Key.isDown(Key.UP)) {
            _root.opcionElegida = 0;
            _root.gotoAndPlay(3);
        } else if (Key.isDown(Key.DOWN)) {
            _root.opcionElegida = 1;
            _root.gotoAndPlay(3);
        } // etc.
    }
}
```

Este objeto es universal: maneja ambas situaciones.

Solo necesitas asegurarte de que:

- `_root.NombreDeCarta` esté definido antes de entrar al frame 2.
- Los nombres de las variables opcionales sigan la convención de `NombreDeCarta + "Opciones"`.

---

### 2. Limpieza al salir del frame

En el Frame 3 podrías resetear cosas:

```actionscript
mostrandoOpciones = false;
opcionElegida = -1;
```

---

## 🧠 Alternativa Más Limpia (Con Objetos)

Si quieres hacer algo más estructurado, puedes usar un objeto (diccionario) para definir las opciones:

```actionscript
CartasConOpciones = {
    "DKMario": ["Arriba", "Abajo"],
    "CartaFuego": ["Izquierda", "Derecha", "Abajo"]
};
```

Y luego:

```actionscript
var opciones = CartasConOpciones[NombreDeCarta];
```

Esto sigue siendo dinámico pero más organizado.

---

## ✅ Conclusión

Tu idea:

- Es válida
- Es eficiente
- Se puede mejorar levemente con objetos o clips genéricos

Lo que te propongo:

- Usa **un solo frame** y **un solo clip de pausa inteligente**
- Usa un objeto o variables dinámicas para definir solo las cartas que tienen opciones
- Evita `if` por cada carta o duplicación de clips

Esto te da un sistema **escalable**, **fácil de mantener** y muy en línea con las capacidades de Flash 5.

¿Te gustaría que te escriba el código completo del clip `PausaCarta` con la lógica completa de selección de opciones?

Lo que entendí es que su "Un solo objeto/clip de pausa" implica hacer ifs a cada rato (120 por segundo creo), así que no me sirve.

Me perdí en lo de diccionario. Quizá está pensando en cosas que aún no pensé.


En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.682


Hackentifiko!


Ver Perfil
Re: Cuando las cartas tienen opciones.
« Respuesta #1 en: 4 Octubre 2025, 02:52 am »

Me acerqué a esto y sigo sin saber cómo resolverlo.

Mi idea es:
// Frame 1: La IA recibe una carta, el humano también.
// F2: Un objeto repite TurnoDeHumano hasta que se presione A.
// F3: Un objeto repite CartaOpcional hasta que se elija una opción.
// F4: Pequeña pausa.
// F5: Turno de la IA.
// F6: Nada, sólo para mostrar victoria o derrota.

El problema es CartaOpcional.

Variables relevantes:
MarioDKAt = 2;
MarioDKDescription = "Mario de Donkey Kong. Poder: "+MarioDKAt+"\nElige:\n<- Mario ataca con su poder normal.\n-> Pierdes 1HP, Mario ataca con su poder +1.";

Función normal, hay una para cada carta:
Código
  1. function MarioDK (ataque, objetivo) {
  2. if (objetivo == "IA") {
  3. // Esta carta tiene opciones:
  4. // Option1 = "Normal";
  5. Ataque1 = ataque;
  6. Mensaje1 = "¡Rival dañado!";
  7. // Option2 = "Hammer";
  8. Ataque2 = ataque+1;
  9. Mensaje2 = "¡Rival dañado y perdiste 1HP!";
  10. // Va a un frame hasta que se elige una:
  11. gotoAndStop (3);
  12. } else {
  13. // ESTO NECESITA IA
  14. Mensaje = Mensaje+"\n¡DKMario rival te dañó!";
  15. TipicoAtaqueDeIA(ataque);
  16. }
  17. }
  18.  
Que necesita IA no es el problema, eso lo debo hacer luego.

Función problemática:
Código
  1. function CartaOpcional () {
  2. // Si se presiona izquierda:
  3. if (Key.isDown(37)) {
  4. // Usa la carta elegida aplicando la opción 1:
  5. Mensaje = Mensaje1;
  6. TipicoAtaqueHumano (Ataque1);
  7. play();
  8. // sino si se presiona derecha:
  9. } else if (Key.isDown(39)) {
  10. Mensaje = Mensaje2;
  11. // ACÁ DEBE PERDER 1HP, NO ES TÍPICO
  12. TipicoAtaqueHumano (Ataque2);
  13. play();
  14. }
  15. }

El problema es que esa función debe ejecutarse repetidamente en el frame 3, hasta que el humano elija una opción. Sea cual sea la carta que usó. Pero las opciones y efectos dependen de la carta. En la función que ejecuta los efectos de DKMario intenté crear lo que servirían de parámetros. Pero no parece suficiente. Paso el mensaje que debe dar y el daño que debe causar al rival, pero no los efectos atípicos como daño al usuario, paralizar al rival, etc. ¿Debería crear una función para cada efecto y pasar el parámetro de qué efectos se deben llamar en cada opción?
Otra opción sería crear una función extra para este tipo de cartas, y con una variable indicar cual de ellas debe ejecutarse cuando se elija una opción.
Supongo que lo de función para cada efecto es mejor, aunque al principio parezca una tarea más pesada.
¿Está bien? ¿alternativas mejores?


En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.682


Hackentifiko!


Ver Perfil
Re: Cuando las cartas tienen opciones.
« Respuesta #2 en: Hoy a las 04:17 »

Resolví esto pero creo que podría mejorarse. Lo que diré es un poco independiente de los posts anteriores, pero el problema a grandes rásgos es el mismo.

HumanoObtieneCarta agrega un objeto (invisible) u otro según si la carta da opciones o no:
Código
  1. function HumanoObtieneCarta () {
  2. (...)
  3. // Si la carta no da opciones:
  4. if (eval(Cartas[NroDeCartaDeHumano]+"Op") == 1) {
  5. // Se agrega un objeto que la ejecuta al presionar A:
  6. attachMovie("sParaCartaSimple", "Ventana", 4);
  7. } else {
  8. // Se agrega un objeto que la ejecuta de un modo u otro según qué tecla se presione:
  9. attachMovie("sParaCartaOpcional", "Ventana", 4);
  10. }
  11. }

Esto es el código en sParaCartaSimple:
Código
  1. onClipEvent (enterFrame) {
  2. // Si se presiona A:
  3. if (Key.isDown(65)) {
  4. _level0.UsarCartaSimple();
  5. removeMovieClip (_parent);
  6. }
  7. }

Este es en sParaCartaOpcional:
Código
  1. onClipEvent (enterFrame) {
  2. // Si se presiona izquierda:
  3. if (Key.isDown(37)) {
  4. // Humano eligió opción 1:
  5. _level0.CartaUsada = _level0.Cartas[_level0.NroDeCartaDeHumano]+"1";
  6. _level0.UsarCartaOpcional();
  7. removeMovieClip (_parent);
  8. } else if (Key.isDown(39)) {
  9. // Humano eligió opción 2:
  10. _level0.CartaUsada = _level0.Cartas[_level0.NroDeCartaDeHumano]+"2";
  11. _level0.UsarCartaOpcional();
  12. removeMovieClip (_parent);
  13. }
  14. }

Código
  1. function UsarCartaSimple () {
  2. // CartaUsada es para resumir:
  3. CartaUsada = Cartas[NroDeCartaDeHumano];
  4. User = "Humano";
  5. Ataque = eval(CartaUsada+"At");
  6. eval(CartaUsada)();
  7. }

Código
  1. function UsarCartaOpcional () {
  2. // CartaUsada es para resumir, definida en el objeto sParaCartaOpcional:
  3. User = "Humano";
  4. eval(CartaUsada)();
  5. }

Ejemplo de carta con opciones (el único que tengo por ahora):
Código
  1. function MarioDK1 () {
  2. Ataque = MarioDKAt;
  3. Mensaje = "¡Mario de Donkey Kong dañó al rival!";
  4. MarioDK();
  5. }
  6. function MarioDK2 () {
  7. HumanoHP--;
  8. if (HumanoHP > 0) {
  9. Ataque = MarioDKAt+1;
  10. Mensaje = "¡Perdiste 1HP pero Mario de Donkey Kong consiguió un martillo y dañó al rival!";
  11. MarioDK();
  12. } else {
  13. Mensaje = "¡Mario de Donkey Kong consiguió un martillo pero ya no tienes HP!";
  14. HumanoPierde();
  15. }
  16. }
  17. function MarioDK () {
  18. if (User == "Humano") {
  19. IAHP = IAHP-Ataque;
  20. if (IAHP > 0) {
  21. TerminandoTurnoHumano();
  22. } else {
  23. HumanoGana();
  24. }
  25. } else {
  26. // Aquí la IA debería poder elegir otra opción, pero es otro tema.
  27. HumanoHP = HumanoHP-Ataque;
  28. Mensaje = Mensaje+"\n¡Donkey Kong rival te dañó!";
  29. if (HumanoHP > 0) {
  30. TerminandoTurnoDeIA();
  31. } else {
  32. HumanoPierde();
  33. }
  34. }
  35. }

1era cuestión:
¿Es buena idea agregar un objeto invisible para que se capten unas teclas u otras según si la carta da opciones o no?

Creo que sí, una alternativa sería que fuese un único objeto y que esté haciendo un if constantemente de "si no tiene opciones, ver si se presiona A, sino ver si se presiona <- o ->", lo cual para mí es peor.
Lo malo en mi método es que el objeto se autoremueve luego de haber ejecutado funciones que llaman a otras así que no sé realmente cuando se remueve xP Aunque por ahora no noté errores. Además, un objeto con igual nombre es agregado cuando se recibe una carta, así que se sustituye al que hubiera si no se removió.
Otra opción es poner el código en frames y que haya goto al anterior, pero eso parece peor, es el mismo código en 2 frames (excepto por el goto) o se ejecuta cada 2 frames.
¿Se les ocurre algo mejor?

2nda cuestión:
Los objetos sParaCartaSimple y sParaCartaOpcional usan a funciones de la zona raíz, pero sólo los usan ellos, diferente cada uno, es decir las funciones podrían ser código en ellos ¿no sería mejor así?

El problema es que esos códigos deben hacer cambios en la raíz, entonces si estuvieran directamente en los objetos habría que poner _root. delante de varias variables, por eso a pesar del lío me parece mejor así como está (al llamar a la función de root, sólo habría que poner un solo _root delante) ¿pero no hay alguna forma mejor?
¿A mi Flash (Macromedia 5) le enlentece referencias como
_root.CartaUsada = _root.Cartas[_root.NroDeCartaDeHumano];
comparado con sin _root, o al compilarse el código da igual?


Pregunté a GPT sobre esto e interpretó que puede haber 2 movieclips a la vez chequeando teclas. No, es uno u otro. Sobre otras cosas quedé algo saturado, lo pensaré otro día.
https://poe.com/s/82EsYOmKzQuiyy9noUYz
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines