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


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


  Mostrar Mensajes
Páginas: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 25
1  Media / Diseño Gráfico / Re: ¿En un espacio cómo separar objetos por la misma distancia? en: 8 Noviembre 2025, 16:58 pm
Primero tienes que calcular la distancia entre las figuras de los extremos, es decir, entre el extremo izquierdo de la última y el extremo derecho de la primera. Luego, a este valor le restas la suma de los anchos de las (3) figuras interiores. Esto es la cantidad total de espacio en blanco que queda. Ahora simplemente divide esto entre la cantidad de "huecos" que debe haber: 4 (este número es igual a la cantidad total de figuras menos 1). Este es el espacio que debes dejar entre cada figura.
2  Programación / Programación General / Re: ¿Sugerencias sobre detectar colisiones? en: 30 Octubre 2025, 01:06 am
En ese caso, el uso de cajas simples debería bastar. Ten por seguro que casi todos los juegos retro usan ese método o alguna variación. Simplemente, como te dije antes:

Citar
se busca de forma intencional que las áreas de colisión sean un poco más pequeñas o un poco más grandes (según convenga) que el propio sprite, para mejorar la jugabilidad.

Sin necesidad de ver el código del Donkey Kong original, es muy obvio que las cajas de colisión son más pequeñas que los sprites.

En cuanto a los paralelogramos, el método no es inútil, pero sí innecesario en este caso. La detección de colisiones se hace más complicada, y que yo sepa, Flash no la implementa (lo único que hará será verificar la colisión entre las áreas rectangulares que delimitan esas figuras), así que tendrías que programarla tú. Y aún si Flash lo hiciera por ti, necesariamente va a ser menos eficiente. Independientemente del método que se use, detectar colisiones con paralelogramos será al menos unas 30 o 40 veces más lento que hacerlo con cajas "simples" (alineadas al eje). En la práctica, como las computadoras modernas son rápidas, probablemente no haya problemas de rendimiento, y aún si pudieras tener cientos de barriles en pantalla (cosa que obviamente ya en el juego no sucedería), se pueden realizar optimizaciones (separar la verificación de colisiones en dos fases, dividir el nivel en secciones/sectores), pero no deja de ser trabajo extra que no se justifica para juegos de este tipo.

Otras alternativas más eficientes serían: usar zonas de forma circular y verificar la colisión comparando la distancia al centro del círculo con su radio, o cápsulas, que se pueden implementar como un rectángulo con semicírculos en dos extremos opuestos, pero tampoco las considero necesarias, puesto que el método de las cajas basta y sobra en este caso. El Donkey Kong probablemente haga algo así:



Aunque pueda parecer que las cajas son muy pequeñas, puedes hacer pruebas en un emulador y verás que son bastante aproximadas a las que el juego original de arcade debe usar. En todo caso, puedes hacer ajustes o incluso usar cajas separadas para la cabeza y el cuerpo si quieres algo un poco más preciso, pero sólo un poco, pues paradójicamente, las colisiones muy exactas pueden perjudicar la jugabilidad y causar frustración. Como regla general, y en particular en juegos de plataformas, suele ser aconsejable que, cuando se trata de cosas que pueden dañar al jugador (enemigos, balas, barriles), las cajas de colisión sean más pequeñas, y en caso contrario (plataformas, escaleras, power-ups), hacerlas exactas o incluso más grandes, según cada caso. De igual manera, por lo general es conveniente tratar los pies de manera aparte, ya que su principal uso es aterrizar en superficies (o pisar enemigos, pero aquí no es el caso), por lo cual su caja es algo más precisa y muchas veces no se toma en cuenta para colisiones con enemigos, así que yo te aconsejaría que únicamente la uses para detectar si Mario está sobre una plataforma, pero no con barriles y bolas de fuego. Con esto consigues dar al jugador un margen de tolerancia para la parte inferior del sprite.
3  Programación / Programación General / Re: ¿Sugerencias sobre detectar colisiones? en: 22 Octubre 2025, 01:31 am
Puede que te estés complicando de más. La gran mayoría de los juegos de plataformas 2D simples usan cajas alineadas a los ejes, es decir, sin rotar, como lo hacías al principio. Simplemente usan varias (Super Mario Bros de NES usaba 3: cabeza, pies y torso), y, de ser necesario, son distintas para cada frame de la animación. Incluso juegos como Street Fighter o Fatal Fury lo hacen así. Que la colisión tenga unos cuantos pixels de imprecisión es irrelevante. A escala normal y en plena acción prácticamente no se nota, y por eso esa técnica sigue siendo usada en la actualidad. Y lo que es más, casi siempre se busca de forma intencional que las áreas de colisión sean un poco más pequeñas o un poco más grandes (según convenga) que el propio sprite, para mejorar la jugabilidad.

