Mostrando entradas con la etiqueta Herramientas de creación. Mostrar todas las entradas
Mostrando entradas con la etiqueta Herramientas de creación. Mostrar todas las entradas

viernes, 17 de mayo de 2024

Efecto de scanlines de TV en archivos HTML

Si queremos dar un toque añejo a nuestros juegos o web realizada en HTML, podremos hacerlo de una forma muy sencilla. En la hoja de estilo, o dentro de la etiqueta Style de HTML, deberemos añadir el siguiente código CSS:

/* CRT */ 

@keyframes flicker{0%{opacity:0.27861;}5%{opacity:0.34769;}10%{opacity: 0.23604;}15%{opacity:0.90626;}20%{opacity:0.18128;}25%{opacity:0.83891;}30%{opacity:0.65583;}35%{opacity:0.67807;}40%{opacity:0.26559;}45%{opacity:0.84693;}50%{opacity:0.96019;}55%{opacity:0.08594;}60%{opacity:0.20313;}65%{opacity:0.71988;}70%{opacity:0.53455;}75%{opacity:0.37288;}80%{opacity:0.71428;}85%{opacity:0.70419;}90%{opacity:0.7003;}95%{opacity:0.36108;}100%{opacity:0.24387;}} @keyframes textShadow{0%{text-shadow: 0.4389924193300864px 0 1px rgba(0,30,255,0.5), -0.4389924193300864px 0 1px rgba(255,0,80,0.3), 0 0 3px;}5%{text-shadow: 2.7928974010788217px 0 1px rgba(0,30,255,0.5), -2.7928974010788217px 0 1px rgba(255,0,80,0.3), 0 0 3px;}10%{text-shadow: 0.02956275843481219px 0 1px rgba(0,30,255,0.5), -0.02956275843481219px 0 1px rgba(255,0,80,0.3), 0 0 3px;}15%{text-shadow: 0.40218538552878136px 0 1px rgba(0,30,255,0.5), -0.40218538552878136px 0 1px rgba(255,0,80,0.3), 0 0 3px;}20%{text-shadow: 3.4794037899852017px 0 1px rgba(0,30,255,0.5), -3.4794037899852017px 0 1px rgba(255,0,80,0.3), 0 0 3px;}25%{text-shadow: 1.6125630401149584px 0 1px rgba(0,30,255,0.5), -1.6125630401149584px 0 1px rgba(255,0,80,0.3), 0 0 3px;}30%{text-shadow: 0.7015590085143956px 0 1px rgba(0,30,255,0.5), -0.7015590085143956px 0 1px rgba(255,0,80,0.3), 0 0 3px;}35%{text-shadow: 3.896914047650351px 0 1px rgba(0,30,255,0.5), -3.896914047650351px 0 1px rgba(255,0,80,0.3), 0 0 3px;}40%{text-shadow: 3.870905614848819px 0 1px rgba(0,30,255,0.5), -3.870905614848819px 0 1px rgba(255,0,80,0.3), 0 0 3px;}45%{text-shadow: 2.231056963361899px 0 1px rgba(0,30,255,0.5), -2.231056963361899px 0 1px rgba(255,0,80,0.3), 0 0 3px;}50%{text-shadow: 0.08084290417898504px 0 1px rgba(0,30,255,0.5), -0.08084290417898504px 0 1px rgba(255,0,80,0.3), 0 0 3px;}55%{text-shadow: 2.3758461067427543px 0 1px rgba(0,30,255,0.5), -2.3758461067427543px 0 1px rgba(255,0,80,0.3), 0 0 3px;}60%{text-shadow: 2.202193051050636px 0 1px rgba(0,30,255,0.5), -2.202193051050636px 0 1px rgba(255,0,80,0.3), 0 0 3px;}65%{text-shadow: 2.8638780614874975px 0 1px rgba(0,30,255,0.5), -2.8638780614874975px 0 1px rgba(255,0,80,0.3), 0 0 3px;}70%{text-shadow: 0.48874025155497314px 0 1px rgba(0,30,255,0.5), -0.48874025155497314px 0 1px rgba(255,0,80,0.3), 0 0 3px;}75%{text-shadow: 1.8948491305757957px 0 1px rgba(0,30,255,0.5), -1.8948491305757957px 0 1px rgba(255,0,80,0.3), 0 0 3px;}80%{text-shadow: 0.0833037308038857px 0 1px rgba(0,30,255,0.5), -0.0833037308038857px 0 1px rgba(255,0,80,0.3), 0 0 3px;}85%{text-shadow: 0.09769827255241735px 0 1px rgba(0,30,255,0.5), -0.09769827255241735px 0 1px rgba(255,0,80,0.3), 0 0 3px;}90%{text-shadow: 3.443339761481782px 0 1px rgba(0,30,255,0.5), -3.443339761481782px 0 1px rgba(255,0,80,0.3), 0 0 3px;}95%{text-shadow: 2.1841838852799786px 0 1px rgba(0,30,255,0.5), -2.1841838852799786px 0 1px rgba(255,0,80,0.3), 0 0 3px;}100%{text-shadow: 2.6208764473832513px 0 1px rgba(0,30,255,0.5), -2.6208764473832513px 0 1px rgba(255,0,80,0.3), 0 0 3px;}} .crt::after{content:" ";display:block;position:absolute;top:0;left:0;bottom:0;right:0;background:rgba(18, 16, 16, 0.1);opacity:0;z-index:2;pointer-events:none;animation:flicker 0.15s infinite;} .crt::before{content:" ";display:block;position:absolute;top:0;left:0;bottom:0;right:0;background:linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%),linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));z-index:2;background-size:100% 2px, 3px 100%;pointer-events:none;} .crt{animation:textShadow 1.6s infinite;}

En el archivo HTML, dentro de la etiqueta body o de un div que englobe la estructura del juego, habrá que llamar a la clase de la siguiente forma:

<div class="crt"> o <body class="crt">

Según la etiqueta que usemos.

Para aprovecharlo en nuestros juegos realizados con Twine 2,  tendremos que añadir el código CSS al estilo de nuestro juego, y dentro de todos los pasajes, incluir el texto dentro de la siguiente estructura:

<div class="crt"> Texto del pasaje </div> 



 

jueves, 18 de mayo de 2023

Pocket Platformer


Hoy día, quien no crea un juego es porque no quiere (o no tiene tiempo, vale) pero la falta de conocimientos hace tiempo que dejó de ser una excusa. Con la aparición de "engines" como Game Maker o Multimedia Fusion que se basaban en el "no-code", hacer un juego nos alejaba de aprender complejos lenguajes de programación, pudiendo desarrollar un matamarcianos simplemente añadiendo objetos a la escena y dándole propiedades a los mismos. Obviamente, no tendremos el control sobre el producto que tendríamos de haber desarrollado el juego desde cero, pero para la mayoría de los mortales con un deseo por hacer un juego, es suficiente.

Hay multitud de programas en el mercado que nos facilitan la creación de juegos y este no es un post para hablar de ellos, pero incluso los grandes como Unreal Engine o Unity tienen integrado o algún plugin de "Visual Script" con el que no tener que programar. Uno de los últimos programas con los que me  he encontrado para hacer juegos es Pocket Platformer, desarrollado por @the_l0bster e inspirado en Mario Maker, Bitsy y la "consola de fantasía" Pico-8. Como su propio nombre indica, está enfocado en los juegos de plataformas y es quizá el más sencillo de usar que me he encontrado hasta el momento. Se ejecuta desde su página en Itch.io así que no tendremos que instalar nada. Viene con una serie de gráficos predeterminados con sus características asociadas aunque podremos crear los nuestros propios. Según el tipo de gráfico que modifiquemos, tendremos un NPC, objetos de decoración, tiles de escenario, etc. En la ventana podremos ir colocando los objetos con el botón izquierdo del ratón y borrarlos con el derecho. La interface la completan una columna con las opciones del juego que podremos cambiar, como el nombre, el mensaje cuando acabe el juego, si el jugador tendrá doble salto o no, y la ventana de los niveles, que podremos ir editando de forma sencilla. Podremos exportar con solo un clic el juego a un archivo HTML, será la forma de guardarlo si cerramos el navegador sin haberlo terminado pues al importarlo, podremos seguir editándolo.

