Making a bullet pass opposite sides of the screen - java

So, for a coding assignment we have to make a tank game. I created a bullet class using this:
package com.MyName.battletanks;
import com.badlogic.gdx.graphics.g2d.Sprite;
public class Bullet {
public Sprite b;
public float vx = 0;
public float vy = 0;
public Bullet(Sprite temp) { b = temp;}
public void move() { b.translate(vx*3,vy*3);}
}
My variables are as follows:
Sprite Player1;
Sprite Player2;
ArrayList<Bullet> bullets;
Upon Clicking space it creates the bullet using this:
if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
Bullet bullet = new Bullet(new Sprite(new Texture("Bullet1.png")));
bullet.b.setPosition(Player1.getX() + Player1.getWidth() / 2, Player1.getY() + Player1.getHeight() / 2);
float rotation = (float) Math.toRadians(Player1.getRotation());
bullet.vx = (float) Math.cos(rotation);
bullet.vy = (float) Math.sin(rotation);
bullets.add(bullet);
}
Now, here is my code for getting my tanks to pass through one side of the screen to another:
if (Player1.getX() > Gdx.graphics.getWidth()){
Player1.setX(-64f);
} else if(Player1.getX()<-64f){
Player1.setX(Gdx.graphics.getWidth());
}
if (Player1.getY() > Gdx.graphics.getHeight()){
Player1.setY(-64);
} else if(Player1.getY() < -64f){
Player1.setY(Gdx.graphics.getHeight());
}
Now, Player 1 is a sprite, however, the bullets are created using an arraylist and a self made bullet class. As a result, I cannot use the code for Player1 that I did for the bullet. SO, my question is, how can I get my bullet to pass to the other side of the screen?

You can use the modulo % operator to do something like this:
bullet.position.x %= Gdx.graphics.getWidth();
bullet.position.y %= Gdx.graphics.getHeight();
This isn't tested but it should work. Also, I noticed you're using 2 floats for your velocity, and you should really be using Vector2 because then you can easily scale and normalise it, which would be useful for a velocity.

It is really the same thing for the Player class and for the Bullet class since you have the same screen-space therefore you can reuse your current code by making it into a function that takes any sprite. This function would be defined as follows:
void fitOnScreen(Sprite sprite) {
if (sprite.getX() > Gdx.graphics.getWidth()){
sprite.setX(-64f);
} else if(sprite.getX()<-64f){
sprite.setX(Gdx.graphics.getWidth());
}
if (sprite.getY() > Gdx.graphics.getHeight()){
sprite.setY(-64);
} else if(sprite.getY() < -64f){
sprite.setY(Gdx.graphics.getHeight());
}
}
You would call this function on the Player as well as loop over every bullet, such as:
fitOnScreen(Player1);
for (Bullet b: bullets) fitOnScreen(b.b);

Well, what you are asking is how can you run through each instance of the bullets and change their properties.
I have to agree #Zac's algorithm would work fine for one bullet, but you need to put it in a loop to go through each and every bullet in order to be effective.
Here is an example of what you could do in your render() method of your game screen:
Iterator<Bullet> it = bullets.iterator();
while(it.hasNext()) {
Bullet bullet = it.next();
// Now you do the position correction
bullet.b.setPosition(bullet.b.getX()%Gdx.graphics.getWidth(), bullet.b.getY()%Gdx.graphics.getHeight());
}
Of course there are other ways of doing this, but this is probably the easiest way. You could also recycle the code you used for you player in this loop too.
Also, note that with this method, the more bullets, the more laggy the application becomes.

Related

Creating a second object makes functions of class not work anymore

