libgdx自制简易版Don't Touch The White Tile
Don't Toutch The White说来也奇快,本来没什么难的,但是在欧美ios榜上却雄踞榜首好长时间。即使是在国内,也很火,还真是想不通,谁能解释下,难道真是所谓的抓住了用户的G点,或是这些开发者够极客。
这个问题,很难回答。算了,不去追究了,技术人员还是安心敲个代码吧!!!
下面是我自己的代码,使用libgdx做的,纯手工的。
game类,游戏入口,主类
package com.fxb.whitetile; import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.scenes.scene2d.ui.Skin; public class WhiteTile extends Game{ static Skin skin; StartScreen startScreen; static GameScreen gameScreen; LevelScreen levelScreen; @Override public void create() { // TODO Auto-generated method stub skin = new Skin( Gdx.files.internal( "skin/uiskin.json" ) ); startScreen = new StartScreen( this ); gameScreen = new GameScreen( this ); levelScreen = new LevelScreen( this ); setScreen( startScreen ); } @Override public void dispose() { // TODO Auto-generated method stub skin.dispose(); startScreen.dispose(); gameScreen.dispose(); levelScreen.dispose(); super.dispose(); } }
//开始场景
package com.fxb.whitetile; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.scenes.scene2d.Action; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; public class StartScreen extends ScreenAdapter{ WhiteTile game; Stage stage; TextButton btnStart, btnLevel; SequenceAction actionTotal; public StartScreen(WhiteTile game0){ game = game0; stage = new Stage(); btnStart = new TextButton( "Start Game", WhiteTile.skin, "default" ); btnStart.addListener( new InputListener(){ @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub return true; } @Override public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub stage.addAction( actionTotal ); } }); btnLevel = new TextButton( "Select Mode", WhiteTile.skin, "default" ); btnLevel.addListener( new InputListener(){ @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub return true; } @Override public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub game.setScreen( game.levelScreen ); } }); //stage.addAction( Actions.fadeOut( 2 ) ); Action actionChange = new Action(){ @Override public boolean act(float delta) { // TODO Auto-generated method stub game.setScreen( game.gameScreen ); dispose(); return false; } }; Action actionRotate = Actions.rotateBy( -360, 2 ); //actionTotal = Actions.sequence( Actions.parallel( actionRotate, Actions.fadeOut(2) ), actionChange ); actionTotal = Actions.sequence( Actions.fadeOut(0.2f), actionChange ); btnStart.setSize( 150, 70 ); btnStart.setPosition( stage.getWidth()/2-btnStart.getWidth()/2, stage.getHeight()/2-btnStart.getHeight()-50 ); btnLevel.setSize( 150, 70 ); btnLevel.setPosition( stage.getWidth()/2-btnStart.getWidth()/2, stage.getHeight()/2+50 ); stage.addActor( btnStart ); stage.addActor( btnLevel ); } @Override public void show() { // TODO Auto-generated method stub Gdx.input.setInputProcessor( stage ); } @Override public void render(float delta) { // TODO Auto-generated method stub Gdx.gl.glClearColor( 0, 1, 1, 1 ); Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); stage.act(); stage.draw(); } @Override public void dispose() { // TODO Auto-generated method stub //stage.dispose(); super.dispose(); } }
//模式选择场景
package com.fxb.whitetile; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; public class LevelScreen extends ScreenAdapter{ WhiteTile game; Stage stage; //Table table; TextButton[] sButton; public LevelScreen(WhiteTile game0){ game = game0; stage = new Stage(); //table = new Table( WhiteTile.skin ); sButton = new TextButton[3]; String[] arrStr = { "Simple", "Normal", "Hard" }; for( int i=0; i<sButton.length; ++i ){ sButton[i] = new TextButton( arrStr[i], WhiteTile.skin ); sButton[i].setSize( 150, 60 ); stage.addActor( sButton[i] ); //table.row(); } sButton[0].addListener(new InputListener(){ @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub return true; } @Override public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub Constant.level = 1; game.setScreen( game.startScreen ); } }); sButton[1].addListener(new InputListener(){ @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub return true; } @Override public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub Constant.level = 2; game.setScreen( game.startScreen ); } }); sButton[2].addListener(new InputListener(){ @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub return true; } @Override public void touchUp(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub Constant.level = 3; game.setScreen( game.startScreen ); } }); //stage.addActor( table ); //table //sButton[i].setPosition( stage.getWidth()/2-sButton[i].getWidth()/2, stage.getHeight()/2 ); sButton[0].setPosition( stage.getWidth()/2-sButton[0].getWidth()/2, stage.getHeight()/2+sButton[0].getHeight()/2+50 ); sButton[1].setPosition( stage.getWidth()/2-sButton[1].getWidth()/2, stage.getHeight()/2-sButton[1].getHeight()/2 ); sButton[2].setPosition( stage.getWidth()/2-sButton[2].getWidth()/2, stage.getHeight()/2-3*sButton[2].getHeight()/2-50 ); } public boolean IsInside( Actor actor, float x, float y ){ return x>actor.getX() && x<actor.getRight() && y>actor.getY() && y>actor.getTop(); } @Override public void render(float delta) { // TODO Auto-generated method stub Gdx.gl.glClearColor( 0, 1, 1, 1 ); Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); stage.act(); stage.draw(); } @Override public void show() { // TODO Auto-generated method stub Gdx.input.setInputProcessor( stage ); super.show(); } @Override public void dispose() { // TODO Auto-generated method stub super.dispose(); } }
//游戏主场景
package com.fxb.whitetile; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.graphics.GL10; public class GameScreen extends ScreenAdapter{ WhiteTile game; GameStage gameStage; OverStage overStage; public GameScreen( WhiteTile game0 ){ game = game0; gameStage = new GameStage(this); overStage = new OverStage(); } @Override public void show() { // TODO Auto-generated method stub Gdx.input.setInputProcessor( gameStage ); //Constant.state = Constant.GameState.game_on; } @Override public void render(float delta) { // TODO Auto-generated method stub if( Constant.state == Constant.GameState.game_ready ){ gameStage.act(); gameStage.draw(); gameStage.Clear(); Constant.state = Constant.GameState.game_on; Gdx.input.setInputProcessor( gameStage ); } else if( Constant.state == Constant.GameState.game_on ){ Gdx.gl.glClearColor( 0, 1, 1, 1 ); Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); gameStage.act(); gameStage.draw(); } else if( Constant.state == Constant.GameState.game_preover ){ Gdx.gl.glClearColor( 0, 1, 1, 1 ); Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); gameStage.draw(); overStage.act(); overStage.draw(); Gdx.input.setInputProcessor( overStage ); } else if( Constant.state == Constant.GameState.game_over ){ //dispose(); Gdx.app.exit(); } } @Override public void dispose() { // TODO Auto-generated method stub gameStage.dispose(); super.dispose(); } }
//游戏主舞台
package com.fxb.whitetile;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.utils.Pool; import com.badlogic.gdx.utils.Pools; import com.fxb.whitetile.Constant.GameState; public class GameStage extends Stage{ //Pool<Image> poolWhite; //Pool<Image> poolBlack; Pool<Block> poolBlock; int topIndex; float transferHeight; float imgHeight; Group groupImg; Drawable drawWhite; Drawable drawGray; GameScreen gameScreen; float speed; int count; int lastIndex1, lastIndex2; Block block; public GameStage(GameScreen screen0){ //poolWhite = Pools.get( Image.class ); //poolBlack = Pools.get( Image.class ); gameScreen = screen0; poolBlock = Pools.get( Block.class ); imgHeight = (this.getHeight()-9)/4; groupImg = new Group(); this.addActor( groupImg ); drawGray = WhiteTile.skin.newDrawable( "white", Color.GRAY ); drawWhite = WhiteTile.skin.newDrawable( "white" ); //Block.gameScreen = gameScreen; Clear(); } public void Clear(){ topIndex = 5; this.getCamera().translate( 0, -transferHeight, 0 ); transferHeight = 0; speed = Constant.initSpeed*Constant.level; count = 0; groupImg.clear(); poolBlock.clear(); lastIndex1 = lastIndex2 = -1; for( int j=0; j<topIndex; ++j ){ AddBlock( j ); } } public void AddBlock( int yIndex ){ int index; do{ index = MathUtils.random( 98 )%3; }while( lastIndex1==lastIndex2 && index==lastIndex1 ); lastIndex2 = lastIndex1; lastIndex1 = index; for( int i=0; i<3; ++i ){ Block block = poolBlock.obtain(); block.Clear(); if( i == index ){ block.color = Color.GRAY; block.setDrawable( drawGray ); }else{ block.color = Color.WHITE; block.setDrawable( drawWhite ); } //blockTran = block; //block.gameScreen = gameScreen; block.setSize( (this.getWidth()-12)/3, imgHeight ); block.setPosition( 3+3*i+i*block.getWidth(), (yIndex+2)*(imgHeight+3) ); groupImg.addActor( block ); } } @Override public void draw() { // TODO Auto-generated method stub super.draw(); } @Override public void act() { // TODO Auto-generated method stub count++; if( count > 60 ){ count = 0; speed += Constant.speedInc*Constant.level; } getCamera().translate( 0, speed, 0 ); transferHeight += speed; /* for( int i=0; i<groupImg.getChildren().size; ++i ){ Block block = (Block)groupImg.getChildren().items[i]; if( block.getY() < transferHeight && block.color==Color.GRAY && !block.isTouch ){ Constant.state = Constant.GameState.game_preover; } } */ boolean bIsDis = false; for( int i=0; i<groupImg.getChildren().size; ++i ){ Block block = (Block)groupImg.getChildren().items[i]; if( block.color==Color.WHITE && block.isTouch ){ Constant.state = Constant.GameState.game_preover; //gameScreen.overStage = new OverStage(); gameScreen.overStage.Show(); Gdx.input.setInputProcessor( gameScreen.overStage ); } if( block.getTop() < transferHeight ) { if( block.color==Color.GRAY && !block.isTouch ){ Constant.state = Constant.GameState.game_preover; //gameScreen.overStage = new OverStage(); gameScreen.overStage.Show(); Gdx.input.setInputProcessor( gameScreen.overStage ); } groupImg.removeActor( block ); poolBlock.free( block ); if( !bIsDis ){ bIsDis = true; } } } if( bIsDis ){ AddBlock( topIndex ); topIndex++; } super.act(); } @Override public void dispose() { // TODO Auto-generated method stub super.dispose(); } }
//游戏结束舞台
package com.fxb.whitetile; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Dialog; public class OverStage extends Stage{ Dialog dialogOver; GameScreen gameScreen; public OverStage(){ dialogOver = new Dialog( "", WhiteTile.skin, "dialog" ){ @Override protected void result(Object object) { // TODO Auto-generated method stub //System.out.println( "Chosen" + object ); if( object.toString().equals( "true" ) ){ Constant.state = Constant.GameState.game_ready; }else{ System.out.println( "No" ); Constant.state = Constant.GameState.game_over; Gdx.app.exit(); } } }; dialogOver.text("GAME OVER").button("Again", true).button("Exit", false); addActor( dialogOver ); dialogOver.setSize( 150, 100 ); dialogOver.setPosition( this.getWidth()/2-dialogOver.getWidth()/2, this.getHeight()/2-dialogOver.getHeight()/2 ); //dialogOver.show( this ); } public void Show(){ //addActor( dialogOver ); dialogOver.show(this); } }
//游戏中元素块,白块或灰块
package com.fxb.whitetile; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.ui.Image; public class Block extends Image{ Color color; boolean isTouch; //GameScreen gameScreen; public Block(){ Clear(); addListener( new InputListener(){ @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { // TODO Auto-generated method stub isTouch = true; if( color == Color.WHITE ){ //Constant.state = Constant.GameState.game_preover; //gameScreen.game. overStage.Show(); //gameScreen.overStage.Show(); } return true; } }); } public void Clear(){ isTouch = false; } }
//全局参数类
package com.fxb.whitetile; public class Constant { enum GameState{ game_ready, game_on, game_pause, game_over, game_preover }; public static GameState state = GameState.game_ready; public static float initSpeed = 5; public static float speedInc = 0.25f; public static int level = 2; }
游戏写的很粗糙,自己试了下,在android手机下能运行,但有些bug,还有待改进。还望大家多多指正,谢谢!!!