Entre las pegas que se le pueden poner está el mencionado de la escasez de opciones de modificación. Podremos elegir el color del fondo, pero será el mismo para todos los niveles, no podremos poner una imagen de fondo, tampoco añadir música a menos que lo hagamos con un enlace web a una canción que tengamos subida en alguna parte. No se puede modificar la pantalla de Título, la de derrota / victoria es la misma y podría seguir un buen rato, pero pese a todo, merece la pena pasar una tarde desarrollando un pequeño plataformas con el que poner en práctica niveles para implementar en otros proyectos más grandes o simplemente darnos la satisfacción de haber creado un juego. 



miércoles, 13 de marzo de 2019

Death Generator

La comunicación humana ha ido evolucionando a lo largo de la historia: desde los iniciales gruñidos ininteligibles, hasta los libros, pasando por jeroglíficos en piedra o señales de humo. En la era de Internet, dicha evolución ha seguido su curso y hoy día raro es no encontrar un mensaje que no esté complementado por un gif o un meme.

Por ello, han surgido infinidad de herramientas para crear dichas imágenes. Una de ellas es Death Generator, desarrollada por el usuario Foone, en el que podremos añadir el texto que queramos, a imágenes de distintos videojuegos, desde la pantalla de inicio de Super Mario World, hasta la carta que escribe Peach en Super Mario 64, pasando por la pizarra de la clase de medicina de Life & Death. La lista de juegos cuyas imágenes podemos modificar es enorme y nos puede servir tanto para crear memes graciosos, como para perfilar nuestros desarrollos, eso sí, teniendo en cuenta que el contenido tiene copyright de sus distintos creadores y que no se verán los caracteres especiales que usamos en la lengua española como la "ñ", las tildes o los signos de apertura de interrogación y exclamación. 

Puedes encontrar Death Generator en la siguiente dirección: http://deathgenerator.com





jueves, 7 de marzo de 2019

Adventures para Twine 2

Twine se usa principalmente para historias interactivas con texto y alguna que otra imagen, al estilo de los libros de "Elige tu propia aventura". Sin embargo, los límites están para romperlos y por ello, el usuario Longwelwind, ha creado "Adventures" un formato de historia para Twine 2 con el que crear historias algo más interactivas que la simple elección de opciones a los que estamos acostumbrados.

Para empezar, nos encontraremos con un aspecto visual del juego que recuerda a los RPG de los 8 bits, con una fuente parecida a la que podemos encontrar en los viejos arcades, un panel con información de nuestro personaje, una barra de vida y un inventario con iconos que representarán a los objetos que podemos conseguir.

Instalarlo es tan sencillo como agregar un nuevo formato de historia y no tendremos que hacer más que escribir nuestra aventura. Adventures está basado en Snowman 2, por lo que podremos pasar funciones JavaScript usando los símbolos <% %> Abriéndose un abanico de posibilidades como implantar un sistema de lucha, una tienda, misiones, etc. 

Puedes descargar la documentación en español traducida por mí en la siguiente dirección:


 

miércoles, 27 de febrero de 2019

Bitsy Game Maker

Hoy día quien no hace un juego es porque no quiere. Y quien dice juego, dice aventura o literatura interactiva. Ya no es no es necesario aprender los secretos de la programación en C pues existen multitud de herramientas para facilitar la vida a esos pobres creadores que lo único que quieren es contar algo de forma más o menos entretenida, sin tener que dejarse los ojos estudiando arrays o polimorfimos de clases.

Una de esas herramientas es Bitsy Game Maker, programada por Adam Ledoux. Bitsy funciona en cualquier navegador, aunque está optimizado para Google Chrome. Yo suelo usar Firefox y no he encontrado ningún problema, he de decir. Consta de una página web, que en cuanto se carga, nos muestra distintos paneles que corresponden a los aspectos de nuestro juego:

. Dibujar: donde podremos crear los sprites del protagonista, los tiles que conformarán nuestros niveles, los personajes que nos encontraremos y los objetos a recoger. Además podremos crear animaciones de los mismos fácilmente, así como configurar los mensajes que se mostrarán en pantalla cuando interactuemos con ellos.

. Room: será donde creemos nuestros niveles, con una perspectiva cenital.

. Sobre Bitsy: en el que se muestra un texto con agradecimientos y el objeto de la creación del programa, así como unas breves instrucciones.

. Salidas: donde definiremos las salidas de las distintas pantallas de nuestro juego.

. Finales: que nos permitirá crear un mensaje para dar por terminado el juego.

. Buscar dibujo: para seleccionar fácilmente los componentes del juego que hayamos dibujado. Muy práctico si hemos creado tiles complejos, a la hora de dibujar los niveles.

. Colores: para seleccionar el color del fondo y de los objetos, teniendo en cuenta que solo podremos usar dos colores en todo el juego.

. Diálogo: con una lista de los diálogos que introduzcamos.

. Descargar: para descargar nuestro fichero HTML con el juego y poder distribuirlo como mejor nos parezca.

. Grabar GIF: para grabar un gif de nuestro juego y posteriormente descargarlo para facilitar su publicidad.

. Datos del juego: una vista del código tras el juego.

. Ajustes: con una serie de opciones de Bitsy que podremos modificar, como idioma del programa, color de la página, fuente, etc.



Bitsy cuenta con varias limitaciones: solo se pueden usar dos colores, no cuenta con sonido, y más allá de hablar con los personajes que nos encontremos, no podremos interactuar de otras formas; sin embargo, es una buena forma de introducirse en el desarrollo de historias más allá del simple texto plano. Si quieres probar algún juego, en Itch.io encontrarás una buena selección.

Puedes encontrar Bitsy en la siguiente dirección: https://ledoux.itch.io/bitsy

Actualmente se encuentra en su versión 5.4 Si quieres descargarlo y poder trastear sin estar conectado a Internet, puedes hacerlo desde la página de Github del desarrollador: https://github.com/le-doux/bitsy

martes, 18 de diciembre de 2018

PlataGO!

Si te gusta hacer videojuegos hay multitud de programas, engines, frameworks y librerías ahí fuera como para cubrir las necesidades del profano y del experto. Las opciones van desde el software generalista como Unity o Game Maker, hasta algo más especializado, según el tipo de videojuego que queramos crear, como Renpy o el título que nos ocupa hoy: PlataGO!

Antes de nada, he de decir que es un juego que se encuentra en Early Access y que podréis encontrar en Steam por 5 dólares. Sus creadores son los mismos que están detrás de Life of Pixel, un simpático plataformas en el que hacíamos un recorrido a las principales plataformas de juegos desde la Atari 2600 hasta la Super Nintendo, pasando por muchas más. Pues bien, en PlataGO podremos crear nuestros plataformas para todos esos sistemas. 

El funcionamiento es el siguiente: seleccionamos un tema de los diez disponibles, diseñamos nuestro nivel pinchando y arrastrando en los elementos que queramos ver en el mismo, si pulsamos con el botón derecho del ratón sobre algunos elementos podremos modificar variables como la velocidad, el número de disparos (en caso de ser un enemigo), la velocidad de una plataforma, etc. Una vez hemos terminado, podemos seleccionar otro tema y no tendremos que hacer nada más para ver el juego que habíamos creado con los gráficos de Game Boy, como si fuera uno de Spectrum. Una vez guardado nuestro nivel, podremos jugarlo cuando queramos. Además, podremos enlazar distintos niveles creando un mapa similar al que se veía en los niveles estrella de Super Mario World, creando un "juego". Tanto los niveles, como los juegos, podremos subirlos a la Steam Workshop, donde podremos encontrar y crear nuevos temas, personajes, niveles y juegos creados por la comunidad.

