Necesito que esto sea más preciso

Started by La momia que fuma, November 02, 2009, 12:47:58 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

La momia que fuma

Para el concurso de Wiz estoy rescatando una idea que use en uno de mis primeros juegos, controlar el salto de un personaje con el ratón, indicandole en que dirección debe saltar con este (La idea es que el lugar donde apuntas se convierta en el punto álgido del salto a partir del cual empiezas a descender). El caso es que todo esto lo tenía ya solucionado, pero para este proyecto, a diferencia del anterior, necesito más precisión, a cortas distancias va bastante bien, pero cuanto mas grande es el salto (o sea, cuanto mas lejos haces click con el ratón), mas se desvía este del punto que le marcas...

He probado con resolution (en el codigo que os pongo ahora mismo lo deje a 1, la resolution normal, porque aumentandola solo conseguia que fuese la "gravedad" mas despacio pero con los mismos fallos) y usando floats para tener mas precisión (De ahi las variables fx y fy) pero nada, que sigo en las mismas (o alguna de las soluciones es válida pero estoy haciendo algo mal...)

Pues nada, a ver si a vosotros se os ocurre algo, tampoco necesito que sea precisión pixel-perfect pero con el tipo de juego que quiero hacer y poniendome en el lugar del jugador, nada me reventaría mas que perder vidas injustamente porque el control no es lo bastante preciso XD

[code language="bennu"]program apetecanemore;

import "mod_debug"
import "mod_key"
import "mod_video"
import "mod_mouse"
import "mod_map"
import "mod_math"

const
suelo=235;

private
float vx, vy, fx, fy;

begin

resolution=1;
set_fps(60,0);
set_mode(320,240,16);
load_fpg("hr.fpg");
graph=2;
fy=suelo*resolution; fx=160*resolution;
mouse.graph=2;

repeat

if(mouse.left and y==suelo*resolution)
   vy=1.5*(sqrt(y-(mouse.y*resolution)));
   vx=(((mouse.x*resolution)-x)/vy)*2;
end

fx+=vx; fy-=vy;
x=fx; y=fy;

if(y>suelo*resolution) y=suelo*resolution; fy=suelo*resolution; vx=0; end

if(y!=suelo*resolution) vy--; end

if(x<0) x=0; fx=0; elseif(x>320*resolution) fx=320*resolution; x=320*resolution; end

frame;

until(key(_esc))

end[/code]

Para que se vea claro la coincidencia o no coincidencia del salto yo estoy usando este gráfico


DCelso

El problema creo que está en que siempre decrementas en incrementas x e y.
A ver, usando matemáticas para moverte al siguiente punto más cercano al señalado debes de:
Calcular la fórmula de la recta entre los dos puntos (si quieres hacerlo parabólico entonces es mas complicado ya que tendrías que usar una fórmua cuadrática en la que el punto mas alto sea el término independiente http://es.wikipedia.org/wiki/Función_polinómica_de_grado_2),
En esta fórmula debes de despejar "x" para que esté en función de "y" y también despejar "y" para que esté en función de "x"
Ahora tienes que comprobar cuantos pixeles de distancia hay entre x_origen y x_destino y también cuantos pixeles hay entre y_origen e y_destino. En la coordenada en la que más pixeles de diferencia haya es la que tienes que usar para encontrar el nuevo punto destino.
Es decir:
Si x_destino - x_origen es mayor que y_destino - y_origen, el nuevo punto debes calcularlo con y_siguienge=f(x_origen+1), donde f(x) es la función de la recta calculada en función a x y "x_origen+1" es la x_siguiente, así obtienes el nuevo punto (x_siguigne, y_siguiente).
Si es el caso contrario, entonces deberías de calcular x_siguiente=g(y_origen-1) donde g(x) es la función de la recta calculada en función a "y" e "y_origen+1" es la y_siguiente, así obtienes el nuevo punto (x_siguigne, y_siguiente).

Este truco es para moverte por la coordenada en la que más precisión tienes.

Otra opción es que uses path_find, es mas facil de trabajar con ella ya que calcula esto por si solo solo tienes que usar getnextx y gentnexty, además esta como ventaja en caso de que haya obstáculos te da el camino mas corto saltándo los obstáculos.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

Me puse y saqué la mitad del problema :D.
Prueba esto a ver que tal, he intentado tocar lo menos posible tu ejemplo.
He calculado "y" en función de "x"
esta fórmula es perfecta para saltos en los que la distancia en la coordenada y sea más grande que en la coordenada x, osea, saltos muy altos.
Si hace saltos muy bajos verás que es preciso desde el punto de vista del destino, llega a este, pero es impreciso haciendo la parábola. Esto puede que lo soluciones un poco subiendo la precision, pero lo correcto sería calcular "x" en función de "y" y usar esta otra fórmula para este tipo de salto.

program apetecanemore;

import "mod_debug"
import "mod_key"
import "mod_video"
import "mod_mouse"
import "mod_map"
import "mod_math"

const
    suelo=235;

private
    id_graph;
    float vx, vy, fx, fy;
    int x1,x2,x3;
    int y1,y2,y3;
    int jumping;

begin
    id_graph=load_png("hr.png");
    resolution=1;
    set_fps(60,0);
    set_mode(320,240,16);
    graph=id_graph;
    fy=suelo*resolution; fx=160*resolution;
    mouse.graph=id_graph;
    x = 100;
    y = fy;
    repeat
     
        if(mouse.left and not jumping)
        x1 = x;
        x2 = mouse.x;
        x3 = 2 * x2 - x1; // es igual a ( x1 + dos veces la distancia entre x1 y x2
            y1 = y;
            y2 = mouse.y;
            y3 = y1;
            jumping = 1;
            if (x1 > x2)
              vx = -1;
            else
              vx = 1;
            end
        end
        if (jumping)
            x+=vx;
            // Fórmula cuadrática a partir de tres puntos (fórmula de interpolación de Lagrange)
            y =  (y1* ((x-x2) *(x-x3)) / ((x1-x2) *(x1-x3)) ) +
                 (y2* ((x-x1) *(x-x3)) / ((x2-x1) *(x2-x3)) ) +
                 (y3* ((x-x1) *(x-x2)) / ((x3-x1) *(x3-x2)) );
        end
         
        if(y>suelo*resolution) y=suelo*resolution; fy=suelo*resolution; jumping=0; end
     
         
        frame(200);
     
    until(key(_esc))
    unload_map(0,id_graph);
end
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

Windgate

Arg, ¿Por qué no pones la descarga directa desde Mediafire o similar?

El proyecto suena interesante, este finde llevo un lío enorme con el Bennu 3D pero si me saturo le dedico un tiempo aunque ya veo que DCelso ha resuelto parte del problema, es un super héroe xD
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

La momia que fuma

Y tan superheroe! :P Yo en cambio soy un zote en matemáticas XD, de hecho la linea esa en la que calculo la velocidad vertical (vy) se la debo a un amigo mío matemático, a mi no se me ocurriría una aplicación práctica de una raiz cuadrada ni aunque me fuese la vida en ello XD

Va guay el código de DCelso, pero (no me matéis por haceros pensar para solucionarlo al final tan tontamente, por favor XDD) al final lo he arreglado trasteando en las lineas en las que calculo vx y vy, concretamente en los valores por los que multiplico al final, multiplicando vy por 1.375 en lugar de 1.5 y multiplicando la vx por....nada XD

No lo entiendo, en el proyecto donde use por 1ª vez esto tanto vy como vx iban multiplicadas por 2 e iba muy bien ???

Ahora va cojonudamente, en velocidad vertical parece que se pasa apenas un par de pixels en saltos muy cortos, y se queda corto un par de pixels tambien en los saltos mas altos, sería cuestión de afinar mas con los decimales del multiplicador, pero vamos, bien me vale así, en el juego ni se notara :)