Si entiendo lo que pones en tu último mensaje, ¿quieres que las zonas de colisión sean paralelogramos, pero que tú las crees como rectángulos simples, y al ejecutar el programa, se deformen/roten para formar los paralelogramos deseados? Para hacer esto último necesitarías encontrar la transformación afín que haga esa conversión. Y luego usar alguna de las técnicas que hay para detectar colisiones entre polígonos convexos. Nada de eso es muy difícil (sólo hace falta un poco de álgebra lineal) pero sí más que el método de las cajas "sin rotar",  además de  ser menos eficiente y mucho más tedioso, pues aunque en ciertos casos y para ciertos tipos de juegos sí se llegan a usar polígonos convexos como zonas de colisión, éstas siempre se generan directamente con herramientas visuales como las que proporcionan los motores. En mi opinión no vale la pena, suponiendo que lo que buscas son colisiones para un juego tipo Mario clásico, cosa que tampoco has especificado, pero si es el caso, yo usaría directamente las cajas alineadas al eje y ya.
4  Programación / .NET (C#, VB.NET, ASP) / Re: Bordes redondeado de un cuadrado o rectáncugo. en: 27 Octubre 2024, 20:07 pm
Lo que pasa es que los únicos códigos realmente ASCII son los del 0-127. Los demás son una extensión no estándar y sus caracteres varían según la página de códigos configurada. Para usarlos necesitas configurar la consola con la codificación correcta, pero como estamos en 2024, no tiene sentido seguir usando ASCII (extendido) para eso, así que olvídate de esa tabla y mejor usa Unicode, que sí es universal. Vas a necesitar buscar los códigos (o puntos de código, como se les conoce) Unicode de esos caracteres que quieres usar, y por suerte, son tan comunes que tienen su propia entrada en la Wikipedia: https://en.wikipedia.org/wiki/Box_Drawing

Así que lo primero que debes hacer es asegurarte de que tu consola use alguna codificación Unicode. La más recomendable y universal es UTF-8, y la configuras así:

Código
  1. Console.OutputEncoding = Encoding.UTF8;

a partir de aquí, ya puedes imprimir caracteres especiales Unicode, usando el prefijo \u. Por ejemplo, en la tabla que hay en el link de la Wikipedia, puedes ver que el caracter ╔ tiene asignado el punto de código U+2554, por lo que lo puedes imprimir así:

Código
  1. System.Console.Write("\u2554");
5  Programación / .NET (C#, VB.NET, ASP) / Re: Salir de un void en: 31 Agosto 2024, 02:50 am

En cuanto al return, me imagino que te refieres que justo antes que acabe un void o función, tenga return true; o el return false;

Sí, pero las void no pueden devolver valores, así que tendrías que cambiar las funciones de los submenús a bool.

Te pongo un ejemplo genérico (y medio en pseudocódigo) de cómo podrías hacerlo:

Código
  1. void MenuPrincipal()
  2. {
  3. bool salir = false;
  4. do {
  5. dibujar menu principal;
  6. leer opcion;
  7. switch (opcion) {
  8. case 1:
  9. Ajustes();
  10. break;
  11. case 2:
  12. SubMenuB();
  13. break;
  14. etc ...
  15. case N:
  16. salir = true;
  17. break;
  18.  
  19. }
  20. } while (!salir);
  21. }
  22.  
  23. bool AjustesPrincipal()
  24. {
  25. // La variable inicio indicara si se selecciono volver al inicio
  26. bool salir = false, inicio = false;
  27. do {
  28. dibujar menu;
  29. leer opcion;
  30. switch (opcion) {
  31. case 1:
  32. salir = inicio = Volumen();
  33. break;
  34. case 2:
  35. salir = inicio = SubMenuB();
  36. break;
  37. etc ...
  38. case Atras:
  39. salir = true;
  40. break;
  41. case Inicio:
  42. salir = inicio = true;
  43. break;
  44. }
  45. } while (!salir);
  46.  
  47. return inicio;
  48. }

Con Volumen y todos los demás submenús harías esencialmente lo mismo que con AjustesPrincipal:

Código
  1. bool Volumen()
  2. {
  3. bool salir = false, inicio = false;
  4. do {
  5. dibujar menu;
  6. leer opcion;
  7. switch (opcion) {
  8. case 1:
  9. instrucciones;
  10. break;
  11. case 2:
  12. // Si volumen llamara a un submenu, habria que hacerlo tambien asi:
  13. salir = inicio = SubMenu();
  14. break;
  15. etc ...
  16. case Atras:
  17. salir = true;
  18. break;
  19. case Inicio:
  20. salir = inicio = true;
  21. break;
  22. }
  23. } while (!salir);
  24.  
  25. return inicio;
  26. }

Puede que tengas que reestructurar un poco tu código, pero eso debería funcionar.

Como mencionaste lo de los goto, si acaso necesitaras que cuando se seleccione "Atrás" o "Inicio", la función retorne inmediatamente sin pasar por el while, podrías hacerlo así:

Código
  1. case 2:
  2. // Si volumen llamara a un submenu, habria que hacerlo tambien asi:
  3. inicio = SubMenu();
  4. if (inicio)
  5. return true;
  6.  
  7. break;
  8. etc ...
  9. case Atras:
  10. return false;
  11. break;
  12. case Inicio:
  13. return true;
  14. break;
  15. }
  16. } while (!salir);
  17.  
  18.  

