GustavXIII
Jr. Member   Posts: 57
|
 |
«
on:
2012-01-31 16:16:34 » |
|
Hey! So how could I do it that my tank shoot bullets in a straight line?? Is the bullet an object??
I want that the player could shoot endless bullets while moving and then it would be hundreds objects... I will try it but you can tell me how you did it if you want ^^"
|
|
|
|
|
aazimon
Full Member   Posts: 208 Medals: 5
|
 |
«
Reply #1 on:
2012-01-31 16:38:54 » |
|
Yes the bullet would be an object. You need to keep track of the bullet's location. I would just use a base sprite class (same as your player).
|
|
|
|
|
tw0v
JGO n00b  Posts: 14
|
 |
«
Reply #2 on:
2012-01-31 16:54:15 » |
|
Once the bullet object is destroyed or reaches the boundaries of the program. Set it to null and ensure you don't use it again. The JVM will garbage collect it.
|
Programming for better games.
|
|
|
Games published by our own members! Go get 'em!
|
|
UprightPath
Full Member   Posts: 214 Medals: 9
|
 |
«
Reply #3 on:
2012-01-31 16:54:55 » |
|
Hmm, my suggestion would be to think about how you would do a single bullet first. Then, from there move on to how you would extend (Not talking about class inheritance) that to cover multiple bullets.
First, you need to think about how you want the bullets to move. You said they will be moving in straight lines and since you can 'fire while moving' that the game will be at least somewhat real-time, and as such the bullets will move with the game's 'tick' instead of instant transition between where it's fired and where it impacts.
What this means is that you'll have to keep track of the bullet's current position and it's change in position.
Start by figuring out how you would do that and you're a good distance into figuring out how you'll do it for multiple bullets.
Some things you might want to think about when you're making these decisions: 1) That you will probably want to put some limit on the size of your battle field in a 'If the bullet moves outside of the area, it's no longer movement is no longer calculated. 2) That the bullet impact computation should be something of a 'next' step after you've got the bullet moving. If you're new to programming, don't bite off more than you can chew by attempting both in your first program. 3) While it might seem like you should do this as a drawing/animation outputting the bullet's coordinates will work better for testing than that, since before you attempt to do this, you should be able to at least calculate the location of the bullet after each tick on your own.
|
I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
|
|
|
ReBirth
JGO Wizard     Posts: 1279 Medals: 19
|
 |
«
Reply #4 on:
2012-01-31 18:54:40 » |
|
Once the bullet object is destroyed or reaches the boundaries of the program. Set it to null and ensure you don't use it again. The JVM will garbage collect it.
Seems not good to rely on GC. Remove it manually.
|
Follow me, your mastah, on TWITTAH!
|
|
|
sproingie
JGO Strike Force    Posts: 899 Medals: 55
|
 |
«
Reply #5 on:
2012-01-31 19:01:26 » |
|
Seems not good to rely on GC. Remove it manually.
How do you propose to do that?
|
|
|
|
|
ReBirth
JGO Wizard     Posts: 1279 Medals: 19
|
 |
«
Reply #6 on:
2012-01-31 19:09:16 » |
|
Seems not good to rely on GC. Remove it manually.
How do you propose to do that? LoL my bad. I meant when you use for example List to store all entities, I'll remove it rather set it null. With null object in my main List of entities, I have to check isNull every update and I don't want.
|
Follow me, your mastah, on TWITTAH!
|
|
|
sproingie
JGO Strike Force    Posts: 899 Medals: 55
|
 |
«
Reply #7 on:
2012-01-31 23:39:53 » |
|
I think the idea is that you null them then sweep the list into a new collection rather than incur the overhead of removing entities one at a time. They're going to get gc'd either way, the question is how much unnecessary bookkeeping you're doing on the collection.
|
|
|
|
|
ReBirth
JGO Wizard     Posts: 1279 Medals: 19
|
 |
«
Reply #8 on:
2012-02-01 19:19:03 » |
|
So I'm doing this wrong all time! D:
|
Follow me, your mastah, on TWITTAH!
|
|
|
UprightPath
Full Member   Posts: 214 Medals: 9
|
 |
«
Reply #9 on:
2012-02-01 19:24:18 » |
|
Hmm, instead of nulling them, then sweeping the other into a list, what about just using two lists (Linked Lists of some sort, IE- Removing the first element is relatively low overhead wise). Every update, you remove the first element, do your computations on it. If it's still a valid bullet, add it to the second list otherwise release it. Repeat until the first list is empty then swap them.
I'm not sure whether this will make good use of the GC (That mystical thing), but it seems better to me that doing a double-pass of the list of projectiles each time.
|
I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
|
|
|
Games published by our own members! Go get 'em!
|
|
theagentd
JGO Wizard     Posts: 1392 Medals: 88
|
 |