Se puede considerar una pega el que no podamos exportar los juegos a un archivo independiente, pero en realidad, más que un "maker" se trata de un juego, así que es una opción que aunque deseable, no es totalmente necesaria. Otras pegas que se le pueden poner son las escasas opciones de decoración de nuestros niveles, o el escaso número de enemigos, pero teniendo en cuenta que podemos crear nuestros propios gráficos, tampoco es una desventaja, aunque todo lo que venga de gratis, es siempre bien recibido.

Al estar todavía en desarrollo, se pueden encontrar decenas de bugs muy evidentes, aunque a día de hoy es un título totalmente funcional, recomendable para todo aquel que quiera probar sus habilidades de diseño de niveles de plataformas de una forma fácil y rápida, sin tocar una sola línea de código.

A continuación, una lista de las características que podremos encontrar por ahora, traducida del siguiente post en Steam:


Temas Visuales


10 temas visuales de las siguientes consolas y ordenadores:

-ZX Spectrum
-C64
-Gameboy
-NES
-AppleII
-Amiga: muy parecido al de SuperNes
-SNES
-Moderno: gráficos más o menos actuales
-SciFi horror: temática de horror
-Minimal: graficos rojos y blancos que recuerdan al Virtual Boy.

Opciones de los niveles


- Gravedad editable
- Un HUD donde colocar los iconos de vida, tiempo que queda para terminar el nivel, gemas recogidas, puntos...
- Tres capas con las que crear profundidad en nuestros niveles haciendo que el personaje pase por detras de árboles, por ejemplo.
- Scroll parallax
- Autoscroll vertical y horizontal


Personalizacion del protagonista


- Se puede elegir entre un chico y una chica, aunque podemos crear los nuestros
- Edición del salto, si queremos hacer doble o triple, que salte por las paredes.
- Fricción en las paredes, en el suelo y el aire.
- Salud que queremos que tenga o pueda conseguir
- Puede saltar sobre enemigos y puede disparar en diagonal
- Se pueden recoger armas y todo tipo de objetos

Terreno


- Bloques estáticos de distintos tipos
- Columnas y tuberías
- Pendientes
- Escaleras
- Bloques que se destruyen al pasar o se caen
- Plataformas estáticas y móviles
- Bloques invisibles
- Teletransportadores
- Cañones para saltar
- JetPack
- Trampas como pinchos o lava
- Enemigos que vuelan y van por el suelo y pueden disparar...

Todo esto y mucho más que me dejo, aparte de lo que se vaya a incluir en un futuro.


lunes, 15 de enero de 2018

Puzzle Script

P.S.. es un engine de creación de juegos basados en puzles que se pueden desarrollar en HTML5. En realidad está más enfocado a los juegos estilo "Sokoban" de mover cajas para colocarlas en determinados sitios, aunque como todo, se puede exprimir para crear otro tipo de puzles. Podremos acceder a él desde la página web: http://www.puzzlescript.net Una vez allí, podremos disfrutar de varios títulos realizados con la herramienta, un sencillo tutorial con el que hacer nuestros primeros pinitos, aparte de una extensa documentación si queremos profundizar en la materia y el programa en sí.

Este es muy sencillo de usar. Cuando pulsemos en el enlace, se nos abrirá una ventana dividida en dos de forma vertical. A la izquierda podremos encontrar el código fuente a editar, la ventana derecha está a su vez dividida en dos: arriba con una muestra de nuestro juego y debajo de esta, distintas herramientas y la consola de información, donde podremos ver los distintos mensajes de error, confirmación, etc, a medida que se vaya ejecutando nuestro código.

En la parte superior, nos encontramos con un menú desde el cual cargar distintos ejemplos, así como las opciones de compilar, ejecutar nuestro juego, compartirlo con la comunidad, acceso a la documentación y los foros. Como comentaba, podremos compartir el juego, en cuyo caso el engine creará un enlace en sus servidores desde el cual acceder al mismo y además podremos descargar un archivo HTML por si queremos subirlo a cualquier otro sitio.

Una característica muy curiosa es que podremos escoger la paleta de nuestro juego, para simular sistemas como GameBoy, C64, Amiga500, Master System, etc. De esta forma podremos crear la ilusión de encontrarnos ante un juego desarrollado para estas máquinas.

Los juegos que podremos encontrar tienen un enlace llamado "Hack" que si lo pulsamos, nos llevará al editor de Puzzlescript, de forma que podremos ver su código y así saber cómo han hecho determinada acción, algo muy útil para aprender rápidamente.

Podéis encontrar una traducción de su documentación, realizada por mí, en las siguientes direcciones:
Como curiosidad, existe otra versión llamada DungeonScript, en el que podremos crear juegos de puzzle que se jueguen en primera persona. Puedes probarlo en la siguiente dirección: http://dungeonscript.farbs.org/editor.html

domingo, 7 de enero de 2018

Pix64

Las consolas virtuales están experimentando un inusitado florecimiento en los últimos tiempos. Desde la primigenia (creo) Pico-8 hasta otras como Liko-12, no dejan de aparecer máquinas "de fantasía" con una serie de limitaciones con las que programar nuestros juegos. En esta ocasión hablaremos de Pix64, creado por ZappedCow, que podéis encontrar en Twitter con dicho nick. La particularidad de esta consola es que sus juegos se componen de una sola pantalla, que podremos dibujar en una imagen de 64x64 píxeles, siguiendo el siguiente código de colores:

000000   Será utilizado para crear espacios vacíos o el fondo, mismamente
FFFFFF  Es el color para pintar paredes
00FFFF   Es el color asignado a nuestro jugador
00FF00  Se usará para señalar la meta del juego, por ejemplo la línea de llegada o monedas que tendremos que recoger
FFFF00   Es el color de los obstáculos, que una vez otro objeto choque contra ellos, desaparecerán
FF0000   Con este color se señalará al enemigo o enemigos de nuestro juego. Si chocamos contra algo de este color, moriremos

Además, está la particularidad de que si dibujamos una flecha, esta se moverá automáticamente en el sentido al que apunta, sin detenerse.

El pequeño tamaño de las imágenes hace que se convierta en todo un desafío el idear pantallas con las que retar a nuestros amigos. Obviamente no existe ningún método de exportación de nuestros "cartuchos", sino que deberemos usar el programa para ejecutarlos. Nuestros juegos deberán ir dentro de la carpeta Carts en el directorio principal. El nombre de los mismos no debería tener más de 17 caracteres, contando espacios, si queremos que se pueda leer entero.

Cuando iniciemos Pix64, nos aparecerá una lista con los juegos instalados que podremos seleccionar. Además, tendremos de inicio tres escuetos tutoriales con los que aprender las bases del programa y varios ejemplos para darnos ideas. Con la tecla ESC saldremos al menú principal y con la R, reiniciaremos la partida.

Por descontado no se trata de un método serio de creación de juegos, pero sí que supondrá un desafío para los diseñadores de niveles.

Puedes descargar Pix64 desde la siguiente dirección: https://zappedcow.itch.io/pix64


Cavern of Ruilova 2 - Un nivel de prueba que hice para ilustrar el artículo

miércoles, 23 de septiembre de 2015

Megazeux

ZZT es un juego desarrollado en 1991 por Tim Sweenye para la empresa Potomac Computer Systems, que más tarde se convertiría en la conocida Epic Megagames, que tenía una curiosa particularidad para la época: sus gráficos estaban creados con caracteres ANSI.

Se trataba de una aventura en la que controlábamos a un personaje representado por un rectángulo con ojos a través de distintos escenarios de distinta temática, mientras íbamos recogiendo gemas, disparando a los enemigos y resolviendo puzles. Tuvo tanto éxito entre la comunidad de jugadores que pronto se usó su motor para crear, no solo clónicos, sino first person shooters, shoot´m´ups y hasta juegos tipo Lemmings.

Un año después nacería su sucesor, SuperZZT, que permitía mapas más grandes, scroll en los mismos, nuevos enemigos y objetos entre otras muchas ventajas, entre la que destacaba la inclusión de un editor para que cualquiera pudiera crear sus propios niveles, aunque se dice que estaban un tanto decepcionados con el mismo, por lo que solo se podía acceder a él a través de la linea de comandos. No tardaron mucho en surgir programas inspirados en estos juegos, entre ellos Megazeux.