I'm trying to write a class that shows vectors. If I create one vector object everything works as intended. In my example code the object lin1 gets drawn with the help of the draw() function.
If I now create a second vector object, the (unchanged) draw-function doesnt do anything anymore, even though the object itself is unchanged. It's the same the other way around: Is the second object the only one existing, then it can be drawn, but only as long as lin1 doesnt exist.
Does anyone know where my mistake is?
vector lin;
vector lin2;
void setup()
{
size(500,500);
background(255);
cenX = width/2;
cenY = height/2;
noLoop();
}
void draw()
{
coordSys();
lin = new vector(0,0,100,100);
lin2 = new vector(0,0,-200,-200);
lin.draw();
lin2.draw();
lin.getAll();
}
class vector
{
float x1,y1,x2,y2;
float length;
float angle;
float gegenK, anK;
vector(float nx1, float ny1, float nx2, float ny2)
{
translate(cenX,cenY);
x1 = nx1; y1 = -ny1; x2 = nx2; y2 = -ny2;
strokeWeight(2);
// Gegenkathete
gegenK = ny2 - ny1;
// Ankathete
anK = x2 - x1;
// length and angle
length = sqrt(sq(anK) + sq(gegenK));
angle = winkel(gegenK, anK);
}
void draw()
{
stroke(0);
line(x1,y1,x2,y2);
}
}
}
Please use standard naming conventions when writing code. Specifically, your class should be Vector with an upper-case V. Also, please post your code in the form of an MCVE that compiles and runs.
Anyway, the first call in your Vector() constructor is this:
translate(cenX,cenY);
This moves the origin of the window halfway across the window. When you do this once, this simply makes your drawing calls relative to the center of the window. But when you do this twice, it moves the origin to the bottom-right corner of the window, so all of your drawings are moved off the edge of the screen.
To fix your problem, you need to move this line so it only happens once (perhaps at the beginning of the draw() function) instead of every single time you draw a Vector. Another way to approach this would be to use the pushMatrix() and popMatrix() functions to avoid this stacking of window translations.

Is it possible to create a simple animation just with translation and rotation in libGDX?

I'm trying to develop a very simple game using libGDX with boxes (so 3D game) moving and rotating.
I have almost everything ready, but I'm not able to animate my boxes. I mean, when I touch the screen, I'd like my cube to move to the right by rotating 90 degrees and translating 1 (unit) to the right. As result, the right side of the box will be the new base, the old base will be in the left side, and the box is moved to the right.
So, the question is: now that I have the move set correctly (I or at least I hope so), but change is applied immediately; so how can I see the animation between first position and second position ?
Only reference to animation for 3D objects in documentation is about using obj files from blender (and similar), and for movement I need I do not consider it necessary.
Can anybody provide me some help? Thanks in advance!!
You can do that something like this:
public static class YourAnimation {
public ModelInstance instance;
public final Vector3 fromPosition = new Vector3();
public float fromAngle;
public final Vector3 toPosition = new Vector3();
public float toAngle;
public float speed;
public float alpha;
private final static Vector3 tmpV = new Vector3();
public void update(float delta) {
alpha += delta * speed;
if (alpha >= 1f) {
alpha = 1f;
// TODO: do whatever you want when the animation if complete
}
angle = fromAngle + alpha * (toAngle - fromAngle);
instance.transform.setToRotation(Vector3.Y, angle);
tmpV.set(fromPosition).lerp(toPosition, alpha);
instance.transform.setTranslation(tmpV);
}
}
YourAnimation animation = null;
void animate(ModelInstance instance) {
animation = new YourAnimation();
animation.instance = instance;
animation.instance.transform.getTranslation(animation.fromPosition);
animation.toPosition.set(animation.fromPosition).add(10f, 10f, 10f);
animation.fromAngle = 0;
animation.toAngle = 90f;
animation.speed = 1f; // 1 second per second
animation.alpha = 0;
}
public void render() {
final float delta = Math.min(Gdx.graphics.getDeltaTime(), 1/30f);
if (animation != null)
animation.update(delta);
// render model as usual etc.
}
Ofcourse this is just a quick example. The actual implementation will vary depending on the use case. For example you could also extend ModelInstance and keep track of the animation in there. Because it is very specific to the use-case, but very simple to implement, it is usually not worth using tools (like the Universal Tween Engine)
Here is another example I recently wrote for my latest tutorial, perhaps it helps as well. It rotates and moves the cards in this video.

