Detecciones en SuperBASIC

Subforo oficial del Sinclair QL: realiza aquí las consultas relativas a tu QL.

Moderador: Sir Cilve Sinclair

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Detecciones en SuperBASIC

Mensaje por na_th_an » Vie Ene 23, 2009 11:37 am

¿No hay una mejor forma de temporizar para garantizar que un programa se ejecutará a la misma velocidad en todas las máquinas? :?

Avatar de Usuario
radastan
Phantomas
Mensajes: 2232
Registrado: Lun May 07, 2007 5:34 pm
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por radastan » Vie Ene 23, 2009 12:04 pm

na_th_an escribió:¿No hay una mejor forma de temporizar para garantizar que un programa se ejecutará a la misma velocidad en todas las máquinas? :?


Simplemente quitar la goldcard... :lol:
_________________________________________
Hay otras páginas.... pero no son Bytemaniacos
http://www.bytemaniacos.com
Orgullo de 8 bits
_________________________________________

Gandulf
Nonamed
Mensajes: 1067
Registrado: Lun May 07, 2007 10:06 pm

Re: Detecciones en SuperBASIC

Mensaje por Gandulf » Vie Ene 23, 2009 12:35 pm

SIn tener ni idea de QL, en PC por ejemplo los juegos tienen que ir mas o menos o a la misma velocidad en todos los ordenadores, con las abismales diferencias que hay entre ellos. En la época de DOS, una forma fácil y rápida de sincronizar era con el sincronismo vertical (en todos los ordenadores esperar por ejemplo dos retrazos verticales tarda lo mismo). Me imagino que en el QL se puede hacer una pausa de este tipo para establecer un "tope" de velocidad, o detectar la velocidad del cacharro mediante un contador e interrupciones. El problema me imagino que es trabajar en Basic puro; si se hiciera una rutina en cm seguro que se podría solucionar esto.

Pero bueno, creo que como dice Radastan, para un programilla así en Basic y en los tiempos actuales, con avisar del tema de la GoldCard listo.
Un saludo,

Gandulf

Avatar de Usuario
badaman
Sabreman
Mensajes: 499
Registrado: Mar Ene 29, 2008 10:58 am
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por badaman » Vie Ene 23, 2009 2:47 pm

En SuperBASIC podemos usar la función DATE, que devuelve el valor numerico de la hora. Por ejemplo:

Código: Seleccionar todo

REPeat bucle
a=DATE
..
REMark líneas de relleno o del juego
..
b=DATE
IF b>a THEN PRINT "ha pasado un segundo o más": EXIT bucle
END REPeat bucle


Con una precisión al segundo no es que podamos hacer mucho, pero podemos crear un pequeño test de velocidad al inicio del juego o programa (por ejemplo, ver cuantoas sumas pueden hacerse en un segundo...) para intentar afinar lo más posible los bucles de retardo dentro del juego.
Última edición por badaman el Lun Ene 26, 2009 4:32 pm, editado 1 vez en total.
Sinclair QL, la respuesta profesional de los 80

afx
Sabreman
Mensajes: 396
Registrado: Dom Feb 24, 2008 10:56 pm

Re: Detecciones en SuperBASIC

Mensaje por afx » Vie Ene 23, 2009 7:12 pm

radastan escribió:na_th_an escribió:
¿No hay una mejor forma de temporizar para garantizar que un programa se ejecutará a la misma velocidad en todas las máquinas?

Simplemente quitar la goldcard...


Hay algunos comandos de la Gold Card (y Super Gold Card) que hacer un "degrader" de la máquina a un QL pelao, o con menos memoria.

Por ejemplo:

Código: Seleccionar todo

RES_128
Simula un QL de paquete (en cuanto a memoria)

Código: Seleccionar todo

RES_SIZE 14*64
Este por ejemplo simula un QL con TrumpCard con 768K.

Otro comando de la Gold Card es por ejemplo:

Código: Seleccionar todo

SLUG 15
SLUG n provoca un retardo de n milisegundos en la lectura del teclado.

Otras utilidades interesantes es saber sobre en qué hardware se está ejecutando nuestro código. Aquí pongo código encontrado en algún artículo parar averigura el hardware, con ello podríamos programa una serie de retardos (¿no valdrían simplemente bucles for ... end for ?) diferentes en función del tipo de máquinas. (El autor de este código: J.D.Mitchell, he puesto una referencia a él en el hilo Procedimientos y Funciones).

Código: Seleccionar todo

