[Java] Hulp gevraagd :collision detection Space Invaderclone

Pagina: 1
Acties:
  • 145 views sinds 30-01-2008
  • Reageer

  • kmf
  • Registratie: November 2000
  • Niet online
Ben bezig om een Space Invadersclone te maken voorlopig (later breid ik het wel uit tot een shootemup)

Spel bestaat uit 3 classes, en ik heb kan niet verzinnen welke class de test voor collision detection moet gaan regelen.

Ik heb het nu geprobeerd te gooien bij de run()-method in main, maar hele applet hangt dan.

Het lijkt erop dat wanneer ik de posities van de class shots opvraagt en deze direct in de GotHit-method pompt van de Class ship, deze het geheel laat hangen. Hoe dat komt weet ik niet. Taskmanager zegt dat de applet helemaal niks doet. Geen CPU-time OID.

Vraag is dus: weet iemand waar het aan ligt, of kan iemand me op betere ideeen brengen? (ben nog nieuw met OOP)

Java:
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/* Main class
 * *
 * *
 * */
 
import java.applet.Applet;
import java.awt.*;

public class main extends Applet implements Runnable
{
    Thread runner;
    Image background_img, PlayerShip_img, EnemyShip_img, Explosion_img;
    
    Ship playership; 
    Ship Enemies[] =new Ship[20] ;
    private Shot[] shots;
    
    int background_scrolling_speed;
    
    //doublebuffering vars
    Image dbImage;
    Graphics dbg;
    
    //key events
    boolean key_left;
    boolean key_right;
    boolean key_up;
    boolean key_down;
    boolean space;
    
    //Game variables
    private final int PlayerSpeed = 5;
    private final int shotSpeed = -7;
    private final int MaxEnemies = 16;
    private final int maxShots = 3;
    int PlayerStartX = 350;
    int PlayerStartY = 450;
    
    
    int EnPosX = 10;
    int EnPosY = 30;
    
    public void init()
    {
        background_img= getImage(getCodeBase(), "images/GameBackground.jpg");
        EnemyShip_img= getImage(getCodeBase(), "images/EnemyShip.gif");
        PlayerShip_img= getImage(getCodeBase(), "images/PlayerShip.gif");
        Explosion_img= getImage(getCodeBase(), "images/Explosion.gif");
        playership = new Ship(PlayerStartX, PlayerStartY,this);
        playership.setImages(PlayerShip_img);
        
        for (int i = 0; i<MaxEnemies; i++)
               { 
               Enemies[i] = new Ship (EnPosX, EnPosY, this);
               Enemies[i].setImages(EnemyShip_img);
               if (EnPosX<500)
                  EnPosX +=80;
               else if (EnPosX>=500)
                   {
                   EnPosX =50;
                   EnPosY =80;
                   }
               }
        shots = new Shot[maxShots];
    }
    

    public void run()
    {        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

        while(true)
        {
            //Thread sleeps for 10 milliseconds here
            try {runner.sleep(10);}
            catch (Exception e) { }
            background_scrolling_speed+=1;
            repaint();
            
            // do operations on shots in shots array
            for(int i=0; i<shots.length; i++)
            {
                if(shots[i] != null)
                {
                    // move shot
                    shots[i].moveShot(shotSpeed);

                    // test if shot is out
                    if(shots[i].getYPos() < 0)
                    {
                        // remove shot from array
                        shots[i] = null;
                    }
                }
            }
            
          //Player control
          if(playership.getPosX() >=0 && playership.getPosX()<=660)
           {
                if (key_left) 
                  playership.moveX(-PlayerSpeed);
                if (key_right)
                    playership.moveX(PlayerSpeed);
           }
          if(playership.getPosY() >=0 && playership.getPosY()<=460)
          {
                if (key_up)
                    playership.moveY(-PlayerSpeed);
                if (key_down)
                    playership.moveY(PlayerSpeed);
           }
/*           
 //Enemies movement (for testing purposes only)
         for (int i = 0; i<MaxEnemies; i++)
            {
                Enemies[i].moveY(1);
             }
*/
/*
 //Collision Detection 
 
          for (int i=0; i<MaxEnemies; i++)
            {
                for (int j=0; j<maxShots; j++)
                    if (
                        Enemies[i].GotHit(shots[j].getXPos(),shots[j].getYPos())
                        )
                        Enemies[i].setImages(Explosion_img);
            }
 */          
        }
    }
    
  
    
    public void paint(Graphics g)
    {   
        //Tiling and scrolling the backgroundImage
        if (background_scrolling_speed>640 ) background_scrolling_speed=0;
        for (int i=-640; i <10; i+=640)
            {
            g.drawImage(background_img,0, background_scrolling_speed+i,this);
            }
            
        //Paint the playership    
        playership.paintShip (g);
        
        //paint the enemies
        for (int i = 0; i<MaxEnemies; i++)
               Enemies[i].paintShip (g);

        // draw shots
        for(int i=0; i<shots.length; i++)
        {
            if(shots[i] != null)
            {
                shots[i].drawShot(g);
            }
        }
     }
 
    public boolean keyDown (Event e, int key)
    {
        if (key==Event.LEFT)
            key_left = true;
        else if (key== Event.RIGHT)
            key_right =true;
        else if (key==Event.UP)
            key_up=true;
        else if (key==Event.DOWN)
            key_down=true;
        
            // generate new shot and add it to shots array
        else if (key==32)
            for(int i=0; i<shots.length; i++)
            {
                if(shots[i] == null)
                {
                    shots[i] = playership.Shoot();
                    break;
                }
            }
        
        return true;
    }
    
    public boolean keyUp (Event e, int key)
    {
        if (key==Event.LEFT)
            key_left = false;
         if (key==Event.RIGHT)
            key_right = false;
        if (key==Event.UP)
            key_up = false;
        if (key==Event.DOWN)
            key_down = false;
        return true;
    }
    
 
 
     //Double Buffering
     public void update (Graphics g)
    {
       //initialize buffer
        if (dbImage==null)
        {
            dbImage = createImage(this.getSize().width, this.getSize().height);
            dbg = dbImage.getGraphics();
        }
        //clear screen in background
        dbg.setColor(getBackground());
        dbg.fillRect(0,0,this.getSize().width, this.getSize().height);
        
        //draw elements in background
        dbg.setColor(getForeground());
        paint(dbg);
        
        //draw image on the screen
        g.drawImage(dbImage,0,0,this);

    }

        public void start()
    {
        if (runner == null)
        {
            runner = new Thread (this);
            runner.start();
        }
    }


    public void stop()
    {
        if (runner != null)
        {
            runner.stop();
            runner = null;
        }
    }    
}


Java:
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
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * class Ship, will later become superclass for 
 * different type of ships
 * 
 */

import java.awt.*;

public class Ship
{
    int x_pos;
    int y_pos;
   
   //gameplay components
   int speed;
   int shield;
   Image Ship_Img;

   private Component parent;

    public Ship(int x, int y, Component parent)
    {
        x_pos = x;
        y_pos = y;
        speed = speed;
        shield = shield;
        this.parent = parent;
    }
    
    public void setImages (Image Ship_img)
    {
        this.Ship_Img = Ship_img;
    }
    
    public void moveX (int move)
    {
           x_pos += move;
           if (x_pos>660)
               x_pos=660;
           if (x_pos<0) 
                x_pos=0;
    }
    
    public void moveY (int move)
    {
        y_pos +=move;
        if (y_pos>460)
               y_pos=460;
           if (y_pos<0) 
                y_pos=0;
    }
    
 
    public Shot Shoot()
    {
        Shot shot = new Shot(x_pos+30, y_pos);

        return shot;
    }

    public boolean GotHit(int x, int y)
    {
        int distance_x = x - x_pos;
        int distance_y = y - y_pos;
        
        double distance = Math.sqrt ((distance_x*distance_x)+(distance_y*distance_y));
        
        if (distance <40)
            return true;
        else return false;
    }
            
                                
    public void paintShip(Graphics g)
    {
        g.drawImage(Ship_Img, x_pos, y_pos, parent);
    }
    
    public int getPosX()
    {
        return x_pos;
    }
    
    public int getPosY()
    {
        return y_pos;
    }
    
    public int getShieldStatus()
    {
        return shield;
    }
    
    public int getSpeedStatus()
    {
        return speed;
    }
    
}


Java:
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
/*
 * Class shot
 * handles the bulletsobject.
 */

  
import java.awt.Graphics;
import java.awt.Color;

public class Shot
{
    private int x_pos;
    private int y_pos;

    private final int radius = 5;

    public Shot(int x, int y)
    {
        x_pos = x;
        y_pos = y;
    }

    public int getYPos()
    {
        return y_pos;
    }
    public int getXPos()
    {
        return x_pos;
    }
    
    public void moveShot(int speed)
    {
        y_pos += speed;
    }

    public void drawShot(Graphics g)
    {
        g.setColor(Color.yellow);
        g.fillOval(x_pos -28, y_pos+5, radius, radius);
    }
}


Collegamodjes, mijn host lycos.nl is een beetje down, dus kan ik de code niet daar gaan proppen. Ben nu aan het proberen te zoeken naar de tweakers-FTP-data, dan pas ik deze post wel aan zodat het niet zo'n lap aan code laat zien

[ Voor 3% gewijzigd door kmf op 18-04-2003 11:48 ]

One thing's certain: the iPad seriously increases toilet time.. tibber uitnodigingscode: bqufpqmp


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
het enige dat opvalt is dat jouw 'shots' array een beetje 'vuil' is als een element op null staat is er geen shot. Maar in jouw detection hou je daar geen rekening mee. Je zult dus vast NullPointerExceptions gooien.

tips:
+Gebruik GEEN [] maar een LinkedList en gebruik Iterators - zo is de kans op null pointers heel wat minder (een remove v/e LL is triviaal).
+Ook staat je code vol nummers die moeten allemaal final statics worden als je ooit hoopt de code te veranderen.
+schrijf je constrcuts volledig (if(){}else{})
+gebruik een classe voor de posities (ie X-Y zou in postion.x, y)
+collision detection in jouw geval hoeft helemaal geen sqrt te gebruiken:
dX*dX+dY*dY < Distance*Distance is een pak sneller.
+ if () return false / return true === return (distance < maxDistance);
+ keys bijhouden doe je beter niet per variable maar in een ArrayList ...

Laat weten wanneer ie klaar is...

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Zoals hobbit_be al zei, is het waarschijnlijk dat er ergens een exception optreedt. Draai je de applet wel in de applet viewer? Of direct in een browser? In het laatste geval is het niet altijd eenvoudig om de exceptions (of andere debug uitvoer) te zien te krijgen.
Tips zijn altijd welkom, maar nu poneer je een aantal van jouw persoonlijke voorkeuren als algemene waarheden. Dat is natuurlijk niet zo netjes.
+Gebruik GEEN [] maar een LinkedList en gebruik Iterators - zo is de kans op null pointers heel wat minder (een remove v/e LL is triviaal).
Die LinkedList is niet heilig. Je zou ook prima een ander soort Container (op basis van een dynamische array of een boomstructuur) kunnen gebruiken. Dat het beter is om een Container te gebruiken voor dynamische collectie ben ik natuurlijk wel met je eens.
+schrijf je constrcuts volledig (if(){}else{})
Heb je hier een argument voor? Alleen correcte indentation is doorgaans al meer dan duidelijk genoeg, het toevoegen van extra haakjes (of zelfs een overbodige else-clause, als ik je voorstel goed beegrijp) is naar mijn mening zinloos.

