Jump to content

[Codigo] Menu 3D


Recommended Posts

Hace un rato publique este vídeo:

Para todos aquellos que busquen conocer que funciones utilice, les dejo el código:

CLIENTE:

addEventHandler("onClientResourceStart", resourceRoot, 
    function() 
        myRenderTarget = dxCreateRenderTarget( 796, 512, true ) 
    end 
) 
  
text = '' 
cNumber = 1 
cName = 'ROJO' 
cR, cG, cB = 245, 0, 0 
oR, oG, oB = 245, 0, 0 
state = 0 
alpha = 0 
  
tColors = { 
[1]= {'ROJO', 245, 0, 0}, 
[2]= {'AZUL', 0, 0, 230}, 
[3]= {'AMARILLO', 245, 223, 0}, 
[4]= {'VERDE', 0, 240, 0}, 
[5]= {'PURPURA', 157, 0, 214}, 
[6]= {'ROSA', 255, 15, 220}, 
[7]= {'PLATA', 192, 192, 192}, 
[8]= {'MARRON', 100, 50, 0}, 
[9]= {'BLANCO', 255, 255, 255}, 
[10]= {'NEGRO', 0, 0, 0} 
} 
  
function alternateColor( key ) 
    if key == 'arrow_l' then 
        cNumber = math.max( cNumber - 1, 1 ) 
    elseif key == 'arrow_r' then 
        cNumber = math.min( cNumber + 1, #tColors ) 
    end 
     
        if tColors[cNumber] then 
            --outputChatBox( cNumber ) 
            local name, r, g, b = unpack( tColors[cNumber] ) 
                cName = name 
                oR, oG, oB = r, g, b 
        end 
end 
  
function getPositionFromElementOffset(element,offX,offY,offZ) 
    local m = getElementMatrix ( element ) 
    local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]  
    local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2] 
    local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3] 
    return x, y, z  
end  
  
function draw3DMenu() 
  
    if state == 1 then 
        alpha = math.min(alpha + 12.5, 255) 
    elseif state == 2 then 
        alpha = math.max( alpha - 10, 0 ) 
    end 
     
        if cR > oR then 
            cR = math.max(cR - 8, oR) 
        elseif cR < oR then 
            cR = math.min(cR + 8, oR) 
        end 
         
        if cG > oG then 
            cG = math.max(cG - 8, oG) 
        elseif cG < oG then 
            cG = math.min(cG + 8, oG) 
        end 
         
        if cB > oB then 
            cB = math.max(cB - 8, oB) 
        elseif cB < oB then 
            cB = math.min(cB + 8, oB) 
        end 
  
        if myRenderTarget then 
            dxSetRenderTarget( myRenderTarget, true ) 
                dxDrawRectangle( 0, 0, 796, 512, tocolor( 128, 128, 128, math.max(alpha - 72, 0) ) ) 
                dxDrawText( 'Vehiculo:', 32, 32, 764, 64, tocolor( 255, 255, 255, alpha ), 2.4, 'sans', 'left', 'center', true, true ) 
                dxDrawRectangle( 64, 88, 668, 64, tocolor( 255, 255, 255, alpha ) ) 
                dxDrawText( text, 66, 90, 732, 152, tocolor( 0, 0, 0, alpha ), 2.8, 'sans', 'center', 'center', true, true ) 
                dxDrawText( '[<]  '..cName..'  [>]', 66, 184, 732, 248, tocolor( cR, cG, cB, alpha ), 2.4, 'sans', 'center', 'center', true, true ) 
                dxDrawRectangle( 270, 296, 256, 132, tocolor( math.max(cR-20, 0), math.max(cG-20, 0), math.max(cB-20, 0), alpha) ) 
                dxDrawRectangle( 282, 308, 232, 108, tocolor( 128, 128, 128, alpha ) ) 
                dxDrawText( 'ACEPTAR', 286, 312, 512, 412, tocolor( 255, 255, 255, alpha ), 1.2, 'bankgothic', 'center', 'center', true, true )  
            dxSetRenderTarget() 
    if x and y and z then 
            dxDrawMaterialLine3D( x - 0.08, y, z + 0.7, x - 0.08, y, z - 0.7, myRenderTarget, 2.4, tocolor(255,255,255,255), x2, y2, z2 ) 
        end 
    end 
         
