===SPRGES - Parte Basic === SprGes es un grupo de programas que tenía por objeto acabar con el límite de memoria que Qbasic imponía a las matrices de gráficos. A través de un programa residente en memoria (TSR) vinculado a un controlador de interrupción se reservaba memoria para gráficos de modo MCGA (320x200, 256 colores, el mejor modo gráfico para juegos usando gráficos VGA estándar). El programa estaba creado en una mezcla de [[csembler_y_programas_relacionados|CSEMBL] (para la parte del TSR) y basic (para el juego en cuestión). Una versión compilada (funciona solo en sistemas anteriores a XP, que soporten archivos .COM, y podría ser peligroso ejecutarla en Windows) puede descargarse de [[http://jgmoyay.apagada.com]]. Antes de ejecutar estos programas es necesario haber cargado SPRGES16.COM o SPRGES2.COM * Juego16.BAS: un prototipo de juego. DECLARE SUB LUCHA (X%, Y%) DECLARE SUB Centrar (Lin%, MSG$) DECLARE FUNCTION ValorM% (X%, Y%) DECLARE SUB SPRITEPSET2 (N%) DECLARE SUB CARGASPRITES () DECLARE SUB PonerM (X%, Y%, Objeto%) DECLARE SUB MostrarP (X%, Y%) DECLARE FUNCTION VALORMAPA% (X%, Y%) DEFINT A-Z PRINT "JUEGOMAP." PRINT "Ejemplo de juego, creado con MAPAGES2, que utiliza SPRGEST." SLEEP 5: I$ = INKEY$: I$ = "" CLS DIM SHARED NULL AS STRING * 1: NULL = CHR$(0) 'Este programa utiliza SPRGEST para poner gr ficos en pantalla. 'Lo que sigue son matrices est ticas '$STATIC DIM SHARED RUTINAMAQUINA%(1 TO 16), MAQDESP%, MAQSEG% 'Inicializar la rutina secundaria de c¢digo m quina. MAQDESP% = VARPTR(RUTINAMAQUINA%(1)) MAQSEG% = VARSEG(RUTINAMAQUINA%(1)) DEF SEG = MAQSEG% RESTORE RutiMaqData FOR F = 0 TO 15 READ DATO$ POKE MAQDESP% + F, VAL("&h" + LTRIM$(DATO$)) NEXT DEF SEG DIM SHARED MAPADESP%, MAPASEG% 'Tomar ubicaci¢n de INT 60h DEF SEG = 0 I60 = 4 * &H60 des = PEEK(I60) + 256 * PEEK(I60 + 1) MAPASEG% = PEEK(I60 + 2) + 256 * PEEK(I60 + 3) DEF SEG = MAPASEG% FOR F = 1 TO 8 IF PEEK(des + F + 1) <> ASC(MID$("SPR_GEST", F, 1)) THEN PRINT "ERROR: SPRGEST (gestor de sprites y memoria) no cargado." SYSTEM END IF NEXT UBI = des + 10 MAPADESP% = PEEK(UBI) + 256 * PEEK(UBI + 1) 'No podr‚ utilizar los 256 sprites, puesto que ocupan mucho m s de '64Kb. '$STATIC DIM SHARED SPRITES%(32766), SPRDESP%, SPRSEG% 'DIM SHARED SPRIT%(FRE(1) / 2) SPRDESP% = VARPTR(SPRITES%(0)) SPRSEG% = VARSEG(SPRITES%(0)) SCREEN 13 CARGASPRITES X = 0: Y = 0 SPRACT% = 0 LSTSPRACT% = -1 Armapa$ = "JUEGO" IF Armapa$ > "" THEN IF INSTR(Armapa$, ".") = 0 THEN Armapa$ = Armapa$ + "._MA" DEF SEG = MAPASEG% BLOAD Armapa$, MAPADESP% DEF SEG END IF 'Poner el marcador de energ¡a Energia = 200 LINE (256, 0)-(319, 199), 0, BF LINE (280, 0)-(296, 200 - Energia), 7, B LINE (280, 200 - Energia)-(296, 199), 7, BF X0 = 1: Y0 = 1: ' ObjetoSPR = ValorM(X1 + X0 + 1, Y1 + Y0 + 1) DO ObjetoSPR = ValorM(X1 + X0 + 1, Y1 + Y0 + 1) SELECT CASE ObjetoSPR CASE 1 Oro = Oro + 100: ObjetoSPR = 0': PLAY "L63CDEFCDEG" 'SOUND 1000, .5: SOUND 2000, .5 FOR W = 1 TO 5: SOUND 500 * W, .1: NEXT CASE 20, 21 PLAY "L63A#C" SWAP ObjetoSPR, ObjetCogido SELECT CASE ObjetCogido CASE 20: Nobjeto$ = "Hacha" CASE 21: Nobjeto$ = "Espada" END SELECT END SELECT PonerM X1 + X0 + 1, Y1 + Y0 + 1, 50 + DIRE + ESTA LOCATE 25, 1: PRINT USING "ORO: ##### Arma:\ \ Llaves:####"; Oro; Nobjeto$; llaves; ESTA = ESTA + 1: IF ESTA > 1 THEN ESTA = 0 DO GOSUB MueveMalos IN$ = INKEY$ LOOP UNTIL IN$ > "" PonerM X1 + X0 + 1, Y1 + Y0 + 1, ObjetoSPR SELECT CASE IN$ CASE "4", NULL + "K" X0 = X0 - 1 DIRE = 2 IF X0 < 0 THEN X0 = 0: IF X1 > 0 THEN X1 = X1 - 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN X0 = X0 + 1 IF VM1 >= 30 AND VM1 <= 36 THEN X0 = X0 + 1: LUCHA X1 + X0, Y1 + Y0 + 1 CASE "8", NULL + "H" Y0 = Y0 - 1 DIRE = 4 IF Y0 < 0 THEN Y0 = 0: IF Y1 > 0 THEN Y1 = Y1 - 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN Y0 = Y0 + 1 IF VM1 >= 30 AND VM1 <= 36 THEN Y0 = Y0 + 1: LUCHA X1 + X0 + 1, Y1 + Y0 CASE "6", NULL + "M" X0 = X0 + 1 DIRE = 0 IF X0 > 7 THEN X0 = 7: IF X1 < 119 THEN X1 = X1 + 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN X0 = X0 - 1 IF VM1 >= 30 AND VM1 <= 36 THEN X0 = X0 - 1: LUCHA X1 + X0 + 2, Y1 + Y0 + 1 CASE "2", NULL + "P" Y0 = Y0 + 1 DIRE = 6 IF Y0 > 5 THEN Y0 = 5: IF Y1 < 248 THEN Y1 = Y1 + 1 END IF VM1 = ValorM(X1 + X0 + 1, Y1 + 1 + Y0) IF VM1 > 1 AND VM1 < 20 THEN Y0 = Y0 - 1 IF VM1 >= 30 AND VM1 <= 36 THEN Y0 = Y0 - 1: LUCHA X1 + X0 + 1, Y1 + Y0 + 2 CASE CHR$(27): EXIT DO END SELECT LOOP RutiMaqData: 'Rutina en c¢digo m quina DATA b8,00,00,bb,00,00,b9,00,00,ba,00,00,cd,60,cb,90 MueveMalos: ESTADO = ESTADO + 1 IF ESTADO > 20 THEN FOR F = 0 TO 8: FOR G = 0 TO 6 XF = X1 + F: YG = Y1 + G 'Espero que esto acelere el programa. VM = ValorM(XF, YG) SELECT CASE VM CASE 30, 31, 33, 34: PonerM XF, YG, VM + 1 CASE 32, 35: PonerM XF, YG, VM - 2 END SELECT NEXT: NEXT MostrarP X1, Y1 ESTADO = 0 END IF RETURN SUB CARGASPRITES Archiv$ = "Juego" Archiv$ = LTRIM$(RTRIM$(Archiv$)) PRINT "Cargando la paleta.": PRINT "Espere, por favor..." FOR F = 0 TO 7: FOR G = 0 TO 31 LINE (G * 8, 64 + F * 8)-(7 + G * 8, 73 + F * 8), F * 32 + G, BF NEXT: NEXT DIM RGB AS STRING * 3 NFILE = FREEFILE OPEN Archiv$ + "._PA" FOR BINARY AS NFILE FOR F = 0 TO 255 GET NFILE, , RGB PALETTE F, CVL(RGB + NULL) NEXT F CLOSE NFILE PRINT "Cargando los dibujos.": PRINT "Espere, por favor..." NFILE = FREEFILE OPEN Archiv$ + "._SP" FOR BINARY AS NFILE LIMITF = UBOUND(SPRITES%) 'X = 0: Y = 0 F = 0 DO UNTIL EOF(1) GET NFILE, , SPRITES%(F) 'MK$ = MKI$(SPRITES%(F)) 'SPRITES%(F) = CVI(RIGHT$(MK$, 1) + LEFT$(MK$, 1)) IF F = LIMITF THEN EXIT DO F = F + 1 LOOP CLOSE NFILE END SUB SUB Centrar (Lin, MSG$) X2 = 40 - LEN(MSG$) / 2 IF X2 = 0 THEN LOCATE Lin, 1 ELSE LOCATE Lin, X2 PRINT MSG$ END SUB SUB LUCHA (X, Y) SHARED Energia, ObjetCogido Venem = ValorM(X, Y) SELECT CASE Venem CASE 30 TO 32 'Anillo Ataque2 = 1: Efecto = 15 'Soborno = 500: ObjetDesea = 0: Enigma = -1 CASE 33 TO 35 'Devorador Ataque2 = 2: Efecto = 10 'Soborno = 500: ObjetDesea = 0: Enigma = 0 END SELECT IF Ataque2 = 0 THEN EXIT SUB SOUND 250, .4: SOUND 100, .8: SOUND 250, .4 SELECT CASE ObjetCogido CASE 20 'Hacha Ataque1 = 1 CASE 21 'Espada Ataque1 = 2 END SELECT Suerte1 = INT(RND * Ataque1 * 10): Suerte2 = INT(RND * Ataque2 * 10) IF Suerte1 > Suerte2 THEN PonerM X, Y, 0 ELSE 'Si han tenido el mismo resultado, ambos pierden IF Suerte1 = Suerte2 THEN PonerM X, Y, 0 'Si el malo ha tenido mucha suerte, el bueno pierde m s vida. IF Suerte2 > Suerte1 * 10 THEN Efecto = Efecto * 2 Energia = Energia - Efecto LINE (256, 0)-(319, 199), 0, BF LINE (280, 0)-(296, 200 - Energia), 7, B LINE (280, 200 - Energia)-(296, 199), 7, BF IF Energia < 0 THEN Centrar 12, "Est s Muerto" END END IF END IF END SUB SUB MostrarP (X, Y) DEF SEG = MAQSEG% 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT POKE MAQDESP% + 1, Y: POKE MAQDESP% + 2, 0 POKE MAQDESP% + 4, X: POKE MAQDESP% + 5, 0 POKE MAQDESP% + 7, SPRSEG% MOD 256 POKE MAQDESP% + 8, INT(SPRSEG% / 256) POKE MAQDESP% + 10, SPRDESP% MOD 256 POKE MAQDESP% + 11, INT(SPRDESP% / 256) 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT 'END CALL ABSOLUTE(MAQDESP%) DEF SEG END SUB SUB PonerM (X, Y, Objeto) DEF SEG = MAPASEG% IF X > 127 OR Y > 255 THEN BEEP: EXIT SUB MEMUBIC& = MAPADESP% + (X * 256& + Y) POKE MEMUBIC&, Objeto DEF SEG END SUB SUB SPRITEPSET2 (N%) DIM SPR%(514) N2% = N% * 512 GET (0, 0)-(31, 31), SPR%(0) FOR F = 0 TO 511 SPR%(F + 2) = SPRITES%(N2% + F) NEXT 'SPR%(0) = 32: SPR%(1) = 32 PUT (288, 0), SPR%(0), PSET END SUB FUNCTION ValorM (X, Y) DEF SEG = MAPASEG% IF X > 127 OR Y > 255 THEN BEEP: EXIT FUNCTION MEMUBIC& = MAPADESP% + (X * 256& + Y) ValorM = PEEK(MEMUBIC&) DEF SEG END FUNCTION FUNCTION VALORMAPA% (X, Y) DEF SEG = MAPASEG% MEMUBIC% = MAPADESP% + (Y * 256 + X) VALORMAPA% = PEEK(MEMUBIC%) DEF SEG END FUNCTION * Mapages: un prototipo de editor de mapa DECLARE SUB ReorgaMapa () DECLARE SUB SPRITEPSET2 (n%) DECLARE SUB CARGASPRITES () DECLARE SUB PONERM (X%, Y%, Objeto%) DECLARE SUB MOSTRARP (X%, Y%) DECLARE FUNCTION VALORMAPA% (X%, Y%) DEFINT A-Z PRINT "MAPAGEST." PRINT "Creador de mapas para juegos que utilizan SPRGEST." SLEEP 5: I$ = INKEY$: I$ = "" CLS DIM SHARED NULL AS STRING * 1: NULL = CHR$(0) 'Este programa utiliza SPRGEST para poner gr ficos en pantalla. 'Lo que sigue son matrices est ticas '$STATIC DIM SHARED RUTINAMAQUINA%(1 TO 16), MAQDESP%, MAQSEG% 'Inicializar la rutina secundaria de c¢digo m quina. MAQDESP% = VARPTR(RUTINAMAQUINA%(1)) MAQSEG% = VARSEG(RUTINAMAQUINA%(1)) DEF SEG = MAQSEG% RESTORE RutiMaqData FOR F = 0 TO 15 READ DATO$ POKE MAQDESP% + F, VAL("&h" + LTRIM$(DATO$)) NEXT DEF SEG DIM SHARED MAPADESP%, MAPASEG% 'Tomar ubicaci¢n de INT 60h DEF SEG = 0 I60 = 4 * &H60 des = PEEK(I60) + 256 * PEEK(I60 + 1) MAPASEG% = PEEK(I60 + 2) + 256 * PEEK(I60 + 3) DEF SEG = MAPASEG% FOR F = 1 TO 8 IF PEEK(des + F + 1) <> ASC(MID$("SPR_GEST", F, 1)) THEN PRINT "ERROR: SPRGEST (gestor de sprites y memoria) no cargado." SYSTEM END IF NEXT UBI = des + 10 MAPADESP% = PEEK(UBI) + 256 * PEEK(UBI + 1) 'No podr‚ utilizar los 256 sprites, puesto que ocupan mucho m s de '64Kb. '$STATIC DIM SHARED SPRITES%(32766), SPRDESP%, SPRSEG% 'DIM SHARED SPRIT%(FRE(1) / 2) SPRDESP% = VARPTR(SPRITES%(0)) SPRSEG% = VARSEG(SPRITES%(0)) SCREEN 13 FOR F = 0 TO 10 STEP 2 FOR G = 0 TO 10 STEP 2 PONERM F, G, 0 PONERM F + 1, G, 1 PONERM F, G + 1, 1 PONERM F + 1, G + 1, 0 NEXT NEXT PONERM 0, 1, 1 PONERM 1, 0, 1 CARGASPRITES X = 0: Y = 0 SPRACT% = 0 LSTSPRACT% = -1 DO IF SPRACT% <> LSTSPRACT% THEN SPRITEPSET2 (SPRACT%) END IF LSTSPRACT% = SPRACT% MOSTRARP X1, Y1 LINE (X0 * 32, Y0 * 32)-(X0 * 32 + 31, Y0 * 32 + 31), 7, B LINE (X0 * 32 + 1, Y0 * 32 + 1)-(X0 * 32 + 30, Y0 * 32 + 30), 0, B DO: IN$ = INKEY$: LOOP UNTIL IN$ > "" SELECT CASE IN$ CASE NULL + CHR$(68) INPUT "Grabar: Entre el nombre del archivo mapa:"; Armapa$ IF Armapa$ > "" THEN IF INSTR(Armapa$, ".") = 0 THEN Armapa$ = Armapa$ + "._MA" DEF SEG = MAPASEG% BSAVE Armapa$, MAPADESP%, 32768! DEF SEG END IF CASE NULL + CHR$(67) INPUT "Cargar: Entre el nombre del archivo mapa:"; Armapa$ IF Armapa$ > "" THEN IF INSTR(Armapa$, ".") = 0 THEN Armapa$ = Armapa$ + "._MA" DEF SEG = MAPASEG% BLOAD Armapa$, MAPADESP% DEF SEG END IF 'Cambiado 256 a 61 (en realidad s¢lo hay 63 dibujos (o menos)) CASE "+": SPRACT% = SPRACT% + 1: IF SPRACT% > 62 THEN SPRACT% = 0 CASE "*": SPRACT% = SPRACT% + 1: IF SPRACT% > 62 THEN SPRACT% = 62 - SPRACT% CASE "-": SPRACT% = SPRACT% - 1: IF SPRACT% < 0 THEN SPRACT% = 61 CASE "/": SPRACT% = SPRACT% - 10: IF SPRACT% < 0 THEN SPRACT% = 62 + SPRACT% CASE "4", NULL + "K" X0 = X0 - 1 IF X0 < 0 THEN X0 = 0: IF X1 > 0 THEN X1 = X1 - 1 END IF CASE "8", NULL + "H" Y0 = Y0 - 1 IF Y0 < 0 THEN Y0 = 0: IF Y1 > 0 THEN Y1 = Y1 - 1 END IF CASE "6", NULL + "M" X0 = X0 + 1 IF X0 > 7 THEN X0 = 7: IF X1 < 119 THEN X1 = X1 + 1 END IF CASE "2", NULL + "P" Y0 = Y0 + 1 IF Y0 > 5 THEN Y0 = 5: IF Y1 < 248 THEN Y1 = Y1 + 1 END IF CASE CHR$(13) PONERM X0 + X1 + 1, Y0 + Y1 + 1, SPRACT% 'PLAY "C63" MOSTRARP X1, Y1 CASE CHR$(27): EXIT DO CASE NULL + CHR$(59)'F2 ReorgaMapa MOSTRARP X1, Y1 CASE CHR$(10) 'CTR_RET VM = VALORMAPA%(X1 + X0 + 1, Y1 + Y0 + 1) IF VM >= 0 AND VM <= 62 THEN SPRACT% = VM END SELECT IF INSTR("24568", IN$) > 0 THEN PONERM X0 + X1 + 1, Y0 + Y1 + 1, SPRACT% LOOP RutiMaqData: 'Rutina en c¢digo m quina DATA b8,00,00,bb,00,00,b9,00,00,ba,00,00,cd,60,cb,90 DatoJCarJuego: 'Datos de las paredes de varias direcciones del juego "JUEGO". DATA 12,3,2,18,17,16,15,14,7,6,5,4,8,11,10,9: SUB CARGASPRITES DO INPUT "Entre el nombre del juego de sprites:"; Archiv$ IF INSTR(Archiv$, ".") > 0 THEN PRINT "Lo siento, no puede especificar una extensi¢n." ELSE EXIT DO END IF LOOP Archiv$ = LTRIM$(RTRIM$(Archiv$)) PRINT "Cargando la paleta; espere, por favor..." DIM RGB AS STRING * 3 NFILE = FREEFILE OPEN Archiv$ + "._PA" FOR BINARY AS NFILE FOR F = 0 TO 255 GET NFILE, , RGB PALETTE F, CVL(RGB + NULL) NEXT F CLOSE NFILE PRINT "Cargando los dibujos; espere, por favor..." NFILE = FREEFILE OPEN Archiv$ + "._SP" FOR BINARY AS NFILE LIMITF = UBOUND(SPRITES%) 'X = 0: Y = 0 F = 0 DO UNTIL EOF(1) GET NFILE, , SPRITES%(F) 'MK$ = MKI$(SPRITES%(F)) 'SPRITES%(F) = CVI(RIGHT$(MK$, 1) + LEFT$(MK$, 1)) IF F = LIMITF THEN EXIT DO F = F + 1 LOOP CLOSE NFILE END SUB SUB MOSTRARP (X, Y) DEF SEG = MAQSEG% 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT POKE MAQDESP% + 1, Y: POKE MAQDESP% + 2, 0 POKE MAQDESP% + 4, X: POKE MAQDESP% + 5, 0 POKE MAQDESP% + 7, SPRSEG% MOD 256 POKE MAQDESP% + 8, INT(SPRSEG% / 256) POKE MAQDESP% + 10, SPRDESP% MOD 256 POKE MAQDESP% + 11, INT(SPRDESP% / 256) 'FOR F = 0 TO 16: PRINT RIGHT$("0" + HEX$(PEEK(MAQDESP% + F)), 2); " "; : NEXT: PRINT 'END CALL ABSOLUTE(MAQDESP%) DEF SEG END SUB SUB PONERM (X, Y, Objeto) DEF SEG = MAPASEG% IF X > 127 OR Y > 255 THEN BEEP: EXIT SUB MEMUBIC& = MAPADESP% + (X * 256& + Y) POKE MEMUBIC&, Objeto DEF SEG END SUB SUB ReorgaMapa CLS PRINT " Petici¢n de reorganizaci¢n del mapa." PRINT PRINT " ATENCIàN: si su mapa no utiliza un jue-" PRINT " go de objetos compatible con ®JUEGO¯, " PRINT " esta opci¢n podr¡a arruinar su trabajo." PRINT INPUT "¨Proseguir?"; A$ IF A$ <> "S" AND A$ <> "s" THEN EXIT SUB RESTORE DatoJCarJuego FOR F = 0 TO 15 READ CADV CAD$ = CAD$ + CHR$(CADV) NEXT FOR FX = 0 TO 127 FOR FY = 0 TO 255 VMACT = VALORMAPA(FX, FY) 'Utilizo IF...THEN IF ... THEN IF... THEN porque suele ser 'm s r pido que AND. '1)- S¢lo se act£a sobre bloques de pared est ndar (2...18 excepto 13) IF VMACT >= 2 THEN IF VMACT <= 18 THEN IF VMACT <> 13 THEN VBL = 0 IF FX > 0 THEN VMIZQ = VALORMAPA(FX - 1, FY) ELSE VMIZQ = 0 IF FX < 127 THEN VMDCH = VALORMAPA(FX + 1, FY) ELSE VMDCH = 0 IF FY > 0 THEN VMARR = VALORMAPA(FX, FY - 1) ELSE VMARR = 0 IF FY < 255 THEN VMABA = VALORMAPA(FX, FY + 1) ELSE VMABA = 0 IF VMIZQ >= 2 THEN IF VMIZQ <= 18 THEN IF VMIZQ <> 13 THEN VBL = VBL + 1 IF VMDCH >= 2 THEN IF VMDCH <= 18 THEN IF VMDCH <> 13 THEN VBL = VBL + 2 IF VMARR >= 2 THEN IF VMARR <= 18 THEN IF VMARR <> 13 THEN VBL = VBL + 4 IF VMABA >= 2 THEN IF VMABA <= 18 THEN IF VMABA <> 13 THEN VBL = VBL + 8 PONERM FX, FY, ASC(MID$(CAD$, 1 + VBL, 1)) END IF END IF END IF NEXT LOCATE 15, 1: PRINT USING "###.## % del mapa completado."; (FX / 127) * 100 NEXT END SUB SUB SPRITEPSET2 (n%) DIM SPR%(514) N2% = n% * 512 GET (0, 0)-(31, 31), SPR%(0) FOR F = 0 TO 511 SPR%(F + 2) = SPRITES%(N2% + F) NEXT 'SPR%(0) = 32: SPR%(1) = 32 PUT (288, 0), SPR%(0), PSET END SUB FUNCTION VALORMAPA% (X, Y) DEF SEG = MAPASEG% IF X < 0 OR Y < 0 THEN BEEP: EXIT FUNCTION IF X > 127 OR Y > 255 THEN BEEP: EXIT FUNCTION MEMUBIC& = MAPADESP% + (X * 256& + Y) VALORMAPA% = PEEK(MEMUBIC&) DEF SEG END FUNCTION