[quote]+gebruik een classe voor de posities (ie X-Y zou in postion.x, y)[quote]In principe mee eens, maar realiseer je wel dat dit de manier is waarop Java applicaties ontzettend traag worden. Als snelheid van belang is (hier niet, lijkt me) kun je beter niet zoveel objecten instantieren. Er zit trouwens een Point2d klasse in de (niet-standaard) javax.vecmath package.
+collision detection in jouw geval hoeft helemaal geen sqrt te gebruiken:
dX*dX+dY*dY < Distance*Distance is een pak sneller.
Nu kom je opeens wel met optimalisaties aanzetten; wat wil je nu? Heldere code schrijven of snelle code schrijven? Naar mijn idee geeft het gebruik van die wortelfunctie veel duidelijker de intentie en werking van de code weer. Jouw voorstel is efficiënter (en ook nauwkeuriger) voor kleine getallen (distance < 46340) maar de algemene schrijfwijze is waarschijnlijk duidelijker voor een beginner.
+ keys bijhouden doe je beter niet per variable maar in een ArrayList ...
Waarom? Ik zou niet weten waarom je een Container zou moeten gebruiken als je van te voren een vast aantal keys hebt die je op wilt slaan. Als je dan een Container gebruikt, zou ik niet weten waarom dat per se een ArrayList zou moeten zijn. Heb je hier een uitleg bij?

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Soultaker schreef op 18 april 2003 @ 14:33:
1) Tips zijn altijd welkom, maar nu poneer je een aantal van jouw persoonlijke voorkeuren als algemene waarheden. Dat is natuurlijk niet zo netjes.
2) Die LinkedList is niet heilig. Je zou ook prima een ander soort Container (op basis van een dynamische array of een boomstructuur) kunnen gebruiken. Dat het beter is om een Container te gebruiken voor dynamische collectie ben ik natuurlijk wel met je eens.
3)Heb je hier een argument voor? Alleen correcte indentation is doorgaans al meer dan duidelijk genoeg, het toevoegen van extra haakjes (of zelfs een overbodige else-clause, als ik je voorstel goed beegrijp) is naar mijn mening zinloos.
4)In principe mee eens, maar realiseer je wel dat dit de manier is waarop Java applicaties ontzettend traag worden. Als snelheid van belang is (hier niet, lijkt me) kun je beter niet zoveel objecten instantieren.
5)Nu kom je opeens wel met optimalisaties aanzetten; wat wil je nu? Heldere code schrijven of snelle code schrijven? Naar mijn idee geeft het gebruik van die wortelfunctie veel duidelijker de intentie en werking van de code weer. Jouw voorstel is efficiënter (en ook nauwkeuriger) voor kleine getallen (distance < 46340) maar de algemene schrijfwijze is waarschijnlijk duidelijker voor een beginner.
6)Waarom? Ik zou niet weten waarom je een Container zou moeten gebruiken als je van te voren een vast aantal keys hebt die je op wilt slaan. Als je dan een Container gebruikt, zou ik niet weten waarom dat per se een ArrayList zou moeten zijn. Heb je hier een uitleg bij?
1) nou als ik zo'n code zie dan gruwel ik gewoon een beetje - de meeste tips zijn toch maar heel generaal (behalve structures) . Je hebt gelijk maar als ie zo verder ploeterd krijg je toch de typische errors.

2) LL is in een geval van een destroyable collection veruit de beste oplosiing (zie maar naar de collection benchmarks) nog beter is een CachedPool (ie: tripple []). Maar een [] is geen degelijke oplossing voor iets waar dingen moeten vernietigd worden... (ie hence de foute code)

3) Dit is kwestie van smaak natuurlijk. Maar als je met meerdere samen werkt is dit toch de vaakst gebruikte methode: ie least-common-denominator. Persoonlijk vind ik het toelaten van zulke gevallen een fout in de taal (net zoals een do/while, while, do gevallen) geef de user gewoon 1 manier en iedereen is beter af. (De grootse gruwel is de ? : constructie (hoe handig ie ook is :) ) (euh idd geen lege else maar wel dit:
code:
1
2
3
4
if (someTrurth)
{
    return Here; //en niet direct erachte
}

Ook for loops zonder haakjes... brr (koude rillingen)

4) Nou - nou een new van een pos zal vast wel meevallen - ie doe hier vaak een parsing van 100000 XML elements en dat duurt toch ook niet lang hoor. Als het snel moet gebruik je idd best [] maar Overzichtelijkheid > Snelheid. En ben
je nu met C bezig of Java? :)

5) Deze optimalisatie is heus wel belangrijk een SQRT KILLED alle speed en is een v/d traagste dingen op je PC (zeker als JVM geen Native doet) de meeste snelheidst winst word geboekt in het gebruik van Algoritmes niet of je [] or LL gebruikt... (HashMap bijvoorbeeld of BSP). Zelfs op mijn Assembly code Image Processing Routines probeer ik die SQRT te vermijden (en alle afstanden eerste te berekenen (en maar 1 keer). Hier kun je ook een Cell approach bijzetten als het nog sneller moet...

6) Nou heel leuk voor uitbreidbaarheid - of hersigning van keys - blijkbaar zelf nog geen game gemaakt? sorry maar dit is al standaard van toen ik in assembly bezig was...

Enne: het waren ook maar Tips he niet van: he eikel je code zuigt doe dit. Daarom gaf ik ook antwoord (en tamelijk precies) waar de fout kan zitten. Ooit schreef ik ook zo'n code en ben blij dat er toen mensen waren die me om alle tips wezen... Zoals alles advies: Take it or leave it...

Ik wou net vragen of het mogelijk was een aplet te testen en dankzij jouw weet ik ny dat ik appletviewer moet gebruiken :)

[ Voor 4% gewijzigd door hobbit_be op 18-04-2003 15:19 . Reden: (lege else) ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Trouwens, overal waar ik Container zei bedoelde ik Collection. :)
hobbit_be schreef op 18 April 2003 @ 15:09:
1) nou als ik zo'n code zie dan gruwel ik gewoon een beetje - de meeste tips zijn toch maar heel generaal (behalve structures) . Je hebt gelijk maar als ie zo verder ploeterd krijg je toch de typische errors.
Accoord, maar zoals je merkt valt er over veel van je stellingen wel te discussiëren (ook al ben ik het ondanks m'n kritiek in grote lijnen wel met je eens).
2) LL is in een geval van een destroyable collection veruit de beste oplosiing (zie maar naar de collection benchmarks) nog beter is een CachedPool (ie: tripple []). Maar een [] is geen degelijke oplossing voor iets waar dingen moeten vernietigd worden... (ie hence de foute code)
What the hell is een CachedPool? In ieder geval geen standaard Java Collection klasse. Het voordeel van een Collection object is juist dat je robuuste code kunt schrijven en het kiezen van de meest efficiente implementatie kunt uitstellen tot een latere fase. In principe maakt het weinig uit of je een LinkedList of een TreeList gebruikt.

Dat een linked list de beste keuze is voor een situatie waarin elementen uit een verzameling verwijderd moeten worden, is niet zomaar waar. In een linked list kun je uitsluitend lineair zoeken en dat is in veel situaties niet acceptabel. Als het opzoeken van elementen een veelvoorkomende operatie is, kun je beter een geordende Collection klasse nemen.
3) Dit is kwestie van smaak natuurlijk. Maar als je met meerdere samen werkt is dit toch de vaakst gebruikte methode: ie least-common-denominator.
Misschien zou je gewoon Nederlandse termen kunnen gebruiken en dan uitleggen wat het kleinste gemene veelvoud (want dat betekent least common denominator, als ik me niet vergis) te maken heeft met samenwerken? Ik kan me wel een voorstelling maken van wat je bedoelt, maar als het jouw punt is, mag je het zelf verdedigen, vind ik.
Persoonlijk vind ik het toelaten van zulke gevallen een fout in de taal (net zoals een do/while, while, do gevallen) geef de user gewoon 1 manier en iedereen is beter af. (De grootse gruwel is de ? : constructie (hoe handig ie ook is :) ) (euh idd geen lege else maar wel dit:
Die if en if-else zijn juist de twee manieren (die jij er dus wél in wil houden?!). Verder is de structuur gewoon altijd "if(<expressie>) <statement>" waarbij statements toevallig gegroepeerd mogen worden tot een composiet statement, door er accolades omheen te zetten.
4) Nou - nou een new van een pos zal vast wel meevallen - ie doe hier vaak een parsing van 100000 XML elements en dat duurt toch ook niet lang hoor. Als het snel moet gebruik je idd best [] maar Overzichtelijkheid > Snelheid. En ben
je nu met C bezig of Java? :)
Ok, onthoud die stelling en lees even mee:
5) Deze optimalisatie is heus wel belangrijk een SQRT KILLED alle speed en is een v/d traagste dingen op je PC (zeker als JVM geen Native doet)
Bron, beredenering? IBM-compatible PC's vanaf de 486 (of, laten we gewoon voor het gemak zeggen: alle hedendaagse computers) hebben een FPU die dit soort berekeningen redelijk snel uitvoert. Het is inderdaad veel trager dan een vermenigvuldiging, maar is dit significant in de context van het hele programma?

Kijk nog even terug naar wat je bij puntje 4 zegt: gaat het nu over overzichtelijkheid of snelheid? Ben je nu met C bezig of Java? Ik zou zelf in zowel Java als C beide optimalisaties doorvoeren, maar ik vind het gek dat je wel enerzijds achterlijk veel objecten gaat alloceren en anderszijds klaagt over het gebruik van een FPU-instructie, terwijl de FPU toch vaak idle is en het verdelen van werk over de CPU en FPU juist een verhoogde efficiëntie met zich mee brengt, waardoor de performance winst die jouw voor ogen staat maar twijfelachtig is.
de meeste snelheidst winst word geboekt in het gebruik van Algoritmes niet of je [] or LL gebruikt...
Dat hangt er dus maar vanaf. De feitelijke efficiëntie van een algoritme wordt bepaald door de gebruikte datastructuren. Niet alleen de theoretische complexiteit kan daarmee variëren, maar ook (bij gelijke complexiteit) de verborgen constante bij de executie van het algoritme.
Zelfs op mijn Assembly code Image Processing Routines probeer ik die SQRT te vermijden (en alle afstanden eerste te berekenen (en maar 1 keer). Hier kun je ook een Cell approach bijzetten als het nog sneller moet...
Je wil assembly met Java (en/of helder programmeren) vergelijken? Zie nogmaals je eigen commentaar bij puntje 4.
6) Nou heel leuk voor uitbreidbaarheid - of hersigning van keys - blijkbaar zelf nog geen game gemaakt? sorry maar dit is al standaard van toen ik in assembly bezig was...
Zo, ben jij even een 1337 h4x0r; een assembly programmeur weet vast alles van gestructureerd en overzichtelijk programmeren. Ik heb inderdaad geen game gemaakt, maar ik zie (gek genoeg) nog steeds niet wat je nu met je ArrayList wilt bereiken. Wat ga je daar in stoppen? Aangeslagen toetsen? Waarom dan een ArrayList en geen andere Collection klasse? Als je associaties wilt maken tussen toetsen en acties kun je dan niet beter een Map gebruiken?

