martes, 7 de julio de 2015

Game Of Balls el juego de reflejos más adictivo del Universo

He desarrollado un nuevo juego!! Se trata de "Game Of Balls"

Game of Balls es el juego de reflejos más simple y adictivo del universo.
Cada día la puntuación del récord diario se pone a cero! Todos tenéis la oportunidad de ser el mejor del día o de batir el récord del mundo!
Jugar es muy fácil, las partidas duran 60 segundos en los que vuestros reflejos y velocidad con los dedos se ponen a prueba.
En el selector de arriba aparece una bola de un color, debéis dar con el dedo a las bolas de ese color todo lo rápido que podáis. Cuando se acaban aparece otro color y debéis hacer lo mismo.
Cada bola es un punto, consigue todas las que puedas antes de que acabe el tiempo.
Lleva al límite tus reflejos y conviértete en el mejor jugador!
No importa tu edad sólo importan tus habilidades.

Aquí tenéis el enlace a play store:
https://play.google.com/store/apps/details?id=game.iwok.com.gameofballs

Muy pronto lo publicaré para IOS!!
Aquí os dejo el vídeo, espero que lo disfrutéis.


Para cualquier pregunta relacionada con el desarrollo o publicación ya sabéis que podéis consultarme!

Un saludete a todos!

lunes, 2 de febrero de 2015

Diario de un developer

En año nuevo me propuse un reto. Tenía un proyecto pensado desde hacia tiempo, pero no había tenido el valor de intentar hacerlo, básicamente por sus dimensiones.
Estoy desarrollando como un loco, y voy publicando en un blog diario de desarrollo, lo que hago cada día, con un tono menos serio de lo que se esperaría de un blog técnico!


El blog está teniendo bastantes más visitas de las que esperaba!

El tema es:
1 developer, 1 proyecto enorme, 60 días de loco desarrollo, sin dinero, solo tiempo.

O me hará rico o más pobre!

Espero que lo disfrutéis y no dudéis en comentar en el blog, preguntar. También podéis seguirme en twitter: @iwoklocoBlog



miércoles, 5 de noviembre de 2014

Sushi Dragon

Hola a todos!
Os quiero presentar Sushi Dragon! El juego para Android que he creado.
Durante un año estuve desarrollando mi propio engine 2D sobre el SDK de android basado en OpenGL ES 1.0.
Decidí hacerlo completamente de cero, incluso implementé el sistema detector de gestos sobre las funciones básicas de la SDK de android.
Como primer proyecto mostrando las funcionalidades de mi engine Iwok2D, presento Sushi Dragon. 
Un juego para que los más pequeños se diviertan cuidando, disfrazando y jugando con un pequeño dragón azul comedor de sushi!
Este es el enlace para descargarlo: Sushi Dragon en Play Store!


Espero que os guste, y que os animeis a probarlo!
Para aquellos que tengáis dudas sobre el proceso de desarrollo, diseño, distribución, inclusión de publicidad, etc. No dudeis en preguntar!
Un saludo a todos!

Aquí os dejo el enlace a mi portal de desarrollo de juegos:


martes, 23 de septiembre de 2014

CSS: Bordes redondeados CSS

Buenas a todos!
Para tener divs con los bordes redondeados compatibles con todos los navegadores la clase css contendrá los siguientes atributos:

-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;

Div con los bordes redondeados!

10px lógicamente hace referencia al radio.

Un saludete!

CSS: Fondo transparente con CSS

Buenas a todos!

Esta es una solución cross browser, para tener fondos transparentes en CSS.
El color lo indicamos con los valores rgb, el último parámetro de rgba indica el porcentaje de opacidad.

div.bg_opacity{
    background: rgb(0, 0, 0) transparent;
    background: rgba(0, 0, 0, 0.6);
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
}

Un saludete!

miércoles, 17 de septiembre de 2014

Apuntes de C++: Sobrecarga de funciones, constructores de copias y argumentos implícitos

Buenas a todos!
El siguiente post, continua con los apuntes sobre C++, esta vez resumo un poco el tema de la sobrecarga de funciones contructoras, los constructores de copias y los argumentos implícitos. Finalizo con algo curioso, obtener punteros que apunten a funciones sobrecargadas.

Las funciones constructoras de clase se pueden sobrecargar, pero las funciones destructoras no.


class Persona{
    int x;
public:
    Persona(){ x=0; }       //Constructor sin inicializador
    Persona(int n){ x=n; }  //Constructor con inicializador
};

En el código anterior tenemos la función constructora sobrecargada.
Sin la versión de constructor sin inicializador, no podría inicializarse un array dinámico, y se generaría un error en tiempo de compilación.

Persona *persona;
persona = new Persona[20];

Con el constructor sin inicializador el array dinámico persona, contiene 20 objetos de tipo persona, con x = 0.

