Hola, sean bienvenidos a mi nuevo post, hoy ha llegado el gran dia porque vamos a hacer nuestro primer juego, en este caso es uno bien simple: pong.

Anuncios

Primero, vamos a descargar este archivo pong_assets, luego procederemos con la creacion de nuestro proyecto, vamos a llamarlo Pong y deberian crearlo junto con los anteriores, una vez creado y descargado nuestro archivo, debemos extraer el contenido dentro del directorio del proyecto, una vez hecho en la seccion de los assets nos deberia quedar de esta forma

godot47

Ahora nos pondremos nostalgicos, vamos a usar una resolucion de 640×400 y el color de fondo sera negro, para hacer esto debemos modificarlo en Ajustes del proyecto->Display->Window.>Width (para modificar el ancho) y Height (para modificar el alto)

godot48.png

Y para modificar el color, dentro de Ajustes del proyecto -> Rendering -> Environment -> Default Clear Color, y ahi elijan en la paleta el color negro

godot49.png

Una vez finalizado procederemos a crear nuestros nodos, primero vamos a agregar un Node2D, lo podemos renombrar a Juego, ahora procedemos a agregar a nuestros hijos del Nodo principal, primero agregamos uno nuevo del tipo Sprite y este lo podemos duplicar, o bien con Ctrl+D o agregando nuevos como hicimos antes, despues los renombramos a cada uno como izquierda, derecha, pelota y separador, nos quedaria algo asi

godot50