Je argument komt nu neer op "je moet een ArrayList gebruiken want jij hebt geen game gemaakt en ik deed het zo toen ik in assembly bezig was" en dat slaat natuurlijk nergens op. In assembly lijkt het me trouwens veel makkelijker gewoon een statische array te gebruiken, maar dat terzijde.
Enne: het waren ook maar Tips he niet van: he eikel je code zuigt doe dit. Daarom gaf ik ook antwoord (en tamelijk precies) waar de fout kan zitten. Ooit schreef ik ook zo'n code en ben blij dat er toen mensen waren die me om alle tips wezen... Zoals alles advies: Take it or leave it...
Dat begrijp ik; daarom geef ik ook weer wat commentaar op jouw tips, misschien leren we dan nog wat van elkaar.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
(Sorry effe EMail stylee quotes :)

> Trouwens, overal waar ik Container zei bedoelde ik Collection. :)

dat had ik wel door :) Nu nog wachten to Iterable in 1.5 komt en Java begint
er wat beter uit te zien.

>What the hell is een CachedPool? In ieder geval geen standaard Java Collection >klasse.

Nee idd.. er ontbreken in die Classen trouwens heel wat nuttige Collections: een Cached Pool is als volgt"

je hebt een Linear Access Collection (ie ArrayList, of []) waar je de data bijhoudt.

iedereen weet dat realloc of mem deadly is voor realtime. dus we willen ervoor zorgen dat die nooit gereaccolled word.

dan heb je een LAC die bijhoudt welke van de bovenstaande gebruikt wordt (ie een LUT met zelfde groote), en dan heb je NOG :) een LAC die bijhoud welke
vrij zijn. DWZ dat voor ieder object je idd dus nog een 2 x 1 integer gaat bijhouden. (ik heb niet gezegd dat het memory friendly was , MAAR wel even groot als een LL)

Goed alleen bij de init heb je effe probleempje bij het vullen van je Free List (vieze for loop) maar daarna wordt het super snel: je kan direct een nieuwe aanvragen, direct een oude wegvegen, je kunt direct alle opvragen met een iterator. En nog degoutanter is dat de originele indez ook blijft behouden (als jde dat zou nodig hebben).

Merk wel op dat eenmaal de Pool vol is je natuurlijk wel moet resizen (unlike LL).

Deze strcutuur gebruik ik al heel lang voor heel intensieve 'games' tostanden (ie
35.000 verschillende gravity objects die kunnen vernietigd worden in eender welke volgorde en die gespawned worden, maar altijd linear time access) . Euh dit is vast niet mijn idee hoor :) (is te simpel om iemands idee te zijn ). Vooral bij games (en dus respawn, is dit heel handig (als de aantallen groot zijn).

>Het voordeel van een Collection object is juist dat je robuuste code kunt schrijven >en het kiezen van de meest efficiente implementatie kunt uitstellen tot een latere >fase. In principe maakt het weinig uit of je een LinkedList of een TreeList gebruikt.

idd - maar some Collections kunnen bepaalde acties niet aan wat dan weer wil zeggen dat er toch niets helemaal klopt in Collection spul (veel te high-level) maar idd heel leuk om snel om te wisselen...

>Dat een linked list de beste keuze is voor een situatie waarin elementen uit een >verzameling verwijderd moeten worden, is niet zomaar waar.

idd - ik gaf alleen aan dat voor de shots (ie nameless) wel zo is (maar zoals above kan alles beter natuurlijk)

> Misschien zou je gewoon Nederlandse termen kunnen gebruiken en dan uitleggen wat het kleinste gemene veelvoud (want dat betekent least common denominator, als ik me niet vergis) te maken heeft met samenwerken? Ik kan me wel een voorstelling maken van wat je bedoelt, maar als het jouw punt is, mag je het zelf verdedigen, vind ik.

lol - nu moest ik er zelf om lachen - ik heb heel mijn leven bijna in engelstalige landen gewoont dus excuses - het wil zeggen : hetgeen dat voor iedereen opgaat (maar wel dus niet altijd de 'optimal' solution)...

>Die if en if-else zijn juist de twee manieren (die jij er dus wél in wil houden?!). Verder is de structuur gewoon altijd "if(<expressie>) <statement>" waarbij statements toevallig gegroepeerd mogen worden tot een composiet statement, door er accolades omheen te zetten.

Dat kan zijn maar een taal die op 'Bloks' berust moet, vind ik, (!) niet ineens er zonder mee beginnen. Maar ik neem aan dat jij meer kent van de manier waarop if is bepaalt. WNWZ dat ik ermee akkord ga. Moest daarnet nog uitlegeen aan een newbie waarom je some wel {} en niet {} moest doen. Het feit dat die vragen voorkomen is voor mij al genoeg om te zeggen: het 'kan' ook anders:
"id (<expressie>) <codeblock> 'Optional: ': else <codeblock>. Denk ook aan 'case' geval (heel handig als je het misbruikt :), maar eigenlijk niet om aan te zien :) ...

>Bron, beredenering? IBM-compatible PC's vanaf de 486 (of, laten we gewoon voor het gemak zeggen: alle hedendaagse computers) hebben een FPU die dit soort berekeningen redelijk snel uitvoert. Het is inderdaad veel trager dan een vermenigvuldiging, maar is dit significant in de context van het hele programma?

yep :) sorry maar SQRT is niet zomaar een 'imul' of 'idiv' maar echt wel HEEL erug traag. op een 486 ging het op de 'FPU' zelfs zo traag dat je beter in pure Integer code je eigen Newton-Rapson kon toepassen. Net zoals Cos/Sin (nog steeds beter om in een LUT te steken) gelukkig is een mul nu toch triviaal (hoeveel keer ik nog
shr, shl heb getypt voor address berekening). Maar helaas is SQRT nog steeds een v/d traagste gevallen. Nu ja als het echt snel moet kunt je nog beter Fixed Point gebruiken (nog steeds) (voor simpel gevallen).

> Ik zou zelf in zowel Java als C beide optimalisaties doorvoeren, maar ik vind het gek dat je wel enerzijds achterlijk veel objecten gaat alloceren en anderszijds klaagt over het gebruik van een FPU-instructie, terwijl de FPU toch vaak idle is en het verdelen van werk over de CPU en FPU juist een verhoogde efficiëntie met zich mee brengt, waardoor de performance winst die jouw voor ogen staat maar twijfelachtig is.

tja - je hebt wel gelijk natuurlijk - waar ligt die grens: ik vind altijd als je 30x in je code moet gaan schrijven: if (mX < 0) && (mY <0) && (mX >...) dat het dan toch beter is gewoon een fucntion of method erop los. in C++ kun je het allemaal inlinen natuurlijk (Java 1.5?) maar ook code-size doet ertoe. Maar ik denk wel dat we hetzelfde erover denken dat ze in Quake III heus geen mX en mY voor elk object gebruiken :). Zelfs in Demos these days is het ook al OOP wat de klok slaat (ivm opslagen van x,y,dx,dy, waren te tijde nog hele kunsten om die te aligen en weet ik wat nog, zlefs in WinAPI moet alles int-alligned zijn) zelfs de orde van de variable doet er nog steeds toe: ie

class
{
short t;
int t;
int k;
}

is een heel pak trager (zonder pack statements - ugly)

dan
{
int tl
int k;
short t;
}


>Dat hangt er dus maar vanaf. De feitelijke efficiëntie van een algoritme wordt bepaald door de gebruikte datastructuren. Niet alleen de theoretische complexiteit kan daarmee variëren, maar ook (bij gelijke complexiteit) de verborgen constante bij de executie van het algoritme.

Ok. 50-50. (Quicksort/Bubblesort...) ze moeten hand in hand gaan...

>Je wil assembly met Java (en/of helder programmeren) vergelijken? Zie nogmaals je eigen commentaar bij puntje 4.

nee maar wel met programma opbouw...

>Zo, ben jij even een 1337 h4x0r; een assembly programmeur weet vast alles van gestructureerd en overzichtelijk programmeren.

yep - aangezien je in assembler VEEL gestructuurd moet bezig zijn aangezien de taal zelf nou, maar zo simpel is. (1337 h4xOr ? de lingo is al wat veranderd since de old days :)

>Ik heb inderdaad geen game gemaakt, maar ik zie (gek genoeg) nog steeds niet wat je nu met je ArrayList wilt bereiken. Wat ga je daar in stoppen? Aangeslagen toetsen? Waarom dan een ArrayList en geen andere Collection klasse? Als je associaties wilt maken tussen toetsen en acties kun je dan niet beter een Map gebruiken?

Wel een Map is ook goed hoor - ik bedoel dat je kunt doen:

if (isKeyPressed("A", (of "Action")))
{

}

dan kun jw de helemanier van input abstraheren - en heel nuttig bij welk ook programma... (voor spelletje waar iedereen wel andere keys gebruikt: mijn FPS zijn
"y" = forward, "z" backward, "e"-"r" zijn left/right...... Maar het idee van een Map vind ik wel leuk ook trouwens, maar is dan weer een tikkeltje trager dan:

static FORWARD_KEY = 125;

ff (keyPressed(FORWARD_KEY))...

> In assembly lijkt het me trouwens veel makkelijker gewoon een statische array te gebruiken, maar dat terzijde.

idd - maar je vergeet wel dat een ArrayList == Statsiche array (die groeit als het moet) het gaat em om random access (en LL is deadly, Hash DIngen een mooie
tussen weg (als je hash goed is)..

Ik vraag me af wat de 'poster' van de topic ervan denkt :)

Net als jij met mij ga ik dus ook akkord met 90% van je comments...

  • kmf
  • Registratie: November 2000
  • Niet online
Even reageren, de discussies in deze topic zijn zeer interessant, maar gaan toch redelijk offtopic. Ik vind het niet erg om dat te lezen, maar ik kan me voorstellen dat mijn collega's daar anders over denken. Ga vooral door though, ik leer er een hoop van.

Dankzij de paar relevante posts is het me wel duidelijk geworden dat de applet idd hangt omdat er een nullpointerexception aan de gang is. Er wordt immers een shot onderzocht dat helemaal nog niet bestaat.
Ik zal daar nog even over na moeten denken hoe ik dat kan oplossen.

Maar ik heb toch het gevoel dat ik niet op de juiste manier de col. detect. aan het checken bent. Ten eerste bekijk ik idd een momentopnamen, ten tweede om ELKE keer dat alle shots en alle targets te gaan checken lijkt mij niet te goede (lees efficiente) methode.
Misschien dat jullie me een andere tip kan geven hierover?

En hobbit en soul, hetgeen wat jullie vertellen is nogal geavanceerd. Ik ben nu ongeveer anderhalf maand bezig met java te leren en hoewel ik gelinkte lijsten onder pascal wel eens had gebruikt, heb ik geen toepassing gezien hoe dit in Java hoort te gebeuren, dus kwam het ook niet direct bij mij op om dat te gebruiken.
En ik vraag me af of de vectorclass niet een betere keuze is dan een linked list.

Ik ben java aan het leren a.d.h. van een boek en wat tutorials, en die behandelen enkel de standaard progdingen.
Mbv. van het maken van een spel kan ik al die losse informatiestukjes aan elkaar binden, maar ik heb me dus nog niet verdiept in de wat geavanceerdere technieken.
Dit zie je dan ook terug in de stukjes code, het is vrij warrig omdat ik bij nieuwe inzicht, nieuwe aanpassingen maakt.
Het gebruik van al die nummers en variabelen is niet netjes, maar het helpt voor mij wel om een beetje overzicht in het geheel te krijgen.
Als ik java redelijk onder de knie heb, zal ik een meer coherent stuk code schrijven.

Ook is het de eerste keer dat ik een spel zit te maken ipv een applicatie, dus zit ik ook tegelijkertijd uit te vogelen wat er bij komt kijken bij het proggen van een spel.
En ik moet zeggen dat het niet eenvoudig is om daar informatie over te vinden.

Wat ik mij nu vooral afvraag is hoe een scenario van een level wordt opgezet. Hoe wordt geprogrammeerd hoe een groep enemies door een level vliegt.

[ Voor 25% gewijzigd door kmf op 18-04-2003 17:40 ]

One thing's certain: the iPad seriously increases toilet time.. tibber uitnodigingscode: bqufpqmp


  • Ericston
  • Registratie: Maart 2001
  • Laatst online: 30-03 17:41
Ik heb nog nooit Java geprogrammeerd, dus met die vastloper kan ik je niet helpen.

Misschien kan ik je wel op betere ideeën brengen. Dit vroeg ik me namelijk ook af toen ik op een nette manier collision detection wilde implementeren in mijn Pong kloon in C++. Ik dus flink op zoek naar bepaalde Design Patterns die hier misschien betrekking op hebben.
Uiteindelijk kwam ik op deze link: http://www.datasim.nl/education/articles/dp/whitep3.htm
Dit is het meest interessant:
More generally, the Observer pattern can be used to create constraint-management systems using a Change Manager class. For example, it is possible to define relationships between objects which must be satisfied at all times. Such applications are important when implementing CAD design rules, collision detection rules in virtual reality applications and geometric constraints (parallel, perpendicular, concentric).
Meer kan ik je eigenlijk niet helpen want uiteindelijk heb ik het toch maar procedureel gedaan (the joys of programming in C++ O-)) omdat het overkill leek om iets dergelijks te implementeren voor 2 paddles wat muren en een bal. Wellicht kunnen andere users je wat meer vertellen over de implementatie van het Observer pattern in deze situatie.

