I have a class which spawns an enemy, and a class that spawns a player. At the moment they are both 2 circles coming towards each other. I have made a collision detection function for when they crash, but I can't make it work. I have made the function outside the classes and try to call the position variables of each class, but it says I can't make a static reference to a non static field. I have also tried the collision detection in each class which also doesn't work.
class Player {
int Pos_X;
int Pos_Y;
int Speed;
Player(int x, int y, int speed) {
this.Pos_X = x;
this.Pos_Y = y;
this.Speed = speed;
}
void Update() {
ellipse(Pos_X, Pos_Y, 40, 40);
Pos_X += Speed;
}
}
class Enemy {
int Pos_X;
int Pos_Y;
int Speed;
Enemy(int x, int y, int speed) {
this.Pos_X = x;
this.Pos_Y = y;
this.Speed = speed;
}
void Update() {
ellipse(Pos_X, Pos_Y, 40, 40);
Pos_X -= Speed;
}
}
Player Player1;
Enemy Enemy1;
void setup() {
size (500, 500);
Player1 = new Player (0, 200, 3);
Enemy1 = new Enemy (500, 200, 3);
}
void draw() {
background(200);
Player1.Update();
Enemy1.Update();
if (intersectsBox(Player.Pos_X, Player.Pos_Y)) {
ellipse(100, 100, 100, 100);
}
}
boolean intersectsBox(float X, float Y) {
if (X > Enemy.Pos_X && X < Enemy.Pos_X + 40) {
if (Y > Enemy.Pos_Y && Y < Enemy.Pos_Y + 40) {
return true;
}
}
}
To use a variable that's in a class, you have to refer to an instance of that class. In your code, Enemy is a class, and Enemy1 is an instance of that class. So when you try to do this:
if (X > Enemy.Pos_X && X < Enemy.Pos_X + 40) {
Processing gives you an error because you're using the class, not an instance. Processing doesn't know which Enemy you're talking about. Instead, you have to do something like this:
if (X > Enemy1.Pos_X && X < Enemy1.Pos_X + 40) {
Now Processing knows which instance of the Enemy class you're talking about. You might also pass in an instance of Enemy as a parameter to that function, that way you can use it to collide with multiple enemies.
And just a general piece of advice: your code would be much easier to read if you followed standard formatting and naming conventions- indent your code (Processing will do it for you if you press ctrl+t in the editor), and make sure only classes start with an upper-case letter. Methods and variables should start with lower-case letters.
Related
class Bullet {
float bulletX, bulletY;
float angle;
int x;
int y;
int score; // add a score variable
static final float BULLET_SPEED = 5; // define a constant for the bullet's speed
Bullet(float x, float y, float angle) {
this.bulletX = x;
this.bulletY = y;
this.angle = angle;
}
// Updates the position of the bullet based on its angle and speed.
void update() {
bulletX += cos(angle) * BULLET_SPEED;
bulletY += sin(angle) * BULLET_SPEED;
}
// Draws the bullet image on the screen.
void show() {
drawBullet();
}
// Draws the bullet image on the screen.
void drawBullet() {
image(Bulletimg, bulletX, bulletY);
Bulletimg.resize(30, 30);
}
//Returns true if the bullet is off screen, false otherwise.
boolean offScreen() {
return bulletX < 0 || bulletX > width || bulletY < 0 || bulletY > height;
}
//Checks if the bullet hits the enemy, and updates the score and enemy position accordingly.
// check for collision
void checkCollision(Enemy e) {
float distance = dist(bulletX, bulletY, e.x, e.y);
if (distance < e.x / 2) {
// assuming enemy.size is the radius of the
}
}
}
I tried changing around the check collision(enemy e) block and I'm not sure how i would go about removing an enemy object and also updating my score. i've tried messing about with the draw(); method but i cant seem to figure it out without breaking my entire game. any help with this class would be much appreciated.
You can use/create some attribute in your Enemy object to know/check if is alive or death.
For example in your check collision you can add
if (distance < e.x / 2) {
// assuming enemy.size is the radius of the
e.alive = false
}
Edit: I dont know how your manage the Enemy object and if it can be modified directly in the check collision method if this is not possible then you need to find a way to have access inside the method or use a return and manage that return outside.
I have a moving image as a background
PImage background;
int x=0; //global variable background location
rocket Rocket;
void setup(){
size(800,400);
background = loadImage("spaceBackground.jpg");
background.resize(width,height);
Rocket = new rocket();
}
void draw ()
{
image(background, x, 0); //draw background twice adjacent
image(background, x+background.width, 0);
x -=4;
if(x == -background.width)
x=0; //wrap background
Rocket.defender();
Rocket.move();
}
In a different class i'm trying to make a rocket move up and down
class rocket {
float x;
float y;
float speedy;
boolean up;
boolean down;
rocket(){
x = 50;
y = 200;
speedy = 3;
}
void move() {
if(up)
{
y = y - speedy;
}
if(down)
{
y = y + speedy;
}
}
void defender(){
fill(255,0,0);
rect(x,y,50,20);
triangle(x+50,y,x+50,y+20,x+60,y+10);
fill(0,0,100);
rect(x,y-10,20,10);
}
void keyPressed(){
if(keyCode == UP)
{
up = true;
}
if(keyCode == DOWN)
{
down = true;
}
}
void keyReleased(){
if(keyCode == UP)
{
up = false;
}
if(keyCode == DOWN)
{
down = false;
}
}
}
The rocket will display but won't move. I tried everything I know but nothing works. I also tried the rocket class just as a project by itself and the rocket moves, so it has to be something with the class. i'm quite new to coding so please keep that in mind, thank you in advance.
The keyPressed() and keyReleased() functions (and any other event function) need to be at the sketch level, not inside another class. If they're inside another class, Processing doesn't know how to find them.
So, what you need to do is move the keyPressed() and keyReleased() functions to the sketch, and then call functions on your Rocket class (class names should start with an upper-case letter, btw), similar to how you're calling rocket.defender() and rocket.move() (variable names should start with a lower-case letter) from the sketch-level draw() function.
So, as the title reads I am trying to add offsets to my java game. I was given a tip by a friend that I need to minus the offset from where I render the tiles onto my screen.
So I created a random world generator and did the offset thing, but I ran into a problem.
My Code:
public void generateMap(Graphics g) {
block = seed.nextInt(2);
//Render Dirt
if(block == 0) {
g.drawImage(Assets.dirt, x - GameState.xOffset, y - GameState.yOffset, null);
x += 32;
}
//Render Grass
if(block == 1) {
g.drawImage(Assets.grass, x - GameState.xOffset, y - GameState.yOffset, null);
x += 32;
}
//Check Where the X is
if(x > xFinish) {
if(y < yFinish) {
x = xStart;
y += 32;
}
}
}
looks simple enough right? after I do that I create code to add one to the offset every time I loop around:
public void tick() {
xOffset += 1;
}
So after that is done I run it but it does this:
is there any simple way I can fix this so that it appears that the screen "scrolls" to the left?
Is there any simple way I can fix this...
Probably not. Games are complicated. Don't let that dissuade you.
You are generating your game world and drawing in the same methods - you don't want to do this. Separation of responsibility is very important - you don't want a whole bunch of code in one spot doing the same thing. In this case, the functionality to generate the world and the drawing code need to be split.
For the world generation, generate the game world once, and persist it to storage using whatever format you like. Keep this away from the drawing code - it has no place there.
For representing blocks in your world, consider something like this:
class Block {
public BlockType getType() {
return type;
}
public int getxPosition() {
return xPosition;
}
public int getyPosition() {
return yPosition;
}
// hashCode(), equals(), etc omitted, they should be implemented
public static enum BlockType {
Dirt(Assets.dirt),
Grass(Assets.grass);
private final BufferedImage image;
BlockType(BufferedImage image) {
this.image = image;
}
public BufferedImage getImage() {
return image;
}
}
private final BlockType type;
private final int xPosition;
private final int yPosition;
private Block(BlockType type, int xPosition, int yPosition) {
this.type = type;
this.xPosition = xPosition;
this.yPosition = yPosition;
}
public static Block getInstance(BlockType type, int xPosition, int yPosition) {
return new Block(type, xPosition, yPosition);
}
}
You can then use Block.getInstance() to generate a map once, like this:
class GameState {
private final int WORLD_SIZE = 1024;
private Block[][] _world = new Block[WORLD_SIZE][WORLD_SIZE];
private static Random seed = new Random();
public void generateMap() {
int blockTypeLength = Block.BlockType.values().length;
for (int x = 0; x < WORLD_SIZE; x++) {
for (int y = 0; y < WORLD_SIZE; y++) {
int blockType = seed.nextInt(blockTypeLength);
_world[x][y] = Block.getInstance(Block.BlockType.values()[blockType], x, y);
}
}
}
public Block[][] getMap() {
return _world; // not thread safe, shares internal state, all the usual warnings
}
This obviously isn't the only way to generate a world - you would probably generate a world and save, then load from disk in later games (unless it was a short lived game - I don't know, that's your call).
Once you've got the world sorted out, you'd move on to a different module that would handle drawing. Assume GameState has two fields playerX and playerY that represent the player's coordinates in the game world (note: direct fields like this are bad practice, but used to simplify this example):
public void paintComponent(Graphics g) {
super.paintComponent(g);
Block[][] screen = new Block[16][16]; // declare a screen buffer to draw
// Assumes player is in the center of the screen
int screenRadiusX = GameFrame.Assets.SCREENBOUNDS_X / 2 / blockSize;
int screenRadiusY = GameFrame.Assets.SCREENBOUNDS_Y / 2 / blockSize;
for (int x = state.playerX - 8, xS = 0; x < state.playerX + 8; x++, xS++) {
for (int y = state.playerY - 8, yS = 0; y < state.playerY + 8; y++, yS++) {
screen[xS][yS] = world[x][y];
}
}
for (int x = 0; x < screen.length; x++) {
for (int y = 0; y < screen.length; y++) {
Block current = screen[x][y];
g.drawImage(current.getType().getImage(),
x * blockSize, // blockSize is the pixel dimension of
y * blockSize,
null
);
}
}
}
If this helps, then great! I'm glad I was able to help. If not, or if some ideas are still unclear, then I would consider perhaps running through a tutorial or book that walks you through making a game. Don't forget to learn the platform you're coding on during such a process.
Please look at the following structure of my pong game.
gameLoop(); method
//Only run this in another Thread!
private void gameLoop()
{
//This value would probably be stored elsewhere.
final double GAME_HERTZ = 30.0;
//Calculate how many ns each frame should take for our target game hertz.
final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
//At the very most we will update the game this many times before a new render.
//If you're worried about visual hitches more than perfect timing, set this to 1.
final int MAX_UPDATES_BEFORE_RENDER = 5;
//We will need the last update time.
double lastUpdateTime = System.nanoTime();
//Store the last time we rendered.
double lastRenderTime = System.nanoTime();
//If we are able to get as high as this FPS, don't render again.
final double TARGET_FPS = 60;
final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;
//Simple way of finding FPS.
int lastSecondTime = (int) (lastUpdateTime / 1000000000);
while (running)
{
double now = System.nanoTime();
int updateCount = 0;
if (!paused)
{
//Do as many game updates as we need to, potentially playing catchup.
while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
{
updateGame();
lastUpdateTime += TIME_BETWEEN_UPDATES;
updateCount++;
}
//If for some reason an update takes forever, we don't want to do an insane number of catchups.
//If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
{
lastUpdateTime = now - TIME_BETWEEN_UPDATES;
}
//Render. To do so, we need to calculate interpolation for a smooth render.
float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
//float interpolation = 1.0f;
drawGame(interpolation);
lastRenderTime = now;
//Yield until it has been at least the target time between renders. This saves the CPU from hogging.
while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
{
Thread.yield();
//This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it.
//You can remove this line and it will still work (better), your CPU just climbs on certain OSes.
//FYI on some OS's this can cause pretty bad stuttering. Scroll down and have a look at different peoples' solutions to this.
try {Thread.sleep(1);} catch(Exception e) {}
now = System.nanoTime();
}
}
}
}
updateGame(); method
if(p1_up){
if(player.equals("p1")){
p1.moveUp();
}
else
{
p2.moveUp();
}
}
else if(p1_down){
if(player.equals("p1")){
p1.moveDown();
}
else
{
p2.moveDown();
}
}
moveUp(); moveDown(); method of paddle
public void moveUp(){
last_y = y;
last_x = x;
y -= 50.0;
}
public void moveDown(){
last_y = y;
last_x = x;
y += 50.0;
}
drawGame(interpolation); method
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i=0;i<balls.size();i++){
paintBall(g, balls.get(i));
}
drawPaddle(g, p1);
drawPaddle(g, p2);
}
public void drawPaddle(Graphics g, Paddle p){
paddle_drawX = (int)((p.x - p.last_x)*interpolation + p.last_x);
paddle_drawY = (int)((p.y - p.last_y)*interpolation + p.last_y);
g.drawRect(paddle_drawX, paddle_drawY, 10, 50);
}
I am a beginner in game programming so i don't have a good idea about game loops. I found the above fixed time-step game loop in the internet and used it as the game loop for my game. The loop makes the ball move smoothly but the paddle isn't staying at one place when moved. When I move my paddle by pressing one down key stroke then the paddle keeps shaking
without stopping in one spot. The y coordinates of the paddle keeps changing like
33, 45, 20, 59, 34, 59, 34, 59, 33, 59, 34, 58
I know the problem is in interpolation value as it keeps changing value that will change the y coordinate of paddle in render. I have been thinking about this for a while and i don't know how to make the game loop work for any movements so i have come here for some help. I appreciate any suggestion/help!
Here is my full Paddle class.
public class Paddle
{
float x;
float y;
float last_y;
float last_x;
public Paddle(int x, int y)
{
this.x = x;
this.y = y;
this.last_x = x;
this.last_y = y;
}
public void setNewX(int d){
last_y = y;
last_x = x;
x = d;
}
public void setNewY(int d){
last_y = y;
last_x = x;
y = d;
}
public void moveUp(){
last_y = y;
last_x = x;
y -= 50.0;
}
public void moveDown(){
last_y = y;
last_x = x;
y += 50.0;
}
}
and i initiate the paddle position in the main class through global variable.
public Paddle p1 = new Paddle(10, 10);
public Paddle p2 = new Paddle(950, 10);
I have following event listeners for handling key strokes.
Action handle_up_action = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_up = true;
}
};
Action handle_up_action_released = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_up = false;
}
};
Action handle_down_action = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_down = true;
}
};
Action handle_down_action_released = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_down = false;
}
};
What are you trying to achieve with interpolation? From my understanding, it represents the percentage of time elapsed between previous previous and next "update time".
So it should progress continuously from 0 to 1 each 33.3 ms.
I don't know how you use this interpolation variable in the paintBall method, but for the paddles, it will draw your paddle at a "pseudo random position" between p.x;p.y and p.last_x;p.last_y (depending on the time between the two updateGame()).
In order to correct this, from your loop logic, you should understand that every game entity (balls, paddles, ...) must have two states (the positions):
- the logical state, which is updated only each TIME_BETWEEN_UPDATES
- the visual state, which can be updated anytime, at each render.
It is the same as if you have a set of points (which represent the logical states) and you want to interpolate anywhere between this points (reprensenting the visual state).
Your code is like this.
First solution
The simplest way to correct the paddle shaking, is to avoid the interpolation and use:
public void drawPaddle(Graphics g, Paddle p){
paddle_drawX = (int)p.x;
paddle_drawY = (int)p.y;
g.drawRect(paddle_drawX, paddle_drawY, 10, 50);
}
But your movement will look like this (visual position will be changed only each TIME_BETWEEN_UPDATES)
Second solution
You want p.x;p.y to be the logical position, but the visual position should be interpolated between p.last_x;p.last_y and the logical position if the rendering is done between the input processing and the next updateGame(): you must reset p.last_x;p.last_y when updateGame() is called. To achieve this, call the paddles' updateMovement() method inside updateGame().
public void updateMovement(){
last_y = y;
last_x = x;
}
You can have other solutions, such as to use a speed variable or a movement function, in order to have a smooth movement, accelerations, and so on. It is mainly a generalisation of second solution. It requires bigger changes, but it is more flexible and powerful. To achieve this, you may want to store in paddles the last "update position", and all movement-related variables, such as movement start date. Add a method to retrieve the "visual position" that can be called with any date between two updates, and a method to update the "logical position" called each updateGame().
I have a game of a rocket landing game, where the player is the rocket and you must land it safely at the right speed on the landing pad. This was taken from www.gametutorial.net
Its actually for educational purposes and I recently added a still meteor in the game.
When the player hits the meteor (touches) the game is over.
if(...) {
playerRocket.crashed = true;
}
My problem is there I need to replace the "..." with the actual condition that "Has the rocket crashed into the meteor?"
Plus the following variables (coordinates, height and width) for use -
[All Integers]:
X and Y coordinates: playerRocket.x, playerRocket.y, meteor.x, meteor.y
Height and Width: playerRocket.rocketImgHeight, playerRocket.rocketImgWidth, meteor.meteorImgHeight, meteor.meteorImgWidth
For collision detection in 2D games, you can use rectangles. I'd use a base class called GObject and inherit all objects in the game from it.
public class GObject
{
private Rectangle bounds;
public float x, y, hspeed, vspeed;
private Image image;
public GObject(Image img, float startx, float starty)
{
image = img;
x = startx;
y = starty;
hspeed = vspeed = 0;
bounds = new Rectangle(x, y, img.getWidth(null), img.getHeight(null));
}
public Rectangle getBounds()
{
bounds.x = x;
bounds.y = y;
return bounds;
}
}
There's also other methods like update() and render() but I'm not showing them. So to check for collision between two objects use
public boolean checkCollision(GObject obj1, GObject obj2)
{
return obj1.getBounds().intersects(obj2.getBounds());
}
Also, there's a specific site for game related questions. Go to Game Development Stack Exchange
You need to check if you hit the object, meaning, if the click coordinates are within the object's Rectangle.
if( playerRocket.x + playerRocket.width >= clickX && playerRocket.x <= clickX &&
playerRocket.y + playerRocket.height >= clickY && playerRocket.Y <= clickY ) {
playerRocket.crashed = true;
}