Apologies if the title is not appropriate, was having trouble what to call this.
Scenario:
I have a universe type project in java where there are different types of things you can find in a universe (stars, planets, comets etc).
This is part of my university coursework and I'm stuck on one part
I have a class called Space_Object which is a superclass and all things found in the universe inherit it. The superclass has variables such as xPosition, yPosition.
I am currently stuck on trying to get planets to orbit around stars. I am trying to get the x,y coordinates of a star so that the planet can orbit around it (there can be multiple planets and stars). Right now I am passing the star that the planet will orbit around as a field whenever making a new planet.
I created getters inside of Planet to retrieve the x,y of the Star (which works). I am stuck on how can I use that x and y to alter the starting point of the planet. This is what I added to Universe class:
public void setCoordsOfPlanet(Planet planetObj)
{
planetObj.xPosition = planetObj.getSolarSystemX();
}
Which gave me an error of:
xPosition has private access in Space_Object
I am not allowed to make any of the fields public.
Planet class:
public class Planet extends Space_Object
{
private int distanceFromStar;
private int orbitSpeed;
static Star solarSystem;
public Planet(int disFromStar, int orbSpeed, Star solSystem, int objectDiameter, Color objectColor, Universe theUniverse)
{
super(0, 0, 0, 0, objectDiameter, objectColor, theUniverse);
distanceFromStar = disFromStar;
orbitSpeed = orbSpeed;
solarSystem = solSystem;
}
public int getSolarSystemX ()
{
return solarSystem.getXPosition();
}
public int getSolarSystemY ()
{
return solarSystem.getYPosition();
}
}
Just in case, the Space_Object constructor:
public Space_Object(int xPos, int yPos, int xVel, int yVel, int objectDiameter, Color objectColor, Universe theUniverse)
{
xPosition = xPos;
yPosition = yPos;
xSpeed = xVel;
ySpeed = yVel;
color = objectColor;
diameter = objectDiameter;
universe = theUniverse;
universeHeight = universe.getUniverseHeight();
universeWidth = universe.getUniverseWidth();
lifeTime = 1000000;
}
Am I approaching this from the completely wrong angle? I been trying to change things regarding this matter for past three hours and made no progress - any help is appreciated. If you need more code let me know.
PS: All items in the universe are objects and are represented as colour circles on a canvas.
If you are asking how do I modify private fields from another class: then all you need to do is to add setter methods in your Space_Object or Planet class, for example:
public class Planet {
...
public setCoor(int x, int y) {
this.xPosition = x;
this.yPosition = y;
}
}
Now you can call this method from the Star class: planet.setCoor(x, y)
If you want this method to only be accessible from classes of the same package only, remove public.
There are multiple issues here.
Programming stuff
Model of planetary rotation
Use of 'Solar System' when it should be 'Star System' :-) The Solar System is our star system; that's because our star is "Sol"
A1. You need xposition to have a method to set it.
A2a. There are no x and y for our solar system or even a star system. If you're going to model spinning galaxies and/or expanding universe (in which case the galaxies also move in 3d space away from each other,) then the star positions (or positions of any object for that matter) are not fixed.
A2b. If you're going with immobile stars and galaxies, a star (not its system) will have an x and a y.
A2c. A planet revolves around its star in a Kepler orbit with eccentricity greater than 0 and less than 1. To calculate the path, you need axis information for the orbit in addition to the star's location. Wikipedia will have the equations.
A2d. There is no starting position of a planet unless you plan to have planets with unstable orbits. (Or comets which will have their orbits modified during every revolution by the planets they pass by). Planets with stable orbits have always followed and will forever follow the same path (not really, but...) You can place the planet at any point on the orbit and give it appropriate initial velocity (=speed+direction) and watch it go. A3. Self-explanatory
Sounds like a fun project, especially you're animating the model onscreen. In such a case, you also need to decide on your system's clock-speed; the numbers of days that will pass in real time for each second of your simulation time. Additionally, you'll need to select your refresh frequency; how often will you update the screen.
Related
I´m currently programming my first chess game and I have a small problem with my pieces. I´ll add some of my code below, but generally, I would like to check whether the tile a player moves a certain piece (in this example the king) to, is already occupied by another piece because in that case the other piece would either be killed (if the piece belongs to the other player) or the move would be false (tile occupied by own piece).
If you have any ideas how it could be done, I´d appreciate it greatly.
Best regards
public abstract class Piece
{
protected int x;
protected int y;
protected Tile finalTile;
protected Type type;
protected boolean killed;
protected boolean white;
public Piece(boolean white, int x, int y)
{
this.setWhite(white);
this.x = x;
this.y = y;
this.finalTile = finalTile;
}
public boolean isWhite() {
return this.white;
}
public void setWhite (boolean white) {
this.white = white;
}
public boolean isKilled() {
return this.killed;
}
public void setKilled (boolean killed) {
this.killed = killed;
}
// which type of Piece is being used
public abstract Type getType();
//is the chosen move valid?
public abstract boolean canMovePiece (Chessboard chessboard, int finalX, int finalY);
//The validation of the move does not show in which direction the piece is being moved. To set
the piece at its new spot (tile), a determination of the direction is needed for the
// calculation of the new spot on the chessboard
public abstract void setNewPieceLocation();
}
public class King extends Piece
{
public King(boolean white, int x, int y)
{
super(white, x, y);
type = Type.KING;
}
public Type getType() {
return Type.KING;
}
#Override
public boolean canMovePiece(Chessboard chessboard, int finalX, int finalY) {
int x_diff = Math.abs(finalX - this.x);
int y_diff = Math.abs(finalY - this.y);
//the king can only move one tile per round. The direction does not matter. Therefore, the
movements can be either one on the x-axis, the y-axis or one on both.
if ( x_diff == 1 && y_diff == 0 || x_diff == 0 && y_diff == 1 || x_diff == 1 && y_diff ==1) {
return true;
}
}
#Override
public void setNewPieceLocation() {
int finalX = this.x;
int finalY = this.y;
}
}
In tile-based computer games, you always have to make a very important initial design decision about what you choose as your central data structure:
The field itself, e.g. as a two-dimensional array, where the state of each tile in the field represents which piece is on it or
A collection of pieces with coordinates.
Option 1 is great if you have a small field and the pieces can only be directly on a tile.
Option 2 should only be done if option 2 is not possible, i.e.:
your game world is very large and sparse, e.g. 1 million x 1 million, then you would have an array with one trillion entries or (inclusive or)
your pieces can be halfway or otherwise fractionally located respectively with the tiles
Option 1 is easiest to implement if there is at most one piece at any one tile at the same time but you can work around that and it would depend on the specific circumstances, which one is best.
Now which case do we have in chess? As an exercise you can think about this yourself but I will give the solution below:
The first option is the perfect fit for chess, because you have a very small field (8x8), the pieces are exactly on the tiles (in theory, even if they may be a few millimeters off in practice) and there can be at most one piece per tile.
Option 1 has the advantage that it becomes extremely easy to check, which piece is on a certain tile: just check the field data structure at that point!
Another very important point for beginners is however how to map your coordinate system to your data structure especially in the case of a two dimensional array. Which dimension of the array is which axis of your game world and in which direction? There is however no right or wrong here, just clearly document it and be consistent!
For example, I personally like to have y going from top to bottom as the first dimension of the array and x going from left to right as field[y][x] because computer graphics memory is aligned that way (at least it was this way in the old 10h 320x200 8 bit palette video mode) but a mathematics teacher may very well prefer x first and y going from bottom to top as field[x][y] because that's how you usually draw 2-dimensional plots and write points with x first in mathematical notation.
So in my mental model, checking the top left would be checking the value field[0][0], top right would be field[0][7], bottom left field[7][0] and bottom right would be field[7][7].
Our hypothetical mathematics teacher could instead use field[0][7] for top left, top right would be field[7][7], bottom left field[0][0] and bottom right would be field[7][0].
Just use what works for you (and your team if you have one).
In order to prevent problems with object equality vs object identity I would not use a class for the type but an enum as that is the perfect fit for this case. As an empty field, you can either use null, but then you may need a bunch of checks to prevent NullPointerException, or you create a special value for an empty field.
Checking, which piece is in a certain spot with option 2 is not hard either, but as option 1 is so much easier here and also faster in case that matters, I will not get into detail about that here as that is not the best solution to your problem.
I've been looking for a while now at how to fill a shape with a certain color using Turtle in java.
Let's say I have something like this:
private static void test(Turtle t1) {
for (int count = 0; count < 4; count++) {
t1.fd(100);
t1.right(90);
}
}
Where t1 is: Turtle t1 = new Turtle();
The code above creates a simple rectangle, and what I'm trying to figure out, is how to fill that rectangle with color (red, green, blue) . I've looked at the documentation in this link But so far I couldn't figure it out.
Thanks.
I've seen more useful methods like begin_fill then "do something" and end_fill for Turtle Graphics in Python and it seems that the Java implementation works different but I believe I achieved what you need (but I'm not sure if that's the best approach though) but I agree with you, I couldn't find info about this plus, the methods described in the link that you provided are not the same as the ones from the Turtle object in the Java code. Why? because your Turtle object is using the fd method to move forward while the provided documentation says that there's a forward method to do so (make sure you are using the correct library, in my case I'm using jturtle-0.1.1.jar and the methods are accurate to the code snippet from the OP).
Java code:
package com.turtle.main;
import java.awt.Color;
import ch.aplu.turtle.Turtle;
public class TurtleMain {
public static void main(String[] args) {
Turtle turtle = new Turtle();
// Init config
turtle.setColor(Color.RED);
turtle.setPenColor(Color.BLUE);
turtle.setFillColor(Color.GREEN);
// Draw rectangle
for (int count = 0; count < 4; count++) {
turtle.fd(100);
turtle.right(90);
}
// Fill rectangle
turtle.fill(1, 1);
}
}
So, when using the fill method (which makes the trick) you will see that there's one without parameters and another one expecting X and Y coordinates.
Obtained from the Turtle class:
/** Fills the region the Turtle is in.
A Region is bounded by lines
of any other color than the background color and by the border of
the Window. <br>
#return the turtle to allow chaining.
*/
public Turtle fill(){
getPlayground().fill(this);
return this;
}
/** Fills the region with coordinates <code>x</code> and <code>y</code>.
A Region is bounded by lines
of any other color than the background color and by the border of
the Window. <br>
#return the turtle to allow chaining.
*/
public Turtle fill(double x, double y){
double oldX = getX();
double oldY = getY();
boolean hidden = isHidden();
ht().setPos(x,y);
getPlayground().fill(this);
setPos(oldX, oldY);
if(!hidden){
st();
}
return this;
}
However, when I invoke just fill() it doesn't work but when specifying X=1 and Y=1 in the fill(x, y) method, it works (could be good to debug the core methods to see what's going on?) anyway, I didn't do it but when using above code, this is the output:
I'm trying to create a bullet hell type game similar to Touhou in Java.
I need some help getting started, like an example to follow. I tried my hand in it making it from scratch using JFrame, but my main problem is lag when creating bullets.
I have a bullet class, with parameters to make it go from A to B. But whenever the program creates or removes bullet objects (which are stored in an ArrayList) it freezes for a tiny fraction of a second, but this becomes very pronounced when there are many bullets.
Am I doing it wrong to use an ArrayList here? What guides are recommended to learn how to do this properly?
Here is my Bullet class:
import java.awt.Graphics;
public class Bullet
{
double x,y, xend, yend;
int width, height;
int life = 200;
private static final double speed = 8;
double dirX, dirY;
public Bullet(double x, double y, double xend, double yend, int width, int height)
{
this.x=x;
this.y=y;
this.xend = xend;
this.yend = yend;
this.width = width;
this.height = height;
dirX = speed*Math.cos(getAngle());
dirY = speed*Math.sin(getAngle());
}
public double getAngle()
{
double angle = (double) Math.toDegrees(Math.atan2(yend-y, xend - x));
if(angle < 0){
angle += 360;
}
System.out.println(angle);
return Math.toRadians(angle);
}
public void tick()
{
life--;
x+=dirX;
y+=dirY;
}
public void draw (Graphics g)
{
g.fillRect((int) Math.round(this.x),(int) Math.round(this.y),this.width,this.height);
}
}
And this is the code that is run when the user creates a bullet. It uses the mouseListener for the xend yend coordinates - finding the bullet's destination.
public void fireNormal(double xend, double yend)
{
Bullet bullet= new Bullet (x,y,xend,yend,5,5);
firedBullets.add(bullet);
}
}
I'm using a timer to refresh the game but it still isn't at a consistent speed because of the freezes.
ArrayList.add() should usually be extremely fast. Occasionally, when the implementation has to add new capacity, it will allocate a new backing array, copy the data from one to the other, before continuing. You can avoid this by specifying a suitable initial capacity in the ArrayList(int initialCapacity) constructor.
However you would need tens of thousands of entries for this to take long enough to add noticeable game lag.
ArrayList.remove(int index) has to shift all the entries above the removed item, down the backing array by one slot. However, this is highly optimised at the CPU level, and again should not add noticeable game lag unless you have tens of thousands of bullets.
ArrayList.remove(Object o) has to examine every element in turn, and run equals() on each one, until it finds the target element. Avoid this!
It's possible that the pauses you are seeing are due to garbage collection, and this could be because you're creating thousands of short-lived Bullet objects. These last from the moment they're fired until they go off screen. When they go out of scope, they remain in memory until the GC has to clear up thousands of them.
You could avoid this by maintaining an object pool of Bullets. There are libraries with object pool implementations, or you can roll your own using Collections.
In environments with tight memory constraints (like 8 bit games consoles) it's necessary to ensure a game runs within fixed memory, and this is similar to the kinds of things programs on those platforms would do.
However you should prove what your issue is, before trying to fix it, and for that you need to use a profiler such as VisualVM. This will show you where your execution is spending its time, and how it is using memory. Garbage collection in modern Java is very high-performing in most circumstances, though - don't assume it's the problem.
Im trying to get a rectangle to move from a fixed location, to a click point in my game. I have it working to the point that im getting good coordinates from the e.getX and e.getY methods in the mouse listener class. I also have the rectangle moving in straight lines to the side or up and down by increasing and decreasing the positionX and Y values but i need a way to move it to any point that i click on, basically i need to set the change in x and y. The way i was thinking is to compute the rise and run of the line from the click points and the start point and then set the x and y values to the rise and run. If i do it this way, i need a way to decrease the rise and run values down to their lowest terms so it moves fluidly. Or if there is a way im not thinking of that you can offer any guidence that would be helpfull.
How are you drawing it at the moment? Below is a method I used to shoot bullets in a little game that I made/really should finish sometime.
This is by no means all the code you will need, and in some places there are better ways to do things (which I'm sure people will start to tell me in the comments section after :) ) but it should give you a basis to work from.
The one thing missing from this is regulating the speed at which it repaints (fps), sorry but I can't remember the simple way to do this right now (need to get back to my actual job!) Hope it helps.
The barebones of it will be something like this:
//these set out the current position of your rectangle
double recX, reYy, recH, recW;
//this gives something to manage speed
int speed;
public void paintComponent(Graphics g) {
g.drawRectangle(recX,rexY,recH,recW);
}
//here we work out the movement
public void clickedScreen(double x, double y){
double newX = x;
double newY = y;
//calculate the speed to move at
vX = newX - recX;
vY = newY - recY;
//get the distance
length = Math.sqrt((v1*v1)+(v2*v2));
//make it a unit vector
v1 = v1/length;
v2 = v2/length;
}
public moveRec(){
recX = recX+(v1*speed);
recY = recY+(v2*speed);
}
while(true) {
moveRec();
repaint();
}
Not sure how to approach this problem.
Basically, I want a Pixel -> Tile representation of a 400x400 window. Each coordinate on the screen, e.g 120x300 should be part of a tile. My smallest sprite is 4 pixels, so we can say that 1 tile = 4 pixels. The player and enemy sprites are all 20 x 20, so each player/bad guy will occupy 5 tiles.
Then I want to use this Map class to:
Retrieve the x/y coordinates of a player/monster sprite by suppling the index/id of the tile.
Knowing where the boundaries are, so it doesn't move the sprite beyond 400x400, thus hiding it.
Collision detection, knowing whether a tile is vacant or not.
How can this be done? Talking specifically about the x,y->tile or tile index->x,y conversion (for drawing the sprites appropriately) here.
Firstly, split out the concept of a pixel, which is just concerned with representation, with a tile, which is an actual game object with constraints it places on the game.
I find a good way to disentangle things like this is to start out sketching out the rough API of what you want. Something like:
public class Board {
public Board (int width, int height){.. }
public boolean isOccupied(int x, int y){.. }
public void moveTo(Point from, Point to) { ..
(maybe throws an exception for outofbounds )
where all internal units of the board are in tiles, not pixels.
Then pixel information can be derived from the board independantly from the tile representation with a bit of internal multiplication-
public Point getPixelPosition(int xTilePos, int yTilePos, int pixelsPerTile)..
The tiles can be internally represented as a 2d array or a single array, in which case you'd use some kind of internal representation scheme to map your array to the board squares, thus the mod arithmetic.
Short answer: Multiplication and Modulo operations.
But if this is stumping you, I'd suggest you do a serious math refresher before trying to write a game.
Also your statement
My smallest sprite is 4 pixels, so we
can say that 1 tile = 4 pixels. The
player and enemy sprites are all 20 x
20, so each player/bad guy will occupy
5 tiles.
doesn't work out for any reasonable geometry. If by "1 tile = 4 pixels" you mean that the tiles are 2x2, then a player takes 100, not five. If you mean they are 4x4 then players take 25, which still isn't 5.
/** size of a tile in pixel (for one dimension)*/
int TILE_SIZE_IN_PIXEL = 4;
/** size of a piece in tiles (for one dimension)*/
int PIECE_SIZE_IN_TILE = 5;
public int tileToPixel(int positionInTiles){
return TILE_SIZE_IN_PIXEL * positionInTiles;
}
/** returns the tile coordinate to which the given tile coordinate belongs
Note: tileToPixel(pixelToTile(x)) only returns x if x is the upper or left edge of a tile
*/
public int pixelToTile(int positionInPixel){
return positionInPixel / TILE_SIZE_IN_PIXEL;
}
You'll probably want methods operating on two arguments (x and y at) as well.
For the ID->piece conversion and vice versa you have various approaches available. Which one to choose depends on the exact requirements (speed, size of game ...). So make sure that you are hiding the implementation details, so you can change them later on.
I'd start with a real easy solution:
public class Piece{
/** x position measured in tiles */
private int x;
/** y position measured in tiles */
private int y;
/** I don't think you need this, but you asked for it. I'd pass around Piece instances instead */
private final Long id;
public void getX(){
return x;
}
public void getY(){
return y;
}
public void getID(){
return id;
}
}
public class Board(){
private Set<Long,Piece> pieces = new HashMap<Piece>(pieces);
public Piece getPieceOnTile(int tileX, int tileY){
for(Piece piece:pieces){
if (isPieceOnTile(piece, tileX, tileY)) return piece;
}
}
private boolean isPieceOnTile(piece, tileX, tileY){
if (piece.getX() < tileX) return false;
if (piece.getX() > tileX + PIECE_SIZE_IN_TILE) return false;
if (piece.getY() < tileY) return false;
if (piece.getY() > tileY + PIECE_SIZE_IN_TILE) return false;
return true;
}
}
Hope that gets you started. All code is writen without a compiler nearby so it will include typos and of course bugs, which may be distributed under the creative commons license.
The approach of keeping the pieces in a set should work well if there are not to many pieces. It should work better than a 2D array as long as most board area does not contain a piece. The whole thing currently assumes there are no overlapping pieces. If you need those getPieceOnTile must return a Collection of pieces. A set if order does not matter, a List if it does.