Продолжаем создавать игру Марсианин, здесь будут анимированные Актёры, 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; } }