Page 1 of 1

Line of Sight

Posted: Tue Jun 02, 2009 3:13 pm
by Koodiapina
Mietinpä tuossa, että mitenköhän saisi tehtyä hyvin toimivan Line of Sightin Roguelike-peliä varten. Algorithmin pitäisi yksinkertaisesti siis etsiä kaikki kohdat, joihin pelihahmo kykenee näkemään ja sitten merkata ne nähdyiksi. Homma vaikutti aluksi simppeliltä, mutta tekemäni viritelmä jätti joitain ruutuja havaitsematta.

Tässä omani, jotta kukaan ei postaisi samaa systeemiä.

Code: Select all

	for (float i=0; i<360; i++)
	{
		for (float a=0; a<12; a++)
		{
         // Location-olio kertoo pelaajan koordinaatit.
			int x = Location.x + Cos (i) *a;
			int y = Location.y + Sin (i) *a;
						
			Map.Sqr[x][y].Seen = 1;
						
			if (Map.HasCollision (x, y))
				break;
		}
	}
Nyt pyytäisinkin jotakuta tekemään kunnolla toimivan LOSsin. Kielellä ei ole väliä, koska pääasia on, että saan perusajatuksen selville :-)

Re: Line of Sight

Posted: Tue Jun 02, 2009 3:37 pm
by JATothrim
wikipeadia on ystäväsi: click! Tuon algotrimin "viivalla" kun skannaat karttaasi, niin ei pitäisi olla ongelmia. Et tarvitse ollenkaan trigonometrisiä fuktioita, sillä tuo algotrimi toimii pelkästään kokonaisluvuilla. En jaksa vääntää esimerkkiä, kun artikkelin 2. lähde kertoo kaiken.

Re: Line of Sight

Posted: Tue Jun 02, 2009 3:42 pm
by Koodiapina
Sillähän se onnistui. Kiitos paljon :-)

Re: Line of Sight

Posted: Tue Jun 02, 2009 6:53 pm
by otto90x
Teinpäs tuosta wikipedian mukaisen käännöksen CB:lle. Funktio MemBresenham laskee kahden pisteen välisten ruutujen koordinaatit järjestyksessä ja palauttaa ne muistipalassa, jonka ensimmäinen kokonaisluku on ruutujen määrä. Kun tarkistaa onko näissä ruuduissa seinää, saa helposti jätettyä piirtämättä seinän taakse jäävät ruudut.

Esimerkissä välilyönti piirtää viivan kahden ruudun välille ja matkalle osuvat ruudut värjäytyvät vihreän sävyihin.

Code: Select all

SCREEN 800,600


Const resolution = 40
Const size = 12

Repeat

    Color cbwhite
    For x=0 To resolution-1
        For y=0 To resolution-1
            Box x*size+10,y*size+10,size,size,0
        Next y
    Next x

    
    
    If mem Then
        
        määrä = PeekInt(mem,0)
    
        o=0
        For i=4 To MEMBlockSize(mem)-1 Step 8
            o+1
            xx=PeekInt(mem,i)
            yy=PeekInt(mem,i+4)
            
            
            väri# = 255-(Float(o)/float(määrä))*255.0
            
            Color 0,väri,0
            
            Box xx*size+10,yy*size+10,size,size,1
        Next i
        
        Color cbred
        Line lx*size+10+size/2,ly*size+10+size/2,lxx*size+10+size/2,lyy*size+10+size/2
    EndIf
    
    

    If KeyDown(cbkeyspace) Then
        If mem Then DeleteMEMBlock mem : mem=0
        lx=Rand(resolution-1)
        ly=Rand(resolution-1)
        lxx=Rand(resolution-1)
        lyy=Rand(resolution-1)
        
        mem = MemBresenham(lx,ly,lxx,lyy)
        ClearKeys
    EndIf


    DrawScreen
    
Forever

Function MemBresenham(x,y,xx,yy)

    mem=MakeMEMBlock(4)
    
    PokeInt mem,0,0

    lw=Abs(xx-x)
    lh=Abs(y-yy)
    
    w=Max(lh,lw)
    h=Min(lh,lw)
    
    If lw>lh Then
        
        If x<xx Then 
            s0=x
            t0=y
            s1=xx
            t1=yy
        Else
            s0=xx
            t0=yy
            s1=x
            t1=y
        EndIf
        
    Else
    
         If y<yy Then 
            s0=y
            t0=x
            s1=yy
            t1=xx
        Else
            s0=yy
            t0=xx
            s1=y
            t1=x
        EndIf
    EndIf
    
    If t0<t1 Then 
        tstep=1
    Else
        tstep=-1
    EndIf
    
    virhe = w/2
    
    t = t0
    
    For s=s0 To s1
    
        oldsize = MEMBlockSize(mem)
        ResizeMEMBlock mem,oldsize+8
        PokeInt mem,0,PeekInt(mem,0)+1

        If lw>lh Then 
            PokeInt mem,oldsize,s
            PokeInt mem,oldsize+4,t
        Else
            PokeInt mem,oldsize,t
            PokeInt mem,oldsize+4,s
        EndIf
        
        virhe = virhe + h
        If virhe >= w Then 
            t = t + tstep
            virhe = virhe - w
        EndIf
        
    Next s
    
    Return mem
        
End Function
EDIT: Taas hidastelin

Re: Line of Sight

Posted: Sun Aug 16, 2009 8:40 pm
by JATothrim
*BUMP* anteeksi nostosta, mutta ongelma painaa päälle. Ajattelin toteuttaa pikselin tarkan raycasterin otto90x koodin pohjalle. Funktiossa on kuitenkin yksi vika: 45-255 asteen kulmassa viiva tehdään "väärään suuntaan", mikä tekee funktion kelvottomaksi, koska pikselit pitäisi tarkistaa aina aloituspisteestä -> loppupisteeseen. :( koetin fiksata funktiota moneen kertaan, mutta en saanut sitä toimimaan kuten haluaisin. koetin jopa toista algotrimiä, mutta se rasteroi viivan hieman eri tavalla. (huonommin) apuja?

Re: Line of Sight

Posted: Thu Aug 20, 2009 9:44 am
by fella5s
Helpottaisi muuten hieman jos näkisi sen muutetun koodin.

Re: Line of Sight

Posted: Thu Aug 20, 2009 10:25 am
by JATothrim
En nähnyt tarvetta antaa koodia, koska jo otto90x alkuperäisessä versiossa on kyseinen ongelma. Oma viritelmäni on "väärin" toimiessaan tuottanut täysin samanlaisen tuloksen tai käyttökelvottoman (mm. viiva kohdistuu aivan väärin). Käyttökelvottomia koeversioita en ole edes tallentanut. Tarkoituksenani oli siis muokata otto90x koodia niin, että pikselit piirretään/iteroidaan aina "from(x, y) -> to(xx, yy)" vektorin suunnassa. Nykyinen versio kääntää järjestyksen väärinpäin 45-225 kulmissa.