Autor Tema: Re-iniciándome en la programación del C64  (Leído 1450 veces)

migrator

  • Commodorista
  • ***
  • Mensajes: 67
  • SYS 0
    • Ver Perfil
Re-iniciándome en la programación del C64
« en: Agosto 23, 2019, 08:53:05 »
Hola a todos.

Últimamente me ha dado por ponerme de nuevo con la programación del C64. Bueno, en realidad iniciarme con la programación del C64, pues yo salté del C16 al Amiga, aunque hice algunas cosillas en el C64.

La cuestión es que en mis tiempos mozos ;D me dedicaba a realizar versiones propias para el C16 de los juegos de C64 que veía en casa de mis amigos, y me quedó el gusanillo de hacer algo serio para el C64.
Siempre utilicé el lento BASIC con algunas rutinas en código máquina para acelerar determinadas cosas (el C16 carece de sprites por hardware, y ahora me he propuesto hacer un juego totalmente en ensamblador. Pero, aquí está el problema, hay muchas cosas básicas que todavía me quedan por aprender. Os cuento.

Para refrescar un poco el CM he programado algún scroll de texto, contadores decimales en pantalla (para puntuaciones) , capturas de teclado, control de RAM de pantalla y de color, movimiento de sprites, música por interrupciones, multiplexación de sprites y otras cosas básicas.

Por cierto, estoy usando el CBMprgStudio.

Lo último que he hecho es un Sprite que cae desde la parte superior de la pantalla y parándose sobre los caracteres que defino como "suelo", para control de colisiones como paso previo para un juego de plataformas.

El problema, que no sé si es la "forma correcta" de hacerlo o si hay alguna manera más sencilla y/o directa.

Básicamente recojo las coordenadas de sprite, les resto las no visibles (el offset) las convierto a las coordenadas del caracter bajo el Sprite. Recojo el carácter que hay en esa posición y si es un carácter "sólido" compruebo la diferencia entre las coordenadas de éste y del Sprite y ajusto el Sprite hasta que esa diferencia sea 0 para que quede bien posicionado sobre el carácter "suelo".
Esto me funciona en esta prueba, pero en un juego me obligaría a hacerlo en las 2 esquinas inferiores del Sprite (los pies) y en los laterales (para controlar las paredes).

¿Sería está la forma correcta o me estoy liando mucho?

Otra cosa. Me imagino que hay diferentes métodos para almacenar las pantallas con enemigos y sus movimientos, pero ¿Alguna más o menos sencilla que me sirva como guía para adaptarla a lo que necesite?

Tampoco sé que rutinas sería interesante (o necesario) meterlas en interrupciones, ¿Entrada, colisiones, movimiento de sprites...?

Toda ayuda me vendría genial, porque aunque tengo bastante experiencia programando juegos nunca lo hice totalmente en ML. Para aprender hay que darse muchas tortas, pero siempre que se aprenda la dirección adecuada, no para estrellarse continuamente contra un muro por no saber hacia dónde ir.

Muchas gracias.

xwolfoverride

  • Commodorista
  • ***
  • Mensajes: 52
  • RUN
    • Ver Perfil
    • XWolf Blog
Re:Re-iniciándome en la programación del C64
« Respuesta #1 en: Agosto 23, 2019, 09:16:31 »
Has comentado que la pantalla es un scroll no?
Lo cierto es que aún conozco poco sobre el scrolling en C64 se que tiene, pero no se que de cuanto buffer off-screen dispones. Es decir cuantos caracteres puedes tener en la memoria de la pantalla sin que se vean.

Por un lado, se que hay un registro que indica colisión con la pantalla, pero es un flag 0/1 por lo que solo te indica si hay o no, pero no dónde ni con que valor del caracter, por lo que tu técnica es válida, además por lo general en plataformas puedes tener pixeles transparentes en un caracter que realmente quieres tratarlo cómo caracter solido entero y cómo el detector de colisión es basado en pixeles, no te va a detectar la colisión, O te va a detectar una colisión con un caracter que está encima del sprite y no en los pies.

Por eso creo que tu técnica es válida, solo que si tienes que cambiar la información de pantalla para adaptar el scroll, creo que es mejor que intentes detectar la colisión con la fuente de datos del mapa, y no con la versión en pantalla, ya que se puede dar el caso de sprites con un "pie" fuera del scroll en vídeo y que no detectes suelo

migrator

  • Commodorista
  • ***
  • Mensajes: 67
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #2 en: Agosto 23, 2019, 10:28:09 »
Gracias, xwolfoverride.

No, la pantalla no es scroll. Hice puebas de scroll para refrescar un poco el ensamblador, pero, de momento es una pantalla estática.

Me quedo con lo que me has dicho de que el método que utilizo es el correcto. Es básicamente lo que quería saber. Sabiendo esto, se me plantea la posibilidad de hacerlo de dos formas:

1.- Recoger esos datos (laterales y las dos esquinas inferiores) mediante una interrupción, para tener controlado en todo momento el sprite, y guardarlos en memoria para poder capturarlos en la rutina de movimiento.
2.- Hacerlo solo en la rutina de movimiento.

Con la primera opción tendría siempre controlado al sprite, pero serían ciclos perdidos en el caso de no producirse ningún movimiento. Con la segunda el sprite solo lo controlaria si se produce movimiento, ahorrando ciclos pero dependiendo de las condiciones almacenadas la última vez que se movió. Como tengo varias ideas sobre qué juego hacer ya me decidiré por una u otra según las necesidades.

Por otra parte, para las pantallas me había planteado tener una tabla para el diseño de cada una de ellas en la que los primeros bytes sirvieran de puntero hacia la rutina de comportamiento de su contenido (enemigos, mayormente). No sé si esto es lo adecuado o, por el contrario, es mejor generar un patrón de movimiento para cada tipo de enemigo y simplemente pasarles, en cada pantalla, los parámetros particulares de cada una de ellas.

¡Buff, ya no estoy tan acostumbrado al ahorro de ciclos y memoria como hace 30 años!
¡Cómo ha ido cambiando en estos años la forma de de enfrentarse al desarrollo de una aplicación!

Últimamente me estoy leyendo (y releyendo en el caso de muchos libros clásicos) y aprendiendo cosas que antes había pasado por encima por no necesitarlas.
También estoy buscando el código de algún juego clásico comentado para poder analizarlo, pero no encuentro ninguno.

Al menos no empiezo de cero, pero me da que voy a ser bastante pesado por aquí si quiero llevarlo a buen puerto.
« última modificación: Agosto 23, 2019, 10:43:41 por migrator »

xwolfoverride

  • Commodorista
  • ***
  • Mensajes: 52
  • RUN
    • Ver Perfil
    • XWolf Blog
Re:Re-iniciándome en la programación del C64
« Respuesta #3 en: Agosto 23, 2019, 10:59:13 »
En este hilo:

https://commodoremania.com/foro/index.php/topic,1960.0.html

Hay vídeos de youtube sobre disección de juegos. lo mismo te puede ayudar, ya que los analiza y comenta cómo hacen ciertas cosas algunos juegos comerciales.

migrator

  • Commodorista
  • ***
  • Mensajes: 67
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #4 en: Agosto 23, 2019, 11:06:09 »
Muchas gracias. ¡A estudiar!

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 9573
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Re-iniciándome en la programación del C64
« Respuesta #5 en: Agosto 23, 2019, 12:56:52 »
Quizás ese hilo te sirva, ahí intento poner todo lo que encuentro sobre desarrollo de juegos.

¿Puedes contar algo más del juego que vas a hacer?, recuerda que aquí en el foro hay gente que sabe hacer gráficos y música, por si necesitas apoyo en alguna de esas tareas.

migrator

  • Commodorista
  • ***
  • Mensajes: 67
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #6 en: Agosto 23, 2019, 15:32:37 »
Pues estoy en ello, dándole vueltas al tipo de lío en el que me quiero meter.
En el C16 deje inconcluso un juego de un explorador que quedaba atrapado en una caverna y tenía que salir de ella (original al 100%, lo sé). Era una aventura de las de buscar objetos y usarlos en el sitio correcto. Pero el guión era muy rocambolesco con situaciones un tanto absurdas (había zonas a las que se accedía por cuerdas, otras por escaleras y algunas que solo eran accesibles ¡agarrado a un globo! que había que conseguir de una forma determinada tras encontrar el helio para inflarlo. Incluso había que ir a la NASA para colarse en un cohete y llegar al cielo, en donde San Pedro nos daría la llave de... ¡De locos! Habría que darle un par de vueltas a ese guión. Lo que con 15 años nos parece un prodigio de imaginación, con cierta edad uno se pregunta qué se había fumado en aquel entonces.
Ya tenía hecho el mapeado y los gráficos (y lo tengo todo localizado después de tanto tiempo), que habría que actualizar un poco si me pongo a ello.

Así que esa es una opción, pues se me quedó la espinita clavada. Pero para comenzar estaba pensando en algo más sencillo como paso previo.

Lo importante es disfrutar con lo que se haga e intentar hacerlo lo mejor posible.

Ya iré informando (y preguntando), y si consigo que vaya adelante nunca vienen mal colaboradores. Pero ahora mismo no voy a pedirle a nadie que colabore en un proyecto sin que haya algo sólido y pueda garantizar que no se trabaje por nada.

Pero se agradece tener a tanta gente entusiasta de este maravilloso equipo, y con tantos conocimientos como hay aquí.
« última modificación: Agosto 23, 2019, 15:36:57 por migrator »

Dashiad

  • Commodorista
  • ***
  • Mensajes: 99
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #7 en: Agosto 24, 2019, 00:13:50 »
Hola! Yo estoy en lo mismo que tu, haciendo tonterias previas a algún juego serio...Tras haber montado mapa con scroll, ahora estoy liado con la estructura general del juego.

Sobre lo que comentas, yo pondría un "pero" a una cosa:
Básicamente recojo las coordenadas de sprite, les resto las no visibles (el offset) las convierto a las coordenadas del caracter bajo el Sprite.
Dependiendo del juego, que la posición del sprite sean las coordenadas guardadas en los registros del VIC, puede servirte o no.
Supón que tienes una bala hecha con un sprite, que se mueve X pixeles en horizontal, en cada repintado. Si las coordenadas de la bala son las del sprite, podría atravesar una pared que tuviera menos de X pixeles de ancho.
Si la bala se mueve de 8 en 8 pixeles, y puede haber paredes de hasta 4 pixeles de ancho, la bala, en cada actualizacion, debería moverse 4 pixeles, comprobar colisiones, luego otros 4...Básicamente, interpolar.

O sea, la idea sería romper la dependencia entre el repintado y el movimiento.
En algunos juegos, cuando habia mucho enemigo en pantalla, se ralentizaba todo. Se podría hacer que el juego repintara cada frame, o cada 2 frames, o cada 3, pero que las cosas no fueran más "lentas", porque el movimiento y las colisiones seguirian calculándose cada frame. Si las posiciones las guardas directamente en los registros de los sprites, tendrías parpadeos y cosas raras en pantalla.


migrator

  • Commodorista
  • ***
  • Mensajes: 67
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #8 en: Agosto 24, 2019, 08:27:06 »
Gracias por el aporte.

Sí, ya caí en ello, por eso realizo el cálculo del carácter bajo el Sprite teniendo en cuenta que los caracteres son de 8x8.

Tras calcular las relativas al carácter bajo el sprite, las paso (de nuevo) a coordenadas de pantalla, les vuelvo a sumar el Offset y calculo la diferencia entre ese resultado y las del Sprite, sabiendo que me tiene que dar un resultado entre 7 y 0, con lo que reposiciono el Sprite hasta que este resultado sea 0.

Es decir, algo así para la coordenada Y de un sprite:

Supongamos un sprite en (x,79).
Supongamos un OFFSET en Y de 29.

    1.- Restamos el offset a la coordenada del sprite para obtener su posición en la parte de texto (el fondo) de la pantalla.

79-29 = 50

  2.- Ahora calculamos la coordenada de un carácter ahí situado, para ello lo dividimos entre 8 y obteniendo el entero (no necesito realizar cálculos de decimales, así que con tres desplazamientos de bits a la derecha me sirve. Esto me dará el carácter en el que se encuentra la parte inferior de sprite, pero yo necesito el que hay bajo él, así que le sumo 1

50/8 = 6 + 1 = 7  <-- Esta será la fila del carácter

  3.- Como hemos despreciado los decimales, hago la conversión inversa para obtener la diferencia real entre el carácter y el sprite.

7*8 = 56 + 29 (offset) = 85 <-- Esta es la coordenada equivalente del carácter bajo el sprite

Teniendo esto, sé que la diferencia entre las coordenadas del sprite y del carácter es:

85-79 = 6 <-- Esto es lo que queda entre el "suelo" y el sprite, que siempre ha de ser inferior a 8, así que ajusto el sprite para que sea 0 (exactamente encima de él).

Estoy haciendo pruebas calculando también el carácter en el que se encuentra el sprite e igualando a 7 (justo por encima del siguiente).

De esta forma me está funcionando. Además, sabiendo la posición del carácter, lo recojo para saber qué carácter es y, de esa forma, saber el tipo al que corresponde y si hay que ignorarlo en el cálculo (por ser atravesable) o no.

Esto me está funcionando perfectamente. La única forma en la que veo que puede fallar es en la que tú comentas, pero solo por movimientos superiores a 8 píxeles, en los que el desplazamiento sea superior a 1 carácter y, por lo tanto, se quedarían caracteres intermedios sin calcular y alguno podría ser un muro o suelo y nuestro sprite lo saltaría.  La solución fácil, el personaje no utilizará armas con balas, sino un potente láser que lo atraviesa todo ;D

Por eso no sé si me estoy liando un poco y si hay formas más sencillas de hacerlo, ya que este método son muchos cálculos y muchos ciclos en cada redibujado, que ahora está bien pero cuando haya más cosas que calcular no sé, no sé.
Es hora de seguir practicando y poner en práctica todo lo que aprenda con los enlaces que me habéis pasado.
« última modificación: Agosto 24, 2019, 11:27:21 por migrator »

migrator

  • Commodorista
  • ***
  • Mensajes: 67
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #9 en: Agosto 24, 2019, 09:13:53 »
Pero cierto, no se cómo hacéis vosotros, pero yo para los gráficos digo siendo clásico. Prefiero dibujarlos "a la antigua" sobre el papel milimetrado y luego pasarlos a un editor, me da la impresión de que lo puedo controlar todo más.

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 9573
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Re-iniciándome en la programación del C64
« Respuesta #10 en: Agosto 24, 2019, 13:48:56 »
Era una aventura de las de buscar objetos y usarlos en el sitio correcto. Pero el guión era muy rocambolesco con situaciones un tanto absurdas (había zonas a las que se accedía por cuerdas, otras por escaleras y algunas que solo eran accesibles ¡agarrado a un globo! que había que conseguir de una forma determinada tras encontrar el helio para inflarlo. Incluso había que ir a la NASA para colarse en un cohete y llegar al cielo, en donde San Pedro nos daría la llave de... ¡De locos! Habría que darle un par de vueltas a ese guión. Lo que con 15 años nos parece un prodigio de imaginación, con cierta edad uno se pregunta qué se había fumado en aquel entonces

Jajajajajja cierto, cierto :D

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 9573
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Re-iniciándome en la programación del C64
« Respuesta #11 en: Agosto 24, 2019, 13:50:03 »
Sí, ya caí en ello, por eso realizo el cálculo del carácter bajo el Sprite teniendo en cuenta que los caracteres son de 8x8.

Si el calculo no se puede optimizar más (que no lo sé), lo único que te permitiría optimizar más podría ser usar tablas con valores precalculados (que no sé si este sea el caso), por comentar algo :P

Dashiad

  • Commodorista
  • ***
  • Mensajes: 99
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #12 en: Agosto 24, 2019, 23:47:48 »
Supongamos un sprite en (x,79).
Supongamos un OFFSET en Y de 29.
A qué llamas offset aqui?
La posición del sprite la defines por su esquina superior izquierda del sprite "hardware", por el bounding box de la parte "activa" del sprite (cuadrado que contiene a todos los pixeles no transparentes de un determinado frame/estado), o por el centro del sprite (o bounding box)?

Si el sprite es 24*21, pero el area dibujada (en un cierto frame/estado), es de 18x16, es a eso a lo que llamas "offset"?
Si es eso, ese bounding box puede estar precalculado, no hace falta hacer la resta en cada iteracion (que creo que es lo que haces en el paso 1) ).

Para los puntos 2 y 3, se podría jugar restando a la posicion del sprite, la diferencia entre el 0 del sprite, y el 0 de pantalla. Con esa resta, los 3 bits menos significativos dan "los decimales", mientras el resto de bits da el caracter.(Estoy sólo pensando en voz alta...son cosas que tengo "apuntadas" para cuando me meta en estos problemas)
La única forma en la que veo que puede fallar es en la que tú comentas, pero solo por movimientos superiores a 8 píxeles, en los que el desplazamiento sea superior a 1 carácter y, por lo tanto, se quedarían caracteres intermedios sin calcular y alguno podría ser un muro o suelo y nuestro sprite lo saltaría.  La solución fácil, el personaje no utilizará armas con balas, sino un potente láser que lo atraviesa todo
Tampoco puede desplazarse (saltando, cayendo, etc) más de 8 pixeles a la vez.
Hay más casos en los que utilizar el registro de posición de los sprites para almacenar la posición del personaje, da problemas:
- Como decía antes, cuando quieres hacer frameskip sin perder velocidad en el juego.
- Cuando el personaje se puede mover, con scroll, por un mapa más grande que la pantalla (diferencia entre coordenadas de mundo, y coordenadas de pantalla).

migrator

  • Commodorista
  • ***
  • Mensajes: 67
  • SYS 0
    • Ver Perfil
Re:Re-iniciándome en la programación del C64
« Respuesta #13 en: Agosto 25, 2019, 00:05:41 »
Citar
A qué llamas offset aqui?
Citar
Para los puntos 2 y 3, se podría jugar restando a la posicion del sprite, la diferencia entre el 0 del sprite, y el 0 de pantalla

Precisamente eso es lo que hago en el punto 1, restarle el alto del borde (a lo que estoy llamando offset) a la coordenada y del sprite para igualar el 0 del sprite y el 0 de los caracteres.

Citar
Hay más casos en los que utilizar el registro de posición de los sprites para almacenar la posición del personaje, da problemas:
- Como decía antes, cuando quieres hacer frameskip sin perder velocidad en el juego.
- Cuando el personaje se puede mover, con scroll, por un mapa más grande que la pantalla (diferencia entre coordenadas de mundo, y coordenadas de pantalla).

Hace tiempo que no programo nada en ensamblador del C64 (o C16), pero recuerdo que cuando hacía algo con scroll mayor que la pantalla guardaba unas coordenadas en el mundo y otras locales a la pantalla y calculaba todo lo local en referencia a esas coordenadas en la pantalla. Las coordenadas en el mundo solo las utilizaba para lanzar eventos especiales, como alcanzar cierto lugar del mapa.

He estado viendo alguno de los fuentes del enlace de josepzin y cuando llego a las colisiones... ¡utiliza las colisiones por hardware! así que tendré que seguir revisando otros ejemplos.

Estás haciendo que le dé muchas vueltas a la forma en la que realizarlo, me gusta, me gusta. Así es como se aprende. Muchas gracias.

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 9573
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Re-iniciándome en la programación del C64
« Respuesta #14 en: Agosto 25, 2019, 00:25:54 »
Si haber hecho ningún desarrollo, yo siempre pensé que una buena manera de detectar las colisiones es combinar la detección por hardware y por software.

Me explico: la detección por hardware está bien para algunos casos, pero cuando hay multiplexión o una caja de colisión distinta no sirve, pero quizás sí que sirva para saber cuando calcular la colisión por software, que viene a ser: si no hay ninguna colisión por hardware entonces no tiene sentido comprobar si hay colisión por software.