multipoint [gdiplus]

  • [Blockierte Grafik: http://www10.pic-upload.de/27.11.12/lajan65nrtq.jpg]

    ich habe mal aus spaß ein multiplayer spiel geskriptet.
    das rote feld wird mit den pfeiltasten gesteuert und muss versuchen das, das blaue feld nicht mehr auf dem feld zusehen ist. das blaue feld wird mit wasd gesteuert und muss versuchen auf das rote feld zukommen.

    ändern der konstanten
    $MAP_SIZE die größe der karte auf der gespielt wird
    $SCREEN_SIZE bildschirmgröße
    $SPEED geschwindigkeit. je niedriger desto schneller
    $DENSITY die dichte der schwarzen felder. je niedriger desto mehr schwarze felder

    mit q könnt ihr die musik an oder aus machen

    neu
    ich habe nun das ganze auch nochmal in purebasic programmiert um mal den unterschied zu sehen
    autoit 50fps
    purebasic 60fps

    DOWNLOAD

    freue mich über kritik

    Einmal editiert, zuletzt von gem (28. November 2012 um 02:25)

  • find das ganze schon ziemlich geil :D Gut gemacht ;)

    Ps: Bei mir hackt das aber trotzdem bisschen obwohl es konstant über 70 fps bleibt.
    Ps2: In deinem Code den du hochgeladen hat ist das #include für gdiplus.au3 falsch geschrieben nur als Hinweis

    :thumbup:

  • bobekos

    danke :)

    1. ich glaub das liegt daran das sich die felder nicht dynamisch sondern ruckartig bewegen . das werde ich aber in der nächsten version ändern. da wird dann auch das blaue feld einen eigeen bilschirm bekommen

    2. achso das habe ich vergessen ich nutze die GDIP.au3 LINK weil dort mehr funktionen drin sind, die ich aber bei diesem skript garnicht genutzt habe . das habe ich vergessen, nächstes mal nehm ich die normale

  • Wenn du eine flüssige Animation willst, musst du den Zeichenvorgang aus der GUIMessage Schleife nehmen. GUIGetMsg wartet eine gewisse Zeit wenn der Mauszeiger nicht über der GUI ist und verzögert so die Animation wenn die Maus sich außerhalb der GUI befindet.
    Es gibt schon seit einiger Zeit ein paar kleine Tricks wie man eine Animation / ein Spiel mit GDI+ möglichst gut umsetzt. Wenn du willst, kannst du ja mal das Forum nach ein paar fertigen Spielen durchstöbern (oder in meine Signatur schauen).
    Ganz perfekt kriegt man das aber trotzdem nicht hin, da sind GDI+ nun mal gewisse Limits gesetzt.
    Dein Spiel gefällt mir, nur das Script finde ich stellenweise etwas unübersichtlich ;).

  • name22

    das die animation so unflüssig ist liegt nicht an der GUImessage schleife, sondern daran das sich die felder immer ruckartig um 25px verschieben
    oder ruckelt bei dir auch das bitmap das gezeichnet wird? wieviel fps hast du?

  • Zitat

    das die animation so unflüssig ist liegt nicht an der GUImessage schleife, sondern daran das sich die felder immer ruckartig um 25px verschieben
    oder ruckelt bei dir auch das bitmap das gezeichnet wird? wieviel fps hast du?


    Das meinte ich nicht. Aber die FPS sinken bei mir von 120 auf 56 wenn ich die Maus aus der GUI bewege ;).

  • Also GDI+ ist hier ganz bestimmt nicht das langsamste.
    Eine pure AutoIt & GDI+ Version (bearbeitet) packt auf meinem Rechner 8000 FPS.
    (ist natürlich Quatsch, aber so schnell läuft die Hauptschleife)

    Und warum ?

    1. Spielfeld nur dann zeichnen, wenn der Spieler sich bewegt. (Reduziert das Ganze auf Max 5 anzeigbare Frames bei 200ms Schritten)
    2. Den Mittelteil des Spielfelds als Bitmap kopieren (DrawImageRect ist nicht wirklich schnell, aber viel schneller als 400 FillRect) und nur den äußeren Rand neu erstellen.
    3. Adlib und so Kram durch Timer ersetzen. Adlib funkt immer dazwischen und verursacht öfters Fehler als wenn das Skript "geordnet" durchläuft.
    4. Im Event Mode arbeiten.

    Habe an meinem PC leider ein Ton Problem, deshalb habe ich alles Tonmäßige aus dem Skript auesgebaut.
    Das Skript läuft bei mir im Leerlauf mit 8000+ und bei "Last" mit 7500. (Völlig unnötig, aber möglich).
    Diese Extrem hohen möglichen Schleifen Raten haben aber einen riesen Vorteil. Wenn ich das Spiel auf z.B. 60FPS begrenze läuft es bei 1-2% CPU.

    Kannst ja mal reinschauen. Hab nur etwas umgeräumt.
    FPS Einstellung ganz oben im Skript.

    Spoiler anzeigen
    [autoit]

    #region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Icon=Symbol.ico
    #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
    #endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
    #include <gdip.au3>
    #include <misc.au3>
    ;~ #include <sound.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt('GUIOnEventMode', 1)

    [/autoit] [autoit][/autoit] [autoit]

    Const $MAP_SIZE = 100
    Const $SCREEN_SIZE = 21
    Const $SPEED = 200
    Const $DENSITY = 6.5
    Const $FPS = 60

    [/autoit] [autoit][/autoit] [autoit]

    Dim $map[$MAP_SIZE][$MAP_SIZE]
    Global $x = Int($MAP_SIZE / 2)
    Global $y = Int($MAP_SIZE / 2)
    Global $d = 0
    Global $px = Int($SCREEN_SIZE / 2)
    Global $py = Int($SCREEN_SIZE / 2)
    Global $fx = $x + Int($SCREEN_SIZE / 2)
    Global $fy = $y + Int($SCREEN_SIZE / 2) + 5
    Global $fd = 0
    Global $frames = 0
    Global $Exit, $Verdunkeln = True, $xAlt, $yAlt, $iTimer = TimerInit()

    [/autoit] [autoit][/autoit] [autoit]

    Func Init()
    $x = Int($MAP_SIZE / 2)
    $y = Int($MAP_SIZE / 2)
    $d = 0
    $px = Int($SCREEN_SIZE / 2)
    $py = Int($SCREEN_SIZE / 2)
    $fx = $x + Int($SCREEN_SIZE / 2)
    $fy = $y + Int($SCREEN_SIZE / 2) + 5
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;FileInstall("sound1.wav", "Sound1.wav")
    ;FileInstall("sound2.wav", "Sound2.wav")
    $gui = GUICreate("MULTIPOINT", $SCREEN_SIZE * 25, $SCREEN_SIZE * 25)
    GUISetOnEvent(-3, '_Exit', $gui)
    _GDIPlus_Startup()
    $graphic = _GDIPlus_GraphicsCreateFromHWND($gui)
    $bitmap = _GDIPlus_BitmapCreateFromGraphics($SCREEN_SIZE * 25, $SCREEN_SIZE * 25, $graphic)
    $buffer = _GDIPlus_ImageGetGraphicsContext($bitmap)
    GUISetState()
    _GDIPlus_GraphicsClear($graphic, 0xFFFFFFFF)
    $brush1 = _GDIPlus_BrushCreateSolid(0xFF000000)
    $brush2 = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $brush3 = _GDIPlus_BrushCreateSolid(0xFF0000FF)
    $brush4 = _GDIPlus_BrushCreateSolid(0x99000000)
    $brush5 = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
    $text = "CLICK SPACE"
    $bg = $brush5
    $start = 0 ; -1 = Neues Spielfeld incl warten, 0 = neues Spielfeld, 1 = Spiel
    $sound = 1
    ;~ $sound1 = _SoundOpen("Sound1.wav")
    ;~ $sound2 = _SoundOpen("Sound2.wav")
    ;~ AdlibRegister("sound", 500)
    ;~ New()
    $timer = TimerInit()

    [/autoit] [autoit][/autoit] [autoit]

    Func New()
    For $a = 0 To UBound($map) - 1
    For $b = 0 To UBound($map, 1) - 1
    If Random(0, 10) > $DENSITY Then
    $value = 1
    Else
    $value = 0
    EndIf
    If $b = Int($SCREEN_SIZE / 2) Or $b = $MAP_SIZE - Int($SCREEN_SIZE / 2) - 1 Or $a = Int($SCREEN_SIZE / 2) Or $a = $MAP_SIZE - Int($SCREEN_SIZE / 2) - 1 Then $value = 1
    $map[$a][$b] = $value
    Next
    Next
    $map[$x + $px][$y + $py] = 0
    $map[$x + $px + 1][$y + $py] = 0
    $map[$x + $px - 1][$y + $py] = 0
    $map[$x + $px][$y + $py + 1] = 0
    $map[$x + $px][$y + $py - 1] = 0
    $map[$fx][$fy] = 0
    $map[$fx + 1][$fy] = 0
    $map[$fx - 1][$fy] = 0
    $map[$fx][$fy + 1] = 0
    $map[$fx][$fy - 1] = 0
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func Feld()
    _GDIPlus_GraphicsClear($buffer, 0xFFFFFFFF)
    For $a = 0 To $SCREEN_SIZE - 1
    For $b = 0 To $SCREEN_SIZE - 1
    If $map[$a + $x][$b + $y] = 1 Then
    _GDIPlus_GraphicsFillRect($buffer, $a * 25, $b * 25, 25, 25, $brush1)
    EndIf
    Next
    Next
    _GDIPlus_GraphicsFillRect($buffer, $px * 25, $py * 25, 25, 25, $brush2)
    _GDIPlus_GraphicsFillRect($buffer, ($fx - $x) * 25, ($fy - $y) * 25, 25, 25, $brush3)
    _GDIPlus_GraphicsDrawImage($graphic, $bitmap, 0, 0)
    EndFunc ;==>Feld

    [/autoit] [autoit][/autoit] [autoit]

    Func Text($s, $v = True)
    If $v Then _GDIPlus_GraphicsFillRect($buffer, 0, 0, $SCREEN_SIZE * 25, $SCREEN_SIZE * 25, $brush4)
    _GDIPlus_GraphicsFillRect($buffer, 0, 0, $SCREEN_SIZE * 25, 40, $bg)
    _GDIPlus_GraphicsDrawString($buffer, $s, 0, 0, "Arial Black", 20)
    _GDIPlus_GraphicsDrawImage($graphic, $bitmap, 0, 0)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;~ Feld()

    [/autoit] [autoit][/autoit] [autoit]

    While FPS($FPS) And Not $Exit
    If _IsPressed(51) Then
    If $sound = 1 Then
    $sound = 0
    ;~ _SoundStop($sound1)
    Else
    $sound = 1
    EndIf
    Sleep(50)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If $start = 1 Then
    If _IsPressed(27) And $map[$x + $px + 1][$y + $py] <> 1 Then $d = 1
    If _IsPressed(25) And $map[$x + $px - 1][$y + $py] <> 1 Then $d = 2
    If _IsPressed(26) And $map[$x + $px][$y + $py - 1] <> 1 Then $d = 3
    If _IsPressed(28) And $map[$x + $px][$y + $py + 1] <> 1 Then $d = 4
    If _IsPressed(44) And $map[$x + ($fx - $x) + 1][$y + ($fy - $y)] <> 1 Then $fd = 1
    If _IsPressed(41) And $map[$x + ($fx - $x) - 1][$y + ($fy - $y)] <> 1 Then $fd = 2
    If _IsPressed(57) And $map[$x + ($fx - $x)][$y + ($fy - $y) - 1] <> 1 Then $fd = 3
    If _IsPressed(53) And $map[$x + ($fx - $x)][$y + ($fy - $y) + 1] <> 1 Then $fd = 4
    If $fx - $x < 0 Or $fx - $x > $SCREEN_SIZE - 1 Or $fy - $y < 0 Or $fy - $y > $SCREEN_SIZE - 1 Then
    ;~ $text = "RED WINS"
    $bg = $brush2
    $start = -1
    Text('RED WINS')
    ;~ AdlibUnRegister("direction")
    ;~ If $sound = 1 Then _SoundPlay($sound2)
    ElseIf $fx - $x = $px And $fy - $y = $py Then
    ;~ $text = "BLUE WINS"
    $bg = $brush3
    $start = -1
    Text('BLUE WINS')
    ;~ AdlibUnRegister("direction")
    ;~ If $sound = 1 Then _SoundPlay($sound2)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If TimerDiff($iTimer) > $SPEED Then
    $iTimer = TimerInit()
    direction()
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If $xAlt <> $x Or $yAlt <> $y Then
    $xAlt = $x
    $yAlt = $y
    _GDIPlus_GraphicsFillRect($buffer, $px * 25, $py * 25, 25, 25, $brush5)
    _GDIPlus_GraphicsFillRect($buffer, ($fx - $x) * 25, ($fy - $y) * 25, 25, 25, $brush5)
    Switch $d
    Case 1
    _GDIPlus_GraphicsDrawImage($buffer, $bitmap, -25, 0)
    Case 2
    _GDIPlus_GraphicsDrawImage($buffer, $bitmap, 25, 0)
    Case 3
    _GDIPlus_GraphicsDrawImage($buffer, $bitmap, 0, 25)
    Case 4
    _GDIPlus_GraphicsDrawImage($buffer, $bitmap, 0, -25)
    EndSwitch
    For $a = 0 To $SCREEN_SIZE - 1 Step $SCREEN_SIZE - 1
    For $b = 0 To $SCREEN_SIZE - 1 Step 1
    If $map[$a + $x][$b + $y] = 1 Then
    _GDIPlus_GraphicsFillRect($buffer, $a * 25, $b * 25, 25, 25, $brush1)
    Else
    _GDIPlus_GraphicsFillRect($buffer, $a * 25, $b * 25, 25, 25, $brush5)
    EndIf
    Next
    Next
    For $a = 1 To $SCREEN_SIZE - 2 Step 1
    For $b = 0 To $SCREEN_SIZE - 1 Step $SCREEN_SIZE - 1
    If $map[$a + $x][$b + $y] = 1 Then
    _GDIPlus_GraphicsFillRect($buffer, $a * 25, $b * 25, 25, 25, $brush1)
    Else
    _GDIPlus_GraphicsFillRect($buffer, $a * 25, $b * 25, 25, 25, $brush5)
    EndIf
    Next
    Next
    _GDIPlus_GraphicsFillRect($buffer, $px * 25, $py * 25, 25, 25, $brush2)
    _GDIPlus_GraphicsFillRect($buffer, ($fx - $x) * 25, ($fy - $y) * 25, 25, 25, $brush3)
    _GDIPlus_GraphicsDrawImage($graphic, $bitmap, 0, 0)
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If $start <> 1 Then
    Init()
    New()

    [/autoit] [autoit][/autoit] [autoit]

    $bg = $brush5

    [/autoit] [autoit][/autoit] [autoit]

    If $start = -1 Then
    Sleep(1000)
    Text('CLICK SPACE', 0)
    Else
    Feld()
    Text('CLICK SPACE')
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    While Not _IsPressed('20') And Not $Exit
    FPS($FPS)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Feld()
    $start = 1

    [/autoit] [autoit][/autoit] [autoit]

    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $frames += 1
    If TimerDiff($timer) >= 1000 Then
    WinSetTitle($gui, "", "MULTIPOINT " & $frames & " fps")
    $frames = 0
    $timer = TimerInit()
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func FPS($w)
    Local Static $a = TimerInit(), $p, $i
    Local $s = 1000 / $w - TimerDiff($a) + $i
    If $s > 0 Then $p += $s
    $a = TimerInit()
    Sleep($p)
    $i = TimerDiff($a)
    $p -= $i
    Return True
    EndFunc ;==>FPS

    [/autoit] [autoit][/autoit] [autoit]

    ;~ AdlibUnRegister("sound")
    ;~ _SoundClose($sound2)
    ;~ _SoundClose($sound1)
    _GDIPlus_BrushDispose($brush5)
    _GDIPlus_BrushDispose($brush4)
    _GDIPlus_BrushDispose($brush3)
    _GDIPlus_BrushDispose($brush2)
    _GDIPlus_BrushDispose($brush1)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_Shutdown()
    GUIDelete()
    Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    $Exit = True
    EndFunc ;==>_Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func direction()
    Switch $d
    Case 1
    If $map[$x + $px + 1][$y + $py] <> 1 Then
    $x += 1
    EndIf
    Case 2
    If $map[$x + $px - 1][$y + $py] <> 1 Then
    $x -= 1
    EndIf
    Case 3
    If $map[$x + $px][$y + $py - 1] <> 1 Then
    $y -= 1
    EndIf
    Case 4
    If $map[$x + $px][$y + $py + 1] <> 1 Then
    $y += 1
    EndIf
    EndSwitch
    Switch $fd
    Case 1
    If $map[$x + ($fx - $x) + 1][$y + ($fy - $y)] <> 1 Then
    $fx += 1
    EndIf
    Case 2
    If $map[$x + ($fx - $x) - 1][$y + ($fy - $y)] <> 1 Then
    $fx -= 1
    EndIf
    Case 3
    If $map[$x + ($fx - $x)][$y + ($fy - $y) - 1] <> 1 Then
    $fy -= 1
    EndIf
    Case 4
    If $map[$x + ($fx - $x)][$y + ($fy - $y) + 1] <> 1 Then
    $fy += 1
    EndIf
    EndSwitch
    EndFunc ;==>direction

    [/autoit] [autoit][/autoit] [autoit]

    ;~ Func sound()
    ;~ If $sound = 1 And _SoundStatus($sound1) = "stopped" Then
    ;~ _SoundPlay($sound1)
    ;~ EndIf
    ;~ EndFunc

    [/autoit]
  • BinDannMalWeg

    doch habe ich ;)

    name22

    komisch bei mir bleibt die fps zahl konstant egal ob die maus drin oder draußen ist.aber ich werde trozdem nächstes mal das mit dem oneventmode arbeiten,danke. benutzt du zufällig vista oder win7

    Mars

    jo das mit adlib und dem oneventmode werde ich ändern
    leider funktioniert das spielt in deiner version nicht mehr aber ich werde die beiden sachen mal ändern, danke