«
Reply #10 on:
2012-02-02 03:08:39 » |
|
LinkedLists are slow as hell because they create an inner Entry object to keep references to the previous and next object. This is slow and causes lots of garbage collection if you remove lots of objects every frame.
|
There is no god.
|
|
|
ReBirth
JGO Wizard     Posts: 1279 Medals: 19
|
 |
«
Reply #11 on:
2012-02-02 21:57:37 » |
|
I use ArrayList 
|
Follow me, your mastah, on TWITTAH!
|
|
|
UprightPath
Full Member   Posts: 214 Medals: 9
|
 |
«
Reply #12 on:
2012-02-02 22:02:39 » |
|
Hmm, I guess it would depend on the implementation. If you made a bare-bones Linked List the removal/addition could probably be faster than that of the ArrayList. I would need to actually look at the ArrayList implementation, but if it does any sort of shifting operations to keep the array from having holes, then the Linked List would probably be faster.
Of course, it would depend on how many projectiles would be on the screen at once. There would be a point where nothing would be particularly efficient for a given form of efficiency.
|
I am filled with despair... About how far people think about ideas they propose, about the state of my teams in classes when people do not understand what an assumption is...
|
|
|
StumpyStrust
Full Member   Posts: 103 Medals: 1
|
 |
«
Reply #13 on:
2012-02-03 05:01:14 » |
|
Why not use queues? Sounds more like a queue when you say remove the first and if its valid add to then end. Pop, update, if alive, add to the end of the queue. You may not be able to get a specific object that is in the middle of the queue but most of the time I never want to do that.
Also, from my experience, running through arrays/collections that are about 1-5k in size is really not that expensive. Its the updating that will slow you down. Heck I really don't think 25-50k is that massive. Now if you have many arrays that are all large and all need to be updated, sure it can get cumbersome but still. Anyways sorry for getting off topic.
The easiest way would be to use an object that has say an x and y value for the location and updating and a sprite/image that you will draw on the screen. You can store it in an arraylist as its really easy to use. Then when its suppose to die just do remove(); Not most efficient but worry about making things faster when you have something to make faster.
You may also want some sort of collision method to see if its hitting a bad guy or if its off the screen. Maybe if your getting more complex give it some sort of life that you subtract from every update and when it reaches 0 remove it. This way you wont worry about it going off screen as much and maybe you can make bullets not go on forever but what fun would that be.
|
|
|
|
|
GustavXIII
Jr. Member   Posts: 57
|
 |
«
Reply #14 on:
2012-02-04 04:03:23 » |
|
Ok I did it thanks! If the player now keep pushing SPACE he shoots a straight beam of sprites xD" I have to make a time interlay or something like that.
|
|
|
|
|
MunchGamer
JGO n00b  Posts: 22
|
 |
«
Reply #15 on:
2012-02-05 01:48:53 » |
|
Here is some code for guns that shoot I worked up in the last couple of days: 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
| public abstract class RangedWeapon extends Weapon { protected double maxRange; protected int clipSize; protected int clip; protected double projectileVelocity; protected double coolDown; protected double heatUp; protected double reloadtime; protected double reload; protected double direction; protected HashMap<Attack, ArrayList<Sprite>> hits; public RangedWeapon(Sprite owner){ super(owner); hits = new HashMap<Attack, ArrayList<Sprite>>(); this.clip = 0; }
public double getProjectileVelocity(){ return projectileVelocity; } @Override public void use(double mouseX, double mouseY) { if(!(atkTime < speed) && clip != 0){ atkTime = 0; direction = Math.atan2(mouseX - getOwner().getAX(), mouseY - getOwner().getAY()); attack(); clip -= 1; t.threaten(getOwner().getWorld(), 0); accuracyModifier += (accuracy/2)/heatUp; if(accuracyModifier > accuracy/2){ accuracyModifier = accuracy/2; } } else if(clip == 0 && !(reload < reloadtime)){ getOwner().requestReload(this); }
} public void attack(){ attacks.add(new RangedAttack(getOwner().getAX(), getOwner().getAY(), this, direction + (Math.random()*2 -1)*(accuracy/2 + accuracyModifier + getOwner().getMoveAccuPenalty()*accuracy/2))); } @Override public void tick(double d){ if(reload < reloadtime){ reload += d; if(reload >= reloadtime){ clip = clipSize; } } if(accuracyModifier > 0){ accuracyModifier -= (accuracy/2)/coolDown*d; } else { accuracyModifier = 0; } if(atkTime < speed){ atkTime += d; } for(Attack a : attacks){ ((RangedAttack) a).tick(d); } for(Attack a : attacks){ CollisionReport cr = getOwner().getWorld().getCollisionReportForAttack(a); if(!hits.containsKey(a)){ hits.put(a, new ArrayList<Sprite>()); } for(Sprite s : cr.getCollidees()){ if(!hits.get(a).contains(s)){ hits.get(a).add(s); s.receiveDamage(damage); s.receiveKnockBack(knockback, a.getX1(), a.getY1()); } } } }
public void removeAttack(RangedAttack a) { hits.remove(a); attacks.remove(a); } public void setReload(){ reload = 0; } @Override public void reload(){ getOwner().requestReload(this); } public Item equip(){ if(reload < reloadtime){ reload = 0; } return this; } } |
RangedAttacks essentially hold 2 points (origin and vector) and use Line2d.intersects(Rect2d) to test for collision with enemy hit boxes. Hope this helps you!
|
|
|
|
|
elamre
Jr. Member   Posts: 79 Medals: 14
hitar!
|
 |
