Libro de simpleJ disponible en Internet

Anuncio | Programación con simpleJ | simpleJ

El libro ¡Descubre cómo se hace un videojuego! ya está a la venta por Internet en formato electrónico (PDF).

Lo puedes comprar en http://www.lulu.com/content/799370.


Support independent publishing: buy this e-book on Lulu.

como mantener los valores en un arreglo

yo estoy creando un juego, utilizo un arreglo de ambientes en donde almaceno mis sprites, en el juego voy modificando los valores de la posicion de cada sprite para que la imagen valla cambiando de posicion, pero el problema es que como modifico los valores se quedan asi, y yo necesito que se devuelva a su valor original, ya intente igualando arreglos y trabajando con el segundo pero devido a que tien la misma referencia se modifica, y ya cree uno nuevo para sean independientes pero modifico uno y se modifican los dos ¿como puedo hacer que mi arreglo de ambientes después de modificarlo regrese a tener los mismo valores que cuando lo declaro?

Crear nuevos arreglos

Puedes lograr lo quieres haciento esto:

var datos;

initDatos() {
   datos = [1, 10, 30, 40];
}

Cada vez que ejecutes el procedimiento initDatos() se va a crear un nuevo arreglo que se asigna a la variable datos.

hacer varios procedimientos

mago en simple j habra una manera de que la consola me ejecute varios procedimientos simultaneos pero independientes (aparte del vbi) uos de otros ya que necesito poder hacer eso para que al presionar una flecha mis sprites se sigan moviendo y no se detengan pero tambien que suene música.
y si quiero componer una cancion que me recomiendas que use notas musicales o audio avanzado ya que quiero componer una cancion a mi juego para que suene al mismo tiempo que valla jugando y que no interfiera con este.

Usa el sfi()

Para el audio lo ideal es usar el procedimiento sfi(). En la versión 1.1 de simpleJ viene un "preview" del juego Rogue, ahí puedes ver cómo se hace lo que quieres hacer.

notas musicales

como puedo saber que frecuencia equivale a cada nota musical para componerla, hay un intervalo que existe para cada nota musical o simplemente las tengo que ir sacando yo midiendo la agudes y la gravedad de los sonidos usando los sonidos con frecuencia attack etc.

Frecuencias

Para convertir una frecuencia en Hz a un valor para el procedimiento setSoundFrequency, lo que haces e multiplicar el valor en Hz por 23.77723356. Dentro del proyecto Rogue hay un archivo "audio.sj" donde puedes ver cómo crear un ambiente "notas" en donde están almacenados los valores que hay que pasar a setSoundFrequency para generar cada nota.

Lo puedes usar asi: setSoundFrequency(canal, notas["C4"]);

Comentario: notas["C4"], cuando notas es un ambiente, es lo mismo que notas.C4.

metodo sfi();

y si yo quisiera poner una cancion compuesta en el metodo sfi como le tengo que hacer ya que si la pongo en un metodo como este si la reproduce
frecuencias() {
setSoundFrequency(0, 18642);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 16608);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 16000);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 16608);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 22168);
soundOn(0);
pause(0.5);
setSoundFrequency(0, 23486);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 22168);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 18642);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 22168);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 24884);
soundOn(0);
pause(0.5);
setSoundFrequency(0, 27928);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 23486);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 24884);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 24884);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 37284);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 33216);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 31352);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 33216);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 37284);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 33216);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 33216);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 31352);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 33216);
soundOn(0);
pause(0.2);
setSoundFrequency(0, 47000);
soundOn(0);
pause(0.2);

}
setSoundDecay(0, 500);
frecuencias();

pero al meterla en el metodo sfi no me la reproduce como tal, ¿que debo hacer para poder lograr que el metodo sfi me la reprodusca tal y como esta arriba independientemente de los demas procesos del juego?

Ya viste?

Ya viste la manera que emplea el juego de Rogue para hacer eso?

Un ejemplo más sencillo

Aquí está un ejemplo sencillo de cómo poner tu melodía en el sfi, junto con un procedimiento vbi que muestra una bola rebotando en la pantalla:

