I am trying to get animated water tile and I cannot figure it out..
Here, I try to use the modulus to get the remainder and switch it from there, I set it up like I would in my player walking animation. Here is the code I try to use to get it to fluctuate.
public void update() {
if (anim < 1000000) anim++;
else anim = 0;
if(anim % 30 > 20) {
sprite = Sprite.water_;
} else {
sprite = Sprite.water;
}
}
Then within my Main class I put in private WaterTile water; and called it, and put it in my update() method but it decides to not work.
If you would like to look at my overall code, here are my classes involved..:
Game.java http://pastebin.com/6sTePyx0
Tile.java http://pastebin.com/ZtGwdcmt
Sprite.java http://pastebin.com/e7yt9gek
WaterTile.java http://pastebin.com/EMezX4QQ
Related
I am kinda new to Java and LibGdx but for my school project I need to Animate a Player-Sprite.
For only one Animation per Player everything went fine with the Methode I made for this but now I also need a Walking, Idling and Fighting Animation. I managed to get the Animations to switch but the Problem is now, that only one Frame of each Animation gets Displayed. After some research I know that I need to stop updating my Textures every frame but I cant get to know how to do so.
So far Ive tried a simple timer before updating but this just looks weird.
Here is my Code:
public Player(){
img3 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_idle_anim_strip_4.png");
img = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_idle_anim_strip_4.png");
img1 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_run_anim_strip_6.png");
img2 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_sword_attack_anim_strip_4.png");
animation();
changeCharacter();
}
public static void animation(){
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
img3 = img2;
amount = 3;
tileWidth = 32;
}else if(Gdx.input.isKeyPressed(Input.Keys.D) || Gdx.input.isKeyPressed(Input.Keys.A)){
img3 = img1;
tileWidth = 16;
amount = 3;
}else{
img3 = img;
amount = 3;
tileWidth = 16;
}
}
public static void changeCharacter(){
batch = new SpriteBatch();
regions = TextureRegion.split(img3, tileWidth, 16);
sprite = new Sprite(regions[0][0]);
sprite.setPosition(x,y);
Timer.schedule(new Timer.Task() {
#Override
public void run() {
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[0][frame]);
}
}, 0, 1 / 12f);
}
Both Methodes "animation" and "changeCharacter" are called in render().
I know there are simpler solutions for this in LibGdx but the rest of my code is based on this and I basically would have to rewrite the entire Project...
If you need any other classes just ask. I'm probably asking a very easy thing but I dont know what to do with this.
You need to rename first.
img3 looks like it serves the purpose of being the pointer to the currentTextureSet. so when you initialise in Player() you might want to rename img3 to currentTextureSet and then, instead of the duplicate load of herochar_idle_anim_strip_4.png, set
currentTextureSet = img;
after
(you may also want to rename img, img1, img2 to idleTextureSet, runTextureSet and swordAttackTextureSet).
That aside,
definitely get rid of Timer.schedule which you are calling from render will run in a background thread you don't want that.
Looking at the asset pack here https://o-lobster.itch.io/platformmetroidvania-pixel-art-asset-pack?download if this is the same one, the images should be selected left to right i.e. x should be incremented not y. However, it looks like you increment y...
sprite.setRegion(regions[0][frame]); and the incorrect array access is swallowed because in a background timer task and the only textureRegion you can access is [0][0] i.e. you just see a single frame.
So dump this
Timer.schedule(new Timer.Task() {
#Override
public void run() {
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[0][frame]);
}
}, 0, 1 / 12f);
and replace with
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[frame][0]);
*EDIT
So this means that your frame updates with every render, which is too fast. So the -easy fragile way- (not the best which would be deltaTime please read this excellent article https://gafferongames.com/post/fix_your_timestep/ ). The easy way, not the best in the case there is no time left, would be to declare
long renderCallCount =0;
put the above where frame is declared, then in your render method
renderCallCount++; //One more render call
if (renderCallCount % 60 == 0) { //Should I update frame?
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[0][frame]);
}
So whenever renderCallCount is divisible by 60 using the mod operator https://www.edureka.co/blog/mod-method-in-java/ , which would be once a second if your refresh rate is 60hz, then your frame is incremented. To switch frames twice a second change 60 to 30.
This assumes your monitor is ONLY going to run at 60hz. I think your application probably depends on the timing on the refresh rate for position updates so you may want to update that in the future based on some thinking from the article. On a monitor with a faster frame rate everything will speed up (consistently).
I just put some stuff in the right order and it now works! I dont really get why the number after the mod operator needs to be so small but otherwise it just doesnt look right. Also I know that you shouldnt create the Spritebatch in render() but when I do it in the constructor the Program just crashesbecause of the missing Spritebatch??? But thanks for the help :) Here is the working code for anyone whos interested in this:
public static void animation(){
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT) && InfoGame.cl.isGrounded() && current > Enemy.lastDmg + Enemy.dmgCool){
currentTextureSet = attackTexture;
amount = 3;
tileWidth = 32;
}else if(Gdx.input.isKeyPressed(Input.Keys.D) || Gdx.input.isKeyPressed(Input.Keys.A)){
currentTextureSet = runTexture;
tileWidth = 16;
amount = 3;
}else{
currentTextureSet = idleTexture;
amount = 3;
tileWidth = 16;
}
}
public static void changeCharacter(){
batch = new SpriteBatch();
regions = TextureRegion.split(currentTextureSet, tileWidth, 16);
sprite = new Sprite(regions[0][0]);
sprite.setPosition(x,y);
sprite.setOrigin(8,8);
if (renderCallCount % 6 == 0) {
frame++;
if (frame > amount) {
frame = 0;
}
}
sprite.setRegion(regions[0][frame]);
}
I'm creating a game similar to Snake in which my Batman character image collides with the Joker character image and "catches" it. Once the first one disappears, another Joker pops up on the screen in a random spot for the Batman to chase after and then so and so forth.
I've made it so the first Joker disappears when my Batman character collides with it but I'm struggling to get a second Joker to pop on the screen. I'm not sure if a for loop would be best - but then how do I make it so only one Joker appears until Batman "catches" it and then the next can appear - or perhaps an if statement. Any help would be greatly appreciated because I'm feeling really stuck right now.
//loads music for background
import processing.sound.*;
SoundFile file;
String audioName = "dark_knight_rises.wav";
String path;
//loads gif library for background
import gifAnimation.*;
Gif myAnimation;
PImage batman; //pixel images
PImage joker; //pixel images
int batmanX = 100; //batman X position on screen
int batmanY = 100; //batman Y position on screen
int jokerX = 500; //joker X position on screen
int jokerY = 500; //joker Y position on screen
int batman1Size = 50; //for batman distance
int joker2Size = 50; //for joker distance
int width = 100; //width for characters
int height = 100; // height for characters
boolean showImage = true; // boolean to help joker disappear and reappear
int score = 0; // declaration for high score
void setup() {
size(1067, 800);
//plays background music
path = sketchPath(audioName);
file = new SoundFile(this, path);
file.play();
//loads background and pixel-style batman/joker
myAnimation = new Gif(this, "background.gif");
myAnimation.play();
batman = loadImage("pixelbatman.png");
joker = loadImage("pixeljoker.png");
}
void draw() {
image(myAnimation, 0, 0); //lays down gif background
//display the score
textSize(20);
text("Jokers caught:", 900, 40);
text(score, 1045, 40);
image(batman, batmanX, batmanY, width, height); //places Batman character on screen
//pixel batman movement
if (keyPressed) {
if (key == CODED) {
if (keyCode == UP) batmanY--;
if (keyCode == RIGHT) batmanX++;
if (keyCode == DOWN) batmanY++;
if (keyCode == LEFT) batmanX--;
}
} //end of pixel batman movement
if (showImage) image(joker, jokerX, jokerY, width, height); //if Boolean is true, place Joker character on screen
if (dist(batmanX, batmanY, jokerX, jokerY) < (batman1Size + joker2Size)/10 ) { //if batman and joker collide - joker disappears
showImage = false;
score += 1; //increase the score by 1 when batman eats a joker
// idea is that the first joker disappears and another pops up in a random position
if (showImage == false) {
image(joker, random(jokerX, 0), random(0, jokerY), width, height);
}
} // end of what happens if batman and joker collide
} // end of void draw
The answer is easier than you think. In fact, you already did most of the job, you just need a rubber duck.
I'll take that job.
In the draw() function, you do a lot of things. When you have free time, I suggest you break these down a little bit. draw() is the main loop in processing, and as such it'll always tend to be clogged with code. When you do this, aim to have an easily understandable loop, something like this:
void draw() {
drawBackground();
manageInput();
collisions();
drawCharacters();
}
Now, to the matter which interests you:
What you're doing good:
you use clear nomenclature (your naming convention makes things easy to read, a mistake beginners do is to shorten variables names because they know what they are speaking about, then it confuses everybody else including themselves later on)
great job overall with being able to add stuff like gif and sounds!
What we're going to do to achieve the joker thing:
Get rid of the showImage variable. I get what you're doing here, and it was a good idea, but we won't need it.
In the If where you check for a collision, right where you wrote showImage = false, instead we'll update the joker's coordinates:
Like this (I randomized it, but now that you get the idea you can custom this):
jokerX = (int)random(width);
jokerY = (int)random(height);
Delete the if (showImage == false).
Aaand... there you go! If you read well, you'll notice that your mistake wat that, in the if (showImage == false) part, you "teleported" the joker without actually changing his coordinated.
I'll stick around in case you have questions. Have fun!
I am trying to make some movable cars in JFrame(Canvas) to make a game.
I am using this type of code to move the position of the image object.
public void tick() {
z += 1;
}
but it always run once. And it go through JFrame.
How do i make the object to loop infinity like cars?
I am developing an Android game in java where I will have a sprite that follows the user's finger and is supposed to fire a bullet every second. In other words, I am trying to attach a bitmap that moves up every second. The bitmap starts at the x and y coordinates of the main character sprite. I can't get it to draw more than one missile at a time, and I have run out of ideas of how to do so. I have tried so many things, and I really could use some help.
By the way, my Main Game Panel class extends a surfaceView and implements a SurfaceHolder.Callback:
public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback{
Thanks!
As far as I understand you want to have the ability to shoot more than 1 bullet at a time? You can use a Vector or Array to do this. With an Array you can set a default amount of visible bullets and in a Vector you could have as mant bullets that your finger is capable of producing.
Here's my code that I use to generate lasers (I store the values in an Array).
public void updatePlayerLaser(boolean shootLaser) {
// Check if a new Laser should be created
if(shootLaser == true) {
if(timeLastCreatedLaser + 100 < System.currentTimeMillis()) {
timeLastCreatedLaser = System.currentTimeMillis();
boolean createdNewLaser = false;
for(int i = 0; i < this.amountOfVisibleLasers; i++) {
if(createdNewLaser == false) {
if(holderLaser[i].isDisposed()) {
this.generateNewLaser(i);
createdNewLaser = true;
}
}
}
}
}
// Update all the other Lasers
for(int i = 0; i < this.amountOfVisibleLasers; i++) {
if(holderLaser[i].isDisposed() == false) {
holderLaser[i].update();
}
}
}
Disposed in this contexts means that the laser is dead, thus making space for a new laser to take the old lasers spot.
I'm working on a pacman clone in java using eclipse and sometimes it appears laggy more specifically the movement of pacman/ghosts is slow, sometimes its fine. Once it has happened while I was running it so it wasn't after I added code and it doesn't seem to be after any specific event in game. I can't find any trigger or produce the lag on purpose
The resource manager shows the same cpu usage(only around 50%)/memory usage . Aswell the FPS seems to be around 200 consistently through lag and during the periods where it is working well.
Does anyone know what this could be?
Is there any information I left out that could be of use?
edit - I am basing movement on a timer is that bad? I will post the movement relevant code below is there a good way of posting the whole code on here?
Timer movement = new Timer(20, new ActionListener()//500 is time in milliseconds between
//calls to actionPerformed as far as I know.
{
public void actionPerformed(ActionEvent arg0)
{
if(movingUp == true)
{
moveUp();
}
else if(movingDown == true)
{
moveDown();
}
else if(movingRight == true)
{
moveRight();
}
else if(movingLeft == true)
{
moveLeft();
}
}
});
public void moveUp()
{
yPos -= 1;
this.rect.y -= 1;
}
public void setDirUp()
{
movingUp = true;
movingDown = false;
movingRight = false;
movingLeft = false;
}
in the main class in public void keyPressed:
if(keyCode == KeyEvent.VK_W)
{
if(pacMan.isUpHittingWall == false)
{
pacMan.setDirUp();
pacMan.isDownHittingWall = false;
pacMan.isRightHittingWall = false;
pacMan.isLeftHittingWall = false;
}
}
edit 2 -Thanks for the help guys. I have the movement using System time now and it seems to have fixed the issue because I implemented it only for pacman at first and the ghosts were still slow. Now there is an issue where moving right and down are much slower than moving left or up The only difference I see is that right and down are both adding and left and up are subtracting. What can I do about this?
The updated code is below.
//updated movement code
public void moveUp(long timePassed)
{
yPos -= vy * timePassed;
this.rect.y -= vy * timePassed;
}
public void moveDown(long timePassed)
{
yPos += vy * timePassed;
this.rect.y += vy * timePassed;
}
public void moveRight(long timePassed)
{
xPos += vx * timePassed;
this.rect.x += vx * timePassed;
}
public void moveLeft(long timePassed)
{
xPos -= vx * timePassed;
this.rect.x -= vx * timePassed;
}
//I passed timePassed through a globalInputObject because my input is handled in public //void keyPressed(KeyEvent e) and I didnt know how else to get timePassed in to the //movement method
//Here is the code in gameLoop()
globalInputObject.isPacManMovingUp(timePassed);
globalInputObject.isPacManMovingDown(timePassed);
globalInputObject.isPacManMovingRight(timePassed);
globalInputObject.isPacManMovingLeft(timePassed);
//This is inside the GlobalInputObject
public void isPacManMovingUp(long timePassed)
{
if(pacMan.movingUp == true)
{
pacMan.moveUp(timePassed);
}
}
public void isPacManMovingDown(long timePassed)
{
if(pacMan.movingDown == true)
{
pacMan.moveDown(timePassed);
}
}
public void isPacManMovingRight(long timePassed)
{
if(pacMan.movingRight == true)
{
pacMan.moveRight(timePassed);
}
}
public void isPacManMovingLeft(long timePassed)
{
if(pacMan.movingLeft == true)
{
pacMan.moveLeft(timePassed);
}
}
Rather than always moving the pacman by a constant distance (1 pixel, it appears) each time the timer runs, you should:
Set the timer to run as fast as possible (e.g. once every millisecond or less). Edit: if you set it too fast, the game may end up actually running slower, you'll have to experiment.
Calculate how much time has passed between each frame using the system clock and move the pacman by an amount proportional to that.
Doing the above will mean that if the system is "laggy," it will simply show fewer frames per second, rather than actually moving everything slower.
As I feared, you're basing the distance moved on the time chunk from the Timer. You shouldn't do this as all timers can be variable and unreliable, especially with small time chunks. Better to base movement on difference in system time. So yes, use a Timer or something to run your "game loop", but know the sprite's position and velocity using doubles, and calculate the distance to move based on velocity vector (math vector not Java Vector) * difference in system time. That way if the timer is delayed by say garbage collection, making the time chunk larger, the distance moved will be correspondingly greater and will look smoother.
You should look into creating a proper "main loop" or "game loop" as some call it. Take a look at the game structure part of this wikipedia article.. Basically those input events are happening\invoked from a separate thread than the main thread and they are directly modifying geometry of in game objects. Instead consider something like this for a main loop:
loop:
process collision detection
process animation (alters geometry of game objects)
process input (more on this later)
any other game specific logic
render screen
your process input could be something like this
if (globalInputObject.movingUp==true) {
hero.y -= 10;
}
if (globalInputObject.movingDown==true) {
hero.y += 10;
}
if (globalInputObject.movingLeft==true) {
hero.x -= 10;
}
if (globalInputObject.movingRight==true) {
hero.x += 10;
}
and your input handler would look something like this:
public void actionPerformed(ActionEvent evt) {
if (evt.button==UP_BUTTON) {
globalInputObject.movingUp=true;
}
if (evt.button==DOWN_BUTTON) {
globalInputObject.movingDown=true;
}
if (evt.button==LEFT_BUTTON) {
globalInputObject.movingLeft=true;
}
if (evt.button==RIGHT_BUTTON) {
globalInputObject.movingRight=true;
}
}
Basically the processing that you're doing in your "extra" threads (input thread) is minimal and therefore doesn't interfere with your main thread. Also, this method has the benefied of easily supporting multiple directions simultaneously (ie: UP+RIGHT = diagonal).
Only super high end games have more than a single thread (if they even need it at all). Dealing with synchronisation in a game is not good for performance.