ObjectSight() kuville (Raycast)

Oletko tehnyt jotain, mistä muut voisivat hyötyä. Postita vinkit tänne.
Post Reply
User avatar
Misthema
Advanced Member
Posts:312
Joined:Mon Aug 27, 2007 8:32 pm
Location:Turku, Finland
Contact:
ObjectSight() kuville (Raycast)

Post by Misthema » Mon Jan 09, 2012 2:01 pm

Olen siis koodaillut jo melkein kolme viikkoa peliä DroneWars jossa tosiaan käytän pelkkiä kuvia (myös karttaformaatti on omaa käsialaa, joten muutin tähän funktioon GetMap:n että toimii cb:n karttojen kanssa). Halusin myös ettei vihollisia näkisi toisesta huoneesta suoraan, joten irkissä minulle sitten ehdotettiin raycasting:iä ja sehän toimi vallan mainiosti.

Esimerkkikoodi ja funktio:

Code: Select all

SCREEN 640,480

SW=ScreenWidth()/2-32
SH=ScreenHeight()/2-32

DrawToWorld ON

Type ENEMY
    Field x
    Field y
    Field can_see
EndType

map=LoadMap("media\testmap.til", "media\tileset.bmp")

plyX=0
plyY=64

For i=0 To 500
    e.ENEMY = New(ENEMY)
    e\x=Rand(-SW,SW)
    e\y=Rand(-SH,SH)
Next i

Repeat
    DrawGame
    
    plyX = plyX + (RightKey()-LeftKey())*2
    plyY = plyY + (UpKey()-DownKey())*2
    
    If MouseHit(1)
        e.ENEMY = New(ENEMY)
        e\x=MouseWX()
        e\y=MouseWY()
    EndIf

    start=Timer()
    scanned_enemies=0
    For e.ENEMY = Each ENEMY
        
        If e\can_see Then Color cbgreen Else Color cbred
        Circle e\x-5,e\y+5,10
        
        If Distance(plyX,plyY, e\x,e\y)<160
            'Muuta kahta viimeistä arvoa ja huomaa ero
            e\can_see = CanSee(plyX,plyY,e\x,e\y, 8,8)
            scanned_enemies+1
        Else
            e\can_see = 0
        EndIf
    Next e
    ms=Timer()-start
    
    Color cbBlue
    Circle plyX-5,plyY+5,10
            
    _text$=scanned_enemies+" scans in "+ms+"ms"
    
    Color 255,255,255
    Text 2,2,_text
    
    DrawScreen

Forever

Function CanSee(p1X,p1Y, p2X,p2Y,_steps=8,approx=8)
    dest_ang#=GetAngle(p1X,p1Y, p2X,p2Y)
    dest_dist#=Distance(p1X,p1Y, p2X,p2Y)
    For d=0 To dest_dist/_steps
        px#=p1X+Cos(dest_ang)*(d*_steps)
        py#=p1Y-Sin(dest_ang)*(d*_steps)
        If Distance(px,py,p2X,p2Y)<=approx
            Color cbgreen       // Poista piirtofunktiot
            Line p1X,p1Y,px,py  // ellet koe tarvetta
            Return 1
        EndIf
        If GetMap(2,px,py)=1 Then
            Color cbred         // Poista piirtofunktiot
            Line p1X,p1Y,px,py  // ellet koe tarvetta
            Return 0
        EndIf
    Next d
EndFunction
Funktio:

Code: Select all

Function CanSee(p1X,p1Y, p2X,p2Y,_steps=8,approx=8)
    dest_ang#=GetAngle(p1X,p1Y, p2X,p2Y)
    dest_dist#=Distance(p1X,p1Y, p2X,p2Y)
    For d=0 To dest_dist/_steps
        px#=p1X+Cos(dest_ang)*(d*_steps)
        py#=p1Y-Sin(dest_ang)*(d*_steps)
        If Distance(px,py,p2X,p2Y)<=approx
            'Color cbgreen       // Poista piirtofunktiot
            'Line p1X,p1Y,px,py  // ellet koe tarvetta
            Return 1
        EndIf
        If GetMap(2,px,py)=1 Then
            'Color cbred         // Poista piirtofunktiot
            'Line p1X,p1Y,px,py  // ellet koe tarvetta
            Return 0
        EndIf
    Next d
