I am currently working on a 2d game in which a player sprite pushes other sprites around on the screen.
My current code (within subclass):
//x and y being the co-ords i want this object to move to (e.g 50 pixels
right of its starting point etc.)
public Boolean move(float x, float y, int delta) {
this.setx(x);
}
How do i make the object move say 50 pixels every 1 second? or alternatively every x frames.
I've tried using delta but that results in smooth motion which is much harder to control for my particular needs.
Any help would be much appreciated
Your approach to accomplish it with the deltas is right. Assuming you have your move method inside your update method and call it in there (or implementing it in a similar way). One way you could achieve these would be the following:
class YourGameStateWithUpdateRenderInit extends BasicGameOrWhatever{
//Global variables for updating movement eacht second.
float myDelta = 0; // your current counter
float deltaMax = 1000; // 1 second, determines how often your object should move
public void update(...){
objectToMove.move(50,50,delta); //The object which contains the move method and you move it by 50 x/y per second.
}
}
Inside your objectToMove class you have your move method:
public Boolean move(float x, float y, float pDelta) {
myDelta += pDelta;
if(myDelta >= deltaMax){
this.setx(x);
myDelta = 0;
}
}
This should work for an update every second. However this implementation is not really good or precise since as you stated you probably have that move method in a sub class or something similar. So you need to adapt it to your needs, but i hope you get the idea behind it. I think it demonstrates the purpose of counting an class attribute up by the delta values until a certain value (e.g. 1000 for 1 second) and after that set it back to zero.
Related
Problem: my player model is supposed to turn into the direction of the last mouse click but instead of turning slowly it spins in all possible ways(Game has an isometric view, the model is supposed to rotate only around the Y-axis but it rotates around the X- and Z-axis too).
Following method(called in render()) is responsible for the turning behavior of the model:
public static void turnUnit(){
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
mX = Gdx.input.getX();
mY = Gdx.input.getY();
angle = (float) (180+Math.atan2(mX-Gdx.graphics.getWidth()/2, mY-Gdx.graphics.getHeight()/2)*(180/Math.PI));
newAngle = ((((currentAngle - angle) % 360) + 540) % 360) - 180;
turning = newAngle/60*turnRate;
currentAngle = currentAngle-turning;
}
TestGround.player.transform.setToRotation(Vector3.Y, currentAngle).setTranslation(posX,0,posZ);
}
And the movement-method(also called in render()):
public static void movement(){
if(northM==true){
TestGround.player.transform.trn(0,0,-1f);
}
if(southM==true){
TestGround.player.transform.trn(0,0,1f);
}
if(westM==true){
TestGround.player.transform.trn(-1f,0,0);
}
if(eastM==true){
TestGround.player.transform.trn(1f,0,0);
}
posX = TestGround.player.transform.getTranslation(Vector3.X).x;
posY = TestGround.player.transform.getTranslation(Vector3.Y).y;
posZ = TestGround.player.transform.getTranslation(Vector3.Z).z;
}
Tried to use "rotate" in the last line but then it just spins faster.
Also, even though this makes no sense to me but after some testing it seems the movement-method somehow interferes with the turn-method(moving in a certain direction will rotate the model in a certain way).
Am I doing something fundamentally wrong here?
Additional Info:
originally I used simple polling to get all keyboard and mouse input
calculated movement/rotation in one big method and everything worked
fine
decided to use the inputprocessor of libgdx to make the code more readable and open-ended
The Matrix4#getTranslation(Vector3) method will set the specified vector to the translation component of the matrix and return it for chaining. What this means is that the vector you supply as argument to the TestGround.player.transform.getTranslation(vector) method, will be set (read: overwritten) to the translation (position) of the model instance.
So, in the case of the call to:
TestGround.player.transform.getTranslation(Vector3.Y)
This will practically modify the Vector3.Y variable from the default [x:0, y:1, z:0], to whatever the translation component of the matrix is set to. This will result in any other call that uses the Vector3.Y variable (like your call to setToRotation) to behave differently.
To fix that you can modify the last few lines to:
Vector3 pos = new Vector3();
TestGround.player.transform.getTranslation(pos);
posX = pos.x;
posY = pos.y;
posZ = pos.z;
Note that you should move the creation of the Vector3 out of the method and therefor might as well remove the posX, posY and posZ members in favor of the pos member.
So, you might be wondering two questions:
Why does the getTranslation method modify its arguments? This is because libGDX is designed to avoid creating garbage, because that will create hick-ups on some platforms, like Android. So instead of creating a new Vector3 every time the method is called, it allows you to specify an instance of that class which you want to reuse. You will see this pattern throughout the lib at multiple places because of this reason.
Why is it even possible to modify Vector3.Y, making it useless and cause all kind of problems? This is because the Vector3 class is mutable and does not encapsulate its members. So practically it allows you to do vector.x += 3; instead of forcing you to call vector.setX(vector.getX() + 3);. This is both for readability and performance reasons (although the latter might vary on your target platform). Also, java does not support something comparable to const.
I'm making apong game, in a boolean method in the Paddle class I want to determine if the ball touching any of the two paddles, I'm struggling of finding the proper logic...
here are the variables:
// instance variables
private Screen theScreen;
private MyroRectangle theRectangle;
private int topLeftX;
private int topLeftY;
// constants
private final int HEIGHT = 100; //the paddle's fixed height
private final int WIDTH = 5; //the paddle's fixed width
private final int PIXELS_PER_MOVE = 20; //the number of pixels a paddle can move either up or down in one timestep
here is the method: * this method is just to determine if the ball touch or not it doesn't do anything with bounce the ball back
public boolean isTouching(Ball b)
{
boolean t = false;
if ((theScreen.getWidth()-(b.getX() + b.getRadius())) >= theScreen.getWidth()-theRectangle.getCenterX() )
{
t= true;
}
return t;
also I tried:
if ((b.getX() > theRectangle.getCenterX()/2) && (b.getY() < theRectangle.getCenterY()/2))
==========
** the methods of the ball class that might be needed:
getX()
getY()
getRadius()
==============
** the Rectangle class:
getCenterX()
getCenterY()
===============
** the Screen class:
getWidth()
getHeight()
I just want to determine at least on of the conditions then I can figure out the rest of them.
In my junior year in college I worked on a Collision detection system algorithm for the windows phone. It is hardly perfect but it was EXTREMELY efficient and can be adapted to a majority of games.
The way that it worked was pretty simple. There were two types of objects; Collidable objects (such as enemies or buildings) and Objects that you wish to check for collisions with these collidable objects.
I had this idea when I was going through a data structures class and we spoke about Linked Lists. I thought what if each link was a collidable object that you could stick your game objects that were already created in it. Then as the game objects moved around you would have a lightweight way of checking their locations for collisions. Thus my system was born.
Basically what it comes down to is using
C (or the distance between to points) = SqrRoot(A^2 + B^2) - radius of ball
this formula should look very familiar to you.
You can see the full answer on this question:
Java More Resourceful Collision Detection
This problem can be seen as solving the question if two 2d-areas, the paddle (a rectangle) and the ball (a circle) intersect. You can just google/wiki formulas for that.
If you don't want to go into the math for solving the problem through geometry, package java.awt.geom contains classes that can do the calculations for you, namely java.awt.Area. You would just create Area instances for paddle and ball and then call the intersects() method to know if they collided.
I'm writing a bomberman game in Java and I have already wrote the code for the map of the game (which contains tiles), the players (and their movement in the map) and now I am stuck in the code for the bomb explosion.
I have a Map class which contains a 2d array of Tiles, which can contain Players, Blocks and Bombs.
The Player object have a method dropBomb who calls the method receiveBomb from the Map object (every Player has the reference of the Map object) with the position of the bomb and the bomb. When the Map method receiveBomb is called, the map put the bomb in the correct Tile.
My problem is in the explosion of the bomb. Who should care about it? The bomb itself? If it is, should the bomb have the reference for the Tile that contains it? Until now my tile haven't need the Map reference.
One possibility that I thought is to have the Tile reference inside the Bomb object, so, when the bomb explodes (and the bomb knows when it should explode) it calls a method in the tile object for the explosion and the tile calls a method in the map. By the way, I don't know this is a good idea. What should I do?
public class Tile {
private boolean available; //if the tile is not occupied by a indestructible block or bomb
private List<Entity> entities; //you can have more than one player at a tile
public boolean receiveEntity(Entity entity) {
boolean received = false;
if (available) {
this.entities.add(entity);
received = true;
if (entity instanceof Block || entity instanceof Bomb) {
available = false;
}
}
return received;
}
public boolean removePlayer(Player player) {
return entities.remove(player);
}
}
Player class:
public class Player implements Entity {
private Map gameMap;
private int posX;
private int posY;
private int explosionRange; //the explosion range for bombs
public Player(int posX, int posY, Map gameMap) {
this.gameMap = gameMap;
this.posX = posX;
this.posY = posY;
this.explosionRange = 1;
}
public void dropBomb() {
gameMap.receiveBomb(new Bomb(explosionRange), posX, posY);
}
}
Map class:
public class Map {
private Grid<Tile> tileGrid;
private int width;
private int height;
public Map(int width, int height, BuildingStrategy buildingStrategy) {
this.width = width;
this.height = height;
this.tileGrid = new Grid<Tile>(width, height);
buildingStrategy.buildMap(this);
}
public void receiveBomb(Bomb bomb, int posX, int posY) {
tileGrid.get(posX, posY).receiveEntity(bomb);
}
}
I have omitted the movement methods, because the movement is already fine.
I have always learned, and live by the rule "the table paints itself". The painter might choose the color and call the method, the floor might decide how the leaks and splatter is shown, but the table paints itself.
Back to your issue: the bomb explodes itself. This way you can have different effects of different bombs. The bomb has an effect on the tile, and the tile reacts to that.
Example: A bomb has a force and a type of explosion. The bomb, (occupying one and one tile only I think?) will 'give' it's effect to a tile.
Now it's the tile that deals with distributing this force. Lets say you have several kinds of bombs, one power (lets say a number between 1 and 10), and two type (lets say normal, incendiary, freeze).
Now your bomb explodes, and because your avatar is a level 5 fire-mage, your bombs are of power 4 and type incendiary. So you say to your tile: I explode with power 4 and I am setting you on fire!
Now the tile comes in to play. Any tile that gets 'touched' by the force of an explosion needs to call it's "Exploded" function to do stuff. If it is also on fire, there is more to do in the "onFire" function
What tiles are 'exploded' comes from force. Normal tiles with force 4 will give the expotion off to all squares within a range of 4, but if it is a special tile (it knows that from itself), like a mountain tile, it might not be able to advance with that force.
Tile 1 explodes with 4 and gives it to adjacent tiles with force 3. One of those tiles might be a wall, so doens't do anything further. Another is a normal tile, and explodes, and continues giving it forward with force 2, etc. If it is a 'water' tile, the explosion is pushed ofrward, but the fire isn't, etc
so:
bomb explodes itself and gives calls the tiles explosion function
tile is exploded and pushes explosion forward according to tile-type.
subsequent tiles explode because of this.
In the end it might look like most of the work is done by the tiles, and this is probably even the case. but the first steps: the calculation of the force, type, and the first calls are from the bomb. The bomb explodes. And then the explosion has an effect on the tile. The tile handles that, and if needed propagates it.
Your Map should be responsible for the explosion, as it is for every other tile on the map. After all, what is an explosion if not for another tile-type that disappears after a few seconds?
When your game loop calls the update method on the Map object your map should figure out:
What tile is the bomb on
Ask the bomb how far the reach is
Figure out what's in the adjacent tiles that the bomb can reach
Think of your design as a series of events, taken care of one by one in the game loop before eventually being drawn. When your bomb is dropped, it raises an event to the Map in the form of recieveBomb() with the Map being the event controller.
I believe this question fits better in a discussion format and not a Q&A format. It's hard to tell you what is the "correct design" without understanding the overall architecture.
The Map should be the responsible one for handling a bomb explosion.
I would suggest having a queue in the Map, that contains all the bombs present. Also, your bombs should have a timer (i.e., CreationTime) so that as bombs get pushed into the queue, you check each bomb in the queue for how long they have been in there and if applicable "explode" them.
Add a ExplodeBomb function in the Map that checks all 4 directions and handle the tiles accordingly.
In Java using the acm.graphics GPen is there any way to move the entire drawn sequence of lines? I've read the manual thoroughly and I'm beginning to think it's not possible which brings me to my second question. Are there any other graphics objects in Java that work very similar to a pen that can also be moved. The reason I'm asking is because I've been working on a graphing program that allows mouse gestures to be used to pan around and zoom in and out. After building functionality for implicit functions I realized simply clearing the drawing board and redrawing everything is not going to cut it anymore so I really need to work on more efficient ways to handle intermediate changes of the graph without having to recalculate everything. For example with this or similar code:
GPen p = new GPen();
p.setLocation(100,100); //places the pen on the canvas at 100, 100
p.drawLine(-50,0); //draw a line left 50 pixels
p.drawLine(50,-50); //draw a line right and up 50 pixels each
p.drawLine(0,50); //draw a line down 50 pixels
This would result in a simple right triangle who's bottom right most point is at 100, 100 on a particular canvas. What I need to do is be able to move this same drawn sequence of lines relative to one another to another origin. What I hoping for is a class that has separate methods for setLocation() and move() where setLocation() controls pen position and move() would move the entire object around.
Ok so having received almost no attention on here I've came to the conclusion that such a method just needs to be written from scratch and went ahead and did that. I'm not entirely sure how helpful posting my proprietary code would be but in the event that anybody could use it I'll post the basic idea of it. Since Pen utilities are essentially a bunch of lines and lines are a bunch of from and to's I created an object that I called FPen (for FunctionPen) that accepts the instructions for from and to. While defining FPen you pass it where to start and how far to go however many times you need and that's it. Once you've passed these instructions I created another method called returnGPen(Color c) which will on call use the instructions it has on hand and generate the desired GPen object. When you want to move the entire GPen you can then create a method called adjustOrigin(double oX, double oY); which will calculate a change from a previously recorded origin and this new one and go through the list of instructions and adjust them appropriately.
My needs for this Class are strictly for my Graphing program and are not entirely finished either but it does work for most purposes.
import acm.graphics.GPen;
import java.awt.Color;
import java.util.ArrayList;
public class FPen{
private double relativeCenterX;
private double relativeCenterY;
private ArrayList<Double> fromX = new ArrayList<Double>();
private ArrayList<Double> fromY = new ArrayList<Double>();
private ArrayList<Double> distX = new ArrayList<Double>();
private ArrayList<Double> distY = new ArrayList<Double>();
public FPen(double rX, double rY, double z){
relativeCenterX = rX;
relativeCenterY = rY;
}
public void adjustOrigin(double cX, double cY){
double changeX = relativeCenterX-cX;
double changeY = relativeCenterY-cY;
for(int i = 0; i < fromX.size(); i++){
fromX.set(i,fromX.get(i)+changeX*zoom);
fromY.set(i,fromY.get(i)-changeY*zoom);
}
relativeCenterX = cX;
relativeCenterY = cY;
}
public void clear(){
fromX.clear();
fromY.clear();
distX.clear();
distY.clear();
}
public void drawLine(double fX, double fY, double tX, double tY){
fromX.add(fX);
fromY.add(fY);
distX.add(tX);
distY.add(tY);
}
public GPen returnGPen(Color c){
GPen pen = new GPen();
pen.setColor(c);
for(int i = 0; i < fromX.size(); i++){
pen.setLocation(fromX.get(i),fromY.get(i));
pen.drawLine(distX.get(i),distY.get(i));
}
return pen;
}
}
Of course a unexpected nice thing that came out of this was the idea that I can now quickly benchmark different drawing routines by creating different methods for each and calling what I'm interested in.
Having the following display() -
float tranX , tranY , tranZ ;
public void display(GLAutoDrawable gLDrawable) {
final GL gl = gLDrawable.getGL();
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glTranslatef(tranX ,tranY ,tranZ);
gl.glCallList(i);
gl.glPopMatrix();
tranX += 0.05;
tranY += 0.05;
tranZ += 0.05;
}
As you can see each display() calling the matrix of the object in gl.glCallList(i) saved and get coordinates change by gl.glTranslatef(tranX ,tranY ,tranZ) .
Suppose that at some stage I want to save this object at its current position (after gl.glTranslatef calling ) and start to translate it to another tranX , tranY , tranZ values .
How could I save this object position considering the above gl.glPushMatrix() and gl.glPopMatrix() ?
Push/pop matrices are there to accumulate complex matrix transformations that would otherwise be painful to do by hand. For storing and moving object positions, keeping variables as you have done is correct. To expand on that and, as you say start moving in another, add a directionX/y/Z. Eg, tranX += directionX etc. Then when you want to change direction, simply set directionX/Y/Z to a different value.
The speed will change depending on how fast your computer is though. You'll want to find the time since the last frame (or last call to display) and do something like this: transX += velocityX * deltaTime etc.
If you want to move an object from one point to another specific point, you want to look into key-framed interpolation. For example position = pointA * (1.0 - x) + pointB * x and make x move from 0 to 1 (x += speed * deltaTime). When x is above one, pointA becomes pointB and pointB is set to the next position in the list. Then subtract 1.0 from x and continue.
Assuming you're translating from the origin (and even if you're not) - it should be quite possible to save the position of the object relative to the origin in this case. You might use an object that stores the data in three fields (xPosition, yPosition, zPosition).
To translate the object later on, you would first translate to this position and then translate from there as needed.