Hopelijk heb ik de thread zo wat meer on-topic gebracht. :)

Nog wat andere linkjes die mogelijk interessant zijn en betrekking hebben op CD in het algemeen:
http://www.gamedev.net/reference/articles/article736.asp
http://www.gamasutra.com/features/20000330/bobic_pfv.htm
http://www.gamasutra.com/features/19991018/Gomez_7.htm
(Wellicht moet je lid worden van Gamasutra om die artikelen te zien.)

  • kmf
  • Registratie: November 2000
  • Niet online
Ericston schreef op 18 April 2003 @ 18:02:

Meer kan ik je eigenlijk niet helpen want uiteindelijk heb ik het toch maar procedureel gedaan (the joys of programming in C++ O-)) omdat het overkill leek om iets dergelijks te implementeren voor 2 paddles wat muren en een bal.
Haha, ik had juist voor Java gekozen omdat ik dan wel OO MOET programmeren :)

Zelfs dan zie ik mezelf dan te vaak procedureel denken... I blame the system met rotpascal, het is er zo ingestampt gewoon.
8)7

One thing's certain: the iPad seriously increases toilet time.. tibber uitnodigingscode: bqufpqmp


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
athlonkmf schreef op 18 April 2003 @ 17:34:
Even reageren, de discussies in deze topic zijn zeer interessant, maar gaan toch redelijk offtopic. Ik vind het niet erg om dat te lezen, maar ik kan me voorstellen dat mijn collega's daar anders over denken. Ga vooral door though, ik leer er een hoop van.
offtopic:
Jij hebt zeker nog nooit een C++ topic hier doorgelezen :P >:)


Gebruik trouwens liever geen Vector, maar een ArrayList. Ze doen opzich precies hetzelfde, alleen is ArrayList niet syncronized (net als alle andere >1.1 Collection classes)
Maar je keuze tussen ArrayList en LinkedList hangt op 1 punt:
Wat ga je er mee doen?

ArrayLists zijn sterk in random access. Het opvragen van een element kost altijd evenveel tijd. Het zijn in feite gewoon resizeable array's :)
LinkedLists zijn veel sterker in het invoegen/ verwijderen van elementen.
Het verschil is namelijk dat de LinkedList alleen 1 link in de lijst hoeft te veranderen en een ArrayList moet alles gaan verschuiven.

Illustratie
code:
1
2
LinkedList:
A -> B -> C -> D -> E
Stel nu, B moet weg. Dan gaat A gewoon naar C wijzen

code:
1
2
ArrayList:
A | B | C | D | E

Stel dat nu B weg moet. Dan moet C B overschrijven, D moet de oude plek van C overschrijven, E moet de oude plek van E overschrijven enz enz.
Daardoor is LinkedList vele malen sneller met het verwijderen/invoegen van objecten.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
yow - ok terug ontopic

je kunt je detection wel doen werken door te controleren in jouw loopje of shot weldegelijk valid is...

for (int j=0; j<maxShots; j++)
{
if ( shots[j] != null) //dit moet je dus overal doen - ook op je enemies denk ik
{

}
}

imho staat je collision detection wel op het goede punt in de classe structuur.

Als je nog maar zo kort bezig bent vind ik dit trouwens DE perfecte methode om een taal te leren - fun en meestal gebruik je elk element v/d taal. Zoals je zelf aanhaalt is het nog wat te Pascal achtig maar zoals Soul al zei - op een bepaald niveau is dat nog steeds de snelste methode. (We hebben hier ooit eens een Replace in een String geschreven daar kon je ook geen punten mee winnen , maar was wel super snel).

Ovm je vraag over het maken van levels - dat is ook stevig voer :)

Het eleganst is een 'scripting' taaltje (ie een soort van mix tussen een timeline editor en event editor). Maar het hangt allemaal af van hoe 'intelligent' hoeft te zijn. gek Genoeg zit heel veel in zoiets als VRML (yeah i know) dat werkt met 'Triggers' die dan iets doen.

Wat je eventueel wel kan doen is dat een 'shot' is eigenlijk een 'ship' (of vice versa) dus probeer de overeenkomsten tussen beide te vinden en dan daarvan de classe afleiden:

zowel jij, enemies, 'shot' zijn 2D objectes die: bewegen, een omvang hebben (collision) dus
kun je daar bijvoorbeeld een simple classes van hebben

class Object2D
{
void move()
vector getPosition();
boolean hit(pos);
ImageIcon getUIRepresentation();
int getZLevel(); //nodig om ervoor te zorgen dat je shot later word getekent

}

class Shot
extends Object2D {}

class Me
extends Object2D
{
void shoot();
}

class World
{
}

ie OOP is vooral over reusability en over gelijk behaviour...

  • kmf
  • Registratie: November 2000
  • Niet online
hobbit_be schreef op 18 April 2003 @ 19:06:
yow - ok terug ontopic

je kunt je detection wel doen werken door te controleren in jouw loopje of shot weldegelijk valid is...

for (int j=0; j<maxShots; j++)
{
if ( shots[j] != null) //dit moet je dus overal doen - ook op je enemies denk ik
{

}
}

imho staat je collision detection wel op het goede punt in de classe structuur.

Als je nog maar zo kort bezig bent vind ik dit trouwens DE perfecte methode om een taal te leren - fun en meestal gebruik je elk element v/d taal. Zoals je zelf aanhaalt is het nog wat te Pascal achtig maar zoals Soul al zei - op een bepaald niveau is dat nog steeds de snelste methode. (We hebben hier ooit eens een Replace in een String geschreven daar kon je ook geen punten mee winnen , maar was wel super snel).

Ovm je vraag over het maken van levels - dat is ook stevig voer :)

Het eleganst is een 'scripting' taaltje (ie een soort van mix tussen een timeline editor en event editor). Maar het hangt allemaal af van hoe 'intelligent' hoeft te zijn. gek Genoeg zit heel veel in zoiets als VRML (yeah i know) dat werkt met 'Triggers' die dan iets doen.

Wat je eventueel wel kan doen is dat een 'shot' is eigenlijk een 'ship' (of vice versa) dus probeer de overeenkomsten tussen beide te vinden en dan daarvan de classe afleiden:

zowel jij, enemies, 'shot' zijn 2D objectes die: bewegen, een omvang hebben (collision) dus
kun je daar bijvoorbeeld een simple classes van hebben

class Object2D
{
void move()
vector getPosition();
boolean hit(pos);
ImageIcon getUIRepresentation();
int getZLevel(); //nodig om ervoor te zorgen dat je shot later word getekent

}

class Shot
extends Object2D {}

class Me
extends Object2D
{
void shoot();
}

class World
{
}

ie OOP is vooral over reusability en over gelijk behaviour...
Doordat ik programmeren hebt geleerd met pascal, pascal en nog eens pascal heb ik vrij veel moeite om OOP te gaan denken. Ik begrijp de theorie daarachter wel, en ben er zeker mee eens dat het veel handiger werken is, maar de mens neigt de makkelijkste weg te nemen bij problemen. En de makkelijkste weg is meestal ook de meest vertrouwde, daarom koos ik voor java om te leren en niet C++, zodat ik het gestructureerd of procedureel programmeren zoveel mogelijk kan afleren.
Ik begin het ook een beetje onder de knie te krijgen, maar dat betekent wel heel vaak code herschrijven :)


Mijn probleem met Collision Detection is trouwens ook al opgelost dankzij jullie inbreng.
Met een simpele preconditietest, is de nullexception ding verleden tijd. Ziehier:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
for (int k=0; k<MaxEnemies; k++)
            {
                for (int l=0; l<maxShots; l++)
                    if (Enemies[k] != null && shots[l] != null &&
                        Enemies[k].GotHit(shots[l].getXPos(),shots[l].getYPos())
                        )
                        {
                        Enemies[k].setImages(Explosion_img);
                        Enemies[k] = null;
                        shots[l] = null;
                        }
            }


Alleen, bij het oplossen van een probleem komt meestal een ander boven water.
Met het direct nullstellen van enemies[k], zie ik de explosie niet meer, aangezien deze pas later in de paint-loop wordt aangeroepen.

Dus het wordt weer tijd voor verdere studie: Animaties :)
(tips zijn welkom though ;)

Zo wordt een beginnend programmeur wel steeds op een uitdagende manier gedwongen extra dingen aan te leren.
Veel ingewikkelder dan de standaard "hello world"->"berekeningen"->"iteraties"->"arrays"->etc loopbaan, maar de behoefte om een eindproduct af te leveren EN omdat het veel leuker is om een daadwerkelijke spel te maken ipv een of ander BinaireBoom-afzoek-progsel blijf je aan de gang :)

One thing's certain: the iPad seriously increases toilet time.. tibber uitnodigingscode: bqufpqmp


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
hobbit_be schreef op 18 april 2003 @ 17:00:
Nee idd.. er ontbreken in die Classen trouwens heel wat nuttige Collections: een Cached Pool is als volgt"

je hebt een Linear Access Collection (ie ArrayList, of []) waar je de data bijhoudt.

iedereen weet dat realloc of mem deadly is voor realtime. dus we willen ervoor zorgen dat die nooit gereaccolled word.

dan heb je een LAC die bijhoudt welke van de bovenstaande gebruikt wordt (ie een LUT met zelfde groote), en dan heb je NOG :) een LAC die bijhoud welke
vrij zijn. DWZ dat voor ieder object je idd dus nog een 2 x 1 integer gaat bijhouden. (ik heb niet gezegd dat het memory friendly was , MAAR wel even groot als een LL)