«
Reply #16 on:
2012-02-06 02:26:23 » |
|
Thats a lot of unnececary work you're doing there MunchGamer! Also instead of using ArrayLists, use lists! they are much easier to use once they are implemented once youve set them up. also, what does this line of code do? 1
| t.threaten(getOwner().getWorld(), 0); |
Ive never seen it before. threaten
|
|
|
|
MunchGamer
JGO n00b  Posts: 22
|
 |
«
Reply #17 on:
2012-02-06 11:39:20 » |
|
Thats a lot of unnececary work you're doing there MunchGamer! Also instead of using ArrayLists, use lists! they are much easier to use once they are implemented once youve set them up. also, what does this line of code do? 1
| t.threaten(getOwner().getWorld(), 0); |
Ive never seen it before. threaten That's a part of the engine I'm making which sends threats to the world, ie when you fire a gun, the "sound" of you firing alerts nearby enemies to your position.
|
|
|
|
|
elamre
Jr. Member   Posts: 79 Medals: 14
hitar!
|
 |
«
Reply #18 on:
2012-02-06 12:03:12 » |
|
explains all. Thanks for clearing it up for me!
|
|
|
|
WildChild88
JGO n00b  Posts: 2
|
 |
«
Reply #19 on:
2012-02-10 08:25:49 » |
|
Just a quick question on this topic... when I am using bullets (or missiles/bombs or any similar object), I have an ArrayList and I add the object to the arraylist (and then in update/collision checks I just go through the ArrayList)
Once a bullet/missile/projectile hits something or goes out of bounds, I have been removing it from the ArrayList... only recently I have wondered, is this enough for the GC to collect it, as it is no longer referenced to? Or should I be manually setting the item to null before removing it?
Thanks B
|
|
|
|
|
evilfrenchguy
Jr. Member   Posts: 80 Medals: 3
|
 |
«
Reply #20 on:
2012-02-10 08:53:44 » |
|
It depends. In my experience, it is probably best to set it to null just to be certain.
|
|
|
|
|
ReBirth
JGO Wizard     Posts: 1279 Medals: 19
|
 |
«
Reply #21 on:
2012-02-10 21:52:41 » |
|
Or add it to secondary ArrayList and use removeAll(). Bit slow but works fine.
|
Follow me, your mastah, on TWITTAH!
|
|
|
GustavXIII
Jr. Member   Posts: 57
|
 |
«
Reply #22 on:
2012-02-15 07:07:09 » |
|
EDIT: Problem solved, I've done it without Rects...Hey! The player can shoot now projectiles and they will be drawn correctly. Now I create for every bullet a rectangle for collision with the enemy. But somehow for 1 bullet there will be 60 Rectangles created?!?! I checked the for loop and it loop the corect time(how many bullets have been created) I make a bullet like this: 1
| projectile = new Projectile(player.getX() + 55, player.getY() + 22); |
I created a ArrayList 1 2 3
| ArrayList <Projectile> bullets = new ArrayList<Projectile>(); Rectangle[] projectileRect = new Rectangle[1000]; ArrayList <Rectangle> shootingCollision = new ArrayList<Rectangle>(); |
So when the player shoot I add the bullet the Container: 1
| bullets.add(projectile); |
This is fine, but now I have to set every RectangleBullet new in each loop so in the Update method Id make: 1 2 3 4 5 6 7 8 9 10 11 12
| for(int z=0 ; z<bullets.size(); z++){ projectileRect[z].setX(bullets.get(z).x); projectileRect[z].setY(bullets.get(z).y); projectileRect[z].setWidth(12); projectileRect[z].setHeight(12); shootingCollision.add(projectileRect[z]); System.out.println("Looped: " +z); } |
shootingCollision.add(projectileRect[z]); Here it adds like 60 Rectangles?!?! But why? It only go throught the Loop as how many bullets there are. If I shoot 1 Bullet there should be only one Rectangle.
|
|
|
|
|
StumpyStrust
Full Member   Posts: 103 Medals: 1
|
 |