Por si quereis ver como queda, el código queda al final así, limpie el código de todo lo de resolution, que no pintaba nada, y deje los floats, que si que ayudan.

[code language="bennu"]program apetecanemore;


import "mod_debug"
import "mod_key"
import "mod_video"
import "mod_mouse"
import "mod_map"
import "mod_math"

const
resx=320;
resy=240;

private
float vx, vy, fx, fy;
int suelo;
begin

set_fps(60,0);
set_mode(resx,resy,16);
load_fpg("hr.fpg");
graph=2;
suelo=resy-5;
fy=suelo; fx=(resx/2);
mouse.graph=2;

repeat

if(mouse.left and y==suelo)
   vy=1.375*(sqrt(y-mouse.y));
   vx=((mouse.x-x)/vy);
end

fx+=vx; fy-=vy;
x=fx; y=fy;

if(y>suelo) y=suelo; fy=suelo; vx=0; end

if(y!=suelo) vy--; end

if(x<0) x=0; fx=0; elseif(x>resx) fx=resx; x=resx; end

frame;

until(key(_esc))

end
[/code]

Karma para DCelso por la leccion de mates :) (La 1ª vez que doy karma, es que me parece un poco una chorrada, pero me siento culpable por haberte hecho trabajar en balde :()

DCelso

 :o cagoen, bueno, espero que al menos hay sido didáctica la lección, ¿quien dijo que las matemáticas no servían para nada? :D.

No se si te has dado cuenta pero adapté el ejempo porque el tuyo no me iba, supongo que a ti tampoco: no asignas el fpg a la variable file ni en el proceso principal ni en el mouse.

Por otro lado he probado tu ejemplo, y la solución la veo un poco chapu (lo siento :D) pero el resultado es muy bueno, si con esto te vale pues nada, adelante con él lo importante es el resultado, pero date cuenta que no es nada genérico y está calculado a la cuenta de la vieja :D, puede que falle para casos no controlados como cambios de resolución de pantalla :D.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

La momia que fuma

Jejejeje, si, la chapuza es mi estilo  8) (Y la vieja de "la cuenta de la vieja" era una tatarabuela mia)

Al ser un ejemplo voy a lo que voy, por eso no asigne el fpg, porque ya lo va a coger por defecto al ser el único que hay :P

En el ultimo código que puse se adapta facil a otras resoluciones cambiando las constantes resx y resy, a resoluciones altas ya se nota mas como "no llega" por un poco a saltos muy altos, pero bueno, al ser para el concurso de Wiz va a ir a 320x240 si o si :P

Windgate

Momia, déjanos una descarga funcional porfavor, y dale Karmas a DCelso que se merece un aura en plan Dragon Ball xD

Tengo por ahí una plantilla con las bgd para Windows y Linux y el .bat/.sh que se encarga de hacerlo funcionar... Hay que darle más difusión a esa plantilla, facilita mucho las cosas y se puede seguir compilando a partir del .prg como si no existiese :(
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

DCelso

windgate ,no creo que ponga el juego,
Quote from: La momia que fuma on November 02, 2009, 12:47:58 AM
Para el concurso de Wiz estoy rescatando una idea que use en uno de mis primeros juegos ...
:D, o te refieres a otra cosa.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

Windgate

lol, pues no, me refería a eso...

Maldito concurso... ;)
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

La momia que fuma

Aun así, es que no hay nada que ver, empezé ayer a programar...lo que habeis visto aqui...es lo que hay XD (Excepto algún gráfico que ya he ido haciendo entre ayer y hoy)