Goed alleen bij de init heb je effe probleempje bij het vullen van je Free List (vieze for loop) maar daarna wordt het super snel: je kan direct een nieuwe aanvragen, direct een oude wegvegen, je kunt direct alle opvragen met een iterator. En nog degoutanter is dat de originele indez ook blijft behouden (als jde dat zou nodig hebben).

Merk wel op dat eenmaal de Pool vol is je natuurlijk wel moet resizen (unlike LL).

Deze strcutuur gebruik ik al heel lang voor heel intensieve 'games' tostanden (ie
35.000 verschillende gravity objects die kunnen vernietigd worden in eender welke volgorde en die gespawned worden, maar altijd linear time access) . Euh dit is vast niet mijn idee hoor :) (is te simpel om iemands idee te zijn ). Vooral bij games (en dus respawn, is dit heel handig (als de aantallen groot zijn).
Ik zie eigenlijk niet echt in hoe dit efficienter is dan een ArrayList die (bv.) ten alle tijde een grootte van 2^N heeft.
in C++ kun je het allemaal inlinen natuurlijk (Java 1.5?) maar ook code-size doet ertoe. Maar ik denk wel dat we hetzelfde erover denken dat ze in Quake III heus geen mX en mY voor elk object gebruiken :). Zelfs in Demos these days is het ook al OOP wat de klok slaat (ivm opslagen van x,y,dx,dy, waren te tijde nog hele kunsten om die te aligen en weet ik wat nog, zlefs in WinAPI moet alles int-alligned zijn)
Maar in C++ zijn structs (of klassen) gewoon waarden terwijl het in Java per se references moeten zijn. In C++ is deze code:
C++:
1
2
3
4
5
class Whatever
{
    int x1, y1;
    int x2, y2;
}

equivalent (qua geheugengebruik) aan:
C++:
1
2
3
4
5
6
7
8
9
class Point
{
    int x, y;
};

class Whatever
{
    Point p1, p2;
};


In Java wordt in het eerste geval echt een object met 4 integers aangemaakt, en in het tweede 3 objecten (2 met 2 integers, en 1 met 2 references). Dat zijn dus drie keer zoveel allocaties, 50% meer geheugen, en het gebruik van de coordinaten kost een extra indirectie.
maar je vergeet wel dat een ArrayList == Statsiche array (die groeit als het moet) het gaat em om random access (en LL is deadly, Hash DIngen een mooie
tussen weg (als je hash goed is)..
Een ArrayList encapsuleert een dynamische array: voor het benaderen van de elementen is een extra indirectiestap nodig en (tenminste één) extra allocatie. Een gewone array is dus wel degelijk efficiënter. Dat neemt niet weg dat je die efficiëntie in 95% van de gevallen niet nodig hebt, natuurlijk. Als je echter aan een vast aantal waarden (toetsen op het toestenbord) een functie wilt koppelen, zou ik gewoon een statische array gebruiken en die indiceren om de gewenste functie te vinden.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
ik denk dat Java well animated gif aankan - maar don't quote me :). ivm weergevn van explosies: logisch gezien is dit een object waar collesion detection er niet meer omdoet (tenzij je collateral damage hebt ;) ) dus kun je eventueel een nieuw class 'explosions' doen
(in mijn simpele stijl - een object2d maar dan zonder omvang) die 'add' je dan als je het ding 'explodeert' - is in feite een non-interacting particle system...

  • kmf
  • Registratie: November 2000
  • Niet online
hobbit_be schreef op 18 April 2003 @ 20:00:
ik denk dat Java well animated gif aankan - maar don't quote me :). ivm weergevn van explosies: logisch gezien is dit een object waar collesion detection er niet meer omdoet (tenzij je collateral damage hebt ;) ) dus kun je eventueel een nieuw class 'explosions' doen
(in mijn simpele stijl - een object2d maar dan zonder omvang) die 'add' je dan als je het ding 'explodeert' - is in feite een non-interacting particle system...
Een aparte klasse lijkt me mooi hierover, dan kan ik natuurlijk een hoop animaties invoegen.
(animated gifs kan java niet aan trouwens)

Kijk, dat is weer een voorbeeld de lood van procedureel programmeren aan m'n schoenen.

Ik zal eerst denken aan een doorlopend stuk aan instructies.

coll.detect->paint explosionimg->set null-> repaint
zat dus gelijk de "verkeerde" kant op te denken :/

One thing's certain: the iPad seriously increases toilet time.. tibber uitnodigingscode: bqufpqmp


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
offtopic:
>>Ik zie eigenlijk niet echt in hoe dit efficienter is dan een ArrayList die (bv.) ten >>alle tijde een grootte van 2^N heeft.

als je dat niet begrijpt doe dan een een remove van je eerste element op een arraylist en vraag dan de eerste terug op. (oh en maak wel dat je je arraylist een deftige size is) . Qua Memory is een ArrayList DE meest effeciente manier - qua speed kan niets op (met die kenmerken: Linear Random Access, Linear Delete, Linear New) tegen een Pool.

Om je de code te besparen als je de allereerste removed op een ArrayList van stel 1000 element (kleine nummer om het simpel te houden) moet ie dus wel degelijk :
999 element (de references) gaan kopieren (en aangezien een arraylist indexed based is kan die niet bijvoorbeeld effe het laatse object in die plaats zetten). Bij een CachedPool is een remove gelijk aan 2 memory 'copies' (assignment) van 2 variable... Ik neem aan dat ArrayList zelfs eerst een volledige nieuwe array gaat maken (ie van 999, + dan nog eens een copy) als het object ergens in het midden zit moeten er zelfs 2 copies gebeuren (toch weer een stukje trager)... en een memory copy en resize in Java is SUPER cruciaal (om maar aan te halen het geval v/d replace: we hadden verschillende methode voor een match te vinden, maar alleen door ervoor te zorgen dat er niets teveel werd gecopierd ging de snelheid ENORM omhoog (we spreken hier op bepaalde gevallen over duizenden % increase in speed). Maar ook bij C++ is zoiets ook aan te raden.

Een van de redenen waarom de MFC CString zo snel is dat hij bij het creeren v/e nieuw type in verschillende pools met verschillende grote gaat kiezen in welk stukje geheugen hij hem gaat zetten). En dat StringBuffer in java ook belachelijk veel sneller is dan String += String weet je vast ook...

Natuurlijk is een pure array het snelste (das gewoon een pointer+offset) maar niet zodra je er iets mee moet doen: ie die CachedPool van me gebruik ook doodleuk 3 [] (en geen 3 ArrayLists) omdat idd die indirectie weer wat vertraagd (en 3 keer range checking is nog veel erger).

En Natuurlijk is een 'struct' beter voor compactheid (maar in Java heb je geen struct) maar als dat allemaal zo goed is waarom dan nog OO :) Maar ook al de functies en code voor C spul neemt plaats in waar dat dan weer wordt uitgespaard in OOP. OOP trager: of course, OOP beter: bijna altijd...

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
athlonkmf schreef op 18 April 2003 @ 20:07:
[...]
Een aparte klasse lijkt me mooi hierover, dan kan ik natuurlijk een hoop animaties invoegen. (animated gifs kan java niet aan trouwens)

Kijk, dat is weer een voorbeeld de lood van procedureel programmeren aan m'n schoenen.

Ik zal eerst denken aan een doorlopend stuk aan instructies.

coll.detect->paint explosionimg->set null-> repaint
zat dus gelijk de "verkeerde" kant op te denken :/
sorry ivm animated gifs :) ben er zelf nog niet aan toegekomen :) tja old habits die hard - or can't teach on old dog new tricks. Gelukkig ben jij net iets slimmer dan onze viervoeter :) ...

In een spelletje dat ie heb geschreven gebruik ik voor deze animaties (die er eigenlijk alleen maar zijn voor visual 'flair' ) een apart system die je tekent nadat de echte wereld is gedaan.

Wat tips: een particle heeft meestal: een animatie (ie een set van images, of een volgorde van kleuren), een positie (en/of velocity + vertraging) , en een levensduur. vooral dit laatste is erg leuk en handig.

Stel je 'dood' je enemy. dan maakt ie een nieuw 'particle' aan die je op dezelfde plaats + directie zet) dan verwijder je de enemy uit de wereld. Dan voor elke
frame ga je alle partciles af - je zegt dat ze zich moeten 'updaten' (ie mischien moet ie een nieuw tekeningetje laten zien na 1/5 sec) en als is zegt dat ie dood is (ie na een bepaalde duur) dan ruimt de globale klasse hem op door hem ook te verwijderen... (of het web zijn er honderdebn van die particle engines, die met heel simpele rules erg veel kunnen) heel leuk om mee te spelen (te leuk :)

  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

athlonkmf schreef op 18 April 2003 @ 17:34:
[...]

Maar ik heb toch het gevoel dat ik niet op de juiste manier de col. detect. aan het checken bent. Ten eerste bekijk ik idd een momentopnamen, ten tweede om ELKE keer dat alle shots en alle targets te gaan checken lijkt mij niet te goede (lees efficiente) methode.
Misschien dat jullie me een andere tip kan geven hierover?

[...]
Als de bewegingen/banen van de shots en enemyships te verspellen zijn dan kan je bij de creatie van een shot bepalen welk enemyship het eerst geraakt wordt wat je vervolgens bij het schip kan vast leggen.
Vervolgens hoef je bij de collision detectie voor een schip alleen te controleren wanneer dat schot het schip bereikt heeft (tellertje?).

Natuurlijk moet je bij het exploderen en het nieuw verschijnen van schepen controleren of de voorspelde hits nog kloppen.


De vraag is overigens of dit nog wel volgens het OO model is. Je gaat namelijk informatie van de shot (de hit) vast leggen bij het ship object.

[ Voor 21% gewijzigd door Buffy op 18-04-2003 23:29 ]

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik zal mijn post in CA hier ook eens neergooien, voor de volledigheid :)



Geen idee waarom ie hangt, dat kan ik zo snel even niet zien.
De plaats van je collision detection is in principe wel goed. OO gezien moet dat in het object waarmee je test, maar dat zuigt als je er met een gamedev oog naar kijkt :)
Overigens doe je het wel raar. Je gaat altijd maxEnemies en 15 shots af, maar misschien zijn er wel helemaal niet zoveel enemies of shots. Verder geef je puur de x en y coordinaten van een shot door, maar een Shot heeft ook een radius (dan kun je beter de hele Shot zelf doorgeven)

Nog een performance-issue: sqrt () is traag. Aangezien je de afstand niet per se hoeft te berekenen, maar puur alleen hoeft te vergelijken, kun je die hele sqrt achterwege laten.
Want als r > sqrt (x), dan r2 > x :)

Verder is je col.detection niet helemaal correct, aangezien je een momentopname controleert. Veel beter is te kijken naar de afgelegde afstand van het vorige moment tot nu helemaal te controleren, maar dat is wel wat ingewikkelder (hoewel het met 2 cirkels geen probleem moet vormen)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

