GustavXIII
|
 |
«
Posted
2012-01-31 22: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
|
 |
«
Reply #1 - Posted
2012-01-31 22: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
Senior Newbie 
|
 |
«
Reply #2 - Posted
2012-01-31 22: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! Check 'em out!
|
|
UprightPath
|
 |
«
Reply #3 - Posted
2012-01-31 22: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.
|
|
|
|
ReBirth
|
 |
«
Reply #4 - Posted
2012-02-01 00: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.
|
|
|
|
sproingie
|
 |
«
Reply #5 - Posted
2012-02-01 01:01:26 » |
|
Seems not good to rely on GC. Remove it manually.
How do you propose to do that?
|
|
|
|
|
ReBirth
|
 |
«
Reply #6 - Posted
2012-02-01 01: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.
|
|
|
|
sproingie
|
 |
«
Reply #7 - Posted
2012-02-01 05: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
|
 |
«
Reply #8 - Posted
2012-02-02 01:19:03 » |
|
So I'm doing this wrong all time! D:
|
|
|
|
UprightPath
|
 |
«
Reply #9 - Posted
2012-02-02 01: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.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
theagentd
|
 |
«
Reply #10 - Posted
2012-02-02 09: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.
|
Myomyomyo.
|
|
|
ReBirth
|
 |
«
Reply #11 - Posted
2012-02-03 03:57:37 » |
|
I use ArrayList 
|
|
|
|
UprightPath
|
 |
«
Reply #12 - Posted
2012-02-03 04: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.
|
|
|
|
StumpyStrust
|
 |
«
Reply #13 - Posted
2012-02-03 11: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
|
 |
«
Reply #14 - Posted
2012-02-04 10: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
Senior Newbie  Medals: 1
|
 |
«
Reply #15 - Posted
2012-02-05 07: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
|
 |
«
Reply #16 - Posted
2012-02-06 08: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
Senior Newbie  Medals: 1
|
 |
«
Reply #17 - Posted
2012-02-06 17: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
|
 |
«
Reply #18 - Posted
2012-02-06 18:03:12 » |
|
explains all. Thanks for clearing it up for me!
|
|
|
|
WildChild88
Junior Newbie
|
 |
«
Reply #19 - Posted
2012-02-10 14: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
|
 |
«
Reply #20 - Posted
2012-02-10 14:53:44 » |
|
It depends. In my experience, it is probably best to set it to null just to be certain.
|
|
|
|
|
ReBirth
|
 |
«
Reply #21 - Posted
2012-02-11 03:52:41 » |
|
Or add it to secondary ArrayList and use removeAll(). Bit slow but works fine.
|
|
|
|
GustavXIII
|
 |
«
Reply #22 - Posted
2012-02-15 13: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
|
 |
«
Reply #23 - Posted
2012-02-16 01: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
|
 |
«
Reply #24 - Posted
2012-02-16 13: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
|
 |
«
Reply #25 - Posted
2012-02-16 14: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
Senior Newbie 
|
 |
«
Reply #26 - Posted
2012-02-16 23: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
|
 |
«
Reply #27 - Posted
2012-02-17 18: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
|
 |
«
Reply #28 - Posted
2012-02-22 18: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
|
 |
«
Reply #29 - Posted
2012-02-23 04: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. 
|
|
|
|
|