I'm making a 2D Java game and I'm trying to figure out how to generate an image every few seconds(2 or 3) with the y axis picked randomly from an array of numbers. I don't know how to make the more than 1 of the same image appear on the screen at once, making a timer, or getting a random number out of an array.
Can someone please help me with this? I've been stuck on this for about 3 weeks, also some tips on collision would be appreciated.
*Overall I'm trying to have images generate at a y that is randomly picked from a array
"int[] blocky = {0, 29, 50, 79, 109, 138, 168, 204, 222, 248, 276, 304, 334, 363, 393, 418, 443}; "
Assuming your array of numbers looks like this, initialized somewhere in your class:
int[] numbers = new int[]{ 123, 321, 456, 765, 923, 931 };
You can create a method looking like this:
private int getRandomNumberFromArray(){
int min = 0;
int max = numbers.length;
return numbers[min + (int)(Math.random() * ((max - min) + 1))];
}
Then you could call that method like this:
int randomNumberFromArray = getRandomNumberFromArray();
Look into this thread for a detailed explanation of Java's Random implementation.
As for your other problems, I'm not quite sure what you are trying to accomplish. Please provide some more details.
Update
With your OP updated, I think I have a better idea of what you're trying to do. Allow me to revise.
First, for getting images displayed with Slick2D, here is a good, short video tutorial. I recommend you check his series on the subject, as they are very clear and concise.
As for your timer, I found this piece of code here.
int time;
public void update(GameContainer container, int delta) {
time += delta;
}
public void render(GameContainer container, Graphics g) {
g.drawString("Time : " + time/1000, 100, 100);
}
This will draw a simply timer that on the screen at x=100, y=100 that updates itself. This is something you could use for test purposes. As for your random interval, you can expand on the above code like this.
int time;
int deadline; // initialize this somewhere in the start of your game
public void update(GameContainer container, int delta) {
time += delta;
}
public void render(GameContainer container, Graphics g) {
g.drawString("Time : " + time/1000, 100, 100);
// if the current time has passed the deadline, do something
if(time > deadline){
int min = 2;
int max = 3;
deadline = time + ((min + (int)(Math.random() * ((max - min) + 1))) * 1000); // reset the interval timer
// draw the image
int x = 100;
int y = getRandomNumberFromArray(); // this is the method I provided in my first part of the answer
Image img = new Image("path/file.png");
g.drawImage(img, x, y) // image file, x, y
}
}
This piece of code creates a deadline that functions as a random interval timer. The deadline is a summation of the current time, to which a number between 2 and 3 will be added (multiplied with 1000, because time is kept in milliseconds). When the current time surpasses this deadline, a random image will be created.
As for displaying multiple images, I would refer to the previously linked tutorial. I think this could be accomplished by keeping track of the images in an ArrayList. Then rendering all of those images in the render() method. But I'm not quite sure since I only know a few basics of Slick2D.
I haven't tested any of this, but I hope to have pointed you into the right direction.
Update 2
As for the recommendation in the comment, this would be a way of implementing that.
ArrayList<DrawnImage> images; // make sure you initialize this at the beginning as: images = new ArrayList<Image>();
int time;
int deadline; // initialize this somewhere in the start of your game
public void update(GameContainer container, int delta) {
time += delta;
}
public void render(GameContainer container, Graphics g) {
g.drawString("Time : " + time/1000, 100, 100);
// if the current time has passed the deadline, do something
if(time > deadline){
int min = 2;
int max = 3;
deadline = time + ((min + (int)(Math.random() * ((max - min) + 1))) * 1000); // reset the interval timer
// draw the image
int x = 100;
int y = getRandomNumberFromArray(); // this is the method I provided in my first part of the answer
images.add(new DrawnImage(new Image("path/file.png"), x, y));
for(DrawnImage di : images){
g.drawImage(di.image, di.x, di.y); // image file, x, y
}
}
}
DrawnImage class
public class DrawnImage {
public Image image;
public float x;
public float y;
public DrawnImage(Image image, float x, float y){
this.image = image;
this.x = x;
this.y = y;
}
}
You don't need a timer at all.
while (true) {
Thread.sleep(x); //x is the number of milliseconds you want the computer to wait for
int y = Math.random() * array.length; //array is the name of the array
//Create your new image, with y-value as array[y]
}
Related
I just need to get this code working. I know it's not good form or very efficient but I just need it to draw the Sierpinski's Triangle, recursively. It reaches the first recursive call, but never gets past it and only draws part of the triangle. I know I'm being stupid and the answer will be obvious but I haven't coded in a long time. Thank you for any help!
import javax.swing.*;
import java.awt.*;
public class recursiveTriangle18 extends JApplet
{
private final int APPLET_WIDTH = 800;
private final int APPLET_HEIGHT = 800;
/*
//x is accross and y is down
point 1 - Right A x[0],y[0] (720,600)
point 2 - Left B x[1],y[1]
point 3 - Top C x[2],y[2]
point 4 draws back to point 1 to complete triangle
*/ private int[] xPos = {720, 80, 400, 720};
private int[] yPos = {600, 600, 40, 600};
//-----------------------------------------------------------------
// Sets up the basic applet environment.
//-----------------------------------------------------------------
public void init()
{
setBackground (Color.white);
setSize (APPLET_WIDTH, APPLET_HEIGHT);
}
//-----------------------------------------------------------------
// Draws a rocket using polygons and polylines.
//-----------------------------------------------------------------
public void paint (Graphics page)
{
page.setColor (Color.BLUE);
page.drawPolyline (xPos, yPos, xPos.length);
Triangle(xPos,yPos, 0, page);
}//end of paint
public void Triangle(int[] xPos, int[] yPos, int flag, Graphics page)
{
//Find the distance between 2 points ex. - x,y & x1,y1
int x = xPos[0];
int x1 = xPos[1];
int x2 = xPos[2];
int x3 = xPos[3];
int y = yPos[0];
int y1 = yPos[1];
int y2 = yPos[2];
int y3 = yPos[3];
double dist = Math.sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1));
//find the mid points of each line segment
while (dist >= 100){
int midpointx = ((x+x1)/2);
int midpointy = ((y+y1)/2);
int midpointx1 = ((x1+x2)/2);
int midpointy1 = ((y1+y2)/2);
int midpointx2 = ((x2+x3)/2);
int midpointy2 = ((y2+y3)/2);
//make the x and y array (3 points + first point to finish triangle)
//create x,y Array using the midpoints you calculated
int [] xpoints = {midpointx2, midpointx, midpointx2};
int [] ypoints = {midpointy2,y, midpointy, midpointy2};
int [] xpoints1 = {midpointx, midpointx1, x1, midpointx};
int [] ypoints1 = {midpointy, midpointy1, y1, midpointy};
int [] xpoints2 = {midpointx1, midpointx2,x2,midpointx1};
int [] ypoints2 = {midpointy1, midpointy2,y2,midpointy1};
page.drawPolyline(xpoints1, ypoints1, xpoints1.length);
page.drawPolyline(xpoints2, ypoints2, xpoints2.length);
page.drawPolyline(xpoints, ypoints, xpoints.length);
//if the segment/distance is 300 or so, good length to stop
// Recursive calls for each section of triangle
Triangle(xpoints, ypoints, flag, page);
Triangle(xpoints2, ypoints2, flag, page); // how to get here?
Triangle(xpoints1, ypoints1, flag, page);
}
}
//end of Triangle
}
Triangle(xpoints, ypoints, flag, page);
Triangle(xpoints2, ypoints2, flag, page); // how to get here?
Every Triangle call is making another call to Triangle, so it's an infinite recursion that never returns. You need an if (stop condition) block around the recursive calls to tell it when to stop recursing.
There's also another issue:
double dist = Math.sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1));
//find the mid points of each line segment
while (dist >= 100){
You never update the value of dist, so this is an infinite loop.
I am learning processing right now and I am trying to make a sketch that could change colour when the sound changes.
(When Amplitude + ,
Then Brightness+ )
Because changing colour does not need to change as rapid as the draw() function. So how could I build a clock so that the color would not change in every draw?
This is the code I am using right now:
import ddf.minim.*;
import ddf.minim.signals.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
Minim minim;
AudioPlayer song;
FFT fft;
BeatDetect beat;
color start=color(0,0,0);
color finish;
float amt = 0.0;
void setup()
{
frameRate(50);
size(600,600,P3D);
minim = new Minim(this);
song = minim.loadFile("song2.mp3", 512);
song.loop();
fft = new FFT(song.bufferSize(), song.sampleRate());
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
}
// draw is run many times
void draw()
{
float brightness = map( 0, 0, song.bufferSize(), 0, 255 );
background( brightness );
// println(song.bufferSize());
stroke(100);
// draw the waveforms
for( int i = 0; i < song.bufferSize() - 1; i++ )
{
// find the x position of each buffer value
float x1 = map( i, 0, song.bufferSize(), 0, width );
float x2 = map( i+1, 0, song.bufferSize(), 0, width );
// draw a line from one buffer position to the next for both channels
line( x1, 50 + song.left.get(i)*50, x2, 50 + song.left.get(i+1)*50);
line( x1, 150 + song.right.get(i)*50, x2, 150 + song.right.get(i+1)*50);
println(x1);
}
}
When you call frameRate(50); you are telling Processing to (try to) update the draw() 50 times a second. You can tell how many frames have passed since the start of the sketch by checking the built-in variable frameCount.
This can then be divided by a number which represents how many frames you want to draw before doing something special - I would use modulus for this, it will divide the numbers and return the remainder. If it equals 0, then that number of frames have passed.
int updateTriggerCount = 10;
void setup() {
...
}
void draw()
{
if((frameCount % updateTriggerCount) == 0)
{
// Another 10 frames have passed! Do something special
}
....
}
Trusting in frameRate to control timing is ok, but is, of course, frameRate dependent. Meaning that if your frameRate drops the timimg will drop together.
To avoid that, you may use millis() and attach your timing to, well time :)
Here a very simple timer example:
PFont font;
String time = "000";
int initialTime;
int interval = 1000;//one second
color bg = color (255);
void setup()
{
size(300, 300);
font = createFont("Arial", 30);
background(255);
fill(0);
initialTime = millis();
frameRate(30);// changed framerate to exemplify
}
void draw()
{
background(bg);
if (millis() - initialTime > interval)
{
time = nf(int(millis()/1000), 3);
initialTime = millis();
bg = color (random(255), random(100), random(255));
}
text(time, width/2, height/2);
}
Please look at the following structure of my pong game.
gameLoop(); method
//Only run this in another Thread!
private void gameLoop()
{
//This value would probably be stored elsewhere.
final double GAME_HERTZ = 30.0;
//Calculate how many ns each frame should take for our target game hertz.
final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
//At the very most we will update the game this many times before a new render.
//If you're worried about visual hitches more than perfect timing, set this to 1.
final int MAX_UPDATES_BEFORE_RENDER = 5;
//We will need the last update time.
double lastUpdateTime = System.nanoTime();
//Store the last time we rendered.
double lastRenderTime = System.nanoTime();
//If we are able to get as high as this FPS, don't render again.
final double TARGET_FPS = 60;
final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;
//Simple way of finding FPS.
int lastSecondTime = (int) (lastUpdateTime / 1000000000);
while (running)
{
double now = System.nanoTime();
int updateCount = 0;
if (!paused)
{
//Do as many game updates as we need to, potentially playing catchup.
while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
{
updateGame();
lastUpdateTime += TIME_BETWEEN_UPDATES;
updateCount++;
}
//If for some reason an update takes forever, we don't want to do an insane number of catchups.
//If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
{
lastUpdateTime = now - TIME_BETWEEN_UPDATES;
}
//Render. To do so, we need to calculate interpolation for a smooth render.
float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
//float interpolation = 1.0f;
drawGame(interpolation);
lastRenderTime = now;
//Yield until it has been at least the target time between renders. This saves the CPU from hogging.
while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
{
Thread.yield();
//This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it.
//You can remove this line and it will still work (better), your CPU just climbs on certain OSes.
//FYI on some OS's this can cause pretty bad stuttering. Scroll down and have a look at different peoples' solutions to this.
try {Thread.sleep(1);} catch(Exception e) {}
now = System.nanoTime();
}
}
}
}
updateGame(); method
if(p1_up){
if(player.equals("p1")){
p1.moveUp();
}
else
{
p2.moveUp();
}
}
else if(p1_down){
if(player.equals("p1")){
p1.moveDown();
}
else
{
p2.moveDown();
}
}
moveUp(); moveDown(); method of paddle
public void moveUp(){
last_y = y;
last_x = x;
y -= 50.0;
}
public void moveDown(){
last_y = y;
last_x = x;
y += 50.0;
}
drawGame(interpolation); method
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i=0;i<balls.size();i++){
paintBall(g, balls.get(i));
}
drawPaddle(g, p1);
drawPaddle(g, p2);
}
public void drawPaddle(Graphics g, Paddle p){
paddle_drawX = (int)((p.x - p.last_x)*interpolation + p.last_x);
paddle_drawY = (int)((p.y - p.last_y)*interpolation + p.last_y);
g.drawRect(paddle_drawX, paddle_drawY, 10, 50);
}
I am a beginner in game programming so i don't have a good idea about game loops. I found the above fixed time-step game loop in the internet and used it as the game loop for my game. The loop makes the ball move smoothly but the paddle isn't staying at one place when moved. When I move my paddle by pressing one down key stroke then the paddle keeps shaking
without stopping in one spot. The y coordinates of the paddle keeps changing like
33, 45, 20, 59, 34, 59, 34, 59, 33, 59, 34, 58
I know the problem is in interpolation value as it keeps changing value that will change the y coordinate of paddle in render. I have been thinking about this for a while and i don't know how to make the game loop work for any movements so i have come here for some help. I appreciate any suggestion/help!
Here is my full Paddle class.
public class Paddle
{
float x;
float y;
float last_y;
float last_x;
public Paddle(int x, int y)
{
this.x = x;
this.y = y;
this.last_x = x;
this.last_y = y;
}
public void setNewX(int d){
last_y = y;
last_x = x;
x = d;
}
public void setNewY(int d){
last_y = y;
last_x = x;
y = d;
}
public void moveUp(){
last_y = y;
last_x = x;
y -= 50.0;
}
public void moveDown(){
last_y = y;
last_x = x;
y += 50.0;
}
}
and i initiate the paddle position in the main class through global variable.
public Paddle p1 = new Paddle(10, 10);
public Paddle p2 = new Paddle(950, 10);
I have following event listeners for handling key strokes.
Action handle_up_action = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_up = true;
}
};
Action handle_up_action_released = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_up = false;
}
};
Action handle_down_action = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_down = true;
}
};
Action handle_down_action_released = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_down = false;
}
};
What are you trying to achieve with interpolation? From my understanding, it represents the percentage of time elapsed between previous previous and next "update time".
So it should progress continuously from 0 to 1 each 33.3 ms.
I don't know how you use this interpolation variable in the paintBall method, but for the paddles, it will draw your paddle at a "pseudo random position" between p.x;p.y and p.last_x;p.last_y (depending on the time between the two updateGame()).
In order to correct this, from your loop logic, you should understand that every game entity (balls, paddles, ...) must have two states (the positions):
- the logical state, which is updated only each TIME_BETWEEN_UPDATES
- the visual state, which can be updated anytime, at each render.
It is the same as if you have a set of points (which represent the logical states) and you want to interpolate anywhere between this points (reprensenting the visual state).
Your code is like this.
First solution
The simplest way to correct the paddle shaking, is to avoid the interpolation and use:
public void drawPaddle(Graphics g, Paddle p){
paddle_drawX = (int)p.x;
paddle_drawY = (int)p.y;
g.drawRect(paddle_drawX, paddle_drawY, 10, 50);
}
But your movement will look like this (visual position will be changed only each TIME_BETWEEN_UPDATES)
Second solution
You want p.x;p.y to be the logical position, but the visual position should be interpolated between p.last_x;p.last_y and the logical position if the rendering is done between the input processing and the next updateGame(): you must reset p.last_x;p.last_y when updateGame() is called. To achieve this, call the paddles' updateMovement() method inside updateGame().
public void updateMovement(){
last_y = y;
last_x = x;
}
You can have other solutions, such as to use a speed variable or a movement function, in order to have a smooth movement, accelerations, and so on. It is mainly a generalisation of second solution. It requires bigger changes, but it is more flexible and powerful. To achieve this, you may want to store in paddles the last "update position", and all movement-related variables, such as movement start date. Add a method to retrieve the "visual position" that can be called with any date between two updates, and a method to update the "logical position" called each updateGame().
I implemented different type of sorting (bubble, insertion, selection). Know I want to compare their implementations like the following for each sort (here's an example with the bubble sort) :
For example, here's my bubble sort :
private static int[] bubbleSort(int[] tabToSort) {
int [] tab = tabToSort.clone();
boolean tabSort = false;
while(!tabSort){
tabSort = true;
for(int i = 0; i < tab.length -1; i++){
if(tab[i]> tab[i+1]){
int temp = tab[i+1];
tab[i+1] = tab[i];
tab[i] = temp;
tabSort = false;
}
}
}
return tab;
}
I started the GUI and I placed 1000 random points on it and the line y=x :
#Override
public void paintComponent (Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
Dimension size = getSize();
Insets insets= getInsets();
int w = size.width - insets.left - insets.right;
int h = size.height - insets.top - insets.bottom;
g2d.drawLine(size.width ,0, 0, size.height);
Random r = new Random();
for (int i =0; i < 1000; i++) {
int x = Math.abs(r.nextInt()) % w;
int y = Math.abs(r.nextInt()) % h;
Point p = new Point(x, y);
g2d.drawLine(p.x, p.y, p.x, p.y);
}
}
Here's what I've done :
Now I'm stuck, I have no idea about how to start. Could anyone indicate me the steps/ hints to follow to implement that ?
Thanks :)
You must define what the points mean. Looking at the animation, it looks like the y axis represents a value, whilst the x axis represents the position in the array of that value.
In your paint method, you would then go through the list of items and paint a dot, with the x-point being the position in the array and the y-point being a position on the y-axis. Assuming the values are within a known range.
Also, remember that the y-axis in graphics starts with 0 at the top, so you may have to do some translation of values to coordinates (depending on how you want it to look).
The easiest way would be to convert your paint method into one that uses a predefined List of points as a parameter instead of random points. On each iteration of your sort method pass the sorted array into the paint method and repaint the dots.
You'll need to
Create an int[] array with random values as a member variable. Let's call the array data. You probably want to start with a fixed array size and range of 100 each. You can adjust the values to the window size later, when a simple version is working. It may be even better to stick to a fixed size and range and just scale to the space available in paintComponent, making the behavior independent of the window size.
Change paintComponent to loop over data. The loop index is your x value and data[x] determines the y value.
Test that the code still draws the initial random array. Don't care if it is in the uppler left corner only now, you can fix that when the animation is working.
You'll need to add some kind of sleep() call to the innermost loop of your sort method, so you get a chance to observe the steps. Otherwise, even bubblesort will be too fast to observe. I'd recommend to start with one second (parameter value 1000). Make it faster later when everything works.
Start the bubbleSort method in a new thread and make sure your component gets repainted with each step. This may be the most tricky part. Perhaps hand in the component to the bublleSort method (or make bubbleSort a non-static method of the component) and let it request a repaint() at each step (fortunately, this is one of the few thread safe methods in Swing).
Fine-tune your code: Scale the x and y coordinates by multiplying with the space available and then dividing by the array size or value range. Adjust the sleep time as needed. Add support for different sorting algorithms....
If any of the steps is unclear, add a comment.
I've done this for my bachelorthesis, I did it like this (it's not perfect, but it might help you):
(I removed some unimportant methods/functions from the code below. It's mainly to illustrate how I visualized it. You can replace the GRectangle class by a simple java.awt.Point for example.)
The initialization method gives you an example of how you can find the maximum and minimum value of the data so you know how to transform your datavalues => coordinates.
public class DotVisualisation extends Visualisation {
private ArrayList<GRectangle> m_points;
private Comparable[] m_data;
private Comparable m_maxValue;
private Comparable m_minValue;
private int MAX_HEIGHT; // max height in pixels of visualization
/**
* Creates a new DotVisualisation.<br>
* <br>
* This class is a runnable JComponent that will visualize data as a function.
* The visualisation will plot the data with X and Y coordinates on the window.
* The X coordinate of the point is index of the dataelement.
* The Y coordinate of the point is relative to the value of the dataelement.<br>
* <br>
* This visualisation should be used for medium and large arrays.
*
* #author David Nysten
*/
public DotVisualisation()
{
m_points = new ArrayList<GRectangle>();
MAX_HEIGHT = 150;
}
/**
* Returns the maximum supported dimension by this visualisation.
*
* #return The supported dimension.
*/
public static int getSupportedDimension()
{
return 1;
}
#Override
public Dimension getMaximumSize()
{
return getPreferredSize();
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(m_points.size() + 2, MAX_HEIGHT + 6);
}
#Override
public Dimension getMinimumSize()
{
return getPreferredSize();
}
#Override
public void paintComponent(Graphics g)
{
for(int i = 0; i < m_points.size(); ++i)
m_points.get(i).paintComponent(g);
}
private void swap(int index, int index2) { // See below }
private void initialise()
{
findMinimum();
findMaximum();
m_points.clear();
double multiplier;
int x = 0, y = 0, h;
for(int i = 0; i < m_data.length; ++i)
{
if(m_data[i].compareTo(-1) <= 0)
h = 0;
else
{
Integer value = (Integer) m_data[i];
Integer min = (Integer) m_minValue;
Integer diff = (Integer) m_maxValue - min;
multiplier = MAX_HEIGHT / diff.doubleValue();
h = (int) ((value - min) * multiplier);
}
y = (int) (MAX_HEIGHT - h);
GRectangle r = new GRectangle(x, y, 1, 1); // 1, 1 = width and height
r.setColor(Color.BLACK);
m_points.add(r);
++x;
}
}
private void findMaximum()
{
Comparable max = null;
if(m_data.length > 0)
{
max = m_data[0];
for(int i = 1; i < m_data.length; ++i)
if(m_data[i].compareTo(max) > 0)
max = m_data[i];
}
m_maxValue = max;
}
private void findMinimum()
{
Comparable min = null;
if(m_data.length > 0)
{
min = m_data[0];
for(int i = 1; i < m_data.length; ++i)
if(m_data[i].compareTo(min) < 0)
min = m_data[i];
}
m_minValue = min;
}
}
Take this into account:
Visualizing integers between 0 and 150 on a height of 150 pixels is straightforward. Visualizing a set of integers between the values 565 and 3544545 on a height of 150 is a bit less so.
PS: The code uses the index of the element in the inputarray as the X-coordinate.
PS: The class keeps a reference to the inputarray (m_data variable) but that's ofcourse not needed, you only need it to initialize your points.
PS: My "Visualization" class which is extended by all visualizations, is basicly a JPanel.
PS: The code above is written for positive integers, so will probably need some extra coding to handle negative integers aswell ;).
Then to visualize the actions of the algorithm, I used the observer pattern. The algorithm, for example bubblesort, looked like this:
for(int i = 0; i < size(); ++i)
for(int j = 1; j < size(); ++j)
if(greaterThan(j - 1, j))
swap(j - 1, j);
Where the function swap was defined as follows (simplified version again):
protected void swap(int index1, int index2)
{
if(index1 != index2)
{
incrementSwap(); // counting swaps and visualizing counter
m_command.clear();
m_command.setAction(Action.SWAP);
m_command.addParameter(index1);
m_command.addParameter(index2);
setChanged();
notifyObservers(m_command);
E temp = m_data[index1];
m_data[index1] = m_data[index2];
m_data[index2] = temp;
}
}
Where I notified my observers (visualizations) that a swap occured on index1 and index2. The m_command variable is an instance of the Command-class (wrote it myself) which is just a wrapper for the information needed by the visualization. Which is: the action that occured and the relevant information (indices for a swap-action for example).
So in the visualization i swapped the GRectangles on those indices aswell as their X-coordinates;
private void swap(int index, int index2)
{
if(index == index2)
return;
GRectangle r1 = m_points.get(index);
GRectangle r2 = m_points.get(index2);
int tempX = r1.getX();
r1.setLocation(r2.getX(), r1.getY());
r2.setLocation(tempX, r2.getY());
m_points.set(index, r2);
m_points.set(index2, r1);
}
You can add lines like this:
try {
Thread.sleep(100);
} catch(InterruptedException ignore) {}
to let a thread sleep 100ms before continueing. This might come in handy if it's getting visualized too fast.
So for an array with random integers it might look like this:
And after sorting:
(Ofcourse it's not a straight line because the values in the inputarray were generated at random in this case)
So if you have to - like I had to - allow multiple algorithms to work with the same visualization, I can recommend you to separate the visualization class and the algorithm class and work with an observer pattern to let the visualization update whenever an action occurs (set, swap, ...).
And then you can create something like this for comparisons;
http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany_zps63269d2a.png
http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany2_zps65e96fa9.png
Good luck!
(The event listener is in another class) When Game.render = true, i get a constant stream of bullets that look more like a laser-beam, i want there to be gaps. What I mean is that I would like the bullets to be generated as if they were being fired from a machine gun. I know i should add a time or something, but I'm not sure how to do that, to get the effect I want. Any help would be greatly appreciated because I've been trying to get this to work for about an hour now.
import java.util.ArrayList;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
public class Bullet {
// ArrayList
#SuppressWarnings("unchecked")
static ArrayList<Bullet> arrL = new ArrayList();
public Bullet(int x , int y) throws SlickException{
}
public static void update(GameContainer gc, int u) throws SlickException{
// when the left mouse button is clicked Game.fire = true, the key listener is in another class
if(Game.fire){
Bullet b = new Bullet(5,5);
arrL.add(b);
reloaded = false;
} if(!reloaded){
}
}
public static void renderBullets(GameContainer gc, Graphics g, int x, int y) {
// draws a new bullet for every 'bullet object' in the ArrayList called arrL
for(Bullet b : arrL){
g.drawRect(x,y,10,10);
x++;
}
}
}
What I do most frequently in this kind of situation is add a time variable that I subtract the delta (the variable you have as u) from every update until it goes below 0, at which point I reset it:
// Set this to whatever feels right for the effect you're trying to achieve.
// A larger number will mean a longer delay.
private static int default_bullet_delay = 500;
private static int time = 0;
public static void update (GameContainer gc, int u) throws SlickException {
time -= u;
if (time <= 0 && Game.fire) {
fireBullet(); // Replace this with your code for firing the bullet
time = default_bullet_delay; // Reset the timer
}
// The rest of the update loop...
}
Basically, even if Game.fire is true the bullet won't fire until the timer counts down. Once that happens, the timer is set and the next bullet can't fire until the timer counts down again. If you set this to something reasonably small then there should be a bit of a gap between each bullet.
This is how I did this:
boolean reloaded = false; // Start with a reload becouse weapon not reload itself
float reloadTime = 100; // This is the "timer" (the value doesnt matter)
float startReloadTime = 100; // This is the actual reload time
private void shoot(int delta, float screenWidth, float screenHeight) {
// reload if not reloaded
if (!reloaded) {
reloadTime -= 0.5f * delta; // As I said, this is the timer
// If the reload finished, set the timer back to the reload time
if (reloadTime <= 0) {
reloaded = true; // reloaded, we can shoot
reloadTime = startReloadTime;
}
}
// Shoot only if reloaded
if (reloaded) {
// This is some direction calculating, ignore for now
float mouseWorldX = (x + (mouseX - screenWidth / 2));
float mouseWorldY = (y + (mouseY - screenHeight / 2));
float randomX = (float) Math.random() * (2000 / mouseWorldX);
float randomY = (float) Math.random() * (2000 / mouseWorldY);
mouseWorldX += randomX;
mouseWorldY += randomY;
// Add a new bullet element to the world (where will be rendered)
world.add(new Shot(world, camera, x + width / 2, y + height / 2, mouseWorldX - 2.5f, mouseWorldY - 2.5f, 5, 5, new Color(1, 0, 0, 1f)));
// We need to reload
reloaded = false;
}
}