EndFunction

Jos teillä on lisättävää tai löydätte jotain optimoitavaa, kertokaa siitä myös minulle. Tämä siis on käytössä pelissäni joten olisi ihan mukava jos jotain optimoitavaa olisi. :D

User avatar
Latexi95
Guru
Posts:1165
Joined:Sat Sep 20, 2008 5:10 pm
Location:Lempäälä

Re: ObjectSight() kuville (Raycast)

Post by Latexi95 » Mon Jan 09, 2012 5:03 pm

Misthema wrote:
Eikös tämä ole käytännössä ObjectsSight funktio, mutta toimii koordinaateilla objectien sijaan? Tuo kyllä selvittää törmäyskohdatkin, mikä ObjectSightia käyttämällä ei selviä. ObjectSight on kuitenkin nopeampi. Tein tuohon esimerkkiisi kaksi globaalia MakeObjectilla luotua tyhjää objektia ja asetin ne aina funktion alussa annettuihin koordinaatteihin ja palautin ObjectSightilla saadun vastauksen. ObjectSightilla toimiva funktio vei yleensä 8ms suorittaa ja tuo sinun CanSee funktiosi vei keskimäärin 10ms.

User avatar
MaGetzUb
Guru
Posts:1715
Joined:Sun Sep 09, 2007 12:35 pm
Location:Alavus

Re: ObjectSight() kuville (Raycast)

Post by MaGetzUb » Mon Jan 09, 2012 5:28 pm

Kröh-köhöm: Trolololoo
Mutta juu taitaa sinulla olla nopeampi systeemi... :D
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

User avatar
Misthema
Advanced Member
Posts:312
Joined:Mon Aug 27, 2007 8:32 pm
Location:Turku, Finland
Contact:

Re: ObjectSight() kuville (Raycast)

Post by Misthema » Mon Jan 09, 2012 5:39 pm

MaGetzUb wrote:Kröh-köhöm: Trolololoo
Mutta juu taitaa sinulla olla nopeampi systeemi... :D
Tuota taisin ensimmäisenä kokeilla pelissäni, mutta oli törkeän hidas jopa 25:llä vihollisella.
Latexi95 wrote:
Misthema wrote:
Eikös tämä ole käytännössä ObjectsSight funktio, mutta toimii koordinaateilla objectien sijaan? Tuo kyllä selvittää törmäyskohdatkin, mikä ObjectSightia käyttämällä ei selviä. ObjectSight on kuitenkin nopeampi. Tein tuohon esimerkkiisi kaksi globaalia MakeObjectilla luotua tyhjää objektia ja asetin ne aina funktion alussa annettuihin koordinaatteihin ja palautin ObjectSightilla saadun vastauksen. ObjectSightilla toimiva funktio vei yleensä 8ms suorittaa ja tuo sinun CanSee funktiosi vei keskimäärin 10ms.
Joo, ObjectSight on varmasti nopeampi kuin minun funktioni, sehän on sanomattakin selvää koska se on runtime:ssä. Tämän funktion tarkoitus onkin olla käytössä peleissä joissa ei objekteja käytetä lainkaan, kuten minun pelissäni. Ainoa objekteihin liittyvä tuossa esimerkissä on on CB:n oma kartta.

User avatar
Latexi95
Guru
Posts:1165
Joined:Sat Sep 20, 2008 5:10 pm
Location:Lempäälä

Re: ObjectSight() kuville (Raycast)

Post by Latexi95 » Mon Jan 09, 2012 5:43 pm

