libgdx游戏引擎开发笔记(十三)SuperJumper游戏例子的讲解(篇七)----各个物体的创建及其碰撞检测

   接着上一篇,我们完成后续的扫尾工作:游戏中个物体创建及其碰撞检测,分数保存,音效处理。


1.World类:(加入所有物体,及其碰撞检测,代码里有详细注解)

package com.zhf.mylibgdx;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.badlogic.gdx.math.Vector2;
/**
 * 统一管理世界中各个部分
 * @author ZHF
 *
 */
public class World {
    /**世界监听器接口**/
    public interface WorldListener {
        //跳跃
        public void jump ();
        //高跳
        public void highJump ();
        //碰撞
        public void hit ();
        //收集金币
        public void coin ();
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    //宽和高
    public static final float WORLD_WIDTH = 10;
    public static final float WORLD_HEIGHT = 15 * 20;
    //状态
    public static final int WORLD_STATE_RUNNING = 0;  //运行
    public static final int WORLD_STATE_NEXT_LEVEL = 1;  //下一关
    public static final int WORLD_STATE_GAME_OVER = 2;  //游戏结束
    //世界监听器
    public  WorldListener listener;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    //重力
    public static final Vector2 gravity = new Vector2(0, -12);
    //随机数
    public Random rand;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    public float heightSoFar; //
    public int score;
    public int state;
    //游戏中物体
    public final List<Platform> platforms;  //跳板
    public final Bob bob;  //主角
    public final List<Spring> springs;  //弹簧
    public final List<Squirrel> squirrels; //会飞的松鼠
    public final List<Coin> coins;  //金币
    public Castle castle;  //城堡
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    public World(WorldListener listener) {
        this.listener = listener;
        //初始化游戏中的物体
        this.bob = new Bob(5, 1);
        this.platforms = new ArrayList<Platform>();
        this.springs = new ArrayList<Spring>();
        this.squirrels = new ArrayList<Squirrel>();
        this.coins = new ArrayList<Coin>();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
        rand = new Random();
        generateLevel();  //生成关卡中除了Bob外所有的物体
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    /**生成关卡中除了Bob外所有的物体**/
    private void generateLevel() {
        float y = Platform.PLATFORM_HEIGHT / 2;
        float maxJumpHeight = Bob.BOB_JUMP_VELOCITY * Bob.BOB_JUMP_VELOCITY / (2 * -gravity.y);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
        while (y < WORLD_HEIGHT - WORLD_WIDTH / 2) {
            int type = rand.nextFloat() > 0.8f ? Platform.PLATFORM_TYPE_MOVING : Platform.PLATFORM_TYPE_STATIC;
            float x = rand.nextFloat() * (WORLD_WIDTH - Platform.PLATFORM_WIDTH) + Platform.PLATFORM_WIDTH / 2;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
            //跳板的位置
            Platform platform = new Platform(type, x, y);
            platforms.add(platform);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
            //弹簧的位置
            if (rand.nextFloat() > 0.9f && type != Platform.PLATFORM_TYPE_MOVING) {
                Spring spring = new Spring(platform.position.x, platform.position.y + Platform.PLATFORM_HEIGHT / 2
                    + Spring.SPRING_HEIGHT / 2);
                springs.add(spring);
            }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
            //松鼠的位置
            if (y > WORLD_HEIGHT / 3 && rand.nextFloat() > 0.8f) {
                Squirrel squirrel = new Squirrel(platform.position.x + rand.nextFloat(), platform.position.y
                    + Squirrel.SQUIRREL_HEIGHT + rand.nextFloat() * 2);
                squirrels.add(squirrel);
            }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
            //金币的位置
            if (rand.nextFloat() > 0.6f) {
                Coin coin = new Coin(platform.position.x + rand.nextFloat(), platform.position.y + Coin.COIN_HEIGHT
                    + rand.nextFloat() * 3);
                coins.add(coin);
            }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
            //游戏中的物体的位置根据跳板的位置来确定
            y += (maxJumpHeight - 0.5f);
            y -= rand.nextFloat() * (maxJumpHeight / 3);
        }
        //城堡的位置是确定的
        castle = new Castle(WORLD_WIDTH / 2, y);
    }
    /**刷新界面**/
    public void update(float deltaTime, float accelX) {
        updateBob(deltaTime, accelX);  //刷新主角
        updatePlatforms(deltaTime);  //刷新跳板
        updateSquirrels(deltaTime);  //刷新松鼠
        updateCoins(deltaTime);  //刷新金币
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
        if (bob.state != Bob.BOB_STATE_HIT) checkCollisions();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
        //游戏结束判断
        checkGameOver();
    }
    /**碰撞检测**/
    private void checkCollisions() {
        // TODO Auto-generated method stub
        checkPlatformCollisions();  //跳板的碰撞
        checkSquirrelCollisions();  //松鼠的碰撞
        checkItemCollisions();   //金币和弹簧的碰撞
        checkCastleCollisions();  //城堡的碰撞
    }
    /**跳板碰撞**/
    private void checkPlatformCollisions() {
        if (bob.velocity.y > 0) return;
        int len = platforms.size();
        for (int i = 0; i < len; i++) {
            Platform platform = platforms.get(i);
            if (bob.position.y > platform.position.y) {
                //调用工具类中矩形块碰撞检测
                if (OverlapTester.overlapRectangles(bob.bounds, platform.bounds)) {
                    bob.hitPlatform();
                    listener.jump();
                    if (rand.nextFloat() > 0.5f) {
                        platform.pulverize();
                    }
                    break;
                }
            }
        }
    }
    /**松鼠碰撞**/
    private void checkSquirrelCollisions () {
        int len = squirrels.size();
        for (int i = 0; i < len; i++) {
            Squirrel squirrel = squirrels.get(i);
            if (OverlapTester.overlapRectangles(squirrel.bounds, bob.bounds)) {
                bob.hitSquirrel();
                listener.hit();
            }
        }
    }
    /**金币和弹簧碰撞**/
    private void checkItemCollisions () {
        int len = coins.size();
        for (int i = 0; i < len; i++) {
            Coin coin = coins.get(i);
            if (OverlapTester.overlapRectangles(bob.bounds, coin.bounds)) {
                coins.remove(coin);
                len = coins.size();
                listener.coin();
                score += Coin.COIN_SCORE;  //加分
            }
        }
        if (bob.velocity.y > 0) return;  //若是上升状态不去考虑碰撞检测
        len = springs.size();
        for (int i = 0; i < len; i++) {
            Spring spring = springs.get(i);
            if (bob.position.y > spring.position.y) {
                //弹簧的碰撞检测
                if (OverlapTester.overlapRectangles(bob.bounds, spring.bounds)) {
                    bob.hitSpring();
                    listener.highJump();
                }
            }
        }
    }
    /**城堡的碰撞**/
    private void checkCastleCollisions () {
        if (OverlapTester.overlapRectangles(castle.bounds, bob.bounds)) {
            state = WORLD_STATE_NEXT_LEVEL;
        }
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    /**刷新Bob**/
    private void updateBob(float deltaTime, float accelX) {
        //碰撞跳板
        if (bob.state != Bob.BOB_STATE_HIT && bob.position.y <= 0.5f) bob.hitPlatform();
        //主角x轴方向移动的速度
        if (bob.state != Bob.BOB_STATE_HIT) bob.velocity.x = -accelX / 10 * Bob.BOB_MOVE_VELOCITY;
        bob.update(deltaTime);
        //竖直最大高度
        heightSoFar = Math.max(bob.position.y, heightSoFar);
    }
    /**刷新跳板**/
    private void updatePlatforms(float deltaTime) {
        int len = platforms.size();
        for (int i = 0; i < len; i++) {
            Platform platform = platforms.get(i);
            //取出集合中的跳板对象,调用其自身的刷新方法
            platform.update(deltaTime);
            //若状态为破碎状态,将该跳板对象移除出去
            if (platform.state == Platform.PLATFORM_STATE_PULVERIZING && platform.stateTime > Platform.PLATFORM_PULVERIZE_TIME) {
                platforms.remove(platform);
                len = platforms.size();
            }
        }
    }
    /**刷新松鼠**/
    private void updateSquirrels (float deltaTime) {
        int len = squirrels.size();
        for (int i = 0; i < len; i++) {
            Squirrel squirrel = squirrels.get(i);
            squirrel.update(deltaTime);
        }
    }
    /**刷新金币**/
    private void updateCoins (float deltaTime) {
        int len = coins.size();
        for (int i = 0; i < len; i++) {
            Coin coin = coins.get(i);
            coin.update(deltaTime);
        }
    }
    /**游戏结束判断**/
    private void checkGameOver () {
        //目前的Bob的高度小于场景的高度
        if (heightSoFar - 7.5f > bob.position.y) {
            state = WORLD_STATE_GAME_OVER;
        }
    }
}


       看着代码挺多,其实就是一个update()和checkCollisions(),还有重要的generateLevel()。接下来就是渲染WorldRenderer类中绘制各个物体


/**渲染游戏中各种物体(Bob,跳板,松鼠,弹簧,城堡,金币)**/
    private void renderObjects() {
        batch.enableBlending();
        batch.begin();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
        renderPlatforms(); //绘制跳板
        renderBob(); //绘制主角
        renderItems();  //绘制金币和弹簧
        renderSquirrels();  //绘制松鼠
        renderCastle();  //绘制城堡
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
        batch.end();
    }

   

   由于代码过多,这里就不一一贴出来了,大家可以自行参考源码,有注解的哦!

既然添加了游戏中的物体,那自然又得在Asset中加载资源

声明:

//游戏中各种物体
    public static TextureRegion platform;  //跳板
    public static Animation brakingPlatform;  //破碎的跳板(动画)
    //主角
    public static Animation bobJump;  //跳跃(动画)
    public static Animation bobFall;  //下落(动画)
    public static TextureRegion bobHit;  //碰撞图片
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    public static TextureRegion spring; //弹簧
    public static TextureRegion castle; //城堡
    public static Animation coinAnim;  //金币 (动画)
    public static Animation squirrelFly;  //飞着的松鼠 (动画)

实例化:

//游戏中各个物体
        platform = new TextureRegion(items, 64, 160, 64, 16);  //跳板
        brakingPlatform = new Animation(0.2f, new TextureRegion(items, 64, 160, 64, 16), new TextureRegion(items, 64, 176, 64, 16),
                new TextureRegion(items, 64, 192, 64, 16), new TextureRegion(items, 64, 208, 64, 16));//破碎的跳板
        spring = new TextureRegion(items, 128, 0, 32, 32);  //弹簧
        castle = new TextureRegion(items, 128, 64, 64, 64);  //城堡
        coinAnim = new Animation(0.2f, new TextureRegion(items, 128, 32, 32, 32), new TextureRegion(items, 160, 32, 32, 32),
            new TextureRegion(items, 192, 32, 32, 32), new TextureRegion(items, 160, 32, 32, 32));  //金币
        squirrelFly = new Animation(0.2f, new TextureRegion(items, 0, 160, 32, 32), new TextureRegion(items, 32, 160, 32, 32)); //飞着的松鼠
        //主角
        bobJump = new Animation(0.2f, new TextureRegion(items, 0, 128, 32, 32), new TextureRegion(items, 32, 128, 32, 32));
        bobFall = new Animation(0.2f, new TextureRegion(items, 64, 128, 32, 32), new TextureRegion(items, 96, 128, 32, 32));
        bobHit = new TextureRegion(items, 128, 128, 32, 32);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

   运行一下代码,我们发现,我们操作者主角向上移动,会遇到弹簧,会破碎的跳板,飞着的松鼠,金币,一切都正常的运行着! 仔细一看,加上金币后分数值没有改变哦!当然还有死亡的判断,音效的加入等等。

效果图:


在此先做一个代码版本,方便初学者能够清楚的了解代码

源码下载:http://down.51cto.com/data/897211


下面我们来完成分值的计算:


在GameScreen中:

/**游戏运行状态**/
    private void updateRunning (float deltaTime) {
        if (Gdx.input.justTouched()) {
            guiCam.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
            //点击暂停
            if (OverlapTester.pointInRectangle(pauseBounds, touchPoint.x, touchPoint.y)) {
                Assets.playSound(Assets.clickSound);
                state = GAME_PAUSED;
                return;
            }
        }
                                                                                                                                                                                                                                                                                                                                                                                    
        ApplicationType appType = Gdx.app.getType();
                                                                                                                                                                                                                                                                                                                                                                                    
        // should work also with Gdx.input.isPeripheralAvailable(Peripheral.Accelerometer)
        if (appType == ApplicationType.Android || appType == ApplicationType.iOS) {
            world.update(deltaTime, Gdx.input.getAccelerometerX());
        } else {
            float accel = 0;
            if (Gdx.input.isKeyPressed(Keys.DPAD_LEFT)) accel = 5f;
            if (Gdx.input.isKeyPressed(Keys.DPAD_RIGHT)) accel = -5f;
            world.update(deltaTime, accel);
        }
        //当前分数(变化)
        if (world.score != lastScore) {
            lastScore = world.score;
            scoreString = "SCORE: " + lastScore;
        }
        //本关结束
        if (world.state == World.WORLD_STATE_NEXT_LEVEL) {
            state = GAME_LEVEL_END;
        }
        //游戏结束,分值计算
        if (world.state == World.WORLD_STATE_GAME_OVER) {
            state = GAME_OVER;
            if (lastScore >= Settings.highscores[4])
                scoreString = "NEW HIGHSCORE: " + lastScore;
            else
                scoreString = "SCORE: " + lastScore;
            //获取最后分数
            Settings.addScore(lastScore);
            //保存分数
            Settings.save();
        }
                                                                                                                                                                                                                                                                                                                                                                                    
    }

   这里我们每次碰到金币就会加上10分,到游戏结束后,将最终得分保存起来,同时更新排行榜。

Settings:

package com.zhf.mylibgdx;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import com.badlogic.gdx.Gdx;
/**
 * 设置类:三个方法: 1.load()读取声音开关和最高分.  2.save()保存配置     3.addScore()最高分排行榜,对数组赋值。
 * @author ZHF
 *
 */
public class Settings {
    //记录声音开起与关闭
    public static boolean soundEnabled = true;
    //默认分数排行榜分数
    public final static int[] highscores = new int[] {100, 80, 50, 30, 10};
    //保存的文件名
    public final static String file = ".superjumper";
                                                                                                                                                                                                                                                                                                                                                    
    /**加载配置文件**/
    public static void load () {
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(Gdx.files.external(file).read()));
            soundEnabled = Boolean.parseBoolean(in.readLine());
            for (int i = 0; i < 5; i++) {
                highscores[i] = Integer.parseInt(in.readLine());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) in.close();
            } catch (IOException e) {
            }
        }
    }
    /**保存分值**/
    public static void save () {
        BufferedWriter out = null;
        try {
            //声音的开关
            out = new BufferedWriter(new OutputStreamWriter(Gdx.files.external(file).write(false)));
            out.write(Boolean.toString(soundEnabled));
            for (int i = 0; i < 5; i++) {
                //将分数写入文件
                out.write(Integer.toString(highscores[i]));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) out.close();
            } catch (IOException e) {
            }
        }
    }
    /**将所得分数与排行榜分数比较,从高到低重新排一下**/
    public static void addScore (int score) {
        for (int i = 0; i < 5; i++) {
            if (highscores[i] < score) {
                for (int j = 4; j > i; j--)
                    highscores[j] = highscores[j - 1];
                highscores[i] = score;
                break;
            }
        }
    }
}


   再次运行代码,加了几个金币,分值发生变化了,回到主界面分数排行榜也发生变化了!(原先默认:100, 80, 50, 30, 10


接下来就是声音部分:


我们再次回到GameScreen中:

//实例化场景
        worldListener = new WorldListener() {
            @Override
            public void jump () {
                Assets.playSound(Assets.jumpSound);
            }
            @Override
            public void highJump () {
                Assets.playSound(Assets.highJumpSound);
            }
            @Override
            public void hit () {
                Assets.playSound(Assets.hitSound);
            }
            @Override
            public void coin () {
                Assets.playSound(Assets.coinSound);
            }
        };

   

   在监听器中给对应方法播放对应的声音,当然少不了在Asset中添加对声音资源的加载:

声明:

//声音部分
    public static Sound clickSound; //按下音效
    public static Music music;  //背景音乐
    public static Sound jumpSound; //跳跃
    public static Sound highJumpSound; //高跳
    public static Sound hitSound; //碰撞
    public static Sound coinSound;  //金币

实例化:

//背景音乐
        music = Gdx.audio.newMusic(Gdx.files.internal("data/music.mp3"));
        music.setLooping(true); //循环
        music.setVolume(0.5f);  //大小
        if (Settings.soundEnabled) music.play();
                                                                                                                                                          
        jumpSound = Gdx.audio.newSound(Gdx.files.internal("data/jump.ogg"));
        highJumpSound = Gdx.audio.newSound(Gdx.files.internal("data/highjump.ogg"));
        hitSound = Gdx.audio.newSound(Gdx.files.internal("data/hit.ogg"));
        coinSound = Gdx.audio.newSound(Gdx.files.internal("data/coin.ogg"));
        //点击音效
        clickSound = Gdx.audio.newSound(Gdx.files.internal("data/click.ogg"));


ok!运行一下!貌似没有什么问题,对应的声音都播放出来了!


  到此为止,libgdx中demo程序superjumper分版本的学习就结束了,由于本人也是边学边总结,中间肯定有许多地方讲解的不完善,不妥的地方,这里先想大家说声抱歉哈,希望大家发现问题能及时提出来,这样我也能进步么!这里还是那句话,在学习新东西的时候,我们的不求甚解也不失为一种快速掌握的好方法! 希望这一些列学习笔记能帮助到初学者!


完整代码下载:http://down.51cto.com/data/897232  代码里详细注解哦!


你可能感兴趣的:(android,文件保存,游戏开发,libgdx,superjumper,声音和音效处理)