Índice de entradas
Esta serie de artículos han sido traducidos a partir del documento "How to
Write ZX Spectrum Games" con permiso de su autor, Jonathan Cauldwell, un gran
desarrollador de juegos para el Spectrum, os recomiendo
visitar su Web donde está
el texto original. El documento original, y por tanto esta traducción, tiene
© Jonathan Cauldwell y solo puede duplicarse con permiso expreso por escrito
de su autor.
ACTUALIZADO 21/09/2022: Se añaden al final los fuentes, ahora ejecutables según el nuevo apéndice C
Números aleatorios
La generación de números aleatorios en código de máquina puede ser un problema
difícil para un programador novato.
En primer lugar vamos a dejar una cosa clara, no hay una cosa que sea un generador
de números aleatorios. La CPU se limita a seguir las instrucciones y no tiene
mente propia, no puede simplemente sacar un número de la nada sobre la base
de un capricho. En su lugar, tiene que seguir una fórmula que producirá una
secuencia impredecible de números que no parecen seguir ningún tipo de patrón,
y por lo tanto dan la impresión de aleatoriedad. Todo lo que podemos hacer es
devolver un falso (o seudo) número aleatorio.
Un método de obtención de un número seudo-aleatorio sería el uso de la secuencia
de Fibonacci, sin embargo el método más fácil y más rápido de generar un número
de 8 bits seudo-aleatorio en el Spectrum es poner un puntero hacia la ROM,
y examinar el contenidos del byte en ese lugar a su vez. Hay un pequeño inconveniente
en este método, la ROM de Sinclair contiene una área muy uniforme y poco aleatoria
hacia el final que es mejor evitar. Al limitar el puntero a, por ejemplo, los
primeros 8K ROM tenemos una secuencia de 8192 números de "al azar", más que
suficiente para la mayoría de los juegos. De hecho, todos los juegos que he
escrito con un generador de números aleatorios utilizan este método, o uno muy
similar:
; Sencillo generador de números seudo-aleatorio. ; Seguir un puntero a través de la ROM (a partir de una semilla), ; retornando el contenido del byte en esa posición. random ld hl,(seed) ; puntero ld a,h and 31 ; mantenerlo en los primeros 8Kb de ROM. ld h,a ld a,(hl) ; Obtener el número "aleatorio" de esa ubicación. inc hl ; Incrementar el puntero. ld (seed),hl ret seed defw 0
Vamos a poner nuestro nuevo generador de números aleatorios para utilizarlo
en nuestro juego Centipede. Todos los juegos centipede necesita setas - muchas-
dispersas al azar en todo el área del juego, y ahora podemos llamar a la rutina
aleatoria para que nos suministre las coordenadas donde se muestra cada seta.
Las partes resaltadas son los que tenemos que añadir.
; Queremos una pantalla en negro. ld a,71 ; tinta blanca (7) en fondo negro (0), ; con brillo (64). ld (23693),a ; establecer nuestros colores de pantalla. xor a ; forma rápida de cargar el acumulador con cero. call 8859 ; establecer el colore del borde permanente. ; Configurar los gráficos. ld hl,blocks ; dirección de los datos para los UDG. ld (23675),hl ; apuntar los UDG hacia aquí. ; De acuerdo, vamos a empezar el juego. call 3503 ; rutina ROM - borra la pantalla, abre el canal 2. ; Inicializar coordenadas. ld hl,21+15*256 ; cargar el par hl con las coordenadas iniciales. ld (plx),hl ; fijar las coordenadas del jugador. call basexy ; establecer las posiciones x e y del jugador. call splayr ; mostrar símbolo de la base del jugador. ; Ahora queremos llenar la zona de juegos con setas. ld a,68 ; tinta verde (4) en fondo negro (0), ; con brillo (64). ld (23695),a ; establecer nuestros colores temporales. ld b,50 ; comenzar con unas pocas. mushlp ld a,22 ; código del carácter de control para AT. rst 16 call random ; obtener un número 'aleatorio'. and 15 ; en vertical en rango de 0 a 15. rst 16 call random ; obtener otro número seudo-aleatorio. and 31 ; horizontal en el rango de 0 a 31. rst 16 ld a,145 ; el UDG 'B' es el gráfico de las setas. rst 16 ; poner la seta en la pantalla. djnz mushlp ; bucle hasta que todas las setas aparezcan. ; Este es el bucle principal. mloop equ $ ; Borrar el jugados. call basexy ; establecer las posiciones x e y del jugador. call wspace ; mostrar un espacio sobre el jugador. ; Ahora hemos eliminado el jugador y lo movemos antes de volverlo a mostrar ; en sus nuevas coordenadas. ld bc,63486 ; fila del teclado 1-5/joystick puerto 2. in a,(c) ; ver que teclas están pulsadas. rra ; bit mas externo = tecla 1. push af ; recordar el valor. call nc,mpl ; si está siendo pulsada, moverse a la izquierda. pop af ; restaurar el acumulador. rra ; siguiente bit (valor 2) = tecla 2. push af ; recordar el valor. call nc,mpr ; si está siendo pulsada, moverse a la derecha. pop af ; restaurar el acumulador. rra ; siguiente bit (valor 4) = tecla 3. push af ; recordar el valor. call nc,mpd ; si está está siendo pulsada, moverse hacia abajo. pop af ; restaurar el acumulador. rra ; siguiente bit (valor 8) = tecla 4. call nc,mpu ; si está está siendo pulsada, moverse hacia arriba. ; Ahora que se ha movido podemos volver a mostrar al jugador. call basexy ; establecer las posiciones x e y del jugador. call splayr ; mostrar al jugador. halt ; retardo. ; Saltar de nuevo al principio del bucle principal. jp mloop ; Mover al jugador a la izquierda. mpl ld hl,ply ; recordar, ¡y es la coordenada horizontal! ld a,(hl) ; ¿cuál es el valor actual? and a ; ¿es cero? ret z ; sí - no podemos seguir hacia la izquierda. dec (hl) ; restar 1 a la coordenada y. ret ; Mover al jugador a la derecha. mpr ld hl,ply ; recordar, ¡y es la coordenada horizontal! ld a,(hl) ; ¿cuál es el valor actual? cp 31 ; ¿está en el borde derecho (31)? ret z ; sí - no podemos seguir hacia la derecha. inc (hl) ; sumar 1 a la coordenada y. ret ; Mover al jugador hacia arriba. mpu ld hl,plx ; recordar, ¡x es la coordenada vertical! ld a,(hl) ; ¿cuál es el valor actual? cp 4 ; ¿está en el límite superior (4)? ret z ; sí - no podemos seguir hacia arriba. dec (hl) ; restar 1 a la coordenada x. ret ; Mover al jugador hacia abajo. mpd ld hl,plx ; recordar, ¡x es la coordenada vertical! ld a,(hl) ; ¿cuál es el valor actual? cp 21 ; ¿está en el límite inferior (21)? ret z ; sí - no podemos seguir hacia abajo. inc (hl) ; sumar 1 a la coordenada x. ret ; Configurar las coordenadas X e Y de la posición de la base del jugador, ; se le llama antes de la visualización y supresión de la base. basexy ld a,22 ; código para AT. rst 16 ld a,(plx) ; coordenada vertical del jugador. rst 16 ; fijar la posición vertical del jugador. ld a,(ply) ; coordenada horizontal del jugador. rst 16 ; fijar la posición horizontal del jugador. ret ; Mostrar al jugador en la posición de impresión actual. splayr ld a,69 ; tinta cían (5) en fondo negro (0), ; brillante (64). ld (23695),a ; establecer nuestros colores temporales de pantalla. ld a,144 ; código ASCII para el UDG 'A'. rst 16 ; dibujar jugador. ret wspace ld a,71 ; tinta blanca (7) en fondo negro (0), ; brillante (64). ld (23695),a ; establecer nuestros colores temporales de pantalla. ld a,32 ; carácter de ESPACIO. rst 16 ; dibujar espacio. ret ; Sencillo generador de números seudo-aleatorio. ; Seguir un puntero a través de la ROM (a partir de una semilla), ; retornando el contenido del byte en esa posición. random ld hl,(seed) ; puntero ld a,h and 31 ; mantenerlo en los primeros 8Kb de ROM. ld h,a ld a,(hl) ; Obtener el número "aleatorio" de esa ubicación. inc hl ; Incrementar el puntero. ld (seed),hl ret seed defw 0 plx defb 0 ; coordenada x del jugador. ply defb 0 ; coordenada y del jugador. ; gráficos UDG. blocks defb 16,16,56,56,124,124,254,254 ; base del jugador. defb 24,126,255,255,60,60,60,60 ; seta.
Una vez ejecutado este listado se parece más a un juego de Centipede de lo que
lo hacía antes, pero hay un problema importante. Las setas se distribuyen de
forma aleatoria alrededor de la pantalla, pero el jugador puede moverse a través
de ellas. Se requiere algún tipo de detección de colisiones para evitar que
esto ocurra, lo que se cubrirá en el siguiente capítulo.
Muchas gracias por el esfuerzo!
ResponderEliminarExcelente trabajo de traduccion!!!
Enhorabuena y seguid asi por favor!
De nada, las traducciones las hago yo solo, no es trabajo de equipo, y las reviso poco por lo que seguro son mejorables.
EliminarAun mas merito tiene si las haces solo!
ResponderEliminarEn ese caso, rectifico:
Enhorabuena, adelante y sigue asi , que estas haciendo un excelente trabajo!
Saludos!