Cuando se pasa un objeto a una función o esta lo devuelve pueden presentarse dificultades, ya que automáticamente se generan copias del objeto.

Al pasar un objeto a una función se realiza una copia bit a bit de ese objeto. Hay cosas que no deseamos que sean idénticas en la copia, como por ejemplo si el objeto original apunta a la memoria asignada por un puntero, la copia apuntará a la misma dirección de memoria, y la copia podría alterar la memoria original.

Cuando una función devuelve un objeto, normalmente el compilador generará un objeto temporal que mantiene una copia del valor devuelto por la función. Esta acción es automática y no controlable.
Este objeto desaparece al devolver su valor y al desaparecer llama a su función destructora.

Para evitar estos problemas se puede definir un "constructor de copias", un tipo especial de función constructora sobrecargada.

Situaciones en las que se aplica un constructor de copias

Los constructores de copias sólo se aplican a situaciones de inicialización, no de asignación.
Hay tres situaciones de inicialización típicas:
- Se emplea un objeto para inicializar otro en una declaración.
myclass x = y;
- Se pasa un objeto como parámetro a una función.
funcionX(y);
- Se crea un objeto temporal al devolver un objeto por una función.
y = funcionX();

class Persona{
    int x;
public:
    Persona(){ x=0; }       //Constructor sin inicializador
    Persona(int n){ x=n; }  //Constructor con inicializador
    Persona(const Persona &obj){…}//Constructor de copias
};

Argumentos implícitos

Usar argumentos implícitos es una forma abreviada de sobrecarga de funciones.
void f(int a = 0, int b = 0);
La función anterior emplea como argumentos implícitos los parámetros a y b.
Este tipo de declaración permite llamar a la función f de las siguientes formas:

f();    //a=0, b=0
f(5);   //a=5, b=0
f(5,2); //a=5, b=2

No hay forma de dar valor por defecto a 'a' y especificar 'b'.
Los argumentos implícitos deben ser constantes o variables globales.

Búsqueda de la dirección de una función sobrecargada

Igual que en C es posible asignar la dirección de una función a un puntero y acceder a la misma a través del puntero:

p = zap;  //donde tenemos zap();

Para obtener la dirección de una función sobrecargada, es el modo de declarar el puntero el que determina la dirección de la función sobrecargada.

void space(int count);
void space(int count, char ch);
main(){
    void (*fp1)(int);   //puntero a una función void con un parámetro int
    void (*fp2)(int)(char);
    
    fp1 = space;    //void space(int count);
    fp2 = space;    //void space(int count, char ch);
    
    fp1(22);
    fp2(30, 'x');
}


En el siguiente post, continuaré con la sobrecarga de operadores.
Un saludo a todos!


domingo, 7 de septiembre de 2014

Apuntes de C++ : Arrays y punteros

Continuando con los resúmenes de mis apuntes del libro "C++ guia de autoenseñanza" de Herbert Schildt, en este post trataré los Arrays, los punteros y las referencias.

Cómo crear un array

int lista[20];
Esta línea crea un array de 20 elementos de tipo entero.

Para crear un array de objetos de una clase concreta, se emplea la misma sintaxis:

class Nave_espacial{
    int r;
    int g;
    int b;
public:
    Nave_espacial(int r, int g, int b);
    void setColor(int r, int g, int b);
};

void Nave_espacial::setColor(int r, int g, int b){...}

main(){
    Nave_espacial naves[20];
    naves[0].setColor(255, 0 , 0);  
}

Creamos un array para 20 objetos de tipo Nave_espacial y modificamos el color de la primera nave de la lista.

Nave_espacial naves[2] = { Nave_espacial(1,2,3) ,  Nave_espacial(4,5,6) };

Este tipo de inicialización del array, permite llamar a las funciones constructoras de cada uno de los objetos del array pasándoles los parámetros que sean necesarios.

Punteros a objetos


class Muestra{
     int id, valor;
public:
     Muestra(int _id, int _valor){ id = _id; valor = _valor; }
     int getId(){ return id; }
     int getValor(){ return valor; }
};

main(){
     int i;
     Muestra muestras[4] = {
          Muestra(0, 20),
          Muestra(1, 23),
          Muestra(2, 21),
          Muestra(3, 23)
     };
     Muestra *m;
     m = muestras;

     for(i=0; i<4; i++){
          cout << m->getValor() << " , ";
          m++; 
     }
}

Creamos un puntero m para apuntar a objetos de la clase Muestra, y cogemos la dirección del array.
Cuando se incrementa el puntero, este apunta al próximo objeto del array.
Para emplear las funciones miembro de los objetos se emplea el operador ->.

Uso de new y delete