var melodia = [
  {frequency: 18642, pausa: 2},
  {frequency: 16608, pausa: 2},
  {frequency: 16000, pausa: 2},
  {frequency: 16608, pausa: 2},
  {frequency: 22168, pausa: 12},
  {frequency: 23486, pausa: 2},
  {frequency: 22168, pausa: 2},
  {frequency: 18642, pausa: 2},
  {frequency: 22168, pausa: 2},
  {frequency: 24884, pausa: 12},
  {frequency: 27928, pausa: 2},
  {frequency: 23486, pausa: 2},
  {frequency: 24884, pausa: 2},
  {frequency: 24884, pausa: 2},
  {frequency: 37284, pausa: 2},
  {frequency: 33216, pausa: 2},
  {frequency: 31352, pausa: 2},
  {frequency: 33216, pausa: 2},
  {frequency: 37284, pausa: 2},
  {frequency: 33216, pausa: 2},
  {frequency: 33216, pausa: 2},
  {frequency: 31352, pausa: 2},
  {frequency: 33216, pausa: 2},
  {frequency: 47000, pausa: 2}
];

var nota = 0;

var pausa = 0;

setSoundDecay(0, 500);

sfi() {
  if (pausa > 0) {
    pausa = pausa - 1;
    return;
  }
  setSoundFrequency(0, melodia[nota].frequency);
  soundOn(0);
  pausa = melodia[nota].pausa;
  nota = nota + 1;
  if (nota == length(melodia))
    nota = 0;
}

var x = 10;
var dx = -2;
var y = 16;
var dy = 2;

setSmallSpriteImage(0, 20);

vbi() {
  x = x + dx;
  y = y + dy;
  if (x == 0 || x == 248)
    dx = -dx;
  if (y == 0 || y == 184)
    dy = -dy;
  putSpriteAt(0, x, y);
}

metodo source

si deseo usar el metodo source y que las variables me las ponga en mi estado global al igual que mi método sfi(), que devo de poner de argumento en el metodo source.

source(filename,env)

filename va el nombre del archivo y por cierto entre comilllas pero si quiero que las variables me las guarde en mi estado global para que me las ejecute y las use que le pongo en ENV y va entre comillas?

Lo más sencillo

Lo más sencillo si quieres usar source es emplearlo de esta manera (asumiendo que tu código de sfi y todo lo relacionado con el audio está dentro de un archivo llamado audio.sj):

source("audio.sj");

Eso lo pones para que se ejecute dentro de tu ambiente global (es decir que no lo pones dentro de un procedimiento).

metodo source

si lo puse asi pero hay un problema, mi juego consta de cuatro estados metidos en un case, si lo pongo antes de todo el case (en el estado global), me lo ejecuta de inmediato, y lo que yo quiero hacer es que el audio suene cuando mi juego esta en el estado tres por lo tanto si lo pongo en el case 3 no suena, y si lo meto en el procedimiento de mi juego del estado tres que es interaccion, tampoco se escucha, la unica manera de que se escuche es sacandolo del case y metiendolo desde un principio en el estado global, pero yo necesito que el audio suene cuando mi estado de mi juego sea 3 mas no al principio, o hay una manera de hacer que mi archivo audio.sj suene pero cuando yo este en mi case 3 osea en mi estado de interaccion?
porque ya le he intentado y no puedo.

Usa una variable

Usa una variable para indicar cuando debe sonar la música:


var suena = false;

prendeMusica() {
  nota = 0;
  suena = true;
}

apagaMusica() {
  suena = false;
}

sfi() {
  if (!suena)
    return;
  if (pausa > 0) {
    pausa = pausa - 1;
    return;
  }
  setSoundFrequency(0, melodia[nota].frequency);
  soundOn(0);
  pausa = melodia[nota].pausa;
  nota = nota + 1;
  if (nota == length(melodia))
    nota = 0;
}


vbi();

mago quisiera saber una ultima cosa, si empleo el metodo vbi() para mover mis sprites, mira los tengo fuera de la pantalla por el lado derecho, luego pasan por mi pantalla, y los saco de ella poniendolos hasta el lado izquierdo, lo que quisiera saber es que si hay una forma de que cuando acabe mi arreglo de pasar todos los sprites.

