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

Bigmek

Frischling

  • »Bigmek« ist der Autor dieses Themas

Beiträge: 28

Beruf: Informatiker(programmierer)

  • Private Nachricht senden

1

24.04.2008, 12:17

Kollision mit gedrehten Sprites

Ich arbeite gerade an einem 2D Weltraumshooter.
Ansicht ist eine Top Ansicht.

Habe den Code für die Kollisionsabfrage aus dem Buch "Jetzt lerne ich Spieleprogrammierung mit DirectX"
Der funktioniert aber nicht mit gedrehten Sprites.
Bin über hilfe sehr froh da ich alleine nichtmehr weiterkomme.

2

24.04.2008, 12:26

Damit dir jemand helfen kann, müsstest du schon etwas konkreter werden und den relevanten Code posten. ;)

Bigmek

Frischling

  • »Bigmek« ist der Autor dieses Themas

Beiträge: 28

Beruf: Informatiker(programmierer)

  • Private Nachricht senden

3

24.04.2008, 12:44

oh tschuldigung ganz vergessen.

allso ich möchte ein 2d game machen kamera position ist top allso von oben.

mein spiel mit einem raumschiff das sich 360 grad drehen kann,
und deshalb muss ich eine kollisionsabrfage mit gedrehten sprites machen können, weis aber nicht wie.

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
BYTE* CSprite::GetReducedImage(int AnimationNr)
{
    int nReductionFactor = 1;
    D3DSURFACE_DESC desc;

    LPDIRECT3DTEXTURE9 lpTexture = m_AnimationSequence[AnimationNr];
    lpTexture->GetLevelDesc(0, &desc);

    // Breite und Hoehe speichern

    DWORD tempWidth  = desc.Width;
    DWORD tempHeight = desc.Height;

    BYTE* lpReducedImage = new BYTE[m_Width / nReductionFactor * m_Height / nReductionFactor];

    // Textur sperren

    D3DLOCKED_RECT LockedRect;

    lpTexture->LockRect(0, &LockedRect, NULL, D3DLOCK_READONLY);

    DWORD* pPixels = reinterpret_cast<DWORD*>(LockedRect.pBits);

    LockedRect.Pitch /= 4;

    int i, j;

    // reduzierten Puffer füllen

    for(i=0;i<tempHeight;i+=nReductionFactor)
    {
        for(j=0;j<tempWidth;j+=nReductionFactor)
        {
            if(pPixels[i*LockedRect.Pitch + j] != 0)
            {
                lpReducedImage[i/nReductionFactor * tempWidth/nReductionFactor + j/nReductionFactor] = 1;
            }
            else
            {
                lpReducedImage[i/nReductionFactor * tempWidth/nReductionFactor + j/nReductionFactor] = 0;
            }
        }
    }

    // Textur freigeben

    lpTexture->UnlockRect(0);

    return lpReducedImage;
}

und hier die Kollisionsabfrage

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
BOOL TestCollision2D::TestCollision(CSprite* sprite1, float rotation1, float x1, float y1,int imgNr1, 
                                    CSprite* sprite2, float rotation2, float x2, float y2,int imgNr2)
{
    int tempSize = 0;
    int tempSize2 = 0;

    //Radius des Sprites messen

    if (sprite1->GetHeight() > sprite1->GetWidth())
        tempSize = (int)(sprite1->GetHeight() /2);
    else
        tempSize = (int)(sprite1->GetWidth() /2);

    //Radius des Sprites messen

    if (sprite2->GetHeight() > sprite2->GetWidth())
        tempSize2 += (int)(sprite2->GetHeight() /2);
    else
        tempSize2 += (int)(sprite2->GetWidth() /2);
    //Grobes testen ob Sprites sich berüren könnten


    //Distanz berechnen

    float xDis = x1-x2;
    float yDis = y1-y2;

    if (xDis < 0)
        xDis *= -1;

    if (yDis < 0)
        yDis *= -1;

    float tempDisToSprite2 = sqrt(pow(xDis,2)+pow(yDis,2));

    //wenn sich die Sprites berühren könnten genauer messen

    if (tempDisToSprite2 - (tempSize+tempSize2) <= 0)
    {
        
        int nReductionFactor = 1;

        BYTE* lpArea  = new BYTE[(tempSize*2+tempSize2*2+x1+y1)*(tempSize*2+tempSize2*2+x1+y1)];
        DWORD nAreaWidth = (tempSize*2+tempSize2*2+x1+y1)/nReductionFactor;

        memset(lpArea,0,nAreaWidth*nAreaWidth);
        DWORD Width = sprite1->GetWidth() / nReductionFactor;
        DWORD Height = sprite1->GetHeight() /nReductionFactor;
        DWORD x = nAreaWidth/2-(int)((sprite1->GetWidth() /2)/nReductionFactor);//(DWORD)(x1/nReductionFactor);

        DWORD y = nAreaWidth/2-(int)((sprite1->GetHeight() /2)/nReductionFactor);//(DWORD)(y1/nReductionFactor);

        DWORD i, j;
        BYTE* RedImg = sprite1->GetReducedImage(imgNr1);
        int index  = 0;
        // reduzierten Puffer füllen


        for(i=0;i<Height;i+=nReductionFactor)
        {
            for(j=0;j<Width;j+=nReductionFactor)
            {
                lpArea[(i+y)*nAreaWidth+j+x] = RedImg[i*Width+j];
            }
        }

        xDis = x2-x1;
        yDis = y2-y1;
        
        Width = sprite2->GetWidth() / nReductionFactor;
        Height = sprite2->GetHeight() /nReductionFactor;
        x = (nAreaWidth/2+xDis/nReductionFactor)-(int)((sprite2->GetWidth() /2)/nReductionFactor);//(DWORD)(x1/nReductionFactor);

        y = (nAreaWidth/2+yDis/nReductionFactor)-(int)((sprite2->GetHeight() /2)/nReductionFactor);//(DWORD)(y1/nReductionFactor);

        i, j;
        RedImg = sprite2->GetReducedImage(imgNr2);

        for(i=0;i<Height;i+=nReductionFactor)
        {
            for(j=0;j<Width;j+=nReductionFactor)
            {
                if (lpArea[(i+y)*nAreaWidth+j+x] && RedImg[i*Width+j])
                    return true;
            }
        }
        
    }
    
    return FALSE;
};

