/**************/ /* timeman.c */ /****************************************************************************/ /* ** Malliohjelma "animaatiosta": ** Tikku-ukko osoittaa oikealla kädellään missä hiiri menee. ** Vasen käsi pyörii ajan mukana. Aika näkyy myös ikkunan otsikossa. ** Aika voidaan nollata painamalla hiiren vasenta nappulaa. ** ** Käyttö: Tee projekti time_man.prj jossa on: ** time_man.c ** simplet.def ** ALI\timer.c ** ALI\tabhand.c ** ja aja. ** ** Vesa Lappalainen 15.8.1992 & 13.6.1994 ** ** Animaation idea: ** 1. kuva on piirretty valmiiksi ** 2. kun jotakin osaa kuvasta pitää siirtää, pyyhitään vanha osa pois ** 3. lasketaan osan uusi paikka ja/tai muoto ** 4. piirretään uudistettu osa ** ** "Rautalankamallissa" pyyhkiminen käy siten, että piirretään ** kuvan osa kynällä, joka muuttaa kaikki pisteet päinvastaisen ** värisiksi (mm. musta piste muuttuu valkoiseksi ja päinvastoin). ** Kun tällaisella kynällä piirretään kaksi kertaa sama kuva, ei ** tuloksena olekaan mitään, siis joka toisella kerralla kuva häviää. ** ** Monimutkaisemmassa tapauksessa kuvan osan alla oleva taustakuva ** pitää ensin tallettaa ja sitten piirtää vasta kuvan osa. ** Siirrossa tausta palautetaan ja luetaan uusi tausta uudesta ** paikasta ja sitten piirretään uusi osa. ** ** Animaatio: ** ========== ** Tehtäviä: 1) Ukolla on seuraava vika: ** - käynnistä ukko-ohjelma ** - aktivoi jokin pieni ikkuna, esim. WinCD ** - siirrä ko. pieni ikkuna ukon vartalon oikealle puolelle ** - odota kunnes kellon mukana liikkuva käsi kiertyy ** tämän pikkuikkunan alle ** - aktivoi ukkoikkuna ennenkuin käsi tulee pikkuikkunan ** takaa näkyviin ** Mistä vika johtuu? Miten vika voitaisiin korjata? ** (Vian syytä voit tutkia asettamalla vakion TUTKI_VIESTIT ** 1:ksi, jolloin näet viestien saapumisjärjestyksen.) ** ** 2) Muuta ohjelmaa siten, että kun hiiren nappi painetaan ** alas, kääntyy oikea jalka osoittamaan hiiren suuntaa ** painamishetkellä. Oikea käsi osoittaa koko ajan. ** ** 3) Muuta ohjelmaa siten, että aluksi oikea käsi osoittaa kursoria ** Kun oikea nappi painastaan alas, lukittuu oikea käsi paikalleen ** ja vasen jalka rupeaa osoittamaan hiirtä niin kauan kun nappi ** on alhaalla. Kun nappi päästetää ylös, alkaa oikea jalka ** osoittamaan kursoria ja kun nappi painetaan alas alkaa ** oikea käsi osoittamaan jne... ** Kello: ** ====== ** Tehtäviä: 1) Onko kello tarkka? ** ** 2) Miten kello saataisiin tarkaksi? ** ** 3) Kirjoita ohjelma, missä pallo pomppii abs(sin(x)):n muotoista ** rataa edestakaisin välillä 0-400 (eli kun tulee ** koordinaattiin 400, kääntyy takaisin ja kun ** tulee koordinaattiin 0, kääntyy taas takaisin) ** ** 4) Muuta pomppimisohjelmaa siten, että kun pallo törmää ikkunan ** reunaan, muutetaan suuntaa. Ikkunan koko saadaan selville ** kutsulla GetClientRect (ks. Help). ** ** 5) Kirjoita "Tennis"-peli, missä pallo kulkee suoraviivaista ** rataa ja aina törmätessään ikkunan seinään, kimpoaa oikeaan ** suuntaan. Myös törmätessään kursoriin, muuttaa ** pallo suuntaansa. ** ----------------------------------------------------------------------------*/ #include #include #include #include "tabhand.h" #define TUTKI_VIESTIT 1 /* Halutaanko tutkia viestien tulojärjestystä */ /***************************************************************************/ TblClassSWindowMAIN("TimemanClass",0,"Aika-ukko",MsgTbl,0); /***************************************************************************/ typedef struct { int pituus; double suunta; POINT alku; } raaja_tyyppi; #define RAD(d) ((d)*M_PI/180.0) static raaja_tyyppi Raajat[4] = { /* pituus,suunta , alku.x alku,y */ { 80, RAD(180) , { 60, 90} }, /* 0 = Vasen käsi */ { 80, RAD(30) , { 60, 90} }, /* 1 = Oikea käsi */ { 90, RAD(180+60) , { 60,180} }, /* 2 = Vasen jalka */ { 90, RAD(-60) , { 60,180} } /* 3 = Oikea jalka */ }; static raaja_tyyppi *Vasen_kasi = &Raajat[0]; static raaja_tyyppi *Oikea_kasi = &Raajat[1]; #define AIKA_VALI 50 /* ms */ #define TARKKUUS 1000 /* kellon näyttö näin usein */ static double aika = 0; /* ms */ static double vasen_alhaalla = 0; /* Aika ei etene jos vasen on alhaalla! */ /****************************************************************************/ #define POINT_TO_2(pt) pt.x,pt.y /* Pisteestä 2 erillistä lukua */ #define POINT_PLUS_RA(pt,r,a) \ pt.x+r*cos(a)+0.5,pt.y-r*sin(a)+0.5 /* Piste + r*suunta */ /****************************************************************************/ static void PiirraRaaja(HDC hdc,raaja_tyyppi *raaja) /* Piirretään ukon raaja. */ { MoveToEx(hdc,POINT_TO_2(raaja->alku),NULL); LineTo(hdc,POINT_PLUS_RA(raaja->alku,raaja->pituus,raaja->suunta)); } /****************************************************************************/ static void PiirraNotRaaja(HDC hdc,raaja_tyyppi *raaja) /* Piirretään ukon raaja NOT-kynällä. */ { int oldROP = SetROP2(hdc,R2_NOT); PiirraRaaja(hdc,raaja); SetROP2(hdc,oldROP); } /****************************************************************************/ static int muuta_raajan_suunta(HDC hDC, LONG lParam, raaja_tyyppi *raaja) { int dx,dy; POINTS pt = MAKEPOINTS(lParam); PiirraNotRaaja(hDC,raaja); /* Pyyhitään vanha raaja pois */ dx = pt.x - raaja->alku.x; dy = pt.y - raaja->alku.y; if ( dx || dy ) raaja->suunta = atan2(-dy,dx); else raaja->suunta=0; PiirraNotRaaja(hDC,raaja); /* Piirretään uusi raaja tilalle */ return 1; } /****************************************************************************/ static int muuta_raajan_suunta_rad(HDC hDC, double rad, raaja_tyyppi *raaja) { PiirraNotRaaja(hDC,raaja); /* Pyyhitään vanha raaja pois */ raaja->suunta = fmod(rad,2*M_PI); PiirraNotRaaja(hDC,raaja); /* Piirretään uusi raaja tilalle */ return 1; } /****************************************************************************/ #if TUTKI_VIESTIT /* Täälä voidaan tutkia viestien tulojärjestystä */ # include # define T "--" # define MV 10 /* Näytettävien viestien maksimimäärä. */ static char *v[MV]; static int paikka = 0; /* V = laita ja näytä Viesti n ** LV = Lisää Viestit. Jonossa st täytyy jo olla jotakin (strcat => vaara!) ** TV = Tyhjennä Viestien näyttö */ # define V(n) {v[paikka]=n; paikka++; if (paikka>=MV) paikka=MV-1; else nayta_aika(msg); } # define LV() {int i;for (i=0; ihWnd,st); } /****************************************************************************/ static EVENT WM_paint(tMSGParam *msg) /* # MAKE_DC # */ { int i; Ellipse(msg->hDC,40,40,80,80); /* Pää */ MoveToEx(msg->hDC, 60, 80, NULL); LineTo(msg->hDC, 60,180); /* Keskivartalo */ for (i=0; i<4; i++) PiirraNotRaaja(msg->hDC,&Raajat[i]); /* Jäsenet */ V("PA"); nayta_aika(msg); return 0; } /****************************************************************************/ static void InitMy(tMSGParam *msg) /* Ajastin täytyy alustaa jotta se toimisi. */ { SetTimer(msg->hWnd,1,AIKA_VALI,NULL); } /****************************************************************************/ static EVENT WM_timer_1(tMSGParam *msg) /* # MAKE_DC # */ /* Aliohjelmaa kutsutaan kun valittu aika on tullut täyteen */ { static int laskuri = 0; /* Aikaa ei kannata näyttää kokoajan, vain sek väl*/ if ( vasen_alhaalla ) return 0; if ( aika == 0 ) laskuri = 0; muuta_raajan_suunta_rad(msg->hDC,Vasen_kasi->suunta-M_PI/45.0,Vasen_kasi); aika += AIKA_VALI; if ( ++laskuri >= TARKKUUS/AIKA_VALI ) { laskuri = 0; nayta_aika(msg); } return 0; } /****************************************************************************/ /* ** Seuraavissa aliohjelmissa on seuraavat parametrit: ** ** hWnd - ikkunan kahva ** wParam - SHIFT, CTRL ja ALT -näppäimen tile, voidaan testata esim. ** if ( wParam && MK_CONTROL ) ... hommat jos CTRL alhaalla ** lParam - x = LOWORD(lParam) ja y = HIWORD(lParam) ** kätevämpi on kuitenkin selvittää hiren paikka: ** POINT pt = MAKEPOINT(lParam) ** ----------------------------------------------------------------------------*/ /****************************************************************************/ static EVENT WM_lbuttondown(tMSGParam *msg) /* # MAKE_DC # */ /* Aliohjelmaa kutsutaan kun hiiren nappi on painettu alas */ { aika = 0; vasen_alhaalla = 1; muuta_raajan_suunta_rad(msg->hDC,M_PI,Vasen_kasi); V("LD"); nayta_aika(msg); return 0; } /****************************************************************************/ static EVENT WM_lbuttonup(tMSGParam *msg) /* Aliohjelmaa kutsutaan kun hiiren nappi on päästetty ylös */ { #pragma argsused V("LU"); vasen_alhaalla = 0; return 0; } /****************************************************************************/ static EVENT WM_mousemove(tMSGParam *msg) /* # MAKE_DC # */ /* Aliohjelmaa kutsutaan kun hiiri on liikkunut */ { muuta_raajan_suunta(msg->hDC,msg->lParam,Oikea_kasi); return 0; } /****************************************************************************/ static EVENT WM_create(tMSGParam *msg) /* Aliohjelmaa kutsutaan kun ikkuna on luotu, muttei vielä näytössä. */ { InitMy(msg); nayta_aika(msg); V("CR"); return 0; } /****************************************************************************/ static EVENT WM_rbuttondown(tMSGParam *msg) { #pragma argsused TV(); return 0; } /****************************************************************************/ /* Viestien käsittelytaulukko */ /****************************************************************************/ tMSGEntry MsgTbl[] = { EV_HANDLE_WM_DESTROY, { WM_PAINT , DoC , DoC , WM_paint, MAKE_DC }, /*a*/ { WM_TIMER , 1 , DoC , WM_timer_1, MAKE_DC }, /*a*/ { WM_LBUTTONDOWN , DoC , DoC , WM_lbuttondown, MAKE_DC }, /*a*/ { WM_LBUTTONUP , DoC , DoC , WM_lbuttonup }, /*a*/ { WM_MOUSEMOVE , DoC , DoC , WM_mousemove, MAKE_DC }, /*a*/ { WM_CREATE , DoC , DoC , WM_create }, /*a*/ { WM_RBUTTONDOWN , DoC , DoC , WM_rbuttondown }, /*a*/ { 0 } }; /****************************************************************************/