data/manual/colisiones/index.html
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Colisiones - pilas-engine</title>
<link rel="shortcut icon" href="../img/favicon.ico">
<link href='https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="../css/theme.css" type="text/css" />
<link rel="stylesheet" href="../css/theme_extra.css" type="text/css" />
<link rel="stylesheet" href="../css/highlight.css">
<script>
// Current page data
var mkdocs_page_name = "Colisiones";
var mkdocs_page_input_path = "colisiones.md";
var mkdocs_page_url = "/colisiones/";
</script>
<script src="../js/jquery-2.1.1.min.js"></script>
<script src="../js/modernizr-2.8.3.min.js"></script>
<script type="text/javascript" src="../js/highlight.pack.js"></script>
<script src="../js/theme.js"></script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-nav-search">
<a href=".." class="icon icon-home"> pilas-engine</a>
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul class="current">
<li>
<li class="toctree-l1 ">
<a class="" href="..">Principal</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../que_juegos/">Tipos de juegos</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../instalacion/">Instalación</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../about/">Acerca de ...</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../empezando/">Empezando y los primeros pasos con pilas</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../actores/">Actores</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../actores_personalizados/">Actores personalizados</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../grupos/">Grupos</a>
</li>
<li>
<li>
<li class="toctree-l1 current">
<a class="current" href="./">Colisiones</a>
<ul>
<li class="toctree-l3"><a href="#colisiones-fisicas">Colisiones Físicas</a></li>
<li><a class="toctree-l4" href="#dos-tipos-de-colisiones">Dos tipos de colisiones</a></li>
<li><a class="toctree-l4" href="#modo-depuracion-fisica">Modo depuración física</a></li>
<li><a class="toctree-l4" href="#acceder-a-las-figuras-de-colision">Acceder a las figuras de colisión</a></li>
<li><a class="toctree-l4" href="#cambiando-las-figuras-de-colision">Cambiando las figuras de colisión</a></li>
<li><a class="toctree-l4" href="#deteccion-constante-de-colisiones">Detección constante de colisiones</a></li>
<li><a class="toctree-l4" href="#colisiones-con-etiquetas">Colisiones con etiquetas</a></li>
</ul>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../etiquetas/">Etiquetas</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../fisica/">Fisica</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../controles/">Controles</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../joystick/">Joystick</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../imagen/">Imagen</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../sonidos/">Audio: Sonidos y Música</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../dibujado_simple_en_pantalla/">Dibujado simple en pantalla</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../dibujado_avanzado_con_superficies/">Dibujado avanzado con Superficies</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../tareas/">Manejo de tiempo con tareas</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../interpolacion/">Interpolaciones</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../controlando_la_pantalla/">Controlando la pantalla</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../comportamientos/">Comportamientos</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../escenas/">Escenas</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../interfaz/">Interfaz de usuario</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../menu/">Cómo crear menúes para tu juegos</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../mapas_y_plataformas/">Mapas y plataformas</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../dialogos/">Diálogos</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../camara/">Manejo de Cámara</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../eventos/">Eventos</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../texto/">Textos</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../habilidades/">Habilidades</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../depurando/">Depurando</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../como_funciona_pilas_por_dentro/">¿Cómo funciona pilas por dentro?</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../complementos/">Complementos</a>
</li>
<li>
<li>
<li class="toctree-l1 ">
<a class="" href="../desarrolladores/">Guía para desarrolladores</a>
</li>
<li>
</ul>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="..">pilas-engine</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="..">Docs</a> »</li>
<li>Colisiones</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main">
<div class="section">
<h1 id="colisiones-fisicas">Colisiones Físicas</h1>
<p>El sistema de colisiones te permite disparar acciones cuando dos o más actores
entran en contacto. Esto nos permite hacer que los personajes puedan
chocar con enemigos, capturar objetos y mucho más.</p>
<h2 id="dos-tipos-de-colisiones">Dos tipos de colisiones</h2>
<p>En pilas-engine tenemos dos tipos de colisiones: colisiones
físicas y colisiones programadas.</p>
<p>Las <strong>colisiones físicas</strong> son aquellas que generan una reacción que se puede
visualizar como una respuesta física, por ejemplo si creamos 5 cajas y las
hacemos rebotar entre sí, estas serían colisiones físicas:</p>
<p><img alt="" src="../imagenes/colisiones/cajas.png" /></p>
<pre><code class="python">cajas = pilas.actores.Caja() * 5
</code></pre>
<p>Podríamos decir que las colisiones físicas son casi automáticas, las genera
el mismo motor de física que trae pilas-engine sin mucho código.</p>
<p>En cambio, las <strong>colisiones programadas</strong> son aquellas que tienen una reacción
por código, y generalmente tienen que ver con la lógica del juego (perder, ganar
puntos, pasar de nivel etc..)</p>
<p>Por ejemplo, una colisión programada sencilla se puede visualizar si creamos
un personaje que se pueda mover con el mouse y se alimente comiendo bananas:</p>
<p><img alt="" src="../imagenes/colisiones/mono.png" /></p>
<pre><code class="python">mono = pilas.actores.Mono()
mono.aprender("Arrastrable")
bananas = pilas.actores.Banana() * 10
def cuando_colisiona(mono, banana):
banana.eliminar()
mono.sonreir()
pilas.colisiones.agregar(mono, bananas, cuando_colisiona)
</code></pre>
<h2 id="modo-depuracion-fisica">Modo depuración física</h2>
<p>El modo depuración física nos permite observar las figuras físicas de
cada uno de los actores. Para activar este modo, podés pulsar la tecla <strong>F12</strong>
o simplemente hacer click sobre el ícono "mostrar figuras físicas":</p>
<p><img alt="" src="../imagenes/colisiones/depurador.png" /></p>
<p>Con este modo habilitado, vas a poder observar la figura de colisión
que lo representa:</p>
<p><img alt="" src="../imagenes/colisiones/ejemplo.png" /></p>
<p>En color blanco aparecen las figuras físicas, que al rebotar con otras
producirán una reacción de choque y rebote. Y de color verde van a aparecer
los sensores.</p>
<p>Los sensores son figuras físcias pero que no generan una reacción
al momento del choque.</p>
<h2 id="acceder-a-las-figuras-de-colision">Acceder a las figuras de colisión</h2>
<p>En muchos momentos vas a necesitar hacer ajustes sobre las figuras
de colisión. Lo mas común es cambiar el tamaño de las figuras (para ajustarlas
al tamaño del actor) o convertir las figuras a sensores.</p>
<p>Para acceder a las figuras de colisión tienes que usar el atributo
<code>figura_de_colisión</code> del actor, o bien cambiar su tamaño directamente
cambiando el atributo <code>radio_de_colisión</code> por ejemplo:</p>
<pre><code class="python">mono = pilas.actores.Mono()
mono.radio_de_colision = 30
mono.radio_de_colision = 80
mono.radio_de_colision = 10
</code></pre>
<p>Cada vez que asignes un valor al atributo <code>radio_de_colision</code>, pilas va a
generar una circunferencia y la va a colocar como figura de colisión para el
actor.</p>
<h2 id="cambiando-las-figuras-de-colision">Cambiando las figuras de colisión</h2>
<p>En la mayoría de los casos la figura circular es la que mejor se ajusta
al area de un actor.</p>
<p>Sin embargo, hay algunos casos en donde necesitamos cambiar completamente
la figura de colisión por otra.</p>
<p>La forma mas sencilla de cambiar una figura por otra, es crear la figura
física primero y luego asignarla a la propiedad <code>figura_de_colision</code> del
actor:</p>
<p><img alt="" src="../imagenes/colisiones/figuras.png" /></p>
<p>Para construir este ejemplo construímos dos actores, al primero lo dejamos
tal cual, pero al segundo le cambiamos la figura de colisión por un rectángulo:</p>
<pre><code class="python">zanahoria_normal = pilas.actores.Zanahoria(x=-100)
zanahoria = pilas.actores.Zanahoria(x=100)
rectangulo = pilas.fisica.Rectangulo(0, 0, 40, 100, sensor=True, dinamica=False)
zanahoria.figura_de_colision = rectangulo
</code></pre>
<h2 id="deteccion-constante-de-colisiones">Detección constante de colisiones</h2>
<p>Pilas también incluye un forma constante de detectar colisiones, algo que
puede ser mucho más sencillo de implementar en juegos de acción.</p>
<p>Cada figura física tiene una propiedad llamada <code>figuras_en_contacto</code> con
una lista de todas las figuras con las que colisiona.</p>
<p>Por ejemplo, tomemos de ejemplo un actor "Pelota". Si queremos consultar
si el actor Pelota está colisionando con alguna figura podemos ejecutar:</p>
<pre><code>>> pelota = pilas.actores.Pelota()
>> print(pelota.figura_de_colision.figuras_en_contacto)
</code></pre>
<p>Si el actor no colisiona con nada, se nos retornará una lista vacía:</p>
<pre><code>[]
</code></pre>
<p>En cambio, si el actor está en colisión con alguna figura, la lista
que se retornará contendrá al menos un elemento:</p>
<pre><code>[<Figura Rectangulo en (0, -240)>]
</code></pre>
<p>Este tipo de colisiones constantes son super útiles cuando creamos
actores personalizados (como se indica en el apartado
<a href="../actores_personalizados/">Actores personalizados</a>), ya que desde el método
actualizar vamos a poder comprobar colisiones constantemente.</p>
<p>Por ejemplo, para emitir un mensaje cada vez que se produce una colisión
podríamos escribir un código como el siguiente:</p>
<pre><code>indicador_de_colision = pilas.actores.Texto("HAY COLISION!", y=100)
indicador_de_colision.transparencia = 100
class PelotaTransparente(pilasengine.actores.Pelota):
def iniciar(self):
pilasengine.actores.Pelota.iniciar(self)
self.aprender('arrastrable')
def actualizar(self):
if self.figura_de_colision.figuras_en_contacto:
self.transparencia = 0
indicador_de_colision.transparencia = 0
else:
self.transparencia = 50
indicador_de_colision.transparencia = 100
pilas.actores.vincular(PelotaTransparente)
pilas.actores.PelotaTransparente()
pilas.actores.Aceituna()
</code></pre>
<p><img alt="" src="../imagenes/colisiones/colision_constante.gif" /></p>
<p>Eso sí, ten en cuenta que la lista de <code>figuras_en_contacto</code> no es una
referencia a los actores, sino la lista de figuras. Si lo que quieres es
obtener información de los actores tendrías que usar el atributo
<code>actor_que_representa_como_area_de_colision</code> de la figura.</p>
<p>Por ejemplo, podemos cambiar el código que maneja la colisión para
que indique si el actor que colisiona es aceituna o no:</p>
<p><img alt="" src="../imagenes/colisiones/colisiones_constantes_con_etiquetas.gif" /></p>
<pre><code>indicador_de_colision = pilas.actores.Texto("HAY COLISION!", y=100)
indicador_de_colision.transparencia = 100
def es_aceituna(actor):
return 'aceituna' in actor.etiquetas.lista
class PelotaTransparente(pilasengine.actores.Pelota):
def iniciar(self):
pilasengine.actores.Pelota.iniciar(self)
self.aprender('arrastrable')
def actualizar(self):
figura = self.figura_de_colision.figuras_en_contacto
if figura:
indicador_de_colision.transparencia = 0
self.cambiar_texto(figura[0])
else:
indicador_de_colision.transparencia = 100
def cambiar_texto(self, figura):
actor = getattr(figura, "actor_que_representa_como_area_de_colision", None)
if actor:
# Ha colisionado con una figura que tiene un actor enlazado.
if es_aceituna(actor):
indicador_de_colision.texto = "Colisiona con actor aceituna."
else:
indicador_de_colision.texto = "Colisiona con Actor, no es Aceituna!!!"
pilas.actores.vincular(PelotaTransparente)
pilas.actores.PelotaTransparente()
pilas.actores.Aceituna()
pilas.actores.Zanahoria(x=150)
</code></pre>
<h2 id="colisiones-con-etiquetas">Colisiones con etiquetas</h2>
<p>Ten en cuenta que existe un atajo para definir colisiones
usando el concepto de etiquetas, que se verá en la siguiente
página de este manual.</p>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="../etiquetas/" class="btn btn-neutral float-right" title="Etiquetas"/>Siguiente <span class="icon icon-circle-arrow-right"></span></a>
<a href="../grupos/" class="btn btn-neutral" title="Grupos"><span class="icon icon-circle-arrow-left"></span> Anterior</a>
</div>
<hr/>
<div role="contentinfo">
<p>
<!-- Copyright etc -->
</p>
</div>
Creado con <em>MkDocs</em>.
<script>
$(document).ready(function() {
$('img').each(function(elemento) {
if (this.src.indexOf('github.io') > 0) {
this.src = this.src.replace('github.io/imagenes', 'github.io/pilas-manual/imagenes');
}
});
});
</script>
<script>
$(document).ready(function() {
String.prototype.endsWith = function(suffix){
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
$('a').each(function(){
var x=this.href;
if (!this.href.endsWith('html') && this.href.indexOf('#') < 0 && this.href.indexOf('http://') === -1 && this.href.indexOf('https://') === -1) {
if (this.href.endsWith('/')) {
this.href = this.href + "index.html";
} else {
this.href = this.href + "/index.html";
}
}
});
});
</script>
<script>
function alternar_menu() {
var sidebar = document.querySelectorAll(".wy-nav-side")[0];
var left = sidebar.style.left;
if (left === "-300px") {
sidebar.style.left = "0px";
} else {
if (left === "0px") {
sidebar.style.left = "-300px";
} else {
sidebar.style.left = "0px";
}
}
}
$(document).ready(function() {
document.querySelector('ul.wy-breadcrumbs>li>a').onclick = function() {
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
if (w < 768) {
alternar_menu();
return false;
} else {
return true;
}
}
});
</script>
<style>
.rst-versions {
border: 0 !important;
}
.wy-nav-side {
padding-bottom: 50px;
}
.wy-nav-content-wrap {
background-color: white !important;
}
.wy-nav-content {
background-color: white !important;
}
.star {
display: inline-block !important;
width: 14px !important;
height: 14px !important;
background-image: url('/imagenes/star.png');
margin-bottom: -2px;
margin-left: 4px;
}
</style>
</footer>
<script type="text/javascript">
var dentro_de_pilas_engine = (document.location.href.indexOf('file://') === 0);
// Ocultando la barra de búsqueda
if (dentro_de_pilas_engine) {
var b = document.getElementsByName('q');
b[0].style.display = "none"
}
</script>
<style media="screen">
code {
font-size: 15px !important;
}
</style>
<style>
img {
width: auto !important;
}
pre {
padding: 0px !important;
}
.hljs {
font-size: 15px;
}
td {
padding: 15px;
text-align: center;
}
.wy-menu-vertical li.current {
background: #0B0B0B;
}
.wy-menu-vertical li.on a, .wy-menu-vertical li.current>a {
color: #FFFFFF;
padding: 0.4045em 1.618em;
font-weight: bold;
position: relative;
background: #6C6C6C;
border: none;
border-bottom: none;
border-top: none;
padding-left: 1.618em -4px;
}
.wy-menu-vertical li.current a {
color: rgb(186, 186, 186);
}
.wy-menu-vertical li.current a:hover {
background: #444444;
}
</pre>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" style="cursor: pointer">
<span class="rst-current-version" data-toggle="rst-current-version">
<span><a href="../grupos/" style="color: #fcfcfc;">« Previous</a></span>
<span style="margin-left: 15px"><a href="../etiquetas/" style="color: #fcfcfc">Next »</a></span>
</span>
</div>
</body>
</html>