Продолжаем создавать игру Марсианин, здесь будут анимированные Актёры, 3 экрана игры, кнопочки, русский текст и т.п.
Скачать исходники для статьи можно ниже
Ниже выложу готовой код игры и все текстуры игры.
Структура файлов игры будет следующей:
Экраны игры:
Структура папки assets, где хранятся все картинки и текстуры:
Скачать папку assets можно по следующей ссылке – скачать папку assets.
1. Код файлов MartianRun, MainMenuScreen и GameOverScreen.
Код файла MartianRun:
package com.gamestudio24.martianrun;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
public class MartianRun extends Game {
public SpriteBatch batch;
public BitmapFont font;
public BitmapFont myfont;
@Override
public void create() {
batch = new SpriteBatch();
font = new BitmapFont();
myfont = new BitmapFont();
final String FONT_CHARS = "абвгдежзийклмнопрстуфхцчшщъыьэюяabcdefghijklmnopqrstuvwxyzАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789][_!$%#@|\\\\/?-+=()*&.;:,{}\\\"´`'<>";
final String FONT_PATH = "fonts/Imperial Web.ttf";
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal(FONT_PATH));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.characters = FONT_CHARS;
parameter.size = 17;
parameter.color = Color.BROWN;
myfont = generator.generateFont(parameter);
generator.dispose();
this.setScreen(new MainMenuScreen(this));
font.setColor(1f, 0f, 0f, 1f);
}
// Get rid of render function, let the parent class handle it
@Override
public void dispose() {
super.dispose();
batch.dispose();
}
}
Код файла MainMenuScreen:
package com.gamestudio24.martianrun;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.viewport.FillViewport;
import com.gamestudio24.martianrun.screens.GameScreen;
public class MainMenuScreen implements Screen {
final MartianRun Game;
public static Texture backgroundTexture1;
private Stage stage;
private Skin skin;
private Image gameover;
private TextButton retry;
public MainMenuScreen(final MartianRun gam) {
Game = gam;
backgroundTexture1 = new Texture("bg.png");
stage=new Stage(new FillViewport(640, 360));
skin=new Skin(Gdx.files.internal("skin/uiskin.json"));
gameover = new Image();
retry=new TextButton("Play",skin);
retry.addCaptureListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Game.setScreen(new GameScreen(Game));
}
});
gameover.setPosition(320-gameover.getWidth(), 320- gameover.getHeight());
retry.setSize(200,100);
retry.setPosition(220,50);
stage.addActor(retry);
stage.addActor(gameover);
}
@Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
@Override
public void hide() {
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Game.batch.begin();
Game.batch.draw(backgroundTexture1, 0, 0, 800, 480);
Game.myfont.draw(Game.batch, "Не дай инопланетянам схватить тебя!", 240, 450);
Game.batch.end();
stage.act();
stage.draw();
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
stage.dispose();
Game.dispose();
}
}
Код файла GameOverScreen:
package com.gamestudio24.martianrun;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.viewport.FillViewport;
import com.gamestudio24.martianrun.screens.GameScreen;
import com.gamestudio24.martianrun.stages.GameStage;
public class GameOverScreen implements Screen {
final MartianRun Game;
public static Texture backgroundTexture1;
private Stage stage;
private Skin skin;
private Image gameover;
private TextButton retry, menu;
public GameOverScreen(final MartianRun gam2) {
Game = gam2;
backgroundTexture1 = new Texture("bg.png");
stage=new Stage(new FillViewport(640, 360));
skin=new Skin(Gdx.files.internal("skin/uiskin.json"));
gameover = new Image(new Texture(Gdx.files.internal("gameover.png")));
retry=new TextButton("Retry",skin);
menu=new TextButton("Menu", skin);
retry.addCaptureListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Game.setScreen(new GameScreen(Game));
GameStage.schot=0;
}
});
menu.addCaptureListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Game.setScreen(new MainMenuScreen(Game));
GameStage.schot=0;
}
});
gameover.setPosition(520-gameover.getWidth(), 320- gameover.getHeight());
retry.setSize(200,100);
retry.setPosition(350,50);
stage.addActor(retry);
menu.setSize(200,100);
menu.setPosition(100,50);
stage.addActor(menu);
stage.addActor(gameover);
}
@Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Game.batch.begin();
Game.batch.draw(backgroundTexture1, 0, 0, 800, 480);
Game.batch.end();
stage.act();
stage.draw();
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
}
@Override
public void dispose() {
stage.dispose();
Game.dispose();
}
}
2. Файлы папки actor.
Код файла Background:
package com.gamestudio24.martianrun.actors;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.gamestudio24.martianrun.utils.Constants;
public class Background extends Actor {
private final TextureRegion textureRegion;
private Rectangle textureRegionBounds1;
private Rectangle textureRegionBounds2;
private int speed = 100;
public Background() {
textureRegion = new TextureRegion(new Texture(Gdx.files.internal(Constants.BACKGROUND_IMAGE_PATH)));
textureRegionBounds1 = new Rectangle(0 - Constants.APP_WIDTH / 2, 0, Constants.APP_WIDTH, Constants.APP_HEIGHT);
textureRegionBounds2 = new Rectangle(Constants.APP_WIDTH / 2, 0, Constants.APP_WIDTH, Constants.APP_HEIGHT);
}
@Override
public void act(float delta) {
if (leftBoundsReached(delta)) {
resetBounds();
} else {
updateXBounds(-delta);
}
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.draw(textureRegion, textureRegionBounds1.x, textureRegionBounds1.y, Constants.APP_WIDTH,
Constants.APP_HEIGHT);
batch.draw(textureRegion, textureRegionBounds2.x, textureRegionBounds2.y, Constants.APP_WIDTH,
Constants.APP_HEIGHT);
}
private boolean leftBoundsReached(float delta) {
return (textureRegionBounds2.x - (delta * speed)) <= 0;
}
private void updateXBounds(float delta) {
textureRegionBounds1.x += delta * speed;
textureRegionBounds2.x += delta * speed;
}
private void resetBounds() {
textureRegionBounds1 = textureRegionBounds2;
textureRegionBounds2 = new Rectangle(Constants.APP_WIDTH, 0, Constants.APP_WIDTH, Constants.APP_HEIGHT);
}
}
Код файла Enemy:
package com.gamestudio24.martianrun.actors;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.physics.box2d.Body;
import com.gamestudio24.martianrun.box2d.EnemyUserData;
import com.gamestudio24.martianrun.utils.Constants;
public class Enemy extends GameActor {
private Animation animation;
private float stateTime;
public Enemy(Body body) {
super(body);
TextureAtlas textureAtlas = new TextureAtlas(Constants.SPRITES_ATLAS_PATH);
TextureRegion[] runningFrames = new TextureRegion[getUserData().getTextureRegions().length];
for (int i = 0; i < getUserData().getTextureRegions().length; i++) {
String path = getUserData().getTextureRegions()[i];
runningFrames[i] = textureAtlas.findRegion(path);
}
animation = new Animation(0.1f, runningFrames);
stateTime = 0f;
}
@Override
public EnemyUserData getUserData() {
return (EnemyUserData) userData;
}
@Override
public void act(float delta) {
super.act(delta);
body.setLinearVelocity(getUserData().getLinearVelocity());
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
stateTime += Gdx.graphics.getDeltaTime();
batch.draw(animation.getKeyFrame(stateTime, true), (screenRectangle.x - (screenRectangle.width * 0.1f)),
screenRectangle.y, screenRectangle.width * 1.2f, screenRectangle.height * 1.1f);
}
}
Код файла GameActor:
package com.gamestudio24.martianrun.actors;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.gamestudio24.martianrun.box2d.UserData;
import com.gamestudio24.martianrun.utils.Constants;
public abstract class GameActor extends Actor {
protected Body body;
protected UserData userData;
protected Rectangle screenRectangle;
public GameActor() {
}
public GameActor(Body body) {
this.body = body;
this.userData = (UserData) body.getUserData();
screenRectangle = new Rectangle();
}
@Override
public void act(float delta) {
super.act(delta);
if (body.getUserData() != null) {
updateRectangle();
} else {
// This means the world destroyed the body (enemy or runner went out of bounds)
remove();
}
}
public abstract UserData getUserData();
private void updateRectangle() {
screenRectangle.x = transformToScreen(body.getPosition().x - userData.getWidth() / 2);
screenRectangle.y = transformToScreen(body.getPosition().y - userData.getHeight() / 2);
screenRectangle.width = transformToScreen(userData.getWidth());
screenRectangle.height = transformToScreen(userData.getHeight());
}
protected float transformToScreen(float n) {
return Constants.WORLD_TO_SCREEN * n;
}
}
Код файла Ground:
package com.gamestudio24.martianrun.actors;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.physics.box2d.Body;
import com.gamestudio24.martianrun.box2d.GroundUserData;
import com.gamestudio24.martianrun.utils.Constants;
public class Ground extends GameActor {
private final TextureRegion textureRegion;
private Rectangle textureRegionBounds1;
private Rectangle textureRegionBounds2;
private int speed = 10;
public Ground(Body body) {
super(body);
textureRegion = new TextureRegion(new Texture(Gdx.files.internal(Constants.GROUND_IMAGE_PATH)));
textureRegionBounds1 = new Rectangle(0 - getUserData().getWidth() / 2, 0, getUserData().getWidth(),
getUserData().getHeight());
textureRegionBounds2 = new Rectangle(getUserData().getWidth() / 2, 0, getUserData().getWidth(),
getUserData().getHeight());
}
@Override
public GroundUserData getUserData() {
return (GroundUserData) userData;
}
@Override
public void act(float delta) {
super.act(delta);
if (leftBoundsReached(delta)) {
resetBounds();
} else {
updateXBounds(-delta);
}
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.draw(textureRegion, textureRegionBounds1.x, screenRectangle.y, screenRectangle.getWidth(),
screenRectangle.getHeight());
batch.draw(textureRegion, textureRegionBounds2.x, screenRectangle.y, screenRectangle.getWidth(),
screenRectangle.getHeight());
}
private boolean leftBoundsReached(float delta) {
return (textureRegionBounds2.x - transformToScreen(delta * speed)) <= 0;
}
private void updateXBounds(float delta) {
textureRegionBounds1.x += transformToScreen(delta * speed);
textureRegionBounds2.x += transformToScreen(delta * speed);
}
private void resetBounds() {
textureRegionBounds1 = textureRegionBounds2;
textureRegionBounds2 = new Rectangle(textureRegionBounds1.x + screenRectangle.width, 0, screenRectangle.width,
screenRectangle.height);
}
}
Код файла Runner:
package com.gamestudio24.martianrun.actors;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.physics.box2d.Body;
import com.gamestudio24.martianrun.MainMenuScreen;
import com.gamestudio24.martianrun.box2d.RunnerUserData;
import com.gamestudio24.martianrun.utils.Constants;
public class Runner extends GameActor {
private boolean dodging;
private boolean jumping;
private boolean hit;
private Animation runningAnimation;
private TextureRegion jumpingTexture;
private TextureRegion dodgingTexture;
private TextureRegion hitTexture;
private float stateTime;
public Runner(Body body) {
super(body);
TextureAtlas textureAtlas = new TextureAtlas(Constants.SPRITES_ATLAS_PATH);
TextureRegion[] runningFrames = new TextureRegion[Constants.RUNNER_RUNNING_REGION_NAMES.length];
for (int i = 0; i < Constants.RUNNER_RUNNING_REGION_NAMES.length; i++) {
String path = Constants.RUNNER_RUNNING_REGION_NAMES[i];
runningFrames[i] = textureAtlas.findRegion(path);
}
runningAnimation = new Animation(0.1f, runningFrames);
stateTime = 0f;
jumpingTexture = textureAtlas.findRegion(Constants.RUNNER_JUMPING_REGION_NAME);
dodgingTexture = textureAtlas.findRegion(Constants.RUNNER_DODGING_REGION_NAME);
hitTexture = textureAtlas.findRegion(Constants.RUNNER_HIT_REGION_NAME);
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
float x = screenRectangle.x - (screenRectangle.width * 0.1f);
float y = screenRectangle.y;
float width = screenRectangle.width * 1.2f;
if (dodging) {
batch.draw(dodgingTexture, x, y + screenRectangle.height / 4, width, screenRectangle.height * 3 / 4);
} else if (hit) {
// When he's hit we also want to apply rotation if the body has been rotated
batch.draw(hitTexture, x, y, width * 0.5f, screenRectangle.height * 0.5f, width, screenRectangle.height, 1f,
1f, (float) Math.toDegrees(body.getAngle()));
} else if (jumping) {
batch.draw(jumpingTexture, x, y, width, screenRectangle.height);
} else {
// Running
stateTime += Gdx.graphics.getDeltaTime();
batch.draw(runningAnimation.getKeyFrame(stateTime, true), x, y, width, screenRectangle.height);
}
}
@Override
public RunnerUserData getUserData() {
return (RunnerUserData) userData;
}
public void jump() {
if (!(jumping || dodging || hit)) {
body.applyLinearImpulse(getUserData().getJumpingLinearImpulse(), body.getWorldCenter(), true);
jumping = true;
}
}
public void landed() {
jumping = false;
}
public void dodge() {
if (!(jumping || hit)) {
body.setTransform(getUserData().getDodgePosition(), getUserData().getDodgeAngle());
dodging = true;
}
}
public void stopDodge() {
dodging = false;
// If the runner is hit don't force him back to the running position
if (!hit) {
body.setTransform(getUserData().getRunningPosition(), 0f);
}
}
public boolean isDodging() {
return dodging;
}
public void hit() {
body.applyAngularImpulse(getUserData().getHitAngularImpulse(), true);
hit = true;
}
public boolean isHit() {
return hit;
}
}
3. Файлы папки box2d.
Код файла EnemyUserData:
package com.gamestudio24.martianrun.box2d;
import com.badlogic.gdx.math.Vector2;
import com.gamestudio24.martianrun.enums.UserDataType;
import com.gamestudio24.martianrun.stages.GameStage;
import com.gamestudio24.martianrun.utils.Constants;
public class EnemyUserData extends UserData {
private Vector2 linearVelocity;
private String[] textureRegions;
public EnemyUserData(float width, float height, String[] textureRegions) {
super(width, height);
userDataType = UserDataType.ENEMY;
if (GameStage.stadya == 1) {
linearVelocity = Constants.ENEMY_LINEAR_VELOCITY2;
} else {
linearVelocity = Constants.ENEMY_LINEAR_VELOCITY;
}
this.textureRegions = textureRegions;
}
public void setLinearVelocity(Vector2 linearVelocity) {
this.linearVelocity = linearVelocity;
}
public Vector2 getLinearVelocity() {
return linearVelocity;
}
public String[] getTextureRegions() {
return textureRegions;
}
}
Код файла GroundUserData:
package com.gamestudio24.martianrun.box2d;
import com.gamestudio24.martianrun.enums.UserDataType;
public class GroundUserData extends UserData {
public GroundUserData(float width, float height) {
super(width, height);
userDataType = UserDataType.GROUND;
}
}
Код файла RunnerUserData:
package com.gamestudio24.martianrun.box2d;
import com.badlogic.gdx.math.Vector2;
import com.gamestudio24.martianrun.enums.UserDataType;
import com.gamestudio24.martianrun.utils.Constants;
public class RunnerUserData extends UserData {
private final Vector2 runningPosition = new Vector2(Constants.RUNNER_X, Constants.RUNNER_Y);
private final Vector2 dodgePosition = new Vector2(Constants.RUNNER_DODGE_X, Constants.RUNNER_DODGE_Y);
private Vector2 jumpingLinearImpulse;
public RunnerUserData() {
super();
jumpingLinearImpulse = Constants.RUNNER_JUMPING_LINEAR_IMPULSE;
userDataType = UserDataType.RUNNER;
}
public RunnerUserData(float width, float height) {
super(width, height);
jumpingLinearImpulse = Constants.RUNNER_JUMPING_LINEAR_IMPULSE;
userDataType = UserDataType.RUNNER;
}
public Vector2 getJumpingLinearImpulse() {
return jumpingLinearImpulse;
}
public void setJumpingLinearImpulse(Vector2 jumpingLinearImpulse) {
this.jumpingLinearImpulse = jumpingLinearImpulse;
}
public float getDodgeAngle() {
// In radians
return (float) (-90f * (Math.PI / 180f));
}
public Vector2 getRunningPosition() {
return runningPosition;
}
public Vector2 getDodgePosition() {
return dodgePosition;
}
public float getHitAngularImpulse() {
return Constants.RUNNER_HIT_ANGULAR_IMPULSE;
}
}
Код файла UserData:
package com.gamestudio24.martianrun.box2d;
import com.gamestudio24.martianrun.enums.UserDataType;
public abstract class UserData {
protected UserDataType userDataType;
protected float width;
protected float height;
public UserData() {
}
public UserData(float width, float height) {
this.width = width;
this.height = height;
}
public UserDataType getUserDataType() {
return userDataType;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
}
4. Файлы папки enums.
Код файла EnemyType:
package com.gamestudio24.martianrun.enums;
import com.gamestudio24.martianrun.utils.Constants;
public enum EnemyType {
/* RUNNING_SMALL(1f, 1f, Constants.ENEMY_X, Constants.RUNNING_SHORT_ENEMY_Y, Constants.ENEMY_DENSITY),
RUNNING_WIDE(2f, 1f, Constants.ENEMY_X, Constants.RUNNING_SHORT_ENEMY_Y, Constants.ENEMY_DENSITY),
RUNNING_LONG(1f, 2f, Constants.ENEMY_X, Constants.RUNNING_LONG_ENEMY_Y, Constants.ENEMY_DENSITY),
RUNNING_BIG(2f, 2f, Constants.ENEMY_X, Constants.RUNNING_LONG_ENEMY_Y, Constants.ENEMY_DENSITY),
FLYING_SMALL(1f, 1f, Constants.ENEMY_X, Constants.FLYING_ENEMY_Y, Constants.ENEMY_DENSITY),
FLYING_WIDE(2f, 1f, Constants.ENEMY_X, Constants.FLYING_ENEMY_Y, Constants.ENEMY_DENSITY);*/
RUNNING_SMALL(1f, 1f, Constants.ENEMY_X, Constants.RUNNING_SHORT_ENEMY_Y, Constants.ENEMY_DENSITY,
Constants.RUNNING_SMALL_ENEMY_REGION_NAMES),
RUNNING_WIDE(2f, 1f, Constants.ENEMY_X, Constants.RUNNING_SHORT_ENEMY_Y, Constants.ENEMY_DENSITY,
Constants.RUNNING_WIDE_ENEMY_REGION_NAMES),
RUNNING_LONG(1f, 2f, Constants.ENEMY_X, Constants.RUNNING_LONG_ENEMY_Y, Constants.ENEMY_DENSITY,
Constants.RUNNING_LONG_ENEMY_REGION_NAMES),
RUNNING_BIG(2f, 2f, Constants.ENEMY_X, Constants.RUNNING_LONG_ENEMY_Y, Constants.ENEMY_DENSITY,
Constants.RUNNING_BIG_ENEMY_REGION_NAMES),
FLYING_SMALL(1f, 1f, Constants.ENEMY_X, Constants.FLYING_ENEMY_Y, Constants.ENEMY_DENSITY,
Constants.FLYING_SMALL_ENEMY_REGION_NAMES),
FLYING_WIDE(2f, 1f, Constants.ENEMY_X, Constants.FLYING_ENEMY_Y, Constants.ENEMY_DENSITY,
Constants.FLYING_WIDE_ENEMY_REGION_NAMES);
private float width;
private float height;
private float x;
private float y;
private float density;
private String[] regions;
EnemyType(float width, float height, float x, float y, float density, String[] regions) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.density = density;
this.regions = regions;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getDensity() {
return density;
}
public String[] getRegions() {
return regions;
}
}
Код файла UserDataType:
package com.gamestudio24.martianrun.enums;
public enum UserDataType {
GROUND,
RUNNER,
ENEMY
}
5. Файлы папки screens.
Код файла GameScreen:
package com.gamestudio24.martianrun.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.gamestudio24.martianrun.MartianRun;
import com.gamestudio24.martianrun.stages.GameStage;
public class GameScreen implements Screen {
private GameStage stage;
final MartianRun Game;
private String nagrada = "";
public GameScreen(final MartianRun gam) {
this.Game = gam;
stage = new GameStage(Game);
}
@Override
public void render(float delta) {
//Clear the screen
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//Update the stage
stage.draw();
stage.act(delta);
Game.batch.begin();
if (GameStage.ochkov >= 5) {
nagrada=String.valueOf("отличная работа");
}
if (GameStage.ochkov == 10) {
nagrada=String.valueOf("ты супер, перекури 5 секунд и вперед!");
stage.addAction(
Actions.sequence(Actions.delay(5f),Actions.run(new Runnable() {
@Override
public void run() {
Game.setScreen(new GameScreen(Game));
GameStage.ochkov=0;
GameStage.stadya=1;
stage.dispose();
}
}))
);
}
Game.myfont.draw(Game.batch, "Очки: " + GameStage.schot, 60, 460);
String.valueOf(Game.myfont.draw(Game.batch, "Награда:" + nagrada, 240, 450));
Game.batch.end();
}
@Override
public void resize(int width, int height) {
}
@Override
public void show() {
}
@Override
public void hide() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
}
}
6. Файлы папки stages.
Код файла GameStage:
package com.gamestudio24.martianrun.stages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Manifold;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Scaling;
import com.badlogic.gdx.utils.viewport.ScalingViewport;
import com.gamestudio24.martianrun.GameOverScreen;
import com.gamestudio24.martianrun.MartianRun;
import com.gamestudio24.martianrun.actors.Background;
import com.gamestudio24.martianrun.actors.Enemy;
import com.gamestudio24.martianrun.actors.Ground;
import com.gamestudio24.martianrun.actors.Runner;
import com.gamestudio24.martianrun.utils.BodyUtils;
import com.gamestudio24.martianrun.utils.Constants;
import com.gamestudio24.martianrun.utils.WorldUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
public class GameStage extends Stage implements ContactListener {
// This will be our viewport measurements while working with the debug renderer
private static final int VIEWPORT_WIDTH = Constants.APP_WIDTH;
private static final int VIEWPORT_HEIGHT = Constants.APP_HEIGHT;
private final float TIME_STEP = 1 / 300f;
private float accumulator = 0f;
private OrthographicCamera camera;
private Box2DDebugRenderer renderer;
private Rectangle screenLeftSide;
private Rectangle screenRightSide;
private Vector3 touchPoint;
private World world;
private Ground ground;
private Runner runner;
final MartianRun Game;
public static int ochkov = 0;
public static int stadya = 0;
public static int schot = 0;
public GameStage(final MartianRun gam) {
super(new ScalingViewport(Scaling.stretch, VIEWPORT_WIDTH, VIEWPORT_HEIGHT,
new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT)));
setUpWorld();
setupCamera();
setupTouchControlAreas();
this.Game = gam;
}
private void setUpWorld() {
world = WorldUtils.createWorld();
// Let the world now you are handling contacts
world.setContactListener(this);
setUpBackground();
setUpGround();
setUpRunner();
createEnemy();
}
private void setUpBackground() {
addActor(new Background());
}
private void setUpGround() {
ground = new Ground(WorldUtils.createGround(world));
addActor(ground);
}
private void setUpRunner() {
runner = new Runner(WorldUtils.createRunner(world));
addActor(runner);
}
private void setupCamera() {
camera = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0f);
camera.update();
}
private void setupTouchControlAreas() {
touchPoint = new Vector3();
screenLeftSide = new Rectangle(0, 0, getCamera().viewportWidth / 2, getCamera().viewportHeight);
screenRightSide = new Rectangle(getCamera().viewportWidth / 2, 0, getCamera().viewportWidth / 2,
getCamera().viewportHeight);
Gdx.input.setInputProcessor(this);
}
@Override
public void act(float delta) {
super.act(delta);
Array<Body> bodies = new Array<Body>(world.getBodyCount());
world.getBodies(bodies);
for (Body body : bodies) {
update(body);
}
// Fixed timestep
accumulator += delta;
while (accumulator >= delta) {
world.step(TIME_STEP, 6, 2);
accumulator -= TIME_STEP;
}
//TODO: Implement interpolation
}
private void update(Body body) {
if (!BodyUtils.bodyInBounds(body)) {
if (BodyUtils.bodyIsEnemy(body) && !runner.isHit()) {
ochkov++;
schot=stadya*10+ochkov;
if (ochkov < 10) {
createEnemy();
}else {
}
}
world.destroyBody(body);
}
}
private void createEnemy() {
Enemy enemy = new Enemy(WorldUtils.createEnemy(world));
addActor(enemy);
}
@Override
public boolean touchDown(int x, int y, int pointer, int button) {
// Need to get the actual coordinates
translateScreenToWorldCoordinates(x, y);
if (rightSideTouched(touchPoint.x, touchPoint.y)) {
runner.jump();
} else if (leftSideTouched(touchPoint.x, touchPoint.y)) {
runner.dodge();
}
return super.touchDown(x, y, pointer, button);
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (runner.isDodging()) {
runner.stopDodge();
}
return super.touchUp(screenX, screenY, pointer, button);
}
private boolean rightSideTouched(float x, float y) {
return screenRightSide.contains(x, y);
}
private boolean leftSideTouched(float x, float y) {
return screenLeftSide.contains(x, y);
}
/**
* Helper function to get the actual coordinates in my world
* @param x
* @param y
*/
private void translateScreenToWorldCoordinates(int x, int y) {
getCamera().unproject(touchPoint.set(x, y, 0));
}
@Override
public void beginContact(Contact contact) {
Body a = contact.getFixtureA().getBody();
Body b = contact.getFixtureB().getBody();
if ((BodyUtils.bodyIsRunner(a) && BodyUtils.bodyIsEnemy(b)) ||
(BodyUtils.bodyIsEnemy(a) && BodyUtils.bodyIsRunner(b))) {
runner.hit();
ochkov=0;
stadya=0;
} else if ((BodyUtils.bodyIsRunner(a) && BodyUtils.bodyIsGround(b)) ||
(BodyUtils.bodyIsGround(a) && BodyUtils.bodyIsRunner(b))) {
runner.landed();
}
}
@Override
public void endContact(Contact contact) {
if (runner != null) {
if (runner.isHit())
Game.setScreen(new GameOverScreen(Game));
}
}
@Override
public void preSolve(Contact contact, Manifold oldManifold) {
}
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}
}
7. Файлы папки utils.
Код файла BodyUtils:
package com.gamestudio24.martianrun.utils;
import com.badlogic.gdx.physics.box2d.Body;
import com.gamestudio24.martianrun.box2d.UserData;
import com.gamestudio24.martianrun.enums.UserDataType;
public class BodyUtils {
public static boolean bodyInBounds(Body body) {
UserData userData = (UserData) body.getUserData();
switch (userData.getUserDataType()) {
case RUNNER:
case ENEMY:
return body.getPosition().x + userData.getWidth() / 2 > 0;
}
return true;
}
public static boolean bodyIsEnemy(Body body) {
UserData userData = (UserData) body.getUserData();
return userData != null && userData.getUserDataType() == UserDataType.ENEMY;
}
public static boolean bodyIsRunner(Body body) {
UserData userData = (UserData) body.getUserData();
return userData != null && userData.getUserDataType() == UserDataType.RUNNER;
}
public static boolean bodyIsGround(Body body) {
UserData userData = (UserData) body.getUserData();
return userData != null && userData.getUserDataType() == UserDataType.GROUND;
}
}
Код файла Constants:
package com.gamestudio24.martianrun.utils;
import com.badlogic.gdx.math.Vector2;
public class Constants {
public static final int APP_WIDTH = 800;
public static final int APP_HEIGHT = 480;
public static final float WORLD_TO_SCREEN = 32;
public static final Vector2 WORLD_GRAVITY = new Vector2(0, -10);
public static final float GROUND_X = 0;
public static final float GROUND_Y = 0;
public static final float GROUND_WIDTH = 50f;
public static final float GROUND_HEIGHT = 2f;
public static final float GROUND_DENSITY = 0f;
public static final float RUNNER_X = 2;
public static final float RUNNER_Y = GROUND_Y + GROUND_HEIGHT;
public static final float RUNNER_WIDTH = 1f;
public static final float RUNNER_HEIGHT = 2f;
public static final float RUNNER_GRAVITY_SCALE = 3f;
public static float RUNNER_DENSITY = 0.5f;
public static final float RUNNER_DODGE_X = 2f;
public static final float RUNNER_DODGE_Y = 1.5f;
public static final Vector2 RUNNER_JUMPING_LINEAR_IMPULSE = new Vector2(0, 13f);
public static final float RUNNER_HIT_ANGULAR_IMPULSE = 10f;
public static final float ENEMY_X = 25f;
public static final float ENEMY_DENSITY = RUNNER_DENSITY;
public static final float RUNNING_SHORT_ENEMY_Y = 1.5f;
public static final float RUNNING_LONG_ENEMY_Y = 2f;
public static final float FLYING_ENEMY_Y = 3f;
public static final Vector2 ENEMY_LINEAR_VELOCITY = new Vector2(-10f, 0);
public static final Vector2 ENEMY_LINEAR_VELOCITY2 = new Vector2(-15f, 0);
public static final String BACKGROUND_IMAGE_PATH = "background.png";
public static final String GROUND_IMAGE_PATH = "ground.png";
public static final String SPRITES_ATLAS_PATH = "sprites.txt";
public static final String[] RUNNER_RUNNING_REGION_NAMES = new String[] {"alienBeige_run1", "alienBeige_run2"};
public static final String RUNNER_DODGING_REGION_NAME = "alienBeige_dodge";
public static final String RUNNER_HIT_REGION_NAME = "alienBeige_hit";
public static final String RUNNER_JUMPING_REGION_NAME = "alienBeige_jump";
public static final String[] RUNNING_SMALL_ENEMY_REGION_NAMES = new String[] {"ladyBug_walk1", "ladyBug_walk2"};
public static final String[] RUNNING_LONG_ENEMY_REGION_NAMES = new String[] {"barnacle_bite1", "barnacle_bite2"};
public static final String[] RUNNING_BIG_ENEMY_REGION_NAMES = new String[] {"spider_walk1", "spider_walk2"};
public static final String[] RUNNING_WIDE_ENEMY_REGION_NAMES = new String[] {"worm_walk1", "worm_walk2"};
public static final String[] FLYING_SMALL_ENEMY_REGION_NAMES = new String[] {"bee_fly1", "bee_fly2"};
public static final String[] FLYING_WIDE_ENEMY_REGION_NAMES = new String[] {"fly_fly1", "fly_fly2"};
}
Код файла RandomUtils:
package com.gamestudio24.martianrun.utils;
import com.gamestudio24.martianrun.enums.EnemyType;
import java.util.Random;
public class RandomUtils {
public static EnemyType getRandomEnemyType() {
RandomEnum<EnemyType> randomEnum = new RandomEnum<EnemyType>(EnemyType.class);
return randomEnum.random();
}
/**
* @see [Stack Overflow](http://stackoverflow.com/a/1973018)
* @param <E>
*/
private static class RandomEnum<E extends Enum> {
private static final Random RND = new Random();
private final E[] values;
public RandomEnum(Class<E> token) {
values = token.getEnumConstants();
}
public E random() {
return values[RND.nextInt(values.length)];
}
}
}
Код файла WorldUtils:
package com.gamestudio24.martianrun.utils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.gamestudio24.martianrun.box2d.EnemyUserData;
import com.gamestudio24.martianrun.box2d.GroundUserData;
import com.gamestudio24.martianrun.box2d.RunnerUserData;
import com.gamestudio24.martianrun.enums.EnemyType;
public class WorldUtils {
public static World createWorld() {
return new World(Constants.WORLD_GRAVITY, true);
}
public static Body createGround(World world) {
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(new Vector2(Constants.GROUND_X, Constants.GROUND_Y));
Body body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(Constants.GROUND_WIDTH / 2, Constants.GROUND_HEIGHT / 2);
body.createFixture(shape, Constants.GROUND_DENSITY);
body.setUserData(new GroundUserData(Constants.GROUND_WIDTH, Constants.GROUND_HEIGHT));
shape.dispose();
return body;
}
public static Body createRunner(World world) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(new Vector2(Constants.RUNNER_X, Constants.RUNNER_Y));
PolygonShape shape = new PolygonShape();
shape.setAsBox(Constants.RUNNER_WIDTH / 2, Constants.RUNNER_HEIGHT / 2);
Body body = world.createBody(bodyDef);
body.setGravityScale(Constants.RUNNER_GRAVITY_SCALE);
body.createFixture(shape, Constants.RUNNER_DENSITY);
body.resetMassData();
body.setUserData(new RunnerUserData(Constants.RUNNER_WIDTH, Constants.RUNNER_HEIGHT));
shape.dispose();
return body;
}
public static Body createEnemy(World world) {
EnemyType enemyType = RandomUtils.getRandomEnemyType();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.KinematicBody;
bodyDef.position.set(new Vector2(enemyType.getX(), enemyType.getY()));
PolygonShape shape = new PolygonShape();
shape.setAsBox(enemyType.getWidth() / 2, enemyType.getHeight() / 2);
Body body = world.createBody(bodyDef);
body.createFixture(shape, enemyType.getDensity());
body.resetMassData();
EnemyUserData userData = new EnemyUserData(enemyType.getWidth(), enemyType.getHeight(), enemyType.getRegions());
body.setUserData(userData);
shape.dispose();
return body;
}
}

