[B2D] Topdown Shooter KI

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Eingeproggt

Betreff: [B2D] Topdown Shooter KI

BeitragMo, Sep 14, 2009 19:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja Hallo!

Ich hab schon lang nix mehr fertig gekriegt und da dachte ich mir einfach mal dass ich mich an was Kleinem versuche.
Ein vollwertiger Shooter mit LAN / KI / Graphikeffekten / Story / Scripting / wasweißich wäre etwas zu viel, daher hab ich mich nur der KI angenommen Smile

Hier mal ein Beispiel wie man eine 2D-Topdown-Shooter-KI (auf freiem Feld. Die Berücksichtigung einer Map welcher Art auch immer müsste man selber machen) angehen könnte (inklusive Bots in Teams kämpfen lassen, sogar ein wenig steuern)

BlitzBasic: [AUSKLAPPEN]
Global gfx_w=800
Global gfx_h=800
Graphics gfx_w,gfx_h,0,2
SetBuffer BackBuffer()
AppTitle "TopDown-Shooter-KI-Test auf offenem Feld mit Teambildung"
SeedRnd MilliSecs()

Global ctrl_mhit,ctrl_mx,ctrl_my

Local timer=CreateTimer(50)

Const MODE_ERKUNDEN=0
Const MODE_STICK_TOGETHER=-1
Const MODE_DEFENSE=-2

Type team
;Basis-Koordinaten
Field x,y
;Farbe
Field r,g,b
;Statistik
Field kills,loss
Field members

Field friendlyfire

;Team-spezifische Werte
Field leben
Field schaden
Field speed#
Field radius
Field schussinterval

;Strategie & Befehligung
Field mode
Field leader.player ;Für Stick-together-modus
End Type

Type player
Field x#,y#,w
Field leben
Field mode
Field team.team
Field movetimer
Field schusstimer
Field offsetx,offsety
End Type

Type shot
Field x#,y#,w
Field player.player
Field team.team
End Type

;Default-Teams
CreateTeam(50,50,10,20,4,1,100,700) ;Großer Schaden, sonst eher schwach
CreateTeam(gfx_w-50,gfx_h-50,10,25,1,2,150,500) ;Wenig Schaden, sonst eher gut
CreateTeam(gfx_w-50,50,10,10,2,1.5,80,1000) ;Sollten ziemlich abloosen
CreateTeam(50,gfx_h-50,10,40,3,1,200,1200) ;Panzer-artig

;Super-Rambo
CreateTeam(gfx_w/2,gfx_h/2,1,100,5,0,200,200)

Global team_count=5 ;Für Einstellungs-Menu

;Start-Einstellungen
.menu
Repeat
MouseInput()

Rect gfx_w-150,10,100,20,0
Text gfx_w-100,12,"Kampf!",1
If ctrl_mhit Then
If ctrl_mx>gfx_w-150 And ctrl_mx<gfx_w-50 And ctrl_my>10 And ctrl_my<30 Then
Goto simu
EndIf
EndIf

Settings()

Flip 0:Cls
WaitTimer timer
Until KeyHit(1)
End

;Hauptschleife
.simu
Reset()
anfang=MilliSecs()
Repeat
start=MilliSecs()
MouseInput()

UpdatePlayer()

UpdateShots()

HUD()

Color 255,255,255
Text gfx_w/2,gfx_h-25,"FPS: "+(1000.0/(MilliSecs()-start)),1
Text gfx_w/2,10,"Spielzeit: "+((MilliSecs()-anfang)/1000),1

Flip 0:Cls
WaitTimer timer
Until KeyHit(1)
Goto menu

Function MouseInput()
ctrl_mx=MouseX()
ctrl_my=MouseY()
ctrl_mhit=MouseHit(1)
End Function

Function CreateTeam(spawnx,spawny,anzahl,leben,schaden,speed,radius,schussinterval)
Local team.team=New team
team\x=spawnx
team\y=spawny
team\r=Rand(50,255)
team\g=Rand(50,255)
team\b=Rand(50,255)
team\friendlyfire=True
team\leben=leben
team\schaden=schaden
team\speed=speed
team\radius=radius*radius
team\schussinterval=schussinterval
team\members=anzahl

Local pl.player
For i=1 To team\members
pl=New player
If i=1 Then team\leader=pl
pl\team=team
Respawn(pl)
Next
End Function

Function Reset()
Delete Each shot
Delete Each player
Local team.team
Local pl.player
For team=Each team
For i=1 To team\members
pl=New player
If i=1 Then team\leader=pl
pl\team=team
Respawn(pl)
Next
Next
End Function

