Skip to content

Commit 12d4675

Browse files
committed
Moved the missile explosion and missile removal into its own
listener so that it more easily applies to anything hit.
1 parent 1fa6c6f commit 12d4675

File tree

3 files changed

+150
-17
lines changed

3 files changed

+150
-17
lines changed

sigem/src/main/java/sigem/sim/AsteroidHitListener.java

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ public void newContact( Contact c ) {
8282
ObjectType type1 = ed.getComponent(c.b1.bodyId, ObjectType.class);
8383
ObjectType type2 = ed.getComponent(c.b2.bodyId, ObjectType.class);
8484

85-
String t1 = type1.getTypeName(ed);
86-
String t2 = type2.getTypeName(ed);
85+
String t1 = type1 == null ? null : type1.getTypeName(ed);
86+
String t2 = type2 == null ? null : type2.getTypeName(ed);
8787

8888
if( !ObjectType.TYPE_ASTEROID.equals(t1) && !ObjectType.TYPE_ASTEROID.equals(t2) ) {
8989
// Neither side is an asteroid... nothing to do
@@ -111,30 +111,46 @@ public void newContact( Contact c ) {
111111
protected void missileHit( Body missile, Body asteroid, Contact contact ) {
112112
EntityId shooter = ed.getComponent(missile.bodyId, CreatedBy.class).getCreatorId();
113113
log.info("Shooter:" + shooter + " name:" + ed.getComponent(shooter, Name.class));
114+
115+
Vec3d debrisLoc = missile.pos;
114116

115-
ed.removeEntity(missile.bodyId);
116-
gameEntities.createExplosion(missile.pos, 1);
117-
117+
if( asteroid.radius > 1 ) {
118+
// Need to break it up
119+
120+
// Figure out which way the pieces go
121+
Vec3d offset = contact.cn.cross(Vec3d.UNIT_Y);
122+
offset.multLocal(1 + rand.nextDouble());
123+
124+
double size = Math.max(1, asteroid.radius / 2);
125+
126+
Vec3d loc1 = asteroid.pos.add(offset.mult(asteroid.radius * 0.5));
127+
Vec3d loc2 = asteroid.pos.subtract(offset.mult(asteroid.radius * 0.5));
128+
129+
EntityId ast1 = gameEntities.createAsteroid(loc1, offset.add(asteroid.velocity),
130+
new Vec3d(rand.nextDouble() + 1, rand.nextDouble(), 0),
131+
size);
132+
EntityId ast2 = gameEntities.createAsteroid(loc2, offset.subtract(asteroid.velocity),
133+
new Vec3d(rand.nextDouble() + 1, rand.nextDouble(), 0),
134+
size);
135+
136+
} else {
137+
debrisLoc = asteroid.pos;
138+
}
139+
118140
// Create some asteroid debris
119-
int count = rand.nextInt(3) + 3;
141+
int count = rand.nextInt((int)(3 * asteroid.radius)) + 3;
120142
for( int i = 0; i < count; i++ ) {
121143
double x = rand.nextDouble() * 2 - 1;
122144
double z = rand.nextDouble() * 2 - 1;
123145
Vec3d dir = new Vec3d(x, 0, z);
124146
double size = 0.2 + rand.nextDouble() * 0.4;
125147

126-
EntityId chunk = gameEntities.createAsteroidChunk(missile.pos, dir,
148+
EntityId chunk = gameEntities.createAsteroidChunk(debrisLoc.add(dir), dir,
127149
new Vec3d(rand.nextDouble() + 1, rand.nextDouble(), 0),
128150
size);
129-
}
130-
131-
if( asteroid.radius <= 1 ) {
132-
// Just gone
133-
ed.removeEntity(asteroid.bodyId);
134-
return;
135-
}
136-
137-
// Else we need to break it up
138-
151+
}
152+
153+
// And remove the old one
154+
ed.removeEntity(asteroid.bodyId);
139155
}
140156
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* $Id$
3+
*
4+
* Copyright (c) 2019, Simsilica, LLC
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions
9+
* are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in
16+
* the documentation and/or other materials provided with the
17+
* distribution.
18+
*
19+
* 3. Neither the name of the copyright holder nor the names of its
20+
* contributors may be used to endorse or promote products derived
21+
* from this software without specific prior written permission.
22+
*
23+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27+
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34+
* OF THE POSSIBILITY OF SUCH DAMAGE.
35+
*/
36+
37+
package sigem.sim;
38+
39+
import java.util.Objects;
40+
import java.util.Random;
41+
42+
import org.slf4j.*;
43+
44+
import com.simsilica.es.*;
45+
import com.simsilica.mathd.*;
46+
import com.simsilica.sim.*;
47+
48+
import sigem.es.*;
49+
50+
/**
51+
* Checks for any missile hits to create the hit effect and destroy
52+
* the missile entity. It's up to other listeners to deal with the damage.
53+
*
54+
* @author Paul Speed
55+
*/
56+
public class MissileHitListener extends AbstractGameSystem
57+
implements ContactListener {
58+
59+
static Logger log = LoggerFactory.getLogger(MissileHitListener.class);
60+
61+
private EntityData ed;
62+
private GameEntities gameEntities;
63+
private Random rand = new Random(0);
64+
65+
public MissileHitListener() {
66+
}
67+
68+
@Override
69+
protected void initialize() {
70+
this.ed = getSystem(EntityData.class, true);
71+
this.gameEntities = getSystem(GameEntities.class, true);
72+
73+
getSystem(CollisionSystem.class).addContactListener(this);
74+
}
75+
76+
@Override
77+
protected void terminate() {
78+
getSystem(CollisionSystem.class).removeContactListener(this);
79+
}
80+
81+
@Override
82+
public void newContact( Contact c ) {
83+
84+
if( c.energy == 0 ) {
85+
// An early listener already said this wasn't a real contact
86+
return;
87+
}
88+
89+
ObjectType type1 = ed.getComponent(c.b1.bodyId, ObjectType.class);
90+
ObjectType type2 = ed.getComponent(c.b2.bodyId, ObjectType.class);
91+
92+
// Entities may have already been removed
93+
String t1 = type1 == null ? null : type1.getTypeName(ed);
94+
String t2 = type2 == null ? null : type2.getTypeName(ed);
95+
96+
if( Objects.equals(t1, t2) ) {
97+
// Missiles or not, we don't care if they are the same... even
98+
// missiles can pass each other by.
99+
return;
100+
}
101+
102+
if( ObjectType.TYPE_MISSILE.equals(t1) ) {
103+
// Blow up b2
104+
missileHit(c.b1, c);
105+
} else if( ObjectType.TYPE_MISSILE.equals(t2) ) {
106+
// Blow up b1
107+
missileHit(c.b2, c);
108+
}
109+
110+
}
111+
112+
protected void missileHit( Body missile, Contact contact ) {
113+
ed.removeEntity(missile.bodyId);
114+
gameEntities.createExplosion(missile.pos, 1);
115+
}
116+
}

sigem/src/main/java/sigem/view/GameSessionState.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public GameSessionState() {
104104
systems.addSystem(new PlanetGravity());
105105
systems.register(CollisionSystem.class, new CollisionSystem());
106106
systems.register(AsteroidHitListener.class, new AsteroidHitListener());
107+
systems.register(MissileHitListener.class, new MissileHitListener());
107108
systems.addSystem(new PositionPublisher());
108109
systems.addSystem(new ShipInputSystem());
109110
systems.addSystem(new ArenaBoundary(GameConstants.ARENA_EXTENTS));

0 commit comments

Comments
 (0)