Hello,
I'm new to mobile development and Java. My first project is a tower defence game. I'm using j2me. I figured out how to paint the sprites, made a cursor that moves around and turns green or red depending if you can put a tower there or not. Made a sprite for a monster that follows a fixed path. I managed to adjust the view so that it follows the cursor around and also managed to keep the cursor on the background layer using the collision detection. I also managed to put a menu that opens when fire is pressed but I am unable to put it in the space it needs to be in (which should be the bottom of the screen)
I haven't implemented a timer that counts down until the wave arrives but it probably won't be a big deal.
My main problems are as follows;
-I cannot make multiple copies of the monster sprite and make them move one after the other. I made a class "monsterMovement" that governs the movement of that sprite.
-I cannot put towers where the cursor is on. I think I'm going to be using the get position method and put the tower there. but I have no idea how to do that.
My first goal is to be able to make a single wave of monsters move along the path and be able to get a single
I can't post my code and point to an error because I'm completely lost at this point.
You can find my gamecanvas below. I commented some of it...
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Screen;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;
public class TowerDefenseCanvas extends GameCanvas implements Runnable {
private static final int viewBUFFER = 50;
private static final int SPEED = 3;
private Timer timer;
private boolean interrupted;
private GameDesign gameDesign;
private Sprite spriteMonster;
private Sprite spriteCursor;
private Sprite spriteTower1;
private Sprite spriteTower2;
private Sprite spriteHQ;
private Sprite spriteMenu;
private LayerManager lm;
private byte lastDirection = -1;
private SpriteAnimationTask spriteMonsterAnimator;
private SpriteAnimationTask spriteCursorAnimator;
private MonsterMovement spriteMonsterMovement;
private TiledLayer Grass;
private TiledLayer Road;
private TiledLayer Trees;
private int viewPortX = 0;
private int viewPortY = 0;
private boolean wave1sent = false;
private boolean wave2sent = false;
private boolean wave3sent = false;
private boolean wave4sent = false;
private boolean menuOpen = false;
public TowerDefenseCanvas() {
super(true);
try {
this.setFullScreenMode(true);
this.init();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void init() throws IOException {
this.timer = new Timer();
this.gameDesign = new GameDesign();
this.spriteTower1 = gameDesign.getSpriteTower1();
this.spriteTower2 = gameDesign.getSpriteTower2();
this.spriteTower1.defineReferencePixel(24, 18);
this.spriteTower1.setVisible(false);
this.spriteTower2.defineReferencePixel(28, 28);
this.spriteTower2.setVisible(false);
this.spriteMonster = gameDesign.getSpriteMonster();
this.spriteMonster.defineReferencePixel(8, 8);
this.spriteMonsterAnimator = new SpriteAnimationTask(this.spriteMonster, true);
this.spriteMonsterMovement = new MonsterMovement(this, spriteMonster);
this.spriteMenu = gameDesign.getSpriteMenu();
this.spriteCursor = gameDesign.getSpriteCursor();
this.spriteCursor.defineReferencePixel(15, 15);
//Unused collision rectangle - for animation purposes pixel based collision detection is enough
//this.spriteCursor.defineCollisionRectangle(8, 8, 15, 15);
this.spriteCursorAnimator = new SpriteAnimationTask(this.spriteCursor, false);
this.timer.scheduleAtFixedRate(this.spriteCursorAnimator, 0, gameDesign.spriteCursorGREENDelay);
this.timer.scheduleAtFixedRate(this.spriteMonsterAnimator, 0, gameDesign.MonsterwalkSideDelay);
this.Grass = this.gameDesign.getGrass();
this.Road = this.gameDesign.getRoad();
this.Trees = this.gameDesign.getTrees();
this.lm = new LayerManager();
gameDesign.updateLayerManagerForLVL1(lm);
(new Thread(spriteMonsterMovement)).start();
}
public boolean outofBoundsDetect(Sprite sprite) {
return sprite.collidesWith(sprite == this.spriteCursor ? this.spriteMonster : this.spriteCursor, true)
|| sprite.getX() < 0 || sprite.getY() < 0
|| sprite.getX() > (this.Grass.getWidth() - sprite.getWidth())
|| sprite.getY() > (this.Grass.getHeight() - sprite.getHeight());
}
public boolean collisionDetect(Sprite sprite) {
return sprite.collidesWith(this.Trees, true)
|| sprite.collidesWith(this.Road, true)
|| sprite.getX() < 0 || sprite.getY() < 0
|| sprite.getX() > (this.Grass.getWidth() - sprite.getWidth())
|| sprite.getY() > (this.Grass.getHeight() - sprite.getHeight());
}
private class SpriteAnimationTask extends TimerTask {
private boolean moving = false;
private boolean forward = true;
private Sprite sprite;
public SpriteAnimationTask(Sprite sprite, boolean forward) {
this.sprite = sprite;
this.forward = forward;
}
public void run() {
if (!this.moving) {
return;
}
if (this.forward) {
this.sprite.nextFrame();
} else {
this.sprite.prevFrame();
}
}
public void forward() {
this.forward = true;
this.moving = true;
}
public void backward() {
this.forward = false;
this.moving = true;
}
public void setMoving(boolean isMoving) {
this.moving = isMoving;
}
}
public void run() {
Graphics g = getGraphics();
int w = this.Grass.getX() + this.Grass.getWidth() - spriteCursor.getWidth();
int h = this.Grass.getY() + this.Grass.getHeight() - spriteCursor.getHeight();
this.spriteTower1.setVisible(false);
this.spriteTower2.setVisible(false);
while (!this.interrupted) {
//Checking for user input
int keyState = getKeyStates();
if ((keyState & FIRE_PRESSED) != 0) {
if (menuOpen == false) {
menuOpen = true;
spriteCursor.setVisible(false);
spriteMenu.setVisible(true);
} else if (menuOpen == true) {
menuOpen = false;
spriteCursor.setVisible(true);
spriteMenu.setVisible(false);
}
}
if (menuOpen == false) {
this.spriteMenu.setVisible(false);
if ((keyState & LEFT_PRESSED) != 0) {
if (this.lastDirection != LEFT) {
this.lastDirection = LEFT;
continue;
}
//Makes the cursor red or green depending on the collisions
if (this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorRED);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(-SPEED, 0);
} else if (!this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorGREEN);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(-SPEED, 0);
}
if (this.outofBoundsDetect(this.spriteCursor)) {
this.spriteCursor.move(SPEED, 0);
}
this.adjustView(this.viewPortX - SPEED, this.viewPortY);
} else if ((keyState & RIGHT_PRESSED) != 0) {
if (this.lastDirection != RIGHT) {
this.lastDirection = RIGHT;
continue;
}
if (this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorRED);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(SPEED, 0);
} else if (!this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorGREEN);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(SPEED, 0);
}
if (this.outofBoundsDetect(this.spriteCursor)) {
this.spriteCursor.move(-SPEED, 0);
}
this.adjustView(this.viewPortX + SPEED, this.viewPortY);
} else if ((keyState & UP_PRESSED) != 0) {
if (this.lastDirection != UP) {
this.lastDirection = UP;
continue;
}
if (this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorRED);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(0, -SPEED);
} else if (!this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorGREEN);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(0, -SPEED);
}
if (this.outofBoundsDetect(this.spriteCursor)) {
this.spriteCursor.move(0, SPEED);
}
this.adjustView(this.viewPortX, this.viewPortY - SPEED);
} else if ((keyState & DOWN_PRESSED) != 0) {
if (this.lastDirection != DOWN) {
this.lastDirection = DOWN;
continue;
}
if (this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorRED);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(0, SPEED);
} else if (!this.collisionDetect(this.spriteCursor)) {
this.spriteCursor.setFrameSequence(gameDesign.spriteCursorGREEN);
this.spriteCursorAnimator.forward();
this.spriteCursor.move(0, SPEED);
}
if (this.outofBoundsDetect(this.spriteCursor)) {
this.spriteCursor.move(0, -SPEED);
}
this.adjustView(this.viewPortX, this.viewPortY + SPEED);
}
} else if (menuOpen == true) {
}
this.lm.paint(g, 0, 0);
flushGraphics(0, 0, this.getWidth(), this.getHeight());
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
private void adjustView(int x, int y) {
int sx = this.spriteCursor.getX();
int sy = this.spriteCursor.getY();
int xmin = this.viewPortX + viewBUFFER;
int xmax = this.viewPortX + this.getWidth() - this.spriteCursor.getWidth() - viewBUFFER;
int ymin = this.viewPortY + viewBUFFER;
int ymax = this.viewPortY + this.getHeight() - this.spriteCursor.getHeight() - viewBUFFER;
//These cases check and correct if the cursor is near the edges
if (sx >= xmin && sx <= xmax && sy >= ymin && sy <= ymax) {
return;
}
if (this.lastDirection == LEFT && sx >= xmin) {
return;
}
if (this.lastDirection == RIGHT && sx <= xmax) {
return;
}
if (this.lastDirection == UP && sy >= ymin) {
return;
}
if (this.lastDirection == DOWN && sy <= ymax) {
return;
}
//ensures that the background is shown and view does not extend to beyond the background layer (x values)
if (x < this.Grass.getX()) {
this.viewPortX = this.Grass.getX();
} else if (x > this.Grass.getX() + this.Grass.getWidth() - this.getWidth()) {
this.viewPortX = this.Grass.getX() + this.Grass.getWidth() - this.getWidth();
} else {
this.viewPortX = x;
}
//ensures that the background is shown and view does not extend to beyond the background layer (y values)
if (y < this.Grass.getY()) {
this.viewPortY = this.Grass.getY();
} else if (y > this.Grass.getY() + this.Grass.getHeight() - this.getHeight()) {
this.viewPortY = this.Grass.getY() + this.Grass.getHeight() - this.getHeight();
} else {
this.viewPortY = y;
}
//makes the adjustment
this.lm.setViewWindow(this.viewPortX, this.viewPortY, this.getWidth(), this.getHeight());
}
public void stop() {
this.interrupted = true;
}
}