Puesto a la venta en 1994, a lo largo de los años ha sido portado a multitud de sistemas: Windows 95 y superiores, Linux, Mac OS X, Wii, GP2X, PSP y DS, además de versiones para AmigaOS 4, OpenBSD, FreeBSD OpenSolaris, Haiku y Android.

Pese a correr en tan amplio parque de máquinas, su popularidad es mínima fuera de los círculos de creadores que suelen agruparse en webs como dMZX, donde se puede descargar el programa de forma totalmente gratuita, además de encontrar centenares de juegos de todo tipo, recursos, un foro
donde resolver nuestras dudas y mucha más información. Este poco interés por parte del gran público seguramente sea debido a que sus gráficos son considerados como prehistóricos por parte de las nuevas generaciones, más pendientes de los 1080p y los frames por segundo a los que corre un juego que a la diversión que ofrece este tipo de títulos, a prueba de bombas.

Megazeux es muy sencillo de usar. Nada más arrancar el programa nos aparecerá una pantalla en la que cargar el mundo que queramos. Modificando el fichero de configuración, podremos hacer que nos aparezca directamente la pantalla de edición, a la que accederemos si no cargamos ningún juego.

En la parte inferior podremos ver un menú con distintas opciones en las que podremos modificar las opciones globales del juego, añadir tableros (las pantallas de las que constará nuestro mundo / juego), los elementos que conformarán dicho tablero, grabar nuestro progreso, probar nuestro mundo, etc, etc. Tendremos a nuestra disposición también, lo que en Megazeux se llaman "robots", subrutinas, código con el que programar comportamientos que afecten al juego, como mostrar determinados gráficos, el diseño de puzles, etc.

Decir también, que con Megazeux podremos jugar a cualquiera de los títulos que encontremos por la red. Entre los cuales recomendamos:

. Termination Rehash: http://vault.digitalmzx.net/show.php?id=1367
. Zeux 2: Caverns of Zeux: http://vault.digitalmzx.net/show.php?id=182
. Commander Keen: Heroes Lost: http://vault.digitalmzx.net/show.php?id=1986
. Castle of Zeux: http://vault.digitalmzx.net/show.php?id=142
. Pandora´s Gate: http://vault.digitalmzx.net/show.php?id=1761

Si no quieres instalar nada pero te pica la curiosidad sobre este tipo de juegos, en Archive.org tienen a disposición de los usuarios más de 2000 juegos basados en ZZT para jugar online en la siguiente dirección: https://archive.org/details/softwarelibrary_msdos_zzt

Aparte de la información que puedas encontrar en los foros de la mencionada página oficial, existe un tutorial en Youtube creado por Graham Peet, que podréis encontrar en la siguiente dirección:

https://www.youtube.com/watch?v=dzAOo812cU0&index=1&list=PLqNVTZpOeTjNPd-eJOgZ5EFWIi_btY7Nn

Es una serie de 24 vídeos en los que nos explica de forma sencilla todos los aspectos a tener en cuenta a la hora de desarrollar nuestro juego en MZX. Eso sí, el audio se encuentra en inglés, aunque siguiendo las imágenes en pantalla no es muy complicado seguirle.

lunes, 12 de enero de 2015

Microsoft Virtual Academy

A la fiebre, que parece no tener fin, por la enseñanza gratuita online se viene a sumar la compañía informática por excelencia: Microsoft, que ofrece en su plataforma "Microsoft Virtual Academy" diferentes cursos gratuitos para todo aquel que se quiera formar en el manejo de sus herramientas. Allí podremos encontrar desde cómo programar apps o aplicaciones de escritorio para Windows y Windows Phone, hasta nociones de servicio técnico, pasando por distintos cursos en los que aprender a usar una amplia gama de aplicaciones y servicios del gigante de Redmond.

¿Y qué tiene que ver eso con los videojuegos? Os estaréis preguntando. Pues bien, resulta que entre tal marasmo de información, también se imparten materias sobre la programación de juegos. Si disponemos de una cuenta de hotmail, podremos registrarnos y disfrutar de las siguientes lecciones:

. Developing games with Construct 2
. Desarrolla tu primera aplicación para Kinect V2 con Visual Studio
. Developing 2D & 3D games with Unity for Windows Jump Start
. Creating games with Project Spark
. Conceptos de desarrollo en XNA con Visual Studio
. Gaming Engines for Windows 8 Jump Start (también disponible en español)
. Desarrollo de videojuegos 2D para Windows 8 con Unity
. Creación de videojuegos para Windows 8.1 con Game Maker Studio
. Crear juegos en línea usando Windows Azure Mobile Services
. Crear videojuegos adictivos para Windows 8 y Windows Phone 8
. Porting Unity games to Windows Store and Windows Phone

Obviamente la mayoría son cursos que buscan enganchar futuros usuarios de los productos Microsoft pero nunca está de más aprender algo nuevo. No he tenido oportunidad de comprobar la profundidad de la materia que se imparte, pero es de suponer que al menos servirá como una primera aproximación al desarrollo de videojuegos. Podéis acceder a la MVA desde la siguiente dirección:

martes, 21 de febrero de 2012

[RPGMACE]: Minimapa


Script para mostrar un minimapa en la pantalla de juego para saber por donde nos movemos. No es muy estético pero si funcional.

Código:

#_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#_/ ? Minimap - KMS_MiniMap ? VXAce ?
#_/ ? Last update : 2012/02/12 (TOMY@Kamesoft) ?
#_/ ? Website: http://ytomy.sakura.ne.jp/ ?
#_/ ? Translated by Mr. Bubble ?
#_/----------------------------------------------------------------------------
#_/ Createts a minimap HUD based off the passability settings of the map.
#_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
# This script is plug-and-play, but various customization options are available.
#----------------------------------------------------------------------------
# Map Notetags
#----------------------------------------------------------------------------
# Notetags are added to "Notes" boxes. Right-click a map and select
# Map Properties to find the "Notes" box for maps.
#
# <minimap hide>
# Completely disables the minimap on a specific map. [NOMAP] can also be
# added to the beginning of map names for the same effect.
#----------------------------------------------------------------------------
# Event Comment Tags
#----------------------------------------------------------------------------
# Since events do not have noteboxes, comment tags are used instead. Open the
# event, create a new event command, go to Tab 1, and click the "Comment..."
# event command. A box will open up allowing you to enter tags.
#
# <minimap wall>
# Add this tag to an event's comment to change its minimap color to the
# same as an impassable tile.
#
# <minimap move>
# Add this tag to an event's comment to have them blink in the minimap.
#
# <minimap obj n>
# Add this tag to an event's comment to have them blink in the minimap with
# a specified color where n is the OBJ value defined in OBJECT_COLOR which
# is found in the customization module below.
#----------------------------------------------------------------------------
# Script Calls
#----------------------------------------------------------------------------
# Script calls are used in "Script..." event commands located under Tab 3.
#
# hide_minimap
# Use this script call to hide the minimap on command.
#
# show_minimap
# Use this script call to show the minimap on command.
#
# refresh_minimap
# Use this script call to refresh the minimap.
#
# update_minimap_object
# Use this script call to refresh objects on the minimap such as events.
#----------------------------------------------------------------------------
# Script Calls : Conditional Branches
#----------------------------------------------------------------------------
# The following script calls can be used in Conditional Branches.
#
# minimap_showing?
# Determines if the minimap is currently showing/hidden.
#----------------------------------------------------------------------------
# Usage Notes
#----------------------------------------------------------------------------
# Impassable events will not appear as the correct color in the minimap.
# This effect is intended. If you want an event to appear as impassable
# on the minimap, add the tag <minimap wall> to an event's comment.
#_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

#==============================================================================
# ? BEGIN Setting ?
#==============================================================================
module KMS_MiniMap
# * Minimap Display Toggle Button
# Set to nil to disable this function
SWITCH_BUTTON = :Z

