2010-08-31 6 views
7

Quindi sto creando un gioco di difesa tower con HTML5 e Javascript. Il mio unico problema è quello di rilevare quando il mouse entra in contatto con il percorso dell'attaccante, che è necessario per impedire al giocatore di costruire torri sul percorso. Il path degli attacker è determinato nel file MAP.js (vedi il link in basso), da una matrice bidimensionale (un array contenente coppie x e y), quindi quello con cui devo lavorare è una serie di punti che creare un percorso quando connesso. Voglio semplicemente proibire al giocatore di posizionare torri entro, diciamo, 50 pixel del percorso. Per essere onesti, sono semplicemente pessimo con il rilevamento delle collisioni, quindi un aiuto sarebbe molto apprezzato.HTML5 Canvas: rilevamento collisione di mouse e poligoni

Ecco il link per tutto il codice: http://shapeshifting.comuv.com/Tower_Defense/td/

Come si può immaginare, solo i file .js sono applicabili, ma la maggior parte del codice in questione è all'interno del file objects.js. (Per favore, scusami la confusione)

risposta

2

Mi avvicinerei a questo passo. Diamo un'occhiata a ciò che inizi. Hai un percorso definito da punti: coppie di punti definiscono un segmento di linea. Quindi quello che hai veramente è un percorso fatto di segmenti di linea. Quando l'utente muove il mouse, otterrai le coordinate x, y della posizione corrente. Quello che vuoi fare è trovare la distanza del punto del mouse su tutti i segmenti della linea. Se è inferiore a 50 pixel da qualsiasi segmento di linea, quindi non si vuole consentire loro di costruire lì.

Per trovare la distanza tra un punto e un segmento di linea, lo pseudo codice appare così. Supponiamo che i punti A e B rappresentino entrambe le estremità di un segmento di linea e che il punto C sia il punto del mouse.

float distancePoint2LineSegment(Point a, Point b, Point c) { 
    Vector ab = b - a 
    Vector ac = c - a 
    Vector bc = c - b 

    float e = dotProduct(ac, ab) 
    if (e <= 0.0) 
    return sqrt(dotProduct(ac, ac)) 

    float f = dotProduct(ab, ab) 
    if (e >= f) 
    return sqrt(dotProduct(bc, bc)) 

    return sqrt(dotProduct(ac, ac) - e * e/f) 
} 

Questo sarebbe rispondere alla tua domanda di rilevamento delle collisioni, ma penso che ci si poi si desidera guardare le prestazioni. Quanti segmenti di linea saranno nel tuo percorso e vuoi calcolare la distanza di ogni segmento di linea ogni volta che l'utente muove il mouse? Puoi mettere i segmenti di linea in un quadrilatero in modo che tu debba solo testare le collisioni del punto del mouse con un numero minore di segmenti di linea.

2

Probabilmente più semplice e più veloce per definire le aree che l'utente può inserire torri in eplicitly nel file di mappa ... Definire ogni area come un poligono convesso (posibly anche i bordi della mappa, poligoni concavi dividere, preferiscono orizzontale o verticale linee, allora prova del mouse è in uno dei poligoni, questa risposta per un implementatio

How to test if a point is inside of a convex polygon in 2D integer coordinates?

decomposizione in triangoli rende il test ancora più semplice

3

rilevamento delle collisioni è una di quelle vecchie, nascosta problemi di codifica di un gioco: in genere le persone prendono il darkpenguin L 'approccio di precalcolare in qualche modo dove sulla tua mappa statica è e non è posizionabile. Il prossimo passo è trovare un modo per specificare la mappa collide più efficiente.

Non vuoi che il tuo gioco faccia un sacco di matematica in risposta all'utente che sposta il mouse - deve essere breve e veloce - quindi è molto importante eseguire il calcolo preliminare su qualcosa di veloce.

Se la mappa è una griglia, allora hai la tua risposta proprio lì - la mappa di collisione è una matrice 2D precalcolata - in pratica una piccola immagine in bianco e nero con un pixel per ogni posto sulla griglia di partenza. I pixel bianchi (1) sono posizionabili e i pixel neri (0) no. Basta usare questo array 2D di true/false come ricerca. Se vuoi risparmiare memoria puoi raggruppare ogni striscia di 32 spazi sulla griglia in un singolo bit flag.

Se la tua mappa non è una griglia, allora vuoi comunque precalcolare le cose, ma la strategia è un po 'più complessa. La prima possibilità è quella di eseguire matematiche come Hitesh per produrre una mappa collide leggermente più alta risoluzione, e il resto è esattamente come la strategia della griglia - quindi per esempio se ogni blocco 4x4 di pixel era un ingresso collide, allora se una torre può essere piazzato è un test per verificare se le sue coordinate si attestano su un numero sufficiente di 1 - potresti richiedere che il 100% dei test sia di 1, o potresti lasciare che raggiungano un po 'e lasciare che il 75% dei test sia di 1.

Se questo non è ancora abbastanza dettagliato, è possibile eseguire questi test di poligoni più complessi, ma si desidera che siano il più semplici possibile. Quando non si utilizza una griglia precalcolata, il test di collisione 2D più semplice è di 2 cerchi: basta calcolare la distanza tra i loro centri e verificare se è maggiore o minore della somma dei loro raggi. Se precalcoli il tuo percorso mostruoso in una serie di cerchi, il prossimo passo è dividere quei cerchi in ... indovina un po '... una griglia. Questo impedisce ad ogni controllo di dover testare ogni singolo cerchio sulla mappa. Questo ti permette di avere un numero elevato di questi cerchi nella mappa di collisione, poiché il test di collisione è prima una ricerca su quali voci della griglia sono attualmente finite, seguito da verificare se è in collisione con solo le cerchie a cui è più vicino, piuttosto che l'intera mappa È importante notare che questa griglia precalcolata di elenchi di cerchi avrà spesso la stessa cerchia in più voci di griglia adiacenti, poiché ogni voce di griglia che contiene una porzione di una determinata circonferenza deve avere quel cerchio nella sua checklist di collisione.

Una delle cose belle dei primi 2 approcci alla griglia è che è molto facile da parte del QA - archiviare letteralmente la mappa di collisione come immagine e ispezionarla visivamente per assicurarsi che appaia corretta per la mappa su cui è basata. Puoi anche disegnarlo a mano se non vuoi scrivere il codice per generarli.

L'approccio del cerchio ti dà curve legittime e può portare a dettagli di bordo più fini, ma è ovviamente più difficile testare e garantire che nessuna mappa abbia mappe di collisione cattive. È anche più lavoro per scrivere lo strumento di generazione della mappa.

Buona fortuna!