I have a player class, and it's x, and y positions are manipulated with a xPos and yPos, and I want to create a camera that follows the player.
So far I've tried this:
Camera class:
import org.newdawn.slick.GameContainer;
public class Camera {
public int offsetMaxX;
public int offsetMaxY;
public int offsetMinX;
public int offsetMinY;
public int camX;
public int camY;
private Player player;
public Camera(Player p) {
//Setting offset max's and minimums
offsetMaxX = 0;
offsetMaxY = 0;
offsetMinX = 0;
offsetMinY = 0;
player = p;
}
public void update(GameContainer gc) {
camX = player.xPos - (gc.getWidth() / 2);
camY = player.yPos - (gc.getHeight() / 2);
}
}
And my render function in my main class is:
#Override
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
//Translate to camera X and Y
g.translate(-camera.camX, -camera.camY);
//Scaling map
g.scale(3, 3);
//Rendering map
try {
mapRender.render();
} catch (SlickException e1) {
e1.printStackTrace();
}
//Draw player
player1.drawPlayer(g);
}
This works, but the camera moves slower than the player does. How could I fix this code, or is there a better way to do this?
I fixed it myself. When drawing my player, I did
g.translate(.5, .5);
So when positioning my camera, I had to do
camX = ((player.xPos * 1.5f)) - (gc.getWidth() / 2);
camY = (player.yPos * 1.5f) - (gc.getHeight() / 2);
Related
I am trying to create a background scrolling for an Android game. Lets say it is a set of images moving at a speed.
To test out few basic elements, I have taken a small, rectangular image and moving it linearly from top to bottom. It moves but I see a small trail, like a rocket going in clouds(haha!). I tried various options in Paint() class to rectify this, but I couldn't.
I will first post a screen shot and then add relevant code.
So, here the vertical line is a single png image:
Now all I am doing is moving this bitmap from a certain (x,y) by increasing y by 5 at a time. It moves, but notice the ends of the image while moving. Sort of a trail, but not a permanent one. I have tried but unable to remove this effect. I tried on Samsung Galaxy S5. I didnot test on any other model.
The code:
The moving vertical image is a Sprite object:
package com.src.*.*;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.Log;
public class Sprite {
private Rect sourceRect; // the rectangle to be drawn from the animation bitmap
private int frameNr; // number of frames in animation
private int currentFrame; // the current frame
private long frameTicker; // the time of the last frame update
private int framePeriod; // milliseconds between each frame (1000/fps)
private int spriteWidth; // the width of the sprite to calculate the cut out rectangle
private int spriteHeight; // the height of the sprite
private int x; // the X coordinate of the object (top left of the image)
private int y; // the Y coordinate of the object (top left of the image)
private Bitmap bitmap;
private float degrees;
private boolean rotate=false;
private Matrix matrix;
private Bitmap reversedBitmap;
private Paint paint;
public Sprite(Bitmap bitmap, int x, int y, int fps, int frameCount) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
currentFrame = 0;
frameNr = frameCount;
spriteWidth = bitmap.getWidth() / frameCount;
spriteHeight = bitmap.getHeight();
sourceRect = new Rect(0, 0, spriteWidth, spriteHeight);
framePeriod = 1000 / fps;
frameTicker = 0l;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG
| Paint.FILTER_BITMAP_FLAG);
paint.setDither(true);
}
public void animate(){
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void setReverse(Bitmap reverse){
this.reversedBitmap = reverse;
}
public void rorateSprite(float degrees){
if(degrees == 0){
rotate = false;
}else{
rotate = true;
}
this.degrees = degrees;
}
public void draw(Canvas canvas) {
// where to draw the sprite
Rect destRect = new Rect(getX(), getY(), getX() + spriteWidth, getY() + spriteHeight);
if(rotate){
canvas.drawBitmap(reversedBitmap, sourceRect, destRect, paint);
}else{
canvas.drawBitmap(bitmap, sourceRect, destRect, paint);
}
}
public void update(long gameTime){
if (gameTime > frameTicker + framePeriod) {
frameTicker = gameTime;
//Log.i("INFO", "In if loop" + currentFrame + " framenr:" + frameNr);
// increment the frame
currentFrame++;
if (currentFrame >= frameNr) {
currentFrame = 0;
}
}else{
//Log.i("INFO", "in else" + currentFrame + "");
}
// define the rectangle to cut out sprite
//Log.i("INFO", "sprite width: " + spriteWidth);
this.sourceRect.left = currentFrame * spriteWidth;
this.sourceRect.right = this.sourceRect.left + spriteWidth;
}
}
The bitmap is setup as follows:
wallAnimation = new Sprite(resizedBitmapWall, 0, 0, 30, 1);
wallAnimation.setX(margin);
The onDraw and Update for the sprite is as follows. It works without any exception or error. The only issue in all of this is the image having the blurry/tail effect at the ends. I dont even know the right word for it.
Code for onDraw and Update:
#Override
protected void onDraw(Canvas canvas) {
// fills the canvas with black
canvas.drawColor(Color.WHITE);
wallAnimation.draw(canvas);
paint.setColor(Color.BLACK);
for (int i = 0; i < 6; i++) {
canvas.drawLine(margin+laneWidth*i, 0, margin+laneWidth*i, laneHeight, paint);
}
canvas.drawText("High Score: "+ highScore, 10, 10, paint);
}
public void Update(long gameTime) {
// TODO Auto-generated method stub
if(wallState < laneHeight+laneHeight/6){
wallAnimation.setY(wallState);
//wallState+=laneHeight/80;
wallState+=20;
}else{
wallState = 0;
}
}
We are having trouble making our character animate in a java slick2d game. The tutorial I seen shows doing it how I have done it. Right now it only shows the 1st image when going left or right. It never cycles between the 2 images set in walkLeft and walkRight.
import org.newdawn.slick.*;
import org.newdawn.slick.state.*;
public class Game extends BasicGameState {
Animation cowboy;
Animation movingLeft;
Animation movingRight;
Image background;
boolean quit = false;
int[] animationDuration = {200,200};
float cowboyPositionX = 0;
float cowboyPositionY = -370;
float shiftX = cowboyPositionX + 200;
float shiftY = cowboyPositionY + 830;
public Game(int state) {
}
public void init(GameContainer gc, StateBasedGame sbg)
throws SlickException {
background = new Image("images/background.png");
Image[] walkLeft = { new Image("images/cowboyleft1.png"), new Image("images/cowboyleft2.png") };
Image[] walkRight = { new Image("images/cowboyright1.png"), new Image("images/cowboyright2.png") };
movingLeft = new Animation(walkLeft, animationDuration, false);
movingRight = new Animation(walkRight, animationDuration, false);
cowboy = movingRight;
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g)
throws SlickException {
background.draw(cowboyPositionX, cowboyPositionY);
cowboy.draw(shiftX, shiftY);
g.drawString("Cowboy's X:" + cowboyPositionX + "\nCowboy's Y: "
+ cowboyPositionY, 400, 20);
}
public void update(GameContainer gc, StateBasedGame sbg, int delta)
throws SlickException {
Input input = gc.getInput();
if (input.isKeyDown(Input.KEY_LEFT)) {
cowboy = movingLeft;
cowboyPositionX += horizontalSpeed;
if (cowboyPositionX > 0) {
cowboyPositionX -= delta * horizontalSpeed;
}
}
if (input.isKeyDown(Input.KEY_RIGHT)) {
cowboy = movingRight;
cowboyPositionX -= horizontalSpeed;
if (cowboyPositionX < -2975.0) {
cowboyPositionX += delta * horizontalSpeed;
}
}
public int getID() {
return 1;
}
}
In your update method try inserting cowboy.update(delta); that should work. It worked for the program that I have been working on.
I'm new to libgdx, I'm trying to make a sprite move while the camera follows. I can make the sprite move perfectly until I attach the camera to it. When I click, the sprite will move wherever it feels like (it seems) and the camera will follow properly. I've tried a few different things but at this point its just guessing and checking.
public class MyGdxGame implements ApplicationListener {
OrthographicCamera mCamera;
SpriteBatch mBatch;
Texture mTexture, mMap;
Sprite sprite;
float touchX, touchY;
float spriteX, spriteY, speed = 5;
#Override
public void create() {
float CAMERA_WIDTH = 480, CAMERA_HEIGHT = 320;
mBatch = new SpriteBatch();
mTexture = new Texture(Gdx.files.internal("data/logo.png"));
mMap = new Texture(Gdx.files.internal("data/sc_map.png"));
mCamera = new OrthographicCamera(CAMERA_WIDTH, CAMERA_HEIGHT);
mCamera.setToOrtho(false, CAMERA_WIDTH, CAMERA_HEIGHT);
}
#Override
public void dispose() {
}
#Override
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
mBatch.setProjectionMatrix(mCamera.combined);
mCamera.update();
mBatch.begin();
updateInput();
drawD();
mBatch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
public void drawD() {
mCamera.position.set(spriteX, spriteY, 0);
mBatch.draw(mMap, 0, 0);
mBatch.draw(mTexture, spriteX, spriteY);
}
public void updateInput() {
if (Gdx.input.justTouched()) {
touchX = Gdx.input.getX();
touchY = Gdx.input.getY();
}
if (touchX != spriteX) {
if (spriteX < touchX) {
spriteX += speed;
}
if (spriteX > touchX) {
spriteX -= speed;
}
}
if (touchY != spriteY) {
if (spriteY > Gdx.graphics.getHeight() - touchY) {
spriteY -= 10;
}
if (spriteY < Gdx.graphics.getHeight() - touchY) {
spriteY += 10;
}
}
}
}
Since you have spent a decent amount of time and are trying to get it working, I will give you a little push forward closer to what you are looking for. Look over the changes I made and below I will outline what I did to help you understand the code better.
Orthographic Camera, when you setup the camera 0,0 is the center of the screen. The width and the height are what you specified into the constructor. So the top edge would be x, 160 and the bottom edge would be x, -160. The left edge would be -240, y and the right edge would be 240, y.
drawD() Notice that I'm drawing the sprite in the middle of the image and it isn't moving. I instead move the map around in the opposite direction (y is inverted).
updateInput() Notice I pass in a delta value (this is the time in seconds between frames) this allows you to smoothly move things. The speed is 120, so this will smoothly move your character at a rate of 120/second.
The if condition is basically a simply way to compare the float values so it stops when it gets close enough. This prevents it from over shooting the target position and then bouncing back and forth because it might not be able to get to the exact value.
I added dispose calls for the textures you loaded, these are important as you don't want to fill up your memory.
I hope this helps get you started and pointed in the right direction. Working on games is a lot of work and takes time, so be patient and be ready to learn lots along the way!
Based on your comment I believe what you are looking for is something closer to this:
public class MyGdxGame implements ApplicationListener {
OrthographicCamera mCamera;
SpriteBatch mBatch;
Texture mTexture, mMap;
float touchX, touchY;
float spriteX, spriteY, speed = 120;
final float CAMERA_WIDTH = 480, CAMERA_HEIGHT = 320;
#Override public void create() {
mCamera = new OrthographicCamera(CAMERA_WIDTH, CAMERA_HEIGHT);
mBatch = new SpriteBatch();
mTexture = new Texture(Gdx.files.internal("data/logo.png"));
mMap = new Texture(Gdx.files.internal("data/sc_map.png"));
}
#Override public void dispose() {
mTexture.dispose();
mMap.dispose();
}
#Override public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
updateInput(Gdx.graphics.getDeltaTime());
mCamera.update();
mBatch.setProjectionMatrix(mCamera.combined);
mBatch.begin();
drawD();
mBatch.end();
}
#Override public void resize(final int width, final int height) {}
#Override public void pause() {}
#Override public void resume() {}
public void drawD() {
mBatch.draw(mMap, -spriteX - (mMap.getWidth() / 2), spriteY - (mMap.getHeight() / 2));
mBatch.draw(mTexture, -32, -32, 64, 64);
}
public void updateInput(final float delta) {
if (Gdx.input.justTouched()) {
touchX = Gdx.input.getX() - (Gdx.graphics.getWidth() / 2);
touchY = Gdx.input.getY() - (Gdx.graphics.getHeight() / 2);
}
final float dv = delta * speed;
if (Math.abs(touchX - spriteX) > 1) {
if (spriteX < touchX) {
spriteX += dv;
}
if (spriteX > touchX) {
spriteX -= dv;
}
}
if (Math.abs(touchY - spriteY) > 1) {
if (spriteY > touchY) {
spriteY -= dv;
}
if (spriteY < touchY) {
spriteY += dv;
}
}
}
}
In my game I'm making, I need NPC's/mobs.
I made a class called peasant (my first mob).
In the main class from which the game is running, I have all the information, as well as calling an object called mob1 from Peasant
I need to make it so that if the player is within 300 pixels of the mob, it starts to move towards it. Ive tried doing this but so far, even if the player is 2000 pixels away, the mob starts moving???
Here is my Peasant class
package Entitys.NPCs;
public class Peasant {
public Peasant(float InitX, float InitY, int MobID){
MobX = InitX;
MobY = InitY;
}
//This class shall be used as an object creator. This will randomly move a graphic around, near to a player
private float MobX;
private float MobY;
private int AmountMoved = 0;
private boolean MoveRight = true;
private boolean MoveLeft;
public boolean PlayerDetected = false;
long timer;
//Used to find the mobs X
public float getX(){
return MobX;
}
//Used to find the mobs Y
public float getY(){
return MobY;
}
//Used to set the mobs X
public void setX(float X){
MobX = X;
}
//Used to set the mobs Y
public void setY(float Y){
MobY = Y;
}
//Used to simply move the mob on its X co-ords
public void moveX(int delta){
MobX += delta*0.1f;
}
//Used to simply move the mob on its Y co-ords
public void moveY(int delta){
MobY += delta*0.1f;
}
public void autoEveryThing(int delta, float playerX, float playerY) {
// If the player has not been spotted the NPC/Mob will move left and
// right by 100 Pixels.
if(MobX-300<playerX){
PlayerDetected=true;
}
if(PlayerDetected=true){
if(MobX>playerX){
MobX-=delta*0.12;
}
}
}
}
And here is the main class:
package Worlds.World1;
import org.lwjgl.input.Mouse;
import org.newdawn.slick.Animation;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import Entitys.NPCs.*;
import Main.SimpleMob;
public class World1A extends BasicGameState{
String mousePosition;
Image world;
Animation player, playerLeft, playerRight;
int[] duration = {200,200};
float playerX;
float playerY;
float WorldX;
float WorldY;
float PlayerVisibleScreenX;
float PlayerVisibleScreenY;
String MovementDirection;
Peasant mob1;
public World1A(int state){
}
public void init(GameContainer gc, StateBasedGame sbg) throws SlickException{
Image [] WalkingLeft = {new Image("res/Sprites/buckysLeft.png"),new Image("res/Sprites/buckysLeft.png")};
Image [] WalkingRight = {new Image("res/Sprites/buckysRight.png"),new Image("res/Sprites/buckysRight.png")};
playerLeft = new Animation(WalkingLeft, duration, false);
playerRight = new Animation(WalkingRight, duration, false);
player = playerRight;
WorldX = 0;
WorldY = 0;
world= new Image("res/WorldImages/WorldBackGround.png");
mousePosition="null";
MovementDirection = "Not Moved Yet";
mob1= new Peasant(2000, 200, 1);
if(WorldX<=0){
playerX = Math.abs(WorldX);
}else{
playerX=0-WorldX;
}
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{
player.draw(450, 300);
if(WorldX>0){
world.draw(0, 0);
g.fillOval(0+mob1.getX(), 0+mob1.getY(), 50, 50);
g.fillRect(0, 0+340, 500, 10);
player.draw(-WorldX + 450, 300);
}else{
world.draw(WorldX, WorldY);
g.fillOval(WorldX+mob1.getX(), WorldY+mob1.getY(), 50, 50);
g.fillRect(WorldX, WorldY+340, 500, 10);
g.fillOval(WorldX+mob1.getX(), WorldY+mob1.getY(), 50, 50);
player.draw(450, 300);
}
g.setColor(Color.white);
//All this is co-ords ect, it is for developement help
g.drawString(String.valueOf(mob1.getX()), 50, 200);
g.drawString("World X: "+ String.valueOf(WorldX), 50, 225);
g.drawString("Player X: "+ String.valueOf(playerX), 50, 250);
g.drawString("Player Detetcted?: "+ String.valueOf(mob1.PlayerDetected), 50, 265);
}
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
if(WorldX<=0){
playerX = Math.abs(WorldX);
}else{
playerX=0-WorldX;
}
mob1.autoEveryThing(delta, playerX, playerY);
int posX = Mouse.getX();
int posY = Mouse.getY();
mousePosition = "X: " + posX + "\nY: " + posY;
Input input = gc.getInput();
if(input.isKeyDown(Input.KEY_LEFT)){
WorldX += delta * 0.1f;
MovementDirection = "Left";
player = playerLeft;
}else if(input.isKeyDown(Input.KEY_RIGHT)){
WorldX -= delta * 0.1f;
MovementDirection = "Right";
player = playerRight;
}else{
MovementDirection = "Not Moving";
}
}
//DO NOT CHANGE
public int getID(){
return 2;
}
}
The autoEveryThing method in the Peasant class should make it so that if(mobX-300
But when I first run this it starts moving towards the player?
even though (2000-300<0) is false, it still sets the PlayerDetected boolean to true???
Why does this happen?
Thanks
EDIT:
After trying to go through thi and fix it I found somthing strange, even if I take out the whole bit which can change PlayerDetected to true, the mob still moves towards the player. This meens that PlayerDetected is becominbg true somwhere, but I cant figure out where?
if(PlayerDetected=true){
is wrong you should use ==
if(PlayerDetected==true){
or even better
boolean isPlayerDetected;
if (isPlayerDetected)
further consider
double dx = mobX - playerX;
double dy = mobY - playerY;
double distance = Math.sqrt(dx*dx + dy*dy);
if (distance < 300) {
// is within distacne threshold
}
I'm trying to make a java sand game and can't get past one bit. i've made my method that draws a rectangle at mouseX and mouseY, and i have set it up so it updates every frame so it constantly follows the mouse.
what i assume is that i would use an array to create each rectangle, and from there would use a pre-defined algorithm to float to the ground, I'm all good with that, i just don't understand how to 'hook my method' up to an array.
This is the method i am using to draw the rectangle (in it's own class called Methods)
import org.newdawn.slick.Graphics;
public class Methods {
public Graphics g = new Graphics();
public int sizeX = 4;
public int sizeY = 4;
public void drawParticle(float x, float y){
g.drawRect(x, y, sizeX, sizeY);
}
}
And this is my main class
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class Control extends BasicGameState {
public static final int ID = 1;
public Methods m = new Methods();
int mouseX;
int mouseY;
public void init(GameContainer container, StateBasedGame game) throws SlickException{
}
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
m.drawParticle(mouseX, mouseY);
}
public void update(GameContainer container, StateBasedGame game, int delta) {
}
public void mouseReleased(int button, int x, int y){
mouseX = 0;
mouseY = 0;
}
public void mouseDragged(int oldx, int oldy, int newx, int newy) {
mouseX = newx;
mouseY = newy;
}
public int getID() {
return ID;
}
}
but when i click, just one rectangle follows the mouse, instead of many being created AT the mouse :L
Public Variables:
Rectangle boxes[] = new Rectangle[maxnum];
int boxnum = 0;
On mouse move:
boxes[boxnum] = new Rectangle[e.getX(), e.getY(), sizeX, sizeY);
boxnum = boxnum + 1;
When drawing your particles:
counter = 0;
do
{
g.drawRect(boxes[counter].x, boxes[counter].y, sizeX, sizeY);
counter = counter + 1;
} while (counter < maxnum);
Where maxnum is the maximum number of boxes you will have. This way you can store multiple rectangles in your array and go through the array and draw them when you update the screen. Hope this helps.