# * Minimap Size and Position (x, y, width, height)
MAP_RECT = Rect.new(364, 20, 160, 120)
# * Minimap z-layer Priority
# Glitchy if this value is set too high
MAP_Z = 0
# * Minimap Grid Size
# A size of 3 or higher is recommended
GRID_SIZE = 5

# * Mini-Map Color Settings
# Color.new(red, green, blue, opacity)
FOREGROUND_COLOR = Color.new(224, 224, 255, 160) # Foreground (passable)
BACKGROUND_COLOR = Color.new( 0, 0, 160, 160) # Background (not passable)
POSITION_COLOR = Color.new(255, 0, 0, 192) # Current Position color
MOVE_EVENT_COLOR = Color.new(255, 160, 0, 192) # Moving event color
VEHICLE_COLOR = Color.new( 96, 128, 0, 192) # Vehicle color

# * Object Color Presets
# Create custom color presets for events tagged with the
# corresponding OBJ tag
OBJECT_COLOR = [
# Color.new(red, green, blue, opacity)
Color.new( 0, 128, 0, 192), # OBJ 1
Color.new( 0, 160, 160, 192), # OBJ 2
Color.new(160, 0, 160, 192), # OBJ 3

# More color presets may be added in this array where OBJ number is
# determined by the position in the list (OBJ 4, OBJ 5, etc.)

] # <- Do not delete this line

# * Minimap Blinking Frequency
# Values 5~8 are recommended
BLINK_LEVEL = 7

# * Minimap Cache Setting
# This script creates a cache for each map. If the number of cached
# maps exceed CACHE_NUM, oldest cached maps are deleted.
CACHE_NUM = 10
end
#==============================================================================
# ? END Setting ?
#==============================================================================

$kms_imported = {} if $kms_imported == nil
$kms_imported["MiniMap"] = true

module KMS_MiniMap
# ????????
REGEX_NO_MINIMAP_NOTE = /<(?:?????|MINIMAP)\s*(?:???|HIDE)>/i
REGEX_NO_MINIMAP_NAME = /\[NOMAP\]/i

# ???
REGEX_WALL_EVENT = /<(?:?????|MINIMAP)\s*(?:?|???|WALL)>/i

# ??????
REGEX_MOVE_EVENT = /<(?:?????|MINIMAP)\s*(?:??|MOVE)>/i

# ??????
REGEX_OBJECT = /<(?:?????|MINIMAP)\s+OBJ(?:ECT)?\s*(\d+)>/i
end

# *****************************************************************************

#==============================================================================
# ? KMS_Commands
#==============================================================================

module KMS_Commands
module_function
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def show_minimap
$game_temp.minimap_manual_visible = true
$game_system.minimap_show = true
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def hide_minimap
$game_system.minimap_show = false
end
#--------------------------------------------------------------------------
# ? ????????????
#--------------------------------------------------------------------------
def minimap_showing?
return $game_system.minimap_show
end
#--------------------------------------------------------------------------
# ? ????????????
#--------------------------------------------------------------------------
def refresh_minimap
return unless SceneManager.scene_is?(Scene_Map)

$game_map.refresh if $game_map.need_refresh
SceneManager.scene.refresh_minimap
end
#--------------------------------------------------------------------------
# ? ???????????????
#--------------------------------------------------------------------------
def update_minimap_object
return unless SceneManager.scene_is?(Scene_Map)

$game_map.refresh if $game_map.need_refresh
SceneManager.scene.update_minimap_object
end
end

#==============================================================================
# ¦ Game_Interpreter
#==============================================================================

class Game_Interpreter
# ?????????????????????????
include KMS_Commands
end

#==============================================================================
# ¦ RPG::Map
#==============================================================================

class RPG::Map
#--------------------------------------------------------------------------
# ? ?????????????
#--------------------------------------------------------------------------
def create_minimap_cache
@__minimap_show = true

note.each_line { |line|
if line =~ KMS_MiniMap::REGEX_NO_MINIMAP_NOTE # ??????
@__minimap_show = false
end
}
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def minimap_show?
create_minimap_cache if @__minimap_show.nil?
return @__minimap_show
end
end

#==============================================================================
# ¦ RPG::MapInfo
#==============================================================================

class RPG::MapInfo
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def name
return @name.gsub(/\[.*\]/) { "" }
end
#--------------------------------------------------------------------------
# ? ???????????
#--------------------------------------------------------------------------
def original_name
return @name
end
#--------------------------------------------------------------------------
# ? ?????????????
#--------------------------------------------------------------------------
def create_minimap_cache
@__minimap_show = !(@name =~ KMS_MiniMap::REGEX_NO_MINIMAP_NAME)
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def minimap_show?
create_minimap_cache if @__minimap_show == nil
return @__minimap_show
end
end

#==============================================================================
# ¦ Game_Temp
#==============================================================================

class Game_Temp
#--------------------------------------------------------------------------
# ? ??????????
#--------------------------------------------------------------------------
attr_accessor :minimap_manual_visible # ????????????????
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
alias initialize_KMS_MiniMap initialize
def initialize
initialize_KMS_MiniMap

@minimap_manual_visible = true
end
end

#==============================================================================
# ¦ Game_System
#==============================================================================

class Game_System
#--------------------------------------------------------------------------
# ? ??????????
#--------------------------------------------------------------------------
attr_accessor :minimap_show # ??????????
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
alias initialize_KMS_MiniMap initialize
def initialize
initialize_KMS_MiniMap

@minimap_show = true
end
end

#==============================================================================
# ¦ Game_Map
#==============================================================================

class Game_Map
#--------------------------------------------------------------------------
# ? ??
#--------------------------------------------------------------------------
MINIMAP_FADE_NONE = 0 # ????? ??????
MINIMAP_FADE_IN = 1 # ????? ??????
MINIMAP_FADE_OUT = 2 # ????? ???????
#--------------------------------------------------------------------------
# ? ??????????
#--------------------------------------------------------------------------
attr_accessor :minimap_fade
#--------------------------------------------------------------------------
# ? ???????????
#--------------------------------------------------------------------------
def minimap_show?
return $data_mapinfos[map_id].minimap_show? && @map.minimap_show?
end
#--------------------------------------------------------------------------
# ? ????????????
#--------------------------------------------------------------------------
def fadein_minimap
@minimap_fade = MINIMAP_FADE_IN
end
#--------------------------------------------------------------------------
# ? ?????????????
#--------------------------------------------------------------------------
def fadeout_minimap
@minimap_fade = MINIMAP_FADE_OUT
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
alias refresh_KMS_MiniMap refresh
def refresh
refresh_KMS_MiniMap

SceneManager.scene.refresh_minimap if SceneManager.scene_is?(Scene_Map)
end
end

#==============================================================================
# ¦ Game_Event
#==============================================================================

class Game_Event < Game_Character
#--------------------------------------------------------------------------
# ? ???????????????
#--------------------------------------------------------------------------
def __create_minimap_cache
@__last_page = @page
@__minimap_wall_event = false
@__minimap_move_event = false
@__minimap_object_type = -1

return if @page.nil?

@page.list.each { |cmd|
# ????????????
break unless [108, 408].include?(cmd.code)

# ??????
case cmd.parameters[0]
when KMS_MiniMap::REGEX_WALL_EVENT
@__minimap_wall_event = true
when KMS_MiniMap::REGEX_MOVE_EVENT
@__minimap_move_event = true
when KMS_MiniMap::REGEX_OBJECT
@__minimap_object_type = $1.to_i
end
}
end
private :__create_minimap_cache
#--------------------------------------------------------------------------
# ? ??????????
#--------------------------------------------------------------------------
def graphic_exist?
return (character_name != "" || tile_id > 0)
end
#--------------------------------------------------------------------------
# ? ????
#--------------------------------------------------------------------------
def is_minimap_wall_event?
if @__minimap_wall_event.nil? || @__last_page != @page
__create_minimap_cache
end