hobbit_be schreef op 18 april 2003 @ 17:00:
yep :) sorry maar SQRT is niet zomaar een 'imul' of 'idiv' maar echt wel HEEL erug traag. op een 486 ging het op de 'FPU' zelfs zo traag dat je beter in pure Integer code je eigen Newton-Rapson kon toepassen. Net zoals Cos/Sin (nog steeds beter om in een LUT te steken) gelukkig is een mul nu toch triviaal (hoeveel keer ik nog
shr, shl heb getypt voor address berekening). Maar helaas is SQRT nog steeds een v/d traagste gevallen. Nu ja als het echt snel moet kunt je nog beter Fixed Point gebruiken (nog steeds) (voor simpel gevallen).
vroeger misschien, tegenwoordig niet meer. Heb net effe een benchmark gedaan, waarin ik de imul, fmul, fsqrt en fcos instructies vergeleek

code:
1
2
3
4
imul:  0.0838283
fmul:  0.0808385
fsqrt: 0.17993
fcos:  0.564944


Dus een sqrt heel erg traag noemen vind ik een beetje onzin. Ok, het is nog steeds trager, maar niet een factor 10 tot 20 wat het vroeger altijd was

.edit: processor info erbij zou wel handig zijn natuurlijk 8)7
Athlon XP 1400 MHz

[ Voor 5% gewijzigd door .oisyn op 19-04-2003 18:29 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
.oisyn schreef op 19 April 2003 @ 18:23:
[...]
vroeger misschien, tegenwoordig niet meer. Heb net effe een benchmark gedaan, waarin ik de imul, fmul, fsqrt en fcos instructies vergeleek
code:
1
2
3
4
imul:  0.0838283
fmul:  0.0808385
fsqrt: 0.17993
fcos:  0.564944


Dus een sqrt heel erg traag noemen vind ik een beetje onzin. Ok, het is nog steeds trager, maar niet een factor 10 tot 20 wat het vroeger altijd was
tja daar zit ik dan met me Celeron 400 he :) Nu nog Itanium 2 benchmarks en het is sneller om een SQRT(x*x)+SQRT(y*y) dan x+y :) :) (just kidding). Das inderdaad een phenomenaal verschil met mijn bakkie - heb je met een heel uiteenlopende reeks nummers gewerkt want die gasten bij intel zijn ook wel slim genoeg om heel veel cases erin te propen... Toch wel goed om zien - dat cos nog traag is dat is bijna niet te helpen.

Overigens kun je in bepaalde gevallen de afstand berekenen (de bijna- echte) zonder een sqrt (doe ik in Director/Flash Spul) en tamelijk nauwkeurig. (als je wil post ik hier wel de pseudo - maar das dan weer zo offtopic)

Die collision detection (ie zonder moment opname) = de minimum afstand tussen de tweelijnstukken die beschreven werden (ie oldpos -> newpos en de anders) als die kleiner is dan de grootste v/d twee...

  • kmf
  • Registratie: November 2000
  • Niet online
.oisyn schreef op 19 april 2003 @ 17:51:
Verder is je col.detection niet helemaal correct, aangezien je een momentopname controleert. Veel beter is te kijken naar de afgelegde afstand van het vorige moment tot nu helemaal te controleren, maar dat is wel wat ingewikkelder (hoewel het met 2 cirkels geen probleem moet vormen)
Dawns_sister schreef op 18 april 2003 @ 23:29:
[...]


Als de bewegingen/banen van de shots en enemyships te verspellen zijn dan kan je bij de creatie van een shot bepalen welk enemyship het eerst geraakt wordt wat je vervolgens bij het schip kan vast leggen.
Vervolgens hoef je bij de collision detectie voor een schip alleen te controleren wanneer dat schot het schip bereikt heeft (tellertje?).

Natuurlijk moet je bij het exploderen en het nieuw verschijnen van schepen controleren of de voorspelde hits nog kloppen.


De vraag is overigens of dit nog wel volgens het OO model is. Je gaat namelijk informatie van de shot (de hit) vast leggen bij het ship object.
hobbit_be schreef op 19 April 2003 @ 19:13:
[...]

Die collision detection (ie zonder moment opname) = de minimum afstand tussen de tweelijnstukken die beschreven werden (ie oldpos -> newpos en de anders) als die kleiner is dan de grootste v/d twee...
Ik denk dat jullie alledrie min of meer hetzelfde bedoelen.
Het is idd wel te doen, maar de moeilijkheidsfactor lijkt mij bij elk "verandering" te vergroten.

Als ik later een dubbelshot wilt invoeren (wat ik wel van plan bent) dan de "voorspelling" al flink onnauwkeuriger. Stel dat je een dubbele shot had met zelfde snelheid, alleen enkele pixels van elkaar verwijderd, volgens de voorspelling zullen ze allebei een bewegend target moeten raken, maar als de enemy van links naar rechts beweegt, zal de meest linkse shot de hit krijgen, terwijl de rechtse doorgaat. En waarschijnlijk dwars door een andere enemy jaagt die juist niet "geraakt" wordt.

Als de bewegingen van de enemies en/of jouw schip ingewikkelder worden, wordt het ook veel moeilijker om te voorspellen welk shot welk enemy raakt.

Ik vind de kans op fouten te groot en niet opwegen tegen de waarschijnlijke performancewinst.

==============

Ik heb daarom voorlopig nog steeds de Pietje-col-detect-methode aangehouden, aangezien de spel nog steeds zeer soepel werkt op dit moment.
Maar een andere vraag is gerezen, als ik de col. detection door de main-trhead laat controleren, betekent dit dat ik voor ELK object of een groep van deze in het spel moet gaan controleren. Dat betekent op dit moment een hoop for-loops, omdat ik verschillende groepen van objecten aanmaakt.
Is er een methode om in 1 keer alle soorten objecten te gaan controleren op collision?

One thing's certain: the iPad seriously increases toilet time.. tibber uitnodigingscode: bqufpqmp


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
athlonkmf schreef op 19 April 2003 @ 21:20:
Ik denk dat jullie alledrie min of meer hetzelfde bedoelen.
Het is idd wel te doen, maar de moeilijkheidsfactor lijkt mij bij elk "verandering" te vergroten.
Nee die blijft constant: per frame ga je kijken naar de uitgevoerde beweging vergeleken met de vorige.

Effe simpler uitleggen in een 1D wereld :)

code:
1
2
3
4
frame 1 [...A...........B.......]
(A beweegt naar Recht, B Links)                
frame 2 [........A...B..........]
frame 3 [.........B.A...........]


dus A en B nooit op dezelfde plaats(ie in de 'hit' omgeving) toch kunnen we weten
dat ze elkaar hebben geraakt:

code:
1
2
3
4
5
6
7
[...A...........B.......]
[........A...B..........]
[   [  A ]   [B ]      ]  // de binnester zijn de lijnstukjes die jij weet die ze hebben  
[.........B.A...........]
[        [   A]              //nu kun je dus zien dat ze elkaar overlappen maw ze  
         [B      ]              //hebben elkaar geraakt. Voor een simple spel 
                             //maakt het niet uit waar , maar dit is heel goed te bepalen


In 2D kun je bijvoorbeeld eerst beide Bounding Boxend van deze vectors bekijken
en als die al niet overlappen is er zeker geen hit geweest, if wel dan moet je
wat beter analyseren.

All collision doen dat gaat - in een van mijn eerste replys had ik gezegd dat je all
iobject die kunnen collisionen van 1 class afleiden - zo behouw je maar 1 dubbele
loop (ie vergelijk het volledige web). Met die boudnignbox truuk kun je al heel snel
collisions negeren (ie andere kant v/h scherm). Er zijn nog een hele hoop andere truken maar voor een simpel spel voldoet dit...

(voor mijn Video Object Tracker, komt daar enorm veel meer bij zien - maar zelfs deze truukjes gebruik ik nog)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
offtopic:
Ik begrijp nog steeds niet hoe hobbit_be's CachedPool werkt en dat kan ik niet hebben. Ik kan met Google zowel voor "cached pool" als "caching pool" niets zinnigs vinden. Zou ik er een nieuw topic over kunnen openen, aangezien het hier wel erg off-topic gaat, of zou iemand me op een verhelderend linkje kunnen wijzen?

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
here's the drill:
code:
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
template class<T, Size> CachedPool
{
    int[Size] mUsed
    int mUsedIndex
    int[Size] mFree
    int mFreeIndex
    T[Size] mData

    void init()
    {
        mFreeIndex = SIze-1;
        mUsedIndex =-1
        foreach()
        {
             mFree[each] = index++;
        }
    }

     void remove(int id)
     {
          mFree.add(id);  //1mov
          mUsed.remove(id); //replace last available with place... 1 mov
     }  
     
     void new()
     {
         mUsed.push(mFree.pop());
         return mData[mUsed.peek()];
     }

      void get(id)
      {
            return mData[id];
      } 

       int[] used()
       {
            return mUsed
       }    
}

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
hobbit_be schreef op 20 April 2003 @ 14:44:
here's the drill:
code:
1
<knip>
Ah, dank je! Leuk om eens een min-of-meer nieuwe datastructuur te zien. Maar wat is nu het nut van dit ding? Als ik het goed zie, heb je geen enkele garantie over de ordening van de elementen (anders dat de relatieve ordening van 'bestaande' elementen niet kan veranderen) en zit je nog steeds met het probleem van reallocatie (maar dat komt natuurlijk zelden voor als je de initiële grootte goed kiest).

Als ik het goed begrijp is deze datastructuur niet echt een Container, maar meer een eigen memory manager? Voor zover ik kan zien hebben new/remove methoden precies dezelfde eigenschappen als malloc/free of new/delete. Aangezien get(id) vrij zinloos is (aangezien je geen manier hebt om een zinnige id te bepalen, anders dan de id bij een zekere reference te kennen), biedt deze implementatie dezelfde garanties als (bijvoorbeeld) een Linked List. Het verschil in performance wordt daarbij vooral bepaald door de kwaliteit van de memory manager van het besturingssysteem. Wat mij betreft 'mist' deze klasse dus niet echt in Java, aangezien 'ie vanuit de programmeur gezien niets nieuws toevoegt. (In Java code zelf is 'ie ook niet te realiseren, bij gebrek aan object values of 'boxed' arrays.)