10000 REMark *****************************
10010 REMark Version: V1.0
10020 REMark Date: 20/Sep/1997
10030 REMark Author: J.D.Mitchell
10040 REMark EMAIL: Jack@home9999.demon.co.uk
10050 REMark Change: 1) Default system vars base is at 160K not 128K
10060 REMark 2) Add change control header
10070 REMark *****************************
10080 REMark Version: 1.1
10090 REMark Date: 20/Sep/1997
10100 REMark Author: J.D.Mitchell
10110 REMark EMAIL: Jack@home9999.demon.co.uk
10120 REMark Change: 1) Use peek(!!addr) etc. when possible
10130 REMark *****************************
10140 REMark Version: 1.2
10150 REMark Date: 28/Nov/1997
10160 REMark Author: J.D.Mitchell
10170 REMark EMAIL: Jack@home9999.demon.co.uk
10180 REMark Change: 1) Corect error in change history
10190 REMark Change: 2) Report QDOS versions as ROM names not versions
10200 REMark *****************************
10210 DEFine FuNction DISPLAY_WIDTH
10220   IF os$='SMSQE' THEN RETurn SCR_XLIM
10230   RETurn scr__lim%('scr_','x256a0x0')&&-2
10240 END DEFine
10245 :
10250 DEFine FuNction display_height
10260   IF os$='SMSQE' THEN RETurn SCR_YLIM
10270   RETurn scr__lim%('scr_512x','a0x0')
10280 END DEFine
10285 :
10290 DEFine FuNction scr__lim%(prefix$,sufix$)
10300   LOCal h_max%,h_min%,h%,loop
10310   h_max%=1280
10320   h_min%=256
10330   REPeat loop
10340     h%=(h_max%+h_min%+1)DIV 2
10350     IF h%>h_max% THEN h%=h_max%
10360     IF FTEST(prefix$&h%&sufix$)=0 THEN
10370       h_min%=h%
10380     ELSE
10390       h_max%=h%-1
10400     END IF
10410     IF h_min%=h_max% THEN RETurn h_max%
10420   END REPeat loop
10430 END DEFine
10435 :
10440 REMark mimics peek_w(!!addr)
10450 DEFine FuNction peek_w_sys(addr)
10460   IF os$='QDOS' THEN
10470     RETurn PEEK_W(addr+sys_vars_base)
10480   END IF
10490   RETurn PEEK_W(!!addr)
10500 END DEFine
10505 :
10510 REMark mimics peek(!!addr)
10520 DEFine FuNction peek_sys(addr)
10530   IF os$='QDOS' THEN
10540     RETurn PEEK(addr+sys_vars_base)
10550   END IF
10560   RETurn PEEK(!!addr)
10570 END DEFine
10575 :
10580 REMark mimics peek_l(!!addr)
10590 DEFine FuNction peek_l_sys(addr)
10600   IF os$='QDOS' THEN
10610     RETurn PEEK_L(addr+sys_vars_base)
10620   END IF
10630   RETurn PEEK_L(!!addr)
10640 END DEFine
10645 :
10650 DEFine PROCedure setup_read
10660   LOCal hardware_code,cpu_code,display_code,sys_vars_base,monitor_code,display_register
10670   IF VER$<>'HBA' THEN
10680     IF VER$='JSL1' THEN
10690       os$='Minerva'
10700       version$=VER$(1)
10710       sys_vars_base=VER$(-2)
10720       lang$='GB'
10730     ELSE
10740       os$='QDOS'
10750       version$=VER$
10760       sys_vars_base=(128+32)*1024
10770       IF LEN(version$)<=2 THEN
10780         lang$='GB'
10790       ELSE
10800         lang$=version$(3 TO)
10810       END IF
10820     END IF
10830   ELSE
10840     IF FTEST('history_1024')<>0 THEN
10850       os$='SMSQ'
10860     ELSE
10870       os$='SMSQE'
10880     END IF
10890     sys_vars_base=VER$(-2)
10900     version$=VER$(1)
10910     lang$=LANGUAGE$
10920    END IF
10930    REMark mimics  PROCESSOR   provided by SMSQE
10940    cpu_code=(peek_sys(161) DIV 16)*10
10950    REMark mimics  MACHINE     provided by SMSQE
10960    hardware_code=peek_sys(167)&&31
10970    REMark mimics  DISP_TYPE   provided by SMSQE but gives 6 for VGA on a QXL
10980    display_code=peek_sys(167) DIV 32
10990    display_register=peek_sys(52)
11000    freq=peek_w_sys(168)
11010    SELect freq
11020      =50,60
11030      =REMAINDER :freq=50
11040    END SELect
11050    ram_top=peek_l_sys(32)
11060    monitor_code=peek_sys(50)
11070    REMark Convert to text
11080    SELect ON hardware_code
11090      =0:hardware$='Standard QL'
11100      =1:hardware$='Atari'
11110      =2,3:hardware$='Mega/RTC ST'
11120      =4,5:hardware$='Stacy'
11130      =6,7:hardware$='STE'
11140      =8,9:hardware$='Mega STE'
11150      =10,11:hardware$='GOLD card'
11160      =12,13:hardware$='Super Gold card'
11170      =16:hardware$='Falcon'
11180      =24:hardware$='TT 030'
11190      =28:hardware$='QXL'
11200      =30:hardware$='QPC'
11210      =31:hardware$='QLAY'
11220      =REMAINDER :hardware$='Unknown HW('&hardware_code&')'
11230    END SELect
11240    SELect hardware_code
11250      =1,3,5,7,9:add_on$='Blitter'
11260      =11,13:add_on$='Hermes'
11270      =REMAINDER :add_on$=''
11280    END SELect
11290    SELect ON monitor_code
11300      =0:monitor$='Monitor'
11310      =1:monitor$='625 line TV'
11320      =2:monitor$='525 line TV'
11330      =REMAINDER :monitor$='Unknown Monitor('&monitor_code&')'
11340    END SELect
11350    display_mode=4+(display_register&&8)DIV 2
11360    display_page=display_register DIV 128
11370    SELect display_code
11380      =0:display$='Standard'
11390      =1:display$='Monochrome'
11400      =2:display$='Extended 4 emulator'
11410      =4:display$='QMVE'
11420      =5:display$='Aurora'
11430      =6:display$='VGA'
11440      =REMAINDER :display$='Unknown display('&display_code&')'
11450    END SELect
11460    SELect cpu_code
11470      =0:cpu$='68000/68008'
11480      =10:cpu$='68010'
11490      =20:cpu$='68020'
11500      =30:cpu$='68030'
11510      =40:cpu$='68040'
11520      =REMAINDER :cpu$='Unknown CPU('&cpu_code&')'
11530    END SELect
11540 END DEFine
11545 :
11550 DEFine PROCedure setup_show(chan%)
11560   PRINT#chan%,'Running ';os$;
11570   IF os$=='QDOS' THEN
11580     PRINT#chan%,' ';version$;' ROM'
11590   ELSE
11600     PRINT#chan%,' V';version$
11610   END IF
11620   PRINT#chan%,'On a ';cpu$;' powered ';hardware$
11630   PRINT#chan%,'With ';INT(ram_top/1024)-128;'KByte RAM';
11640   IF add_on$<>'' THEN PRINT#chan%,' and ';add_on$
11650   PRINT#chan%,\'Using ';display$;' ';DISPLAY_WIDTH;'x';display_height;' on a ';monitor$
11660   PRINT#chan%,'Displaying ';position_name$(display_page+1);' page in mode ';display_mode
11670   PRINT#chan%,'Country ';lang$;' @';freq;'Hz'
11680 END DEFine
11685 :
11690 DEFine FuNction position_name$(n)
11700   SELect n
11710     =1:RETurn '1st'
11720     =2:RETurn '2nd'
11730     =3:RETurn '3rd'
11740     =REMAINDER :RETurn n&'th'
11750   END SELect
11760 END DEFine
11765 :
11770 DEFine PROCedure setup_test
11780   TK2_EXT
11790   setup_read
11800   CLS
11810   setup_show #1
11820 END DEFine
11825 :
11830 setup_test

Avatar de Usuario
badaman
Sabreman
Mensajes: 499
Registrado: Mar Ene 29, 2008 10:58 am
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por badaman » Sab Ene 24, 2009 1:07 pm

Algunas curiosidades sobre el juego crash_bas.

Pego de nuevo el juego:

Código: Seleccionar todo

100 REMark crash_bas - 2009 - badaman
110 MODE 8: CLS: CLS #0
120 REMark cambia "an" = ancho pista
130 al=9: an=11: REMark vals. 2 a 28
140 REMark cambia "nv" = dificultad
150 nv=3: REMark 1 dific. a 5 facil
160 h=INT(an/2): ch=h+1: v=al: cv=v
170 coche$=CHR$(174): otro$=CHR$(183)
180 lin$=FILL$(" ",an): tp=0: sw=0
190 DIM camino$(al,an): ca=5
200 FOR i=0 TO al: camino$(i)=lin$
210 OPEN #ca,scr_448x200a32x16
220 PAPER #ca,4: CLS#ca: INK#ca,1
230 WINDOW #ca,an*16,(al+1)*20,32+(448-(an*16))/2,16+(200-((al+1)*20))/2
240 PAPER #ca,6: CLS#ca: CSIZE#ca,3,1
250 REPeat carrera
260   ov=v:oh=h
270   IF KEYROW(1)=4 AND v>1 AND cv>1
280     IF camino$(cv-1,ch)<>" " THEN sw=1: ELSE cv=cv-1: v=v-1
290   END IF
300   IF KEYROW(1)=128 AND v<al THEN cv=cv+1: v=v+1
310   IF KEYROW(1)=2  AND ch>1  THEN ch=ch-1: h=h-1
320   IF KEYROW(1)=16 AND ch<an THEN ch=ch+1: h=h+1
330   cv=cv-1: IF cv<0 THEN cv=al
340   AT #ca,ov,oh: PRINT #ca," "
350   SCROLL #ca,20
360   AT #ca,v,h: PRINT #ca,coche$
370   IF camino$(cv,ch)<>" " OR sw THEN EXIT carrera
380   REMark PAUSE 5: REMark quita REM para GoldCar
390   tp=tp-1: IF tp<0 THEN tp=al
400   camino$(tp)=lin$
410   n=RND(0 TO nv)
420   IF NOT n
430     n=RND(1 TO an)
440     AT #ca,0,n-1: PRINT #ca,otro$
450     camino$(tp,n)=otro$
460   END IF
470 END REPeat carrera
480 AT #ca,v,h: PRINT #ca,"*";
490 AT #ca,0,0: PRINT #ca,"Crash!"
500 CSIZE #ca,0,0: CLOSE #ca


Empezamos:

Código: Seleccionar todo

180 lin$=FILL$(" ",an): tp=0: sw=0
190 DIM camino$(al,an): ca=5
200 FOR i=0 TO al: camino$(i)=lin$


En la línea 180 llenamos de espacios la variable lin$, y en la 190 definimos la matriz camino$.

Los parámetros de camino$ son alto y ancho. aunque en realidad los valores al y an corresponden a alto y ancho +1.

Cuando definimos esta matriz lo que estamos diciendo en SuperBASIC es que tenemos una lista 'al' de cadenas de 'an' caracteres de ancho. Dado que una cadena de cualquier longitud numera sus caracteres del 1 a n, siendo n la longitud total de la cadena, no podemos usar el valor 0 de 'an'.

En la línea 200 lo que hacemos es pues asignar a cada cadena de la lista camino$(0), camino$(1)... la cadena de caracteres lin$ para limpiar toda la matriz con espacios.

En la línea:

Código: Seleccionar todo

400   camino$(tp)=lin$


lo hacemos de nuevo.

En otros BASICs tendríamos que hacer dos bucles anidados, uno para poner el valor 'al' y otro para poner el valor 'an'.

En estas líneas vemos como el valor de pantalla y el valor de la matriz varían en 1:

Código: Seleccionar todo

430     n=RND(1 TO an)
440     AT #ca,0,n-1: PRINT #ca,otro$
450     camino$(tp,n)=otro$


Ya que si pintamos caracteres en la pantalla, estos pueden pintarse en las posiciones n,0, no así en la matriz camino$(n,0) como hemos visto.

Vamos con más cosas.

Código: Seleccionar todo

210 OPEN #ca,scr_448x200a32x16
220 PAPER #ca,4: CLS#ca: INK#ca,1
230 WINDOW #ca,an*16,(al+1)*20,32+(448-(an*16))/2,16+(200-((al+1)*20))/2
240 PAPER #ca,6: CLS#ca: CSIZE#ca,3,1


en la línea 210 abrimos un nuevo canal.

Por cierto, hemos usado una variable para el canal para que, en cualquier momento podamos cambiar el número de canal fácilmente por si ya existiese ese canal abierto por otro programa en ejecución. Es una buena costumbre hacer siempre esto, de igual forma que es conveniente siempre definir una variable de tipo cadena para guardar la información relativa al dispositivo de almacenamiento que queremos usar, por ejemplo 'mdv1_', 'flp1_', 'ram1_', 'win1_'... Luego podemos usar este dato dentro del programa. Por ejemplo:

Código: Seleccionar todo

100 disp$="flp1_"
110 DIR disp$


Volviendo a lo que estábamos, hay que saber que cuando abrimos un canal de tipo 'scr_' (pantalla), o 'con_' (consola) no podemos usar variables para definir sus parámetros. Así pues, si queremos abrir un canal en pantalla con valores que estén almacenados en variables, debemos primero abrir el canal con unos parámetros fijos, y luego cambiar los valores con el comando WINDOW, como hago en la línea 230.

Podemos abrir el canal sin pasar parámetros:

Código: Seleccionar todo

OPEN #ca,scr_


En este caso, el sistema toma los parámetros por defecto: 448x180a32x16

O bien pasarle los valores de el ancho y alto de la pantalla completa en pixels y luego usar CLS para borrar toda la pantalla:

Código: Seleccionar todo

OPEN #ca,scr_512x256a0x0: CLS #ca


De cualquier forma, luego deberemos usar WINDOW.

El valor que uso por defecto es el del canal 1 y canal 2 cuando arrancamos el ordenador en el modo 8 (modo 256, modo TV).

CSIZE es un comando que nos permite usar un tamaño de letra mayor en pantalla. el valor 3,1 indica un carácter el doble de alto y de ancho que uno normal.

En la línea:

Código: Seleccionar todo

500 CSIZE #ca,0,0: CLOSE #ca


Devolvemos el tamaño de caracteres a su valor original (no es necesario en el juego, ya que a continuación...) y cerramos el canal definitivamente.

La línea:

Código: Seleccionar todo

350   SCROLL #ca,20


Es la que más 'juego' nos dá, pues nos permite mover el contenido de la ventana o canal #ca hacia abajo. En otros BASICs tendríamos que mover una por una las posiciones de los coches contrarios o crear una rutina de scroll en C/M.

A partir de aquí, si queréis, podemos hablar de como funciona la detección. :)
Última edición por badaman el Dom Ene 25, 2009 7:59 am, editado 1 vez en total.
Sinclair QL, la respuesta profesional de los 80

Avatar de Usuario
radastan
Phantomas
Mensajes: 2232
Registrado: Lun May 07, 2007 5:34 pm
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por radastan » Sab Ene 24, 2009 6:48 pm

Si señor, muy interesantes explicaciones, tomo nota (sobre todo de los canales).

Poquito a poquito vamos avanzando.
_________________________________________
Hay otras páginas.... pero no son Bytemaniacos
http://www.bytemaniacos.com
Orgullo de 8 bits
_________________________________________

Avatar de Usuario
badaman
Sabreman
Mensajes: 499
Registrado: Mar Ene 29, 2008 10:58 am
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por badaman » Dom Ene 25, 2009 9:01 am

Pues ya que estamos, explico como funciona la detección de colisiones en este juego pues, aunque no tiene ninguna característica específica relacionada con el QL, siempre puede resultar útil para alguien que no ha tocado el mundillo de los juegos.

Partimos de la definición de matriz camino$(al,an) y los datos de partida relacionados.

Pongamos que al=6 (0 a 5) y an=7. Al iniciar el juego, los valores de las variables serán los siguientes:

Código: Seleccionar todo

  1234567
0 ...E... <- tp
1 .......
2 .......
3 .......
4 .......
5 ...C... <- cv
     ^
    ch


Recordemos que tp indica la posición mas alta de la carretera, y es la línea donde aparecen nuevos coches en la carretera. por su parte, cv indica la posición vertical de nuestro coche en relación con la matrix (no con la pantalla). La variable ch nos indicaría la posición de nuestro coche horizontalmente.

Pintamos de espacios en blanco (línea 400) y en la posición (0,4) pintamos un coche enemigo (E).

Si no movemos las flechas del cursor, a cada ciclo restamos 1 a tp y a cv (líneas 330 y 390) y comprobamos que los valores sean siempre mayores o iguales a 0. Si llegamos a 0 en cualquiera de los dos punteros lo que hacemos es asignar al puntero el valor 'al'.

Restando 1 a ambos punteros lo que hacemos es el efecto de recorrer hacia arriba la matriz como si fuese una cinta continua en vez de mover los mismos valores de la matriz hacia abajo.

Veamos lo que pasa a la siguiente vuelta:

Código: Seleccionar todo

  1234567
0 ...E...
1 .......
2 .......
3 .......
4 ...C... <- cv
5 .E..... <- tp


Vemos que el coche enemigo no se ha movido, pero ahora el puntero que indica donde está nuestro coche ha subido una posición acercándose a la línea del coche enemigo.

Por su parte, el puntero tp, al tener un valor menor que 0, ha pasado a apuntar a la posición 5 de la matriz. Y en esa línea ha pintado tambien un coche enemigo.

Si repetimos el proceso varias veces, veremos que tp siempre estará, como mínimo, una fila por detrás de cv, aun cuando movamos nuestro coche hacia abajo.

Veamos que pasa tras 3 vueltas más:

Código: Seleccionar todo

  1234567
0 ...E...
1 ...C... <- cv
2 .....E. <- tp
3 .......
4 ......E
5 .E.....


Los punteros han ido subiendo por la matriz, y en las líneas apuntadas por tp se han puesto coches enemigos al azar.

Podemos intuir que pasará en la siguiente vuelta, cuando cv=0. Nos encontramos entonces con que en la posición ch hay un coche enemigo. En ese momento hemos chocado (línea 370).

De no haber habido ahí un coche, seguiríamos adelante volviendo a la primera posición dibujada, donde tp=0 y cv=5.

Como hemos ido borrando las líneas donde apunta tp, el circuito se va renovando a cada vuelta.

En todos es tos casos, en la pantalla han pasado solo tres cosas: hemos borrado nuestro coche, hemos hecho scroll, y hemos pintado de nuevo nuestro coche en la misma posición.

La cosa no es más complicada si añadimos movimiento al coche.

Si desplazamos el coche a izquierda o derecha, la cosa no se ve muy afectada. lo único que cambia es el valor de ch. pero si movemos el coche arriba o abajo la cosa es distinta.

Si movemos el coche hacia abajo comprobaremos nos ponemos como tope el final de la carretera, lo que en la matriz va a coincidir con la posición tp-1 siempre que tp>0. Vamos, que se cumple eso de que tp siempre estará por debajo de nuestro coche.

Si movemos el coche hacia arriba nos separamos de tp, pero no lo superaremos por arriba.

Veamos mejor un ejemplo. si usamos la tecla de subir para mover el coche 1 posición hacia arriba.

Partimos de la siguiente posición:

Código: Seleccionar todo

  1234567
0 ...E...
1 .......
2 .......
3 .......
4 ...C... <- cv
5 .E..... <- tp


Y pulsamos la tecla subir (recordemos que el bucle resta 1 a tp y a cv)

Código: Seleccionar todo

  1234567
0 ...E...
1 .......
2 ...C... <- cv
3 .......
4 ....... <- tp
5 .E.....


la linea apuntada por cv esta a 2 íneas de la apuntada por tp.

cv podra seguir separandose de tp cada vez que pulsemos la tecla arriba, pero nunca superará a tp. Y no es que tp esté entonces por encima de cv, es que cv le lleva una vuelta de ventaja.

Si usamos la tecla abajo despues del ejemplo anterior, volveremos a acortar la distancia entre cv y tp:

Código: Seleccionar todo

  1234567
0 ...E...
1 .......
2 ...C... <- cv
3 ....... <- tp
4 .......
5 .E.....


Parece que cv no se ha movido, pero en realidad cv debería estar en la posición 1 debido a que a cada ciclo, como hemos dicho, restamos 1 a cv y a tp.

En los dos útimos ejemplos no han aparecido nuevos coches enemigos. Es cosa del azar.

Y como se verá todo esto en la pantalla pues solo haremos esto a cada vuelta: borrar nuestro cohe, hacer scroll y pintar de nuevo el coche en la posición v,h.

Sin el scroll, como decía en otro post más arriba, tendríamos que repintar también cada uno de los coches enemigos o hacernos una rutina de scroll en C/M. Así es más sencillo (gráficamente hablando claro).

Y ahora que veo todo lo que he escrito, me da que aquí tienes material para un artículo en bytemaniacos, Radas. XD
Sinclair QL, la respuesta profesional de los 80

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Detecciones en SuperBASIC

Mensaje por na_th_an » Lun Ene 26, 2009 11:18 am

Hmmm - sigo empeñado, debe haber algo. El Speccy genera una interrupción en cada refresco, ¿seguro que no habrá nada parecido? Voy a leerme el manual técnico a ver qué saco en claro.

Avatar de Usuario
badaman
Sabreman
Mensajes: 499
Registrado: Mar Ene 29, 2008 10:58 am
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por badaman » Lun Ene 26, 2009 12:26 pm

Si que lo hay, puedes usar el servicio de interrupciones. Te pego algo de info:

"Las interrupciones son generadas por dispositivos externos de 'hardware'. El circuito de vídeo del QL, genera interrupciones 50 veces por segundo. La llegada de la señal al 68008 hace que sucedan varias cosas. Se suspende la operación que se está ejecutando en ese momento (asumiendo que la prioridad de la interrupción sea lo suficientemente alta), y el 68008 salta a ejecutar la rutina de servicio de interrupciones. Antes de entrar en esta rutina, debe salvar el contenido de todos los registros, realizar las funciones necesarias para dar servicio a la interrupción, restaurar los registros y devolver el control. El efecto aparente de la interrupción es que se han realizado algunas funciones, pero sin afectar seriamente a la operación que estaba ejecutando el programa, solamente retrasándola unos pocos microsegundos. Las interrupciones se usan generalmente para dar servicio a dispositivos que requieren una atención inmediata. Si no son atendidos inmediatamente, se pueden perder algunos datos (ej. la cinta del microdrive puede pasar de largo los datos esperados). "

"Al programa se le asigna una parte de tiempo del procesador, pero el BASIC permanece operacional. Esto es debido a una de las principales características del QDOS - el hecho de soportar multitarea. Esencialmente, es una rutina dentro del sistema operativo, llamada planificador. Se invoca normalmente 50 veces cada segundo por medio de interrupciones. Cuando toma control, mira todos los jobs que hay en la máquina y decide cual de ellos debe ejecutarse (de acuerdo con la prioridad). El Job seleccionado se ejecutará durante el siguiente cincuentavo de segundo."

Como vas a tratar con dispositivos, te recomiendo que mires el cap. 9 del libro "QL Programación Avanzada" al que pertenecen estos extractos, y que gracias a nuerstros colaboradores, lo tienes disponible en HTML en nuestra web:

http://www.speccy.org/sinclairql/manual ... /index.htm

Ya ves que la cosa está muy madura en el QL.

Cuéntanos cómo usar esto para controlar la velocidad del juego, porque yo no tengo mucha idea de eso.
Sinclair QL, la respuesta profesional de los 80

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Detecciones en SuperBASIC

Mensaje por na_th_an » Lun Ene 26, 2009 1:57 pm

Genial :)

La forma más sencilla de controlar la velocidad de un juego es tener una señal periódica que podamos usar para medir el tiempo. Por lo general, los métodos basados en esperar al retrazo vertical, funcionan de la siguiente forma: En el bucle del juego tú haces todo lo que tienes que hacer, actualizas los bichos, lees el input del jugador, ejecutas la lógica, etcétera. Al final del bucle, lo que se hace es esperar al retrazo (que sabemos que ocurre cada 20ms) y cuando ocurra, dibujamos la pantalla. Con esto conseguimos dos cosas:

1.- Que la imagen no tiemble porque la actualización nos caiga durante el barrido.
2.- Que el juego vaya a la misma velocidad en todos los equipos.

Un ejemplo: imaginate que tienes un ordenador que funciona exactamente el doble de rápido que otro. Por lo tanto, si en el lento una iteración del bucle de juego tarda, digamos, 16ms, en el rápido esta iteración tardará 8ms. Si no hacemos nada, el juego irá el doble de rápido en el ordenador rápido. Si esperamos a que ocurra el retrazo vertical al final del bucle del juego, estaremos forzando en ambas máquinas que cada iteración dure 20ms, por muy rápidas que sean estas, con lo que conseguiremos que el juego vaya igual de rápido sin tener que preocuparnos de la velocidad de las máquinas que lo ejecutan.

Esto sólo tiene sentido, por supuesto, si una iteración del bucle del juego dura menos que el tiempo entre retrazos.

El tema es que para usar esto en condiciones habría que "desactivar" las tareas del S.O. que hay de fondo, que no son necesarias mientras se está jugando, como se suele hacer en todos los micros (por ejemplo, en Spectrum por lo general se desactiva todo el S.O. cuando se ejecuta un juego)

Avatar de Usuario
badaman
Sabreman
Mensajes: 499
Registrado: Mar Ene 29, 2008 10:58 am
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por badaman » Lun Ene 26, 2009 3:13 pm

na_th_an escribió:El tema es que para usar esto en condiciones habría que "desactivar" las tareas del S.O. que hay de fondo, que no son necesarias mientras se está jugando, como se suele hacer en todos los micros (por ejemplo, en Spectrum por lo general se desactiva todo el S.O. cuando se ejecuta un juego)


El uso de interrupciones lo veo bien para el primer punto que indicas, el de sincronizarnos con el pintado de la pantalla, por ejemplo cuando usamos sprites, pero parece que para medir la velocidad del juego deja de tener sentido cuando pensamos en la multitarea.

Por lo que veo, lo que necesitas entonces es una señal de reloj periódica para ir sincronizando (a cada ciclo) el retardo del juego, porque desconectar el sistema para algo así no me parece la mejor forma de afrontar el problema. Supongo que en el Spectrum y en MS-DOS, siendo como son sistemas mono-tarea, esto no será muy importante, pero en un QL, como en un Amiga o en cualquier ordenador de hoy, una tarea en segundo plano va a restar tiempo de proceso al juego, y hay que contar con ello.

Lo que si puedes hacer es generar una interrupción con una prioridad alta cada vez que tengas que hacer algo urgente en el juego. Esto no inhabilita el S.O. pero da prioridad a tu juego sobre las demás tareas.

Pensando en SuperBASIC, lo que proponía es lo que veo más apropiado. Es decir realizar un test al inicio para averiguar cual es el retardo medio a aplicar en cada ciclo del juego y esperar que durante el desarrollo del juego el tiempo de ejecución permanezca constante.

El programa ft_bas que acompaña al emulador QLay nos puede dar una idea de como hacer algo así. El programa se utiliza para saber si nuestro emulador está corriendo a una velocidad mayor o menor que un QL normal. Para ello nos devuelve el valor que debemos cambiar en el parámetro 'f' del emulador. Lo pego aquí:

Código: Seleccionar todo

100 CLS
110 d=60
120 PRINT 'Wait ';d;' seconds for -f test'
130 t=DATE
140 PAUSE d*50
150 e=DATE-t
160 PRINT 'Delay should be ';d;' seconds'
170 PRINT 'Actual delay is ';e;' seconds'
180 IF e-d>1:PRINT 'Divide -f by ';e/d
190 IF d-e>1:PRINT 'Multiply -f with ';d/e
200 IF ABS(d-e)<2:PRINT 'Current value of -f is about right'


