1 package erland.game.tileadventure;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import erland.game.GameEnvironmentInterface;
22 import erland.game.tileadventure.isodiamond.IsoDiamondDrawMap;
23 import erland.game.tileadventure.rect.RectDrawMap;
24
25 import java.util.*;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 /***
31 * Implementation of the main game model that handles all the logic in the game
32 */
33 public class TileAdventureModel implements GameObjectMapActionInterface, ActionHandlerInterface {
34 /*** Logging instance */
35 private static Log LOG = LogFactory.getLog(TileAdventureModel.class);
36 /*** Block container for the game area */
37 protected IrregularBlockContainerInterface cont;
38 /*** Game environment object */
39 protected GameEnvironmentInterface environment;
40 /*** Room map */
41 protected MapObjectContainerInterface roomMap;
42 /*** Object list */
43 protected Vector objectList;
44 /*** A list of all players in the game */
45 private GameObject[] players;
46 /*** A map with mapping between the object maps and rooms */
47 private Map roomByBlockMap;
48 /*** A map with mapping between the object maps and moving maps */
49 private Map movingMapByBlockMap;
50 /*** Mapping between a player and current room */
51 private Map playerRoomMap;
52 /*** A list of all ongoing actions */
53 private Map actionMap = new HashMap();
54
55 /***
56 * Initiate the model
57 * @param environment Game environment
58 * @param cont Block container for the track
59 */
60 public void init(GameEnvironmentInterface environment, IrregularBlockContainerInterface cont) {
61 this.environment = environment;
62 this.cont = cont;
63 movingMapByBlockMap = new HashMap();
64 playerRoomMap = new HashMap();
65 roomByBlockMap = new HashMap();
66 LevelManager levelManager = new WorldGameLevelManager();
67 levelManager.init(environment);
68 levelManager.setContainer(cont);
69 LevelInfoInterface levelInfo = levelManager.getLevel(1);
70 roomMap = levelInfo.getObjects();
71 initRooms(roomMap);
72 }
73 private void initRooms(MapObjectContainerInterface rooms) {
74 this.objectList = new Vector();
75 for (int x = 0; x < rooms.getSizeX(); x++) {
76 for (int y = 0; y < rooms.getSizeY(); y++) {
77 for (int z = 0; z < rooms.getSizeZ(); z++) {
78 RoomObject room = (RoomObject) rooms.getBlock(x,y,z);
79 if(room!=null) {
80 initRoom(room,objectList);
81 }
82 }
83 }
84 }
85 }
86 private void initPlayer(RoomObject room, GameObject player) {
87 DrawMap map = ((TileGameEnvironmentInterface)(environment.getCustomEnvironment())).createBlockMap();
88 map.setContainer(cont);
89 map.addObjectMap(room.getBlocks());
90
91 playerRoomMap.put(player,map);
92 }
93 private void initRoom(RoomObject room,List objectList) {
94 MapObjectContainerInterface movingMap = new MapBlockContainer(room.getBlocks().getSizeX(),room.getBlocks().getSizeY(),room.getBlocks().getSizeZ());
95 roomByBlockMap.put(room.getBlocks(),room);
96 movingMapByBlockMap.put(room.getBlocks(),movingMap);
97 MapObjectContainerInterface map = room.getBlocks();
98 for (int x = 0; x < map.getSizeX(); x++) {
99 for (int y = 0; y < map.getSizeY(); y++) {
100 for (int z = 0; z < map.getSizeZ(); z++) {
101 GameObject o = (GameObject) map.getBlock(x,y,z);
102 if(o instanceof GameObjectUpdateInterface) {
103 o.setActionMap(this);
104 objectList.add(o);
105 }
106 }
107 }
108 }
109 }
110
111 private RoomObject findStartRoom() {
112 for (int x = 0; x < roomMap.getSizeX(); x++) {
113 for (int y = 0; y < roomMap.getSizeY(); y++) {
114 for (int z = 0; z < roomMap.getSizeZ(); z++) {
115 RoomObject room = (RoomObject) roomMap.getBlock(x,y,z);
116 if(room!=null) {
117 return room;
118 }
119 }
120 }
121 }
122 return null;
123 }
124 private void removePlayers(GameObject[] players) {
125 if(players!=null) {
126 for(int i=0;i<players.length;i++) {
127 objectList.removeElement(players[i]);
128 players[i].getObjectMap().removeBlock(players[i],(int)players[i].getPosX(),(int)players[i].getPosY(),(int)players[i].getPosZ());
129 MapObjectContainerInterface movingMap = (MapObjectContainerInterface) movingMapByBlockMap.get(players[i].getObjectMap());
130 movingMap.removeBlock(players[i]);
131 }
132 }
133 }
134 public void initPlayers(GameObject[] players) {
135 removePlayers(this.players);
136 this.players = players;
137 RoomObject room = findStartRoom();
138 MapObjectContainerInterface blockMap = room.getBlocks();
139 for(int i=0;i<players.length;i++) {
140 players[i].setObjectMap(blockMap);
141 players[i].setActionMap(this);
142 players[i].setPos(1,1,1);
143 objectList.addElement(players[i]);
144 blockMap.addObject(players[i],(int)players[i].getPosX(),(int)players[i].getPosY(),(int)players[i].getPosZ());
145 initPlayer(room,players[i]);
146 }
147 }
148 /***
149 * Update model, this will move all cars, check for collisions and apply frictions
150 */
151 public void update() {
152 if(objectList!=null) {
153 for(int i=0;i<objectList.size();i++) {
154 GameObjectUpdateInterface obj = (GameObjectUpdateInterface) objectList.elementAt(i);
155 obj.update();
156 }
157 }
158 for (Iterator it = actionMap.values().iterator(); it.hasNext();) {
159 List list = (List) it.next();
160 for(Iterator it2 = list.iterator();it2.hasNext();) {
161 ActionInterface action = (ActionInterface) it2.next();
162 action.start();
163 if(action.perform()) {
164 action.stop();
165 it2.remove();
166 }
167 }
168 }
169 }
170
171 public MapDrawInterface getMap(GameObject player) {
172 return (MapDrawInterface) playerRoomMap.get(player);
173 }
174 private boolean isInsideMap(MapObjectContainerInterface map, float x, float y, float z) {
175 if(x<map.getSizeX()&& y<map.getSizeY() && z<map.getSizeZ() && x>=0 && y>=0 && z>=0) {
176 return true;
177 }else {
178 return false;
179 }
180 }
181
182 public boolean isFree(MapObjectContainerInterface map,GameObject obj,float x, float y, float z) {
183 if(isInsideMap(map,x,y,z)) {
184 MapObjectInterface block = map.getBlock((int)x,(int)y,(int)z);
185 if((block==null||block==obj)) {
186 return true;
187 }
188 }
189 return false;
190 }
191
192 public boolean isFree(GameObject obj,float x, float y, float z) {
193 if(isInsideMap(obj.getObjectMap(),x,y,z)) {
194 MapObjectInterface block = obj.getObjectMap().getBlock((int)x,(int)y,(int)z);
195
196
197
198
199 if(block==null || block==obj || !block.getBoundingBox().contains(x,y,z)) {
200 return true;
201 }
202 }
203 return false;
204 }
205
206 public boolean isFree(GameObject obj,Box3D boundingBox) {
207 return isFree(obj,boundingBox.getMinX(),boundingBox.getMinY(),boundingBox.getMinZ()) &&
208 isFree(obj,boundingBox.getMinX(),boundingBox.getMinY(),boundingBox.getMaxZ()) &&
209 isFree(obj,boundingBox.getMinX(),boundingBox.getMaxY(),boundingBox.getMinZ()) &&
210 isFree(obj,boundingBox.getMinX(),boundingBox.getMaxY(),boundingBox.getMaxZ()) &&
211 isFree(obj,boundingBox.getMaxX(),boundingBox.getMinY(),boundingBox.getMinZ()) &&
212 isFree(obj,boundingBox.getMaxX(),boundingBox.getMinY(),boundingBox.getMaxZ()) &&
213 isFree(obj,boundingBox.getMaxX(),boundingBox.getMaxY(),boundingBox.getMinZ()) &&
214 isFree(obj,boundingBox.getMaxX(),boundingBox.getMaxY(),boundingBox.getMaxZ());
215 }
216
217 public boolean move(GameObject obj, float x, float y, float z) {
218 Box3D b = new Box3D();
219 obj.fillBoundingBox(x,y,z,b);
220 if(isFree(obj,b)) {
221 Box3D c = obj.getBoundingBox();
222 obj.getObjectMap().removeObject(obj,(int)c.getMinX(),(int)c.getMinY(),(int)c.getMinZ());
223 obj.getObjectMap().removeObject(obj,(int)c.getMinX(),(int)c.getMinY(),(int)c.getMaxZ());
224 obj.getObjectMap().removeObject(obj,(int)c.getMinX(),(int)c.getMaxY(),(int)c.getMinZ());
225 obj.getObjectMap().removeObject(obj,(int)c.getMinX(),(int)c.getMaxY(),(int)c.getMaxZ());
226 obj.getObjectMap().removeObject(obj,(int)c.getMaxX(),(int)c.getMinY(),(int)c.getMinZ());
227 obj.getObjectMap().removeObject(obj,(int)c.getMaxX(),(int)c.getMinY(),(int)c.getMaxZ());
228 obj.getObjectMap().removeObject(obj,(int)c.getMaxX(),(int)c.getMaxY(),(int)c.getMinZ());
229 obj.getObjectMap().removeObject(obj,(int)c.getMaxX(),(int)c.getMaxY(),(int)c.getMaxZ());
230 obj.setPos(x,y,z);
231 c = obj.getBoundingBox();
232 obj.getObjectMap().addObject(obj,(int)c.getMinX(),(int)c.getMinY(),(int)c.getMinZ());
233 obj.getObjectMap().addObject(obj,(int)c.getMinX(),(int)c.getMinY(),(int)c.getMaxZ());
234 obj.getObjectMap().addObject(obj,(int)c.getMinX(),(int)c.getMaxY(),(int)c.getMinZ());
235 obj.getObjectMap().addObject(obj,(int)c.getMinX(),(int)c.getMaxY(),(int)c.getMaxZ());
236 obj.getObjectMap().addObject(obj,(int)c.getMaxX(),(int)c.getMinY(),(int)c.getMinZ());
237 obj.getObjectMap().addObject(obj,(int)c.getMaxX(),(int)c.getMinY(),(int)c.getMaxZ());
238 obj.getObjectMap().addObject(obj,(int)c.getMaxX(),(int)c.getMaxY(),(int)c.getMinZ());
239 obj.getObjectMap().addObject(obj,(int)c.getMaxX(),(int)c.getMaxY(),(int)c.getMaxZ());
240 return true;
241 }
242 return false;
243 }
244
245 private float getMovingPosX(float x, float y, float z, Direction direction) {
246 if(direction == Direction.WEST) {
247 x--;
248 }else if(direction == Direction.EAST) {
249 x++;
250 }
251 return x;
252 }
253 private float getMovingPosY(float x, float y, float z, Direction direction) {
254 if(direction == Direction.NORTH) {
255 y--;
256 }else if(direction == Direction.SOUTH) {
257 y++;
258 }
259 return y;
260 }
261 private float getMovingPosZ(float x, float y, float z, Direction direction) {
262 if(direction == Direction.DOWN) {
263 z--;
264 }else if(direction == Direction.UP) {
265 z++;
266 }
267 return z;
268 }
269
270 private Action getPushActionForDirection(Direction direction) {
271 if(direction==Direction.WEST) {
272 return Action.PUSH_WEST;
273 }else if(direction==Direction.EAST) {
274 return Action.PUSH_EAST;
275 }else if(direction==Direction.NORTH) {
276 return Action.PUSH_NORTH;
277 }else if(direction==Direction.SOUTH) {
278 return Action.PUSH_SOUTH;
279 }else {
280 return Action.NONE;
281 }
282 }
283
284 public ActionInterface isActionPossibleOnObject(GameObject obj, Action action) {
285 MapObjectContainerInterface movingMap = (MapObjectContainerInterface) movingMapByBlockMap.get(obj.getObjectMap());
286 MapObjectContainerInterface blockMap = (MapObjectContainerInterface) obj.getObjectMap();
287 if(action.isMove()||action.isPush()) {
288 Direction direction = action.getDirection();
289 int newX=(int)getMovingPosX(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
290 int newY=(int)getMovingPosY(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
291 int newZ=(int)getMovingPosZ(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
292 if(isInsideMap(blockMap,newX,newY,newZ)) {
293 if(isFree(obj,newX,newY,newZ)) {
294 return action;
295 }else {
296 GameObject nextObj = (GameObject)blockMap.getBlock(newX,newY,newZ);
297 if(nextObj!=null && nextObj.isMovable(action.getDirection())) {
298
299 return getPushActionForDirection(action.getDirection());
300 }
301 }
302 }else if(action.isMove()) {
303 LOG.debug("Try changing room "+newX+","+newY+","+newZ);
304 MapObjectContainerInterface currentRoomMap = obj.getObjectMap();
305 RoomObject currentRoom = (RoomObject) roomByBlockMap.get(currentRoomMap);
306 if(isFreeInNextRoom(currentRoom,newX,newY,newZ) && isAllowedToChangeRoom(obj)) {
307 return action;
308 }
309 }
310 }else if(action==Action.JUMP) {
311 if(isInsideMap(blockMap,obj.getPosX(),obj.getPosY(),obj.getPosZ()+1)) {
312 if(isFree(obj,obj.getPosX(),obj.getPosY(),obj.getPosZ()+1)) {
313 return action;
314 }
315 }
316 }else if(action==Action.DROP) {
317 if(isInsideMap(blockMap,obj.getPosX(),obj.getPosY(),obj.getPosZ()-1)) {
318 if(isFree(obj,obj.getPosX(),obj.getPosY(),obj.getPosZ()-1)) {
319 return action;
320 }
321 }
322 }
323 return Action.NONE;
324 }
325 public ActionInterface startActionOnObject(GameObject obj, Action action) {
326 MapObjectContainerInterface movingMap = (MapObjectContainerInterface) movingMapByBlockMap.get(obj.getObjectMap());
327 MapObjectContainerInterface blockMap = (MapObjectContainerInterface) obj.getObjectMap();
328 if(action.isMove()||action.isPush()) {
329 Direction direction = action.getDirection();
330 int newX=(int)getMovingPosX(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
331 int newY=(int)getMovingPosY(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
332 int newZ=(int)getMovingPosZ(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
333 if(isInsideMap(blockMap,newX,newY,newZ)) {
334 if(isFree(obj,newX,newY,newZ)) {
335 movingMap.setBlock(obj,newX,newY,newZ);
336 return action;
337 }else {
338 GameObject nextObj = (GameObject)blockMap.getBlock(newX,newY,newZ);
339 if(nextObj!=null && nextObj.isMovable(action.getDirection())) {
340 nextObj.action(getPushActionForDirection(action.getDirection()));
341 movingMap.setBlock(obj,newX,newY,newZ);
342 return getPushActionForDirection(action.getDirection());
343 }
344 }
345 }else if(action.isMove()) {
346 LOG.debug("Try changing room "+newX+","+newY+","+newZ);
347 MapObjectContainerInterface currentRoomMap = obj.getObjectMap();
348 RoomObject currentRoom = (RoomObject) roomByBlockMap.get(currentRoomMap);
349 if(isFreeInNextRoom(currentRoom,newX,newY,newZ) && isAllowedToChangeRoom(obj)) {
350 LOG.debug("Start changing room "+newX+","+newY+","+newZ);
351 movingMap.setBlock(obj,newX,newY,newZ);
352 return action;
353 }
354 }
355 }else if(action==Action.JUMP) {
356 if(isInsideMap(blockMap,obj.getPosX(),obj.getPosY(),obj.getPosZ()+1)) {
357 if(isFree(obj,obj.getPosX(),obj.getPosY(),obj.getPosZ()+1)) {
358 movingMap.setBlock(obj,(int)obj.getPosX(),(int)obj.getPosY(),(int)obj.getPosZ()+1);
359 return action;
360 }
361 }
362 }else if(action==Action.DROP) {
363 if(isInsideMap(blockMap,obj.getPosX(),obj.getPosY(),obj.getPosZ()-1)) {
364 if(isFree(obj,obj.getPosX(),obj.getPosY(),obj.getPosZ()-1)) {
365 movingMap.setBlock(obj,(int)obj.getPosX(),(int)obj.getPosY(),(int)obj.getPosZ()-1);
366 return action;
367 }
368 }
369 }
370 return Action.NONE;
371 }
372
373 public void endActionOnObject(GameObject obj, Action action) {
374 MapObjectContainerInterface movingMap = (MapObjectContainerInterface) movingMapByBlockMap.get(obj.getObjectMap());
375 MapObjectContainerInterface blockMap = (MapObjectContainerInterface) obj.getObjectMap();
376 if(action.isMove() || action.isPush()) {
377 Direction direction = action.getDirection();
378 int newX = (int)getMovingPosX(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
379 int newY = (int)getMovingPosY(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
380 int newZ = (int)getMovingPosZ(obj.getPosX(),obj.getPosY(),obj.getPosZ(),direction);
381 if(isInsideMap(blockMap,newX,newY,newZ)) {
382 if(movingMap.getBlock(newX,newY,newZ)==obj) {
383 movingMap.removeBlock(obj,newX,newY,newZ);
384 obj.setPos(newX,newY,newZ);
385 }
386 }else {
387 LOG.debug("Ending changing room "+newX+","+newY+","+newZ);
388 MapObjectContainerInterface currentRoomMap = obj.getObjectMap();
389 RoomObject currentRoom = (RoomObject) roomByBlockMap.get(currentRoomMap);
390 if(isFreeInNextRoom(currentRoom,newX,newY,newZ) && isAllowedToChangeRoom(obj)) {
391 obj.setPos(newX,newY,newZ);
392 RoomObject room = findRoom(currentRoom,newX, newY, newZ);
393 if(newX<0) {
394 newX=room.getBlocks().getSizeX()-1;
395 }else if(newX>=currentRoomMap.getSizeX()) {
396 newX = 0;
397 }
398 if(newY<0) {
399 newY=room.getBlocks().getSizeY()-1;
400 }else if(newY>=currentRoomMap.getSizeY()) {
401 newY = 0;
402 }
403 if(newZ<0) {
404 newZ=room.getBlocks().getSizeZ()-1;
405 }else if(newZ>=currentRoomMap.getSizeZ()) {
406 newZ = 0;
407 }
408 initPlayer(room,obj);
409 obj.setObjectMap(room.getBlocks());
410 obj.setPos(newX,newY,newZ);
411
412 LOG.debug("Changed room "+newX+","+newY+","+newZ);
413 }
414 }
415 }else if(action==Action.JUMP) {
416 if(isInsideMap(blockMap,obj.getPosX(),obj.getPosY(),obj.getPosZ()+1)) {
417 LOG.debug("isInsideMap "+obj.getPosZ());
418 if(movingMap.getBlock((int)obj.getPosX(),(int)obj.getPosY(),(int)obj.getPosZ()+1)==obj) {
419 LOG.debug("getBlock "+obj.getPosZ());
420 movingMap.removeBlock(obj,(int)obj.getPosX(),(int)obj.getPosY(),(int)obj.getPosZ()+1);
421 obj.setPos(obj.getPosX(),obj.getPosY(),obj.getPosZ()+1);
422 }
423 }
424 }else if(action==Action.DROP) {
425 if(isInsideMap(blockMap,obj.getPosX(),obj.getPosY(),obj.getPosZ()-1)) {
426 LOG.debug("isInsideMap "+obj.getPosZ());
427 if(movingMap.getBlock((int)obj.getPosX(),(int)obj.getPosY(),(int)obj.getPosZ()-1)==obj) {
428 LOG.debug("getBlock "+obj.getPosZ());
429 movingMap.removeBlock(obj,(int)obj.getPosX(),(int)obj.getPosY(),(int)obj.getPosZ()-1);
430 obj.setPos(obj.getPosX(),obj.getPosY(),obj.getPosZ()-1);
431 }
432 }
433 }
434 }
435 private RoomObject findRoom(RoomObject currentRoom, float x, float y, float z) {
436 int roomX = (int)currentRoom.getPosX();
437 int roomY = (int)currentRoom.getPosY();
438 int roomZ = (int)currentRoom.getPosZ();
439 if(x<0) {
440 roomX--;
441 }else if(x>=currentRoom.getBlocks().getSizeX()) {
442 roomX++;
443 }
444 if(y<0) {
445 roomY--;
446 }else if(y>=currentRoom.getBlocks().getSizeY()) {
447 roomY++;
448 }
449 if(z<0) {
450 roomZ--;
451 }else if(z>=currentRoom.getBlocks().getSizeZ()) {
452 roomZ++;
453 }
454 return (RoomObject) roomMap.getBlock(roomX,roomY,roomZ);
455 }
456
457 private boolean isFreeInNextRoom(RoomObject currentRoom, float x, float y, float z) {
458 RoomObject room = findRoom(currentRoom, x,y,z);
459 if(room!=null) {
460 if(currentRoom.getPosX()>room.getPosX()) {
461 x = room.getBlocks().getSizeX()-1;
462 }else if(currentRoom.getPosX()<room.getPosX()) {
463 x = 0;
464 }
465 if(currentRoom.getPosY()>room.getPosY()) {
466 y = room.getBlocks().getSizeY()-1;
467 }else if(currentRoom.getPosY()<room.getPosY()) {
468 y = 0;
469 }
470 if(currentRoom.getPosZ()>room.getPosZ()) {
471 z = room.getBlocks().getSizeZ()-1;
472 }else if(currentRoom.getPosZ()<room.getPosZ()) {
473 z = 0;
474 }
475 return isFree(room.getBlocks(),null,x,y,z);
476 }
477 return false;
478 }
479 private boolean isAllowedToChangeRoom(GameObject obj) {
480 return obj instanceof LivingObject;
481 }
482
483 public void register(ActionInterface action) {
484 List list = (List) actionMap.get(action.getController());
485 if(list==null) {
486 list = new ArrayList(10);
487 actionMap.put(action.getController(),list);
488 }
489 for(Iterator it=list.iterator();it.hasNext();) {
490 ActionInterface a = (ActionInterface) it.next();
491 if(a.getClass().equals(action.getClass())) {
492 a.stop();
493 it.remove();
494 }
495 }
496 list.add(action);
497 }
498
499 public void unregister(ActionInterface action) {
500 List list = (List) actionMap.get(action.getController());
501 if(list!=null) {
502 list.remove(action);
503 }
504 }
505 }