January 10, 2012 a las 5:06 pm por Edwin Plauchu · Archivado en Ipad, Programacion
Basicamente este patron, permite personalizar el comportamiento de un “objeto A” evitandonos la necesidad de tener que hacerle una subclase (evitandonos asi ..el clasico estilo de programacion como la hecha en java… ), mediante el uso de otro “objeto B” (un delegado) que realizara el trabajo por el “objeto A”.

Protocolos y Delegados
Un protocolo declara métodos que pueden ser implementados por cualquier clase. Los protocolos no son clases por si mismos. Simplementen definen una interfaz que otros objetos son responsables de implementar. Cuando implementa los métodos de un protocolo en una de sus clases, se dice que su clase se ajusta al protocolo.
Los protocolos son utilizados para especificar la interfaz para objetos delegados. Un objeto delegado es un objeto que actua en nombre de, o coordinandose con, otro objeto. La mjor manera de entender la relación entre protocolos, delegados, y otros objetos es simplemente verlo con un ejemplo.
La clase UIApplication implementa el comportamiento requerido por una aplicación. En lugar de forzarte a hacer una subclase de UIApplication para recibir simples notificaciones sobre el estado actual de la aplicación, la clase UIApplication entrega estas notificaciones llamando a métodos específicos asignados a un objeto delegado. Un objeto que implementa los métodos del protocolo UIApplicationDelegate pueden recibir estas notificaciones y proporcionar una respuesta apropiada.
En Sintesis un protocolo en objetive C sera la forma que tendra una clase de decir “Si alguien quiere trabajar conmigo, debera saber hacer esta serie de tareas”, algunas de caracter obligatorio y otras de caracter opcional.

Con esto, estamos diciendo que cualquier clase que quiera trabajar con el objeto que define este protocolo debe ser capaz de responder al metodo metodoDeInstanciaQueDebeImplementarse
Por parte de la clase que define el protocolo, lo normal es referenciar al objeto que va a cumplirlo como delegado. Es decir, un delegado es un objeto que cumple el protocolo y al que vamos a mandar los mensajes correspondientes.

Con esta nomenclatura le hemos dicho que la variable delegate sera una objeto de cualquier tipo que cumpla con el protocolo MiProtocolo. Es decir, que implemente el metodo medotoDeInstanciaQueDebeImplementarse
January 10, 2012 a las 4:28 pm por Edwin Plauchu · Archivado en Ipad, Programacion
Un Controlador de vista es a menudo el objeto (target) que responde a los controles sobre la pantalla. El patron de diseño Target-Action es quien hace posible que el controller sea conciente de cualquier cambio en la vista.
Los Controladores de vista tienen otras responsabilidades vitales en IPAD tambien…
Administran un conjunto de vistas — Inclullendo la creacion de estas o liberacion de las mismas en situaciones de baja memoria.
Responder al cambio en la orientacion del dispositivo
Creacion de una vista modal –(una ventana hijo de dialogo… al estilo los dialogos en javascript)
January 10, 2012 a las 2:22 pm por Edwin Plauchu · Archivado en Ipad, Programacion

En el universo iPad ( como seran los planetas de ese universo ?… … que mamon), los objetos vista son responsables de la vista en la arquitectura Model-View-Controller architecture.
Una vista es una area rectangular en la pantalla. El contenido de la vista es esa porcion de datos y controles que aparece entre la barra superior y las barra inferiores.

En el framework UIKit, en realidad las ventanas son un especial tipo de vista.
Pero cuales son las responsabilidades de una Vista ?
Las vistas son la principal manera para que nuestras aplicaciones interactuen con los usuarios. Esta interaccion puede sucitarce de 2 maneras:
* Vistas que desplieguen contenido. Por Ejemplo, dibujar animaciones en pantalla. En esencia, el objeto vista desplegara datos del objeto modelo.
* Vistas recogen todo el toqueteo que el usuario hace en la pantalla (los touch events). Los touch events responderan cuando el usuario toque por ejemplo un boton.
La Herarquia de las Vistas
Las vistas y las subvistas crear una gerarquia de vistas. Existen dos maneras de mirar esto “visualmentte (como el usuario percibe esto) y herarquicamente (Como nosotros estructuremos esto).

