|
ActionControl |
|
/*
* JVirus is a PacMan clone, written in Java.
*
* Please read "http://jvirus.sourceforge.net/jvirus_licence.txt" for copyrights.
*
* The sourcecode is designed and created with
* Sun J2SDK 1.3 and Microsoft Visual J++ 6.0
*
* JVirus homepage: http://jvirus.sourceforge.net
*
* autor: Slawa Weis
* email: slawaweis@animatronik.net
*
*/
package org.game.JVirus;
import java.awt.event.*;
import javax.swing.JFrame;
/**
* this class controls the movement of the avatar and the animating thread.
*/
public class ActionControl implements IFields, KeyListener
{
/**
* reference to the level
*
* @see org.game.JVirus.Matrix
*/
protected Matrix level = null;
/**
* reference to the display
*
* @see org.game.JVirus.Display
*/
protected Display display = null;
/**
* reference to the JVirusFrame
*
* @see org.game.JVirus.JVirusFrame
*/
protected JFrame parent = null;
/**
* reference to the Avatar
*
* @see org.game.JVirus.Avatar
*/
protected Avatar avatar = null;
/**
* callback function
*/
protected ActionControl.IGameListener gameListener = null;
/**
* thread to for animated objects
*/
protected ActionControlRunner runner = null;
/**
* clear byte
*
* @see #nextMove()
*/
protected int set_byte = 1;
/**
* game running or not
*/
protected boolean gameStart = false;
/**
* game paused or not
*/
protected boolean gamePaused = false;
/**
* need to escape from stones
*
* @see #nextMove()
*/
protected long lastTimeAvatarMove = 0;
/**
* callback interface for game events
*/
public interface IGameListener
{
/**
* constant for winning the game
*/
public static final int WIN = 0;
/**
* constant for losing the game
*/
public static final int LOSE = 1;
/**
* end of the game
*/
public void gameOver(int reason);
/**
* game score changed
*/
public void scoreChanged(Avatar avatar);
/**
* game lifes changed
*/
public void lifesChanged(Avatar avatar);
}
/**
* creates the ActionControl.
*
* @param display reference to the Display
* @param parent reference to the JVirusFrame
* @param gameListener reference to the callback function
*/
public ActionControl(Display display, JFrame parent, ActionControl.IGameListener gameListener)
{
super();
this.display = display;
this.parent = parent;
this.gameListener = gameListener;
this.avatar = new Avatar();
}
/**
* return the current avatar
*
* @see org.game.JVirus.Avatar
*/
public Avatar getAvatar()
{
return avatar;
}
/**
* start the game
*
* @param level playing level
*/
public void startGame(Matrix level)
{
this.level = level;
// search for start
int i = 0, j = 0;
boolean break_loop = false;
for(i = 0; i < level.matrix.length; i++)
{
for(j = 0; j < level.matrix[i].length; j++)
{
if(level.matrix[i][j] == IFields.START)
{
break_loop = true;
break;
}
}
if(break_loop) break;
}
// reset the avatar
avatar.setLevel(level, j, i);
lastTimeAvatarMove = 0;
// repaint the avatar
display.moveAvatar(avatar);
// add key listener
parent.addKeyListener(this);
// start animating thread
runner = new ActionControlRunner();
runner.start();
gameStart = true;
gamePaused = false;
}
/**
* pause the game
*
* @param b pause or not
*/
public void pauseGame(boolean b)
{
if(!gameStart) return;
if(b)
{
runner.pauseRunner(b);
parent.removeKeyListener(this);
gamePaused = true;
}
else
{
runner.pauseRunner(b);
parent.addKeyListener(this);
gamePaused = false;
}
}
/* *
* reset the game
*/
/*
public void resetGame()
{
}
*/
/**
* reset the scores and lifes of the avatar.
*/
public void resetAvatar()
{
if(!gameStart)
avatar = new Avatar();
}
/**
* stop the game
*/
public void stopGame()
{
if(gameStart)
{
runner.stopRunner();
runner = null;
parent.removeKeyListener(this);
}
gameStart = false;
gamePaused = false;
}
/**
* is the game started or not
*/
public boolean isRunning()
{
return gameStart;
}
/**
* is the game paused or not
*/
public boolean isPaused()
{
return gamePaused;
}
/**
* edit the avatar and call the callback funktion
*/
protected void gameOver(int reason)
{
// stop the game
stopGame();
if(reason == IGameListener.WIN)
{
Sound.playFX(Sound.FX_WIN);
// add current level scores to whole game scores
avatar.gameScore += avatar.gameScoreCurrentLevel;
avatar.gameLifes += avatar.gameLifesCurrentLevel;
// this level solved
avatar.solvedLevels[level.levelNumber] = Avatar.LEVEL_SOLVED;
// unlock the next locked level
for(int i = 0; i < avatar.solvedLevels.length; i++)
{
if(avatar.solvedLevels[i] == Avatar.LEVEL_CAN_NOT_SOLVE)
{
avatar.solvedLevels[i] = Avatar.LEVEL_CAN_SOLVE;
break;
}
}
}
// buuuhhhh... :)
if(reason == IGameListener.LOSE)
{
Sound.playFX(Sound.FX_LOSE);
avatar.gameLifes--;
}
// call the callback function
gameListener.gameOver(reason);
}
/**
* get the key events
*/
public void keyPressed (KeyEvent e)
{
// the last time, the avatar ist moving
lastTimeAvatarMove = System.currentTimeMillis();
// move the position on display
if(e.getKeyCode() == KeyEvent.VK_LEFT)
{
// if(avatar.x - display.mapOnScreen.x < 1 && display.mapOnScreen.x > 0)
if((avatar.x - display.mapOnScreen.x) < Display.DISPLAY_TILES_WIDTH2 &&
display.mapOnScreen.x > 0)
{
display.mapOnScreen.x--;
display.repaintMatrix();
}
moveAvatar(avatar.x, avatar.y, avatar.x-1, avatar.y);
}
else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
{
// if((avatar.x - display.mapOnScreen.x) >= Display.DISPLAY_TILES_WIDTH-1 &&
// display.mapOnScreen.x+Display.DISPLAY_TILES_WIDTH < level.matrix[0].length)
if((avatar.x - display.mapOnScreen.x) >= Display.DISPLAY_TILES_WIDTH2 &&
display.mapOnScreen.x+Display.DISPLAY_TILES_WIDTH < level.matrix[0].length)
{
display.mapOnScreen.x++;
display.repaintMatrix();
}
moveAvatar(avatar.x, avatar.y, avatar.x+1, avatar.y);
}
else if(e.getKeyCode() == KeyEvent.VK_UP)
{
// if(avatar.y - display.mapOnScreen.y < 1 && display.mapOnScreen.y > 0)
if((avatar.y - display.mapOnScreen.y) < Display.DISPLAY_TILES_HEIGHT2 &&
display.mapOnScreen.y > 0)
{
display.mapOnScreen.y--;
display.repaintMatrix();
}
moveAvatar(avatar.x, avatar.y, avatar.x, avatar.y-1);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN)
{
// if((avatar.y - display.mapOnScreen.y) >= Display.DISPLAY_TILES_HEIGHT-1 &&
// display.mapOnScreen.y+Display.DISPLAY_TILES_HEIGHT < level.matrix.length)
if((avatar.y - display.mapOnScreen.y) >= Display.DISPLAY_TILES_HEIGHT2 &&
display.mapOnScreen.y+Display.DISPLAY_TILES_HEIGHT < level.matrix.length)
{
display.mapOnScreen.y++;
display.repaintMatrix();
}
moveAvatar(avatar.x, avatar.y, avatar.x, avatar.y+1);
}
}
/**
* not used
*/
public void keyReleased(KeyEvent e)
{
}
/**
* not used
*/
public void keyTyped (KeyEvent e)
{
}
/**
* next move from thread
*/
protected void nextMove()
{
int i, j;
int set = (set_byte == 1 ? 2 : 1);
boolean matrix_changed = false;
// search in the whole matrix
for(i = 0; i < level.matrix.length; i++)
for(j = 0; j < level.matrix[i].length; j++)
{
// if set, then this field is visited
if(level.bufferMatrix1[i][j] == set) continue;
// if object is a fall object
if((Matrix.actionTyp[level.matrix[i][j]] & AT_FAll) == AT_FAll &&
(Matrix.actionTyp[level.matrix[i+1][j]] & AT_HOLD) == 0)
{
// if under the object is free
if(level.matrix[i+1][j] == EMPTY && (avatar.x != j || avatar.y != i+1))
{
matrix_changed = true;
level.matrix [i+1][j] = level.matrix[i][j];
level.bufferMatrix1[i+1][j] = set;
level.matrix [i][j] = EMPTY;
level.bufferMatrix1[i][j] = set;
// avatar die or not
if((j == avatar.x) && (i+2 == avatar.y) &&
(System.currentTimeMillis() - lastTimeAvatarMove) > 250)
gameOver(IGameListener.LOSE);
}
// if right under the object is free
else if(level.matrix[i][j+1] == EMPTY && level.matrix[i+1][j+1] == EMPTY &&
(avatar.x != j+1 || avatar.y != i) && (avatar.x != j+1 || avatar.y != i+1))
{
matrix_changed = true;
level.matrix [i+1][j+1] = level.matrix[i][j];
level.bufferMatrix1[i+1][j+1] = set;
level.matrix [i][j] = EMPTY;
level.bufferMatrix1[i][j] = set;
// avatar die or not
if((j+1 == avatar.x) && (i+2 == avatar.y) &&
(System.currentTimeMillis() - lastTimeAvatarMove) > 250)
gameOver(IGameListener.LOSE);
}
// if left under the object is free
else if(level.matrix[i][j-1] == EMPTY && level.matrix[i+1][j-1] == EMPTY &&
(avatar.x != j-1 || avatar.y != i) && (avatar.x != j-1 || avatar.y != i+1))
{
matrix_changed = true;
level.matrix [i+1][j-1] = level.matrix[i][j];
level.bufferMatrix1[i+1][j-1] = set;
level.matrix [i][j] = EMPTY;
level.bufferMatrix1[i][j] = set;
// avatar die or not
if((j-1 == avatar.x) && (i+2 == avatar.y) &&
(System.currentTimeMillis() - lastTimeAvatarMove) > 250)
gameOver(IGameListener.LOSE);
}
}
else
{
// position visited
level.bufferMatrix1[i][j] = set;
}
}
set_byte = set;
// if matrix changed, repaint
if(matrix_changed)
{
Sound.playFX(Sound.FX_FALL);
display.repaintMatrix(avatar);
display.repaint();
}
// if matrix not changed, repaint only the animated fields
else
{
display.repaintAnimTiles(avatar);
display.repaint();
}
}
/**
* next move from user
*/
protected void moveAvatar(int sx, int sy, int tx, int ty)
{
Sound.playFX(Sound.FX_MOVE);
// for the avatar image
avatar.move_direction = (sx > tx);
avatar.eat_sequence = !avatar.eat_sequence;
if(sx != tx &&
tx >= 0 &&
tx < level.matrix[ty].length &&
actionAvatar(sx, sy, tx, ty))
{
avatar.lx = avatar.x;
avatar.ly = avatar.y;
avatar.x = tx;
avatar.y = ty;
}
if(sy != ty &&
ty >= 0 &&
ty < level.matrix.length &&
actionAvatar(sx, sy, tx, ty))
{
avatar.lx = avatar.x;
avatar.ly = avatar.y;
avatar.x = tx;
avatar.y = ty;
}
// repaint only the avatar
display.moveAvatar(avatar);
display.repaint();
// if avatar in the end field
if(level.matrix[avatar.y][avatar.x] == END)
gameOver(IGameListener.WIN);
}
/**
* select what Action to do in this field
*/
protected boolean actionAvatar(int sx, int sy, int tx, int ty)
{
// remove field
if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_EAT) == AT_EAT)
{
avatar.gameScoreCurrentLevel += Matrix.scoreTab[level.matrix[ty][tx]];
if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_EAT_SOUND1) == AT_EAT_SOUND1)
{
Sound.playFX(Sound.FX_EAT1);
}
else if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_EAT_SOUND2) == AT_EAT_SOUND2)
{
Sound.playFX(Sound.FX_EAT2);
}
if(level.matrix[ty][tx] == REDKEY ||
level.matrix[ty][tx] == GREENKEY ||
level.matrix[ty][tx] == BLUEKEY)
{
Sound.playFX(Sound.FX_GATE_OPEN);
removeGate(level.matrix[ty][tx]);
display.repaintMatrix();
}
else if(level.matrix[ty][tx] == LIFE)
{
avatar.gameLifesCurrentLevel += 1;
gameListener.lifesChanged(avatar);
}
level.matrix[ty][tx] = EMPTY;
gameListener.scoreChanged(avatar);
}
// transport in the beam
if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_BEAM) == AT_BEAM)
{
Sound.playFX(Sound.FX_BEAM);
beamAvatar(level.matrix[ty][tx], tx, ty);
display.mapOnScreen.x = avatar.x - Display.DISPLAY_TILES_WIDTH2;
display.mapOnScreen.y = avatar.y - Display.DISPLAY_TILES_HEIGHT2;
if(display.mapOnScreen.x < 0)
display.mapOnScreen.x = 0;
if(display.mapOnScreen.x + Display.DISPLAY_TILES_WIDTH >= level.matrix[0].length)
display.mapOnScreen.x = level.matrix[0].length - Display.DISPLAY_TILES_WIDTH;
if(display.mapOnScreen.y < 0)
display.mapOnScreen.y = 0;
if(display.mapOnScreen.y + Display.DISPLAY_TILES_HEIGHT >= level.matrix.length)
display.mapOnScreen.y = level.matrix.length - Display.DISPLAY_TILES_HEIGHT;
display.repaintMatrix();
return false;
}
// can moving into this field or not
if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_END) == AT_END)
{
return true;
}
else if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_MOVE) == AT_MOVE)
{
return true;
}
else if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_ACTION) == AT_ACTION)
{
return true;
}
else if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_WALL) == AT_WALL)
{
return false;
}
else if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_PUSH) == AT_PUSH)
{
return false;
}
else if((Matrix.actionTyp[level.matrix[ty][tx]] & AT_ANIM) == AT_ANIM)
{
}
return false;
}
/**
* search for the gate that pass and remove that
*/
protected void removeGate(char key)
{
char gate = ' ';
if(key == REDKEY)
gate = REDGATE;
else if(key == GREENKEY)
gate = GREENGATE;
else if(key == BLUEKEY)
gate = BLUEGATE;
int i, j;
for(i = 0; i < level.matrix.length; i++)
for(j = 0; j < level.matrix[i].length; j++)
{
if(level.matrix[i][j] == gate)
{
level.matrix[i][j] = EMPTY;
break;
}
}
}
/**
* search for other beam field and move the avatar
*/
protected void beamAvatar(char key, int x, int y)
{
int i, j;
for(i = 0; i < level.matrix.length; i++)
for(j = 0; j < level.matrix[i].length; j++)
{
if(level.matrix[i][j] == key && (x != j || y != i))
{
avatar.x = j;
avatar.y = i;
break;
}
}
}
/**
* Animating thread
*/
protected class ActionControlRunner extends Thread
{
protected boolean run = true;
protected boolean pause = false;
public void run()
{
while(run)
{
if(!pause) nextMove();
try { sleep(500); } catch(InterruptedException e) {}
}
}
/**
* pauses the while thread loop
*/
public void pauseRunner(boolean b)
{
pause = b;
}
/**
* stop and exit from thread loop
*/
public void stopRunner()
{
System.out.println("Thread term.");
run = false;
}
}
}
|
ActionControl |
|