Así que ni siquiera en este caso hay necesidad de gotos. De hecho, prácticamente nunca hay que usarlos (hay poquísimas excepciones donde pueden ser útiles).
6  Programación / .NET (C#, VB.NET, ASP) / Re: Salir de un void en: 30 Agosto 2024, 16:54 pm
Primero que nada, deberías repasar los fundamentos, porque te estás complicando mucho con cosas más bien triviales, además de que la sugerencia de quitar el bucle era tan disparatada, y tan obvio lo que iba a suceder, que no sé cómo se te ocurrió siquiera probarla.

En cuanto al problema, en general, si tienes una secuencia de llamadas de funciones tipo:

A  --> B --> C --> D

deberías intentar evitar que cualquiera de esas funciones llame a alguna de las anteriores (B no debería llamar a A, C no debería llamar ni a A ni a B, etc.). Si por ejemplo, estando en D, quieres volver al submenú anterior (C), la solución NO es llamar a C, sino simplemente dejar que D termine su ejecución, retornando de forma normal.

Si también quieres que, por ejemplo, desde D o C sea posible volver al menú inicial (A), lo único que cambia es que estas funciones deberían devolver un valor que indique que se seleccionó la opción del menú principal. Suponiendo que sea un bool, lo que harías sería que cuando desde una función se desea volver al inicio, ésta termine con un return true (y en todos los demás casos, retornar false). Asimismo, todas las funciones, al invocar a otra, deberán verificar el valor que retorne, y si es true, deberán terminar su ejecución, devolviendo a su vez true, es decir, este valor se propaga a lo largo de la secuencia de llamadas, lo cual hará que termines volviendo al menú inicial de forma limpia.

Para que todo esto funcione, tienes que cambiar tus funciones de manera que los menús se impriman dentro de los bucles.
7  Programación / Programación C/C++ / Re: alguien me puede decir en que falla en: 6 Agosto 2024, 21:31 pm
Es verdad que no es recomendable usar eñes o acentos en los nombres de identificadores. Y eso que desde hace más de 10 años los estándares de C y C++ definen un buen rango de caracteres Unicode válidos, entre los cuales están vocales con acento y la ñ, por lo que no tiene nada de extraño que los compiladores modernos los acepten, de hecho es lo esperado. El problema viene más bien con los editores de código y los IDEs, pues aunque la mayoría trabajan sin problemas con Unicode, hay que asegurarse de que usen exactamente la misma codificación que el compilador que vamos a usar. En cambio, si nos limitamos únicamente a los caracteres ASCII estándar de toda la vida, nunca tendremos problemas.

Y por cierto, no confundamos compiladores con IDEs, que son cosas completamente diferentes. Eso ocasiona muchos problemas entre principiantes. Aquí mismo en el foro he visto cualquier cantidad de hilos donde el problema es justo ése, y luego les dan "soluciones" completamente erróneas debido a que ni quien preguntó ni quien contestó entendían esa diferencia. CLion es sólo un IDE. Los compiladores son GCC, Clang, Visual C++, MinGW, entre otros, y los IDEs simplemente los invocan, evitándonos teclear comandos. Si en Windows CLion incluye MinGW, es sólo para conveniencia del usuario, ya que son herramientas completamente independientes. La idea es que cada uno configure su IDE para que use el compilador que prefiera. Incluso en el caso del propio CLion, si lo usamos con MSVC, es casi seguro que el código con eñes así, de inicio, no va a compilar, ya que, a diferencia de MinGW, MSVC espera que los archivos fuente, si tienen caracteres no ASCII, incluyan marca de orden de bytes, pero los editores/IDEs no suelen ponerla de forma predeterminada, por lo que habría que cambiar manualmente eso en la configuración.

Pero reitero, si omitimos caracteres "especiales", nos facilitamos mucho las cosas y ni siquiera necesitamos saber nada de lo anterior. Bueno, salvo la distinción IDE/compilador: eso sí es indispensable tenerlo bien claro, especialmente si programamos en C o C++.
8  Programación / Programación General / Re: ¿Cómo la PC usa los códigos? en: 2 Marzo 2024, 00:09 am
Lo que te aconsejaría es que simplemente programes como te sea a ti más conveniente. Incluso al crear programas en lenguajes que generan código nativo, como C y C++, determinar a priori si llamar a una función es más/menos rápido, genera código más/menos grande, etc. que escribir directamente el código, es prácticamente imposible, y si en algún lugar lees lo contrario, quien lo escribió no tiene idea de lo que habla. Únicamente analizando el código exacto en cada caso se pueden hacer estimaciones, y aún así es muy complejo y depende de muchas cosas.

Además, tú programas en Flash, el cual hasta donde sé, no compila el ActionScript a código nativo sino a byte code que el reproductor (ya sea el independiente o el que se incluye en los .exe) ejecuta, por lo que casi cualquier explicación general que te den, sea ChatGPT o una persona, te servirá de poco o nada. Sólo alguien que conozca a fondo cómo funciona internamente Flash 5 podría contestar bien tus preguntas. Yo te podría contestar cómo es en los programas nativos, pero es casi 100% seguro que nada de eso aplica para Flash, por lo que no le veo mucho caso.

Lo que podrías hacer es probar escribiendo código de una y otra forma y comparar su ejecución. A menos que notes una diferencia importante (y realmente lo dudo), lo mejor es, como te dije al inicio, que programes como te guste a ti.
9  Programación / Programación C/C++ / Re: ayudaaa tengo un problema con ERROR: Id returned 1 exit status en: 7 Diciembre 2023, 05:08 am
Como te dijo MAFUS, es error del enlazador o linker. En este caso me imagino que será porque en la línea 15 pusiste prinf en lugar de printf (falta la 't').

Como referencia futura, siempre hay que poner los mensajes de error completos, pues eso de "ld returned..." por sí solo no sirve de mucho. Por fuerza el compilador/linker debe haberte dado más información (algo tipo "undefined reference to prinf"). Si usas un IDE, probablemente eso lo encuentras en una pestaña llamada output, build log, build messages o similar.
10  Programación / Programación C/C++ / Re: campos de bits en: 5 Octubre 2023, 19:42 pm
Sí, además de su función principal, volatile puede ser útil al depurar, y en casos como éste, también puede ser válido. Ojo, en ningún momento pretendo decir que todos los ejemplos de los primeros mensajes estén "mal". Se entiende que son cosas que uno normalmente no usaría para cosas más reales (aunque no está de más decir que, aún en códigos simples de ejemplo, violar las reglas nos puede traer más de una sorpresa desagradable).

Pero hay gente, incluso aquí en el foro, que a veces intenta ya no sólo experimentar sino implementar cosas de bajo nivel en sus programas. Por ejemplo, hace poco un usuario estaba haciendo algo similar a un editor hexadecimal. Mis recomendaciones, y lo que sigue, son sobre todo para quien quiera hacer cosas así, "reales".

Primero, para saber más sobre el tema, se puede googlear "strict aliasing" que es como se conoce a la regla de la que hablo en mi mensaje anterior. Y hay unas cosas que es fundamental entender: 1) Esto lo recalco de nuevo, cuando un programa hace cosas que el estándar cataloga como "undefined behaviour", el resultado, y las acciones del compilador, se vuelven impredecibles y éste puede hacer lo que quiera y a menudo hace cosas distintas en versiones distintas. Otra referencia más en FAQ de C: https://c-faq.com/ansi/undef.html . 2) Las optimizaciones que el compilador hace son totalmente dependientes del contexto. Dado un conjunto de líneas, su optimización puede ser totalmente distinta si las metemos en un for, o en dos for anidados, o si hay un if, o si las variables a las que acceden son globales o locales, o parámetros recibidos, o si la función es inline, etc., casi cualquier cosa lo altera. 3) Si el programa está escrito correctamente, un compilador jamás va a cambiar su comportamiento observable y su funcionamiento. Los ejemplos anteriores fallan únicamente porque violan el strict aliasing. Si se cambian de manera que respeten esta regla (usando unsigned char*, por ejemplo) se arreglan de forma permanente.