En C la asignación de memoria dinámica se realizaba mediante malloc() y la memoria asignada se liberaba utilizando free(). Estas funciones estándar siguen siendo válidas en C++.
C++ proporciona un método más seguro para asignar memoria y liberar memoria, new y delete.

Muestra *m;
m = new Muestra(2, 40);
delete m;

Creamos un puntero para objetos de una clase en concreto.
new nos devuelve un puntero a la memoria asignada dinámicamente, que es lo suficientemente grande como para contener el objeto de la clase.
delete devuelve la memoria cuando ya no se necesita.

Si no hay memoria disponible para asignar, new devuelve un puntero nulo.
Solamente debe llamarse delete con punteros obtenidos previamente mediante new. En caso contrario, se bloquea el sistema de asignación, interrumpiéndose el programa.

new asigna automáticamente la memoria necesaria para albergar un objeto del tipo especificado, así que no es necesario emplear sizeof para calcular el número de bytes requeridos.
Tanto new como delete pueden sobrecargarse permitiendo que el programador cree a su medida su propio sistema de asignación de memoria.

m = new Muestra[10];

El puntero m apuntará a la primera posición de un array de 10 objetos de clase Muestra.
Para eliminar un array asignado dinámicamente, se emplea la siguiente instrucción:

delete []m;

Así el compilador llama a la función destructora para cada elemento del array, y m no se libera en múltiples ocasiones, se libera sólo una vez.

Referencias: pasar parámetros por referencia a una función

K = 10;
void sumarK(int *n);

void sumarK(int *n){
    *n = *n + K;
}

main(){
    int i = 5;
    sumarK(&i);
    cout << "Valor de i = " << i;
}

Por defecto, C++ pasa los parámetros por valor, lo que significa que realiza una copia de los mismos y que si alteramos su valor dentro de las funciones, la variable original que se ha pasado a la función no se ve afectada.
En este ejemplo la función sumarK(int *n) recibe como parámetro un puntero a un entero, lo que significa que cuando realizamos la llamada debemos pasar como parámetro la dirección de la variable entera, para coger dicha dirección o referencia, empleamos el operador &i.

Al hacer esto la función f trabaja directamente con la variable original, ya que altera el valor contenido en la dirección apuntada por el puntero.

En C la definición de paso por referencia sólo puede hacerse de la anterior forma, pero en C++ puede automatizarse para simplificarse el paso por referencia:


K = 10;
void sumarK(int &n);

void sumarK(int &n){
    n = n + K;
}

main(){
    int i = 5;
    sumarK(i);
    cout << "Valor de i = " << i;
}

Simplemente es necesario añadir el operador de dirección al declarar la función, &n.
Hecho esto el compilador ya sabe que realmente cuando se haga la llamada sumarK(i) lo que está pasando como parámetro es la dirección de la variable i.
Y del mismo modo tampoco hace falta indicar dentro de la implementación de la función, que n es un puntero.

Importante: no se pueden modificar las direcciones a las que apunta una referencia.

Pasar parámetros por referencia es la mejor forma de evitar los problemas asociados con la copia de argumentos, que al llamar a sus funciones destructoras pueden perjudicar partes del programa.

Una referencia no es un puntero. Cuando se pasa un objeto por referencia su operador de acceso a atributos y funciones miembro, es el punto "." y no la flecha "->".

Devolución de referencias

Una función puede devolver una referencia. Y podemos asignar directamente valores a la dirección de dicha referencia, es decir, una función puede estar en el lado izquierdo de una asignación.
El siguiente ejemplo es una locura, para los que nunca han trabajado con punteros o están muy acostumbrados a lenguajes como Java.
Vamos a crear una clase Array, para almacenar arrays de enteros.
Y en la función main vamos a hacer que las posiciones 2 y 3 del array contengan los valores 4 y 30:


class Array(){
     int size;
     int *set;
public:
     Array(int _size);
     int &put(int i);
     int get(int i);
};

Array::Array(int _size){
     set = new int[_size];
     size = _size;
}

int &Array::put(int i){
     if(!(i<0 || i>=size)) return set[i]; //devuelve una referencia a set[i]
}

int Array::get(int i){
     if(!(i<0 || i>=size)) return set[i]; //devuelve el entero contenido en set[i]
}

main(){
     Array a(20);
     a.put(2) = 4;
     a.put(3) = 30;
}     

Para que una función devuelva una referencia debemos poner el operador & delante del nombre de función.
Una vez hemos indicado esto automáticamente el compilador sabe que debe devolver la dirección de set[i] y no el valor que contiene.

Una referencia no puede ser referenciada.
No pueden crearse arrays de referencias.
Las referencias son similares a los punteros, pero no son punteros.

Hasta aquí la segunda parte de los apuntes de C++.
Espero que estos resúmenes os sirvan de "referencia" y os sean de utilidad!
Un saludo a todos!!