I trying to work on a challenging topic which I would certainly need help and advice . I will upload an image followed by the explanation in order to make things much easier to understand .
So I have uploaded the image. What I'm trying to figure out is to program cars to begin from the starting point in the right corner of the image and take either road 1 in black or road 2 in violet and go all the way round and come back to the starting point where everything began. lets say I have 5 cars in first place and the cars should surf and stop in specific location which I represented in stars before coming back to the starting point I mentioned in the beginning . I should be able at any time to track and locate all cars surfing on either road 1 or road 2 . what I think I should use is coordinates (x,y) with toString to tell me the location of cars on the roads. And I think also use of inheritance is important to pass object between cars and make it more flexible . What is a bit tricky here is how to use coordinates and be able to make the cars stop by itself at specific places which are represented with stars. hope you can give me your tips , advice . thank you for your time and support.
Last edited by david16; November 30th, 2017 at 04:35 PM.
Actually your right if its working for one we can simply add the number of cars then and all roads . what I'm trying to do ( to be more specific then my first description ) first the most important thing is that a car should start where I mentioned (starting point) it should have the ability to stop at any star on its way ( I should tell the car on which star to stop for example ) and then drive back to the starting point when I tell it to. Now lets say a car is on a straight line like you said to make it more simple what I did is I made a class named Car which has private members : road , position ( which I should keep tracking at all time) , and max_speed ( I want for example to be able to fix max speed of all cars by 50 km/h for all time ) did the default and non-default constructors, setters getters and toString and then in the driver I created a new Car car1 ? Any way on how to start the first task I mentioned ?
Last edited by david16; December 3rd, 2017 at 01:02 PM.
Reason: spelling mistake
Any way on how to start the first task I mentioned ?
It depends on what kind of program you're writing. If it proceeds with time there's usually a main loop that does something like this (in principle):
Repeat forever: {
1. Wait for some time (a tick).
2. Inform concerned parties (say cars) that a tick has occurred.
3. Update the consequences of 2 (react to the car's new positions and display the consequences).
4. Check for user action (commands to start things, stop things, modify things or exit the program).
}
I suggest you use a GUI framework such as Swing or the new JavaFX. It very much works like the loop I described.
I also usually recommend a game engine such as JMonkeyEngine but that may be overkill for a learning project like yours.
Yes I guess the program should keep on running till I decided to stop . By the way , I'm using TEXTPAD or notepad++ to implement this program . The main problem I'm facing is how to translate what I said in post #4 into a code . What I'm going to do is add maybe something such as do while in driver to keep on going infinitely what do you think or is there something better ?
I mean something like that :
Code:
public class Forever {
public static void main(String[] args) throws InterruptedException {
while (true) { Thread.sleep(1000); }
}
}
Lets say I have a car with an engine controlled by my program how to send information to the car to start and go to a certain position or a stars ? is there a way to translate this logic to start and stop into a code that's the problem I'm facing at the moment.
Last edited by david16; December 4th, 2017 at 10:51 AM.
Lets say I have a car with an engine controlled by my program how to send information to the car to start and go to a certain position or a stars ? is there a way to translate this logic to start and stop into a code that's the problem I'm facing at the moment.
It's not hard in principle but it depends on what kind of program you are writing. What for example do you mean by "go to a certain position"?
It could mean you call a set position method in a car object and the move would be instant in one gigant leap. But it could also mean the car is supposed to move in small smooth increments like it's driving from one position to another, implying you're planning to show it visually.
Even though you're using a simple text editor you can still make use of Swing or JavaFX (or even AWT) which I think you should. It will help you deal with user events and graphic output. Otherwise you will be forced to do lots of complicated low-level coding to accomplish the same. As I mentioned, these GUI frameworks essentially implement the basic loop I suggested in #5 and you fill in the application specifics.
So start by determining which kind of application you want to write, then decide on an appropriate application structure including choice of GUI, and only then start thinking about the rest. I have a feeling you're doing it backwards.
Last edited by wolle; December 4th, 2017 at 12:57 PM.
Yeah the program should actually meet the real life condition .
It could mean you call a set position method in a car object and the move would be instant in one gigant leap. But it could also mean the car is supposed to move in small smooth increments like it's driving from one position to another, implying you're planning to show it visually.
Actually I supposed that the drawing I did in post #1 is a real surface where I ask car to drive slowly at a fixed speed from a starting point to a position on the image which I represented with stars stop there then go back to the starting point . Each car has 2 things to do with 1 parameter :
1-drive to the position I asked for and stop .
2- Then when I ask it to start again it will drive to the starting point again non stop
3- speed is fixed all the time for all cars ( lets say to 50 km/h )
that is the first task I should do . So like you said it should move in a small smooth increments . now translating it to coding that's where I'm facing difficulties see what I mean ?
Last edited by david16; December 4th, 2017 at 02:01 PM.
So like you said it should move in a small smooth increments . now translating it to coding that's where I'm facing difficulties see what I mean ?
I've planned to get reacquainted with Java after a fairly long pause so I've downloaded the latest Java and Eclipse now.
I'll write a small "game" first thing tomorrow and post here. Not exactly your application but I'm sure you will be able to use it as a starting point. And then you'll have some real code to ask more specific questions about.
I will latch on to the Swing/AWT event loop to accomplish the loop I mentioned in #5. It's not the only way but it's the easiest way to get something up and running.
Oh I'm glad to hear from you again . Thanks I'll be waiting for it then
My program is coming along quite nicely.
I quit Java at about when Java 7 was introduced so it's been some time (since around 2011). Apart from being somewhat rusty in Java I can only program in the evenings so it takes a little bit longer than expected.
I'm doing it in Swing which was the thing to use around the time I left Java. I probably should use JavaFX so I guess my next project will be to port this program to that GUI to really get up to date with Java.
Then there's the functional thing. My program is OO, period. I know Java has become more functional and I'll see what I can do about that but that's for a next project.
I've written a Java program now. The purpose was to get reacquainted with Java again after a long period of C++ programming. It means my Java style probably is a somewhat dated. The program is a non-trivial game of predator-prey type called Circle Chase. It's keyboard controlled and the commands are described at the beginning of the source file. I've used Eclipse version Mars as IDE with the latest Java version 8.
The whole program is on one file for simplicity. The most specific code comes first and then the code becomes more and more general towards the end where the Java entry point main() can be found in class BoardGame. I'm using Swing as GUI so BoardGame is a JFrame. BoardGame sets up class PlayGround which is a JPanel where the game is drawn. The logical part of the game is implemented in class ChaseGame. The rest of the program defines the participating game agents and a collision handling system. For the graphics and the physics I strongly recommend a game engine such as jMonkeyEngine rather than rolling it oneself as I did this time.
The program is designed according to object orientation (OO) which can be somewhat convoluted if you're not familiar with it. The core principle is that objects are made to act as autonomously as possible based on supplied information rather than being controlled in detail from the outside. This leads to a high degree of decoupling which makes the code easy to modify and extend and that's the ultimate goal of OO.
This project has been a nostalgic trip for me but I don't regret for a second I switched to C++. Java still is weak on the desktop, especially for scientific computing, and has been so from the beginning. There were some early attempts to improve the situation, R.I.P Java Grande, R.I.P Java3D, but they all fizzled out. I had high hopes when Oracle took over from Sun but I soon realized this wasn't a priority for them either so I finally gave up. Still Java is an excellent language for many purposes and well worth learning. It's also the most popular language according to the TIOBE index.
The Circle Chase source code is too long for one post so I post it in two parts.
Last edited by wolle; January 5th, 2018 at 02:39 AM.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
import javax.swing.*;
/**********************************
*
* Circle Chase is a predator-prey type game
*
* The predator is the blue triangle. The red circles are the prey.
*
* The predator can be moved and if it hits a prey that prey loses color but if
* it is hit again the color comes back. When all prey have lost color the predator
* wins. But the predator must be careful. It can be trapped inside the middle
* square and the game is lost.
*
* All commands are on the keyboard.
*
* Predator
* --------
* Arrow up: move faster
* Arrow down: move slower
* Arrow right: turn clockwise
* Arrow left: turn counter-clockwise
* Control-key: stop
* Shift-key: attack at top speed
*
* Prey
* ----
* Page up: all move faster
* Page down: all move slower
*
*
***********************************/
class DTuple { // tuple used for positions and vectors
private final double x;
private final double y;
public DTuple(double x, double y) {
this.x = x; this.y = y;
}
public DTuple(Point2D p) {
this(p.getX(), p.getY());
}
public DTuple() {
this(0.0,0.0);
}
public double x() {return x;};
public double y() {return y;};
public static DTuple add(DTuple p, DTuple q) {
return new DTuple(p.x() + q.x(), p.y() + q.y());
}
public static DTuple sub(DTuple p, DTuple q) {
return new DTuple(p.x() - q.x(), p.y() - q.y());
}
public static DTuple neg(DTuple p) {
return new DTuple(-p.x(), -p.y());
}
public static DTuple scale(DTuple p, double f) {
return new DTuple(f*p.x(), f*p.y());
}
public static double lenSqr(DTuple p) { // squared length
return p.x()*p.x() + p.y()*p.y();
}
public static double len(DTuple p) { // the "Euclidean" length
return Math.sqrt(lenSqr(p));
}
public static double angle(DTuple p) { // the "polar" angle (-PI to PI)
return Math.atan2(p.y(), p.x());
}
public static DTuple norm(DTuple p) { // normalize
return scale(p, 1.0/len(p));
}
public static boolean zero(DTuple p) { // is zero!
return lenSqr(p) < 0.000001;
}
public static class Utils {
// true if a line segment (p1,p2) intersects with another segment (p3,p4)
public static boolean SSIntersect(DTuple p1, DTuple p2, DTuple p3, DTuple p4) {
return Line2D.linesIntersect(p1.x(),p1.y(),p2.x(),p2.y(),p3.x(),p3.y(),p4.x(),p4.y());
}
// closest distance between a point (p) and a line segment (p1,p2)
public static double PSDistance(DTuple p, DTuple p1, DTuple p2) {
return Line2D.ptSegDist(p1.x(),p1.y(),p2.x(),p2.y(),p.x(),p.y());
}
// rotate a polygon around an anchor point an angle described by a direction vector
public static DTuple[] rotate(DTuple[] polygon, DTuple direction, DTuple anchor) {
AffineTransform rotate = AffineTransform.getRotateInstance(
direction.x(),direction.y(),anchor.x(),anchor.y());
DTuple[] result = new DTuple[polygon.length];
for (int i=0; i<result.length; i++) {
Point2D point = new Point2D.Double(polygon[i].x(), polygon[i].y());
result[i] = new DTuple(rotate.transform(point, null));
}
return result;
}
// angle between p1 and p2 (-PI to PI)
//https://stackoverflow.com/questions/2150050/finding-signed-angle-between-vectors
public static double angle(DTuple p1, DTuple p2) {
return Math.atan2(p1.x()*p2.y() - p1.y()*p2.x(), p1.x()*p2.x() + p1.y()*p2.y());
}
// rotate a vector (v) an angle (a)
static DTuple rotate(DTuple v, double a) {
return new DTuple(AffineTransform.getRotateInstance(a).transform(
new Point2D.Double(v.x(), v.y()), null));
}
// reverse DTuple array
static DTuple[] reverse(DTuple[] straight) {
final int N = straight.length;
DTuple[] reverse = new DTuple[N];
for (int i=0; i<N; i++) reverse[(N-1)-i] = straight[i];
return reverse;
}
}
} // DTuple
/**********************************
*
* The bouncing system handles collisions
*
* Bouncing elements are circles and polygons. Bouncing acts like reflecting
* light in a mirror. (mass and velocities are not considered)
*
* The Visitor design pattern is used to avoid down-casting.
*
***********************************/
interface IBounceResult { // result of a possible collision
boolean collision(); // true if a collision took place
DTuple bounce(DTuple vector); // get reflecting bounce vector
}
interface IBounceElement { // Element as in the visitor pattern
void accept(IBounceVisitor visitor);
}
interface IBounceVisitor { // Visitor as in the Visitor pattern
void visit(BounceCircle circle);
void visit(BouncePolygon polygon);
IBounceResult result();
}
interface ICollidable { // participates in collisions
enum Property {
ASDEF, // as defined
INVERSE // Inverse bouncing
}
IBounceElement shape(Property p); // returns bounceable shape, possible modified
enum Directive { // application dependent directives
NONE,
MORPH, // change appearance - prey switches between color and no color on collision
TRAP // let in but not out - predator gets trapped inside a shape
}
boolean encounters(ICollidable c, Directive a); // checks for collision and applies directive where applicable
}
class BounceUtils { // algorithms for collision between bounceable shapes
// All collision detection functions return null if there was no collision.
// Otherwise a tangent vector is returned off which the shape bounces
// (like a ray of light reflected by a mirror). The direction of the tangent
// indicates whether the reflection of the first shape took place inside or
// outside the second
// Circle - circle ?
public static DTuple collision(BounceCircle c1, BounceCircle c2) {
DTuple tangent = null;
DTuple normal = DTuple.sub(c2.center(), c1.center());
double distance = DTuple.len(normal);
if (distance <= c1.radius() + c2.radius()) {
tangent = DTuple.Utils.rotate(normal, Math.PI/2.0);
}
return tangent;
}
// Polygon - polygon ?
// All vertices of one polygon is checked for intersection with all vertices
// of another. Either one or two vertices of the first polygon intersects with
// one polygon of the second.
public static DTuple collision(BouncePolygon p1, BouncePolygon p2) {
final DTuple[] v1 = p1.vertices();
final DTuple[] v2 = p2.vertices();
DTuple tangent = null;
for (int j=1; j<v2.length; j++) { // all vertices of the second polygon
for (int i=1; i<v1.length; i++) { // all vertices of the first polygon
if (DTuple.Utils.SSIntersect(v1[i-1],v1[i],v2[j-1],v2[j])) {
if (tangent==null) {
tangent = DTuple.sub(v1[i],v1[i-1]); // a one vertice intersection so far
} else {
tangent = DTuple.sub(v2[j-1],v2[j]); // a two vertice intersection
break;
}
}
}
if (tangent!=null) break;
}
return tangent;
}
// Polygon - circle ?
// Either one or two vertices of the polygon intersect with the circle.
// Intersection takes place when the distance between the circle centre and a polygon
// vertice is shorter than the circle radius. The circle perimeter is considered to
// have a "collision active" thickness and a collision closer to the circle centre is ignored.
// This is a way to allow the circle to be bounceable both on the inside and the outside.
// In a one vector intersection the vector is the collision tangent. In a two vector
// intersection a perpendicular vector is calculated between the circle centre and the
// common point of the two intersecting vertices. This vector is then rotated 90 degrees
// to become the bouncing tangent.
public static DTuple collision(BouncePolygon p, BounceCircle c) {
final DTuple[] v = p.vertices();
DTuple tangent = null;
int q = -1;
for (int i=0,j=v.length-2; i<v.length; j=i++) { // all vertices of the polygon
if (q>=0 && q!=i-1) break;
double distance = DTuple.Utils.PSDistance(c.center(), v[j], v[i]); // distance is inside collision
if (distance <= c.radius() && distance >= c.radius()*0.90) { // active circle perimeter thickness
if (q<0) { // a one vertice intersection so far
tangent = DTuple.sub(v[i],v[j]);
q=i;
} else { // a two vertice intersection
double angle = DTuple.Utils.angle(tangent, DTuple.sub(v[i],v[j]));
//angle = -1.0;
DTuple perpendic = DTuple.sub((angle>=0.0) ? v[i] : v[j], c.center());
tangent = DTuple.Utils.rotate(perpendic, ((angle>=0.0) ? -Math.PI : Math.PI)/2.0);
}
}
}
return tangent;
}
// Circle - polygon ? (reverse of polygon-circle)
public static DTuple collision(BounceCircle c, BouncePolygon p) {
DTuple tangent = collision(p,c);
return (tangent==null) ? null : DTuple.neg(tangent);
}
// Calculates reflected vector after collision with a tangent vector.
// If the angle between vector and tangent is negative the vector is outgoing so
// although there was a collision no bounce should take place.
// The reflection is the same as light reflected in a mirror.
// To allow elastic collision (like say between billiard balls) mass and velocity
// must be included:
// http://www.vobarian.com/collisions/2dcollisions2.pdf
public static DTuple bounce(DTuple vector, DTuple tangent) {
if (tangent != null) {
double angle = DTuple.Utils.angle(vector, tangent);
if (angle > 0.0) vector = DTuple.Utils.rotate(vector, 2.0*angle);
}
return vector; // reflected vector
}
} // BlockUtils
class BounceCircle implements IBounceElement { // defines a bounceable circular shape
private DTuple center;
private double radius;
public BounceCircle(DTuple center, double radius) {
this.center = center;
this.radius = radius;
}
public BounceCircle() {
this(new DTuple(), 0.0);
}
public DTuple center() {
return center;
}
public double radius() {
return radius;
}
@Override
public void accept(IBounceVisitor visitor) {
visitor.visit(this);
}
}
class BouncePolygon implements IBounceElement { // defines a bounceable polygon shape
private final DTuple[] polygon;
public BouncePolygon(DTuple[] vertices, boolean reverse) {
this.polygon = (reverse) ? DTuple.Utils.reverse(vertices) : vertices;
}
public BouncePolygon(DTuple[] vertices) {
this(vertices, false);
}
public BouncePolygon() {
this(new DTuple[0]);
}
public DTuple[] vertices() {
return polygon;
}
@Override
public void accept(IBounceVisitor visitor) {
visitor.visit(this);
}
}
class BounceResult implements IBounceResult { // reports collision result
private final DTuple tangent;
BounceResult(DTuple t) {
tangent = t;
}
BounceResult() {
this(null);
}
@Override
public boolean collision() {
return tangent != null;
}
@Override
public DTuple bounce(DTuple vector) {
return BounceUtils.bounce(vector, tangent);
}
}
// polygon is checked for collision with some other shape
class BouncePolygonVisitor implements IBounceVisitor {
private final BouncePolygon thisPolygon;
private IBounceResult result = new BounceResult();
public BouncePolygonVisitor(BouncePolygon polygon) {
thisPolygon = polygon;
}
public BouncePolygonVisitor() {
this(new BouncePolygon());
}
@Override
public IBounceResult result() {
return result;
}
@Override
public void visit(BounceCircle thatCircle) {
result = new BounceResult(BounceUtils.collision(thisPolygon, thatCircle));
}
@Override
public void visit(BouncePolygon thatPolygon) {
result = new BounceResult(BounceUtils.collision(thisPolygon, thatPolygon));
}
}
// circle is checked for collision with some other shape
class BounceCircleVisitor implements IBounceVisitor {
private final BounceCircle thisCircle;
private IBounceResult result = new BounceResult();
public BounceCircleVisitor(BounceCircle circle) {
thisCircle = circle;
}
public BounceCircleVisitor() {
this(new BounceCircle());
}
@Override
public IBounceResult result() {
return result;
}
@Override
public void visit(BounceCircle thatCircle) {
result = new BounceResult(BounceUtils.collision(thisCircle, thatCircle));
}
@Override
public void visit(BouncePolygon thatPolygon) {
result = new BounceResult(BounceUtils.collision(thisCircle, thatPolygon));
}
}
Last edited by wolle; January 1st, 2018 at 02:32 AM.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.