(Er zitten trouwens nog wel heel wat fouten in je voorbeeldcode, maar het idee is wel duidelijk.)

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Soultaker schreef op 21 April 2003 @ 12:04:
Ah, dank je! Leuk om eens een min-of-meer nieuwe datastructuur te zien. Maar wat is nu het nut van dit ding? Als ik het goed zie, heb je geen enkele garantie over de ordening van de elementen (anders dat de relatieve ordening van 'bestaande' elementen niet kan veranderen)
Idd - vandaar de 'term' POOL (ie unordered allocation). Maar zoals je zelf al aanhaalt blijft wel de orde van 'used' objects hetzelfde. Vooral in 3D toestanden
is dit zeer handig (ie use of indices vs pointer - voor polys etc). Dus vooral voor dingen te gebruiken waar het niet uitmaakt in welke volgorde ze komen wel dat ze gemakkelijk accesible
en zit je nog steeds met het probleem van reallocatie (maar dat komt natuurlijk zelden voor als je de initiële grootte goed kiest).
nou het probleem van reallocatie is er altijd behalve bij Linked - X affairs maar die hebben dan de overhead van new/delete. (en die heeft ook geen snelle random access)
Als ik het goed begrijp is deze datastructuur niet echt een Container, maar meer een eigen memory manager? Voor zover ik kan zien hebben new/remove methoden precies dezelfde eigenschappen als malloc/free of new/delete.
Nee niet echt - maar ook weer wel: een Pool is ook een mix - het geeft je standaard een aantal objects (x) waarvan ze niet allemaal hoeven gebruikt te worden maar ze bestaan wel altijd. Het nut van Pool's ga ik hier nu niet indiepen maar het is een heel vaak gebruikte 'Container' vanwege init-optimalisatie (Database, Games ! :)
Aangezien get(id) vrij zinloos is (aangezien je geen manier hebt om een zinnige id te bepalen, anders dan de id bij een zekere reference te kennen),
euh hoe zou je anders een object krijgen. Ik denk dat je niet begrijpt dat dit een Indexed container is: get(id) == [id] (waarvan niet alle values van id wel degelijk
gebruikt worden maar wel altijd geldig zijn)
biedt deze implementatie dezelfde garanties als (bijvoorbeeld) een Linked List. Het verschil in performance wordt daarbij vooral bepaald door de kwaliteit van de memory manager van het besturingssysteem.
Euh is een LL dan random access? - zoals je zelf aanhaalt is een goede memmanager (niet standaard) altijd aan te raden - alleen met deze structuur hoef je daar niet op te rekenen dus de compiler kan al niet verkeerd meer doen. Het grote verschil met LL is vooral snelheid (zelfs een goede mem-manager is nooit zo snel omdat hiet totaal NIET moeten worden alloced/released), zoals ik zei als je met 35000 particles werkt (stel dat deze volledige random worden gecreert delete heb je nooit issues)
Wat mij betreft 'mist' deze klasse dus niet echt in Java, aangezien 'ie vanuit de programmeur gezien niets nieuws toevoegt. (In Java code zelf is 'ie ook niet te realiseren, bij gebrek aan object values of 'boxed' arrays.)
Nou ik heb hem toch maar Java heeft wel een Pool dacht ik. Maar geen indexed Pool. Hij is perfect te realiseren in Java. (waarom zou ie niet te realiseren zijn?)
(Er zitten trouwens nog wel heel wat fouten in je voorbeeldcode, maar het idee is wel duidelijk.)
Twas gewoon om het idee duidelijk te maken - niet gelukt denk ik :)

Ik gebruik de strcut dus vooral in RealTime gevallen waar de data structures hetzelfde zijn maar heel vaak moeten worden delete/aangemaakt + steeds dezelfde index hebben en snel Iterable + random access zijn.

In feite is het een LL waardat de 'links' of volgorde in een LUT steken + dan nog pool eigenschappen.

Overigens heb ik nog wel een paar Collections die er niet in Java zitten (Linear IndexedHashMap , KeyKeyHashMap etc).

Het gebruik van indices (ie int ipv pointer) heeft wel een paar nadelen: ie no smart pointers (maar ook niet nodig want een pool gaat nooit out of scope).

Het gebruik van deze 'pool' heeft het mogelijk gemaakt om op mijn Dual 400 Celeron Realtime op 640x480x25Fps (32bit) Object tracking te doen. (Realtime Masking, Edge Detection, Edge Tracing (nieuwe techniek die supersnel is), Edge Comparison Cross Frames, Object Matching, Object Tracking, + Realtime OpenGL MC). Geen enkele andere conatiner (zeker het gebruik van dynamisch new/del bleek onmogelijk qua performance).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

athlonkmf schreef op 19 April 2003 @ 21:20:
Ik denk dat jullie alledrie min of meer hetzelfde bedoelen.
Het is idd wel te doen, maar de moeilijkheidsfactor lijkt mij bij elk "verandering" te vergroten.
voorspellen hoeft niet. Zoals hobbit_be al hierboven uitlegde kijk je nog steeds elke frame naar de afgelegde afstand, en doe je time-based collision detection op je objecten - de col.detection levert dus niet alleen 'true' of 'false' op, maar bijvoorbeeld een floating point waarde tussen 0 en 1, wat aangeeft op welk moment er gebotst wordt.

De bounding box methode van hobbit_be is in dit geval niet echt handig, omdat je toch met cirkels werkt, wat hele makkelijke vormen zijn om te detecteren.

Je weet dat als 2 cirkels elkaar snijden, de afstand tussen die 2 cirkels kleiner is dan de radius van de 2 cirkels bij elkaar opgeteld. Voor bewegende cirkels is hier simpelweg een 2e-graads formuletje voor te maken die je kunt oplossen met de welbekende ABC-formule (optimalisaties daargelaten). In plaats van 2 cirkels kun je ook een cirkel en een punt nemen, waarbij die ene cirkel een radius heeft van de 2 cirkels bij elkaar opgeteld. Dit levert hetzelfde antwoord op. Ook is het handig om die cirkel als middelpunt te beschouwen, en dan dat punt te laten bewegen ten opzichte van de cirkel (dus de 2 vectoren van de 2 cirkels bij elkaar opgeteld). Wat je nu overhoudt is een simpele lijn-cirkel intersectie

Voorbeeldje:
De cirkel in de oorsprong heeft een radius van r. Het punt staat op tijdstip t = 0 op positie (x, y), en op t = 1 (dx, dy) verder (dus op (x + dx, y + dy)

Verder weet je, met de stelling van Pythagoras, dat de afstand van het punt tot de oorsprong sqrt (x2 + y2) is. Maar hij beweegt met (t * dx, t * dy), dus dat wordt:

sqrt ((x + t*dx)2 + (y + t*dy)2)

Maar je wilt weten op welk moment het punt de cirkel raakt, dus:

r = sqrt ((x + t*dx)2 + (y + t*dy)2)

en dus

r2 = (x + t*dx)2 + (y + t*dy)2

Als je de t (de waarde die je wilt berekenen) buiten de haakjes haalt, kom je op:

r2 = (dx2 + dy2) * t2 + 2*(x*dx+y*dy)*t + x2 + y2

en dus

0 = (dx2 + dy2) * t2 + 2*(x*dx+y*dy)*t + x2 + y2 - r2

Dus voor de ABC-formule:

a = dx2 + dy2
b = 2*(x*dx+y*dy)
c = x2 + y2 - r2


En de ABC-formule zelf, voor de volledigheid: t = (-b +/- sqrt (b2 - 4*a*c)) / (2 * a)
Je hoeft hier alleen de minus-variant te gebruiken, aangezien je alleen geinteresseerd bent in de kleinste positieve waarde


Dit levert een waarde t op. Als de wortel of de deling niet mogelijk is, dus als
b2 - 4*a*c < 0 of als 2 * a = 0, is er geen oplossing, en botsen ze dus niet

Als t < 0 of t >= 1 valt de botsing niet binnen de huidige frame, en kun je die dus ook negeren.

Als 0 <= t < 1 is er dus wel een botsing, en kun je beide objecten met v * t vooruit bewegen (waarbij v staat voor de richtingsvector voor het object wat je beweegt). Maar dat hoef je nu waarschijnlijk niet eens te doen omdat je toch alleen maar hoeft te controleren of er een botsing is, waarop een explosie volgt. Er is verder geen response systeem oid.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
zeg oisyn - nu vond ik dat zo mooi (te mooi) dus ben effe gaan checken. ik vermoed dat je equations idd wel weten wanner ze gehit zijn maar je 't' klopt toch niet: dat truukje om beide circles tot 1 circle tot 1 punt krijgt dit als gevolg:

http://www.onnos.com/circles.html

je moet dus somehow het geval waar 2 circles slechts 1 punt gemeen hebben (2 cases, 0 , of infinite) en daarvan de eerste... Vraag me niet welke equations :)

edit: (and tha solution)
http://pages.cpsc.ucalgar...cles/vandenhuevel_pfv.pdf

[ Voor 16% gewijzigd door hobbit_be op 22-04-2003 02:29 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

ik snap niet helemaal wat je bedoelt. Het voorbeeld waarmee je kwam klopt idd niet, die doet een lijn-cirkel intersectie, terwijl ik een bewegende punt-cirkel intersectie doe. Het verschil is dat het moment van botsing dus niet is zodra de grote cirkel de lijn raakt, maar zodra het punt de cirkel raakt (waarbij de cirkel dus stil staat en het punt beweegt). Dat is een wezenlijk verschil

Ik heb dit algo al meerdere keren geimplementeerd, en het blijkt prima te werken :)

Ik zal eens kijken of ik hier op mijn werkplek animated gifs oid eruit kan toveren
.edit: gelukt :)

Afbeeldingslocatie: http://www.xs4all.nl/~oisyn/fotos/colission.gif

[ Voor 26% gewijzigd door .oisyn op 22-04-2003 12:10 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
oisyn: hmm als je effe merkt in jouw geval : de circle beweegt altijd recht naar de andere (ie op 1 lijn: maar dat is niet altijd zo (zie my example). Aangezien mijn swf idd onduidelijk was:

http://www.onnos.com/circles2.html

jouw voorbeeld is het simpelste geval maar zoals de pdf al aangeeft klopt het toch niet...

zie ook:

http://www.flipcode.com/tpractice/issue01.shtml

(die pdf van vandenheuvel staat ook op gamasutra).

ie ik denk dat jouw functie verondersteld dat de relatieve afstand een lineare fucntie is maar dat is het niet...

edit4: :)

ik snap em nu ook: je houd geen rekening mee van de hoek tussen te richtings vectors (ie die hoeft niet recht op elkaar zijn) zodoende veranderd de hoek telkens voor de korste: (ie hit) afstand die dus per t, anders word en zodus ook de hit-afstand (dus niet linear) mind you de afwijking lijkt me niet enorm maar ik dat we beide gewoon willen weten hoe het nou zit :)

[ Voor 28% gewijzigd door hobbit_be op 22-04-2003 12:52 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat jij laat zien in die voorbeelden is het raakpunt, wat ik laat zien is de positie van het bewegende object op het moment dat ie de andere raakt. Daar zit een wezenlijk verschil in. Het raakpunt kun je dan alsnog berekenen door te interpoleren tussen het eindpunt van object A en het eindpunt van object B, aan de hand van de verhoudingen van de radii van de cirkels.

Wiskunding kun je het ook bewijzen, ga mijn formules van een paar posts hierboven maar eens omzetten naar 2 cirkels ipv een punt en een cirkel. Door dingen weg te strepen kom je uiteindelijk op precies dezelfde berekening.
Die artikelen waarmee jij aankomt zijn allemaal hele ingewikkelde verklaringen op een heel simpel probleem. Wiskundig is mijn berekening gewoon correct. En je komt met allemaal documentjes, maar kun je eens passages quoten waaruit blijkt dat mijn methode niet klopt?

Wiskundige uitleg:

testen of een punt op de rand van een cirkel ligt:
#1: |Op - Oc| = r

waarbij Op de locatie van het punt is, Oc de locatie van de cirkel, en r de straal van de cirkel

Testen of 2 cirkels elkaar raken:
#2: |O1 - O2| = r1 + r2
O is weer de positie van cirkel 1 en 2, en r weer de straal van cirkel 1 en 2

Je ziet dat #1 en #2 precies dezelfde berekeningen zijn. Als je de ene cirkel een punt laat zijn, en de andere een cirkel van straal r1 + r2, kom je weer op #1

Daar kun je dus ook beweging aan toevoegen, de positie van een cirkel op moment t wordt:
#3: O(t) = Os + V * t
Waarbij Os het startpunt van de cirkel is, en V de richtingsvector

Dan herschrijven we #2 met de formule van #3:
#4: |O1(t) - O2(t)| = r1 + r2

Mijn berekening een paar posts terug, voor de volledigheid
#5: r = sqrt ((x + t*dx)2 + (y + t*dy)2)

Goed, ik stelde de tweede cirkel als het nulpunt met radius r1 + r2, en de eerste cirkel als punt tov cirkel 1. Ook stond de tweede cirkel stil, en beweegde de eerste cirkel tov cirkel 1.

Dus de eigenschappen van cirkel 1 worden dus:
O'1 = O1 - O2
V'1 = V1 - V2
r'1 = 0


En die van cirkel 2:
O'2 = (0, 0)
V'2 = (0, 0)
r'2 = r1 + r2


In #5 maakte ik gebruik van r, x, y, dx en dy, wat natuurlijk de positie en richting van cirkel 1 voorstelde:
r = r'2 = r1 + r2
x = O'1x
y = O'1y
dx = V'1x
dy = V'1y


dus:
#6: O'1(t) = (x + t*dx, y + t*dy)
en
#7: O'2(t) = (0, 0)

Gebruiken we dat in #4 dan krijgen we

#8: |(x + t*dx, y + t*dy)| = r

even de || wegwerken:

#9: sqrt ((x + t*dx)2 + (y + t*dy)2) = r

Heej, da's hetzelfde als #5, wat toevallig :D


Niet lullig bedoeld, je komt met allerlei leuke artikeltjes, maar mijn wiskunde is naar mijn weten gewoon goed en bewezen. Kom jij maar eens met uitleg waarom het niet zou kloppen (onder voorbehoud van typefouten)

.edit: damnit waarom kun je nou weer geen geneste [sub] tags :{

.edit2: ah ok, je snapt het al :D
Ik snap sowieso niet waarom je hoek-berekeningen zou nemen... En de hoek waaronder ze elkaar raken is ook simpel uit te rekenen (simpelweg de hoek van O'1)

[ Voor 8% gewijzigd door .oisyn op 22-04-2003 13:40 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
.oisyn schreef op 22 April 2003 @ 13:10:
Wat jij laat zien in die voorbeelden is het raakpunt, wat ik laat zien is de positie van het bewegende object op het moment dat ie de andere raakt. Daar zit een wezenlijk verschil in. Het raakpunt kun je dan alsnog berekenen door te interpoleren tussen het eindpunt van object A en het eindpunt van object B, aan de hand van de verhoudingen van de radii van de cirkels.
wow weer zo'n mega antwoord :) je hebt gelijk dat ik het raakpunt laat zien: waarom: om het tijdstip te weten. maakt mij echt niet uit waar ze elkaar raken alleen dat ze elkaar raken op een 't'. Nu blijkt dat die t dus verschilt in de twee gevallen: ie en dat vond ik dus best wel gek want normaal zou je die t dan gebruiken op de positie van beide te vinden, maar aangezien dat t1 != t2 kan dus klein balletje niet op dezelfde plek zijn (in de buurt, maar niet op dezelfde plaats) nu bedenk ik dat je t dan nog moet normalisen want: R1+R2=R dus R1/R =en R2/R dus die 't' is voor beide anders - ik ben dus nog eens gaan pluizen op verschillende sites en daarmee ben ik nu aan't verwerken (maths is weer een heel tijdje geleden). Mijn gevoel (ben daar goed in ;)) is dat jouw truukje alleen werkt als beide ballen recht op elkaar afkomen en niet als ze 'afschampen' , maar ik ga nu dat eens checken... mocht je gelijk hebben dan alvast mijn biggest excuses maar ik vind het gek dat ik jouw formules nergens tegenkom (wel deeltjes ervan) op geen enkele van alle oplossingen. If so zou ik je oplossing wel online zetten om andere zotten zoals ik (die eigenlijk moeten werken :)) tegen te houden :). Hopelijk neem je totaal geen offence (ben nogal koppig) want ik doe dat ook helemaal niet. Ik twijfel niet aan je mathematisch kunnen (veel beter dan die van mij ;) ) maar misschien wel je inschatting (ie de wiskundige representation v/h probleem)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

hobbit_be schreef op 22 April 2003 @ 15:12:
[...]

wow weer zo'n mega antwoord :) je hebt gelijk dat ik het raakpunt laat zien: waarom: om het tijdstip te weten. maakt mij echt niet uit waar ze elkaar raken alleen dat ze elkaar raken op een 't'. Nu blijkt dat die t dus verschilt in de twee gevallen: ie en dat vond ik dus best wel gek want normaal zou je die t dan gebruiken op de positie van beide te vinden, maar aangezien dat t1 != t2 kan dus klein balletje niet op dezelfde plek zijn (in de buurt, maar niet op dezelfde plaats)
Je voorbeeld klopt niet, dat is het enige wat ik ervan kan zeggen. Kloppen de beide snelheden wel? En de startposities? En is de straal van de grotere cirkel ook daadwerkelijk de straal van de 2 kleinere opgeteld?
nu bedenk ik dat je t dan nog moet normalisen want: R1+R2=R dus R1/R =en R2/R dus die 't' is voor beide anders - ik ben dus nog eens gaan pluizen op verschillende sites en daarmee ben ik nu aan't verwerken (maths is weer een heel tijdje geleden).
Je hoeft niets met t te doen, dit hoort gewoon te kloppen. Wat je namelijk berekent is het moment waarop de afstand tussen de 2 middelpunten van de cirkels gelijk is aan r1 + r2. Wat r1 en r2 afzonderlijk zijn doet er niet toe, als ze bij elkaar opgeteld maar op hetzelfde uitkomen. Je kunt dus net zo goed 2 cirkels met straal 1 en 5 nemen als 2 cirkels met straal 3 en 3, de afstand ertussen blijft altijd 6
Mijn gevoel (ben daar goed in ;))
blijkbaar niet ;)
is dat jouw truukje alleen werkt als beide ballen recht op elkaar afkomen en niet als ze 'afschampen' , maar ik ga nu dat eens checken...
Nee, mijn "trucje" zoals jij het noemt, wat gewoon een regelrechte wiskundige benadering is van het probleem, klopt in alle gevallen.
mocht je gelijk hebben dan alvast mijn biggest excuses maar ik vind het gek dat ik jouw formules nergens tegenkom (wel deeltjes ervan) op geen enkele van alle oplossingen.
Op dat flipcode artikel hadden ze iets wat er op leek. Ik heb mijn berekening ook verder niet uit een artikel of boek oid, ik heb gewoon mijn gezond verstand gebruikt. In de post waarin ik ze voor het eerst noemde in deze thread heb ik ze ook uit mijn hoofd opnieuw opgezet, ik zat namelijk bij mijn ouders en had dus mijn aantekeningen er verder niet bij. En verder is het ook heel logisch, wat blijkt uit mijn vorige post.
If so zou ik je oplossing wel online zetten om andere zotten zoals ik (die eigenlijk moeten werken :)) tegen te houden :).
mja daar vind ik 'm te simpel voor :)
Hopelijk neem je totaal geen offence (ben nogal koppig) want ik doe dat ook helemaal niet.
oh nee ik ben niet beledigd oid, maar ik vind het wel vervelend dat als je met een harde wiskundige uitleg komt iemand er toch nog tegenin gaat zonder je wiskundige stelling te ontkrachten ;)
Ik twijfel niet aan je mathematisch kunnen (veel beter dan die van mij ;) ) maar misschien wel je inschatting (ie de wiskundige representation v/h probleem)
Daar zit je dus fout. Gooi eens alles weg wat je weet, behalve de berekening van de afstand tussen 2 punten. Combineer dat met dit probleem hier en probeer een formule te vormen. Je zult zien dat je op hetzelfde uitkomt als ik (want het is echt niets anders dan het bepalen van de afstand tussen 2 punten op een bepaald tijdstip)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
.oisyn schreef op 22 April 2003 @ 15:31:
Je voorbeeld klopt niet, dat is het enige wat ik ervan kan zeggen. Kloppen de beide snelheden wel? En de startposities? En is de straal van de grotere cirkel ook daadwerkelijk de straal van de 2 kleinere opgeteld?
M'n voorbeeld klopt IDD niet.

[icoontje hier met een enorme muur en ventje dat ertegen klopt]
[nog een icoontje dat in de grond zakt van pure shame]
[icoontje dat doet alsof ie totaal niets weet]

Je raad het nooit: op een of andere manier deed ik men motion tween verkeerd.
de sizes waren wel juist maar die aan de rechter kant bewoog dus sneller...

DOH!!!

Gek genoeg zag ik het pas toen ik al die wiskunde had gedaan (i h8 maths :) ) en nog effe nageteken waardat de ene in de origin ligt. En snapte ik er geen bal meer van. Dus effe jouw tip nagekeken of mijn simulatie (nu weet je meteen dat ik meer 'fysicus' geneigd ben :) ) wel klopte en dan merkte dat ie op de laatste plek ineens een pak terugsprong


> mja daar vind ik 'm te simpel voor :)

toch maar doen - :)


>oh nee ik ben niet beledigd oid, maar ik vind het wel vervelend dat als je met een harde wiskundige uitleg komt iemand er toch nog tegenin gaat zonder je wiskundige stelling te ontkrachten ;)

Hopelijk heb ik niet teveel van je tijd verspild.

Tja wiskunde - ik heb een hoop vrienden die altijd alles met wiskunde proberen te bewijzen en dan maken ze altijd fouten bij hun opstelling. Zal dus nooit wiskundige antwoorden allemaal over 1 kam trekken :).

>Daar zit je dus fout.

Idd

ah daar zijn ze:

_/-\o_ |:( 8)7 :X

Alsnog mijn 'sincerest' apologies...

(not my greatest moment ;) )

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

verspillen van mijn tijd? nee, ik heb genoten van dit draadje (hoewel mijn baas daar misschien anders over denkt) :Y)
Ben blij dat we het met elkaar eens zijn ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
.oisyn schreef op 22 April 2003 @ 16:13:
verspillen van mijn tijd? nee, ik heb genoten van dit draadje (hoewel mijn baas daar misschien anders over denkt) :Y)
Ben blij dat we het met elkaar eens zijn ;)
Toch nog echt mijn grootste excuses - vooral als je werk erbij inschiet (maar als je een beetje bent zoals mij (behalve dan 2^64 keer beter in maths), dan zijn er priorities ;) ). De code is in ieder geval al c/p naar mijn' pseudo code en als je het niet published (te simple, my ass :) ) kom dat er een van de weken met een mooi flash filmpje op mijn site (met volledige credits of course).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja ik loop stage bij engine software (een nederlands gamedev bedrijf), dus dit heeft wel enigzins iets mee te maken :Y)

Doe ermee wat je wilt. Credits zijn totaal niet nodig, maar wel tof als je ze erbij zet :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
offtopic:
[quote].oisyn schreef op 22 April 2003 @ 16:54:
Mja ik loop stage bij engine software (een nederlands gamedev bedrijf), dus dit heeft wel enigzins iets mee te maken :Y)
[/quote]
gelukzakje ! proggen voor 'portables' (en weer terug naar basics) leuke stage! wat doe je daar specifiek?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mijn officiele opdracht is het porten van een C++ gaming library die hier ontwikkeld is naar java voor gebruik op mobiele telefoons

Verder klus ik nog wat onofficieel bij met een project dat ze hier hebben lopen waar ik verder niet op in wil/kan/mag gaan

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
oh voor J2ME ? wel 'leuk' of niet? C++ -> Java niet altijd evident... maar dat je ervoor betaald word (?) is wel errugg leuk :) .. Begrijp best dat NDA gedoe hoor :)...

Ik ga maar eens werken - twas niet echt productief vandaag :)
Pagina: 1