So I'm working on a Space Invaders theme project, and I have most of my classes up and running and have started on the animation. Part of the process is the ship's weapons.
I have a class for the weapons, as below (Focus on the constructor):
/**
* #(#)Weapon.java
*
*
* #author Tristan Nel - 18179460
* #version 1.00 2015/3/4
*/
public class Weapon {
private String type;
private int damage;
private int rof; //rate of fire
private int orientation;
private int firingStage; //0 - not firing ; 1 - flash & recoil ; 2 - bullet
private String[] sprites; //Set of sprite image file names
public Weapon() {
}
public Weapon(String type, int damage, int rof, int orientation, int firingStage, String[] sprites)
{
this.type = type;
this.damage = damage;
this.rof = rof;
this.orientation = orientation;
this.firingStage = firingStage;
this.sprites = sprites;
}
//GET and SET Methods
public void setType(String type)
{
this.type = type;
}
public void setDamage(int damage)
{
this.damage = damage;
}
public void setROF(int rof)
{
this.rof = rof;
}
public void setOrientation(int orientation)
{
this.orientation = orientation;
}
public void setFiringStage(int firingStage)
{
this.firingStage = firingStage;
}
public void setSprites(String[] sprites)
{
this.sprites = sprites;
}
public String getType()
{
return this.type;
}
public int getDamage()
{
return this.damage;
}
public int getROF()
{
return this.rof;
}
public int getOrientation()
{
return this.orientation;
}
public int getFiringStage()
{
return this.firingStage;
}
public String[] getSprites()
{
return this.sprites;
}
}
In another class, which handles all elements on the game screen to be animated, I want to have a global array of hardcoded Weapon types that can be accessed as needed without fuss. I have attempted to do so at the top of the contents of the class:
/**
* #(#)GameScreen.java
*
*
* #author Tristan Nel - 18179460
* #version 1.00 2015/3/4
*/
import java.util.Scanner;
import java.io.*;
public class GameScreen {
private static final String HIGH_SCORE_FILE = "highScore.txt";
//Available Weapons
//UPDATED SINCE ORIGINAL POST
public static final Weapon[] WEAPONS = new Weapon[4];
WEAPONS[0] = new Weapon("Machinegun", 10, 20, 0, 0, {Graphics.MG_L_NORM, Graphics.MG_R_NORM});
WEAPONS[1] = new Weapon("Plasma MG", 20, 20, 0, 0, {Graphics.PMG_L_NORM, Graphics.PMG_R_NORM});
WEAPONS[2] = new Weapon("Photon Cannon", 40, 5, 0, 0, {Graphics.PC_L_NORM, Graphics.PC_R_NORM});
WEAPONS[3] = new Weapon("Alien Destabilizer", 60, 10, 0, 0, {Graphics.AD_L_NORM, Graphics.AD_R_NORM});
private Ship defender;
private Weapon equipped;
//private Invader[] aliens;
//private Bullet[] bullets;
private int score;
private int highscore;
private int lives;
public GameScreen() {
}
public GameScreen(Ship defender, int score, int lives)
{
this.defender = defender;
this.score = score;
this.lives = lives;
}
public void loadHighscore()
{
try
{
Scanner sc = new Scanner(new File(HIGH_SCORE_FILE));
this.highscore = Integer.parseInt(sc.next());
sc.close();
}
catch(FileNotFoundException fnf)
{
System.out.println(fnf);
this.highscore = 0;
}
}
public void saveHighScore(int highscore)
{
try
{
FileWriter write = new FileWriter(HIGH_SCORE_FILE);
PrintWriter pw = new PrintWriter(write);
pw.print(this.highscore);
pw.close();
}
catch(IOException e)
{
System.out.println(e);
}
}
//GET and SET methods
public void setDefender(Ship defender)
{
this.defender = defender;
}
public void setScore(int score)
{
this.score = score;
}
public void setLives(int lives)
{
this.lives = lives;
}
public Ship getDefender()
{
return this.defender;
}
public int getScore()
{
return this.score;
}
public int getLives()
{
return this.lives;
}
}
This gives me the following error messages on each line that I try to add another element to the array:
UPDATED
https://drive.google.com/file/d/0B7ye7Ul2JDG2NDFDRTJNM1FCd0U/view?usp=sharing
It is highly frustrating..
I read somewhere that you have to create an object within a method? (Eg. main() )
But I tried that in my driver class and it made no difference...
Will appreciate any help/advice (:
There are multiple issues
You cannot have arbitrary code in the body of your class, e.g. the WEAPONS[0] = calls. However, you can initialize the array directly using new Type[]{} syntax. You could also use a static initializer static {} but this is not recommended.
Also, you need to use the constructor via new keyword, it's not just a method, i.e. new Weapon() not Weapon()
You cannot declare arrays using {}, i.e. new String[]{{Graphics.MG_L_NORM, Graphics.MG_R_NORM}} not {Graphics.MG_L_NORM, Graphics.MG_R_NORM}
Working version
public static final Weapon[] WEAPONS = new Weapon[] {
new Weapon("Machinegun", 10, 20, 0, 0, new String []{Graphics.MG_L_NORM, Graphics.MG_R_NORM}),
new Weapon("Plasma MG", 20, 20, 0, 0, new String []{Graphics.PMG_L_NORM, Graphics.PMG_R_NORM}),
new Weapon("Photon Cannon", 40, 5, 0, 0, new String []{Graphics.PC_L_NORM, Graphics.PC_R_NORM}),
new Weapon("Alien Destabilizer", 60, 10, 0, 0, new String []{Graphics.AD_L_NORM, Graphics.AD_R_NORM})
};
Actually I put it wrongly before but it looks like you need to call the constructor using the new operator like this.
arrayName[0] = new Weapon();
Since those classes seem somewhat static, something else to look into is using enums for this. This will help avoid complications when you have to search for a particular Weapon. A better design would be to have a WeaponType enum containing all the static immutable data in relation to a Weapon and have the Weapon class contain all the state data.
Related
Here is the Goals.java
public abstract class Goals {
private String score;
public Goals(String str) {
this.score = str;
}
String getGoals() {
return this.score;
}
void doSomething(score) {
}
}
Here is the Game.java
public class Game implements Serializable {
public String name;
public int game_num;
public int opp;
public int player;
public Goals goal;
public Game(int i, int i2, int i3) {
this.player = i;
this.game_num = i2;
this.opp = i3;
}
public Game(String str, Goals goal) {
this.name = str;
this.goal = goal;
}
}
Can we create a Serialized Object in a way that after it is deserialized and casted to Game , it will set score inside Goals.java ?
Also, can you manipulate / overwrite doSomething method if the serialized data comes from untrusted source?
In the way you are trying to manipulates your objects, I think you can do that Goals implements Serializable, and Game implements Goals:
public abstract class Goals implements Serializable{
private String score;
public Goals(String str) {
this.score = str;
}
String getGoals() {
return this.score;
}
void doSomething(score) {
}
}
for Game
public class Game extends Goals {
public String name;
public int game_num;
public int opp;
public int player;
public Game(int i, int i2, int i3) {
this.player = i;
this.game_num = i2;
this.opp = i3;
}
public Game(String str) {
//create constructor also including the properties of Goals
Super()...
}
}
As mentioned in comments, implement Goals and its implementation with Serializable and also implement default constructor in both the classes .
Working piece of code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
abstract class Goals implements Serializable{
private String score;
public Goals() {
this(null);
}
public Goals(String str) {
this.score = str;
}
String getGoals() {
return this.score;
}
void doSomething(int score) {
}
}
class Game implements Serializable {
public String name;
public int game_num;
public int opp;
public int player;
public Goals goal;
public Game(int i, int i2, int i3) {
this.player = i;
this.game_num = i2;
this.opp = i3;
}
public Game(String str, Goals goal) {
this.name = str;
this.goal = goal;
}
}
class GoalImpl extends Goals implements Serializable{
public GoalImpl() {
}
public GoalImpl(String str) {
super(str);
}
}
public class Main{
public static void main(String...s) {
Goals goal = new GoalImpl("20");
Game game = new Game("name",goal);
try
{
//Saving of object in a file
FileOutputStream file = new FileOutputStream("gamefile.ser");
ObjectOutputStream out = new ObjectOutputStream(file);
// Method for serialization of object
out.writeObject(game);
out.close();
file.close();
System.out.println("Object has been serialized");
}
catch(IOException ex)
{
ex.printStackTrace();
System.out.println("IOException is caught");
}
Game object1 = null;
// Deserialization
try
{
// Reading the object from a file
FileInputStream file = new FileInputStream("gamefile.ser");
ObjectInputStream in = new ObjectInputStream(file);
// Method for deserialization of object
object1 = (Game)in.readObject();
in.close();
file.close();
System.out.println("Object has been deserialized ");
System.out.println("score = " + object1.goal.getGoals());
}
catch(IOException ex)
{
ex.printStackTrace();
System.out.println("IOException is caught");
}
catch(ClassNotFoundException ex)
{
System.out.println("ClassNotFoundException is caught");
}
}
}
Output:
Object has been serialized
Object has been deserialized
score = 20
PS:
An advice to make score as integer as otherwise you will not be able to do basic operations like increase score or decrease score using inbuilt operators (+ , - )
Always place proper getter setter name like getScore() and setScore int this case.
Do try to make constructors in sync, for example in case of Game constructor with player id, game num and opposition is called, Game name and Goals will never be initialized, better to initialize them with default value or other good option is make another constructor accepting all parameters and then from individual constructos you can call master constructor and pass default values for those which are not passed by the calling method.
I'm stumped. I created a method called "makeBed" in the (BedRoom) class that calls another method in the (Bed) class called "make". But when I try to call the method via bedroom.makeBed(); it does not work. I put a // in the part i'm trying to get to work.
Main
public class Main {
Wall wall1 = new Wall("West");
Wall wall2 = new Wall("East");
Wall wall3 = new Wall("South");
Wall wall4 = new Wall("North");
Ceiling ceiling = new Ceiling(12, 55);
Bed bed = new Bed("Modern", 4, 3, 2, 1);
Lamp lamp = new Lamp("classic", false, 75);
BedRoom bedroom = new BedRoom("test",wall1,wall2,wall3,wall4,ceiling,bed,lamp);
bedroom.makeBed(); //bedroom.makeBed(); does not work
//It does not show the public method "makeBed" in the BedRoom class
}
BedRoom Class
public class BedRoom {
private String name;
private Wall wall1;
private Wall wall2;
private Wall wall3;
private Wall wall4;
private Ceiling ceiling;
private Bed bed;
private Lamp lamp;
public BedRoom(String name, Wall wall1, Wall wall2, Wall wall3, Wall wall4, Ceiling ceiling, Bed bed, Lamp lamp) {
this.name = name;
this.wall1 = wall1;
this.wall2 = wall2;
this.wall3 = wall3;
this.wall4 = wall4;
this.ceiling = ceiling;
this.bed = bed;
this.lamp = lamp;
}
public Lamp getLamp(){
return this.lamp;
}
public void makeBed(){ //This is the method I'm trying to access
System.out.println("Bedroom -> Making bed");
bed.make();
}
}
Bed Class
public class Bed {
private String style;
private int pillows;
private int height;
private int sheets;
private int quilt;
public Bed(String style, int pillows, int height, int sheets, int quilt) {
this.style = style;
this.pillows = pillows;
this.height = height;
this.sheets = sheets;
this.quilt = quilt;
}
public void make(){
System.out.println("Bed -< Making"); //Method I'm trying to call
}
public String getStyle() {
return style;
}
public int getPillows() {
return pillows;
}
public int getHeight() {
return height;
}
public int getSheets() {
return sheets;
}
public int getQuilt() {
return quilt;
}
}
I want to say this is it... You don't have your code wrapped into a method so it not compiling right.
public class Main {
public static void main(String[] args) {
Wall wall1 = new Wall("West");
Wall wall2 = new Wall("East");
Wall wall3 = new Wall("South");
Wall wall4 = new Wall("North");
Ceiling ceiling = new Ceiling(12, 55);
Bed bed = new Bed("Modern", 4, 3, 2, 1);
Lamp lamp = new Lamp("classic", false, 75);
BedRoom bedroom = new BedRoom("test",wall1,wall2,wall3,wall4,ceiling,bed,lamp);
bedroom.makeBed(); //bedroom.makeBed(); does not work
//It does not show the public method "makeBed" in the BedRoom class
}
}
Maybe that will work.
This is on the assumption that THIS is your class you want to initilize the whole script from, if not change public static void main(String[] args){} into public Main() {}
I am working on a java project which contains 3 classes and an object array in one of the classes. This project is ultimately supposed to move 4 entity objects around on a board by using the coordinates of the entity objects. These entity objects are stored in an array in the world class. My problem is with the array initialization in the world class. I am not sure how to set each element of the array equal to an object from the entity class and then access that object's coordinates to move it around on the board. The coordinates for the entity objects are initially set at 20x30 in a default constructor. Here is my code:
public class entity {
private int xcoordinate;
private int ycoordinate;
private String name;
private char symbol;
public entity(){
xcoordinate = 20;
ycoordinate = 30;
}
private entity(int newxcoor, int newycoor, String newname, char newsymbol){
xcoordinate = newxcoor;
ycoordinate = newycoor;
name = newname;
symbol = newsymbol;
}
public int getXCoor(){
return xcoordinate;
}
public int getYCoor(){
return ycoordinate;
}
}
public class world {
private entity[] ObArray = new entity[4];
public world(){
world test = new world();
}
public void draw(){
for (int i = 0; i < 4; i++)
{
//int x = ObArray[i].getXLoc();
//int y = ObArray[i].getYLoc();
}
}
}
public class mainclass {
public static void main(String[] args){
world worldob = new world();
//entity a = new entity();
//entity b = new entity();
//entity c = new entity();
//entity d = new entity();
worldob.draw();
}
}
My draw function and main function are not finished. After the array is initialized I will be able to finish the draw method using the entity get functions.
Thanks for your help.
That is one way of doing it. You can also define all of your entities inline like this:
private entity[] ObArray = {
new entity(0,0,"Entity1",'a'),
new entity(10,10,"Entity2",'b'),
new entity(20,20,"Entity3",'c'),
new entity(30,30,"Entity4",'d')
};
A better way may be to do an ArrayList instead of an array:
private List<entity> ObArray = new ArrayList<>();
ObArray.add(new entity(0,0,"Entity1",'a');
ObArray.add(new entity(10,10,"Entity2",'b');
ObArray.add(new entity(20,20,"Entity3",'c');
ObArray.add(new entity(30,30,"Entity4",'d');
To access each element you just need to get the element from the array and either get or set the properties you need:
ObArray[0].getXCoor();
ObArray[0].setXCoor(5);
Your problem is only creating new object of world inside world's constructor which throws stack overflow error, otherwise it is fine:
public world(){ world test = new world(); //REMOVE THIS LINE
}
You simply need to initialise the array. This can be done in the world constructor.
public world()
{
for (int i = 0; i < 4; i++)
{
ObArray[i] = new entity();
}
}
Then you can access the objects in your draw method, as you've shown:
public void draw()
{
for (int i = 0; i < 4; i++)
{
int x = ObArray[i].getXCoor();
int y = ObArray[i].getYCoor();
System.out.println("x" + x);
System.out.println("y" + y);
// Manipulate items in the array
// ObArray[i].setXCoor(10);
}
}
A more complete example, with the move functions added, and the class names capitalised:
public class Entity
{
private int xcoordinate;
private int ycoordinate;
private String name;
private char symbol;
public Entity()
{
xcoordinate = 20;
ycoordinate = 30;
}
private Entity(int newxcoor, int newycoor, String newname, char newsymbol)
{
xcoordinate = newxcoor;
ycoordinate = newycoor;
name = newname;
symbol = newsymbol;
}
public int getXCoor()
{
return xcoordinate;
}
public void setXCoor(int xcoordinate)
{
this.xcoordinate = xcoordinate;
}
public int getYCoor()
{
return ycoordinate;
}
public void setYcoor(int ycoordinate)
{
this.ycoordinate = ycoordinate;
}
public static void main(String[] args)
{
World worldob = new World();
worldob.draw();
worldob.move(0, 15, 30);
worldob.move(1, 45, 0);
worldob.move(2, 23, 27);
worldob.move(3, 72, 80);
worldob.draw();
}
}
class World
{
private final Entity[] ObArray;
public World()
{
this.ObArray = new Entity[4];
for (int i = 0; i < ObArray.length; i++)
{
ObArray[i] = new Entity();
}
}
public void move(int index, int xCoor, int yCoor)
{
if (index >= 0 && index < ObArray.length)
{
Entity e = ObArray[index];
e.setXCoor(xCoor);
e.setYcoor(yCoor);
}
}
public void draw()
{
for (Entity e : ObArray)
{
int x = e.getXCoor();
int y = e.getYCoor();
System.out.println("x" + x);
System.out.println("y" + y);
}
}
}
Good Day,
I am writing a custom event handler in Java. I have a class called BoogieCarMain.java that instantiates three instances of a type called BoogieCar. Whenever any of the three instances exceeds a certain speed limit, then an event should be fired off. The code I currently have is working, so here is what I have:
// BoogieCar.java
import java.util.ArrayList;
public class BoogieCar {
private boolean isSpeeding = false;
private int maxSpeed;
private int currentSpeed;
private String color;
BoogieSpeedListener defaultListener;
public BoogieCar(int max, int cur, String color) {
this.maxSpeed = max;
this.currentSpeed = cur;
this.color = color;
}
public synchronized void addSpeedListener(BoogieSpeedListener listener) {
defaultListener = listener;
}
public void speedUp(int increment) {
currentSpeed += increment;
if (currentSpeed > maxSpeed) {
processSpeedEvent(new BoogieSpeedEvent(maxSpeed, currentSpeed, color));
isSpeeding = true;
} else {
isSpeeding = false;
}
}
public boolean getSpeedingStatus() {
return isSpeeding;
}
private void processSpeedEvent(BoogieSpeedEvent speedEvent) {
defaultListener.speedExceeded(speedEvent);
}
}
// BoogieCarMain.java
import java.util.ArrayList;
public class BoogieCarMain {
public static void main(String[] args) {
BoogieCar myCar = new BoogieCar(60, 50, "green");
BoogieCar myCar2 = new BoogieCar(75, 60, "blue");
BoogieCar myCar3 = new BoogieCar(65, 25, "pink");
BoogieSpeedListener listener = new MySpeedListener();
myCar.addSpeedListener(listener);
myCar2.addSpeedListener(listener);
myCar3.addSpeedListener(listener);
myCar.speedUp(50); // fires SpeedEvent
System.out.println(myCar.getSpeedingStatus());
myCar2.speedUp(20);
System.out.println(myCar2.getSpeedingStatus());
myCar3.speedUp(39);
System.out.println(myCar3.getSpeedingStatus());
}
}
// BoogieSpeedListener.java
public interface BoogieSpeedListener { // extends java.util.EventListener
public void speedExceeded(BoogieSpeedEvent e);
}
// MySpeedListener.java
public class MySpeedListener implements BoogieSpeedListener {
#Override
public void speedExceeded(BoogieSpeedEvent e) {
if (e.getCurrentSpeed() > e.getMaxSpeed()) {
System.out.println("Alert! The " + e.getColor() + " car exceeded the max speed: " + e.getMaxSpeed() + " MPH.");
}
}
}
// BoogieSpeedEvent.java
public class BoogieSpeedEvent { // extends java.util.EventObject
private int maxSpeed;
private int currentSpeed;
private String color;
public BoogieSpeedEvent(int maxSpeed, int currentSpeed, String color) {
// public SpeedEvent(Object source, int maxSpeed, int minSpeed, int currentSpeed) {
// super(source);
this.maxSpeed = maxSpeed;
this.currentSpeed = currentSpeed;
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public int getCurrentSpeed() {
return currentSpeed;
}
public String getColor() {
return color;
}
}
My question is: While this code works, I would like the BoogieCar type to notify BoogieCarMain directly without me have to "poll" the BoogieCar type by having to invoke the getSpeedingStatus() method.
In other words, perhaps defining a variable in BoogieCarMain.java that changes whenever one of the three cars exceeds its predefined speed limit. Is it possible to have the BoogieCar type set the variable?
Is there a cleaner way to do this?
TIA,
coson
Callbacks are ideal for this scenario.
// BoogieCarMain provides a sink for event-related information
public void handleSpeeding(BoogieCar car) {
System.out.println(car.getSpeedingStatus());
}
// MySpeedListener knows about an object that wants event-related information.
// I've used the constructor but an addEventSink method or similar is probably better.
public MySpeedListener(BoogieCarMain eventSink) {
this.eventSink = eventSink;
}
// MySpeedListener handles events, including informing objects that want related information.
// You decide if the event is an appropriate type for the sink to know about.
// Often it isn't, and instead your listener should pull the relevant info out of the event and pass it to the sink.
public void speedExceeded(BoogieSpeedEvent e) {
if (e.getCurrentSpeed() > e.getMaxSpeed()) {
// I've taken the liberty of adding the event source as a member of the event.
eventSink.handleSpeeding(e.getCar());
}
}
Let's just get down to business. I have this line of code:
public static Tile[] tiles = new Tile[400];
which is giving me the following error in eclipse
Syntax error on token ";", { expected after this token
Tile is a class in the same project and package of which I want to make an array because I can't think of any other way to do the things in the rest of the program...
I have looked on google and on stackoverflow, but can't find the answer. Could someone explain to me what I am doing wrong?
Thanks in advance,
Dirk.
EDIT: Here is the Tile class:
package com.mrdls.invade;
public class Tile {
public String name = "";
public int id = 0;
public boolean passable = false;
public Tile(String name, int id){
this.name = name;
this.id = id;
if(name == "air"){
passable = true;
}
}
}
EDIT2, here is the TilesBlocks class
package com.mrdls.invade;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class TilesBlocks {
public static BufferedImage tilesetBlocks;
public static int pixelsPerTile = 20;
public int[] ints = new int[20];
public Tile[] tiles = new Tile[400];
tiles[0] = new Tile("air", -1);
/*public static final Tile earth = new Tile("earth", 0);
public static final Tile stone = new Tile("stone", 1);
public static final Tile cobblestone = new Tile("cobblestone", 2);
public static final Tile sand = new Tile("sand", 3);
public static final Tile sandstone = new Tile("sandstone", 4);
public static final Tile grass = new Tile("grass", 5);
public static final Tile woodLog = new Tile("log", 6);
public static final Tile leaves = new Tile("leaves", 7);
public static final Tile pumpkin = new Tile("pumpkin", 8);
public static final Tile melon = new Tile("melon", 9);
public static final Tile pumpkinCarved = new Tile("carved pumpkid", 10);
public static final Tile copperOre = new Tile("copper ore", 20);
public static final Tile tinOre = new Tile("tin ore", 21);
public static final Tile ironOre = new Tile("iron ore", 22);
public static final Tile silverOre = new Tile("silver ore", 23);
public static final Tile goldOre = new Tile("gold ore", 24);
public static final Tile diamondOre = new Tile("diamond ore", 40);
public static final Tile emeraldOre = new Tile("emerald ore", 41);
public static final Tile rubyOre = new Tile("ruby ore", 42);
public static final Tile sapphireOre = new Tile("sapphire ore", 43);*/
public TilesBlocks(){
try{
TilesBlocks.tilesetBlocks = ImageIO.read(Tile.class.getResourceAsStream("/tileset_terrain.png"));
}catch(Exception e){
}
}
}
tiles[0] = new Tile("air", -1);
You can't do this in your class. You need to assign it in your constructor.
Read the difference between initialization and assignment.
Initialization of field belongs outside a method, but of course is encapsulated by a class.
Assignment belongs in a method.
or you can initialize like so:
Tiles []tiles = new Tiles[]{new Tile("air",-1)} ;
And use .equals not ==
This complete class works fine. I don't see any error in your class and usage.
Here is the complete class
package com.test;
public class Tile {
public static Tile[] tiles = new Tile[400];
public String name = "";
public int id = 0;
public boolean passable = false;
public Tile(String name, int id) {
this.name = name;
this.id = id;
if (name.equals("air")) {
passable = true;
}
}
}
Click on Red error message, Most likely you are going to see 'Suppress' or 'Clear lint markers' Eclipse sometimes record an error (as you type) and doesn't clear the marks.
Clear Lint Markers and see if the error is gone