entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

3votos

Porcentaje de daño (MySQL / PHP)

Buenas. Les comento mi situación, estoy desarrollando un juego online donde algunos datos son almacenados mediante una base de datos MySQL, en este caso en particular (sobre ésto es mi pregunta) los usuarios pueden adquirir vehículos los cuales son almacenados acá:

Tabla 'autos'

Ahora bien, voy al grano:

En el juego todo vehículo se rompe o deja de funcionar cuando su "Vida" es 350. El estado impecable o sin daños de los vehículos es de "Vida" 1000. Esa información se mostrará en una página web (una especie de panel donde puede verse qué vehículo tienen los jugadores), tranquilamente podría usar la definición de "vida del vehículo" (por así decirlo), pero se me ocurrió un porcentaje de daños, sí, vendría a ser esto básicamente: si su "Vida" es de 350, aparecería en daños: 100% (ya que el vehículo está roto), si su "Vida" es de 1000 aparecería en daños: 0% (ya que el vehículo está sano).

Mi pregunta sería: ¿qué código más directo podría usar sin tener que estar colocando un <?php ?> para cada número (350, 351, 352 y así sucesivamente hasta el 1000)?

Me armé la siguiente tabla de valores pero no sabría cómo colocarlos:

Vida | Daños

1000 = 0
975 = 5
950 = 10
925 = 15
875 = 20
850 = 25
825 = 30
775 = 35
750 = 40
725 = 45
675 = 50
650 = 55
625 = 60
575 = 65
550 = 70
525 = 75
475 = 80
450 = 85
425 = 90
400 = 95
350 = 100

Yo intenté de la siguiente manera o formato, pero evidentemente lo hice mal:

<?php if($playerv1['Vida'] >= 350){echo '100%';}?>
<?php if($playerv1['Vida'] >= 400){echo '95%';}?>
<?php if($playerv1['Vida'] >= 425){echo '90%';}?>
Y así sucesivamente con los valores de la tabla de arriba, hasta llegar al...
<?php if($playerv1['Vida'] == 1000){echo '0%';}?>

Espero haberme explicado bien, desde ya muchas gracias por pasarse por acá y disculpen la ignorancia, estoy aprendiendo a manejarme con este lenguaje de programación. Saludos.

0voto

Leonardo-Tadei comentado

Recordá elegir una respuesta para que el tema quede marcado como solucionado y ayudar a otros con el miemo problema!

3 Respuestas

0voto

Kelys Puntos320

Logré hacerlo con este código:

<?php
$vida = $playerv1['Vida'] - 350;
echo round(($vida*100/650)*-1+100, 2)."%";
?>

Ahora, lo que quisiera saber es lo siguiente, quisiera que si el daño es entre 0% a 50% aparezca en verde, y si es entre 51% y 100% sea rojo. ¿Es posible? ¿Cómo? Gracias.

0voto

Leonardo-Tadei comentado

Hola!

pasaste la ecuación de mi respuesta del lado de PHP... si lo hacés del lado de la DB, es más rápido, pero no debería darte ningúin problema de performance hacerlo de uno u otro lado.

Para ponerle colores, un condicional:

...
$vida = $playerv1['Vida'] - 350;
$vida = round(($vida*100/650)*-1+100, 2)."%";
$color="#00FF00";
if($vida <= 50){
  $color="#FF0000";
}
echo "<span style='color:$color;'>$vida</span>

Saludos

0voto

ankeorum comentado

En relación a esto que acabas de comentar @Leonardo-Tadei

Por qué motivo el mismo código en BD es más rápido? Suponiendo claro, que ambos servidores son el mismo equipo.

0voto

ankeorum comentado

Me acabo de fijar que tu código no funcionará @Leonardo-Tadei porque haces la comparación después de que $vida ya sea una cadena (al agregarle el %). Tienes que agregar el símbolo de porcentaje después @Kelys. Tal que así:

$vida = $playerv1['Vida'] - 350;
$vida = round(($vida*100/650)*-1+100, 2);
$color="#00FF00";
if($vida <= 50){
  $color="#FF0000";
}
echo "<span style='color:$color;'>$vida."%"</span>

0voto

Leonardo-Tadei comentado

Hola!

