Bullet Shooting On Target Algorithm - Java - java

I am making a game where you can shoot. I am having a problem with my algorithm, the bullet is pointing in the direction of the mouse but not moving towards it. Can you please provide me with a better algorithm and tell me why mine does not work? All of this code is in Java. BTW the class MImage is a class that I made so don't get confused by it. `
private double angle;
public Bullet(int xx, int yy, int x, int y,Gun gun, int id, double angle) {
this.x = xx;
this.y = yy;
tx = x;
ty = y;
xorg = xx;
yorg = yy;
this.gun = gun;
this.id = id;
this.angle = angle;
try {
image = new MImage(ImageIO.read(new File("PATH")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
image.rotateBy((int)Math.toDegrees(angle));
stopwatch.start();
}
private int speed = 3,time = 0;;
public void update() {
double speedy, speedx;
speedy = speed * Math.sin(Math.toRadians(angle));
speedx = speed * Math.cos(Math.toRadians(angle));
y = (int) ((-5) * time * time + speedy * time + yorg);
x = (int) (speedx * time + xorg);
time++;
System.out.println(y + " --- " + x);
if(stopwatch.getElapsedTime() > 500) {
terminate(id);
}
}
`
And here is when i make a new instance of the class
public boolean shoot(int x, int y, int tx, int ty) {
boolean worked = false;
if(amo >= 0) {
bullets.add(new Bullet(x,y,tx,ty,this,bullets.size(),Math.atan2(ty-y,tx-x)));
amo --;
worked = true;
}
return worked;
}
THANK YOU

I found an answer to my question. The Algorithm is not hard at all, but it's not perfect but still works. It's simple Trigonometry... if you let angle = Math.atan2(dy,dx) then velocityX = speed*Math.cos(angle) and let velocityY = speed*Math.sin(angle) then in the update function put this code x += velocityX y+= velocityY

Related

TileEntitySpecialRenderer’s isGlobalRenderer() method is ignored

I’m making a mod for Minecraft 1.12. In it I have a tile entity that holds a list of block positions. I want to render a box in the world at each position specified in this list, a bit like how structure blocks display air blocks.
I managed to render the boxes by copying relevent code in TileEntityStructureRenderer but whenever the block associated to the tile entity exits the screen, all boxes stop rendering. I saw on some forums and in TileEntityStructureRenderer’s code that I should override isGlobalRenderer() method and make it return true. So I did, but the problem still persists and I have absolutely no clue as why. I looked up Forge’s docs but there isn’t any information on this that I could find.
Did I miss something? Maybe I’m registering the renderer the wrong way?
Here’s how I register my tile entity and its renderer in my mod’s class (I removed irrelevent code):
#Mod(modid = NaissanceE.MODID, name = NaissanceE.NAME, version = NaissanceE.VERSION)
public class NaissanceE {
public static final String MODID = "naissancee";
public static final String NAME = "NaissanceE";
public static final String VERSION = "1.0";
#Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
if (event.getSide() == Side.CLIENT) {
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityLightOrbController.class, new TileEntityLightOrbControllerRenderer());
}
}
#Mod.EventBusSubscriber
static class EventsHandler {
#SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) {
GameRegistry.registerTileEntity(TileEntityLightOrbController.class, new ResourceLocation(MODID, "light_orb_controller"));
}
}
and the code for the renderer (imports removed for clarity):
#SideOnly(Side.CLIENT)
public class TileEntityLightOrbControllerRenderer extends TileEntitySpecialRenderer<TileEntityLightOrbController> {
#Override
public void render(TileEntityLightOrbController te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
EntityPlayer player = Minecraft.getMinecraft().player;
if ((player.canUseCommandBlock() || player.isSpectator())
&& (player.getHeldItemMainhand().getItem() == ModItems.LIGHT_ORB_TWEAKER
|| player.getHeldItemOffhand().getItem() == ModItems.LIGHT_ORB_TWEAKER)) {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
GlStateManager.disableFog();
GlStateManager.disableLighting();
GlStateManager.disableTexture2D();
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
this.setLightmapDisabled(true);
List<PathCheckpoint> checkpoints = te.getCheckpoints();
for (int i = 0, size = checkpoints.size(); i < size; i++) {
PathCheckpoint checkpoint = checkpoints.get(i);
this.renderCheckpoint(te, x, y, z, checkpoint, tessellator, bufferbuilder);
}
this.setLightmapDisabled(false);
GlStateManager.glLineWidth(1F);
GlStateManager.enableLighting();
GlStateManager.enableTexture2D();
GlStateManager.enableDepth();
GlStateManager.depthMask(true);
GlStateManager.enableFog();
}
}
private void renderCheckpoint(TileEntityLightOrbController te, double x, double y, double z, PathCheckpoint checkpoint, Tessellator tessellator, BufferBuilder bufferBuilder) {
GlStateManager.glLineWidth(3f);
bufferBuilder.begin(3, DefaultVertexFormats.POSITION_COLOR);
BlockPos tePos = te.getPos();
BlockPos checkpointPos = checkpoint.getPos();
final double size = 0.25;
double start = 0.5 - size;
double end = 0.5 + size;
double x1 = checkpointPos.getX() - tePos.getX() + start + x;
double y1 = checkpointPos.getY() - tePos.getY() + start + y;
double z1 = checkpointPos.getZ() - tePos.getZ() + start + z;
double x2 = checkpointPos.getX() - tePos.getX() + end + x;
double y2 = checkpointPos.getY() - tePos.getY() + end + y;
double z2 = checkpointPos.getZ() - tePos.getZ() + end + z;
int r = 0, g = 0, b = 0;
if (checkpoint.isStop()) {
r = 1;
} else {
g = 1;
}
RenderGlobal.drawBoundingBox(bufferBuilder, x1, y1, z1, x2, y2, z2, r, g, b, 1);
tessellator.draw();
}
// FIXME ignored
#Override
public boolean isGlobalRenderer(TileEntityLightOrbController te) {
return true;
}
}
The full code is available here.
So, I just found out that for some reason it seems to not work when I run the game through Intellij but works fine when launching the game through the official laucher…

Delaying bullets with reload function

Hi i'm currently confused on how to add a timer into my program to add a delay in between shooting bullets, and timing a reload function. This is my current code to shoot a bullet where the mouse is located at when I click E. I want to add a delay to this and a reload function on top of it.
#Override
public void keyPressed(KeyEvent e) {
keyPressed[e.getKeyCode()] = true;
if(e.getKeyCode()==KeyEvent.VK_E){
double xVel = mouseX - (player.x+player.width/2-cameraX);
double yVel = mouseY - (player.y-cameraY);
double ratio = Math.sqrt(xVel*xVel+yVel*yVel)/10;
xVel /= ratio;
yVel /= ratio;
lasers.add(new Laser(player.x+player.width/2,player.y,10,10,xVel,yVel));
//System.out.println("Laser added at "+(player.x+player.width/2)+","+player.y);
}
}
This is called from my Laser class.
import java.awt.Color;
import java.awt.Graphics;
public class Laser {
double x, y;
int width, height;
double horizVel, vertVel;
boolean debug = false;
public Laser(int x, int y, int width, int height, double horizVel, double vertVel) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.horizVel = horizVel;
this.vertVel = vertVel;
}
public void draw(Graphics g, int x, int y) {
g.setColor(Color.GREEN);
g.fillRect(x, y, width, height);
if (debug) {
g.drawString("horizVel=" + horizVel, x + width + 3, y);
}
}
public void update() {
x += horizVel;
y += vertVel;
}
public static int getHeight() {
// TODO Auto-generated method stub
return 0;
}
public static int getWidth() {
// TODO Auto-generated method stub
return 0;
}
}
My 1st question is how to implement a timer to my program which will cause a delay between shots. From what I believe I'd have to have a while(True) statement when pressing e to check when the timer is over.
My 2nd question is on how to add a reload timer which tracks the amount of bullets fired, creates a delay "while your reloading" so that you can't fire while this is happening.
Any help is greatly appreciated.
System.currentTimeMillis() will return the current time in milliseconds
so if you do
long pastTime = System.currentTimeMillis();
long currentTime = System.currentTimeMillis();
long timeElapsed = currentTime-pastTime;
// I would control both the reloading time and delay between firing
// time with two separate variables
if(bulletsleft>0){ //Not out of ammo
if( reloadTimer<=0 && bulletDelay<=0){ //delays
fireShot();}
}
else{
reload();
}
This obviously doesn't give a full solution to your questions but is at least one way of thinking about it

Moving ball at an Angle

I am a newbie and trying to move a ball at a slope. Here is the code where I am giving coordinates (100,300,300,600) to move the ball in a slope but it's getting away from the the slope line. Here's the code: -
import javax.swing.*;
import java.awt.*;
public class AgentMotion extends JPanel implements Runnable
{
Color color = Color.red;
int dia = 0;
long delay = 40;
private double x;
private double y;
private double x1;
private double y1;
private int dx = 1;
private int dy = 1;
private int dv = 1;
private double direction;
double a;
double b;
double a1;
double b1;
public void abc(double x, double y, double x2, double y2) {
this.x = x;
this.y = y;
this.x1 = x2;
this.y1 = y2;
this.direction=Math.toRadians(Math.atan2(x1-x,y1-y));
System.out.println("segfewg"+direction);
this.a = x;
this.b = y;
this.a1 = x1;
this.b1 = y1;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
//int x=100;
//int y=200;
int x3=(int)this.x;
int y3=(int)this.y;
g.fillOval(x3,y3,5,5); // adds color to circle
g.setColor(Color.black);
g2.drawOval(x3,y3,5,5); // draws circle
g2.drawLine(100, 300, 300, 600);
}
public void run() {
if(direction<0)
{
System.out.println("refregreg");
while(dy!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
else
{
while(dx!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
}
public void move() {
if(direction>0)
{
if(x + dv*Math.cos(direction) <a ||x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x += dx;
}
else
{
System.out.println(x + dia + dv * Math.cos(direction));
if(x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x -= dx;
}
}
public void move2() {
if(direction>0)
{
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y > b1) {
dy *= 0;
color = getColor();
}
y += dy;
}
else
{
System.out.println(dv * Math.sin(direction) + dia + y);
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y < b1) {
dy *= 0;
color = getColor();
}
y -= dy;
}
}
public Color getColor() {
int rval = (int)Math.floor(Math.random() * 256);
int gval = (int)Math.floor(Math.random() * 256);
int bval = (int)Math.floor(Math.random() * 256);
return new Color(rval, gval, bval);
}
public void start() {
while(dx==0) {
try {
System.out.println("jiuj");
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("dwdwdwd");
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
A few suggestions
dx and dy should be double
atan is overkill as #Spektre says. What you want is much more simple to calculate direction.
this.direction = (y2 - y) / (x2 - x)
If we give (100,300,300,600) as the arguments to abc (which would presumably be a constructor for this class), the slope is 1.5. Therefore we could say:
dx = 1.0
dy = 1.5
and this would keep on the line perfectly. For the general case where you want to change the begin and the end point, you have to calculate the ratio. So you could set either dx or dy to 1.0 and then set the other one so that the ratio is maintained. Something like the following mathematical pseudocode:
dx = (x2 - x) / minimum(x2-x, y2-y)
dy = (y2 - y) / minimum(x2-x, y2-y)

2D Collision issues in Java game

I've been working on this game with LWJGL for a few weeks now. Ever since I added the ability to jump, the upward collision has been giving me a lot of problems.
The game is a 2D tile-based sidescroller. Overall, the collision is almost perfect except for when the player jumps. At first I thought "Oh, maybe I just need to change the jumping mechanics," but then I realized that it only happens when the player is passed a certain x coordinate.
Now, for the actual problem itself: if the player jumps when passed a certain x coordinate, they will pass through the tile and testing for top collision returns false.
This is the entire Player class:
package Minecraft2D;
import static Minecraft2D.World.BLOCK_SIZE;
import Minecraft2D.Tools.Tools;
import Minecraft2D.UI.Inventory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import static Minecraft2D.Boot.*;
import org.lwjgl.util.Rectangle;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
public class Player {
private float x;
private float y;
public int width = 32;
public int height = 50;
private float DX = 0;
private float DY = 0;
private Texture left = null;
private Texture right = null;
Texture texture = null;
public boolean direction[] = { false, false, false, false };
public boolean collision = false;
public boolean ground = false;
public boolean jump = false;
public boolean top = false;
public Player(float x, float y) {
this.x = x;
this.y = y;
try {
this.left = TextureLoader.getTexture("PNG", new FileInputStream(new File(path + "player_left.png")));
this.right = TextureLoader.getTexture("PNG", new FileInputStream(new File(path + "player_right.png")));
this.texture = this.right;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void draw() {
Tools.drawTexture((int)x, (int)y, width, height, texture);
}
public void checkCollision(Player player, Block block) {
if (player.getY() < block.getY() + BLOCK_SIZE && player.getX() < block.getX() + BLOCK_SIZE && player.getY() + this.height > block.getY() && player.getX() + this.width > block.getX() && block.getType() != BlockType.AIR) {
Rectangle top = new Rectangle();
top.setBounds((int) player.x + 4, (int) player.y + 1, this.width - 8, 1);
Rectangle bottom = new Rectangle();
bottom.setBounds((int) player.x + 4, (int) player.y + this.height, this.width - 8, 1);
Rectangle left = new Rectangle();
left.setBounds((int) player.x, (int) player.y + 1, 1, this.height - 5);
Rectangle right = new Rectangle();
right.setBounds((int) player.x + player.width, (int) player.y + 1, 1, this.height - 5);
Rectangle blok = new Rectangle();
blok.setBounds((int) block.getX(), (int) block.getY(), BLOCK_SIZE, BLOCK_SIZE);
if (bottom.intersects(blok)) {
player.setY((block.getY() - this.height - 1));
ground = true;
jump = false;
} else if (top.intersects(blok)) {
DY = 0;
this.top = true;
y -= (player.y) - (block.getY() + BLOCK_SIZE);
}
if (!top.intersects(blok)) {
if (left.intersects(blok)) {
player.setX(block.getX() + this.width);
} else if (right.intersects(blok)) {
player.setX(block.getX() - this.width);
}
}
} else {
collision = false;
ground = false;
}
if (!collision && !jump) {
setDY(.003f);
}
if (ground && !jump) {
DY = 0;
}
if (jump && DY < 0.003f) {
DY += 0.0001;
} else {
// jump = false;
}
if (top) {
DY = 0f;
top = false;
}
x += DX;
y += DY;
if (x > Boot.SCREEN_WIDTH) {
x = 0;
}
if (x < 0) {
x = Boot.SCREEN_WIDTH;
}
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public void setDX(float dx) {
this.DX = dx;
}
public void setDY(float dy) {
this.DY = dy;
}
public void setJump() {
if (!jump) {
jump = true;
ground = false;
DY = -0.13f;
y -= 1;
}
}
public void setTexture(int tex) {
if (tex == 0) {
this.texture = this.left;
}
if (tex == 1) {
this.texture = this.right;
}
}
}
==============
EDIT: I have no clue why, but as my character moves closer to the map's 0 x-coordinate, the character's y coordinate increases very slowly. This probably has something to do with the problem I have been getting. I am looking into it and I have a suspicion that it may have something to do when I cast the player's x and y values from doubles to integers for use in the top, bottom, left, and right Rectangles.
EDIT again:
I don't know if this matters, but I have been checking collision like this: (This is in the "Boot" class.)
private void checkCollision() {
for (int x = 0; x < BLOCKS_WIDTH - 1; x++) {
for (int y = 0; y < BLOCKS_HEIGHT - 1; y++) {
Block blk = grid.getAt(x, y);
player.checkCollision(blk);
}
}
}
Why are you passing a player into checkCollision? It seems like you should not be passing in a player, but instead using the members of the player that's calling the checkCollision method. I think that may be leading to some confusion for you. Such as:
y -= (player.y) - (block.getY() + BLOCK_SIZE);
This looks like you are trying to push the player below the block b/c they intersected it during their jump. If that's the case, it should just be
y = (block.getY() + BLOCK_SIZE);
I would remove the player from the function argument and rewrite the function and see what you get. Hope that helps.
EDIT
Your comment states that you can no longer pass the player into the function. Not sure about your exact implementation, but here's what games that I have typically seen look like:
public class Player
{
private int x, y, dx, dy;
public void checkCollision(Block block)
{
if (isTopCollision(block))
fall(block.getY() + block.getHeight());
}
private boolean isTopCollision(Block block)
{
return y > block.getY() + block.getSize() && y < block.getY();
}
private void fall(int adjustedY)
{
y = adjustedY;
top = true;
dy = 0;
// etc
}
}
public class MyGame
{
public void gameloop()
{
for (Block b : blocks)
player.checkCollision(b);
}
}

Custom network library and serialzation VS default Serialization and RMI

I have this class, I m sending this class via RMI and via kryonet and kryo, I m getting the array of 10 objects with both incase of rmi, as return of remote method call and in case of kryonet echoing from server to client with kryonet and kryo, I have total of one object 55*10 which 555 but with RMI 1196bytes ,
Are these results are reasonable?, can some body shed some light,
*why these results are like that?
why there is that much difference.?
which overheads or other factors are involved behind the scene,
which are making that much total in RMI and too much difference and point me.
And is it 55 bytes total for single object is ok?*.
i just need some confirmation and experts eyes as i have to present these results,
I will be really thankful.
This is class which I m using with both:
public class TBall {
private float x, y; // Ball's center (x, y)
private float speedX, speedY; // Ball's speed per step in x and y
private float radius; // Ball's radius
private Color color; // Ball's color
public boolean collisionDetected = false;
public static boolean run = false;
private String name;
private float nextX, nextY;
private float nextSpeedX, nextSpeedY;
public TBall() {
super();
}
public TBall(String name1, float x, float y, float radius, float speed,
float angleInDegree, Color color) {
this.x = x;
this.y = y;
// Convert velocity from polar to rectangular x and y.
this.speedX = speed * (float) Math.cos(Math.toRadians(angleInDegree));
this.speedY = speed * (float) Math.sin(Math.toRadians(angleInDegree));
this.radius = radius;
this.color = color;
this.name = name1;
}
public String getName() {
return this.name;
}
public float getSpeed() {
return (float) Math.sqrt(speedX * speedX + speedY * speedY);
}
public float getMoveAngle() {
return (float) Math.toDegrees(Math.atan2(speedY, speedX));
}
public float getRadius() {
return radius;
}
public Color getColor() {
return this.color;
}
public void setColor(Color col) {
this.color = col;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public void setX(float f) {
x = (int) f;
}
public void setY(float f) {
y = (int) f;
}
public void move() {
if (collisionDetected) {
// Collision detected, use the values computed.
x = nextX;
y = nextY;
speedX = nextSpeedX;
speedY = nextSpeedY;
} else {
// No collision, move one step and no change in speed.
x += speedX;
y += speedY;
}
collisionDetected = false; // Clear the flag for the next step
System.out.println("In serializedBall in move.");
}
public void collideWith() {
float minX = 0 + radius;
float minY = 0 + radius;
float maxX = 0 + 640 - 1 - radius;
float maxY = 0 + 480 - 1 - radius;
double gravAmount = 0.9811111f;
double gravDir = (90 / 57.2960285258);
// Try moving one full step
nextX = x + speedX;
nextY = y + speedY;
System.out.println("In serializedBall in collision.");
// If collision detected. Reflect on the x or/and y axis
// and place the ball at the point of impact.
if (speedX != 0) {
if (nextX > maxX) { // Check maximum-X bound
collisionDetected = true;
nextSpeedX = -speedX; // Reflect
nextSpeedY = speedY; // Same
nextX = maxX;
nextY = (maxX - x) * speedY / speedX + y; // speedX non-zero
} else if (nextX < minX) { // Check minimum-X bound
collisionDetected = true;
nextSpeedX = -speedX; // Reflect
nextSpeedY = speedY; // Same
nextX = minX;
nextY = (minX - x) * speedY / speedX + y; // speedX non-zero
}
}
// In case the ball runs over both the borders.
if (speedY != 0) {
if (nextY > maxY) { // Check maximum-Y bound
collisionDetected = true;
nextSpeedX = speedX; // Same
nextSpeedY = -speedY; // Reflect
nextY = maxY;
nextX = (maxY - y) * speedX / speedY + x; // speedY non-zero
} else if (nextY < minY) { // Check minimum-Y bound
collisionDetected = true;
nextSpeedX = speedX; // Same
nextSpeedY = -speedY; // Reflect
nextY = minY;
nextX = (minY - y) * speedX / speedY + x; // speedY non-zero
}
}
System.out.println("In serializedBall collision.");
// speedX += Math.cos(gravDir) * gravAmount;
// speedY += Math.sin(gravDir) * gravAmount;
System.out.println("In serializedBall in collision.");
}
}
Thanks.
Where did you get '55' from? You have:
9 floats, = 9x4 bytes, total 36 bytes
1 boolean, serialized as a byte, total 1 byte
1 String, could be any length
1 Color, which in turn contains:
1 int, serialized as 4 bytes
1 float, serialized as 4 bytes
2 float[] of length 3 each, serialized as 24 bytes
1 Colorspace, which in turn contains:
2 ints, serialized as 8 bytes
The total of this is at least 77 bytes plus whatever is required to transmit the String.
Serialization also sends class information, versioning information, and a tag in front of every item; RMI also sends method information. All that could easily account for the difference. I don't know what those other packages do.

Categories