Ahora procderemos a agregar las texturas de cada uno de nuestro nodos, el metodo es simple, primero elegimos el elemento en cuestion, por ejemplo izquierda, luego vamos a la solapa inspector y ahi debemos elegir Texture, al principio estara en estado Null, al seleccionarlo deberan elegir Cargar, ahi nos mostrara un cuadro de dialogo con todo el contenido del resource path (res://)

godot51
Anuncios

Elegimos el archivo, el cual va a ser la textura de nuestro jugador del lado izquierdo, una vez seleccionado deberia quedar asi

godot52

Luego procederemos a ubicarlo en el espacio, para eso debemos elegir Transform (se ve en la foto anterior), elegimos Position y seteamos el valor de X e Y

godot60
godot61

Ahora, se deberia hacer lo mismo con el resto de los sprites:

  • Para el jugador derecho, usar la textura right_pallete.png y las coordenadas son 577,187.
  • Para el separador, usar la textura separator.png y las coordenadas son 320,200
  • Para la pelota, usar la textura ball.png y las coordenadas son 320,188
  • Repetimos los del jugador izquierdo, la textura es left_pallete.png y las coordenadas son 67,183
  • En todos los casos, deben destildar (en caso de estarlo) la opcion centered en Offset, salvo para el separador.
godot62.png

Si todo sale bien, deberia quedar una pantalla de este estilo

godot55

Si todo salio bien y obtuvieron una pantalla similar a esta, ya concretamos la mitad del juego porque logramos el esqueleto del mismo ahora procedamos con el scripting para culminar la mitad faltante de nuestro juego.

Antes de empezar nuestros scripts vamos a crear los metodos de interaccion de los jugadores con las “paletas”, para esto iremos a Ajustes del proyecto -> Mapa de Entradas, en accion vamos a definir nuestros cuatro movimientos (dos del jugador izquierdo y dos del derecho), nuestros movimientos van a hacer left_move_up, left_move_down, right_move_up y right_move_down. En accion deben escribir los nombres y usar el boton Añadir, una vez finalizado con cada uno de las acciones nos deberia quedar algo asi

Anuncios
godot56

Ahora si ven , a la derecha hay un boton con el signo Mas (+) si le hacen click le apareceran todas estas opciones, la unica que nos interesa ahora es la de tecla

godot57

Una vez elegida nos aparecera un menu esperando la tecla a asignar

godot58.png

Aca aprieten la tecla a asignar y luego aceptar para asignarlo a ese evento, les recomiendo asignarlo de esta forma:

  • left_move_up: La tecla A
  • left_move_down: La tecla Z
  • right_move_up: La tecla cursor Arriba
  • right_move_down: La tecla cursor Abajo

Una vez terminado de asignar todas las teclas deberia quedar algo asi

godot59
Anuncios

Una vez asignados las teclas a los eventos creados en el mapa de Entradas procederemos con los scripts para manipular el juego, recuerden que primero debemos crear nuestro script y relacionarlo con el Node2D (juego) a traves del boton derecho Adjuntar Script o con el boton en la solapa de Escena, una vez elegida cualquiera de las dos acciones, nos aparecera un menu de dialogo, deben dejarlo como aparece y elegir Crear, recuerden salvar la escena y setearla como Principal y como siempre, primero escribiremos el codigo y luego pasaremos a explicarlo:

juego.gd

extends Node2D

var screen_size
var pad_size
var direction=Vector2(1,0)

const INITIAL_BALL_SPEED = 80

var ball_speed = INITIAL_BALL_SPEED
const PAD_SPEED = 150

func _ready():
	screen_size = get_viewport_rect().size
	pad_size = get_node("izquierda").get_texture().get_size()
	set_process(true)

func _process(delta):
	var ball_pos = get_node("pelota").position
	var left_rect = Rect2(get_node("izquierda").position, pad_size)
	var right_rect = Rect2(get_node("derecha").position, pad_size)
	ball_pos += direction * ball_speed * delta
	if ((ball_pos.y < 0 and direction.y < 0) or (ball_pos.y > screen_size.y and direction.y > 0)):
		direction.y = -direction.y
	if ((left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)):
		direction.x = -direction.x
		direction.y = randf() * 2.0 - 1
		direction = direction.normalized()
		ball_speed *= 1.1
	if (ball_pos.x < 0 or ball_pos.x > screen_size.x):
		ball_pos = screen_size * 0.5
		ball_speed = INITIAL_BALL_SPEED
		direction = Vector2(-1,0)
		get_node("pelota").set_position(ball_pos)

	var left_pos = get_node("izquierda").position

	if (left_pos.y > 0 and Input.is_action_pressed("left_move_up")):
		left_pos.y += -PAD_SPEED * delta
	if (left_pos.y < screen_size.y and Input.is_action_pressed("left_move_down")):
		left_pos.y += PAD_SPEED * delta
		get_node("izquierda").set_position(left_pos)
	var right_pos = get_node("derecha").position
	if (right_pos.y > 0 and Input.is_action_pressed("right_move_up")):
		right_pos.y += -PAD_SPEED * delta
	if (right_pos.y < screen_size.y and Input.is_action_pressed("right_move_down")):
		right_pos.y += PAD_SPEED * delta
		get_node("derecha").set_position(right_pos)

Aqui estamos ante nuestro primer codigo, para explicarlo un poco mejor lo voy a desglosar y explicar cada parte, empecemos con la primera parte:

extends Node2D

var screen_size
var pad_size
var direction=Vector2(1,0)

const INITIAL_BALL_SPEED = 80

var ball_speed = INITIAL_BALL_SPEED
const PAD_SPEED = 150

Como comentamos en este post, al crear un script se nos crea una plantilla predeterminada, la cual borraremos todo lo escrito salvo extends Node2D y func _ready(). Despues agregaremos todas nuestras variables y constantes como vemos en este bloque, aca declaramos a la cual va a contener el tamaño de la pantalla (screen_size), este va a almacenar el valor de la paleta (pad_size), este contiene la direccion inicial de donde sale la pelota (direction), despues tendremos una constante donde se asignara la velocidad inicial de la pelota (INITIAL_BALL_SPEED), otra donde se almacenara la velocidad de la pelota (ball_speed) y por ultimo la velocidad de la paleta (PAD_SPEED), como pueden ver tenemos dos variables donde podemos modificar la velocidad tanto de la pelota como de la paleta, INITIAL_BALL_SPEED y PAD_SPEED respectivamente, ahora pasemos al siguiente bloque:

func _ready():
	screen_size = get_viewport_rect().size
	pad_size = get_node("izquierda").get_texture().get_size()
	set_process(true)
Anuncios

En esta funcion para monitorear el estado ready, vamos a asignar el tamaño de la pantalla a la variable screen_size, tambien vamos a asignar el tamaño de la textura de la paleta a pad_size y por ultimo seteamos en true a set_process, ahora analicemos el siguiente bloque:

func _process(delta):
	var ball_pos = get_node("pelota").position
	var left_rect = Rect2(get_node("izquierda").position, pad_size)
	var right_rect = Rect2(get_node("derecha").position, pad_size)

Aca vemos el inicio de la funcion _process(delta), como comentamos en el post anterior esta se encarga los procesos inactivos y en esta porcion vamos a definir tres variables, la primera va a contener la posicion del balon (ball_pos) y esto lo logra a traves del metodo position y con get_node le definimos el sprite (pelota), en la segunda variable (left_rect) vamos a asignarle a traves de Rect2 la posicion y el tamaño de la paleta (pad_size), lo mismo pasa con la siguiente variable (right_rect) salvo que es la informacion de la paleta derecha, una breve explicacion de Rect2, es el encargado de contener y verificar en forma de rectangulo para dos dimensiones, este almacena dos valores de tipo float, tambien es de tipo Vector2, donde el metodo .position nos devuelve justamente este tipo de informacion y pad_size ya tiene este tipo de valor almacenado, en realidad los datos enviados seria de este estilo:

var left_rect = Rect2((57, 187), (8, 32))

Una vez visto este bloque ahora veamos esta linea:

ball_pos += direction * ball_speed * delta

En esta linea vamos a definir la posicion del balon en base a la direccion (direction), la velocidad de la pelota (ball_speed) y delta, ahora pasemos al siguiente bloque:

	if ((ball_pos.y < 0 and direction.y < 0) or (ball_pos.y > screen_size.y and direction.y > 0)):
		direction.y = -direction.y

Aca vemos un condicional if, en el primer parentesis compararemos si la posicion del eje Y de la pelota y el eje Y de la direccion son menores que cero o en el segundo parentesis si el eje Y de la posicion de la pelota sea mayor que el eje Y del tamaño de la pantalla y el eje Y de la direccion sea mayor que cero, si cumplen cualquiera de las dos condiciones procederemos a invertir el valor del eje Y de direccion, es decir esta condicion nos permite rebotar la pelota en las pared superior o inferior, ahora pasemos al siguiente bloque:

	if ((left_rect.has_point(ball_pos) and direction.x < 0) or (right_rect.has_point(ball_pos) and direction.x > 0)):
		direction.x = -direction.x
		direction.y = randf() * 2.0 - 1
		direction = direction.normalized()
		ball_speed *= 1.1

Aqui tenemos un condicional if el cual en el primer parentesis verifica si la paleta izquierda tuvo contacto con la posicion de la pelota, esto es a traves de has_point(), y el eje X de la direccion sea menor a cero y veamos el segundo parentesis, donde hace exactamente lo mismo pero con la paleta derecha pero la diferencia es verificar que el eje X sea mayor a cero, si se cumplen cualquiera de las dos condiciones, por el operador or, procederemos a ejecutar las siguientes funciones, primero vamos a invertir el valor del eje X de direccion, luego le asignaremos un valor aleatorio a traves de randf * 2.0 – 1 para el eje Y de la direccion, luego estableceremos la direccion como normalizada y por ultimo incrementaremos la velocidad de la pelota, este es el bloque encargado de hacer rebotar la pelota de la paleta. Ahora sigamos con el siguiente bloque:

Anuncios
	if (ball_pos.x < 0 or ball_pos.x > screen_size.x):
		ball_pos = screen_size * 0.5
		ball_speed = INITIAL_BALL_SPEED
		direction = Vector2(-1,0)

En el condicional if vamos a comparar que el eje X de la posicion de la pelota sea menor a cero o el eje X de la posicion de la pelota sea mayor al eje X del tamaño de la pantalla, si se cumple cualquier de las dos condiciones procederemos a asignar el valor medio la posicion de la pelota, es decir x: 320 y y: 200, volvemos a asignar el valor constante de la velocidad inicial de la pelota a la velocidad de la pelota, y reestablecemos la direccion, es decir este bloque se encarga de resetear los parametros una vez que la pelota paso por los limites de la pantalla, es decir supero a la paleta. Veamos la siguiente linea:

get_node("pelota").set_position(ball_pos)

En esta linea setearemos la posicion de la pelota, ahora veamos el siguiente bloque:

	var left_pos = get_node("izquierda").position

	if (left_pos.y > 0 and Input.is_action_pressed("left_move_up")):
		left_pos.y += -PAD_SPEED * delta
	if (left_pos.y < screen_size.y and Input.is_action_pressed("left_move_down")):
		left_pos.y += PAD_SPEED * delta
	get_node("izquierda").set_position(left_pos)
Anuncios

En bloque vamos a ver varias lineas, en la primera vamos a crear una nueva variable donde se guardara la posicion de la paleta izquierda (left_pos), despues utilizaremos un condicional if donde verificaremos que el eje Y de la paleta izquierda sea mayor a cero y en la entrada sea apretada la accion left_move_up asignaremos el valor del eje Y de la posicion de la paleta a traves de la inversion de la constante de la velocidad de la pelota y a su vez multiplicarlo por delta, en el siguiente condicional if chequearemos si el eje Y de la posicion de la paleta sea menor al eje Y del tamaño de la pantalla y en la entrada sea apretada left_move_up sera asignado un nuevo valor al eje Y de la posicion de la paleta a traves de la constante de la velocidad de la paleta multiplicado por delta, una vez pasado este bloque en la siguiente linea asignaremos una nueva posicion a la paleta izquierda con la variable de posicion de la paleta, es decir este bloque es el encargado de permitir a la paleta izquierda moverse. Hay otro bloque mas pero como se imaginaran hace exactamente lo mismo solamente para la paleta derecha.

Con esto terminamos nuestro primer juego, y como para no estar fuera de la moda de los juegos actuales tiene un par de bugs que no pude arreglar, je, en realidad este juego era el primer ejemplo para el motor anterior, la version 2.1, pero en realidad el primer juego es otro para el nuevo motor, version 3.0, y me parecio muy dificil para ser un primer ejemplo asi que decidi intentar adaptar el anterior, grave error porque estuve dos dias completos solucionando la compatibilidad pero si llegaron hasta aca es porque pude solucionarlo pero como habran visto es un juego muy practico y sencillo para entender nuestras primeras interacciones sobre todo con las colisiones, les muestro un video de ejemplo

Anuncios

En resumen, hemos realizado nuestro primer juego, hemos visto como crear los sprites, asignarles “texturas”, establecerlos en la pantalla y por ultimo hicimos nuestro primer script donde pusimos en movimiento una pelota e interactuamos con nuestras paletas. Espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00