Poder terminar (por asi decrilo el vbi(); y que cuando este en mi estado de juego 3 de nuevi me lo volviera a cargar como si se reinicializara para que vuevan a pasar como la primera ves. ya que a la segunda ves mis sprites ya no pasan y no acaba el vbi();
por lo tanto no puedo usarlo nuevamente.
a y gracias por todo ya que me ha servido para entenderle mejor a simplej.

Un ejemplo

No me quedó claro cual es tu problema... Puedes darme un ejemplo, sencillo, del código?

ejemplo

mira mi codigo es este:
flechas2=[
{pixeles: flechaizbri, x: posxflecha1, vx: 0,posiciony: 18},
{pixeles: flechaarrbri, x: posxflecha2, vx: 0, posiciony: 18},
{pixeles: flechaabbri, x: posxflecha3, vx: 0, posiciony: 18},
{pixeles: flechaderbri, x: posxflecha4, vx: 0, posiciony: 18},
{pixeles: flechaizinter, x: posxflecha1, vx: velocidad, posiciony: 50,pantalla:1},
{pixeles: flechaderinter, x:posxflecha4, vx: velocidad, posiciony:66,pantalla:1},
{pixeles: flechaabinter, x:posxflecha3, vx: velocidad, posiciony:82,pantalla:1},
{pixeles: flechaarrinter, x: posxflecha2, vx: velocidad, posiciony:98,pantalla:1},
{pixeles: flechaabinter, x: posxflecha3, vx: velocidad, posiciony: 114,pantalla:1}
];
un arreglo de ambientes donde contiene cada uno de mis sprites; en total son 140 sprites, los cuatro primeros son moviles, y los demas tienen velocidad para que se muevan.
en escencial estos son mis movimientos en el juego,
ahora, la música entra aqui en este estado de mi juego que es interaccion,de fondo y ya se la meti con sfi(); al mismo tiempo en este estado entran mis sprites de uno por uno moviendose.
uso tambien el proceso global para mover o sumar bonus.
bueno mis sprites los necesito mover con el metodo vbi(); y es este:

vbi(){
  if (!mueve)
    return;
   for(var i=4;i<limite;i++){
      if(flechas[i].pantalla==0){
         putSpriteAt(i,flechas[i].x,flechas[i].posiciony);
         flechas[i].posiciony=flechas[i].posiciony+flechas[i].vx;
      }
      if(flechas[i].pantalla>0){
         putSpriteAt(i,256,flechas[i].posiciony);
         flechas[i].posiciony=flechas[i].posiciony+flechas[i].vx;
         
      }
      if(flechas[i].pantalla<0){
         putSpriteAt(i,-2,flechas[i].posiciony);
         flechas[i].posiciony=flechas[i].posiciony+flechas[i].vx;
      }
      if (flechas[i].posiciony <= -16){
          flechas[i].posiciony = 192;
          flechas[i].pantalla--;
      }        
      if(deltaarreglo<length(flechas)){
         if(flechas[nuevaflecha].pantalla<0){
            flechas[nuevaflecha].x=0;
            flechas[nuevaflecha].posiciony=0;
            flechas[nuevaflecha].pantalla=0;
            setLargeSpriteImage(nuevaflecha, flechas[nuevaflecha+28].pixeles);
            flechas[nuevaflecha].x=flechas[nuevaflecha+28].x;
            flechas[nuevaflecha].posiciony=flechas[nuevaflecha+28].posiciony;
            flechas[nuevaflecha].pantalla=flechas[nuevaflecha+28].pantalla;
            nuevaflecha++;
            deltaarreglo++;
         }
      }
   }
}

primero checa si esta mi juego en estado interaccion para moverlos.
luego lo que dice pantalla es la posicion en la que estan cunado es positivo, estan afuera de la pantalla del lado derecho, cuando es cero son visibles en la pantalla, y cuando es negativo se le asigna un nuevo sprite.
todo esto funciona bien la primera ves, pero yo quiero que cuando mi estado de juego ya no sea tres(termine la interaccion), de alguna manera reiniciar el vbi();como la primera vez que uno juega para que vuelvan a aparecer, ya que no aparecen mis sprites, talves porque es un ciclo infinito el de mis sprites que estan dando vueltas en la izquierda; y lo que yo quiero saber es mas o menos lo pueda finalizar.
por cierto la musica si puede utilizar muchas veces ya que cuando acaba se repite pero el metodo vbi en mi juego nunca acaba.

ejemplo continuacion2

primero checa si esta mi juego en estado interaccion para moverlos.
luego lo que dice pantalla es la posicion en la que estan cunado es positivo, estan afuera de la pantalla del lado derecho, cuando es cero son visibles en la pantalla, y cuando es negativo se le asigna un nuevo sprite.
todo esto funciona bien la primera ves, pero yo quiero que cuando mi estado de juego ya no sea tres(termine la interaccion), de alguna manera reiniciar el vbi();como la primera vez que uno juega para que vuelvan a aparecer, ya que no aparecen mis sprites, talves porque es un ciclo infinito el de mis sprites que estan dando vueltas en la izquierda; y lo que yo quiero saber es mas o menos lo pueda finalizar.
por cierto la musica si puede utilizar muchas veces ya que cuando acaba se repite pero el metodo vbi en mi juego nunca acaba.

Un procedimiento init()

No me queda clara tu descripción de lo que hace tu procedimiento vbi, sobretodo que la descripción no parece corresponder a lo que está programado en el código :)

Pero si tú dices que eso te está funcionando correctamente, entoces voy a asumir que hace lo que tu quieres.

Si entendí bien tu problema, lo que necesitas es que la siguiente vez que pases al estado 3 tus sprites regresen a como estaban al iniciar el juego. Para hacer eso basta con definir un procedimiento init(), como este:

init() {
  flechas2=[
    {pixeles: flechaizbri, x: posxflecha1, vx: 0,posiciony: 18},
    {pixeles: flechaarrbri, x: posxflecha2, vx: 0, posiciony: 18},
    {pixeles: flechaabbri, x: posxflecha3, vx: 0, posiciony: 18},
    {pixeles: flechaderbri, x: posxflecha4, vx: 0, posiciony: 18},
    {pixeles: flechaizinter, x: posxflecha1, vx: velocidad, posiciony: 50,pantalla:1},
    {pixeles: flechaderinter, x:posxflecha4, vx: velocidad, posiciony:66,pantalla:1},
    {pixeles: flechaabinter, x:posxflecha3, vx: velocidad, posiciony:82,pantalla:1},
    {pixeles: flechaarrinter, x: posxflecha2, vx: velocidad, posiciony:98,pantalla:1},
    {pixeles: flechaabinter, x: posxflecha3, vx: velocidad, posiciony: 114,pantalla:1}
  ];
  nuevaFlecha = ...
  deltaArreglo = ...
}

Y llamas a ese procedimiento cada vez que pases al estado 3 para que todas esas variables vuelvan a tomar sus valores de inicio.

vbi();??

buenas noches porfavor me podrias decir que funcion cumple vbi();??
porfavor!
gracias!

La función vbi()

simpleJ emula el hardware de una consola sencilla de videojuegos. En ese hardware simulado la pantalla se redibuja 25 veces por segundo. El momento ideal para modificar el contenido de la pantalla (tiles, sprites, etc), en una animación, es justo en el instante cuando se terminó de dibujar la pantalla y antes de que se vuelva a dibujar otra vez.
En las televisiones reales, el intervalo entre que se termina de dibujar una pantalla y se empieza a dibujar la siguiente se llama "Vertical Blank". Las consolas de videojuegos tienen circuitos que le pueden mandar una interrupción al procesador cada vez que empieza el vertical blank, para que sepa que ese es un buen momento para cambiar el contenido de la pantalla. A esa interrupción se le conoce como "Vertical Blank Interrupt" (VBI).
Dentro de simpleJ también se simula el VBI. Si defines en tu programa una función llamada vbi(), esta se va a ejecutar automáticamente 25 veces por segundo (cada vez que se termina de dibujar la pantalla).

ola

otro favor alguien me podria decir como se hacen los disparon en simple j?
please!