«
Reply #23 on:
2012-02-15 19:57:54 » |
|
Collision detection. Vector3f has x,y,z values the z is not used. 1 2 3 4 5 6 7 8 9 10 11 12
| public boolean collision( Vector3f other, double dist ) { if(this.loc.dist(other) > dist ) return false; else return true; }
public double dist( Vector3f other ) { return Math.sqrt(Math.pow(other.x - this.x, 2) + Math.pow(other.y - this.y, 2)); } |
The Vector3f is just an object with an x,y,z coordinates. In this case the z is not used. The dist( Vector3f other ) finds the distance between the center of one location and the center of another. You can then add the size (image length/width) to the collision method to get the collision without overlapping images. It is not perfect but it works well for me. The rect.intersects stuff is more accurate but also more cumbersome to use for me. It will help you to google the distance formula.
|
|
|
|
|
Roquen
JGO Strike Force    Posts: 827 Medals: 25
|
 |
«
Reply #24 on:
2012-02-16 07:52:07 » |
|
Note: It's somewhat undesirable to call pow for small integer exponents. Likewise the sqrt in this instance is not needed since: if a>b, then a2 > b2.
|
|
|
|
|
GustavXIII
Jr. Member   Posts: 57
|
 |
«
Reply #25 on:
2012-02-16 08:03:36 » |
|
Collision detection. Vector3f has x,y,z values the z is not used.
Ive done it this way: 1 2 3 4 5 6 7 8 9 10 11 12
| for(int x=0;x<bullets.size();x++) { for(int z=0;z<enemyContainer.size();z++) { if(bullets.get(x).x > enemyContainer.get(z).x && bullets.get(x).x < enemyContainer.get(z).x + 64 && bullets.get(x).y > enemyContainer.get(z).y && bullets.get(x).y < enemyContainer.get(z).y + 32 ) { enemyContainer.get(z).hp=enemyContainer.get(z).hp-1; } } } |
It work but do you think were will be problems with more enemys?
|
|
|
|
|
Blackout
JGO n00b  Posts: 10
|
 |
«
Reply #26 on:
2012-02-16 17:56:00 » |
|
I've actually made a game that has bullets and enemies. Try it out and tell me if this is something that you'd want to see the source code for, because I have no hesitations to post the source code to help. http://www.mediafire.com/?k86lp3phgp853ey
|
|
|
|
|
evilfrenchguy
Jr. Member   Posts: 80 Medals: 3
|
 |
«
Reply #27 on:
2012-02-17 12:21:57 » |
|
The way I learned is with interfaces. Basically you have an interface called ShotListener that has one method. 1 2 3
| public interface ShotListener { public boolean shotPerformed(ShotEvent event); } |
ShotEvent takes a Bullet when it is made. 1 2 3 4 5 6 7 8 9 10
| public class ShotEvent { private Bullet bullet;
public ShotEvent(Bullet bullet) { this.bullet = bullet; }
public int getX() { return bullet.getX(); } public int getY() { return bullet.getY(); } } |
Then, have like 5 bullets in Player that you recycle, and give Bullet an ArrayList of ShotListeners and an addShotListener(ShotListener listener) method that adds it to the array list. Player and the enemy tanks should implement ShotListener and be added with the method. Now, every update() for Bullet it calls shotPerformed for everything in the list. There is probably a much more organized way to do it, but that's what I do...
|
|
|
|
|
GustavXIII
Jr. Member   Posts: 57
|
 |
«
Reply #28 on:
2012-02-22 12:27:15 » |
|
I've actually made a game that has bullets and enemies. Try it out and tell me if this is something that you'd want to see the source code for, because I have no hesitations to post the source code to help. http://www.mediafire.com/?k86lp3phgp853eyHow do you handled the explosion animation after the enemy died? If the enemy died did you active a switch for the animation?
|
|
|
|
|
ra4king
JGO Kernel      Posts: 3160 Medals: 196
I'm the King!
|
 |
«
Reply #29 on:
2012-02-22 22:49:04 » |
|
In my games, I have an Explosion class that extends Entity and I add it to the GameWorld once the enemy/player is dead. 
|
|
|
|
|