return @__minimap_wall_event
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def is_minimap_move_event?
if @__minimap_move_event.nil? || @__last_page != @page
__create_minimap_cache
end

return @__minimap_move_event
end
#--------------------------------------------------------------------------
# ? ????????????
#--------------------------------------------------------------------------
def is_minimap_object?
if @__minimap_object_type.nil? || @__last_page != @page
__create_minimap_cache
end

return @__minimap_object_type > 0
end
#--------------------------------------------------------------------------
# ? ??????????????
#--------------------------------------------------------------------------
def minimap_object_type
if @__minimap_object_type.nil? || @__last_page != @page
__create_minimap_cache
end

return @__minimap_object_type
end
end

#==============================================================================
# ? Game_MiniMap
#------------------------------------------------------------------------------
# ??????????????
#==============================================================================

class Game_MiniMap
#--------------------------------------------------------------------------
# ? ???
#--------------------------------------------------------------------------
Point = Struct.new(:x, :y)
Size = Struct.new(:width, :height)
PassageCache = Struct.new(:map_id, :table, :scan_table)
#--------------------------------------------------------------------------
# ? ?????
#--------------------------------------------------------------------------
@@passage_cache = [] # ??????????????
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def initialize(tilemap)
@map_rect = KMS_MiniMap::MAP_RECT
@grid_size = [KMS_MiniMap::GRID_SIZE, 1].max

@x = 0
@y = 0
@grid_num = Point.new(
(@map_rect.width + @grid_size - 1) / @grid_size,
(@map_rect.height + @grid_size - 1) / @grid_size
)
@draw_grid_num = Point.new(@grid_num.x + 2, @grid_num.y + 2)
@draw_range_begin = Point.new(0, 0)
@draw_range_end = Point.new(0, 0)
@tilemap = tilemap

@last_x = $game_player.x
@last_y = $game_player.y

@showing = false
@hiding = false

create_sprites
refresh

unless $game_temp.minimap_manual_visible
self.opacity = 0
end
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def create_sprites
@viewport = Viewport.new(@map_rect)
@viewport.z = KMS_MiniMap::MAP_Z

# ???????????
@bmp_size = Size.new(
(@grid_num.x + 2) * @grid_size,
(@grid_num.y + 2) * @grid_size
)
@buf_bitmap = Bitmap.new(@bmp_size.width, @bmp_size.height)

# ???????????
@map_sprite = Sprite.new(@viewport)
@map_sprite.x = -@grid_size
@map_sprite.y = -@grid_size
@map_sprite.z = 0
@map_sprite.bitmap = Bitmap.new(@bmp_size.width, @bmp_size.height)

# ??????????????
@object_sprite = Sprite_MiniMapIcon.new(@viewport)
@object_sprite.x = -@grid_size
@object_sprite.y = -@grid_size
@object_sprite.z = 1
@object_sprite.bitmap = Bitmap.new(@bmp_size.width, @bmp_size.height)

# ???????????
@position_sprite = Sprite_MiniMapIcon.new
@position_sprite.x = @map_rect.x + @grid_num.x / 2 * @grid_size
@position_sprite.y = @map_rect.y + @grid_num.y / 2 * @grid_size
@position_sprite.z = @viewport.z + 2
bitmap = Bitmap.new(@grid_size, @grid_size)
bitmap.fill_rect(bitmap.rect, KMS_MiniMap::POSITION_COLOR)
@position_sprite.bitmap = bitmap
end
#--------------------------------------------------------------------------
# ? ??
#--------------------------------------------------------------------------
def dispose
@buf_bitmap.dispose
@map_sprite.bitmap.dispose
@map_sprite.dispose
@object_sprite.bitmap.dispose
@object_sprite.dispose
@position_sprite.bitmap.dispose
@position_sprite.dispose
@viewport.dispose
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def visible
return @map_sprite.visible
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def visible=(value)
@viewport.visible = value
@map_sprite.visible = value
@object_sprite.visible = value
@position_sprite.visible = value
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def opacity
return @map_sprite.opacity
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def opacity=(value)
@map_sprite.opacity = value
@object_sprite.opacity = value
@position_sprite.opacity = value
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def refresh
update_draw_range
update_passage_table
update_object_list
update_position
draw_map
draw_object
Graphics.frame_reset
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def fadein
@showing = true
@hiding = false
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def fadeout
@showing = false
@hiding = true
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def update_input
return if KMS_MiniMap::SWITCH_BUTTON.nil?

if Input.trigger?(KMS_MiniMap::SWITCH_BUTTON)
if opacity < 255 && !@showing
$game_temp.minimap_manual_visible = true
fadein
elsif opacity > 0 && !@hiding
$game_temp.minimap_manual_visible = false
fadeout
end
end
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def update_draw_range
range = []
(2).times { |i| range[i] = @draw_grid_num[i] / 2 }

@draw_range_begin.x = $game_player.x - range[0]
@draw_range_begin.y = $game_player.y - range[1]
@draw_range_end.x = $game_player.x + range[0]
@draw_range_end.y = $game_player.y + range[1]
end
#--------------------------------------------------------------------------
# ? ??????????
#--------------------------------------------------------------------------
def update_passage_table
cache = get_passage_table_cache
@passage_table = cache.table
@passage_scan_table = cache.scan_table

update_around_passage_table
end
#--------------------------------------------------------------------------
# ? ?????????????????
#--------------------------------------------------------------------------
def get_passage_table_cache
map_id = $game_map.map_id
cache = @@passage_cache.find { |c| c.map_id == map_id }

# ??????????????
if cache == nil
cache = PassageCache.new(map_id)
cache.table = Table.new($game_map.width, $game_map.height)
cache.scan_table = Table.new(
($game_map.width + @draw_grid_num.x - 1) / @draw_grid_num.x,
($game_map.height + @draw_grid_num.y - 1) / @draw_grid_num.y
)
end

# ??????????????????????????
@@passage_cache.unshift(cache)
@@passage_cache.delete_at(KMS_MiniMap::CACHE_NUM)

return cache
end
#--------------------------------------------------------------------------
# ? ??????????????????
#--------------------------------------------------------------------------
def clear_passage_table_cache
return if @passage_scan_table == nil

table = @passage_scan_table
@passage_scan_table = Table.new(table.xsize, table.ysize)
end
#--------------------------------------------------------------------------
# ? ???????????
# x, y : ????
#--------------------------------------------------------------------------
def scan_passage(x, y)
dx = x / @draw_grid_num.x
dy = y / @draw_grid_num.y

# ????
return if @passage_scan_table[dx, dy] == 1

# ??????
return unless dx.between?(0, @passage_scan_table.xsize - 1)
return unless dy.between?(0, @passage_scan_table.ysize - 1)

rx = (dx * @draw_grid_num.x)...((dx + 1) * @draw_grid_num.x)
ry = (dy * @draw_grid_num.y)...((dy + 1) * @draw_grid_num.y)
mw = $game_map.width - 1
mh = $game_map.height - 1

# ???????????????
rx.each { |x|
next unless x.between?(0, mw)
ry.each { |y|
next unless y.between?(0, mh)

# ?????????
# (??????? ??? 1, 2, 4, 8 ???)
flag = 0
[2, 4, 6, 8].each{ |d|
flag |= 1 << (d / 2 - 1) if $game_map.passable?(x, y, d)
}
@passage_table[x, y] = flag
}
}
@passage_scan_table[dx, dy] = 1
end
#--------------------------------------------------------------------------
# ? ?????????????
#--------------------------------------------------------------------------
def update_around_passage_table
gx = @draw_grid_num.x
gy = @draw_grid_num.y
dx = $game_player.x - gx / 2
dy = $game_player.y - gy / 2
scan_passage(dx, dy)
scan_passage(dx + gx, dy)
scan_passage(dx, dy + gy)
scan_passage(dx + gx, dy + gy)
end
#--------------------------------------------------------------------------
# ? ??????????
#--------------------------------------------------------------------------
def update_object_list
events = $game_map.events.values

# WALL
@wall_events = events.find_all { |e| e.is_minimap_wall_event? }