El calificador volatile no es realmente solución; en todo caso, es un parche temporal. De nuevo, si se googlea sobre el tema, van a salir muchos resultados de fuentes confiables, ninguno de los cuales sugiere siquiera a volatile como solución (los pocos que lo mencionan básicamente dicen: "no arregla el problema. Si te sirve es suerte"). El propio Linus Torvalds dijo lo siguiente cuando alguien supuso que volatile servía para arreglar estos problemas: "sí, volatile podría funcionar, pero es como matar una mosca con una bomba atómica (...) y no hay garantía de que el compilador no haga las optimizaciones, aún con acceso volatile, así que de todas formas es un punto irrelevante".

En términos prácticos, con volatile el compilador desactiva optimizaciones relacionadas con el acceso a las variables calificadas de esta manera (ya no las elimina, y para cada lectura, se traen sus valores de la memoria, etc.), pero eso no tiene nada que ver con el aliasing, lo que pasa es que en algunos contextos, como mis ejemplos, la única optimización que hace el compilador al encontrar UB coincide, de forma fortuita, con las que deshabilita volatile. Pero hay toda una gama de cosas que el compilador puede hacer (eliminar instrucciones que producen UB, reordenarlas, etc.) que vuelven a romper los programas a pesar de usar este calificador. No quiero que salga un mensaje aún más largo de lo que es, y no le veo sentido a poner más ejemplos (siempre se puede encontrar un "parche" que arregle de momento el programa, y luego poner un nuevo ejemplo con las instrucciones  reacomodadas/cambiadas de manera que el parche no funcione, y luego otro parche, y así nos pasamos la vida, porque no estamos arreglando el problema) pero nada de esto es hipotético, pasa en la realidad. Por no hablar de otros problemas, como la alineación incorrecta. De esto también hay ejemplos reales, incluso en x86-64 (donde algunas instrucciones producen errores de violación de acceso si los datos no tienen una alineación específica), y derivados de violar el strict aliasing.

La única solución general es seguir las reglas del lenguaje, en este caso, respetar el strict aliasing. Usar punteros char o memcpy (con ciertas precauciones) son maneras válidas. De esta manera nos quitamos de cualquier preocupación. Los programas van a funcionar siempre, en cualquier compilador que acepte la versión del lenguaje elegido, y con cualquier nivel de optimización. Si forzosamente necesitamos acceder a datos mediante punteros a tipos incompatibles (en unas pocas ocasiones puede ser conveniente), lo que se debe hacer es compilar con -fno-strict-aliasing o equivalente. Esto le dice al compilador que vamos a violar el strict aliasing, y así sabe exactamente que debe desactivar las optimizaciones específicas a esta regla (y no otras que podrían o no arreglar estos problemas en un contexto dado). Y todo esto sin los problemas de rendimiento que trae volatile.
Páginas: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 25
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines