Detecciones en SuperBASIC
Moderador: Sir Cilve Sinclair
- na_th_an
- Nonamed
- Mensajes: 1889
- Registrado: Lun May 07, 2007 10:16 am
- Ubicación: Andalucía
Re: Detecciones en SuperBASIC
¿No hay una mejor forma de temporizar para garantizar que un programa se ejecutará a la misma velocidad en todas las máquinas?
- radastan
- Phantomas
- Mensajes: 2232
- Registrado: Lun May 07, 2007 5:34 pm
- Contactar:
Re: Detecciones en SuperBASIC
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 otras páginas.... pero no son Bytemaniacos
http://www.bytemaniacos.com
Orgullo de 8 bits
_________________________________________
Hay otras páginas.... pero no son Bytemaniacos
http://www.bytemaniacos.com
Orgullo de 8 bits
_________________________________________
-
- Nonamed
- Mensajes: 1067
- Registrado: Lun May 07, 2007 10:06 pm
Re: Detecciones en SuperBASIC
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.
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
Gandulf
- badaman
- Sabreman
- Mensajes: 499
- Registrado: Mar Ene 29, 2008 10:58 am
- Contactar:
Re: Detecciones en SuperBASIC
En SuperBASIC podemos usar la función DATE, que devuelve el valor numerico de la hora. Por ejemplo:
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.
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
-
- Sabreman
- Mensajes: 396
- Registrado: Dom Feb 24, 2008 10:56 pm
Re: Detecciones en SuperBASIC
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
Código: Seleccionar todo
RES_SIZE 14*64
Otro comando de la Gold Card es por ejemplo:
Código: Seleccionar todo
SLUG 15
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
- badaman
- Sabreman
- Mensajes: 499
- Registrado: Mar Ene 29, 2008 10:58 am
- Contactar:
Re: Detecciones en SuperBASIC
Algunas curiosidades sobre el juego crash_bas.
Pego de nuevo el juego:
Empezamos:
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:
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:
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.
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:
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:
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:
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:
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:
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.
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
- radastan
- Phantomas
- Mensajes: 2232
- Registrado: Lun May 07, 2007 5:34 pm
- Contactar:
Re: Detecciones en SuperBASIC
Si señor, muy interesantes explicaciones, tomo nota (sobre todo de los canales).
Poquito a poquito vamos avanzando.
Poquito a poquito vamos avanzando.
_________________________________________
Hay otras páginas.... pero no son Bytemaniacos
http://www.bytemaniacos.com
Orgullo de 8 bits
_________________________________________
Hay otras páginas.... pero no son Bytemaniacos
http://www.bytemaniacos.com
Orgullo de 8 bits
_________________________________________
- badaman
- Sabreman
- Mensajes: 499
- Registrado: Mar Ene 29, 2008 10:58 am
- Contactar:
Re: Detecciones en SuperBASIC
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:
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:
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:
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:
Y pulsamos la tecla subir (recordemos que el bucle resta 1 a tp y a cv)
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:
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
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
- na_th_an
- Nonamed
- Mensajes: 1889
- Registrado: Lun May 07, 2007 10:16 am
- Ubicación: Andalucía
Re: Detecciones en SuperBASIC
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.
- badaman
- Sabreman
- Mensajes: 499
- Registrado: Mar Ene 29, 2008 10:58 am
- Contactar:
Re: Detecciones en SuperBASIC
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.
"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
- na_th_an
- Nonamed
- Mensajes: 1889
- Registrado: Lun May 07, 2007 10:16 am
- Ubicación: Andalucía
Re: Detecciones en SuperBASIC
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)
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)
- badaman
- Sabreman
- Mensajes: 499
- Registrado: Mar Ene 29, 2008 10:58 am
- Contactar:
Re: Detecciones en SuperBASIC
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
- na_th_an
- Nonamed
- Mensajes: 1889
- Registrado: Lun May 07, 2007 10:16 am
- Ubicación: Andalucía
Re: Detecciones en SuperBASIC
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.
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.
- badaman
- Sabreman
- Mensajes: 499
- Registrado: Mar Ene 29, 2008 10:58 am
- Contactar:
Re: Detecciones en SuperBASIC
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.
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
- na_th_an
- Nonamed
- Mensajes: 1889
- Registrado: Lun May 07, 2007 10:16 am
- Ubicación: Andalucía
Re: Detecciones en SuperBASIC
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.
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.
¿Quién está conectado?
Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 16 invitados