# MOVE
@move_events = events.find_all { |e| e.is_minimap_move_event? }

# OBJ
@object_list = events.find_all { |e| e.is_minimap_object? }
end
#--------------------------------------------------------------------------
# ? ????
#--------------------------------------------------------------------------
def update_position
# ?????
pt = Point.new($game_player.x, $game_player.y)
ox = ($game_player.real_x - pt.x) * @grid_size
oy = ($game_player.real_y - pt.y) * @grid_size

@viewport.ox = ox
@viewport.oy = oy

# ?????????????
if pt.x != @last_x || pt.y != @last_y
draw_map
@last_x = pt.x
@last_y = pt.y
end
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def in_draw_range?(x, y)
rb = @draw_range_begin
re = @draw_range_end
return (x.between?(rb.x, re.x) && y.between?(rb.y, re.y))
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def in_map_range?(x, y)
mw = $game_map.width
mh = $game_map.height
return (x.between?(0, mw - 1) && y.between?(0, mh - 1))
end
#--------------------------------------------------------------------------
# ? ?????
#--------------------------------------------------------------------------
def draw_map
update_around_passage_table

bitmap = @map_sprite.bitmap
bitmap.fill_rect(bitmap.rect, KMS_MiniMap::BACKGROUND_COLOR)

draw_map_foreground(bitmap)
draw_map_move_event(bitmap)
end
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def draw_map_foreground(bitmap)
range_x = (@draw_range_begin.x)..(@draw_range_end.x)
range_y = (@draw_range_begin.y)..(@draw_range_end.y)
map_w = $game_map.width - 1
map_h = $game_map.height - 1
rect = Rect.new(0, 0, @grid_size, @grid_size)

range_x.each { |x|
next unless x.between?(0, map_w)
range_y.each { |y|
next unless y.between?(0, map_h)
next if @passage_table[x, y] == 0
next if @wall_events.find { |e| e.x == x && e.y == y } # ?

# ???????????
rect.set(0, 0, @grid_size, @grid_size)
rect.x = (x - @draw_range_begin.x) * @grid_size
rect.y = (y - @draw_range_begin.y) * @grid_size
flag = @passage_table[x, y]
if flag & 0x01 == 0 # ?????
rect.height -= 1
end
if flag & 0x02 == 0 # ?????
rect.x += 1
rect.width -= 1
end
if flag & 0x04 == 0 # ?????
rect.width -= 1
end
if flag & 0x08 == 0 # ?????
rect.y += 1
rect.height -= 1
end
bitmap.fill_rect(rect, KMS_MiniMap::FOREGROUND_COLOR)
}
}
end
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def draw_map_move_event(bitmap)
rect = Rect.new(0, 0, @grid_size, @grid_size)
@move_events.each { |e|
rect.x = (e.x - @draw_range_begin.x) * @grid_size
rect.y = (e.y - @draw_range_begin.y) * @grid_size
bitmap.fill_rect(rect, KMS_MiniMap::MOVE_EVENT_COLOR)
}
end
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
def update_animation
if @showing
# ??????
self.opacity += 16
if opacity == 255
@showing = false
end
elsif @hiding
# ???????
self.opacity -= 16
if opacity == 0
@hiding = false
end
end
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def draw_object
# ???
bitmap = @object_sprite.bitmap
bitmap.clear
rect = Rect.new(0, 0, @grid_size, @grid_size)

# ????????
@object_list.each { |obj|
next unless in_draw_range?(obj.x, obj.y)

color = KMS_MiniMap::OBJECT_COLOR[obj.minimap_object_type - 1]
next if color.nil?

rect.x = (obj.real_x - @draw_range_begin.x) * @grid_size
rect.y = (obj.real_y - @draw_range_begin.y) * @grid_size
bitmap.fill_rect(rect, color)
}

# ?????
$game_map.vehicles.each { |vehicle|
next if vehicle.transparent

rect.x = (vehicle.real_x - @draw_range_begin.x) * @grid_size
rect.y = (vehicle.real_y - @draw_range_begin.y) * @grid_size
bitmap.fill_rect(rect, KMS_MiniMap::VEHICLE_COLOR)
}
end
#--------------------------------------------------------------------------
# ? ??
#--------------------------------------------------------------------------
def update
update_input

return unless need_update?

update_draw_range
update_position
update_animation
draw_object

@map_sprite.update
@object_sprite.update
@position_sprite.update
end
#--------------------------------------------------------------------------
# ? ????
#--------------------------------------------------------------------------
def need_update?
return (visible && opacity > 0) || @showing || @hiding
end
end

#==============================================================================
# ? Sprite_MiniMapIcon
#------------------------------------------------------------------------------
# ?????????????????
#==============================================================================

class Sprite_MiniMapIcon < Sprite
DURATION_MAX = 60
#--------------------------------------------------------------------------
# ? ?????????
# viewport : ??????
#--------------------------------------------------------------------------
def initialize(viewport = nil)
super(viewport)
@duration = DURATION_MAX / 2
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
def update
super
@duration += 1
if @duration == DURATION_MAX
@duration = 0
end
update_effect
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def update_effect
self.color.set(255, 255, 255,
(@duration - DURATION_MAX / 2).abs * KMS_MiniMap::BLINK_LEVEL
)
end
end

#==============================================================================
# ¦ Spriteset_Map
#==============================================================================

class Spriteset_Map
attr_reader :minimap
#--------------------------------------------------------------------------
# ? ?????????
#--------------------------------------------------------------------------
alias initialize_KMS_MiniMap initialize
def initialize
initialize_KMS_MiniMap

create_minimap
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def create_minimap
@minimap = Game_MiniMap.new(@tilemap)
@minimap.visible = $game_system.minimap_show && $game_map.minimap_show?
end
#--------------------------------------------------------------------------
# ? ??
#--------------------------------------------------------------------------
alias dispose_KMS_MiniMap dispose
def dispose
dispose_KMS_MiniMap

dispose_minimap
end
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
def dispose_minimap
@minimap.dispose
@minimap = nil
end
#--------------------------------------------------------------------------
# ? ??????
#--------------------------------------------------------------------------
alias update_KMS_MiniMap update
def update
update_KMS_MiniMap

update_minimap
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def minimap_show?
return $game_map.minimap_show? && $game_system.minimap_show
end
#--------------------------------------------------------------------------
# ? ???????
#--------------------------------------------------------------------------
def update_minimap
return if @minimap.nil?

# ????
if minimap_show?
@minimap.visible = true
else
@minimap.visible = false
return
end

# ??????
case $game_map.minimap_fade
when Game_Map::MINIMAP_FADE_IN
@minimap.fadein
$game_map.minimap_fade = Game_Map::MINIMAP_FADE_NONE
when Game_Map::MINIMAP_FADE_OUT
@minimap.fadeout
$game_map.minimap_fade = Game_Map::MINIMAP_FADE_NONE
end

@minimap.update
end
#--------------------------------------------------------------------------
# ? ??????????????
#--------------------------------------------------------------------------
def refresh_minimap
return if @minimap.nil?

@minimap.clear_passage_table_cache
@minimap.refresh
end
#--------------------------------------------------------------------------
# ? ???????????????
#--------------------------------------------------------------------------
def update_minimap_object
@minimap.update_object_list unless @minimap.nil?
end
end

#==============================================================================
# ¦ Scene_Map
#==============================================================================

class Scene_Map
#--------------------------------------------------------------------------
# ? ????????
#--------------------------------------------------------------------------
alias post_transfer_KMS_MiniMap post_transfer
def post_transfer
refresh_minimap

post_transfer_KMS_MiniMap
end
#--------------------------------------------------------------------------
# ? ??????????????
#--------------------------------------------------------------------------
def refresh_minimap
@spriteset.refresh_minimap unless @spriteset.nil?
end
#--------------------------------------------------------------------------
# ? ???????????????
#--------------------------------------------------------------------------
def update_minimap_object
@spriteset.update_minimap_object unless @spriteset.nil?
end
end