Premisas de la Gerarquia de vistas en IPAD
* El contenido de la vista es agregado a la ventana como una subvista.
* Vistas agregadas a la subvista … seran sub sub vistas .. y tendran como supervista a la subvista
* Una vista puede tener una (y solo una) supervista y zero o mas supervistas.
* Una vista tiene la capacidad de administrar sus subvistas.
Crear o Modificar una herarquia de vistas puede realizarce mediante el Interface Builder o Programaticamente mediante el UIKit framework, este automaticamente se encargara de todas las relaciones asociadas con las vistas.
Los tipos de Vistas a usar
La clase UIView define las propiedades basicas de una vista. Aunque en la practica se utilizan clases que heredan de esta.
* Container views
-- UIScrollView
-- UITableView
-- UIToolbar
* Controls
-- UIView
-- UIControl
* Display views
-- UIImageView
-- UILabel
-- UIProgressView
-- UIActivityIndicatorView
* Text and Web views
-- UIWebView
-- UITextView
* Alert views and action sheets
-- UIAlertView
-- UIActionSheet
* Navigation views
-- UITabBar
-- UINavigationBar
* The window
January 10, 2012 a las 1:50 pm por Edwin Plauchu · Archivado en Ipad, Programacion
Gestures
Sobre un dispositivo ipad, un gesture es algo que nosotros podemos hacer con los dedos para lograr que algo pase sobre un ipad, como un tap, un drag, y otros. Aqui les muestro como simular gestures usando nuestro raton o teclado.



