I want to make a game wherein when the main character sprite's X coordinate is less than the middle of the screen, he moves to the right and when it's more than the middle of the screen, he moves to the left. The sprite's animation changes when he is moving and when he is still (after reaching its destination). What I want to know is how can I do this when the sprite and its code for animation is in one class and the code for changing its X coordinate is in another class? Is it best to draw the same sprite in every class? How can I change the sprite when it is moving horizontally and when it is still? I plan to separate the code for what the sprite's actions will be in different classes because i want to call them randomly. Here is my code for the sprite's animation and i have no class for changing the x coordinate yet :
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.jpfalmazan.ninjaassault.NinjaAssault;
public class MainScreen implements Screen {
private static final int FRAME_COLS = 3;
private static final int FRAME_ROWS = 2;
Animation walkAnimation;
Texture walkSheet = new Texture ("ninjaWalk.png");
TextureRegion[] walkFrames;
TextureRegion currentFrame;
Texture holdStart;
float stateTime;
public Texture background;
private NinjaAssault game;
private Music BackgroundSFX;
public float screenWidth = Gdx.graphics.getWidth();
public float screenHeight = Gdx.graphics.getHeight();
float x = screenWidth/2;
float y = screenHeight/2;
public float walkSheetWidth = walkSheet.getWidth();
public float walkSheetHeight = walkSheet.getHeight();
public MainScreen (NinjaAssault game){
this.game = game;
}
#Override
public void show(){
background = new Texture("BGBlue.png");
holdStart = new Texture ("HoldStart.png");
BackgroundSFX = Gdx.audio.newMusic(Gdx.files.internal("data/RADWIMPS-iindesuka.mp3"));
TextureRegion[][] tmp = TextureRegion.split(walkSheet, (int )walkSheetWidth/FRAME_COLS, (int) walkSheetHeight/FRAME_ROWS);
walkFrames = new TextureRegion[FRAME_COLS*FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++){
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation(0.0887f, walkFrames);
stateTime = 0f;
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
float hsWidth = holdStart.getWidth();
float hsHeight = holdStart.getHeight();
float currentFrameWidth = (float)(screenHeight*0.15);
float currentFrameHeight = (float)(screenHeight*0.15);
float holdStartWidth = (float)(screenWidth * 0.75);
game.batch.begin();
game.batch.draw(background,0,0, screenWidth,screenHeight);
BackgroundSFX.play();
game.batch.draw(currentFrame, x -currentFrameWidth/2, 0,currentFrameWidth,currentFrameHeight);
game.batch.draw(holdStart, (screenWidth / 2 - (holdStartWidth / 2)), (float) (screenHeight * 0.5), holdStartWidth, holdStartWidth * (hsHeight / hsWidth));
game.batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
BackgroundSFX.dispose();
background.dispose();
walkSheet.dispose();
holdStart.dispose();
}
}
I tried to research on how to do this but the answers I get wasn't that helpful.
Simplest way is to create a Player class and put all the code for the animation and frames in there. Then give it a way to save its position. Like a vector or just a float for the x coordinate. Or even better, use a Rectangle. A rectangle will make moving and collision detection much easier.
Something like this:
public class Player{
private Animation walkAnimation;
private Texture walkSheet;
private TextureRegion[] walkFrames;
private TextureRegion currentFrame;
private float stateTime;
private Rectangle bound; //used for positioning and collision detection
public Player(float x, float y, float width, float height){
bound = new Rectangle();
bound.x = x;
bound.y = y;
bound.width = width;
bound.height = height;
walkSheet = new Texture ("ninjaWalk.png");
TextureRegion[][] tmp = TextureRegion.split(walkSheet,(int)walkSheetWidth/FRAME_COLS, (int) walkSheetHeight/FRAME_ROWS);
walkFrames = new TextureRegion[FRAME_COLS*FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++){
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation(0.0887f, walkFrames);
stateTime = 0f;
}
public rectangle getBound(){
return bound;
}
public void update(float delta){
statetime += delta;
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
}
public TextureRegion getCurrentFrame(){
return currentFrame;
}
}
This is just a quick untested example.
You say you want to move the player from another class. I don't know how you plan to do that, but all you need to do to move the player is to manipulate the x and y of the bound.
Just some other comments on you code:
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
player.update(delta); // to update the player
/***
* This does not have to be set every single frame. Move it to show()
*
float hsWidth = holdStart.getWidth();
float hsHeight = holdStart.getHeight();
float currentFrameWidth = (float)(screenHeight*0.15);
float currentFrameHeight = (float)(screenHeight*0.15);
float holdStartWidth = (float)(screenWidth * 0.75);
****************************************************/
BackgroundSFX.play(); // I am sure you don't need to start playing this every single frame? 60 times a second.
game.batch.begin();
game.batch.draw(background,0,0, screenWidth,screenHeight);
game.batch.draw(player.getCurrentFrame(), player.getBound().x, player.getbound().y, player.getBound().width, player.getBound().height)
game.batch.draw(holdStart, (screenWidth / 2 - (holdStartWidth / 2)), (float) (screenHeight * 0.5), holdStartWidth, holdStartWidth * (hsHeight / hsWidth));
game.batch.end();
}
Related
I have a animation which i want to flip to the left if key LEFT is pressed, but it doesnt stay flipped. It only flips like 1 frame then turns back again.
Here is my GameScreen where i draw everything:
public class GameScreen extends ScreenManager{
//For the view of the game and the rendering
private SpriteBatch batch;
private OrthographicCamera cam;
//DEBUG
private Box2DDebugRenderer b2dr;
//World, Player and so on
private GameWorld world;
private Player player;
private Ground ground;
//player animations
private TextureRegion currFrame;
public static float w, h;
public GameScreen(Game game) {
super(game);
//vars
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
//view and rendering
batch = new SpriteBatch();
cam = new OrthographicCamera();
cam.setToOrtho(false, w/2, h/2);
//debug
b2dr = new Box2DDebugRenderer();
//world, bodies ...
world = new GameWorld();
player = new Player(world);
ground = new Ground(world);
}
#Override
public void pause() {
}
#Override
public void show() {
}
#Override
public void render(float delta) {
//clearing the screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//updating
update(Gdx.graphics.getDeltaTime());
player.stateTime += Gdx.graphics.getDeltaTime();
//render
batch.setProjectionMatrix(cam.combined);
currFrame = Player.anim.getKeyFrame(Player.stateTime, true);
batch.begin();
batch.draw(currFrame, Player.body.getPosition().x * PPM - 64, Player.getBody().getPosition().y * PPM- 72);
batch.end();
//debug
b2dr.render(GameWorld.getWorld(), cam.combined.scl(PPM));
}
#Override
public void resize(int width, int height) {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
#Override
public void onKlick(float delta) {
}
public void update(float delta){
world.update(delta);
updateCam(delta);
Player.keyInput(delta);
System.out.println("X-POS" + Player.getBody().getPosition().x);
System.out.println("Y-POS" + Player.getBody().getPosition().y);
}
public void updateCam(float delta){
Vector3 pos = cam.position;
pos.x = Player.getBody().getPosition().x * PPM;
pos.y = Player.getBody().getPosition().y * PPM;
cam.position.set(pos);
cam.update();
}
}
and this is the Player class where the animation is:
public class Player {
public static Body body;
public static BodyDef def;
private FixtureDef fd;
//textures
public static Texture texture;
public static Sprite sprite;
public static TextureRegion[][] region;
public static TextureRegion[] idle;
public static Animation<TextureRegion> anim;
public static float stateTime;
//set form
private PolygonShape shape;
private GameScreen gs;
public Player(GameWorld world){
texture = new Texture(Gdx.files.internal("player/char_animation_standing.png"));
region = TextureRegion.split(texture, texture.getWidth() / 3, texture.getHeight() / 2);
idle = new TextureRegion[6];
int index = 0;
for(int i = 0; i < 2; i++){
for(int j = 0; j < 3; j++){
sprite = new Sprite(region[i][j]);
idle[index++] = sprite;
}
}
anim = new Animation<TextureRegion>(1 / 8f, idle);
stateTime = 0f;
def = new BodyDef();
def.fixedRotation = true;
def.position.set(gs.w / 4, gs.h / 4);
def.type = BodyType.DynamicBody;
body = world.getWorld().createBody(def);
shape = new PolygonShape();
shape.setAsBox(32 / 2 / PPM, 64/ 2 / PPM);
fd = new FixtureDef();
fd.shape = shape;
fd.density = 30;
body.createFixture(fd);
shape.dispose();
}
public static Body getBody() {
return body;
}
public static BodyDef getDef() {
return def;
}
public static Texture getTexture() {
return texture;
}
public static void keyInput(float delta){
int horizonForce = 0;
if(Gdx.input.isKeyJustPressed(Input.Keys.UP)){
body.applyLinearImpulse(0, 300f, body.getWorldCenter().x, body.getWorldCenter().y, true);
//body.applyForceToCenter(0, 1200f, true);
System.out.println("PRESSED");
}
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
horizonForce -= 1;
sprite.flip(!sprite.isFlipX(), sprite.isFlipY());
}
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
horizonForce += 1;
}
body.setLinearVelocity(horizonForce * 20, body.getLinearVelocity().y);
}
}
thank you in advance and any answer is appreciated :D
Your sprite variable contain only one frame at the time of pressing left key. So, it flip that current sprite of your animation frame.
To solve the Problem you have to flip all the animation frame on pressing the left key.
You're only flipping last frame of Animation by sprite reference, You need to flip all frames of your Animation anim. You can flip in this way :
if(keycode== Input.Keys.RIGHT) {
for (TextureRegion textureRegion:anim.getKeyFrames())
if(!textureRegion.isFlipX()) textureRegion.flip(true,false);
}
else if(keycode==Input.Keys.LEFT) {
for (TextureRegion textureRegion:anim.getKeyFrames())
if(textureRegion.isFlipX()) textureRegion.flip(true,false);
}
So I am trying to generate random rectangles that the player must avoid. My collision method was working with a single, randomly generated rectangle. I want to draw 10 or so of these and then I will add a finish line and a timer.
Right now, I understand my problem, but I am not sure how to fix it. The ball/player's movement is executed by changing the x or y coordinates by 10 and then repainting the circle. I currently have the rectangles in the same paint method, so each time the player moves the rectangles are regenerated. I would like them to stay in the same place after the initial random generation. I don't really know how to do this though...
Also, if I can get the rectangles to stay in the same place, will my collision method still work with multiple rectangles? or would I need to revise that as well?
I am just going to post the whole program's code because I'm not sure which parts will need to be revised.
import java.awt.*;
import java.awt.Rectangle;
import java.awt.Shape;
import javafx.scene.shape.*;
import java.awt.event.*;
import java.util.Random;
import java.awt.geom.Area;
import javax.swing.JOptionPane;
import java.applet.Applet;
public class Main extends Applet
implements ActionListener{
boolean end = false;
private Rectangle rectangle;
//creates buttons to move player
private Button run = new Button("Run");
private Button jump = new Button("Jump");
private Button fall = new Button("Fall");
//creates player and obstacles
private Circle player = new Circle(110,110,20);
private makeRect block = new makeRect(150, 120, 30, 10);
//initiates the buttons with actionListener
public void init(){
add(run);
add(jump);
add(fall);
run.addActionListener(this);
jump.addActionListener(this);
fall.addActionListener(this);
}
//draws the player and blocks on the screen
public void paint(Graphics g){
for(int numBlocks = 0; numBlocks<11; numBlocks++){
block.draw(g);}
player.draw(g);
}
//if methods to be control movement
public void actionPerformed(ActionEvent e){
if(e.getSource() instanceof Button){
if(e.getSource() == run)
player.horiz(10);
else if (e.getSource()== jump){
player.vert(-10);
}
else if (e.getSource()== fall){
player.down(10);
}
repaint();
collision();
}
}
public void collision(){
if(player.getBounds().intersects(block.getBounds())){
JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
end = true;
}
}
class Circle{
private final Color theColor = Color.BLUE;
private int radius;
private int x,y;
public Circle(){
x = 110; y = 110;
radius = 20;
}
public Circle(int x0, int y0, int rad){
x = x0; y = y0; radius = rad;
}
public void draw(Graphics g){
g.fillOval(x - radius, y-radius, 2*radius, 2*radius);
g.setColor(theColor);
}
public void horiz(int val){
for(int c = 0; c<val+1; c++){
x++;
repaint();}
}
public void vert(int val){
y += val;
}
public void down(int val){
y += val;
}
public Rectangle getBounds(){
return new Rectangle(x-radius, y-radius, 2*radius, 2*radius);
}
}
class makeRect{
private int Xmax = 250;
private int Xmin = 140;
private int Wmax = 50;
private int Hmax = 25;
private int Wmin = 10;
private int Hmin = 5;
Random rand = new Random();
private int randx;
private int randh;
private int x, y, width, height;
public makeRect(){
x = 150; y = 120;
width = 30; height = 10;
}
public makeRect(int x0, int y0, int w0, int h0){
x = x0; y = y0; width = w0; height = h0;
}
public void draw(Graphics g) {
int randx = rand.nextInt((Xmax-Xmin)+1)+Xmin;
int randh = rand.nextInt((Hmax-Hmin)+1)+Hmin;
int randw = rand.nextInt((Wmax-Wmin)+1)+Wmin;
g.drawRect(randx, 110+randh, randh, randw);
}
public Rectangle getBounds(){
return new Rectangle(randx, 110+randh, 30, 10);
}
}
}
Thanks!
For that you will need to construct 10 rects (consider using array) first upon initialization, with random postition for each. I mean, postition randomization occurs when the rects are constructed, not when it's drawn.
What you have there is a same rectangle drawn 10 times at different places each time the paint() gets called.
Here is my Core project :
public class GameClass extends Game {
public static int screenWidth, screenHeight;
public static CustomScreen currentScreen;
public static PlayScreen playScreen;
#Override
public void create () {
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
CustomScreen.initialize();
playScreen = new PlayScreen(this);
SetScreen(playScreen);
}
public void SetScreen(CustomScreen screen) {
currentScreen = screen;
setScreen(currentScreen);
}
}
public abstract class CustomScreen implements Screen {
GameClass game;
static BitmapFont font;
static SpriteBatch batcher;
static OrthographicCamera cam;
public CustomScreen(GameClass game) {
this.game = game;
}
public static void initialize() {
cam = new OrthographicCamera();
cam.setToOrtho(true, GameClass.screenWidth, GameClass.screenHeight);
batcher = new SpriteBatch();
batcher.setProjectionMatrix(cam.combined);
font = new BitmapFont();
font.setScale(4f, -4f);
}
public void Clear() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
#Override
public abstract void render(float delta);
}
public class PlayScreen extends CustomScreen {
public static final int speed = 300;
public ArrayList<Entity> entityList;
Random rand = new Random();
float timer = rand.nextInt(2) + rand.nextFloat();
public PlayScreen(GameClass game) {
super(game);
entityList = new ArrayList<Entity>();
}
void update(float delta) {
timer -= delta;
if (timer <= 0) {
entityList.add(new Enemy(GameClass.screenWidth, rand.nextInt(GameClass.screenHeight - Enemy.Height)));
timer += rand.nextInt(2) + rand.nextFloat() + 1/2;
}
for (int i = entityList.size(); i > 0; --i)
entityList.get(i-1).update(delta);
}
#Override
public void render(float delta) {
Clear();
update(delta);
batcher.begin();
for (int i = 0; i < entityList.size(); ++i) {
entityList.get(i).Display(batcher);
}
if (entityList.size() > 1)
System.out.println(entityList.get(1).posX - entityList.get(0).posX);
batcher.end();
}
}
public abstract class Entity {
protected Sprite sprite;
public int posX, posY, width, height;
public Entity(int posX, int posY, int width, int height) {
this.posX = posX;
this.posY = posY;
this.width = width;
this.height = height;
}
public abstract void update(float delta);
public void Display(SpriteBatch batcher) {
batcher.draw(sprite, posX, posY, width, height);
}
}
public class Enemy extends Entity {
static Sprite texture = new Sprite(new Texture(Gdx.files.internal("enemy.png")));
public static int Width = 300, Height = 200;
public Enemy(int posX, int posY) {
super(posX, posY, Width, Height);
this.sprite = Enemy.texture;
}
#Override
public void update(float delta, int i) {
posX -= delta * PlayScreen.speed;
if (posX + width < 0) {
GameClass.playScreen.entityList.remove(this);
}
}
}
In PlayScreen, enemies keep spawning randomly, and they move from the right of the screen to the left, at a constant speed (final int 300). But when they reach the left edge of the screen (when posX <= 0), they slow down, for an unknown reason. The thing is, I didn't program anything to happen when an enemy reaches the edge of the screen. (I programmed them to disappear when they are completely outside of the screen, when posX + width <= 0, but it has nothing to do with my problem, since even when I remove this, they keep slowing down when reaching the edge of the screen).
It happends with both the desktop and the android projects, so this definitely comes from the Core project.
I have no idea why this happens, this is really, really awkward.
Here is a couple picture to show you what happens.
http://i.stack.imgur.com/DrOSH.png
http://i.stack.imgur.com/Zjtju.png
We can see that the two enemies are closer to each other on the second picture than on the first one.
You can set PlayScreen.speed to 100 instead of 300, it will be even more noticeable.
And if you set it to a low enough value, like 20, enemies will not just slow down, they will basically stop moving.
I'm lost and have no idea how to fix this problem. If you have any, please feel free to share it.
I fixed it. The problem was that Enemy.posX was an int instead of a float.
I'm not quite certain but I'd guess that your calculations in the Enemy class involving delta get rounded (since PlayScreen.Speed is an integer).
Having a low enough PlayScreen.Speed or a low enough delta will result in delta * PlayScreen.Speed being 0.something which will get cut off to 0 when converting to an integer, resulting in posX never changing.
I usually use floats for all calculations involving positions (e.g. posX and posY and so on...) so that this cutting off doesn't happen until something gets drawn on the screen (since pixels are always integers). This produces more accurate results and solves a lot of problems around movement on the screen.
I have made a class for the level generation and have got so far with it:
public class LevelGenerator {
private Sprite environment;
private float leftEdge, rightEdge, minGap, maxGap, y;
public Enemy enemy;
public LevelGenerator(Sprite environment, float leftEdge, float rightEdge,
float minGap, float maxGap) {
this.environment = environment;
this.leftEdge = leftEdge;
this.rightEdge = rightEdge;
this.minGap = minGap;
this.maxGap = maxGap;
}
public void generate(float topEdge){
if(y + MathUtils.random(minGap, maxGap) < topEdge)
return;
y = topEdge;
float x = MathUtils.random(leftEdge, rightEdge);
}
Basically, what I want to happen is for the enemy block to randomly generate on the sides of the screen. Here is the enemy block class (very simple):
public class Enemy extends Sprite{
public Enemy(Sprite sprite) {
super(sprite);
}
#Override
public void draw(Batch spriteBatch){
super.draw(spriteBatch);
}
}
This is what the game looks like at the moment when the block is just simply drawn on the game screen in a static position: http://i.imgur.com/SIt18Qn.png. What I am trying to achieve is for these "enemy" blocks to spawn randomly on either side of the screen but I can't seem to figure out a way to do it with the code I have so far.
Thank you!
I could not test but I think it will be fine, you have a rectangle if you want to see if it collides with another actor, if so updates its position in the update and draw method, and ramdon method start customizing to see if the coordinates, which colicionan be assigned to another actor rectagulo enemy or bye.
public class overFlowEnemy extends Sprite {
private final float maxH = Gdx.graphics.getHeight();
private final float maxW = Gdx.graphics.getWidth();
private Rectangle rectangle;
private Random random = new Random();
private float inttt = 0;
private float randomN = 0;
private boolean hasCollided = false;
public overFlowEnemy(Sprite sprite) {
super(sprite);
crearEnemigo();
rectangle = new Rectangle(getX(), getY(), getWidth(), getHeight());
}
#Override
public void draw(Batch spriteBatch) {
super.draw(spriteBatch);
}
private void crearEnemigo(){
setX(RandomNumber((int)maxW));
setY(RandomNumber((int)maxH));
}
private int RandomNumber(int pos) {
random.setSeed(System.nanoTime() * (long) inttt);
this.randomN = random.nextInt(pos);
inttt += randomN;
return (int)randomN;
}
public Rectangle getColliderActor(){
return this.rectangle;
}
}
the class as this should create a random enemy.
Edit: rereading your question, is that my English is not very good, and I think you wanted to be drawn only on the sides of the screen if so, tell me or adapts the class because when you create thought, which was across the screen.
I just added another class, if you can and want to work as you tell me which is correct, and delete the other.
public class overFlow extends Sprite {
private final float maxH = Gdx.graphics.getHeight();
private final float maxW = Gdx.graphics.getWidth();
private Rectangle rectangle;
private Random random = new Random();
private float inttt = 0;
private float randomN = 0;
private boolean hasCollided = false;
public overFlow(Sprite sprite) {
super(sprite);
crearEnemigo();
rectangle = new Rectangle(getX(), getY(), getWidth(), getHeight());
}
#Override
public void draw(Batch spriteBatch) {
super.draw(spriteBatch);
}
private void crearEnemigo(){
setX(RandomNumber((int)maxW, true));
setY(RandomNumber((int)maxH, false));
}
private int RandomNumber(int pos, boolean w) {
random.setSeed(System.nanoTime() * (long) inttt);
if (w = true){
this.randomN = random.nextInt((pos));
if(randomN % 2 == 0){
randomN = (pos - getWidth());
}else{
randomN = 0; //left screen
}
}else{
this.randomN = random.nextInt(pos - (int)getHeight());
}
inttt += randomN;
return (int)randomN;
}
public Rectangle getColliderActor(){
return this.rectangle;
}
}
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;
}
}