Una pequeña muestra del estado de desarrollo actual de la actualización gráfica de EXcripting que ya permite crear sencillos juegos a partir de rectángulos, como en este caso que construyo un pong de un jugador en unos 30 minutos.
03 marzo, 2018
19 septiembre, 2017
10 marzo, 2017
EXcripting alpha 1 disponible
EXcripting es una herramienta sencilla de programación que en lugar de líneas de código de texto se compone a través de diagramas lógicos, de una manera gráfica e intuitiva. Permite a cualquier usuario, principiante o avanzado automatizar acciones como son llamadas a cmd, peticiones web, operaciones aritméticas o análisis de texto.
Es muy sencillo de utilizar y ofrece muchas posibilidades a pesar de su velocidad lenta y su fase temprana de desarrollo. El control de errores es casi inexistente, así que el software puede entrar en estado de inestabilidad si introducimos datos del tipo incorrecto en una operación. Incluyo documentación detallada y proyectos de ejemplo para reducir las posibilidades de que esto pase.
Se trata de un proyecto personal, permito su uso y redistribución siempre que sea sin ánimo de lucro y no sea modificado ningún elemento a excepción de los proyectos de ejemplo. Ésto significa que puedes crear un script en concreto y compartir EXcripting con él siempre que se incluya el software y la documentación tal y como los encontrarás en el archivo original.
DESCARGA
Es muy sencillo de utilizar y ofrece muchas posibilidades a pesar de su velocidad lenta y su fase temprana de desarrollo. El control de errores es casi inexistente, así que el software puede entrar en estado de inestabilidad si introducimos datos del tipo incorrecto en una operación. Incluyo documentación detallada y proyectos de ejemplo para reducir las posibilidades de que esto pase.
Se trata de un proyecto personal, permito su uso y redistribución siempre que sea sin ánimo de lucro y no sea modificado ningún elemento a excepción de los proyectos de ejemplo. Ésto significa que puedes crear un script en concreto y compartir EXcripting con él siempre que se incluya el software y la documentación tal y como los encontrarás en el archivo original.
DESCARGA
21 agosto, 2016
RGBY
RGBY es el nombre del juego de plataformas y puzzles que estoy desarrollando sobre unity. Lo más importante de todo esto es el sistema de scripts que estoy creando con un diseño modular para ser reutilizado en un futuro y que me va a ahorrar mucho trabajo. Un objeto controla la mayor parte de los comportamientos de los demás, botones, interruptores, temporizadores y sensores genéricos permiten activar o desactivar elementos del juego. La idea consiste en crear un juego donde se deba interactuar con el entorno para avanzar. Un sistema de juego sencillo con el cual diseñar puzzles complicados.
El nombre viene de las iniciales de los tres colores primarios y el amarillo (en inglés) que son los utilizados por los elementos principales del juego. Los colores nos indicarán usualmente el tipo de llave necesaria para activar los diversos objetos que nos abrirán el camino.
El nombre viene de las iniciales de los tres colores primarios y el amarillo (en inglés) que son los utilizados por los elementos principales del juego. Los colores nos indicarán usualmente el tipo de llave necesaria para activar los diversos objetos que nos abrirán el camino.
15 marzo, 2016
Ejemplos básicos de EXcripting
Estos son algunos ejemplos del uso de excripting dirigidos al control del flujo y de entrada/salida o a la comprensión del comportamiento de los bloques más que a una aplicación práctica.
Este circuito es un sumador de 2bits + 2bits que da como resultado 3 bits. Está construido usando solamente puertas lógicas, al método tradicional. para añadir más bits sólo tengo que añadir más semisumadores y conectarlos al acarreo correspondiente. Todo va conectado a un visor bcd de cuatro patillas que vendrá con la nueva versión.
Pero excripting no sólo es un simulador de diagramas lógicos, sino que además dispone de la habilidad de manejar variables y operar con ellas, así que ¿por qué no símplemente transformar a variable cada cifra para operar con ellas? Los bloques bin2int permiten codificar en una variable una cifra de cuatro bits pudiendo recuperar sus bits posteriormente con int2bin. Un ejemplo de la combinación de diagramas lógicos y scripting.
Otro ejemplo claro en donde uso comparación de variables para limitar por arriba y por abajo una cifra que podemos cambiar con dos pulsadores.
Esto otro es un poco más extraño, pero me parece un buen ejemplo de cómo unos elementos se pueden combinar con otros de maneras inesperadas. En este caso para conseguir generar un número más o menos aleatorio combinando varios ciclos que cambian constantemente varias cifras.
Descarga excripting aquí:
Descarga excripting aquí:
12 marzo, 2016
Excripting: scripting like a pro
Quería en mi próximo post hablar sobre Isographx, el engine isométrico en el que ya llevo un tiempo trabajando, pero sólo puede trabajar con cubos y aunque interesante resulta tosco aún. Además hay momentos en que una idea resulta tan evidente, auto coherente y sencilla que eclipsa todo lo demás en lo que puedas estar pensando. Es lo que ha ocurrido con Excripting (ex por experimental) un programa que me cuesta trabajo definir o catalogar.
El caso es que llevo tiempo pensando en hacer algo relacionado con la programación visual, no en el sentido de que el resultado sea visual sino en el de que se interactúe con una serie de elementos gráficos para construir los comportamientos. He usado Appinventor del Mit y usa un sistema de bloques muy interesante e intuitivo de construir lo que en la práctica es un código escrito al uso. Éste sistema de bloques se usa también en blockly así como otros programas por el estilo. Y la idea es muy buena, pero hacer lo mismo no es lo que yo buscaba.
Supongo que fue una combinación de ideas, por un lado de pequeño cuando no teníamos youtube para pasar el rato recuerdo que pasaba horas en electronic workbench haciendo circuitos y abriendo ejemplos para destrozarlos, y aunque es lo que es, un simulador de electrónica, era muy divertido. No se mucho de electrónica, así que a veces era decepcionante. Por otro lado está la idea del inocente "redstone" de minecraft. No soy ningún tipo de fanático de este juego, pero esta serie de elementos del juego diría que tienen hasta valor didáctico. Lo interesante de un circuito de redstone es que no hay un index o cabezal lector que ejecuta línea tras línea lo que el código dice, sino que cada uno de los componentes de un circuito funcionan independientemente "haciendo" algo muy sencillo cuando recibe "true" por su entrada. Y es turing computable, obviamente, incluso hay gente que ha diseñado ordenadores con esa cosa.
Excripting toma esa idea de pequeños elementos, con pequeñas funciones independientes conectados entre sí. Dispone de las puertas lógicas más comunes, visores, botones etc y bloques para crear y editar variables así como (por ahora) para ejecutar comandos de consola. Éstos bloques disponen de entradas y salidas que se cablean entre ellas siempre desde una salida hasta una entrada. Desde el primer momento tenía en mente que usar gráficos no sólo es poner degradados y fondos, sino que deben de ser parte útil de la herramienta. Debía usar códigos de colores y diagramas sencillos e intuitivos. Por otro lado, el espacio 2d sólo existe cara al usuario, es decir, podría procesarse un script sin la información de las posiciones de los bloques, porque no importa. Por otro lado cada bloque dispone de la capacidad de contener texto, el cual en ocasiones es usado por la lógica del propio bloque a modo de parámetros. Las entradas SIEMPRE se dibujan abajo y las salidas arriba del bloque, aquí hay dos factores contrapuestos, por un lado hacer visualmente rica la representación y por otro hacerlo visualmente claro y autocognitivo y he optado por la segunda. los cables se cruzan y puede parecer confuso a veces, pero no lo veo un problema. Editar es muy sencillo, se mueve un bloque con el botón secundario del ratón, con el primario se pulsan los botones o interruptores y shift+click en un bloque permite editar su valor de texto.
Mientras funciona el script un valor true será representado con el color verde así que se ve en todo momento el mecanismo en funcionamiento, otra de las cosas que me gustó del redstone. El control de errores es casi inexistente, y esto es así porque creo que una sintaxis poco estricta permitirá a otros hacer cosas que ni me imagino.
Todo esto lo he hecho en menos de dos semanas, no porque yo sea especialmente rápido, sino porque la idea era tan sencilla y elegante que el código se escribe sólo. Voy a compartir una versión prototipo con la esperanza de que quienes lo probéis me contactéis por la red social google+ o por los comentarios de este blog y me digáis que más bloques añadiríais a la lista o que problemas o dudas os surgen. Y no os cortéis en compartirme un snapshoot o lo que sea si hacéis un circuito interesante.
| excripting |
![]() |
| ejemplo de blockly |
| en este ejemplo el al pulsar el botón el led A lucirá tres veces y después el B una. |
Excripting toma esa idea de pequeños elementos, con pequeñas funciones independientes conectados entre sí. Dispone de las puertas lógicas más comunes, visores, botones etc y bloques para crear y editar variables así como (por ahora) para ejecutar comandos de consola. Éstos bloques disponen de entradas y salidas que se cablean entre ellas siempre desde una salida hasta una entrada. Desde el primer momento tenía en mente que usar gráficos no sólo es poner degradados y fondos, sino que deben de ser parte útil de la herramienta. Debía usar códigos de colores y diagramas sencillos e intuitivos. Por otro lado, el espacio 2d sólo existe cara al usuario, es decir, podría procesarse un script sin la información de las posiciones de los bloques, porque no importa. Por otro lado cada bloque dispone de la capacidad de contener texto, el cual en ocasiones es usado por la lógica del propio bloque a modo de parámetros. Las entradas SIEMPRE se dibujan abajo y las salidas arriba del bloque, aquí hay dos factores contrapuestos, por un lado hacer visualmente rica la representación y por otro hacerlo visualmente claro y autocognitivo y he optado por la segunda. los cables se cruzan y puede parecer confuso a veces, pero no lo veo un problema. Editar es muy sencillo, se mueve un bloque con el botón secundario del ratón, con el primario se pulsan los botones o interruptores y shift+click en un bloque permite editar su valor de texto.
Mientras funciona el script un valor true será representado con el color verde así que se ve en todo momento el mecanismo en funcionamiento, otra de las cosas que me gustó del redstone. El control de errores es casi inexistente, y esto es así porque creo que una sintaxis poco estricta permitirá a otros hacer cosas que ni me imagino.
Todo esto lo he hecho en menos de dos semanas, no porque yo sea especialmente rápido, sino porque la idea era tan sencilla y elegante que el código se escribe sólo. Voy a compartir una versión prototipo con la esperanza de que quienes lo probéis me contactéis por la red social google+ o por los comentarios de este blog y me digáis que más bloques añadiríais a la lista o que problemas o dudas os surgen. Y no os cortéis en compartirme un snapshoot o lo que sea si hacéis un circuito interesante.
10 noviembre, 2015
Sobre los gráficos 2D que uso en mi engine (y de porqué cada vez que publico una foto parece un juego diferente)
Mientras dura el desarrollo de Living paper source debo ir probando sus capacidades y correcto funcionamiento, para ello cargo una serie de gráficos, items y scripts y creo con ello mapas y actores, lo que viene a ser un juego de prueba. Al principio todos los gráficos que usaba venían de internet y en mayor parte de recursos gratuítos para plataformas como rpgmaker o alter engine, pero con el tiempo me cansé de que los gráficos se parecieran tanto a todo lo hecho sobre estas plataformas.
Por otro lado las primeras versiones del engine eran muy limitadas y estaban muy mal optimizadas, por lo que los gráficos eran menos y más pequeños, mientras el proyecto crece necesitaba gráficos más grandes, podía por ejemplo juntar cuatro o cinco árboles en un mismo bitmap, darle solidez y usarlo para abarcar más espacio, por ejemplo.
Y de tanto editar y retocar cosas un día decido probar con actores más grandes (hasta entonces eran de 32x32), en concreto más altos. Encontré en internet muchos modelos, pero lo cierto es que ninguno se parecía a lo que buscaba, todos eran bastante clónicos así que decidí hacerlos a mano. Fue un trabajo mucho más pesado de lo que pensaba, aún con modelos de 64x128 crear animaciones creíbles es más que un arte. Diseñé "herobase" (a continuación) y a partir de él varios avatares clónicos.
Éstos avatares funcionan muy bien con capas y por aquel entonces el engine disponía por primera vez de un sistema de paperdoll muy sencillo. De todas maneras aún debería crear un avatar femenino, versiones infantiles etc con todas sus animaciones, y viendo cuanto me había costado crear un actor decidí centrarme en hacer escenografía a mano. Al principio reutilizando muchas imágenes libres, combinándolas y editándolas pero poco a poco metiendo más de mi mano acabé creando las últimas cabañas de chapa básicamente desde cero.
A esta altura había comenzado ya con la que hasta ahora es la última ramificación del proyecto, la versión tw hires que dispone de más resolución y admite pantalla completa, es la más rápida dibujando y por eso cada vez incluía sprites más grandes, lo cual incide positivamente en la apariencia del juego. Cada vez tenía algo más parecido a Fallout2 o Comandos y menos a zelda. Tenía decidido que no quiero hacer gráficos típicos medievaloides en parte porque mi engine está muy relaccionado con la lucha a distancia lo que lo hace más dado a un juego de "pistolas" que a uno de "espadas". Por otro lado no puedo diseñar una ciudad con tráfico complejo, ni un sistema de conducción de vehiculos decente, lo que me llevó a la idea del "postapocalipsis". Pensé en los zombies, y no he dejado la idea de lado, pero al fin y al cabo por ahora este juego no es más que una simulación para testear por lo que no sigo una línea clara.
Pensando en lo que podría hacer con mi servidor opensim me pasó este proyecto por la cabeza y de alguna manera los conceptos colisionaron. Puesto que opensim es una plataforma de realidad virtual podría simular escenario con fondo azul o magenta para tomar fotografías y extraer las imágenes usando la técnica del croma key. Hice un pequeño script para animar al personaje, otro para rotarlo 90 grados cuando yo decido y uno más para fijar la cámara del visor en la misma posición siempre. De esta forma es muy sencillo crear un personaje, primero hago cada pose de una animación en stopmotion, usando Qavimator, un programa muy sencillo de usar. Luego edito la apariencia de mi propio avatar en opensim para ajustarla al personaje deseado, por último me coloco en la plataforma, la cámara se ajusta y puedo empezar a tomar fotografías, un click rota el avatar. Para una animación de movimiento necesito 16 imágenes, pero usando este método la mayor parte del trabajo se reduce a separar el fondo del personaje y ajustar su tamaño.
Y con esto si que me sorprendí yo mismo, el resultado es muy bueno y el trabajo requerido había casi desaparecido. Durante un tiempo esto me permitió crear más escenografía a mano, pero desde hace poco he comenzado con el siguiente paso que consiste en renderizar edificios, árboles, murallas, rocas etc para igualar el acabado de los actores con los de los escenarios. Al principio tenía el problema de la perspectiva, mi engine usa top-down y cualquier cosa con punto de fuga queda extraña, pero descubrí una opción para abrir o cerrar el campo de visión en opensim, y cerrado del todo queda una perspectiva frontal perfecta. También he explotado más la idea de usar sprites grandes en el escenario, puesto que queda mejor si renderizo todo junto, con el mismo foco de luz.
Aquí algunos ejemplos de los gráficos que estoy preparando.
Y esto no se ha acabado, pero por fin creo que tengo una herramienta con la que puedo hacer animaciones desde diferentes puntos de vista con una perspectiva correcta sin dejarme la piel en ello y puedo dedicar más tiempo al código. Sobre si esto se terminará transformando en un juego, estaba pensado que no, pero cada vez dispongo de más material satisfactorio y la verdad es que la idea me gusta, pero solo lo haré si consigo implementar ciertas ideas que resultarían en un gameplay que tienda más al puzzle y el rol narrativo.
Por otro lado las primeras versiones del engine eran muy limitadas y estaban muy mal optimizadas, por lo que los gráficos eran menos y más pequeños, mientras el proyecto crece necesitaba gráficos más grandes, podía por ejemplo juntar cuatro o cinco árboles en un mismo bitmap, darle solidez y usarlo para abarcar más espacio, por ejemplo.
Y de tanto editar y retocar cosas un día decido probar con actores más grandes (hasta entonces eran de 32x32), en concreto más altos. Encontré en internet muchos modelos, pero lo cierto es que ninguno se parecía a lo que buscaba, todos eran bastante clónicos así que decidí hacerlos a mano. Fue un trabajo mucho más pesado de lo que pensaba, aún con modelos de 64x128 crear animaciones creíbles es más que un arte. Diseñé "herobase" (a continuación) y a partir de él varios avatares clónicos.
Éstos avatares funcionan muy bien con capas y por aquel entonces el engine disponía por primera vez de un sistema de paperdoll muy sencillo. De todas maneras aún debería crear un avatar femenino, versiones infantiles etc con todas sus animaciones, y viendo cuanto me había costado crear un actor decidí centrarme en hacer escenografía a mano. Al principio reutilizando muchas imágenes libres, combinándolas y editándolas pero poco a poco metiendo más de mi mano acabé creando las últimas cabañas de chapa básicamente desde cero.
A esta altura había comenzado ya con la que hasta ahora es la última ramificación del proyecto, la versión tw hires que dispone de más resolución y admite pantalla completa, es la más rápida dibujando y por eso cada vez incluía sprites más grandes, lo cual incide positivamente en la apariencia del juego. Cada vez tenía algo más parecido a Fallout2 o Comandos y menos a zelda. Tenía decidido que no quiero hacer gráficos típicos medievaloides en parte porque mi engine está muy relaccionado con la lucha a distancia lo que lo hace más dado a un juego de "pistolas" que a uno de "espadas". Por otro lado no puedo diseñar una ciudad con tráfico complejo, ni un sistema de conducción de vehiculos decente, lo que me llevó a la idea del "postapocalipsis". Pensé en los zombies, y no he dejado la idea de lado, pero al fin y al cabo por ahora este juego no es más que una simulación para testear por lo que no sigo una línea clara.
Pensando en lo que podría hacer con mi servidor opensim me pasó este proyecto por la cabeza y de alguna manera los conceptos colisionaron. Puesto que opensim es una plataforma de realidad virtual podría simular escenario con fondo azul o magenta para tomar fotografías y extraer las imágenes usando la técnica del croma key. Hice un pequeño script para animar al personaje, otro para rotarlo 90 grados cuando yo decido y uno más para fijar la cámara del visor en la misma posición siempre. De esta forma es muy sencillo crear un personaje, primero hago cada pose de una animación en stopmotion, usando Qavimator, un programa muy sencillo de usar. Luego edito la apariencia de mi propio avatar en opensim para ajustarla al personaje deseado, por último me coloco en la plataforma, la cámara se ajusta y puedo empezar a tomar fotografías, un click rota el avatar. Para una animación de movimiento necesito 16 imágenes, pero usando este método la mayor parte del trabajo se reduce a separar el fondo del personaje y ajustar su tamaño.
Y con esto si que me sorprendí yo mismo, el resultado es muy bueno y el trabajo requerido había casi desaparecido. Durante un tiempo esto me permitió crear más escenografía a mano, pero desde hace poco he comenzado con el siguiente paso que consiste en renderizar edificios, árboles, murallas, rocas etc para igualar el acabado de los actores con los de los escenarios. Al principio tenía el problema de la perspectiva, mi engine usa top-down y cualquier cosa con punto de fuga queda extraña, pero descubrí una opción para abrir o cerrar el campo de visión en opensim, y cerrado del todo queda una perspectiva frontal perfecta. También he explotado más la idea de usar sprites grandes en el escenario, puesto que queda mejor si renderizo todo junto, con el mismo foco de luz.
Aquí algunos ejemplos de los gráficos que estoy preparando.
Y esto no se ha acabado, pero por fin creo que tengo una herramienta con la que puedo hacer animaciones desde diferentes puntos de vista con una perspectiva correcta sin dejarme la piel en ello y puedo dedicar más tiempo al código. Sobre si esto se terminará transformando en un juego, estaba pensado que no, pero cada vez dispongo de más material satisfactorio y la verdad es que la idea me gusta, pero solo lo haré si consigo implementar ciertas ideas que resultarían en un gameplay que tienda más al puzzle y el rol narrativo.
22 septiembre, 2015
Seis sprites para juegos rpg 2D
Voy a compartir unos cuantos sprites para juegos 2D top down que diseñé para ayudarme en el desarrollo de Living paper source rpg engine y voy a dejar de utilizar puesto que he comenzado a usar sprites pre-renderizados usando opensim. Éstos sprites pueden ser usados y modificados sin ninguna restricción y sin necesidad de mención, gracias.
También aprovecho para mencionar que puedes ayudarme a elegir un logotipo para la versión final de mi engine votando el modelo que más te guste aquí: https://plus.google.com/103212854338954376211/posts/Y5njd9TkQU6
18 febrero, 2015
Reproducir sonido para juegos en vb.net varios métodos
Reproducir sonido en vb.net es una tarea muy sencilla siempre y cuando nos atengamos a ciertas limitaciones. La manera más común de reproducir sonido es el espacio de nombres My.Computer.Audio, que sólo es capaz de reproducir ficheros .wav, cumple su trabajo si se trata de introducir un sonido a un botón o a una notificación, pero en proyectos más complejos es una trampa.
Algunos sabreis que estoy actualmente creando un engine arpg en vb.net, un lenguaje contraindicado para programas donde los gráficos y sonidos deben moverse muy rápido. Algunos os preguntareis que porqué no uso XNA games studio, pero la verdad, dicha solución de microsoft no me convence y además creo que ya está desmantenida. ¿Y directx? la verdad es que no quiero portar este proyecto a directx aun, desde el principio he usado Gdi+ y ya está demostrado que sirve aunque hay que usar ciertos trucos, en el sonido no es diferente.
En el desarrollo del engine noté picos muy grandes de lag usando My.computer.audio.play() y peor aún, no podía reproducir varios sonidos en paralelo lo cual es vital para el engine. He pasado un par de semanas informándome y probando y he llegado a soluciones más rápidas o menos limitadas para reproducir audio en .net
Método1: winmm.dll / mciSendStringAl principio encontré un objeto escrito por un tal Blake Pell (bpell@indiana.edu) que durante un tiempo me sirvió para añadir música en bucle al engine mientras que las llamadas a my.computer.audio() no interferían con esta. Así podía tener algo así como dos canales, uno para la música y otro para todo el sonido FX. Además que este objeto puede reproducir entre otros formatos mp3 lo que permite que la música del juego no ocupe una barbaridad. Por supuesto seguía teniendo el problema del lag, pero eso lo solucionaría más adelante. El código es bastante grande y sus funciones estan planteadas como un reproductor con controles de pausa etc.
Public Class PlayFile
'***********************************************************************************************************
' Class: PlayFile
' Written By: Blake Pell (bpell@indiana.edu)
' Initial Date: 03/31/2007
' Last Updated: 02/04/2009
'***********************************************************************************************************
' Windows API Declarations
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Int32, ByVal hwndCallback As Int32) As Int32
'''
''' Constructor: Location is the filename of the media to play. Wave files and Mp3 files are the supported formats.
'''
'''
'''
Public Sub New(ByVal location As String)
Me.Filename = location
End Sub
'''
''' Plays the file that is specified as the filename.
'''
'''
Public Sub Play()
If _filename = "" Or Filename.Length <= 4 Then Exit Sub
Select Case Right(Filename, 3).ToLower
Case "mp3"
mciSendString("open """ & _filename & """ type mpegvideo alias audiofile", Nothing, 0, IntPtr.Zero)
Dim playCommand As String = "play audiofile from 0 repeat"
If _wait = True Then playCommand += " wait"
mciSendString(playCommand, Nothing, 0, IntPtr.Zero)
Case "wav"
mciSendString("open """ & _filename & """ type waveaudio alias audiofile", Nothing, 0, IntPtr.Zero)
mciSendString("play audiofile from 0", Nothing, 0, IntPtr.Zero)
Case "mid", "idi"
mciSendString("stop midi", "", 0, 0)
mciSendString("close midi", "", 0, 0)
mciSendString("open sequencer!" & _filename & " alias midi", "", 0, 0)
mciSendString("play midi", "", 0, 0)
Case Else
'Throw New Exception("File type not supported.")
Call Close()
End Select
IsPaused = False
End Sub
'''
''' Pause the current play back.
'''
'''
Public Sub Pause()
mciSendString("pause audiofile", Nothing, 0, IntPtr.Zero)
IsPaused = True
End Sub
'''
''' Resume the current play back if it is currently paused.
'''
'''
Public Sub [Resume]()
mciSendString("resume audiofile", Nothing, 0, IntPtr.Zero)
IsPaused = False
End Sub
'''
''' Stop the current file if it's playing.
'''
'''
Public Sub [Stop]()
mciSendString("stop audiofile", Nothing, 0, IntPtr.Zero)
End Sub
'''
''' Close the file.
'''
'''
Public Sub Close()
mciSendString("close audiofile", Nothing, 0, IntPtr.Zero)
End Sub
Private _wait As Boolean = False
'''
''' Halt the program until the .wav file is done playing. Be careful, this will lock the entire program up until the
''' file is done playing. It behaves as if the Windows Sleep API is called while the file is playing (and maybe it is, I don't
''' actually know, I'm just theorizing). :P
'''
'''
'''
'''
Public Property Wait() As Boolean
Get
Return _wait
End Get
Set(ByVal value As Boolean)
_wait = value
End Set
End Property
'''
''' Sets the audio file's time format via the mciSendString API.
'''
'''
'''
'''
ReadOnly Property Milleseconds() As Integer
Get
Dim buf As String = Space(255)
mciSendString("set audiofile time format milliseconds", Nothing, 0, IntPtr.Zero)
mciSendString("status audiofile length", buf, 255, IntPtr.Zero)
buf = Replace(buf, Chr(0), "") ' Get rid of the nulls, they muck things up
If buf = "" Then
Return 0
Else
Return CInt(buf)
End If
End Get
End Property
'''
''' Gets the status of the current playback file via the mciSendString API.
'''
'''
'''
'''
ReadOnly Property Status() As String
Get
Dim buf As String = Space(255)
mciSendString("status audiofile mode", buf, 255, IntPtr.Zero)
buf = Replace(buf, Chr(0), "") ' Get rid of the nulls, they muck things up
Return buf
End Get
End Property
'''
''' Gets the file size of the current audio file.
'''
'''
'''
'''
ReadOnly Property FileSize() As Integer
Get
Try
Return My.Computer.FileSystem.GetFileInfo(_filename).Length
Catch ex As Exception
Return 0
End Try
End Get
End Property
'''
''' Gets the channels of the file via the mciSendString API.
'''
'''
'''
'''
ReadOnly Property Channels() As Integer
Get
Dim buf As String = Space(255)
mciSendString("status audiofile channels", buf, 255, IntPtr.Zero)
If IsNumeric(buf) = True Then
Return CInt(buf)
Else
Return -1
End If
End Get
End Property
'''
''' Used for debugging purposes.
'''
'''
'''
'''
ReadOnly Property Debug() As String
Get
Dim buf As String = Space(255)
mciSendString("status audiofile channels", buf, 255, IntPtr.Zero)
Return Str(buf)
End Get
End Property
Private _isPaused As Boolean = False
'''
''' Whether or not the current playback is paused.
'''
'''
'''
'''
Public Property IsPaused() As Boolean
Get
Return _isPaused
End Get
Set(ByVal value As Boolean)
_isPaused = value
End Set
End Property
Private _filename As String
'''
''' The current filename of the file that is to be played back.
'''
'''
'''
'''
Public Property Filename() As String
Get
Return _filename
End Get
Set(ByVal value As String)
If My.Computer.FileSystem.FileExists(value) = False Then
'Throw New System.IO.FileNotFoundException
End If
_filename = value
End Set
End Property
End Class
Método2: winmm.dll / PlaySoundIntentando dar con un modo de reproducir sonidos en varios canales encontré este pequeño objeto que sorprendentemente terminó con el problema del lag al cargar sonido. Reproduce wav pero resulta ser extraordinariamente rápido y sólo le encontré una pega, no permite reproducir varios sonidos a la vez. No solucionó mi problema de los canales, pero inesperadamente solucionó el del lag. Intenté hacer todo tipo de modificaciones para conseguir multicanal, pero nada funcionó.
Private Class SoundCore
Private Declare Auto Function PlaySound Lib "winmm.dll" (ByVal name As String, ByVal hmod As Integer, ByVal flags As Integer) As Integer
' name specifies the sound file when the SND_FILENAME flag is set.
' hmod specifies an executable file handle.
' hmod must be Nothing if the SND_RESOURCE flag is not set.
' flags specifies which flags are set.
' The PlaySound documentation lists all valid flags.
Public Const SND_SYNC As Integer = &H0 ' play synchronously
Public Const SND_ASYNC As Integer = &H1 ' play asynchronously
Public Const SND_FILENAME As Integer = &H20000 ' name is file name
Public Const SND_RESOURCE As Integer = &H40004 ' name is resource name or atom
'more
Public Const SND_APPLICATION = &H80
Public Const SND_NODEFAULT = &H2 '
Public Const SND_LOOP = &H8 '
Public Const SND_NOSTOP = &H10 '
Public Const SND_NOWAIT = &H2000
''' -------------------------------------------------
'''
''' Reproducir un archivo de sonido que esta en un archivo del disco
'''
'''
'''Referencia bibliografica Ayuda MSDM
'''ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.3082/dv_vbcode/html/vbtskCodeExamplePlayingSound.htm
'''
'''Si el archivo especificado no existe, se reproduce el
''' sonido de evento de sistema predeterminado y no devuelve ningun
''' error.
'''
'''
''' El nombre de archivo que debe hacer referencia a un archivo
''' de sonido que se encuentre en el sistema
'''
''' (System.String)
'''
'''
'''
'''Un valor booleano.: Devuelve
'''True.: cuando tiene exito y el archivo de sonido
''' se reproduce
'''False: cuando por la razon que sea no se reproduce el
''' sonido
'''
''' (System.Boolean)
'''
'''
''' -------------------------------------------------
Public Function Play(ByVal nombreFicheroSonido As String) As Boolean
Try
' Plays a sound from filename.
Return CBool(PlaySound(nombreFicheroSonido, Nothing, SND_FILENAME Or SND_ASYNC Or SND_APPLICATION))
Catch ex As Exception
Throw ex
End Try
End Function
End Class
Método3 WMPLib playerÉsta vez di con un método de reproducción multicanal aunque por desgracia no tan rápido como hubiera deseado. Se trata de un objeto COM (yo suelo evitarlos) que funciona como interface para manejar reproductores de windows media, decirle que archivo debe reproducir etc. Incluso permite crear playlists (supongo que tendrá utilidad para el engine). No es tan lento como my.computer.audio pero el pico de lag llega a ser perceptible. Cuando un sonido nuevo llega el anterior sigue reproduciendose lo cual lo convierte en el método adecuado para controlar SFX en la creación de juegos. Es el código más pequeño de todos y no lleva anotaciones puesto que es tan sencillo que símplemente sobran.
Private Class SoundCore_wmp
Private WithEvents player As New WMPLib.WindowsMediaPlayer
Public Sub play(nombrearchivo As String)
If Not (player.URL = nombrearchivo) Then
player.URL = nombrearchivo
End If
player.controls.play()
End Sub
End Class
27 julio, 2014
Soluciona el error al conectar con el motor de hamachi en un sencillo paso
Si eres usuario de las redes de logmein Hamachi posiblemente conozcas el mensaje de error de la imágen, y posiblemente lo odies a muerte. Tranquilo, la solución es sencilla, he creado un script haxbox que solucionará el problema automáticamente. Tan sólo tienes que descargar el siguiente archivo:
https://dl.dropboxusercontent.com/u/24363459/hamachi%20fix.rar
descomprimirlo todo y ejecutar (como administrador!) hbx.exe, hamachi debería comenzar a funcionar como por arte de magia. Importante, si no se ejecuta como ADMINISTRADOR el script no funcionará puesto que carece de permisos para abrir un servicio.
https://dl.dropboxusercontent.com/u/24363459/hamachi%20fix.rar
descomprimirlo todo y ejecutar (como administrador!) hbx.exe, hamachi debería comenzar a funcionar como por arte de magia. Importante, si no se ejecuta como ADMINISTRADOR el script no funcionará puesto que carece de permisos para abrir un servicio.
16 noviembre, 2013
Toma el control de la configuración oculta de windows
Vale, no quiero pasarme de sensacionalista, en realidad no es una configuración oculta, aunque si se puede decir que muchas de estas herramientas sólo se pueden ejecutar conociendo el nombre de la misma y abriendola desde windows/system32. Este sencillo script hax puede facilitarnos la tarea de ejecutar varias herramientas de windows que normalmente pasan desapercibidas como por ejemplo el particionador de discos, el cliente de escritorio remoto, verificador de drivers o el utilisimo creador de paquetes de instalación.
Este script funciona sobre windows7, es posible que muchas de las funciones funcionen también en windows vista o windows xp siempre y cuando se tenga instalado el .net framework 4.5. El código puede ser leido y modificado al gusto del usuario permitiendo así diseñar tu propia "master tool" para windows a medida. El script ejecutado se encuentra en la carpeta "s" con el nombre menu.mc, es un script crashMiniC para haxbox (haxbox.weebly.com)
Se incluyen estas 12 herramientas en el menú:
Este script funciona sobre windows7, es posible que muchas de las funciones funcionen también en windows vista o windows xp siempre y cuando se tenga instalado el .net framework 4.5. El código puede ser leido y modificado al gusto del usuario permitiendo así diseñar tu propia "master tool" para windows a medida. El script ejecutado se encuentra en la carpeta "s" con el nombre menu.mc, es un script crashMiniC para haxbox (haxbox.weebly.com)
Se incluyen estas 12 herramientas en el menú:
- Panel de control de administración
- Opciones de carpeta
- Particionador de discos
- Verificador de drivers
- Creador de instaladores
- Monitor de rendimiento
- Editor de registro
- Cliente de escritorio remoto
- Tareas programadas
- Carpetas compartidas
- Administrador de discos
- Administrador de usuarios y grupos
DESCARGA: Winbox hidden cfg
29 julio, 2013
Living paper source (Proyecto .net rpg game engine)
¿Recuerdan esto http://abdlab.blogspot.com.es/2012/04/proximos-proyectos-imagenes.html?
Pues bien, estuve tiempo trabajando en ello, metiendo código rápidamente hasta que todo se volvió muy complicado de manejar. Entonces surgió una idea, la cual debería haber sido mi punto de partida: "en lugar de hacer diréctamente un juego 2D necesito crear primero un objeto de usuario que simplifique la tarea". Durante este tiempo he comenzado varios proyectos relaccionados con el dibujo en dos dimensiones, aunque de ellos ninguno ha llegado a nada he recolectado códigos reutilizables muy interesantes y con ellos he comenzado el llamado proyecto living paper source, un rpg game engine que permitirá preparar juegos simples para un jugador sin necesidad de tener grandes conocimientos de programación.
Los tilesets, es decir, los paquetes de gráficos para diseñar el mapa se cargan de una manera muy libre, cada escenario puede cargar diferentes tilesets, de diferentes tamaños permitiendo una riqueza visual inimaginable en otros sistemas como rpgmaker o los basados en mirage source. Además se pueden añadir objetos "libres de cuadricula" para añadir detalles opcionalmente animados. El renderizado utiliza 5 capas independientes por ahora, uno para dibujar los sprites, dos debajo y dos sobre ellos, acepta formatos bmp, jpg y png con transparencia.
Lo más importante del proyecto en cuestión es que está basado en un objeto de usuario (al que llamo screen) que se ocupa de manejar todo lo referente al renderizado, manejo de sprites, detección de colisiones e incluso el cargado/guardado de mapeados. Todo dicho código (bastante intratable) queda oculto al programador por lo que se simplifica mucho el trabajo haciendo viables proyectos más complicados. Por ahora living paper source está en un estado muy temprano, y sin embargo permite ya hacer cosas muy interesantes. El editor de mapas es la parte más acabada puesto que es la que más complejidad aglomera. También dispone de un lenguaje de scripting basado en eventos diseñado específicamente para living paper source (satanas scripting) el cual permitirá crear los comportamientos de ciertos objetos interactivos de juego (actores).
El lenguaje combina ideas tanto de hax scripting como de crash minic pero con una gran diferencia, en lugar de cargar un script y ejecutarlo línea a línea, se cargan diferentes módulos combinados dependiendo del evento que se deba ejecutar; es decir, si un jugador presiona el botón de acción justo enfrente de un actor llamado por ejemplo "botón01" la máquina virtual satanas cargará una combinación de:
- framework: igual que en haxbox, jenova o turbotron, funciones reutilizables universales.
- mapscript-action: código que se ejecutará siempre que se usa acción en dicho mapa, es opcional.
- objectscript-action: código de acción que hace referencia a dicho objeto.
Así que si, por ejemplo, el objeto botón abre una puerta, ese código irá en el archivo objectscript en el evento on_action, pero podemos introducir también código en mapscript para que se ejecute siempre que usemos acción sobre cualquier objeto de dicho mapa. Parece complicado de explicar, espero poder documentarlo de una manera clara.
Antes de despedirme quiero dejar claro que falta mucho para liberar una primera versión y que seguramente esta no sea open source en su totalidad, quizás el objeto de usuario "screen" si lo sea, pero el entorno completo seguramente no, a pesar de eso se trata de una herramienta completa que no necesitará ser editada para crear juegos únicos gracias a su versatilidad. Un saludo coders y users.
Pues bien, estuve tiempo trabajando en ello, metiendo código rápidamente hasta que todo se volvió muy complicado de manejar. Entonces surgió una idea, la cual debería haber sido mi punto de partida: "en lugar de hacer diréctamente un juego 2D necesito crear primero un objeto de usuario que simplifique la tarea". Durante este tiempo he comenzado varios proyectos relaccionados con el dibujo en dos dimensiones, aunque de ellos ninguno ha llegado a nada he recolectado códigos reutilizables muy interesantes y con ellos he comenzado el llamado proyecto living paper source, un rpg game engine que permitirá preparar juegos simples para un jugador sin necesidad de tener grandes conocimientos de programación.
Los tilesets, es decir, los paquetes de gráficos para diseñar el mapa se cargan de una manera muy libre, cada escenario puede cargar diferentes tilesets, de diferentes tamaños permitiendo una riqueza visual inimaginable en otros sistemas como rpgmaker o los basados en mirage source. Además se pueden añadir objetos "libres de cuadricula" para añadir detalles opcionalmente animados. El renderizado utiliza 5 capas independientes por ahora, uno para dibujar los sprites, dos debajo y dos sobre ellos, acepta formatos bmp, jpg y png con transparencia.
Lo más importante del proyecto en cuestión es que está basado en un objeto de usuario (al que llamo screen) que se ocupa de manejar todo lo referente al renderizado, manejo de sprites, detección de colisiones e incluso el cargado/guardado de mapeados. Todo dicho código (bastante intratable) queda oculto al programador por lo que se simplifica mucho el trabajo haciendo viables proyectos más complicados. Por ahora living paper source está en un estado muy temprano, y sin embargo permite ya hacer cosas muy interesantes. El editor de mapas es la parte más acabada puesto que es la que más complejidad aglomera. También dispone de un lenguaje de scripting basado en eventos diseñado específicamente para living paper source (satanas scripting) el cual permitirá crear los comportamientos de ciertos objetos interactivos de juego (actores).
El lenguaje combina ideas tanto de hax scripting como de crash minic pero con una gran diferencia, en lugar de cargar un script y ejecutarlo línea a línea, se cargan diferentes módulos combinados dependiendo del evento que se deba ejecutar; es decir, si un jugador presiona el botón de acción justo enfrente de un actor llamado por ejemplo "botón01" la máquina virtual satanas cargará una combinación de:
- framework: igual que en haxbox, jenova o turbotron, funciones reutilizables universales.
- mapscript-action: código que se ejecutará siempre que se usa acción en dicho mapa, es opcional.
- objectscript-action: código de acción que hace referencia a dicho objeto.
Así que si, por ejemplo, el objeto botón abre una puerta, ese código irá en el archivo objectscript en el evento on_action, pero podemos introducir también código en mapscript para que se ejecute siempre que usemos acción sobre cualquier objeto de dicho mapa. Parece complicado de explicar, espero poder documentarlo de una manera clara.
Antes de despedirme quiero dejar claro que falta mucho para liberar una primera versión y que seguramente esta no sea open source en su totalidad, quizás el objeto de usuario "screen" si lo sea, pero el entorno completo seguramente no, a pesar de eso se trata de una herramienta completa que no necesitará ser editada para crear juegos únicos gracias a su versatilidad. Un saludo coders y users.
30 diciembre, 2012
Haxbox mv ya tiene sitio oficial
He creado un pequeño sitio gratuito para reunir toda la información referente a la máquina virtual haxbox mv para windows. Ahí podrás encontrar los últimos avances, las últimas versiones disponibles y toneladas de ejemplos, especificaciones, tutoriales etc que te permitirán, con un poco de tiempo, dominar los lenguajes de programación jenoassembler-hax y crash miniC. Espero que esta herramienta les sea útil, el sitio es:
haxbox.weebly.com
02 septiembre, 2012
Funciones útiles para manejar gráficos en VB.net usando GDI+
Bueno, no necesita demasiada explicación, se trata de funciones comunes como leer un archivo, redimensionarlo, dibujar una imagen sobre otra etc... muy aconsejable usar este tipo de funciones para evitar redibujar las imágenes en resolución máxima todo el tiempo a la hora de programar un juego. Es una buena idea dibujar en un caché cada capa de sprites para poder acoplarlas rápidamente, ya que GDI+ no es una opción especialmente rápida.
'leer una imágen desde archivo
Public Function read_image(ByVal file As String) As System.Drawing.Bitmap
Dim img As New Bitmap(file)
Return img
End Function
Public Function read_image(ByVal file As String, ByVal sizex As Integer, ByVal sizey As Integer) As System.Drawing.Bitmap
Dim img As New Bitmap(file)
Dim b As New Bitmap(sizex, sizey)
Dim bg As Graphics = Graphics.FromImage(b)
bg.DrawImage(img, New Rectangle(New Point(0, 0), New Size(sizex, sizey)), New Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel)
Return b
End Function
'redimensionar una imágen
Public Function resize_bmp(ByVal img As Bitmap, ByVal sizex As Integer, ByVal sizey As Integer) As Bitmap
Dim b As New Bitmap(sizex, sizey)
Dim bg As Graphics = Graphics.FromImage(b)
bg.DrawImage(img, New Rectangle(New Point(0, 0), New Size(sizex, sizey)), New Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel)
Return b
End Function
Public Function resize_bmp(ByVal img As Bitmap, ByVal size As Size) As Bitmap
Dim b As New Bitmap(size.Width, size.Height)
Dim bg As Graphics = Graphics.FromImage(b)
bg.DrawImage(img, New Rectangle(New Point(0, 0), New Size(size.Width, size.Height)), New Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel)
Return b
End Function
' extraer una porción de una imágen
' image = imagen a recortar
' cuadriculax y cuadriculay = número de sectores por cada dimensión
' sectorx y sectory = vector puntero de la selección
Public Function get_portion(ByVal image As System.Drawing.Bitmap, ByVal cuadriculax As Short, ByVal cuadriculay As Short, ByVal sectorx As Integer, ByVal sectory As Integer) As System.Drawing.Bitmap
Dim img As New Bitmap(CInt(image.Size.Width / cuadriculax), CInt(image.Size.Height / cuadriculay))
'Dim b As New Bitmap(CInt(image.Size.Width / cuadriculax), CInt(image.Size.Height / cuadriculay))
Dim bg As Graphics = Graphics.FromImage(img)
Dim tmpx As Integer = (image.Size.Width / cuadriculax) * sectorx
Dim tmpy As Integer = (image.Size.Height / cuadriculay) * sectory
Dim port As New Rectangle(New System.Drawing.Point(0, 0), New Size(New Point(image.Size.Width / cuadriculax, image.Size.Height / cuadriculay)))
bg.DrawImage(image, port, tmpx, tmpy, CInt(port.Size.Width), CInt(port.Size.Height), GraphicsUnit.Pixel)
Return img
End Function
Public Function get_portion(ByVal image As System.Drawing.Bitmap, ByVal cuadricula As System.Drawing.Size, ByVal sector As System.Drawing.Size) As System.Drawing.Bitmap
Dim img As New Bitmap(CInt(image.Size.Width / cuadricula.Width), CInt(image.Size.Height / cuadricula.Height))
'Dim b As New Bitmap(CInt(image.Size.Width / cuadricula.Width), CInt(image.Size.Height / cuadricula.Height))
Dim bg As Graphics = Graphics.FromImage(img)
Dim tmpx As Integer = (image.Size.Width / cuadricula.Width) * sector.Width
Dim tmpy As Integer = (image.Size.Height / cuadricula.Height) * sector.Height
Dim port As New Rectangle(New System.Drawing.Point(0, 0), New Size(New Point(image.Size.Width / cuadricula.Width, image.Size.Height / cuadricula.Height)))
bg.DrawImage(image, port, tmpx, tmpy, CInt(port.Size.Width), CInt(port.Size.Height), GraphicsUnit.Pixel)
Return img
End Function
' sobredibujar una imágen sobre otra
Public Function layer_sum(ByVal layer1 As Bitmap, ByVal layer2 As Bitmap) As Bitmap
Dim bg As Graphics = Graphics.FromImage(layer1)
bg.DrawImage(layer2, New Point(0, 0))
Return layer1
End Function
Public Function layer_sum(ByVal layer1 As Bitmap, ByVal layer2 As Bitmap, ByVal offsetx As Integer, ByVal offsety As Integer) As Bitmap
Dim bg As Graphics = Graphics.FromImage(layer1)
bg.DrawImage(layer2, New Point(offsetx, offsety))
Return layer1
End Function
' dibujar una imágen de texto rasterizado
Public Function get_text_layer(ByVal size As System.Drawing.Size, ByVal text As String) As System.Drawing.Bitmap
Dim img As New Bitmap(size.Width, size.Height)
Dim bg As Graphics = Graphics.FromImage(img)
bg.DrawString(text, New Font("Arial", 12, FontStyle.Bold), Brushes.Black, New Point(1, -1))
bg.DrawString(text, New Font("Arial", 12, FontStyle.Bold), Brushes.White, New Point(0, 0))
Return img
End Function
Public Function get_text_layer(ByVal sizex As Integer, ByVal sizey As Integer, ByVal text As String) As System.Drawing.Bitmap
Dim img As New Bitmap(sizex, sizey)
Dim bg As Graphics = Graphics.FromImage(img)
bg.DrawString(text, New Font("Arial", 12, FontStyle.Bold), Brushes.Black, New Point(1, -1))
bg.DrawString(text, New Font("Arial", 12, FontStyle.Bold), Brushes.White, New Point(0, 0))
Return img
End Function
Public Function get_text_layer(ByVal sizex As Integer, ByVal sizey As Integer, ByVal text As String, ByVal fontsize As Integer) As System.Drawing.Bitmap
Dim img As New Bitmap(sizex, sizey)
Dim bg As Graphics = Graphics.FromImage(img)
bg.DrawString(text, New Font("Arial", fontsize, FontStyle.Bold), Brushes.Black, New Point(1, -1))
bg.DrawString(text, New Font("Arial", fontsize, FontStyle.Bold), Brushes.White, New Point(0, 0))
Return img
End Function 'code by abderramah abdlab software
04 abril, 2012
Proximos proyectos (imágenes)
Es pronto para dar información clara sobre esto, pero se trata de un mundo virtual 2d que usa el servidor "minimal TCP" (ver la entrada anterior). Por ahora estoy añadiendo código muy rápido, dejando una estela de bugs a mi paso que tendré que repasar. Utiliza un modo gráfico basado en haxbox pero con extensiones añadidas, como la capacidad de manejar avatares con capas de ropa o pelo o la de no redibujar las partes estáticas en cada cuadro de dibujo. Supongo que el futuro de éste sistema será crear un juego, y también supongo que no podré liberar el código por cuestiones de cheating.
modo local
modo servidor y menú rápido
ventana de login sobre parte del código
notificaciones y edición de apariencia
20 marzo, 2012
Minimal tcp client code
' Minimal Tcp client for vb.net by abderramah (based in several msdn example codes)
'
' // este cliente no mantiene una conexión abierta, tan sólo conecta a una dirección, envía los datos indicados
' // y espera a recibir respuesta. En caso de no recibirla es posible que se quede en estado de espera, pero
' // con unas pocas líneas se puede solucionar.
'
' // petición http de ejemplo:
' // getsocket.socketsendreceive(192.168.2.5, 80, "GET / HTTP/1.1" + ControlChars.Cr + ControlChars.Lf )
Public Class GetSocket
Public Event errordebug(ByVal datae As String)
Public Function ConnectSocket(ByVal server As String, ByVal port As Integer) As Socket
Dim s As Socket = Nothing
Dim hostEntry As New IPHostEntry
' recibir información del host
Try
Dim ipe As IPAddress = New IPAddress(IPAddress.Parse(server).GetAddressBytes)
hostEntry.AddressList = {ipe}
Catch ex As Exception
Try
hostEntry = Dns.GetHostEntry(server)
Catch exa As Exception
hostEntry.AddressList = {IPAddress.Parse(server)}
End Try
End Try
' recorrer todas las direcciones del host (ipv4 e ipv6)
Dim address As IPAddress
For Each address In hostEntry.AddressList
Dim endPoint As New IPEndPoint(address, port)
Dim tempSocket As New Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
Try
tempSocket.Connect(endPoint)
Catch ex As Exception
Return s
Exit Function
End Try
If tempSocket.Connected Then
s = tempSocket
Exit For
End If
Next address
Return s
End Function
' conectar, enviar petición y recibir la respuesta
Public Function SocketSendReceive(ByVal server As String, ByVal port As Integer, ByVal datae As String) As String
Dim ascii As Encoding = Encoding.ASCII
'httprequest= "GET / HTTP/1.1" + ControlChars.Cr + ControlChars.Lf + "Host: " + server + ControlChars.Cr + ControlChars.Lf + "Connection: Close" + ControlChars.Cr + ControlChars.Lf + ControlChars.Cr + ControlChars.Lf
Dim request As String = datae
Dim bytesSent As [Byte]() = ascii.GetBytes(request)
Dim bytesReceived(128000) As [Byte]
' crear socket
Dim s As Socket = ConnectSocket(server, port)
If s Is Nothing Then
Return "Tcp connection failed"
Exit Function
End If
' enviar la petición tcp
s.Send(bytesSent, bytesSent.Length, 0)
Dim bytes As Int32
' leer los datos de entrada
Dim page As [String] = ""
' loop recibiendo
Do
bytes = s.Receive(bytesReceived, bytesReceived.Length, 0)
page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes)
Loop While bytes > 0
Return page
End Function
End Class
'
' // este cliente no mantiene una conexión abierta, tan sólo conecta a una dirección, envía los datos indicados
' // y espera a recibir respuesta. En caso de no recibirla es posible que se quede en estado de espera, pero
' // con unas pocas líneas se puede solucionar.
'
' // petición http de ejemplo:
' // getsocket.socketsendreceive(192.168.2.5, 80, "GET / HTTP/1.1" + ControlChars.Cr + ControlChars.Lf )
Public Class GetSocket
Public Event errordebug(ByVal datae As String)
Public Function ConnectSocket(ByVal server As String, ByVal port As Integer) As Socket
Dim s As Socket = Nothing
Dim hostEntry As New IPHostEntry
' recibir información del host
Try
Dim ipe As IPAddress = New IPAddress(IPAddress.Parse(server).GetAddressBytes)
hostEntry.AddressList = {ipe}
Catch ex As Exception
Try
hostEntry = Dns.GetHostEntry(server)
Catch exa As Exception
hostEntry.AddressList = {IPAddress.Parse(server)}
End Try
End Try
' recorrer todas las direcciones del host (ipv4 e ipv6)
Dim address As IPAddress
For Each address In hostEntry.AddressList
Dim endPoint As New IPEndPoint(address, port)
Dim tempSocket As New Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
Try
tempSocket.Connect(endPoint)
Catch ex As Exception
Return s
Exit Function
End Try
If tempSocket.Connected Then
s = tempSocket
Exit For
End If
Next address
Return s
End Function
' conectar, enviar petición y recibir la respuesta
Public Function SocketSendReceive(ByVal server As String, ByVal port As Integer, ByVal datae As String) As String
Dim ascii As Encoding = Encoding.ASCII
'httprequest= "GET / HTTP/1.1" + ControlChars.Cr + ControlChars.Lf + "Host: " + server + ControlChars.Cr + ControlChars.Lf + "Connection: Close" + ControlChars.Cr + ControlChars.Lf + ControlChars.Cr + ControlChars.Lf
Dim request As String = datae
Dim bytesSent As [Byte]() = ascii.GetBytes(request)
Dim bytesReceived(128000) As [Byte]
' crear socket
Dim s As Socket = ConnectSocket(server, port)
If s Is Nothing Then
Return "Tcp connection failed"
Exit Function
End If
' enviar la petición tcp
s.Send(bytesSent, bytesSent.Length, 0)
Dim bytes As Int32
' leer los datos de entrada
Dim page As [String] = ""
' loop recibiendo
Do
bytes = s.Receive(bytesReceived, bytesReceived.Length, 0)
page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes)
Loop While bytes > 0
Return page
End Function
End Class
04 marzo, 2012
El intérprete Haxbox, introducción
Haxbox es un intérprete de máquina virtual abstracta, una herramienta de programación con un lenguaje especial, que toma parte de los ensambladores mnemónicos y parte de los lenguajes de nivel alto. Tiene muchas peculiaridades que lo distinguen de otros sistemas de máquina virtual existentes, como por ejemplo java, tampoco emula la arquitectura x86 ni ninguna otra, se trata de una arquitectura propia diseñada especialmente para facilitar la flexibilidad, abstracción y legibilidad al máximo, así como optimizar la capacidad de compartir y editar los códigos. Funciona sobre windows con .net framework 4.0 o superior (solo ha sido probado en W7).
Un procesador común tiene un tipo de datos básico en el que funciona, el byte, es decir tanto las instrucciones como los parámetros de éstas son transformadas a largas cadenas de bytes a la hora de trabajar con los datos. Haxbox utiliza el tipo de cadena de texto como unidad mínima, éstas cadenas pueden ser transformadas a números o a interrupciones boleanas en tiempo de ejecución. Ésto permite la lectura del código en cualquier momento, así como la edición de la memoria. Haxbox no es multihilo, ésto no es un punto a favor, pero facilita la comprensión de los códigos así como su diseño.
Haxbox está escrito en lenguaje .net, se podría entender como un interface que permite manejar una serie de objetos .net de un modo alternativo. Así pues un script en lenguaje hax lee las instrucciones almacenadas en su memoria y las transforma en interacciones con varios objetos separados en módulos. Un objeto es la consola de texto plano, otro para escribir o leer archivos, otra reproduce el sonido indicado, otra es una superficie donde reproducir gráficos gdi, otra ejecuta comandos de la consola de windows (cmd.exe) y devuelve opcionalmente la salida, otra hace peticiones tcp y otra hace peticiones web usando el componente iexplorer y captura la respuesta. Diseñar un programa manejando tantos métodos y objetos usando .net es tedioso, pero con haxbox en unas pocas líneas de texto plano podremos conseguir un resultado decente.
El lenguaje hax no tiene demasiadas instrucciones y su sintaxis es sencilla está basada en ensambladores mnemónicos. A pesar de asemejarse a un código ensamblador se trata de un lenguaje muy diferente con instrucciones que disparan procesos muy complejos y partes muy abstractas. El parecido proviene del hecho de que las instrucciones actuan diréctamente sobre la máquina, en este caso virtual, que dispone de registros y memorias al igual que un cpu físico. Eso si, haxbox mantiene un nivel de abstracción mucho más alto en el propio diseño de dichos componentes, haciendo que no debamos manejar complejas cadenas de bytes. Haxbox usa tipos de datos, pero éstos sólamente afectan en el momento de realizar operaciones y comparaciones aritméticas, el resto del tiempo se considera un objeto variable y su tipo sólo dependerá de dónde lo usemos. Las memorias están compuestas de registros que contienen cada uno una cadena de texto de longitud variable, tanto las memorias de programa como las de acceso aleatorio.
Haxbox dispone de una arquitectura interna y otra externa. Llamamos interna a todo lo que incluye a los registros, la memoria del programa, las de acceso aleatorio, el contador, la caché etc y externa a los dispositivos virtuales de entrada-salida, la consola de texto plano, la superficie gráfica, el sonido, el sistema de archivos, el protocolo tcp etc... Para comunicarnos con toda esta estructura usamos sólamente una instrucción, "busout" que tiene 3 parámetros, el primero indica a qué componente enviar los datos, el segundo y el tercero son los datos que enviaremos. Cada dispositivo dispone de un protocolo propio, en ocasiones muy simple, como la consola de texto plano (que tan sólo escribe todo lo que llega en el primer dato) y otras algo más complejo (como la superficie gráfica). El resto de instrucciones interactuan con la arquitectura interna de la máquina y se usarán tanto para efectuar operaciones como para controlar el flujo del programa.
Instrucciones de la máquina virtual (hasta ahora):
- // comentario
- @ etiqueta label
- flash0 vaciar todos los casilleros de reg0
- flash1 vaciar todos los casilleros de reg1
- flash2 vaciar todos los casilleros de reg2
- set0 asignar valor al casillero 0
- set1 asignar valor al casillero 1
- set2 asignar valor al casillero 2
- p0 cambiar el número de casillero 0
- p1 cambiar el número de casillero 1
- p2 cambiar el número de casillero 2
- mode0 cambiar el tipo de dato en casillero 0
- mode1 cambiar el tipo de dato en casillero 1
- mode2 cambiar el tipo de dato en casillero 2
- cachesave0 guardar todos los casilleros del registro 0 en el bloque caché indicado
- cachesave1 guardar todos los casilleros del registro 1 en el bloque caché indicado
- cachesave2 guardar todos los casilleros del registro 2 en el bloque caché indicado
- cacheload0 recuperar el bloque de caché indicado en el registro 0
- cacheload1 recuperar el bloque de caché indicado en el registro 1
- cacheload2 recuperar el bloque de caché indicado en el registro 2
- parse0 dividir el valor del casillero 0 usando el caracter indicado como separador
- parse1 dividir el valor del casillero 1 usando el caracter indicado como separador
- parse2 dividir el valor del casillero 2 usando el caracter indicado como separador
- explode0 separar cada carácter de texto del registro 0 en un casillero de dicho registro
- explode1 separar cada carácter de texto del registro 1 en un casillero de dicho registro
- explode2 separar cada carácter de texto del registro 2 en un casillero de dicho registro
- setc definir el valor numérico del contador
- csum sumar el valor al contador
- csub restar el valor del contador
- minc definir valor mínimo del contador en modo loop
- maxc definir valor máximo del contador en modo loop
- loopc activar (1) o desactivar (0) el contador en modo loop
- tobyte0 transforma todos los casilleros de texto de reg0 en su equivalente en bytes
- tobyte1 transforma todos los casilleros de texto de reg1 en su equivalente en bytes
- tobyte2 transforma todos los casilleros de texto de reg2 en su equivalente en bytes
- todata0 transforma todos los casilleros de bytes de reg0 en su equivalente en texto
- todata1 transforma todos los casilleros de bytes de reg1 en su equivalente en texto
- todata2 transforma todos los casilleros de bytes de reg2 en su equivalente en texto
- input para la ejecución hasta que el usuario introduzca datos
- busout envía la pareja de datos indicada a través del bus requerido
- set asigna valor a una palabra clave en la memoria de pares o crea una nueva
- get sitúa en reg2 el valor de la palabra clave requerida
- unset elimina la palabra clave indicada y su valor de la memoria de pares
- debug escribe el texto indicado en la consola de debug
- jump salta hasta la etiqueta indicada
- jif_match salta hasta la etiqueta indicada si reg0 es igual a reg1
- jif_max salta hasta la etiqueta indicada si reg0 es mayor que reg1
- jif_less salta hasta la etiqueta indicada si reg0 es menor que reg1
- jif salta hasta la etiqueta indicada si reg0 es igual que el valor true o 1
- call llama al procedimiento de usuario indicado
- return termina el procedimiento de usuario actual y vuelve al lugar desde el que fue llamado
- hardstop para definitivamente la ejecución de la máquina
- pause para la ejecución de la máquina hasta recibir la señal de control run
- suma suma reg1 a reg0 y lo guarda en reg2, si uno de los dos registros es str concatenará en lugar de sumar
- resta resta reg1 a reg0 y lo guarda en reg2
- mult multiplica reg0 y reg1 y lo guarda en reg2
- div divide reg0 entre reg1 y lo guarda en reg2
- rand genera un número aleatorio comprendido entre reg0 y reg1
06 enero, 2012
CONJUNTO DE INSTRUCCIONES ABDLAB JENOVA VM
Éste es el conjunto de instrucciones de la máquina virtual jénova en su versión 1.07
// Comentario, éste quedará reflejado en la memoria ram, pero será ignorado en tiempo de ejecución.
multiflash Borra todos los casillerso de los 3 registros principales del núcleo.
@ Crea una etiqueta multiuso, puede ser encontrada desde cualquier parte del código, anterior o posterior sustituyendo un parámetro de cualquier instrucción por @ nombre.
uso:
@ esto_es_una_etiqueta
para saltar a esta etiqueta usando la instrucción jump (explicada más adelante)
jump @ esto_es_una_etiqueta
En tiempo de ejecución será sustituido por un número entero que representa la posición en memoria de la etiqueta indicada si existe.
proc Define la posición actual como el inicio de una macro que podrá ser llamada con la función call (expicada más adelante). El código saltará hasta la etiqueta proc y continuará ejecutandose hasta que encuentre una instrucción return, lo que hará al código volver a la siguiente posición de la llamada.
uso:
proc my_macro
para llamar a esta macro con la instrucción call:
call my_macro
pause Para la máquina virtual y la deja a la espera de una señal de bus que la haga continuar. Ten en cuenta que si usas pause no puedes volver a arrancar la máquina con el código, sólo sirve una señal a través del bus.
uso:
pause
sleep Pausa la ejecución de la máquina por el número de segundos indicado en el parámetro, que puede ser un número entero o flotante así como una referencia de memoria.
uso:
sleep 0.5
multiproc Indica a la máquina que es un momento seguro para leer las instrucciones llegadas a través del bus y ejecutar los microcódigos recibidos, principalmente de lectura o escritura de memorias. Actualiza todos los datos en el que fueron recibidos desde la última actualización. Es importante ejecutarlo cuando no estemos trabajando con los registros de la cpu ya que sus valores pueden cambiar en el proceso.
uso:
multiproc
hardstop Finaliza la ejecución de la máquina. La próxima vez que recibiera la señal de arranque a través del bus ésta volvería a resetear las memorias y empezar desde cero.
mode0 Define el modo en el que será interpretado el valor del registro0 a la hora de ser utilizado. El modo se guarda siempre en el casillero0 del registro0.
mode1 Igual que mode0 pero para el registro1.
mode2 Igual que mode0 pero para el registro2.
parse0 Divide la cadena contenida en el casillero correspondiente al puntero0 del registro0 utilizando como separador el o los carácteres indicados en el o los parámetros.
uso:
// si reg0 p1 tiene almacenado: creo que / voy a / explotar
parse reg0 /
// forzará reg0 p1 a: creo que
// reg0 p2 a: voy a
// y reg0 p3: explotar
parse1 Igual que parse0 pero para el registro1.
parse2 Igual que parse0 pero para el registro2.
join0 Une todos los casilleros del registro0 intercalando el carácter indicado en el parámetro y los almacena en el primer casillero del mismo registro, es decir reg0 p2.
join0 sobreescribe el registro0 completo.
uso:
// si en reg0 p1 tengo: hola
// y en reg0 p2: mundo
join +
// dejará en reg0 p1: hola+mundo
join1 Igual que join0 pero para el registro1.
join2 Igual que join0 pero para el registro2.
p0 Cambia el puntero que indica qué casillero del registro 0 leeremos o escribiremos a continuación. El parámetro debe de ser un número entero de 1 a 32000.
uso:
p0 5
p1 Igual que p0 pero para el registro1.
p2 Igual que p0 pero para el registro2.
mov0 Mueve el puntero del registro0 hacia arriba de su posición actual si el parámetro es + y a hacia abajo de la misma si es -. Nunca bajará por debajo del valor 1.
uso:
mov0 +
mov1 Igual que mov0 pero para el registro1.
mov2 Igual que mov0 pero para el registro2.
sector Cambia el prefijo de sector de las definiciones de la memoria de pares. Al hacer esto todos los pares almacenados aparentarán haber desaparecido pero al volver al mismo prefijo volveremos a poder trabajar con ellas.
uso:
sector test_zone_
set0 Almacena el dato indicado en el parámetro dentro del casillero indicado en p0 en el registro0.
uso:
set0 hola mundo
set1 Igual que set0 pero para el registro1.
set2 Igual que set0 pero para el registro2.
flash0 Sirve para escribir el contenido de varios casilleros del registro0 de una vez, es decir, se pueden introducir valores en reg0 p1,reg0 p2,reg0 p3, y así sucesivamente, si no se incluyen parámetros vaciará todos los casilleros.
uso:
flash0 12,13,core_reg2,test data01,testdata 02,reg0:p6 data,etc
flash1 Igual que flash0 pero para el registro1.
flash2 Igual que flash0 pero para el registro2.
busout Envía a través del bus indicado en el primer parámetro los datos indicados en el segundo y el tercero.
uso:
busout 15,test data test data,1530
input Para la máquina y se queda a la espera de que se introduzcan datos a través del canal de chat indicado en parámetro, el canal público es 0.
set Guarda en la memoria de pares el dato indicado en el segundo parámetro con el nombre o referencia indicado en el primero.
uso:
set patxi,15000
get Recupera y almacena en reg2 el valor del par con nombre o referencia igual al indicado en el parámetro.
uso:
get patxi
unset Elimina el par con nombre o referencia igual al indicado en el parámetro.
uso:
unset patxi
debug Envía los datos indicados a través del canal de debug.
uso:
debug programa terminado
jump Coloca el puntero de lectura en la posición indicada en parámetro. Se aconseja utilizar etiquetas @ para facilitar el trabajo.
uso:
jump @ label_init
jif_match Saltar a la línea indicada si el valor contenido en reg0 es identico al contenido en reg1.
uso:
jif_match @ label_init
jif Saltar a la posición indicada en el segundo parámetro si el valor del primero puede ser interpretado como SI boleano.
uso:
jif true,@ label_init
jif_max Igual que jif_match pero salta sólo si reg0 es mayor que reg1.
jif_less Igual que jif_match pero salta sólo si reg0 es menor que reg1.
call Ejecutar la macro indicada en el parámetro. La macro debe de estar definida con la etiqueta proc y cargada en la memoria ram.
uso:
call my_macro
return Indica el final de una macro, si la profundidad del proceso actual es 1 fuerza al código a reiniciarse desde el principio. Se puede añadir un parámetro opcional, jénova lo guardará en reg2 para ser consultado después.
uso:
return
suma Suma el valor contenido en reg0 al de reg1 si los dos son valores numéricos o los concatena si alguno de ellos no lo es y guarda el resultado en reg2.
uso:
mode0 int
set0 1
mode0 int
set1 3
suma
// ahora tenemos el valor 4 en reg2
resta Resta el valor contenido en reg0 al contenido en reg1, éste valor deberá ser de tipo numérico.
uso:
set0 10
set1 4
resta
// ahora tenemos el valor 6 en reg2
mult Igual que resta pero multiplicando reg0 por reg1.
div Igual que resta pero dividiendo reg0 entre reg1, además guarda el módulo o resto en los flags.
rand Genera un número aleatorio comprendido entre el número contenido en reg0 y el contenido en reg1 y lo almacena en reg2.
uso:
set0 1
set1 100
rand
// guardará un número entre 0 y 100 en el registro2.
Suscribirse a:
Entradas (Atom)






