NOTA: PAUSE admite valores medidos en 1/50 de segundo. Así pues PAUSE d*50, siendo d=60 (60*50) es 1 minuto de pausa.

Este otro programa llamado qsbb_bas, que también acompaña a QLay, se realizan 3 test de velocidad del QL:

Código: Seleccionar todo

100 REMark QLAY SuperBasic Benchmark
110 CLOSE#1
120 OPEN#1,con_256x202a256x0
130 INK#1,7:PAPER#1,2:BORDER#1,1,7,0
140 MODE 4
150 PRINT#2,\"   QLAY SuperBasic Benchmark "
160 PRINT#2,\"   3 tests, 20 seconds each"
170 PRINT#2,\"   Please wait a minute ..."\\
180 FOR i=0 TO 20:PRINT " "
190 :
200 t=DATE
210 p=0
220 REPeat l1
230 FOR i=1 TO 20
240  PRINT p;" ";
250  p=p+1
260 NEXT i
270 IF DATE-t>20:EXIT l1
280 END REPeat l1
290 PRINT#2,\" Printing         ";p
300 :
310 t=DATE
320 p=0
330 REPeat l2
340 FOR i=1 TO 20
350  a=SIN(1):b=LN(4):c=EXP(10)
360  p=p+1
370 NEXT i
380 IF DATE-t>20: EXIT l2
390 END REPeat l2
400 PRINT#2,\" Functions        ";p
410 :
420 t=DATE
430 p=0
440 REPeat l3
450 FOR i=1 TO 20
460  a$="abcdefghijklmnopqrstuvwxyz"
470  b$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
480  c$=FILL$(a$&b$,i)
490  p=p+1
500 NEXT i
510 IF DATE-t>20:EXIT l3
520 END REPeat l3
530 PRINT#2,\" Strings          ";p
Sinclair QL, la respuesta profesional de los 80

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Detecciones en SuperBASIC

Mensaje por na_th_an » Lun Ene 26, 2009 4:35 pm

Pero es que sigo sin entender, volviendo a una vieja discusión, para qué queréis multitarea y procesos en segundo plano mientras se ejecuta un juego :) Lo suyo es desactivarlos, tener toda la máquina para tí, y poder aprovechar al 100% la potencia que tiene.

Es que siempre pienso con mi mentalidad de desarrollador de juegos... Fijáos en la XBox original, que era un Celeron a 733Mhz con 64 Mb de RAM y rendía muchísimo más que un PC-Windows con las mismas características... ¿Por qué? Porque su S.O. era una especie de Windows 2000 monoproceso.

Avatar de Usuario
badaman
Sabreman
Mensajes: 499
Registrado: Mar Ene 29, 2008 10:58 am
Contactar:

Re: Detecciones en SuperBASIC

Mensaje por badaman » Lun Ene 26, 2009 4:47 pm

Entiendo que para que un juego rinda más, cuantos menos procesos en segundo plano mejor, pero es que hablamos de ordenadores personales, no de consolas, por eso tenemos que jugar con lo que hay. Tu mismo ejemplo X-box vs. PC da fe de ello.

Sea como fuere, apagar el S.O. es como matar moscas a cañonazos cuando tenemos otras formas de hacer las cosas a la hora de afinar la velocidad de ejecución, que es optimizando la programación y utilizando precisamente los recursos del S.O. QDOS.

Recuerda que al final, lo que verdaderamente será determinante para obtener una diferencia notoria de velocidad va a ser tener un procesador más potente, como ha demostrado la historia con la escalada de procesadores Intel desde aquellas CPUs de los 80 hasta lo que tenemos hoy. Vamos, que aplicando la lógica, haremos juegos a la medida de la máquina hasta que tengamos máquinas a la medida de los juegos.
Sinclair QL, la respuesta profesional de los 80

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Detecciones en SuperBASIC

Mensaje por na_th_an » Lun Ene 26, 2009 6:17 pm

Respondeme, sencillamente, ¿para qué quieres multitarea mientras juegas? Es que lo veo desperdiciar un montón de recursos en algo que no estás usando. Cuando estás trabajando, pues perfecto. Puedes tener varios programas en ejecución lo cual facilita el trabajo. Pero jugando...

Estamos hablando de hacer un juego. No creo que sea matar moscas a cañonazos, es aprovechar el hardware. Imaginate que en la época del MSDOS la gente hubiera usado la BIOS de MSDOS para acceder a la VGA en vez de cargarse MSDOS y tocarla directamente... Los juegos hubieran sido mucho peores.

Yo hablo de "optimizar la programación", claro, y además disponer de toda la máquina para mí. Es que me parece bastante curioso que, pudiendo tener juegos de una calidad bestial porque la máquina es MUY potente, parece que os contentáis con tener juegos que parecen sacados del típico libro de listados multi-sistema.

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 16 invitados