Simple 2D Game, Trying to Understand Multiple Classes

I'm creating just a simple 2D game, and I'm having troubles understanding how to interact with other classes.
For example, before now I had all of the player pictures and coordinates stored inside the main loop of the program, but now I wish to take it outside of that, into a new class. and just refer to the player as like Player.whateverhere
To change it.. e.g OO programming.
GitHub Link for my full code.
public int x, y;
public boolean up, down, left, right, jump;
public Image offScreen;
public Graphics d;
public BufferedImage walkAnimations[] = new BufferedImage[5];
public BufferedImage background;
public BufferedImage player;
public void run() {
// Set Window Size
x = 100;
y = 100;
try {
// Import the images to use in the game
background = ImageIO.read(new File("img/background.jpg"));
walkAnimations[0] = ImageIO.read(new File("img/walkleft.png"));
walkAnimations[1] = ImageIO.read(new File("img/walkright.png"));
walkAnimations[2] = ImageIO.read(new File("img/walkup.png"));
walkAnimations[3] = ImageIO.read(new File("img/walkdown.png"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
player = walkAnimations[3];
while (true) {
// Create the Gravity (If player !jumping; and if player is below or above the ground, then set player to ground.
if (!jump) {
if (y < Character.GROUND_LEVEL || y > Character.GROUND_LEVEL) {
y = Character.GROUND_LEVEL;
}
}
// If Keys are Pressed, Move the object
if (left) {
x -= 2;
} else if (right) {
x += 2;
} else if (up) {
y -= 2;
} else if (down) {
y += 2;
}
// Repaint the window to update the changes
repaint();
try {
// Make the thread sleep
Thread.sleep(20);
} catch (InterruptedException e) {
// Catch any errors with the Thread
e.printStackTrace();
}
}
}
(For the people not wanting to go to the trouble of visiting my GitHub for the code); i basically want to take the x/y, and images and stuff, and put them in a new class called "Player" but having a hard time making it work (e.g by doing this.player.y or player.y)
Simply put, if you look at Alpha 0.003 update, you can see it all in 2 classes.
I've tried to move all of the player stuff, into a new class/package called Player
So i'd like to be able to refer to it as say: player.x = 0; instead of doing x = 0;
and same with setting animations.
I'd like to just do this.player = walkAnimations[0]
But I don't understand how to do it properly. Is doing Player player = new Player(); wrong?
Basically, what you're doing is evil. Not "I murdered a baby and drank its blood evil", just the sort of affable friendly evil, like "I went to go pee during the commercial break".
So to answer the question, how should objects interact?
They should interact by sending each other messages.
In Java™ you interact by calling a method.
For instance, from a recent obligatory assignment me and another TA made, we have a SimplePlayer class with an illustrative example:
#Override
public void setDirection(Direction dir) {
this.faces = dir;
}
Thus if I want to tell the player object to face south, I can send it a message telling it to face south:
player.setDirection(Direction.SOUTH);
Now, you could ask, why not just call it like this?
p.faces = Direction.SOUTH;
Wouldn't that work?
Yes, in this and only this instance.
However, there might be other problems afoot when doing that sort of thing. Maybe the player object has to do something when he turns. Maybe it has to tell the sound system to play some noise. Maybe it has to add a number somewhere keeping track of how many steps you've taken. Maybe it has to send an email to the NSA. Who knows. And when you send the message, you don't have to care. the Player object is responsible for all of that. You are not.
This is the answer to the question "how should I interact with my objects?"
The answer to "Why doesn't what I do work?" is that the types don't match. You're trying to make the player be a BufferedImage object, which is not what you want.
"this.player = walkAnimations[0]"
this.player is a Player type variable.
walkAnimations[0] is a cell of a BufferedImage type array.
Therefore, the line will not compile.
Your question wasn't very clear, but I'll try to give you general guidelines on how to approach OO game programming, since I think essentially that's what your asking.
The key thing in Object Oriented Programming is that entities are represented by classes, and classes hold both the entity's state (the data related with it), and it's operations.
So for example a car can be represented by a Car class. This class will contain what characterizes a car - it's weight, it's color, it's price, etc - and also will contain what it can do - start, drive, stop, etc.
That means that every entity in your game (be it the player, monsters, whatever) should have it's own class. And that class should contain all of the entity's info - e.g. it's position on the screen (x,y), it's image - and also anything it can do (e.g. move on the screen, jump, fire a missile).
Here is a very simple Entity class for example in java-pseudocode. All game entity classes should inherit from this class:
class Entity{
private int x, y; // position on screen
private int dx, dy; // this is how much the entity moves each game-loop cycle.
private Image image;
private Rectangle boundingBox;
private int healthPoints;
public Entity(int x, int y){
// ths position of the thing is set through the constructor
this.x = x;
this.y = y;
dx = 0;
dy = 0;
healthPoints = 100;
Image = new Image(/*some file*/); // this is pseudo code.
boundingBox = new Rectangle(image); // pseudo code. A rectangle the size of the image.
}
public int getX(){ return x; }
public int getY() { return y; }
public Image getImage() { return image; }
// user input can affect this from the outside, to move the entity. or possibly an ai mechanism.
public void setDX(int dx){ this.dx = dx; }
public void setDY(int dy){ this.dy = dy; }
public void move(){
x += dx;
y += dy;
}
public Rectangle getBoundingBox(){ return boundingBox; }
}
Any object derived from this class will hold for itself all of it's data and operations.
Now, your gameloop control manages the entities from the outside and access their data - to move them, check for collisions, display their image, etc.
For example, a very simplified game class holding the game loop. In pseudocode (this is one approach, but it's good to start with something similar):
Class GameClass{
ArrayList entities;
public GameClass(){
entities = new ArrayList();
startGameLoop();
}
private void startGameLoop(){
while(true){ // this is bad, don't do this.
displayEntities(); // step 1 of gameloop.
moveEntities(); // step 2
checkForCollisions(); // step 3
}
}
private void displayEntities(){
for(int i=0; i<entities.size(); i++){
Entity entity = entities.get(i);
displayImage(entity.getImage(),entity.getX(),entity.getY());
}
}
private void updateEntities(){
for(int i=0; i<entities.size(); i++){
Entity entity = entities.get(i);
entity.move();
}
}
private void checkForCollisions(){
for(int i=0; i<entities.size(); i++){
Entity entity = entities.get(i);
for(int j=0; j<entities.size(); j++){
entities.remove(i);
}
}
}
}
This is missing ofcourse logic to get user input. What you can do is for example when the user presses the right arrow, set character.setDX(2), and left arrow will be character.setDX(-2). Remember that dx is the value added to x every cycle, when move() is invoked. This is one approach.
It's also missing tons of other things.
It's impossible to cover all of the basics in this one post. But just remember one thing:
All entities are encapsulated in classes, that hold their own data and operations. Have a central class to manage it all, contating a game loop. Also classes can have methods to interact with other classes.
Hope this helps.
EDIT: Also, here's a series of tutorials that helped me a lot when I was starting out.

Animate a propeller in java

I am trying to animate a propeller in java and have come to this code:
int x = 0;
int y = 230;
int h = 40;
int i = 0;
int center = 250;
void setup() {
size(500, 400);
}
void draw () {
if (i == 0) {
if(y>200) {
ellipse(x, y, 20, h);
y--;
h+=2;
x+=1;
} else { i = i + 1; }
}
if (i == 1) {
if(y<=230) {
ellipse(x, y, 20, h);
y++;
h-=2;
x+=1;
} else { i = i + 1; }
}
if (i == 2) {
if(h<70) {
ellipse(x, y, 20, h);
y++;
h+=1;
x+=1;
} else { i = i + 1; }
}
if (i == 3) {
if(h>=40) {
ellipse(x, y, 20, h);
y--;
h-=1;
x+=1;
} else { i = 0; }
}
}
Is there a way of making this shorter, because I want to have 4 propellers and dont want to have so much code for this part.
You're going about this the wrong way. Very wrong, in fact. And the reason might be that you think you're doing this in "Java...in the program 'processing'"
The reason this sort of thinking is wrong is because it is equivalent to someone working with C++ saying, "I am creating classes in C using the program 'C++'". Processing is based on Java but it is a different programming language. If you're uncomfortable stretching the idea of Processing to that of a "programming language" then at least think of it as a framework...a framework that provides you with its own implementation of various tools that are put together to help with the creation of art using computers.
Now your thinking seems to have affected you in your particular case a lot. Just like Jose Gonzalez above suggested, you haven't even thought about rotate(), which is a function built into Processing. Tim B's suggestion about Objects is spot on as well but if you want to do things in Processing, try to do them the Processing way.
Here's a very quick sketch that I did for you to understand what I mean:
Prop myProp1;
Prop myProp2;
Prop myProp3;
Prop myProp4;
float angle;
void setup() {
size(500, 500);
background(255);
angle = 0;
fill(0);
ellipseMode(CENTER);
myProp1 = new Prop(50,50);
myProp2 = new Prop(75,75);
myProp3 = new Prop(100,100);
myProp4 = new Prop(125,125);
}
void draw() {
background(255);
angle = ((angle + 0.1) % 360);
myProp1.buildAndRotate(angle, width*3/4, height/4);
myProp2.buildAndRotate(angle, width/4, height/4);
myProp3.buildAndRotate(angle, width*3/4, height*3/4);
myProp4.buildAndRotate(angle, width/4, height*3/4);
}
class Prop {
int propX;
int propY;
int propW;
int propH;
Prop() {
propX = 0;
propY = 0;
propW = 50;
propH = 50;
}
Prop(int w, int h) {
propX = 0;
propY = 0;
propW = w;
propH = h;
}
void buildAndRotate(float angle, float moveToX, float moveToY) {
pushMatrix();
translate(moveToX, moveToY);
rotate(angle);
ellipse(propX, propY, propW, propH);
ellipse(propX+propW/2, propY+propH/2, propW, propH);
ellipse(propX-propW/2, propY+propH/2, propW, propH);
ellipse(propX+propW/2, propY-propH/2, propW, propH);
ellipse(propX-propW/2, propY-propH/2, propW, propH);
popMatrix();
}
}
Now, this is by no means meant to be the way to do things in Processing but it uses various tools provided by the programming language to do exactly what you want to do. Also, the Object Prop can be built in various different ways and my implementation is not supposed to be top-notch at all.
So what is going on? Well, run the sketch and you will see four propellers rotating on their own axes. I just put four of them there, you can delete them or add more as you please.
What the hell is a Prop made of? It is made of five ellipses. The concept, and this may be different than yours, is based on the idea of a ceiling fan (or other fans for that matter or even a prop engine). These fans have a circular thing in the middle to which all the blades are attached. The center circle rotates and that results in all the blades around it rotating with it. What you get in the end is a rotating fan.
How is this thing rotating? Similar to the fan analogy above, there is an ellipse in the middle that rotates around its center. There are four ellipses "attached" to it that rotate around this center ellipses. This gives the illusion of a prop rotating. What you have to understand is that in Processing rotate() rotates things around the origin. This is the reason the center ellipse starts at (0,0). Then later in buildAndRotate() it is translated using translate(). Using translate() does not move the object, it instead moves the origin resulting in the object moving with it, and then when you execute rotate() it rotates the object around its center. Since all the other ellipses are built around this center ellipse, they all rotate around it too (in actual implementation, they're just rotating around the origin, you can see that by removing the center ellipse). pushMatrix() and popMatrix() are used so all the translate() and rotate() commands don't affect everything else in the sketch and keep all movements and rotations applied to each object to that very object.
What else is going on? The rest is pretty simple (this is all very simple once you get the hang of it). Background is being cleared constantly which is a common animation technique to give the illusion of movement. You can delete the statement for background() from draw() but I wouldn't recommend it because it will leave a big black round circle after a while and you won't be able to see the props. The angle is being changed constantly in the draw() method which is why you see the props rotating. You can speed up or slow down the rotation by changing that + 0.1 value being added to angle if you want.
What else do I do? Read the reference (not the Java reference, Processing has its own reference) by using Google or following links such as: http://www.processing.org/reference/rotate_.html, http://www.processing.org/reference/pushMatrix_.html, http://www.processing.org/reference/popMatrix_.html, http://www.processing.org/reference/translate_.html, and many more.
Hope this helps and leave questions in the comment if you need clarification on something.
You need to think in terms of objects and iteration rather than writing out everything explicitly. You are correct that the code you have above contains a lot of un-needed duplication, which is a bad thing.
For a more complex case you would define each part of the propeller as an object. Have an array of parts within the Propeller object. Each time to do the draw you run through the list of objects and render each one out.
In this case it can be even simpler, just use a for loop.
At the top of your program define:
private static final int NUM_BLADES = 4;
Then you want a loop that looks something like this:
for (int i=0;i<360;i+=360/NUM_BLADES) {
// Draw elipse at current rotation position + the angle for this blade
}
Now you can change the number of blades just by changing the static define as well.

Java game timing movements

I'm trying to make balls fall from the top of the window. I store ball objects in an ArrayList and, at the moment, I am doing this.
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
if (b.isVisible()) {
b.move();
}
the move function just changes the y co-ordinate of the ball so it drops down the screen.
At the moment, it is all being painted at exactly the same time and fall at exactly the same time.
e.g. http://puu.sh/xsGF
How do I make it so they fall at random intervals?
My move() function is as follows.
public void move() {
if (y > 480) {
this.setVisible(false);
System.out.println("GONE");
}
y += 1;
}
You could add balls randomly during the game loop.
//add new balls randomly here:
if(<randomtest>) {
balls.add(new Ball());
}
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
if (b.isVisible()) {
b.move();
}
else {
//also might be good idea to tidy any invisible balls here
//if you do this make sure you reverse the for loop
}
}
There are 2 things you can do:
Add a Timer. When the Timer goes off (every 10 ms for example), select a random ball, and let that one drop 1px. (Mind, you will get balls that will fall at different speeds at different times, because of the random factor)
Use a random value for the speed when initializing the ball. Increase the y coordinate by that speed value, so the balls will all fall at a different rate through the sceen.
The simplest approach, if you want constant velocity, is to place them im random positions putside the top of your viewport.
Since I guess you already draw them outside the screen just add a random displacement there and you are done. eg:
ball.y = -radius + random.nextInt(100);
Ok, seeing your move function, this is not really physically correct. You should have a acceleration. This makes the ball fall more realistically (of course there is air resistance etc, but I think this is enough for now). In order the let them fall at random times, you could either add them at random times (make them existing/visible at random time instances) or so.
class Ball {
private double acc = 9.81; // or some other constant, depending on the framerate
private double velocity = 0;
private double startFallTime = Math.random()*100; // set from outside, not here!
public void move() {
// check if ball is already here
if (startFallTime-- > 0) return;
if (y > 480) {
this.setVisible(false);
System.out.println("GONE");
}
velocity += acc;
y += velocity;
}
}
EDIT: Of course the acceleration stuff is optional, depending on what you want. If you want linear movement, then your approach is fine, it just looks better if the ball has an acceleration. ;) Also, I recommend adding the balls at random instances and not work with this startFallTime that I used, because this is physically not really correct. Depends on your needs though, so you have to figure out the right way by yourself.

Categories

Resources