Function Respawn(pl.player)
pl\leben=pl\team\leben
pl\x=pl\team\x+Rand(-20,20)
pl\y=pl\team\y+Rand(-20,20)
pl\offsetx=Rand(-30,30)
pl\offsety=Rand(-30,30)
pl\w=Rand(0,359)
End Function

Function UpdatePlayer()
Local size=15
Local pl.player,pl2.player
Local shot.shot
Local msecs=MilliSecs()
For pl=Each player
If pl\mode=MODE_ERKUNDEN Then
ok=True
;Bewegen
If pl\team\mode=MODE_STICK_TOGETHER Then
If pl<>pl\team\leader Then
ok=False
pl\w=ATan2(pl\team\leader\y-pl\y+pl\offsety,pl\team\leader\x-pl\x+pl\offsetx)
EndIf
EndIf
If ok Then
If msecs-pl\movetimer>3000 Then
pl\w=pl\w+Rand(-50,50)
pl\movetimer=msecs
EndIf
EndIf
pl\x=pl\x+Cos(pl\w)*pl\team\speed
pl\y=pl\y+Sin(pl\w)*pl\team\speed
If pl\x<0 Or pl\x>gfx_w Or pl\y<0 Or pl\y>gfx_h Then pl\w=pl\w+90
If pl\team\mode=MODE_DEFENSE Then
If (pl\x-pl\team\x)*(pl\x-pl\team\x)+(pl\y-pl\team\y)*(pl\y-pl\team\y)>100*100 Then
pl\w=ATan2(pl\team\y-pl\y+pl\offsety,pl\team\x-pl\x+pl\offsetx)
EndIf
EndIf
;Gegner checken
For pl2=Each player
If pl\team<>pl2\team Then
If (pl\x-pl2\x)*(pl\x-pl2\x)+(pl\y-pl2\y)*(pl\y-pl2\y)<pl\team\radius Then
pl\mode=Handle(pl2)
Exit
EndIf
EndIf
Next
Else
;Angreifen
pl2=Object.player(pl\mode)
If pl2=Null Then
pl\mode=0
Else
pl\w=ATan2(pl2\y-pl\y,pl2\x-pl\x)
If msecs-pl\schusstimer>pl\team\schussinterval Then
shot=New shot
shot\x=pl\x
shot\y=pl\y
shot\w=pl\w
shot\player=pl
shot\team=pl\team
;Line pl\x,pl\y,pl2\x,pl2\y
pl\schusstimer=msecs
EndIf
If (pl\x-pl2\x)*(pl\x-pl2\x)+(pl\y-pl2\y)*(pl\y-pl2\y)>pl\team\radius Then
pl\mode=0
EndIf
EndIf
EndIf

;Zeichnen
Color pl\team\r,pl\team\g,pl\team\b
Oval pl\x-(size/2),pl\y-(size/2),size,size,0
Line pl\x,pl\y,pl\x+Cos(pl\w)*size,pl\y+Sin(pl\w)*size
Next
End Function

Function UpdateShots()
Local shot.shot
Local pl.player
Color 255,255,255
For shot=Each shot
;Bewegen
shot\x=shot\x+Cos(shot\w)*15
shot\y=shot\y+Sin(shot\w)*15
If shot\x<0 Or shot\x>gfx_w Or shot\y<0 Or shot\y>gfx_h Then
Delete shot
Else
;Kollisions-Check
For pl=Each player
If pl<>shot\player Then
If shot\team\friendlyfire=True Or shot\team<>pl\team Then
If (pl\x-shot\x)*(pl\x-shot\x)+(pl\y-shot\y)*(pl\y-shot\y)<8*8 Then
pl\leben=pl\leben-shot\team\schaden
If pl\leben<=0 Then
If shot\player<>Null Then shot\player\mode=0
shot\team\kills=shot\team\kills+1
pl\team\loss=pl\team\loss+1
;Delete pl
Respawn(pl)
EndIf
Delete shot
Exit
EndIf
EndIf
EndIf
Next
;Zeichnen
If shot<>Null Then Oval shot\x-1,shot\y-1,2,2,1
EndIf
Next
End Function

Function HUD()
Local team.team
For team=Each team
Color team\r,team\g,team\b
Oval team\x-80,team\y-80,160,160,0
If (ctrl_mx-team\x)*(ctrl_mx-team\x)+(ctrl_my-team\y)*(ctrl_my-team\y)<80*80 Then
Text team\x,team\y-20,"Kills: "+team\kills,1
Text team\x,team\y-5,"Verluste: "+team\loss,1
Select team\mode
Case MODE_ERKUNDEN
Text team\x,team\y+10,"Erkunden",1
Case MODE_STICK_TOGETHER
Text team\x,team\y+10,"Geschlossenes Team",1
Case MODE_DEFENSE
Text team\x,team\y+10,"Verteidigung",1
End Select
If ctrl_mhit Then
team\mode=(team\mode-1) Mod 3
EndIf
EndIf
Next
End Function

