Line of Sight

Voit pyytää apua ohjelmointiongelmiin täältä.
Post Reply
Koodiapina
Forum Veteran
Posts: 2396
Joined: Tue Aug 28, 2007 4:20 pm

Line of Sight

Post 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 :-)
JATothrim
Tech Developer
Tech Developer
Posts: 606
Joined: Tue Aug 28, 2007 6:46 pm
Location: Kuopio

Re: Line of Sight

Post 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.
-On selkeästi impulsiivinen koodaaja joka...
ohjelmoi C++:lla rekursiivisesti instantioidun templaten, jonka jokainen instantiaatio instantioi sekundäärisen singleton-template-luokan, jonka jokainen instanssi käynistää säikeen tulostakseen 'jea'.
Koodiapina
Forum Veteran
Posts: 2396
Joined: Tue Aug 28, 2007 4:20 pm

Re: Line of Sight

Post by Koodiapina »

Sillähän se onnistui. Kiitos paljon :-)
otto90x
Advanced Member
Posts: 349
Joined: Mon Aug 27, 2007 9:00 pm
Location: Lapinjärvi, Finland
Contact:

Re: Line of Sight

Post 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
Otto Martikainen a.k.a. MetalRain, otto90x, kAATOSade.
Runoblogi, vuodatusta ja sekoiluja.
JATothrim
Tech Developer
Tech Developer
Posts: 606
Joined: Tue Aug 28, 2007 6:46 pm
Location: Kuopio

Re: Line of Sight

Post 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?
-On selkeästi impulsiivinen koodaaja joka...
ohjelmoi C++:lla rekursiivisesti instantioidun templaten, jonka jokainen instantiaatio instantioi sekundäärisen singleton-template-luokan, jonka jokainen instanssi käynistää säikeen tulostakseen 'jea'.
fella5s
Newcomer
Posts: 15
Joined: Tue Aug 18, 2009 6:08 pm

Re: Line of Sight

Post by fella5s »

Helpottaisi muuten hieman jos näkisi sen muutetun koodin.
JATothrim
Tech Developer
Tech Developer
Posts: 606
Joined: Tue Aug 28, 2007 6:46 pm
Location: Kuopio

Re: Line of Sight

Post 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.
-On selkeästi impulsiivinen koodaaja joka...
ohjelmoi C++:lla rekursiivisesti instantioidun templaten, jonka jokainen instantiaatio instantioi sekundäärisen singleton-template-luokan, jonka jokainen instanssi käynistää säikeen tulostakseen 'jea'.
Post Reply