4

24.04.2008, 18:18

Wieso fragst du nicht im JLI Forum, da sind mehr Leute, die z.B. den Code schon kennen ;-)

Ansonsten solltest du dich evtl. von Pixelgenauer Abfrage verabschieden, den, naja, dafür musst du das Sprite drehen, und das ist ein wenig kompliziert und ein wenig Rechenintensiv. Wenn du ein Anfänger bist, lass pixelgenaue Kollision weg, wenn du es wirklich haben willst, sollte es im Inet ne Menge Informationen über das drehen von Bildern geben.
Lieber dumm fragen, als dumm bleiben!

Bigmek

Frischling

  • »Bigmek« ist der Autor dieses Themas

Beiträge: 28

Beruf: Informatiker(programmierer)

  • Private Nachricht senden

5

24.04.2008, 21:09

Ich brauche aber Pixelgenau abfragen, da einige Raumschiffe merkwürdige Formen haben.
Gedreht anzeigen kann ich es ja, nur wie ich es machen soll das bei der Pixelgenauen abfrage das Sprite gedreht wird weis ich nicht.

Ich weis nicht sorecht mit welchen schlüsselwürtern ich nach dem suchen soll was ich will.

6

28.04.2008, 13:02

Wenn ich das richtig sehe, beinhaltet doch die TriBase Engine aus dem Buch "3D-Spiele-Programmierung" alle benötigten Matrix- und Vektor-Routinen für die Rotation.
Da Du ja vermutlich mit Z-Achsen Rotation hinkommst, ist die Rotation ohnehin recht einfach, in etwa:

Zitat

pVBuffer->x =cosf(fRotationZ)+sinf(fRotationZ);
pVBuffer->y =cosf(fRotationZ)-sinf(fRotationZ);

Natürlich ggf. vor und nach der Rotation um Offset des Objektmittelpunktes(Rotationszentrums) zum Ursprung des Kamera-Koordinatensystems verschieben, wenn schon absolute Koordinaten vorlagen.

Gruß
Roberto

7

28.04.2008, 13:10

Dann müsste man aber entweder in einen seperaten Speicher rendern oder später auf den Bildbuffer zugreifen. Man könnte evtl. auch mit dem Stencilbuffer oder so arbeiten, aber auf jeden Fall wird es etwas komplizierter und aufwändiger als mit ungedrehten Objekten.
Lieber dumm fragen, als dumm bleiben!

Bigmek

Frischling

  • »Bigmek« ist der Autor dieses Themas

Beiträge: 28

Beruf: Informatiker(programmierer)

  • Private Nachricht senden

8

16.05.2008, 11:21

Ich habe leider immer noch keine ahnung wie ich das machen soll?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

20.05.2008, 12:01

Wie groß werden die Raumschiffe denn auf dem Bildschirm gerendert? Normalerweise reicht echt ein Kasten um das Sprite den du für die Kollision abfragst. Den musst du halt immer schön mitdrehen und an die Raumschiffe anpassen. kannst natürlich auch nen Kreis nehmen. das ist einfacher abzufragen aber je nach Form des Rauschiffs auch nicht das wahre;)
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

BlazeX

Alter Hase

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

10

20.05.2008, 12:36

Vieleicht kannst du ja den "Laser" oder die "Rakete" für die Berechnung drehen, anstatt das ganze Bild. Vieleicht sogar die Position.
Also alles aus der Sicht des Schiffes

Pseudocode:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
float fAngleShip; //Drehwinkel des Schiffes (im Uhrzeigersinn)

Vector2 vPosShip; //aktuelle Position des Schiffes

Vector2 vPosLaser; //Position des Lasers bzw der Rakete

...
//Laser zum Schiff relativieren

//Position

Vector2 vPosLaserRelToShip=vPosLaser-vPosShip;
//Rotation

vPosLaserRelToShip.x=cosf(fAngleShip)*vPosLaserRelToShip.x
                                -sinf(fAngleShip)*vPosLaserRelToShip.y;
vPosLaserRelToShip.y=cosf(fAngleShip)*vPosLaserRelToShip.y
                                +sinf(fAngleShip)*vPosLaserRelToShip.x;
...
//Jetzt kannst du deine Kollisionsprüfung vornehmen indem du

//für die Raumschiffposition (0,0) verwendest und für den Laser vPosLaserRelToShip

Werbeanzeige