Uso: Copiar en una nueva página en la parte "Personalizados" de los scripts. Durante el juego se puede desactivar / activar con la tecla D.

Si no funciona bien, se debe instalar un nuevo script de compatibilidad con el siguiente código:

#==============================================================================
# Compatibility Patch :                                         v1.1 (7/19/12)
#   Victor Engine - Pixel Movement + KMS Minimap
#   Sapphire Action System IV + KMS Minimap
#--------------------------------------------------------------------------
# Script by:
#     Mr. Bubble
#--------------------------------------------------------------------------
# Place this script below KMS Mini Map in your script edtior.
#==============================================================================

class Game_MiniMap
  #--------------------------------------------------------------------------
  # ○ 通行可否テーブルの探索
  #     x, y : 探索位置
  #--------------------------------------------------------------------------
  def scan_passage(x, y)
    dx = x / @draw_grid_num.x
    dy = y / @draw_grid_num.y

    # 探索済み
    return if @passage_scan_table[dx, dy] == 1

    # マップ範囲外
    return unless dx.between?(0, @passage_scan_table.xsize - 1)
    return unless dy.between?(0, @passage_scan_table.ysize - 1)

    rx = (dx.to_i * @draw_grid_num.x.to_i)...((dx.to_i + 1) * @draw_grid_num.x.to_i)
    ry = (dy.to_i * @draw_grid_num.y.to_i)...((dy.to_i + 1) * @draw_grid_num.y.to_i)
    mw = $game_map.width  - 1
    mh = $game_map.height - 1

    # 探索範囲内の通行テーブルを生成
    rx.each { |x|
      next unless x.between?(0, mw)
      ry.each { |y|
        next unless y.between?(0, mh)

        # 通行方向フラグ作成
        # (↓、←、→、↑ の順に 1, 2, 4, 8 が対応)
        flag = 0
        [2, 4, 6, 8].each{ |d|
          flag |= 1 << (d / 2 - 1) if $game_map.passable?(x, y, d)
        }
        @passage_table[x, y] = flag
      }
    }
    @passage_scan_table[dx, dy] = 1
  end
  #--------------------------------------------------------------------------
  # ○ 通行可能領域の描画
  #--------------------------------------------------------------------------
  def draw_map_foreground(bitmap)
    range_x = (@draw_range_begin.x.to_i)..(@draw_range_end.x.to_i)
    range_y = (@draw_range_begin.y.to_i)..(@draw_range_end.y.to_i)
    map_w   = $game_map.width  - 1
    map_h   = $game_map.height - 1
    rect    = Rect.new(0, 0, @grid_size, @grid_size)
    
    range_x.each { |x|
      next unless x.between?(0, map_w)
      range_y.each { |y|

        next unless y.between?(0, map_h)
        next if @passage_table[x, y] == 0
        next if @wall_events.find { |e| e.x == x && e.y == y }  # 壁
        # グリッド描画サイズ算出
        rect.set(0, 0, @grid_size, @grid_size)
        rect.x = (x - @draw_range_begin.x) * @grid_size
        rect.y = (y - @draw_range_begin.y) * @grid_size
        flag = @passage_table[x, y]
        if flag & 0x01 == 0  # 下通行不能
          rect.height -= 1
        end
        if flag & 0x02 == 0  # 左通行不能
          rect.x     += 1
          rect.width -= 1
        end
        if flag & 0x04 == 0  # 右通行不能
          rect.width -= 1
        end
        if flag & 0x08 == 0  # 上通行不能
          rect.y      += 1
          rect.height -= 1
        end
        bitmap.fill_rect(rect, KMS_MiniMap::FOREGROUND_COLOR)
      }
    }
  end # def
end # class

lunes, 28 de junio de 2010

Twine

Nombre: Twine

Estado: versión 2.2.1 (Totalmente operativa)

Géneros que crea: Historias interactivas. Historias del estilo "Elige tu propia aventura" con un texto que te da diversas opciones que seguir.

Facilidad: Para todo el mundo. Especialmente sencillo para aquellos acostumbrados a los lenguajes de script o la programación HTML. En cualquier caso, cualquiera puede aprenderlo rápidamente y conseguir buenos resultados en poco tiempo.

Página web: http://twinery.org/
           
Desarrollo: De una forma visual se van creando los distintos "pasajes" que tendrá nuestra historia en forma de recuadros y que corresponden con situaciones o directamente con habitaciones de nuestro juego. Cada pasaje tiene un nombre y una descripción. En el nombre podremos definir en qué pasaje se iniciará el juego, en cual terminará y nos servirá para enlazarlos cuando escribamos el código. Cuando se pincha dos veces sobre el recuadro de un pasaje, se abre una nueva ventana donde podemos modificar el nombre, la descripción y podemos añadir tags.

Ejemplo:
Habitación
Estás en una habitación oscura donde los gatos son "pardos".
[[Encender la luz|luceson]]
[[Temblar|miedo]]

.Habitación: es el nombre del pasaje.
. Estás en una habitación oscura donde los gatos son "pardos".: es lo que el usuario leerá al cargarse el pasaje.
. "pardos": si una palabra está entre comillas, aparecerá en negrita en pantalla.
.  [[Encender la luz|luceson]]: es una de las opciones que el usuario podrá escoger. "Encender la luz" es lo que el usuario leerá en pantalla y "luceson" el nombre del pasaje al que saltará si pincha sobre dicha acción".


Comentarios: Usando las etiquetas HTML se pueden incluir imágenes y todo tipo de efectos. Soporta el uso de hojas de estilo, variables con las que "recordar" decisiones y macros.

Recursos:

Twine. Una aproximación al desarrollo de literatura interactiva: libro editado por Backside Games donde se detalla de forma sencilla el manejo de la herramienta en su versión 1.x.

Twine Cookbook: manual en línea con toda la documentación sobre la herramienta así como un listado de código que usar en nuestros juegos.

Harlowe Manual: manual de tres versiones de este estilo para los juegos.

Twine wiki: información tanto sobre Twine 1 como 2.

Juegos desarrollados con la herramienta:

. Twine Pong
. Roll the dice

 


Creando una simple historia con Twine de Chris Klimas

domingo, 6 de junio de 2010

[RPGMACE]: Añadir imágenes antes del título


Función: Script para colocar imágenes antes de la pantalla de título.

Código:

#==============================================================================
# Imagen de intro para el RPG Maker VX
# Creado por: Dark_ Buster_XYZ
# Version: alpha 1.0
# Visita: http://mundodeluxe.mforos.com/
#------------------------------------------------------------------------------
# Este scrip te permite agregar una imagen de intro, como un logo por ejemplo
# La imagen se debe ser de 544 x 416 y la debes guardar en la caperta
#
# Graphics/System/"tu imagen"
#
# solo debes cambiar en configuracion, el nombre de tu imagen,
# cuanto duran las transisiones y cuando dura el logo en pantalla
# NOTA: Este scrip es acumulable, osea que puedes poner varios logos
#==============================================================================

class Intro

#==============================================================================
# Configuracion
#==============================================================================

#nombre de tu imagen
name = "logo"
# Tiempo que dura la transicion
trans = 50
# tiempo que dura el logo en pantalla
tempo = 100

#==============================================================================
# Rutina de Intro
#==============================================================================


@intro = Sprite.new
@intro.bitmap = Cache.system(name)

@intro.opacity = 0

Graphics.freeze
@intro.opacity = 255
Graphics.transition(trans)

Graphics.freeze
Graphics.transition(tempo)

Graphics.freeze
@intro.opacity = 0
Graphics.transition(trans)

@intro.dispose
end

Utilización: Se copia el script en la categoría de Scripts "Personalizado". Tendremos que cambiar la linea "name = logo". En lugar de "logo" deberemos poner el nombre de nuestra imagen, que deberemos importar con el gestor de archivos, para colocarla en el directorio "Graphics/System"

Creador: Dark_Buster_XYZ

Backside Games Studios

Backside Games Studios © 2014 - Designed by Templateism.com, Plugins By MyBloggerLab.com | Published By Gooyaabi Templates