January 7, 2012 a las 11:01 pm por Edwin Plauchu · Archivado en Programacion
A veces nos interesa que un hilo se quede bloqueado a la espera de que ocurra algún evento, como la llegada de un dato para tratar o que el usuario termine de escribir algo en una interface de usuario. Todos los objetos java tienen el método wait() que deja bloqueado al hilo que lo llama y el método notify(), que desbloquea a los hilos bloqueados por wait(). Vamos a ver cómo usarlo
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hilos;
/**
*
* @author pianodaemon
*/
public class Hilos {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Vaso v = new Vaso();
HiloB b = new HiloB(v);
b.start();
HiloA a = new HiloA(v);
a.start();
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hilos;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author pianodaemon
*/
public class HiloA extends Thread {
Vaso vaso;
public Vaso getVaso() {
return vaso;
}
public void setVaso(Vaso vaso) {
this.vaso = vaso;
}
HiloA(Vaso v) {
this.setVaso(v);
}
public void run() {
this.getVaso().llenar();
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hilos;
/**
*
* @author pianodaemon
*/
public class HiloB extends Thread {
Vaso vaso;
public Vaso getVaso() {
return vaso;
}
public void setVaso(Vaso vaso) {
this.vaso = vaso;
}
HiloB(Vaso v) {
this.setVaso(v);
}
public void run() {
this.getVaso().derramar();
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hilos;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author pianodaemon
*/
public class Vaso {
public synchronized void derramar(){
System.out.println("Empuja");
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(HiloA.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("PLOP");
}
public synchronized void llenar(){
int contador = 0;
while(contador!=5){
contador++;
System.out.println("H20 se sirve en el vaso");
}
this.notify();
}
}
La salida de nuestro programa demo
Empuja
H20 se sirve en el vaso
H20 se sirve en el vaso
H20 se sirve en el vaso
H20 se sirve en el vaso
H20 se sirve en el vaso
PLOP
wait() y notify() como cola de espera
wait() y notify() funcionan como una lista de espera. Si varios hilos van llamando a wait() quedan bloqueados y en una lista de espera, de forma que el primero que llamó a wait() es el primero de la lista y el último es el útlimo.
Cada llamada a notify() despierta al primer hilo en la lista de espera, pero no al resto, que siguen dormidos. Necesitamos por tanto hacer tantos notify() como hilos hayan hecho wait() para ir despertándolos a todos de uno en uno.
Si hacemos varios notify() antes de que haya hilos en espera, quedan marcados todos esos notify(), de forma que los siguientes hilos que hagan wait() no se quedaran bloqueados.
En resumen, wait() y notify() funcionan como un contador. Cada wait() mira el contador y si es cero o menos se queda bloqueado. Cuando se desbloquea decrementa el contador. Cada notify() incrementa el contador y si se hace 0 o positivo, despierta al primer hilo de la cola.
Un símil para entenderlo mejor. Una mesa en la que hay gente que pone caramelos y gente que los recoge. La gente son los hilos. Los que van a coger caramelos (hacen wait()) se ponen en una cola delante de la mesa, cogen un caramelo y se van. Si no hay caramelos, esperan que los haya y forman una cola. Otras personas ponen un caramelo en la mesa (hacen notify()). El número de caramelos en la mesa es el contador que mencionabamos.
Aqui les dejo la siguiente clase… que muestra como hasta una lista puede lanza run notify. Esto solo con la intencion de mostrar que las posibilidades son infinitas
public class MiListaSincronizada
{
private LinkedList lista = new LinkedList();
public synchronized void addDato(Object dato)
{
lista.add(dato);
lista.notify();
}
public synchronized Object getDato()
{
if (lista.size()==0)
wait();
Object dato = lista.get(0);
lista.remove(0);
return dato;
}
}
January 7, 2012 a las 7:19 pm por Edwin Plauchu · Archivado en Programacion
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package crc16;
/**
*
* @author pianodaemon
*/
public class Crc16 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
int ocho = 8;
int[] table = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
byte[] bytes = "1085051000201146587443HG234".getBytes();
int crc = 0x0000;
for (byte b : bytes) {
//int beta_tmp = table[(crc ^ b) & 0xff];
//System.out.println(beta_tmp);
crc = (crc >>> ocho) ^ table[(crc ^ b) & 0xff];
}
System.out.println("CRC16 = " + Integer.toHexString(crc));
System.out.println("CRC16 = " + Integer.toString(crc));
}
}
January 7, 2012 a las 7:18 pm por Edwin Plauchu · Archivado en Programacion
using System;
namespace Plauchu{
public class Crc16{
private int[] table;
public Crc16 (){
this.table = new int[]{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
}
public int obtenerIntegerValueFromCrc16Of(string valor){
int crc = 0x0000;
byte[] bytes = this.convert2BytesArray(valor);
for(int i=0;i<bytes.Length;i++){
byte b = bytes[i];
int alfa_tmp = crc >> 8;
int beta_tmp = table[ (crc ^ b) & 0xff ];
crc = alfa_tmp ^ beta_tmp;
}
return crc;
}
public string obtenerHexaValueFromCrc16Of(string valor){
return String.Format("0x{0:X}", this.obtenerIntegerValueFromCrc16Of(valor) );
}
//Convierte la cadena en un arreglo de bytes
private byte[] convert2BytesArray(string str){
System.Text.UTF8Encoding encoding=new System.Text.UTF8Encoding();
return encoding.GetBytes(str);
}
}
}
January 6, 2012 a las 6:31 pm por Edwin Plauchu · Archivado en Programacion
En un inicio teniamos el Analisis de Transacciones
La aventura de esto inicia en los 70’s. En aquellos dias, un programa de computadora tipico era uns sistema de procesamiento por lotes(hola bacheros chocolateros!). Los datos de entrada por lo general era un fichero contenido en un cinta(tape). Un programa lei datos de un fichero de entrada, una vez que era este procesado, se escribia el resultado en otro fichero secuencial de salida. Aquel archivo a su vez, tambien era procesaro por otro programa y este generaba otra salida que se metia en otro archivo secuencial y asi sucesivamente. En aquellos dias el modelo de un sistema computacional era similiar al de una linea de ensamblaje de carros.
Este modelo mental remarco la esencia “Estructurada” en los 70’s. El padre de los metodos estructurados fue Larry L. Constantine. Su padre coorporativo fue el institutode inventisgaciones de IBM. El mas exitoso defensor de la metodologia estructurada fue Edward Yourdon.
Diagramas de flujo de Datos (DFDs)
El analisis estructurado de este tipo de diagramas demostro la estructura logica de un sistema computacional. Sobre un DFD, un registro dentro de un archivo secuencial
fue conceptualizado como un paquete de datos deslizandoce atravez de una tuberia.
Aqui un ejemplo de un DFD de aquellos dias..

Describir un sistema en aquella manera fue conocido como analisis de Transformacion, cuyo nombre se le debe a el autor del libro Marco’s Structured Analysis and System Specification. El autor de dicho libro tambien describio brevemente un segundo tipo de analisis llamado analisis de Transaccion con el siguiente diagrama…

El autor del libro Marco’s Structured Analysis and System Specification explico las diferencias entre el analisis de transformacion y el analisis de transaccion.. llegando a las siguientes concluciones:
Por su parte Edward Yourdon en aquellos bonitos 70’s tambien expuso su DFD de grafos de lo que es un tipico centro de Transacciones. El cual no es otra cosa si no el diagrama arquetipo de la programacion manejada por eventos que actualmente muchos sistemas computacionales usan.

Edward Yourdon decia… una transaccion inicia cuando “cualquier elemento de datos, control, señal, evento, o cambio de estado” es mandado a el proceso que representa al centro de transacciones.
Un centro de transacciones de un sistema debera tener las siguiente aptitudes:
* obtener y responder a transacciones en una forma cruda
* analizar cada transaccion para determinar su tipo
* despachar en base al tipo de transaccion
* completar el procesamiento de cada transaccion
El Diagrama de Estructuras
Un DFD muestra las funciones logicas que un sistema debe realizar, pero este no dice nada sobre el diseño del programa que ejecutara esas funciones. En analisis y diseño estructura, un diagrama diferente nombrado Diagrama de estructuras fue usado entonces para mostras el diseño del programa. Las cajas son organizadas gerarquicamente, con modulos arriba y abajo.
La conversion de un DFD de transaccion a un diagrama de estructuras quedaria como el siguiente dibujo:

Las Transacciones son obtenidas por le funcion GETTRAN. Una vez obtenida, una transaccion, esta es analizada para determinar su tipo (su codigo de transaccion) y entonces se pasa al centro de transacciones. En ese punto, esta es pasada al modulo dispacher (DISPATCH module) el cual manda esta hacia el modulo que recogera la transaccion de ese tipo.
January 4, 2012 a las 6:59 pm por Edwin Plauchu · Archivado en Programacion
Este programa efectua una simple animacion. La Animacion es completada mediante la creacion de un temporizador, el cual es una llamada a un ActionListener sobre intervalos especificos (cada 35 milisegundos). El listener le habla a la bola… para que esta mueva sus coordenadas un poquito, entonces esta repinta el panel. repaint() indirectamente llama nuestro metodo paintComponent(), entonces este dibujara la bola con las cordenadas actualizadas.

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package principal;
/**
*
* @author pianodaemon
*/
public class BolaRebotadora {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Ventana x = new Ventana();
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package principal;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.*;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
*
* @author pianodaemon
*/
final class BallInBox extends JPanel {
private Timer m_timer; // Timer fires to anmimate one step.
private int m_interval = 35; // Milliseconds between updates.
private Ball m_ball;
public BallInBox(){
setPreferredSize(new Dimension(200, 80));
setBorder(BorderFactory.createLineBorder(Color.BLACK));
this.setM_ball(new Ball(0, 0, 2, 3));
this.setM_timer( new Timer(m_interval, new TimerAction()) );
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // Paint background, border
this.getM_ball().draw(g); // Draw the ball.
}
void setAnimation(boolean b) {
if (b) {
this.getM_timer().start(); // start animation by starting the timer.
} else {
this.getM_timer().stop(); // stop timer
}
}
public Ball getM_ball() {
return m_ball;
}
public void setM_ball(Ball m_ball) {
this.m_ball = m_ball;
}
public Timer getM_timer() {
return m_timer;
}
public void setM_timer(Timer m_timer) {
this.m_timer = m_timer;
}
class TimerAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
getM_ball().setBounds(getWidth(), getHeight());
getM_ball().move(); // Move the ball.
repaint(); // Repaint indirectly calls paintComponent.
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package principal;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
/**
*
* @author pianodaemon
*/
final class PanelPrincipal extends JPanel{
BallInBox m_bb; // The bouncing ball panel
public BallInBox getM_bb() {
return m_bb;
}
public void setM_bb(BallInBox m_bb) {
this.m_bb = m_bb;
}
public PanelPrincipal(){
this.setM_bb(new BallInBox());
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
//... Add Listeners
startButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent ae) {
getM_bb().setAnimation(true);
}
});
stopButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent ae) {
getM_bb().setAnimation(false);
}
});
//... Layout inner panel with two buttons horizontally
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(startButton);
buttonPanel.add(stopButton);
//... Layout outer panel with button panel above bouncing ball
this.setLayout(new BorderLayout());
this.add(buttonPanel, BorderLayout.NORTH);
this.add(this.getM_bb() , BorderLayout.CENTER);
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package principal;
import java.awt.Graphics;
/**
*
* @author pianodaemon
*/
final class Ball {
private final static int DIAMETER = 21;
private int m_x;
private int m_y;
private int m_velocityX;
private int m_velocityY;
private int m_rightBound; // Maximum permissible x, y values.
private int m_bottomBound;
public Ball(int x, int y, int velocityX, int velocityY) {
this.setM_x(x);
this.setM_y(y);
this.setM_velocityX(velocityX);
this.setM_velocityY(velocityY);
}
//Dibuja la bola
public void draw(Graphics g) {
g.fillOval(this.getM_x(), this.getM_y(), DIAMETER, DIAMETER);
}
public void move() {
//... Move the ball at the give velocity.
m_x += m_velocityX;
m_y += m_velocityY;
//... Bounce the ball off the walls if necessary.
if (m_x < 0) { // If at or beyond left side
m_x = 0; // Place against edge and
m_velocityX = -m_velocityX; // reverse direction.
} else if (m_x > m_rightBound) { // If at or beyond right side
m_x = m_rightBound; // Place against right edge.
m_velocityX = -m_velocityX; // Reverse direction.
}
if (m_y < 0) { // if we're at top
m_y = 0;
m_velocityY = -m_velocityY;
} else if (m_y > m_bottomBound) { // if we’re at bottom
m_y = m_bottomBound;
m_velocityY = -m_velocityY;
}
}
//Establece los limites de hasta donde puede llegar
//la bola en el cuadrante I del plano cartesiano
//De 2 dimensiones
public void setBounds(int width, int height) {
this.setM_rightBound(width - DIAMETER);
this.setM_bottomBound(height - DIAMETER);
}
public void setPosition(int x, int y) {
this.setM_x(x);
this.setM_y(y);
}
public int getDiameter() { return DIAMETER;}
public int getM_velocityX() {
return m_velocityX;
}
public void setM_velocityX(int m_velocityX) {
this.m_velocityX = m_velocityX;
}
public int getM_bottomBound() {
return m_bottomBound;
}
public void setM_bottomBound(int m_bottomBound) {
this.m_bottomBound = m_bottomBound;
}
public int getM_rightBound() {
return m_rightBound;
}
public void setM_rightBound(int m_rightBound) {
this.m_rightBound = m_rightBound;
}
public int getM_velocityY() {
return m_velocityY;
}
public void setM_velocityY(int m_velocityY) {
this.m_velocityY = m_velocityY;
}
public int getM_x() {
return m_x;
}
public void setM_x(int m_x) {
this.m_x = m_x;
}
public int getM_y() {
return m_y;
}
public void setM_y(int m_y) {
this.m_y = m_y;
}
}
import javax.swing.JFrame;
/**
*
* @author pianodaemon
*/
final class Ventana extends JFrame{
/** Panel principal con un lienzo de dibujo y un botón para cambiar el
* dibujo en el lienzo */
private PanelPrincipal panel = null;
public PanelPrincipal getPanel() {
return panel;
}
public void setPanel(PanelPrincipal panel) {
this.panel = panel;
}
public Ventana(){
this.setPanel(new PanelPrincipal());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.add (panel);
this.setSize(300, 250);
}
}
January 4, 2012 a las 5:22 pm por Edwin Plauchu · Archivado en Programacion
Disculpen el anglisismo, pero el game loop es donde la magia sucede. La mayoria del tiempo que el usuario gastara interactuando con su juego estara dentro del game loop.
Cada vez que corre el game loop podran ser ejecutadas cualquiera de las siguientes acciones:
* Retornar una entrada del usuario, como el pulsado de un botones o flechas direccionales.
* Recepcion de entradas generadas por oponentes (computadora o humano).
* Actualizar las posiciones del jugador y las de los enemigos y el estado de sobrevivencia.
* Arranque y parada de los efectos de sonido o musica de fondo.
* Dibujar el mundo con las posiciones actualizadas y el estado de los jugadores.
Estas acciones son a menudo completadas muchas veces en un segundo y en ocaciones en otros intervalos. El ojo humano tiene un limite… como el conocido numero de cuadros que este puede ver. El repintado de la pantalla dependera bastante de las condiciones del juego.
Veamos un juego bastante tonto como ejemplo, que de a entender el GameLoop
Mi ejemplo es la Bola que cambia de color a lo loco….
Este juego no tiene interaccion con el usuario… salvo que este lo arranca… Pero aqui podemos apreciar bastante bien el gameloop.
Como este genera el mundo… y lo repinta cada que es necesario.

package principal;
/**
*
* @author pianodaemon
*/
public class Principal {
public static void main(String[] args){
Window x = new Window();
}
}
/*
* Window.java
*/
package principal;
import javax.swing.JFrame;
/**
*
* @author pianodaemon
*/
public class Window extends JFrame{
private PanelPrincipal panel = new PanelPrincipal();
public Window(){
this.setSize(250, 250);
this.setVisible(true);
this.add (panel);
}
}
package principal;
/*
* PanelPrincipal.java
*/
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Line2D.Double;
import javax.swing.JButton;
import javax.swing.JPanel;
/**
* Panel con un Lienzo.
*/
public class PanelPrincipal extends JPanel{
/** El lienzo de dibujo */
private Lienzo lienzo = new Lienzo();
/**
* Constructor por defecto. Pone el lienzo y el botón en el panel y
* hace que se dibuje la primera línea.
*/
public PanelPrincipal()
{
ponComponentes();
}
/**
* Pone el lienzo y el botón en el panel.
*/
private void ponComponentes()
{
this.add (lienzo);
}
}
package principal;
/*
* Lienzo.java
*/
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Line2D;
import java.util.Random;
/**
* Clase que hereda de Canvas y sirve para dibujar una linea.
*/
public class Lienzo extends Canvas{
Color randomColor; //Color aleatorio
Random rnd; //Generador de números aleatorios
int red, green, blue; //Variables para asignar valores al RGB del color
int diameter; //Diámetro del círculo
/**
* Constructor. Hace que el tamaño del canvas sea 100x100 pixels.
*/
public Lienzo()
{
this.setSize (200, 200);
rnd = new Random(); //Se crea el objeto Random
diameter = 150; //Asigna un valor al diámetro del círculo
}
/**
* Dibuja la última línea que se le haya pasado.
*/
public void paint(Graphics g)
{
red = rnd.nextInt(256);
green = rnd.nextInt(256);
blue = rnd.nextInt(256);
//Creamos el nuevo color
randomColor = new Color(red, green, blue);
//Establece el nuevo color para pintar el círculo
g.setColor(randomColor);
//Dibuja el círculo
g.fillOval(getWidth() / 2 - diameter / 2, getHeight() / 2 - diameter / 2,
diameter, diameter);
g.setColor(Color.black);
try{
//El método sleep() de la clase Thread pausa
//la ejecución del applet
Thread.sleep(160);
} catch(Exception ex){
System.out.println("Error en " + ex.toString());
}
repaint(); //Llama de nuevo al método paint()
}
}