end 
  
function receptInput(char) 
    if char then 
        text = #text < 21 and text..char or text 
    end 
end 
  
function deleteChar() 
    if #text > 0 then 
        text = (text):sub( 1, #text-1) 
    end 
end 
  
function createCar() 
    if getVehicleModelFromName( text ) then 
        triggerServerEvent( 'createVeh', localPlayer, text, oR, oG, oB, ox, oy, oz ) 
        state = 2 
        setTimer( function()  
            removeEventHandler( 'onClientRender', root, draw3DMenu ) 
            removeEventHandler( 'onClientCharacter',  root, receptInput ) 
            unbindKey( 'arrow_l', 'down', alternateColor ) 
            unbindKey( 'arrow_r', 'down', alternateColor ) 
            unbindKey( 'enter', 'down', createCar ) 
            unbindKey( 'backspace', 'down', deleteChar ) 
            toggleAllControls( true ) 
            end, 1000, 1) 
    end 
end 
  
addCommandHandler( 'cv', 
    function() 
        if state ~= 1 then 
            x, y, z = getPositionFromElementOffset(localPlayer,0,1,1.2) 
            x2, y2, z2 = getPedBonePosition( localPlayer, 8 ) 
            ox, oy, oz = getPositionFromElementOffset(localPlayer,0,5,0.65) 
            cR, cG, cB = 245, 0, 0 
            oR, oG, oB = 245, 0, 0 
            cNumber = 1 
            cName = 'ROJO' 
            addEventHandler( 'onClientRender', root, draw3DMenu ) 
            text = '' 
            addEventHandler( 'onClientCharacter',  root, receptInput ) 
            state = 1 
            bindKey( 'arrow_l', 'down', alternateColor ) 
            bindKey( 'arrow_r', 'down', alternateColor ) 
            bindKey( 'enter', 'down', createCar ) 
            bindKey( 'backspace', 'down', deleteChar ) 
            toggleAllControls( false, true, true ) 
        end 
    end 
) 

SERVIDOR:

function findRotation(x1,y1,x2,y2) 
  
  local t = -math.deg(math.atan2(x2-x1,y2-y1)) 
  if t < 0 then t = t + 360 end; 
  return t; 
  
end 
  
addEvent( 'createVeh', true ) 
    addEventHandler( 'createVeh', root, 
        function( text, oR, oG, oB, ox, oy, oz ) 
            local x, y, z = getElementPosition( source ) 
            local rz = findRotation(ox, oy, x, y) 
            local veh = createVehicle( getVehicleModelFromName( text ), ox, oy, oz, 0, 0, rz-90 ) 
            --outputChatBox( oR..' '..oG..' '..oB ) 
            setVehicleColor( veh, oR, oG, oB ) 
        end 
    ) 
  

* El recurso en si no esta hecho para ser usado en un servidor, solo es una demostración de las posibilidades de MTA en conjunto a DirectX.

Link to comment
Por que no usaste las nuevas matrices y vectores del mta? Lo hubieras podido hacer mucho mas simple.

De cualquier forma te quedó genial :D

Ignora todo lo referente al código que no tenga que ver con el diseño en si, ademas esta hecho en la 1.3.

* Ninguna de las funciones para calculo de posiciones que utilice es mía, ambas están publicadas en la sección 'Useful Functions'.

Link to comment

Aaaah bueno, esta bien entonces.

Solo como un dato interesante, a quien le interese saber... Para obtener la posición enfrente del player en MTA 1.4, puedes hacer esto:

local pos_enfrente = player.position + player.matrix.forward * 2 

Con eso obtienes la posición a dos metros de distancia, enfrente del jugador, no importa hacia adonde este viendo.

Luego para usarlo nomas haces esto:

createVehicle(modelo, pos_enfrente) -- Sí, las funciones como estas ya aceptan vectores, ya no es necesario escribir las tres coordenadas. 

O si prefieres hacerlo en OOP, lo haces así:

Vehicle.create(modelo, pos_enfrente) -- Incluso se puede hacer sin el ".create", solo con Vehicle(cosas), pero no estoy seguro por que no lo he probado aún. 

Link to comment

En términos de eficiencia OOP es una aberración, sobretodo en un juego en línea donde cada milesima de segundo importa. A mi parecer la comodidad que OOP significa se ve completamente opacada por su poca o nula eficiencia, evitarla tanto como sea posible debe ser una prioridad.

Link to comment

En términos de eficiencia OOP es una aberración, sobretodo en un juego en línea donde cada milesima de segundo importa. A mi parecer la comodidad que OOP significa se ve completamente opacada por su poca o nula eficiencia, evitarla tanto como sea posible debe ser una prioridad.

Y la fuente de esta información la sacaste de donde?

*De lo siguiente no estoy seguro, así que no te lo tomes enserio:

Mira, yo he leído los archivos del código fuente donde esta programado el OOP, y esos archivos simplemente hacen referencia a las funciones normales.

Ademas, que no es C mas rápido que lua? Si es asi, entonces es mas rápido hacer todos esos cálculos en C, que llamar la función getElementMatrix y hacer los cálculos tu mismo, ademas que de igual forma tiene que hacer varios cálculos internamente en MTA, no es mejor que directamente se encargue de todo?

Claro, en este contexto especifico de las matrices...

Acá esta el código fuente del que te hablaba:

OOP client-side: https://code.google.com/p/mtasa-blue/source/browse/trunk/MTA10/mods/shared_logic/lua/CLuaMain.cpp

OOP server-side: https://code.google.com/p/mtasa-blue/source/browse/trunk/MTA10_Server/mods/deathmatch/logic/lua/CLuaMain.cpp

Nomas dale al Ctrl+F y busca la función que quieras. Ahí están programadas las referencias a las funciones de las matrices y los vectores también.

Si quieres ponemos esto a prueba, de OOP vs el tradicional procedural. Hacemos múltiples pruebas, les sacamos promedio y vemos quien tiene la razón. Nos ponemos de acuerdo en que métodos vamos a usar para hacer la prueba y lo dejamos todo claro desde el principio sin entrar a discusiones sin sentido y sin fundamento. Que te parece?

Link to comment

He hecho una comprobación sencilla, inicialmente iba a darles la razón, pero tras comprobar un par de veces note que OOP inicialmente puede tardar ligeramente menos que el método estándar, pero tras un par de ejecuciones el tiempo de ejecución aumenta de manera exponencial.

* Ademas OOP posee una variación del tiempo de ejecución que varia erraticamente, mientras que de manera procedimental (la palabra 'procedural' no existe en el idioma español) los tiempos se mantienen constantes en todo momento.

Link to comment

Bueno, yo también hice mis pruebas. Aquí están los resultados:

Procedimental:

Metodo:

-- Crear 1000 objetos, obtener la matris de uno y crear el siguiente adelante y a la derecha del anterior. 
  
------------------- 
-- PROCEDIMENTAL -- 
------------------- 
  
local inicio = getTickCount() 
  
function getPositionFromElementOffset(element,offX,offY,offZ) 
    local m = getElementMatrix ( element ) 
    local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1] 
    local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2] 
    local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3] 
    return x, y, z 