Misthema wrote: Joo, ObjectSight on varmasti nopeampi kuin minun funktioni, sehän on sanomattakin selvää koska se on runtime:ssä. Tämän funktion tarkoitus onkin olla käytössä peleissä joissa ei objekteja käytetä lainkaan, kuten minun pelissäni. Ainoa objekteihin liittyvä tuossa esimerkissä on on CB:n oma kartta.
Ai niin totta. Unohdin, että käytit omaa kartta moottoria, niin ObjectSight ei toimikkaan.

User avatar
MaGetzUb
Guru
Posts:1715
Joined:Sun Sep 09, 2007 12:35 pm
Location:Alavus

Re: ObjectSight() kuville (Raycast)

Post by MaGetzUb » Mon Jan 09, 2012 8:14 pm

Misthema wrote:
MaGetzUb wrote:Kröh-köhöm: Trolololoo
Mutta juu taitaa sinulla olla nopeampi systeemi... :D
Tuota taisin ensimmäisenä kokeilla pelissäni, mutta oli törkeän hidas jopa 25:llä vihollisella.
Funktioni vain ei käytä kerto- ja jakolaskuja, en tiedä mistä hitaus johtunee.. Noh kai CB ei vain hyväksy metodiani. :P
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

vieras_misthemaprkl

Re: ObjectSight() kuville (Raycast)

Post by vieras_misthemaprkl » Mon Jan 09, 2012 11:17 pm

MaGetzUb wrote:
Misthema wrote:
MaGetzUb wrote:Kröh-köhöm: Trolololoo
Mutta juu taitaa sinulla olla nopeampi systeemi... :D
Tuota taisin ensimmäisenä kokeilla pelissäni, mutta oli törkeän hidas jopa 25:llä vihollisella.
Funktioni vain ei käytä kerto- ja jakolaskuja, en tiedä mistä hitaus johtunee.. Noh kai CB ei vain hyväksy metodiani. :P
Juu, en minäkään ymmärrä mistä johtuu, mutta on todella hidas:

Code: Select all

Global HitX, HitY
DrawToWorld ON //Primitiivien piirto maailmaan mahdolliseksi

//Kartta..
map = LoadMap("Media\cdm2.til", "Media\tileset.bmp")
DrawToWorld ON

Type enemy
    Field x
    Field y
    Field cansee
EndType

mw=ObjectSizeX(map)/2
mh=ObjectSizeY(map)/2

For i=1 To 500
    en.enemy=New(enemy)
    en\x=Rand(-mw,mw)
    en\y=Rand(-mh,mh)
    en\cansee=0
Next i

Repeat 

    DrawGame 
    
    If KeyHit(cbKeySpace) Then draw = Not draw

    scans=0
    start=Timer()
    For e.enemy = Each enemy
        e\cansee = ClearSight(0, 0, e\x,e\y)
        If Not e\cansee Then 
            pointX = HitX
            pointY = HitY
            If draw
                Color cbwhite
                Line 0, 0, e\x,e\y
                Color cbred
                Circle pointX - 5, pointY + 5, 10, 0
            EndIf
        EndIf
        scans+1
    Next e
    ms=Timer()-start
    
    SetWindow ""+FPS()+" | "+scans+" scans in "+ms+"ms"

DrawScreen
Forever