; Funktionen fürs Einstellungs-Menu

Function Settings()
Text 10,10,"Anzahl der Teams: "+team_count
Line 10,30,150,30
Oval 10+team_count*4-2,25,4,10,1
If MouseDown(1) Then
If ctrl_my>25 And ctrl_my<35 Then
If ctrl_mx>10 And ctrl_mx<150 Then
team_count=(ctrl_mx-10)/4+1
EndIf
EndIf
EndIf

Rect 10,50,70,20,0
Text 12,52,"Spawn-x"
Rect 80,50,70,20,0
Text 82,52,"Spawn-y"
Rect 150,50,95,20,0
Text 152,52,"Mitglieder"
Rect 245,50,60,20,0
Text 247,52,"Leben"
Rect 305,50,70,20,0
Text 307,52,"Schaden"
Rect 375,50,70,20,0
Text 377,52,"Geschw."
Rect 445,50,70,20,0
Text 447,52,"Radius"
Rect 515,50,130,20,0
Text 517,52,"Schussintervall"
Rect 645,50,110,20,0
Text 647,52,"FriendlyFire"

Local team.team
Local y=0
For team=Each team
team\x=InputField(10,70+y*20,70,20,team\x)
team\y=InputField(80,70+y*20,70,20,team\y)
team\members=InputField(150,70+y*20,95,20,team\members)
team\leben=InputField(245,70+y*20,60,20,team\leben)
team\schaden=InputField(305,70+y*20,70,20,team\schaden)
team\speed=InputField(375,70+y*20,70,20,team\speed)
team\radius=InputField(445,70+y*20,70,20,Sqr(team\radius))^2
team\schussinterval=InputField(515,70+y*20,130,20,team\schussinterval)
If ctrl_mhit Then
If ctrl_mx>645 And ctrl_mx<645+110 And ctrl_my>70+y*20 And ctrl_my<70+y*20+20 Then
team\friendlyfire=Not team\friendlyfire
EndIf
EndIf
Rect 645,70+y*20,110,20,0
If team\friendlyfire Then
Text 647,72+y*20,"An"
Else
Text 647,72+y*20,"Aus"
EndIf

y=y+1
Next
If y>team_count Then
For i=1 To (y-team_count)
Delete Last team
Next
ElseIf y<team_count Then
For i=1 To (team_count-y)
team=New team
team\r=Rand(50,255)
team\g=Rand(50,255)
team\b=Rand(50,255)
Next
EndIf
End Function

Function InputField(x,y,w,h,txt$)
Local ret$=txt$
Rect x,y,w,h,0
Text x+2,y+2,txt$
If ctrl_mhit Then
If ctrl_mx>x And ctrl_mx<x+w And ctrl_my>y And ctrl_my<y+h Then
Color 0,0,0
Rect x+1,y+1,w-2,h-2,1
Color 255,255,255
Flip 0
Locate x+2,y+2
ret$=Input("")
EndIf
EndIf
Return ret$
End Function


Man verzeihe mir, dass der Code kaum kommentiert ist Sad
Bin irgenwie zu faul, aber wenn sich wer echt dafür interessiert werde ich mich anstrengen.

Um die KI in einem eigenen Spiel zu benutzen braucht ihr alle 3 Types, die Konstanten und die Functionen CreateTeam, Reset, UpdatePlayer, UpdateShots und event. Respawn.

Viel Spass beim zuschauen und herumspielen damit.

Achja, wie spielt man das überhaupt? Man kann nur im Einstellungsmenu die Team-Attribute festlegen. Dazu einfach mit der Maus in die Felder klicken und Werte eingeben.
"Ingame" kann man mit der Maus auf die bunten Kreise (Team-Basen) fahren und sich dort den Punktestand anschauen. Bei Klick auf diesen Kreis wird die Team-Taktik geändert. Es gibt "Erkunden", "Geschlossenes Team" und "Verteidigung".
Das Einstellungsmenu ist natürlich kein optischer oder funktionaler Leckerbissen, es tut nur seine Pflicht...

mfG, Christoph.

EDIT 9.1.2010: Code Tags in BB-Code-Tags geändert.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9
  • Zuletzt bearbeitet von Eingeproggt am Sa, Jan 09, 2010 16:04, insgesamt einmal bearbeitet

Nicdel

BeitragMo, Sep 14, 2009 19:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Nicht schön aber sehr funktional Very Happy
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group