Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

killmichnich

unregistriert

1

09.12.2009, 18:00

Hilfe mein Schnee schneit nicht =(

Hiho lieber Programmierer,
ich versuch zur Zeit mir einen eigenen kleinen Bildschirmschoner zu programmieren, in dem es schneien soll. Zu dem Bildschirmschoner hab ich ein kleines Tutorial gefunden, den krieg ich zum laufen. Mein eigentliches Problem liegt aber wohl darin, dass ich das mit dem Zeichnen offenbar nicht so ganz hinkrieg. Ich hab meine "Schneeflocken" schon auf dem Bildschirm, sie bewegen sich nur eben nicht, und ich weiß nicht warum =(

Ich glaub ich zeig am besten mal den Code den ich bis jetzt hab, is eigtl. nich viel:

main.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <windows.h>
#include <scrnsave.h>

#include "Snow.h"


UINT timer_id;
CSnow* Snow;

long WINAPI ScreenSaverProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
HDC hdc;
hdc = GetDC(hWnd);

    switch(message)
    {
        case WM_CREATE:
        {
            srand(GetTickCount());
            SetTimer(hWnd,timer_id,3,NULL);
            int screenX = GetSystemMetrics(SM_CXSCREEN);
            int screenY = GetSystemMetrics(SM_CYSCREEN);
            Snow = new CSnow(100, screenX, screenY, hdc);
            break;
        }
        case WM_TIMER:
        {

            PostMessage(hWnd, WM_PAINT, 0, 0);
            break;
        }
        case WM_DESTROY:
        {
            KillTimer(hWnd,timer_id);
            ReleaseDC(hWnd,hdc);
            delete Snow;
            Snow = NULL;
            break;
        }
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            hdc = BeginPaint(hWnd, &ps);

            Snow->Draw();

            EndPaint(hWnd, &ps);

            break;
        }

    }
    return DefScreenSaverProc(hWnd,message,wParam,lParam);
}


BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_INITDIALOG:
        return TRUE;
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDOK:
            EndDialog(hWnd,0);
            return TRUE;
        case IDCANCEL:
            EndDialog(hWnd,0);
            return FALSE;
        }
        break;
        case WM_CLOSE:
            EndDialog(hWnd,0);
            return TRUE;
    }
    return FALSE;
}

BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
    return TRUE;
}


Hier dann Snow.h, die Klasse CSnow is nur dazu da Schneeflocken zu "erzeugen" und sie zu malen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#pragma once

#include <windows.h>
#include <iostream>
#include <map>

using namespace std;

struct SNOWFLAKE
{
    float Xpos;
    float Ypos;
    float vx;
    float vy;
};

class CSnow
{
    public:
    CSnow();
    CSnow(int numberofflakes, int scr_width, int scr_height, HDC hDc);
    void Draw();

    protected:
    map<int, SNOWFLAKE>SnowFlakes;
    int SCR_Width;
    int SCR_Height;
    HDC hdc;
};

und hier noch dazu Snow.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "Snow.h"

CSnow::CSnow()
{
    SCR_Width   = 800;
    SCR_Height  = 600;
    hdc         = GetDC(NULL);
}
CSnow::CSnow(int numberofflakes, int scr_width, int scr_height, HDC hDc)
{
    SCR_Width = scr_width;
    SCR_Height = scr_height;
    hdc = hDc;

    for(int i=0; i<numberofflakes; i++)
    {
        SNOWFLAKE s = {(float)(rand()%SCR_Width), (float)(rand()%SCR_Height), 1, 10};
        SnowFlakes[i] = s;
    }
}
void CSnow::Draw()
{
    HPEN pen = CreatePen( PS_SOLID,1, RGB(0, 0, 0));
    SelectObject(hdc, pen);
    Rectangle(hdc, 0, 0, SCR_Width, SCR_Height);

    for(int i=0; i<SnowFlakes.size(); i++)
    {
        SNOWFLAKE s = SnowFlakes[i];
        s.Xpos+=s.vx;
        s.Ypos+=s.vy;
        if(s.Xpos>=SCR_Width || s.Ypos>=SCR_Height)
        {
            s.Xpos = (float)(rand()%SCR_Width);
            s.Ypos = 0;
        }
        if(s.Xpos>0 && s.Xpos<SCR_Width && s.Ypos>0 && s.Ypos<SCR_Height)
        {
            SetPixel(hdc, (int)s.Xpos, (int)s.Ypos, RGB(255, 0, 255));
        }
    }
    DeleteObject(pen);

}

Der Bildschirmschoner startet ganz normal, man sieht auch ein paar "Flocken".
Ja und da wär auch noch ein weiteres Problem: Ich hab versucht mir Rectangle(...); den Bildschirm zu übermalen und danach die Schneeflocken draufzumalen, nur leider is der jetzt weiß und nich schwarz(deshalb sind die Flocken auch rosa), und ich weiß nich warum =(

Ich hoff mal ihr könnt mir sagen was ich da schon wieder falsch gemacht hab =)

Danke schonmal ^^

MfG Killmichnich

2

09.12.2009, 18:09

Der Timer sollte ein Redraw veranlassen. Im Moment ist es dir scheinbar egal, was der Timer macht, d.h. er wird einfach ignoriert.

Ahja, den Schnee bei jedem Draw um feste Werte zu bewegen ist keine gute Idee, wenn der Schnee mal öfters gezeichnet wird, fällt er auf einmal schneller. Du solltest da uf jeden Fall noch einen Zeitfaktor einbauen oder nur während dem Timer bewegen und im Draw wirklich nur zeichnen.
Lieber dumm fragen, als dumm bleiben!

killmichnich

unregistriert

3

10.12.2009, 06:45

C-/C++-Quelltext

1
2
3
4
5
6
      case WM_TIMER:
        {

            PostMessage(hWnd, WM_PAINT, 0, 0);
            break;
        }

eigentlich sollte das doch WM_PAINT immer wieder aufrufen und somit zur Bewegung führen oder? ôO

4

10.12.2009, 09:40

Eigentlich... :?

Geb halt bei WM_TIMER eine Statusmeldung aus, um das zu prüfen.

Hast du es an der Stelle mal mit InvalidateRect versucht (anstatt PostMessage)?

unsigned long

Treue Seele

Beiträge: 140

Wohnort: Herzogenrath

Beruf: Fachinformatiker Fachrichtung Anwendungsentwicklung

  • Private Nachricht senden

5

12.12.2009, 21:52

Tipp: Mit einer Refresh-Zeit von 3 Millisekunden fritierst du selbst einen Quad-Core. Also: 1000/25 Millisekunden nehmen. 25 FPS reichen total, wenn nicht. Nimm 35. Mehr erkennt sowieso kein Mensch.

Dann benutz bitte InvalidateRect. Du sollst erst PostMessage WM_PAINT nehmen, wenn du weißt was du tust und das sieht hier definitiv nicht danach aus.

Werbeanzeige