Eli siirrän hiirtä koordinaattien mukaan ja käytän täältä löytynyttä pätkää hiiren siirtoon.
XX = Xchange * 65536 / (Screen.Width / Screen.TwipsPerPixelX) YY = Ychange * 65536 / (Screen.Height / Screen.TwipsPerPixelY) mouse_event MOUSEEVENTF_ABSOLUTE Or MOUSEEVENTF_MOVE, XX, YY, 0, 0
Timerilla taas on interval 1 ja se ajaa yllä olevan pätkän käytännössä koko ajan. Olen kokeillut useaa arvoa intervallille välillä 1-5000. (Ychange ja XChange arvot siis muuttuu). Nyt ongelmana on että hiiri katoaa välillä kokonaan ja liikkuu kovin tahmeasti. Eli se pitäisi jossakin välissä jotenkin piirrättää uudestaan ruudulle ennen uutta timer1 ajo käskyä. Miten? Muutokset tulee winsockin läpi, eli eräänsortin etähallinta, pitää keksiä pyörä uudestaan... Pitäisikö kehitellä jonkin sortin bufferi väliin..? Toimisiko se niin, että arrayhin ajaa koordinaatteja peräkkäin esim. 5kpl ja sitten pukkaa muutokset putkessa tolle hiiren liikutukselle?
Kokeile hiiren paikan muuttamisen jälkeen komentaa DoEvents
Auttoi jo huomattavasti.. Vieläkin tosin vähän töksii.
Mitenkäs olisi, että sen sijaan että pukkaisit aina kokoajan sitä uutta sijaintia, muuttaisit sijaintia vain silloin kun se on muuttunut? Tämä estää tehokkaasti tämän ongelmasi, joka todennäköisesti johtuu siitä että kone ylikuormittuu.
Tietokoneiden kanssa on hyvä aina tehdä mahdollisimman paljon mahdollisimman nopeasti mahdollisimman harvoin :) Säästäisit tuossakin laskentatehoa huomattavasti käyttämällä valmiiksi laskettuja arvoja, esim. laskea tuon 65536 / jne. julkiseen muuttujaan. Tosin helpointahan olisi olla sotkeutumatta tuollaisen laskennan kanssa... en ole tuota mouse_eventiä käytellyt, mutta eikös nämä yleensä ota kaikki arvot pikseleinä?
Vielä yksi tapa tehostaa tuota nykyistä koodiasi ihan suoraan ilman suurta vaivannäköä:
Private Sub Timer1_Timer() Timer1.Enabled = False ' ... liikutuskoodi tässä ... DoEvents Timer1.Enabled = True End Sub
Sitten vain kun lisäät sen "muuta sijaintia vain jos se on muuttunut" -tunnistuksen ja kevennät laskutoimituksia, niin eiköhän tuo sitten ala olla jo kyllin kevyt toimiakseen vähän vanhemmallakin koneella :)
Nyt toimii jo huomattavasti jouheammin ja jopa siedettävästi. Nyt vielä on pari isompaa ongelmaa.
Ensimmäinen on se, että kun tulee syöttöarvoa esim: 5, 15,456,1222 niin miten saisin pätkittyä tuon tulemisen..? Nyt olen tämän liikutuksen teon ajaksi ratkaissut ongelman rajaamalla luvun kolmeen, mutta arvatenkin sen yläpuolelle ei mennnä eli oikeaan alanurkkaan ja yksi ja kaksi numeroisissa hypitään sinne tänne. Eli kun syöttöä tulee hiiren liikkeestä, niin jokainen muuttujana kirjoitettu uusi numero sarja pitäisi jotenkin jonotuttaa läpi ennen seuraavan syöttyöä, muuten menee putkeen ja ei taas toimi. Ideoita jonotuksen tekoon?
Ja toinen liittyy siihen, että mistä löytyisi vinkkiä siihen , miten screenshot bittikartta pakataan tai voiko kaappausken tarkkuutta määritellä jotenkin esim. 16 väriseksi?
Nyt olen käyttänyt tätä putkasta napattua pätkää ensihätään, mutta arvatenkin iso file siirtyy hitaasti toiseen päähän "lankaa"..
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long) Const myScreen = 0 Const myForm = 1 keybd_event vbKeySnapshot, myScreen, 0&, 0& Image1.Picture = Clipboard.GetData(vbCFBitmap)
Tuosta ylemmästä kuvauksestani päättelen, että sinulla on ongelma lukujen määrän kanssa: kaikki numerot eivät ehdi aina tulla perille asti? Jos näin on, niin helpointa lienisi pitää laskuria siitä kuinka monta lukua on kulloinkin vastaanotettu ja piirtää vain silloin kun niitä on neljä tai enemmän.
Grafiikan suhteen "ammattimaiset" tällaiset ohjelmat itseasiassa kaappaavat kaikki Windowsin piirtokomennot ja lähettävät ne verkon ylitse. 16-värinen kikkailu onnistuu kyllä API:n avulla, vaikka siinä onkin omat mutkansa. Tämä sujuu niin, että tehdään muistiin oma 16-värinen DIB (device independent bitmap), jonne kuva kopioidaan (onnistuu esimerkiksi BitBlt:n avulla). Windows suorittaa muunnoksen 16-bittiseksi automaattisesti, joten sitten vain haetaan bittikartan tavut. Lopuksi jäljellä onkin "vain" kuvadatan pakkaaminen. Se kannattaa suorittaa dataa hukkaamatta, erilaisia pakkausalgoritmejä löytyy netistä aika paljonkin jos niitä jaksaa alkaa etsiä. Yksi tapahan olisi lähettää vain muuttunut kuvadata, eli säilöä aina edellinen lähetetty kuva, sitten vertailla mitkä tavut ovat muuttuneet ja lähettää tieto vain niistä muuttuneistä kohdista. Siinä vain on hommaa kehitellä oma protokolla ("standardoitu" tapa jolla ohjelmat keskustelevat verkon ylitse): pitää määrittää, koska tulee sijainnin muutosdataa ja koska tulee sitä olennaista pikselidataa. Tutustumisen arvoista olisi ehkä lukea GIF-formaatin dokumentaatiota.
Eli jotta kuvan saat pienempään kokoon tehokkaasti, joudut opettelemaan aika paljon uusia asioita. Jos pelkkä 16-väriseksi muuttaminen riittää, niin se on vielä suhteellisen helppoa. Valitettavasti olen näemmä hukannut DIB-esimerkkilinkkini eikä tällä koneella ole sitä esimerkkikoodia tallessa, joten ainakin vielä jäät sitä vaille.
Sitten puolittain ohitse aiheen: jos haluat ajoittaa piirtämisen/tarkistamisen tapahtumaan varmasti aina tiettyjä kertoja sekunnissa, niin minulla on lähetettynä tuo "Pelin FPS:n hallinta: tapahtumien moniajo", joka mahdollistaa tarkan ajastamisen. 60 FPS tapahtuu varmasti 60 kertaa sekunnissa, paitsi jos koneesta loppuu teho kesken tai jos jokin muun toiminnon suorittaminen keskeyttää koodin suorittamisen (esim. ikkunan liikuttelu).
Elikkä, elikkä.. (Paljon asiaa kerralla)
Taitaa kyllä olla siten, että kaikki luvut ei ehdi tulla ja se on syy miksi pätkitään. Mutta formit on pixeli tilassa eli screenin reso kertoo sen, että kuinka paljon luku voi maksimissaan olla. Itseasiassa, tulipas mieleen että mitenkä puolittaisin tuon dib kuvan, eli ei nyt ihan -50% mutta vaikka -30% pienemmäksi? Säästyisi kaistaa.. Eli siis lähetetään X ja Y pikseli, missä ollaan ja asetetaan hiiri vastaavalle kohdalle server puolella. Eli luku voi olla 1-4 numeroa pitkä. Pitäisi jotenkin jaksottaa tai pätkiä sen mukaan monikonumeroinen luku on. Pitääkö tehdä sittenkin vaan "putki stringiä" jossa on joku jaksotusmerkki ja vastaanoton jälkeen merkin avulla pätkitään ja ajetaan bufferoituna näytölle ja vaikka tuolla FPS systeemin läpi (Ennemmin kuin timerin läpi)?
Otan kuvan ja vertaan sitä aiemmin otettuun dib:in avulla. Tämä onnistuu jo ja sen perusteella voin tehdä toiminteita. Päivityksen ei tarvi olla kyllä kuin ehkä 10-15 kertaa sekunnissa :)
Ihan hämärän peitossa on se, että miten käsittelisin tuota dib imagea siten, että muuttaisin vain muuttuneita pikseleitä.. Mikä tuon dib:in koko on? Jos se tallennettuna on bmp:nä reilu 3mb. Eli jos siirtäisin aluksi vaikka kerran minuutissa tuon dib kuvan clientille? (Ja rakentelisin myöhemmin sen, että muutetaan vaan muuttuneet pikselit.)
DIB = BMP-kuva. Eli siis ne ovat muodoltaan täsmälleen samanlaiset. BMP-kuva on muistiin avattuna samanlainen kuin tiedostona. BMP-tiedostoa tutkimalla siis näkee, millaisessa muodossa tieto on myös tietokoneen muistissa. Laskeminen taas hoituu näin:
- alkuperäinen kuva on 32-bittinen
- uusi kuva on nelibittinen, eli kahdeksan kertaa pienempi
- näin tasan 3 Mt putoaa kokoon 384 kt
- huomautuksena tosin, että jokainen DIBin (BMP:n) rivi on aina jaollinen 32-bitillä, joten joka riville varataan hieman ylimääräistä tilaa vaikka se ei välttämättä olisi tarpeen; tämä kasvattaa hieman kuvan kokoa ja lisää hukkatilan määrää
- pienenä huomautuksena DIB on muistissa pystysuuntaan flipattuna: alin rivi tulee ensin, ylin rivi viimeisenä
- yhteen neljän bitin kuvan tavuun mahtuu kaksi pikseliä
GIF-pakkaaminen voi pienentää kuvan kokoa huomattavasti, varsinkin jos sitä lähtee vielä toteuttamaan animaatiopakkaamisella. Sen koodaamiseen tosin voi mennä helposti kuukausikin, että se jää varmasti jonkin toisen ajan murheeksi. Eli suosittelen kyllä että ensin vain yrität saada toimimaan ja sitten alat murehtia näitä muita asioita, jotka ovat vaihtoehtoista kehittämistä: selittelen vain kerralla aika paljon kaiken mitä tarvitsee ja mitä voi halutessaan tehdä paremman lopputuloksen eteen :)
Sitten pätkimissyy: miten lähetät tiedot verkon ylitse? Siirtyvätkö ne string-muotoisena datana vai ihan binäärinä? String-datan kanssa täytyy olla siinä mielessä tarkka, että tarkistaa vastaanotettaessa aina loppuuko rivi. Kaikki rivit eivät välttämättä tule kokonaisena, vaan tieto pätkitään useammalle lähetykselle, joten vastaanottoon tarvitsee bufferoinnin. Tarkistaa vain aina tietoa saadessaan, päättyykö tieto rivinvaihtoon: jos ei pääty, laita tieto bufferiin säilöön ja lisää bufferi sitten seuraavan tiedon alkuun.
En ole binääridataa lähettänyt, joten en tiedä millä tavalla se lähtee liikenteeseen: tekstimuotoinen tietohan vaikuttaa lähtevän vasta kun syöttää rivinvaihdon. Binäärimuotoisena data kuitenkin veisi huomattavasti vähemmän kaistaa. Kuvahan on jo pakko lähettää binäärimuodossa. Paketithan voisivat aluksi olla muotoa "neljä integer-lukua (hiiren jutut) + kuvadata". Yhteyttä muodostaessa voisi kertoa ruudun resoluution, niin sitten ei tarvitse kertoa minkä kokoinen kuvadata kulloinkin tulee.
Myöhemmin toimintakuntoisena tuota voi sitten optimoida taas sillä, että kuvadata lähtee vain silloin kun on tapahtunut muutoksia.
Tässä vaiheessa homma on ihan levällään ja käytän tiedon siirtoon useampaa winsockkia, ettei tarvi erikseen tulkita tulevaa dataa vielä. Myöhemmin sitten yhteen. Hiiren kohta tulee ihan stringinä. Pitääpä tutkia seuraavaksi miten tuon rivinvaihden tekisi tuohon hiiren asennon lähetykseen..
Jep, helpoimmalla pääsee oman kokemukseni mukaan sillä, että tekee erillisiä kokeiluprojekteja, joilla katsoo miten kukin eri asia toimii ja sitten vasta tekee sen lopullisen projektin, jossa nivoo kaiken yhteen :) Jos ei etukäteen tiedä lähes tarkalleen mitä vastaan tulee ja millaisia koodeja käyttää missäkin tilanteessa, niin koodista tulee lopulta aika sotkuista kun aiempi koodi ei jousta. Humm, menee jo liikaa ohitse aiheen, joten lopetan tämän tähän.
Aihe on jo aika vanha, joten et voi enää vastata siihen.