Function ClearSight(AloitusX, AloitusY, LopetusX, LopetusY)
    If AloitusX = LopetusX And AloitusY = LopetusY Then Return True //Palautetaan 1 jos koordinaatit ovat päällekäin.
    If GetMap(2, AloitusX, AloitusY) Then HitX = LopetusX : HitY = LopetusY : Return False //Heti ekassa kohdassa oli seinää, palautetaan 0.
    Hyppy = False
    ErotusX = LopetusX - AloitusX 
    If ErotusX > 0 Then
        HyppyX = 1
    Else
        HyppyX = -1
    EndIf
    ErotusY = LopetusY - AloitusY
    If ErotusY > 0 Then
        HyppyY = 1
    Else
        HyppyY = -1
    EndIf
    ErotusX = Abs(ErotusX)
    ErotusY = Abs(ErotusY)
    If ErotusY > ErotusX Then
        Hyppy = True
        RdX = AloitusX
        AloitusX = AloitusY
        AloitusY = RdX
        RdX = ErotusX
        ErotusX = ErotusY
        ErotusY = RdX 
        RdX = HyppyX
        HyppyX = HyppyY
        HyppyY = RdX
    EndIf
    Erotus = (ErotusY + ErotusY) - ErotusX
    For i = 0 To ErotusX
        Color cbred
        If Hyppy Then
            If GetMap(2, AloitusY, AloitusX) Then HitX = AloitusY : HitY = AloitusX : Return False //O-ou tuli seinä vastaan palautetaan 0.
        Else
            If GetMap(2, AloitusX, AloitusY) Then HitX = AloitusX : HitY = AloitusY : Return False //Ja taas tuli seinä vastaan palautetaan 0. 
        EndIf
        While Erotus => 0
            AloitusY = AloitusY + HyppyY
            Erotus = Erotus - (ErotusX + ErotusX)
        Wend
        AloitusX = AloitusX + HyppyX
        Erotus = Erotus + (ErotusY + ErotusY)
    Next i
    //Jos päästiin tänne asti, niin näköyhteys on selvä ja palautetaan 1. \o/
    Return True  
EndFunction

Code: Select all

SCREEN 640,480

SW=ScreenWidth()/2-32
SH=ScreenHeight()/2-32

DrawToWorld ON

Type ENEMY
    Field x
    Field y
    Field can_see
EndType

map=LoadMap("media\testmap.til", "media\tileset.bmp")

plyX=0
plyY=64

For i=0 To 500
    e.ENEMY = New(ENEMY)
    e\x=Rand(-SW,SW)
    e\y=Rand(-SH,SH)
Next i

Repeat
    DrawGame
    
    plyX = plyX + (RightKey()-LeftKey())*2
    plyY = plyY + (UpKey()-DownKey())*2
    
    If MouseHit(1)
        e.ENEMY = New(ENEMY)
        e\x=MouseWX()
        e\y=MouseWY()
    EndIf

    start=Timer()
    scanned_enemies=0
    For e.ENEMY = Each ENEMY
        
        If e\can_see Then Color cbgreen Else Color cbred
        Circle e\x-5,e\y+5,10
        
        If Distance(plyX,plyY, e\x,e\y)<SW*2
            'Muuta kahta viimeistä arvoa ja huomaa ero
            e\can_see = CanSee(plyX,plyY,e\x,e\y, 32)
            scanned_enemies+1
        Else
            e\can_see = 0
        EndIf
    Next e
    ms=Timer()-start
    
    Color cbBlue
    Circle plyX-5,plyY+5,10
            
    _text$=scanned_enemies+" scans in "+ms+"ms"
    
    Color 255,255,255
    Text 2,2,_text
    
    DrawScreen

Forever

Function CanSee(p1X,p1Y, p2X,p2Y,_steps=8,approx=8)
    dest_ang#=GetAngle(p1X,p1Y, p2X,p2Y)
    dest_dist#=Distance(p1X,p1Y, p2X,p2Y)
    While d<dest_dist/_steps
    'For d=0 To dest_dist/_steps
        px#=p1X+Cos(dest_ang)*(d*_steps)
        py#=p1Y-Sin(dest_ang)*(d*_steps)
        If Distance(px,py,p2X,p2Y)<=approx
            Color cbgreen       // Poista piirtofunktiot
            Line p1X,p1Y,px,py  // ellet koe tarvetta
            Return 1
        EndIf
        If GetMap(2,px,py)=1 Then
            Color cbred         // Poista piirtofunktiot
            Line p1X,p1Y,px,py  // ellet koe tarvetta
            Return 0
        EndIf
        d+1
    'Next d
    Wend
EndFunction

Post Reply