end 
  
local rotZ = 0 
local cuenta = 1 
local x, y, z = -1238, -180, 15 -- posiciones iniciales en el aero de SF 
  
for i=1, 1000 do 
    local v = createVehicle(411, x, y, z, 0, 0, rotZ) 
    setElementFrozen(v, true) 
    x, y, z = getPositionFromElementOffset(v,5,5,0) 
    rotZ = rotZ + 90 
    cuenta = cuenta + 1 
    if cuenta > 4 then 
        z = z + 1.5 
        cuenta = 1 
    end 
end 
  
local fin = getTickCount() 
outputDebugString("resultado: "..fin - inicio, 3) 

Resultados en 10 pruebas:

20 + 18 + 19 + 20 + 20 + 20 + 21 + 19 + 19 + 21 = 197

197 / 10 = 19.7 milisegundos.

OOP: por cierto, oop tampoco existe en español, tendrías que decir POO.

Metodo:

-- Crear 1000 objetos, obtener la matris de uno y crear el siguiente adelante y a la derecha del anterior. 
  
------------------------------------ 
-- VECTORES Y ORIENTADO A OBJETOS -- 
------------------------------------ 
  
local inicio = getTickCount() 
  
local rotZ = 0 
local cuenta = 1 
local pos = Vector3(-1238, -180, 15) -- posiciones iniciales en el aero de SF 
  
for i=1, 1000 do 
    local v = Vehicle(411, pos, 0, 0, rotZ) 
    v.frozen = true 
    pos = pos + v.matrix.forward * 5 
    pos = pos + v.matrix.right * 5 
    rotZ = rotZ + 90 
    cuenta = cuenta + 1 
    if cuenta > 4 then 
        pos.z = pos.z + 1.5 
        cuenta = 1 
    end 
end 
  
local fin = getTickCount() 
outputDebugString("resultado: "..fin - inicio, 3) 

Resultados en 10 pruebas:

37 + 37 + 38 + 37 + 37 + 38 + 37 + 38 + 36 + 35 = 370

370 / 10 = 37 milisegundos

Conclusión:

Efectivamente, tras hacer las pruebas, se puede concluir que la implementación OOP es mas lenta que la procedimental, en este caso la diferencia son 17.3 milisegundos. Pero debemos tomar en consideración también los siguientes aspectos:

Primero: En este contexto estamos hablando de crear mil autos, no es una situación común y el tiempo al final dependerá del script que estés creando.

Segundo: Se logró reducir de 34 a 27 lineas un script pequeño como este. Se imaginan cuanto código es posible ahorrar en scripts de miles de lineas?

Tercero: Los problemas de fluctuación del tiempo de ejecución también me pasaron, pero eran debido a laag generado por estar muy cerca del área donde se crearon los autos. Al alejarme los resultados cambiaron dramáticamente e incluso la implementación oop fue mas estable que la procedimental.

Lo dejo a decisión de cada quien, por mi parte yo voy a seguir usando OOP. :lol:

Link to comment

20 milisegundos en comparación a 38 me parece una diferencia demasiado alta como para ignorarla, sin embargo estuve comprobando y en ciertos casos OOP resulta igual o más conveniente que un método estándar (cabe mencionar que OOP en otras ocasiones se tarda 3 ó 4 veces mas), de todas formas no me parece un gran cambio ni en cuanto a comodidad ni a posibilidades, seguiré aconsejando utilizar las formas procedimentales.

* No me tomare la molestia ni el tiempo de hablar sobre traducciones incorrectas, por favor evitalo.

Edited by Guest
Link to comment

Una reacción rápida promedio de un humano dura un poco mas de 200 milisegundos. Acá estamos hablando de apenas decenas de milisegundos, esos son tiempos sumamente rápidos. Entiendo que por ejemplo en un gamemode race es realmente necesaria mucha rapidez de procesamiento (que el mapa vaya cargando mas lento de lo que conduces es fatal!). Pero en otros tipos de gamemode no veo donde esta la importancia de ahorrarse una cantidad tan mínima.

http://www.humanbenchmark.com/tests/reactiontime/stats.php

Link to comment
Una reacción rápida promedio de un humano dura un poco mas de 200 milisegundos. Acá estamos hablando de apenas decenas de milisegundos, esos son tiempos sumamente rápidos. Entiendo que por ejemplo en un gamemode race es realmente necesaria mucha rapidez de procesamiento (que el mapa vaya cargando mas lento de lo que conduces es fatal!). Pero en otros tipos de gamemode no veo donde esta la importancia de ahorrarse una cantidad tan mínima.

http://www.humanbenchmark.com/tests/reactiontime/stats.php

No me parece suficiente argumento como para escribir códigos que tarden el doble o el triple en ejecutarse, la eficiencia y la rapidez de ejecución siguen siendo una prioridad para mi.

Link to comment

El uso de herramientas depende única y exclusivamente del código que quieras hacer, ver la eficacia de un código es la fase final, donde pruebas tiempos de ejecución, una vez que te acostumbras a hacerlo de la manera mas rápida ya no tienes que estar recurriendo a hacer esto. Seria bueno que aprendieran maneras de ver la complejidad de un código, cuantos recursos consume un for por ejemplo, cuantos datos puede procesar su maquina sin caerse, bueno todo esto depende mucho de que sistema operativo y el hardware que usen. Ahí podrán ver que las diferencias en tiempos de ejecución varían de forma notable.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...