I want to have a ****seperate Class**** to have the sounds and i want to call upon that class to play the sounds, but if there is a better way, pls tell me.
Story (can be skipped):
First i used AudioClips that were stored in final statics that i called everytime i needed the sound to play. For single stuff like the background music, this was perfect, but if i wanted to use the sound more than once at a time, like my turrets that shoot, they sometimes play the sound perfectly and sometimes it gets restarted or it is canceled completely.
Then i switched to Clips after reading trhough some posts and that some guy found a solution by doin Clips, after using a tutorial.
Sound Class:
package Game.main;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
public class Sound {
public static final Sound backgroundMusic4 = new Sound("/backgroundMusic4.wav");
public static final Sound blockDestroy = new Sound("/blockDestroy.wav");
public static final Sound bulletHit = new Sound("/bulletHit.wav");
public static final Sound button = new Sound("/button.wav");
public static final Sound camera = new Sound("/camera.wav");
public static final Sound teleporter = new Sound("/teleporter.wav");
public static final Sound turretShot = new Sound("/turretShot.wav");
public static final Sound walking = new Sound("/walking.wav");
public static Clip clip;
public Sound(String fileLocation){
Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();
Mixer mixer = AudioSystem.getMixer(mixInfos[0]);
DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);
try{
clip =(Clip) mixer.getLine(dataInfo);
}catch(Exception e){
e.printStackTrace();
}
try{
URL soundURL = getClass().getResource(fileLocation);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundURL);
clip.open(audioStream);
}catch(Exception e){
e.printStackTrace();
}
}
public void play(){
clip.loop(clip.LOOP_CONTINUOUSLY);
}
public void playOnce(){
clip.start();
}
public void stop(){
clip.stop();
}
}
Turret Class (As example) [Only the last method "shoot()" matters]:
package Game.main.IngameObjects;
import java.applet.AudioClip;
import java.awt.Graphics;
import java.awt.Rectangle;
import Game.main.Controller;
import Game.main.Game;
import Game.main.GameObject;
import Game.main.Sound;
import Game.main.Textures;
import Game.main.classes.EntityC;
public class Turret extends GameObject implements EntityC{
private boolean activated;
private String direction;
private Game game;
private Textures tex;
private Camera activationCam;
private Controller c;
private long lastShot=0;
public Turret (double x, double y, Textures tex, Game game, Controller c, String direction){
super(x,y);
this.game=game;
this.tex=tex;
this.c=c;
if(!direction.equalsIgnoreCase("up") && !direction.equalsIgnoreCase("down") && !direction.equalsIgnoreCase("left") && !direction.equalsIgnoreCase("right")){
System.err.println("ERROR 1: Wrong Direction in Constructor in Class \"java.Game.main.IngameObjects.Camera\"");
System.exit(1);
}else{
this.direction=direction;
}
}
public Turret (double x, double y, Textures tex, Game game, Controller c , Camera cam, String direction){
super(x,y);
this.game=game;
this.tex=tex;
this.c=c;
if(!direction.equalsIgnoreCase("up") && !direction.equalsIgnoreCase("down") && !direction.equalsIgnoreCase("left") && !direction.equalsIgnoreCase("right")){
System.err.println("ERROR 1: Wrong Direction in Constructor in Class \"java.Game.main.IngameObjects.Camera\"");
System.exit(1);
}else{
this.direction=direction;
}
this.activationCam=cam;
}
public void tick() {
if(activationCam==null){
shoot();
}else if(activationCam.getActivated()){
shoot();
}
}
public void render(Graphics g) {
if(activated){
if(direction.equalsIgnoreCase("up")){
g.drawImage(tex.turretActi.get(0), (int)x, (int)y, null);
}else if(direction.equalsIgnoreCase("down")){
g.drawImage(tex.turretActi.get(1), (int)x, (int)y, null);
}else if(direction.equalsIgnoreCase("left")){
g.drawImage(tex.turretActi.get(2), (int)x, (int)y, null);
}else if(direction.equalsIgnoreCase("right")){
g.drawImage(tex.turretActi.get(3), (int)x, (int)y, null);
}
}else{
if(direction.equalsIgnoreCase("up")){
g.drawImage(tex.turretDeac.get(0), (int)x, (int)y, null);
}else if(direction.equalsIgnoreCase("down")){
g.drawImage(tex.turretDeac.get(1), (int)x, (int)y, null);
}else if(direction.equalsIgnoreCase("left")){
g.drawImage(tex.turretDeac.get(2), (int)x, (int)y, null);
}else if(direction.equalsIgnoreCase("right")){
g.drawImage(tex.turretDeac.get(3), (int)x, (int)y, null);
}
}
}
public Rectangle getBounds() {
return new Rectangle((int)x, (int)y, 32, 32);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public void activate() {
activated=true;
}
public void deactivate() {
activated=false;
}
public boolean getActivated() {
return activated;
}
public void setX(double x) {
this.x=x;
}
public void setY(double y) {
this.y=y;
}
public void shoot(){
if(System.currentTimeMillis() - lastShot >= 1000){
Sound.turretShot.playOnce();
lastShot = System.currentTimeMillis();
c.addEntity(new Bullet(x,y,game,tex,c,direction));
}
}
}
Now i have the problem that the turret Shoots once and the sound plays and then its gone (example video: https://youtu.be/q8TR2nR8hUI ). I tried to give every object his own Sound Clip but that very wastefull and last time it reduced my ticks and fps to 1 every 5 seconds or so.
Thats why i wanted to ask for a solution or some heplfull ideas and code.
I red something about and Byte array and dataStreamOutput, or that i could clone the clips but i cant get either one to work.
I am sorry for my somehow bad english, i am german so pls overlook any mistake (unless you can't read it)
Java Clips are not set up for concurrent playback. At best, and this is often done, you can take a playing Clip and reset it back to the start and restart it (i.e., interrupting it before it completes). The next logical alternative is to instantiate multiple copies of the Clip (as suggested in the comment by VGR) and write a layer of code to manage these instances.
There are a couple libraries that allow concurrent playback of clip-equivalents. TinySound is publicly available via github. There is a major thread about it by the dev at java-gaming.org. Several members there have made successful use of this library.
I've been working on my own sound library, and it includes concurrent playback of clip-equivalents. I haven't opened my sources, yet, though. But if you wish to explore writing your own code to do this, I'm happy to reply on a thread either here or at java-gaming.org. The basic plan is to store the data in an array (can be either as bytes or as PCM normals or whatever) and play it back via a SourceDataLine (SDL) that is set to read from this data file. There is also the option of either running several of these through a single SDL output line (mixing them together before outputting) or giving each its own SDL. It is a bit of work to set this all up, hence many prefer to find a library.
Related
I am attempting to create my own version of the well known game Space invaders. I am using zetcode as a point of reference (not a direct copy and paste) http://zetcode.com/tutorials/javagamestutorial/spaceinvaders/
However I seem to be a bit stuck. Namely on the use of KeyAdapters and the MVC design pattern. According to zetcode tutorial, the protected int dx changes when KeyPressed is pressed and once again when it is released, however I not seeing any movement nor value change outside of the KeyPressed and Keyreleased methods.
I carried out some simple checks
1: Does the "player" graphics move without key input at all (basically do graphic updates work)? - Yes, I changed the "move()" method within player to simply do a "x--; " and visibly see movement on screen
2: Does the value "dx" change at all? - Kinda, from Keypressed method, I can use System.out.println(""+dx); to return the value and visibly see, from within the method that dx changes, but not outside of this method, suggesting that the value changes are only occurring local to this method, which in my opinion is bizarre.
My ask from the community is the following:
Is this an issue with concurrency (or should I say, 2 references to the "dx" value stored in memory but only 1 reference is getting updated or there something else funky going on in my code that I am missing?
package spaceInvaders;
import java.awt.event.KeyEvent;
public class Player extends IngameObjects implements Commons {
private int startX = 250;
private final int startY = 150;
public Player(){
initPlayer();
}
public void initPlayer(){
this.setX(startX);
this.setY(startY);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public void move(){
this.x += dx;
if (x <= 2) {
x = 2;
}
if (x >= 400 - 2 * 10) {
x = 400 - 2 * 10;
}
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
dx = -1;
System.out.println(""+dx);
}
if(key == KeyEvent.VK_RIGHT){}
if(key == KeyEvent.VK_ESCAPE){
System.exit(0);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
this.x = -1;
}
if(key == KeyEvent.VK_RIGHT){}
}
}
package spaceInvaders;
public class IngameObjects {
protected int x;
private int y;
protected int dx;
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
package spaceInvaders;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
private Player player;
private Thread animator;
private boolean isRunning;
public GamePanel(){
this.setBackground(Color.BLACK);
this.setDoubleBuffered(true);
addKeyListener(new TAdapter());
setFocusable(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
drawPlayer(g);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void drawPlayer(Graphics g){
g.setColor(Color.GREEN);
g.fillRect(player.getX(), player.getY(), 50, 50);
}
#Override
public void run() {
isRunning = true;
long startTime, timeDiff, sleepTime;
startTime = System.currentTimeMillis();
while(isRunning){
repaint();
gameUpdate();
timeDiff = System.currentTimeMillis() - startTime;
sleepTime = 5 - timeDiff;
try{
Thread.sleep(sleepTime);
}
catch(InterruptedException ex){
System.exit(0);
}
startTime = System.currentTimeMillis();
}
}
#Override
public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
player = new Player();
if(animator == null || !isRunning){
animator = new Thread(this);
animator.start();
}
}
public void gameUpdate(){
player.move();
}
private class TAdapter extends KeyAdapter{
#Override
public void keyPressed(KeyEvent e) {
System.out.println(""+player.getX());
player.keyPressed(e);
}
#Override
public void keyReleased(KeyEvent e) {
player.keyReleased(e);
}
}
}
thanks for the swift responses, much appreciated. After x amount of time (leaving it as x due to embarrassment) I have actually found a problem, quite a serious one actually.
1: Duplicated TAdapter on another class which extended the JFrame
2: 2 classes (GamePanel (which extends JPanel) and class (poorly named) Main (which extends JFrame) both have setFocusable(true);
Regarding Vince's reply, yes you are correct, as an attempt to debug my own code I actually replaced what was originally dx, for x. Obviously neither worked which led me to suspect there was a coding issue elsewhere.
Regarding MadProgrammer's reply, thanks, I am not familiar with Key bindings, I have not been programming in a very long time, which is the reason why I am making my own version of space invaders, so I can not only get back into programming but improve my knowledge, I will look at key bindings, even though you don't specify what is wrong with KeyListeners, I will study the differences. Regarding dispose, yep once again, not very familiar with the uses, i thought it was another way of refreshing the graphics, I will look into this.
in summary, where did I go wrong:
Duplicated TAdapter in a dedicated class for JFrame and another one
in JPanel
Duplicated requests for "focus" setFocusable(true);
Use KeyListener instead of key bindings (not sure why: research required)
Use of the dispose() method
Changing value of x rather than dx
This question can be considered resolved at this point, thanks
I testing to implement graphics into MVC structure but Im a bit stuck. Here is what I got so far. For now I just want to get the red ball to bounce back and forth. And use the button start to start the thread and button stop to stop the thread that runs the GameLoop in the controller.
But I think Im mixing this up a bit. Would very much appreciate some feedback!
Heres what I got so far:
GameModell
suppose to controll the bouncing. If the location of the ball is under 40 px or above 80 px - multiply the locationX with -1 to make the ball change direction
GameView
Here Im putting the labels on a JFrame. I also want to display the buttons start and stop to controll the thread but I guess they are hidden by the JPanel in TheGraphics class
GameController
Starts and stops the thread with ActionListeners. Contains the GameLoop
TheGraphics
Paints the ball and controll the direction
I guess I got a lot of thing that are all wrong but this is the best I can do at the moment. Would very much apreciate some help!
Thanks!
MAIN:
public class MVCgame {
public static void main(String[] args) {
GameModel gm = new GameModel();
GameView gv = new GameView();
GameController gc = new GameController(gm, gv);
}
}
MODEL:
public class GameModel {
private int multi = 1;
public void setMulti(int locX) {
if(locX < 40 || locX > 80) {
multi = multi * -1;
}
}
public int multi() {
return multi;
}
}
VIEW:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameView extends JFrame {
private JPanel jp = new JPanel();
private JButton start = new JButton("Start");
private JButton stop = new JButton("Stop");
TheGraphics gr = new TheGraphics();
public GameView() {
add(jp);
add(gr);
jp.add(start);
jp.add(stop);
setSize(250, 250);
setVisible(true);
}
public void addListener(ActionListener theListener) {
start.addActionListener(theListener);
stop.addActionListener(theListener);
}
public JButton getStart() {
return start;
}
public JButton getStop() {
return stop;
}
// GUESS I SHOULD PUT THIS IN THE VIEW???
public void paintEllipse(Graphics theG) {
Graphics2D g2d = (Graphics2D) theG;
g2d.setColor(new Color(255, 0, 0));
g2d.fillOval(0, 0, 10, 10);
}
}
CONTROLLER:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GameController implements Runnable {
GameView gv;
GameModel gm;
private Thread thread;
private boolean running = false;
public GameController(GameModel gm, GameView gv) {
this.gv = gv;
this.gm = gm;
gv.addListener(theListener);
start();
}
ActionListener theListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == gv.getStart()) {
start();
System.out.println("PLAY = ");
} else if (e.getSource() == gv.getStop()) {
stop();
System.out.println("STOP = ");
}
}
};
public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop() {
thread.interrupt();
running = false;
}
// GameLoop
public void run() {
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 10) {
// tick();
delta--;
// repainting the graphics
gv.gr.drawer();
gm.setMulti(gv.gr.drawer());
System.out.println("gv.gr.drawer() = " + gv.gr.drawer() + " gm.multi() " + gm.multi());
// I want to use this value in the model to change the direction
}
if (running) {
}
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frames);
frames = 0;
}
}
}
}
THE GRAPHICS:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class TheGraphics extends JPanel {
private int locX = 40;
public TheGraphics() {
}
public int drawer() {
locX++;
repaint();
return locX;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(255, 0, 0));
g2d.fillOval(locX, 30, 10, 10);
}
}
GameModell suppose to controll the bouncing. If the location of the ball is under 40 px or above 80 px - multiply the locationX with -1 to make the ball change direction
public void setMulti(int locX) {
if(locX < 40 || locX > 80) {
multi = multi * -1;
}
}
Really bad idea. You should always check position and direction (sign(speed)). Otherwise, your object might get stuck out of bounds always changing direction without moving from place forever.
Apart from this, using the MVC concept is overkill in my eyes and shouldn't be used in such a small project nor in a game. In a game, you should more or less put all three together. Of course you can, but the advantages and disadvantages of the MVC concept don't fit the needs of a game in many ways (except for the GUI, perhaps).
Your main loop might look something like this (you kind of did this already, but why is the tick() commented out in your code?):
while (running) {
update(); // Update all game objects
paint(); // Paint them all
}
Each game object will have its own update() and paint() implementation. You absolutely need to separate the logic of update and paint, even if they are in the same class. So this one:
public int drawer() {
locX++;
repaint();
return locX;
}
is an absolute no-go.
Edit: (Referring your update answer)
You are using the method location() for different purposes. According to the Java name convention, you should rename it getLocation() and setLocation() depending on the use to clarify the code.
(Even if this is not really MVC anymore, I'd let GameFrame implement ActionListener instead of specifying it as variable of GameController.)
One thing you should really change is this one:
private int locX = 0;
public void location(int loc) {
this.locX = (int) loc;
}
Basically, you are duplicating the location value every frame and create unused redundant data. Another problem is, that this might work fine for only one variable, but what if you add more than the position to your model later on? Instead TheGraphics has to render on an instance of the data model, not its values. As long you are using one GameModel
private GameModel model; // set value once at initialisation
and rendering its values in paintComponent will work fine, but if you want to add more than one GameModel (handling GameModel more like a GameObjectModel), you will need to pass it as parameter in the paint method.
public void update() {
repaint();
}
Remove it and try getting around without. A method called from one place forwarding to a different method is a bad idea most of the time, especially if it obfuscates the functionality with a different name.
gv.gr.update();
gv.gr.location(gm.location());
You are first repainting your image and then setting the location? Basically, your game runs one frame behind all the time. Swap that order.
gv.gr.location(gm.location());
gv.gr.repaint();
Will be fine (I already said about location()).
I have a simple physics loop that does a calculation for a time interval, waits for the interval to pass, and then renders the results on the screen. It's very simple code (even though the timing is probably wrong, but that's exactly what I'm trying to learn about) and works well when I am moving the mouse around the screen.
package physicssim;
import java.awt.Graphics;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PhysicsSim extends JFrame {
private static class PhysicsObject {
public PhysicsObject(double x, double y, double v_x, double v_y) {
this.x = x;
this.y = y;
this.v_x = v_x;
this.v_y = v_y;
}
public double x;
public double y;
public double v_x;
public double v_y;
}
PhysicsObject particle;
boolean running = true;
DrawPane drawPane;
public PhysicsSim() {
particle = new PhysicsObject(10,10, .1, .2);
drawPane = new DrawPane(particle);
this.setSize(800,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setContentPane(drawPane);
this.setVisible(true);
}
private static class DrawPane extends JPanel {
PhysicsObject p;
public DrawPane(PhysicsObject p) {
this.p = p;
}
#Override
public void paint(Graphics g) {
super.paint(g); //To change body of generated methods, choose Tools | Templates.
g.fillOval((int)p.x, (int) p.y, 10, 10);
}
}
public void start() {
int FPS = 60;
long TIME_BETWEEN_FRAMES_NS = 1000000000/FPS;
// Initial draw
drawPane.repaint();
long lastDrawTime = System.nanoTime();
while(running) {
// Update physics
particle.x+=particle.v_x*(TIME_BETWEEN_FRAMES_NS*.0000001);
particle.y+=particle.v_y*(TIME_BETWEEN_FRAMES_NS*.0000001);
// While there is time until the next draw wait
while(TIME_BETWEEN_FRAMES_NS > (System.nanoTime()-lastDrawTime)) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(PhysicsSim.class.getName()).log(Level.SEVERE, null, ex);
}
}
drawPane.repaint();
long currentTime = System.nanoTime();
System.out.println(currentTime - lastDrawTime);
lastDrawTime = currentTime;
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
PhysicsSim sim = new PhysicsSim();
sim.start();
}
}
The last bit about printing the time difference was just a sanity check to make sure that it was in fact calling around the requested interval. The results are fairly consistent so I don't see why there should be any choppiness.
As I mentioned above, this code works great if I a moving the mouse around the screen, everything is smooth.
If I am not moving the mouse it becomes very choppy until I start moving the mouse over the application.
I assume this is something simple, but I hope that you guys can help me. Thank you.
Alright, it looks like my problem was I was drawing directly to g in paint(). After replacing with the following everything worked correctly.
#Override
public void paint(Graphics g) {
BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_3BYTE_BGR);
img.getGraphics().fillOval((int) p.x, (int) p.y, 10, 10);
g.drawImage(img, 0, 0, null);
}
I was considering deleting this code snippet because it's rough and shameful, but maybe it will help someone else. Happy coding.
I've got a problem with the jar file that's supposed to run the game i'm trying to create.
It's basicaly a major issue with the loading of Images so that it works in the Jar aswell as Netbeans' environment.
i'm currently using
imgIcon = new ImageIcon(Core.classLoader.getResource("Images/Boss1.png"));
img = imgIcon.getImage();
this works just fine 4 all my enemies the level background and the shots my various object fire. But if I try to use it on my player class the JAR file becomes unexecutablem, even thought it still works perfectly in NetBeans. So did i screw up in the Player or somewhere else because the Images seem to load with this particular code and only if it's also in the player the jar is unusable.
Player class to be seen here(I think it's got to be a problem in here that i overlooked over and over):
package Entity;
import Shots.PlayerShot;
import bullethellreloaded.Core;
import bullethellreloaded.Screen;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Player extends Entity{
public int x,y; // public used to make an easy mouse controll;
int xDirection, yDirection;
int health;
private Image img;
private ImageIcon imgIcon;
private Rectangle hitbox;
public static ArrayList shots;
public Player(){
x = 250;
y = 400;
shots = new ArrayList();
health = 5;
imgIcon = new ImageIcon(Core.classLoader.getResource("Images/spaceship (Redshrike,Stephen Challener).png"));
img = imgIcon.getImage();
}
#Override
public void move(){
x += xDirection;
y += yDirection;
// Wallcollision detection, needs to be ajusted for the size of the object.
if(x <= 0)
x = 0;
if(x >= Screen.getScreenWidth())
x = Screen.getScreenWidth();
if(y <= 0)
y = 0;
if(y >= Screen.getScreenHeight())
y = Screen.getScreenHeight();
}
public void setXDirection(int xdir){
xDirection = xdir;
}
public void setYDirection(int ydir){
yDirection = ydir;
}
#Override
public Image getImage(){
return img;
}
#Override
public ImageIcon getImageIcon(){
return imgIcon;
}
#Override
public int getX(){
return x;
}
#Override
public int getY(){
return y;
}
#Override
public Rectangle getHitbox(){
return hitbox;
}
public static ArrayList getShots(){
return shots;
}
public void fire(){
PlayerShot shot = new PlayerShot(getX(), getY()-getImageIcon().getIconHeight()/2, 0, 1, 1,Core.classLoader.getResource("Images/PlayerShot.png"));
shots.add(shot);
}
#Override
public void removeHitbox(){
hitbox = null;
}
#Override
public Rectangle setHitbox(){
int width = getImageIcon().getIconWidth();
int height = getImageIcon().getIconHeight();
hitbox = new Rectangle(getX()+width/2-5, getY()+height/2-5, 1, 1);
return hitbox;
}
public void takeDamage(int dmg){
health -= dmg;
}
public int getHealth(){
return health;
}
drawn in my screen class which is an extended JFrame in the paintComponent that's invoked by the paint(doublebuffering and stuff^^)
in the following code segment:
}else{
g.drawImage(testlevel.getImage(),0,0,this);
g.drawImage(player.getImage(),player.getX(),player.getY(),this);
// painting the Score
g.setColor(Color.white);
g.setFont(new Font("Arial",Font.BOLD,14));
g.drawString("Score: "+ Score.getScore(), getScreenWidth()-100, 50);
// painting out the content of the ArrayLists shots, enemies, enemyShots
try{
for (int i = 0; i < Player.shots.size(); i++){
PlayerShot s = (PlayerShot) Player.shots.get(i);
if (s.getDeleted() != true){
g.drawImage(s.getImage(), s.getX(), s.getY(), this);
}
}
for (int i = 0; i < Enemy.enemies.size(); i++){
Enemy e = (Enemy) Enemy.enemies.get(i);
if (e.getDestroied() != true){
g.drawImage(e.getImage(), e.getX(), e.getY(), this);
}
}
for (int i = 0; i < Enemy.enemyShots.size(); i++){
EnemyShot es = (EnemyShot) Enemy.enemyShots.get(i);
if (es.getDeleted() != true){
g.drawImage(es.getImage(), es.getX(), es.getY(), this);
}
}
}catch(Exception e){}
}
repaint();
}
I hope thats enough information, if that's not the case please let me know.
EDIT:
The question is more like is there another way that might work with my programm or what did i screw up to get this useless JAR thats not even starting.
changeing this (this path only works in netbeans the jar can't find it with this path)
imgIcon = new ImageIcon("src/Images/spaceship (Redshrike,Stephen Challener).png");
to this:
imgIcon = new ImageIcon(Core.classLoader.getResource("Images/spaceship (Redshrike,Stephen Challener).png"));
makes the JAR not runnable (not even a process in the background) whereas it worked just fine with the old path except the fact that the player didn't had an image.
You should pack the resources into the final Jar.
For Eclipse there's a plugin called FatJar that does that (in newer Eclipse versions it's embedded as the option Export>Runnable Jar File).
Usually compilers will not pack resources into the bundle.
I found it out myself, its quite the ridiculous thing.
The Image's name seems to be to long 4 the classLoader if it's used in a jar shorting down the name of the Image let's the program run ^^
AnyWays thx to the ones trying to help me and to the JAR file that reminded me of looking into the simple stuff 1.
Snake
Alright, now I am working on a small derp-ish game based on Brownian motion, and I am working on a hit-wall function for the particles, but it isn't working. Basically, I am expressing the direction of the particles in radians, and whenever it hits a wall, I add Pi radians to the direction to flip it, but for some reason, it either isn't getting called or not working. These are the peices of code I have, any suggestions are welcome.
import java.awt.*;
public class Particle implements Actor {
protected double xPos;
protected double yPos;
protected Velocity v;
protected Color hue;
protected boolean needsUpdate;
public Particle(){
this((Math.random()*500),(Math.random()*500),new Velocity((int)(Math.random()*500),(Math.random()*Velocity.TAU)));
}
public Particle(double x, double y, Velocity vel){
xPos=x;
yPos=y;
v=vel;
hue=Color.red;
needsUpdate=false;
}
public void draw(Graphics g) {
g.setColor(hue);
g.fillOval((int)xPos, (int)yPos, 16, 16);
}
public void act() {
xPos+=v.getSlopefromDirection();
yPos+=1;
}
public void onHitWall(int dir) {
v.setDirection((v.getDirection()+Math.PI)%(Math.PI*2));
}
public void onHitOther(Actor other) {
}
public boolean canCollide() {
return true;
}
public int getLeftX() {
return (int)xPos;
}
public int getRightX() {
return (int)xPos+4;
}
public int getTopY() {
return (int)yPos;
}
public int getBottomY() {
return (int)yPos+4;
}
}
And this is the class I am using to display it:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import static java.lang.System.out;
public class Feild extends JFrame{
protected ArrayList<Actor> actors;
private final int size=500;
protected Thread th;
public Feild(ArrayList<Actor> a){
super("A Brownian Love Story");
setSize(size, size);
actors=a;
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
th = new Thread();
while(true){
paint(getGraphics());
}
}
public void paint(Graphics g){
super.paint(g);
//g.fillRect(0, 0, 500, 500);
for(int i=0;i<actors.size();i++){
if(actors.get(i).getLeftX()<=0)
actors.get(i).onHitWall(1);
if(actors.get(i).getRightX()>=500)
actors.get(i).onHitWall(2);
if(actors.get(i).getTopY()<=0)
actors.get(i).onHitWall(1);
if(actors.get(i).getBottomY()>=500)
actors.get(i).onHitWall(2);
actors.get(i).act();
actors.get(i).draw(g);
}
for(int i=0;i<1000;i++){out.println(i);}
}
}
So i tried changing the paint function to checking for collisions after acting, and it still looks like onHitWall is getting skipped over, even though after putting in a print statement it isn't.
The problem you have is that your particles will move until they hit a wall, and then the next time you go through the look, they will still be in the wall, turn around again, and continue going into the wall.
If you check for collisions after your act() function this should solve the problem.
They will go into the wall, see they are in the wall, and turn around. The next loop, they will move back out of the wall, and continue on.