Estamos avanzando rápido, en la entrada anterior, vimos como utilizar el sistema de coordenadas para posicionar nuestra nave.

Va siendo hora de comenzar a mover cosas.

Movimiento

El movimiento es un cambio posición, para mover nuestra nave del punto A al punto B únicamente tenemos que cambiar sus coordenadas.

El código

Dejo el fuente completo a continuación. Si lo prefieres puedes descargarlo aqui: altaruru_lec3_invaders.zip

Hemos Partido del código de la entrega anterior y añadido dos funciones nuevas: update() y keyreleased() y modificado keypressed().

En las funciones xInit(), xloadobjs(), load() y draw() no hay cambios.

function xInit()
	print("altaruru intro a love2d")
	print("ESCAPE TO QUIT")	
  -- recupera dimensiones de la ventana
	WINDOWH = love.graphics.getHeight()
	WINDOWW = love.graphics.getWidth()	
end

function xloadobjs()
	background = love.graphics.newImage('recursos/Backgrounds/clouds.png')
	backgroundW = background:getWidth()
	backgroundH = background:getHeight()
	player1 = love.graphics.newImage("recursos/PNG/playerShip1_blue.png")
	player1W = player1:getWidth()
	player1H = player1:getHeight()
	-- coordenadas iniciales del jugador
	player1x=(WINDOWW-player1W)/2
	player1y=WINDOWH-player1H-40
	print("(x,y) --> " .. player1x .. "," .. player1y)	
end

function love.load()
	xInit()
	xloadobjs()
end

function love.draw()
	-- Draw background  
  love.graphics.setColor(255, 255, 255)
  love.graphics.draw(background, 0, 0, 0, WINDOWW/backgroundW, WINDOWH/backgroundH)
	-- Draw player
  love.graphics.draw(player1, player1x, player1y)
end

function love.update(dt)
	if left_down then
		player1x = player1x - 200 * dt	
	end
	if right_down then
		player1x = player1x + 200 * dt	
	end
end

function love.keypressed(key)
   	if key == 'left' then
		left_down = true
	elseif key == 'right' then
    	right_down = true
   	end
	if key == "escape" then
		love.event.quit()
	end
end

function love.keyreleased(key, unicode)
   	if key == 'left' then
		left_down = false
	elseif key == 'right' then
    	right_down = false
   	end
end

Explicando el código

De momento para simplificarlo vamos a «jugar» solo con el eje X, horizontal.

Como vimos anteriormente, hemos definido el punto de inicio nuestra en X=(WINDOWW-player1W)/2.

Para ver el valor por consola podemos añadir la siguiente linea:

print("(x,y) --> " .. player1x .. "," .. player1y)

Por ejemplo, si X=350 y quiero desplazar la nave 20pixels a la derecha lo que tengo que hacer es sumar, el nuevo valor de X será 370. Si ahora quisiera desplazarme hacia la izquierda 60pixels, los resto a X, que ahora vale 370, la nueva posición será 310.

Lo único que hay que hacer es asociar el cambio a la pulsación de teclas.

Control de teclado

Hasta ahora teníamos activado el Escape para salir del juego, añadimos código a la pulsación de los cursores izquierdo y derecho.

keypressed()

Al pulsar una tecla se dispara el evento keypressed():

function love.keypressed(key)
   	if key == 'left' then
	  left_down = true
	elseif key == 'right' then
    	  right_down = true
   	end
	if key == "escape" then
	  love.event.quit()
	end
end

Lo que hacemos con el teclado es activar «banderas», si pulso left pongo left_down a true, si pulsamos right, ponemos right_down a true.

keyreleased()

Cuando soltemos la tecla se dispara el evento keyreleased() y desactivamos la bandera correspondiente:

function love.keyreleased(key, unicode)
   	if key == 'left' then
	  left_down = false
	elseif key == 'right' then
    	  right_down = false
   	end
end

Ok, pero… aun no he modificado ni una coordenada! ¿cuando se mueve la nave?

update(dt)

Una de las ventajas de Love2d es que el control de las funciones del juego se ha simplificado muchísimo respecto otros lenguajes donde hay que construir toda la lógica.

Update() se ejecuta de forma automática siempre que dure el juego, es un bucle activo durante toda la ejecución. En update() realizamos los cálculos para posicionar y calcular que ocurre en el juego, movimiento, colisiones, calculo de daño, scroll de pantalla…

Gracias a update() y la variable dt (DeltaTime*) podemos actualizar todos los objetos y conseguir que el movimiento sea fluido y natural.

dt es DeltaTime, esta variable contiene el tiempo en milisegundos desde la última vez que se ejecuto update(). Dicho tiempo no es siempre el mismo, ni siquiera en el mismo dispositivo, porque el tiempo que tarda el sistema en volver a esta función  depende de otros procesos y aplicaciones. Cuantas más aplicaciones tengamos abiertas más tardará porque la CPU tiene que repartirse en más procesos, si nuestro equipo es más potente tardará menos. Si contamos las veces que entra en update por minuto, tendríamos algo así como las revoluciones por minuto de nuestro juego, aunque en este caso se mide en fps, frames por segundo.

¿Y esto nos afecta cuando programamos? pues si y mucho.

Imagina que decimos a nuestro programa que cada vez que entre en update mueva x 10 pixels.

En un dispositivo capaz 14 ciclos por segundo, nuestra nave se desplazaría 140 pixels en un segundo. En cambio en otro dispositivo que hiciera 8 ciclos por segundo, la nave se desplazaría 80 pixels en el mismo tiempo.

Por lo tanto, si el movimiento es fijo por cada bucle sin tener en cuenta el tiempo entre un ciclo y otro, el juego irá a tirones y a distinta velocidad.

Seria algo parecido a la imagen, para una misma posición de partida (inicio), tras el mismo tiempo (1 segundo), la nave se desplaza 80 pixels en el dispositivoA y 140 en el dispositivoB.

Todo eso se soluciona de forma sencilla gracias a la variable ds, solo tenemos que multiplicar el desplazamiento fijo por ds, si preocuparnos por el valor que contenga ya que eso lo gestiona solo el motor de juego. Por tanto, en cada update() el desplazamiento que se aplica es proporcional. ¿Genial no?

En nuestro código quedará así:

function love.update(dt)
	if left_down then
		player1x = player1x - 200 * dt	
	end
	if right_down then
		player1x = player1x + 200 * dt	
	end
end

Estamos diciendo al motor que si la bandera «left_down», que se activa al pulsar cursos izq. está activa, desplace la nave 200px a la izq. y si la bandera «right_down» esta activa, 200px a la derecha. Al incluir dt en la formula, ajustamos automáticamente el desplazamiento e irá a la misma velocidad en cualquier dispositivo.

Próxima entrada: estructurando el código, intro a tablas.

Se ha añadido un anexo con algunos cambios a esta entrada: Invaders III – anexo, con cambios en la velocidad del player1 y función específica de movimiento para player1.

Saludos y feliz código!

Deja tu comentario