gracias por notar del signo de % (siempre me pasa que escribo el código directamente acá y no pasa por el intérprete). El código fallará solo cuando se compara con el 100%, ya que en todos los demás casos, el intérprete hará el casting a string y el orden alfabético coincide con el numérico.

También se podría hacer la compración:

if(intval($vida) <= 50){

para que el % no moleste.

Respecto de la DB, es más rápido hacerlo ahí porque el motor de DB está muy optimizado para hacer operaciones de enteros, y la query no tarda más que si no se hace el cálculo.

En cambio al pasar el cálculo al lenguaje, consumís ciclos de CPU en la interpretación lo que debe es necesariamente más costoso en CPU. En este caso puntual, la diferencia debe ser de algún milisegundo, es decir que no es a priori significativa, pero como es un entorno web que podría tener miles de visitas concurrentes, se vuelve importante.

Saludos!

0voto

ankeorum comentado

Perfecto, ahora lo entiendo mejor lo de la base de datos y no en código. No sabía por qué era ya que imaginaba el mismo consumo de CPU. Como bien dices en este caso solo será relevante si el juego en cuestión alcanza el millón de jugadores. En cualquier caso, por si ocurriera, recomiendo utilizar la opción más optimizada. Siempre si nos acostumbramos a usar los códigos óptimos programaremos mejor!

0voto

ankeorum Puntos7210

Realmente en tu código estás haciéndolo mal porque si el valor es 1000, es decir, no tiene daño hecho, va a entrar en todos los "echo".

Yo escribiría una función para comparar si un valor se sitúa entre otros dos:

function nBetween($varToCheck, $high, $low) {
if($varToCheck < $low) return false;
if($varToCheck > $high) return false;
return true;
}

y después comparas:

<?php if(nBetween($playerv1['Vida'],400,350)){echo '100%';}?>
<?php if(nBetween($playerv1['Vida'],425,400)){echo '95%';}?>
<?php if(nBetween($playerv1['Vida'],450,425)){echo '90%';}?>
Y así sucesivamente con los valores de la tabla de arriba, hasta llegar al...
<?php if($playerv1['Vida'] == 1000){echo '0%';}?>

0voto

ankeorum comentado

Aún así, con el código que te he puesto, tu tabla está errónea:

La tabla sería así:

Vida -> Daño

1000 - 0
935 - 10
870 - 20
805 - 30
740 - 40
675 - 50
610 - 60
545 - 70
480 - 80
415 - 90
350 - 100

Entre 1000 y 350 tienes 650 unidades, por lo tanto recibir 650 daños sería lo mismo que recibir el 100% del daño, por lo tanto 65 daños equivaldría al 10%. Con eso he construido la escala anterior.

SaludoS!

Edit: ya que 65 es el 10% y para no hacer demasiado complejos los cálculo yo establecería la vida mínima para declarar inservible a 400, obteniendo de esta manera 600 unidades con lo cual los saltos de 5% irían de 30 en 30. Espero haberte ayudado.

2votos

Leonardo-Tadei Puntos227020

Hola @Kelys,

yo lo resolvería directamente con la query, con lo que te ahorrás todo el problema de cómo presentar los datos.

Si 1000 es 0% de daño y 350 es 100% de daño, tus valores oscilarán entre 650 y 0, en dónde 650 es 0% de daño y 0 es 100% de daño.

Con esto, para un valor 'vida' de por ejemplo 800, le restás los 350 del ofset al 0, con lo que te quedan 450, luego el daño será:

100 - 450*100/650 = 30.77% de daño.

En la query podés hacer todo el cálculo:

SELECT *, (200 - ((vida-350)*100/650) ) AS dano
FROM Autos

y mostrás el resultado de 'dano' cómo más te guste.

Saludos cordiales!

0voto

ankeorum comentado

He estado un rato intentando buscar la fórmula que has puesto y no la he encontrado. He guarreado tres folios intentando encontrar eso... xD

Si te gustaría usar valores enteros utiliza trunc(valor,0) para quitar los decimales o round(valor,0) para redondear obteniendo así valores como este:

94%
91%
etc.

0voto

Leonardo-Tadei comentado

Son cosas que pasan con las fórmulas ;-)

Además de redondear el dato, también se podrían mostrar de 5 en 5 haciendo una división entera y recomponiendo el número... son cosas de visualización una vez que la query devuelve el resultado.

Saludos cordiales!

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta