首页 > 代码库 > Running Hero.
Running Hero.
Running Hero开发流程
一、需求分析
Running Hero是在接到大作业以前就已经有的想法,一直没有好的契机好好策划实现,正巧通过此次作业的机会,将它实现出来了。
Running Hero 的初步定义是一款结合了传统的横版闯关以及当下最流行的酷跑模式的新型横版手游,大体上分成两个模块,单机闯关以及网络联机对战,由于技术不太成熟以及时间原因,暂时只开发了单机闯关板块。
Running Hero 整体风格设计为卡通类型的,素材(能力有限,非原创)出自66rpg素材网,游戏流程设计为:
通过避开关卡中的各种陷阱,收集主角升级所需的物品,提升等级来提升主角的各方面的能力值(攻击力,防御力,生命值,力量等)来让你的主角跑得更远;通过击败关卡中的小型怪物获取一些装备,提升主角能力值;通过击败一定距离之后的Boss解锁下一个场景,获得更多的位置元素以及更丰富的游戏玩法,提升游戏的可玩性,用当下比较流行的游戏次数限制(时间性恢复)延长游戏的寿命。
游戏主要有开始界面,游戏界面,暂停界面,菜单界面,装备及属性界面。
有较为丰富的游戏元素和玩法,比较完善的游戏场景,动作效果,音效,bgm等传统游戏所具有的基本功能。
Running Hero 主要设定有2个角色(一前一后),玩家可自由设置主角的能力值,较为推荐的方式为前面一个厚血主要保护后面一个高攻角色的输出环境提升dps。
关卡设定有陷阱(击退角色并且扣除大量血量,无视防御值);
小型怪物(根据对比它和主角的能力值,计算击退距离,扣除双方血量,完成击杀随机获得物品);
Boss (有较为强力的能力值,初期玩家要多次尝试方可击败,击杀获得大量‘宝物’,解锁场景获得下一关卡的权限)。
装备:静态属性(增加角色能力值),特效:特殊能力(暂不考虑);
二、概要设计
1.游戏流程设计(流程图)
2.游戏用例分析(用例图)
3.游戏类图设计
三,详细设计及编码
游戏核心部分代码,一些关联包没上传,等正式版出来了贴游戏apk以及全部源码
1 package com.me.mygdxgame; 2 3 import com.badlogic.gdx.maps.tiled.TiledMap; 4 5 public class Collision { 6 public static int[][] barriers_1; 7 public static int[][] barriers_2; 8 public static TiledMap map; 9 public static int MAP_CELL_HEIGHT = 32;10 public static int MAP_CELL_WIDTH = 32;11 12 static {13 map = GameScreen.map;14 barriers_1 = GameScreen.barriers_1;15 barriers_2 = GameScreen.barriers_2;16 }17 18 public static boolean onFloor(float x, float y) {19 if (y > 0)20 return barriers_1[(int) (y - 2) / MAP_CELL_HEIGHT][(int) x21 / MAP_CELL_WIDTH] != 0;22 else23 return true;24 }25 26 public static boolean onCeiling(float x, float y) {27 return barriers_2[(int) (y - 2) / MAP_CELL_HEIGHT][(int) x28 / MAP_CELL_WIDTH] != 0;29 }30 31 public static boolean fight(Lead lead, Monster monster) {32 if (lead.x + 32f > monster.x && lead.x < monster.x + 3233 && lead.y > monster.y - 32f && lead.y < monster.y + 32) {34 return true;35 }36 return false;37 38 }39 40 }
1 package com.me.mygdxgame; 2 3 import java.util.ArrayList; 4 5 import com.badlogic.gdx.Game; 6 import com.badlogic.gdx.Gdx; 7 import com.badlogic.gdx.Screen; 8 import com.badlogic.gdx.graphics.GL10; 9 import com.badlogic.gdx.graphics.OrthographicCamera; 10 import com.badlogic.gdx.graphics.Texture; 11 import com.badlogic.gdx.graphics.g2d.SpriteBatch; 12 import com.badlogic.gdx.graphics.g2d.TextureAtlas; 13 import com.badlogic.gdx.graphics.g2d.TextureRegion; 14 import com.badlogic.gdx.maps.MapLayer; 15 import com.badlogic.gdx.maps.MapLayers; 16 import com.badlogic.gdx.maps.MapObject; 17 import com.badlogic.gdx.maps.MapObjects; 18 import com.badlogic.gdx.maps.objects.RectangleMapObject; 19 import com.badlogic.gdx.maps.tiled.TiledMap; 20 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; 21 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell; 22 import com.badlogic.gdx.maps.tiled.TmxMapLoader; 23 import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer; 24 import com.badlogic.gdx.scenes.scene2d.InputEvent; 25 import com.badlogic.gdx.scenes.scene2d.InputListener; 26 import com.badlogic.gdx.scenes.scene2d.Stage; 27 import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; 28 import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; 29 30 public class GameScreen implements Screen { 31 32 Game game; 33 34 public static int[][] barriers_1; 35 public static int[][] barriers_2; 36 public static TiledMap map; 37 public static Lead lead; 38 public static ArrayList<Monster> monsters = new ArrayList<Monster>(); 39 40 private OrthographicCamera camera; 41 private OrthogonalTiledMapRenderer render; 42 public Stage stage; 43 private MapLayers layers; 44 private SpriteBatch batch; 45 46 private ImageButton pauseButton; 47 48 private PauseScreen pauseScreen; 49 50 private TextureAtlas bgi; 51 private TextureAtlas bgi2; 52 private TextureRegion region1; 53 private TextureRegion region2; 54 private TextureRegion region3; 55 private TextureRegion region4; 56 57 float bg1x, bg1y, bg2x, bg2y; 58 float bg3x, bg3y, bg4x, bg4y; 59 60 STATE state = STATE.Run; 61 62 enum STATE { 63 Stop, Run 64 }; 65 66 public GameScreen(Game game){ 67 super(); 68 this.game = game;pauseScreen = new PauseScreen(this); 69 70 lead = new Lead(0, 0); 71 72 map = new TmxMapLoader().load("data/test3.tmx"); 73 74 barriers_1 = new int[11][30]; 75 barriers_2 = new int[10][30]; 76 77 // setWindows(); 78 79 setBackground(); 80 81 setButton(); 82 83 render = new OrthogonalTiledMapRenderer(map); 84 85 camera = new OrthographicCamera(); 86 camera.setToOrtho(false, 480, 320); 87 88 stage = new Stage(480, 320, false); 89 this.setMap(); 90 91 for (int i = 0; i < monsters.size(); i++) { 92 stage.addActor(monsters.get(i)); 93 } 94 95 stage.addActor(lead); 96 stage.addActor(lead.buttonUp); 97 stage.addActor(lead.buttonDown); 98 stage.addActor(lead.tblood); 99 stage.addActor(pauseButton);100 101 102 }103 104 @Override105 public void show() {106 Gdx.input.setInputProcessor(stage);107 }108 109 private void setBackground() {110 bgi = new TextureAtlas(Gdx.files.internal("data/background"));111 bgi2 = new TextureAtlas(Gdx.files.internal("data/background"));112 batch = new SpriteBatch();113 region1 = bgi.findRegion("sky");114 region2 = bgi2.findRegion("sky");115 region1.flip(true, false);116 region3 = bgi.findRegion("moutan");117 region4 = region3;118 119 bg1y = bg2y = 0;120 bg3y = bg4y = 0;121 bg1x = 0;122 bg3x = 0;123 bg2x = bg1x + region1.getRegionWidth();124 bg4x = bg3x + region3.getRegionWidth();125 126 }127 128 private void setButton() {129 pauseButton = new ImageButton(new TextureRegionDrawable(130 new TextureRegion(new Texture(131 Gdx.files.internal("data/red.png")), 32, 32)));132 pauseButton.addListener(new InputListener() {133 @Override134 public void touchUp(InputEvent event, float x, float y,135 int pointer, int button) {136 super.touchUp(event, x, y, pointer, button);137 }138 139 @Override140 public boolean touchDown(InputEvent event, float x, float y,141 int pointer, int button) {142 pause();143 return true;144 }145 146 });147 }148 149 @Override150 public void render(float delta) {151 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);152 if (lead.x + 100 >= camera.position.x) {153 camera.position.x = lead.x + 100;154 stage.getCamera().position.x = lead.x + 100;155 156 bg1x -= 1;157 bg2x -= 1;158 bg3x -= 2;159 bg4x -= 2;160 }161 camera.update();162 render.setView(camera);163 164 update(); 165 stage.act();166 draw();167 168 }169 170 public void draw() {171 batch.begin();172 batch.draw(region1, bg1x, bg1y);173 batch.draw(region2, bg2x, bg2y);174 batch.draw(region3, bg3x, bg3y);175 batch.draw(region4, bg4x, bg4y);176 batch.end();177 render.render();178 stage.draw();179 }180 181 public void update() {182 183 lead.buttonUp.setPosition(camera.position.x - 220f, 20f);184 lead.buttonDown.setPosition(camera.position.x + 190f, 20f);185 186 lead.tblood.setPosition(camera.position.x - 220f, 300f);187 lead.tblood.setScaleX((float) lead.blood / lead.lim_blood);188 189 pauseButton.setPosition(camera.position.x + 190f, 280f);190 191 fight();192 bgmove();193 }194 195 private void bgmove() {196 197 float RH1;198 float RH2;199 200 RH1 = region1.getRegionWidth();201 RH2 = region3.getRegionWidth();202 if (bg1x < -RH1) {203 bg1x = bg2x + RH1;204 }205 if (bg2x < -RH1) {206 bg2x = bg1x + RH1;207 }208 if (bg3x < -RH1) {209 bg3x = bg4x + RH2;210 }211 if (bg4x < -RH1) {212 bg4x = bg3x + RH2;213 }214 215 216 }217 218 public void setMap() {219 layers = map.getLayers();220 for (MapLayer layer : layers) {221 if (layer.getName().equals("actor")) {222 MapObjects objs = layer.getObjects();223 for (MapObject obj : objs) {224 RectangleMapObject ro = (RectangleMapObject) obj;225 Monster monster;226 if (ro.getName().equals("lead")) {227 228 lead.x = ro.getRectangle().x;229 lead.y = ro.getRectangle().y;230 231 } else if (ro.getName().equals("monster")) {232 233 monster = new Monster(ro.getRectangle().x,234 ro.getRectangle().y);235 monster.blood = Integer.parseInt((String) ro236 .getProperties().get("blood"));237 monster.attack = Integer.parseInt((String) ro238 .getProperties().get("attack"));239 // monster.defence = Integer.parseInt((String)240 // ro.getProperties().get("defence"));241 monsters.add(monster);242 // monster.x = ro.getRectangle().x;243 // monster.y = ro.getRectangle().y;244 245 }246 }247 } else if (layer.getName().equals("barriers_1")) {248 if (layer instanceof TiledMapTileLayer) {249 TiledMapTileLayer tileLayer = (TiledMapTileLayer) layer;250 // j为高(行) i为宽(列)251 for (int j = 11; j > 0; j--) {252 for (int i = 0; i < 30; i++) {253 // getCell(列,行) 纵坐标翻转254 Cell cell = tileLayer.getCell(i, j);255 if (cell != null) {256 barriers_1[j][i] = 1;257 }258 }259 }260 261 }262 } else if (layer.getName().equals("barriers_2")) {263 if (layer instanceof TiledMapTileLayer) {264 TiledMapTileLayer tileLayer = (TiledMapTileLayer) layer;265 // j为高(行) i为宽(列)266 for (int j = 10; j > 0; j--) {267 for (int i = 0; i < 30; i++) {268 // getCell(列,行) 纵坐标翻转269 Cell cell = tileLayer.getCell(i, j);270 if (cell != null) {271 barriers_2[j][i] = 1;272 }273 }274 }275 276 }277 }278 }279 }280 281 private void fight() {282 for (int i = 0; i < monsters.size(); i++) {283 Monster monster = monsters.get(i);284 if (Collision.fight(lead, monster)) {285 monster.blood -= lead.attack;286 lead.blood -= monster.attack;287 288 // if(monster.attack - lead.defence > 0)289 // lead.blood -= monster.attack - lead.defence;290 // else291 // lead.blood -= 1;292 if (monster.blood < 0) {293 monsters.remove(i);294 stage.getRoot().removeActor(monster);295 break;296 }297 lead.x -= 20;298 monster.x += 20;299 monster.state = Monster.STATE.Run;300 System.out.println(lead.blood);301 }302 }303 304 }305 306 @Override307 public void resize(int width, int height) {308 // TODO Auto-generated method stub309 310 }311 312 @Override313 public void pause() {314 game.setScreen(pauseScreen);315 // stage.dispose();316 }317 318 public Game getGame(){319 return game; 320 }321 322 @Override323 public void hide() {324 // TODO Auto-generated method stub325 326 }327 328 @Override329 public void resume() {330 game.setScreen(this);331 332 }333 334 @Override335 public void dispose() {336 // TODO Auto-generated method stub337 338 }339 340 }
1 package com.me.mygdxgame; 2 3 import com.badlogic.gdx.Gdx; 4 import com.badlogic.gdx.graphics.Texture; 5 import com.badlogic.gdx.graphics.g2d.Animation; 6 import com.badlogic.gdx.graphics.g2d.SpriteBatch; 7 import com.badlogic.gdx.graphics.g2d.TextureRegion; 8 import com.badlogic.gdx.scenes.scene2d.Actor; 9 import com.badlogic.gdx.scenes.scene2d.InputEvent; 10 import com.badlogic.gdx.scenes.scene2d.InputListener; 11 import com.badlogic.gdx.scenes.scene2d.ui.Image; 12 import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; 13 import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; 14 15 public class Lead extends Actor { 16 public float x; 17 public float y; 18 public float statetime; 19 public int count; 20 21 public int blood; 22 public int attack; 23 // public int defence; 24 public int lim_blood; 25 26 private TextureRegion currentFrame; 27 private Animation walk; 28 public ImageButton buttonUp; 29 public ImageButton buttonDown; 30 public Image tblood; 31 32 public STATE state; 33 34 enum STATE { 35 Air, Floor, Ceiling, JumpUp, JumpDown 36 }; 37 38 public Lead(float x, float y) { 39 this.x = x; 40 this.y = y; 41 lim_blood = 20; 42 blood = lim_blood; 43 attack = 2; 44 // defence = 3; 45 state = STATE.Air; 46 statetime = 0; 47 show(); 48 } 49 50 @Override 51 public void act(float delta) { 52 statetime += delta; 53 check(); 54 update(); 55 currentFrame = walk.getKeyFrame(statetime, true); 56 super.act(delta); 57 } 58 59 private void check() { 60 if (Collision.onFloor(x, y) && state == STATE.Air) { 61 state = STATE.Floor; 62 } else if (Collision.onCeiling(x, y) && state == STATE.Air) { 63 state = STATE.Ceiling; 64 } else if (!Collision.onCeiling(x, y) && !Collision.onFloor(x, y) 65 && state != STATE.JumpUp && state != STATE.JumpDown) { 66 state = STATE.Air; 67 } 68 } 69 70 private void update() { 71 x += 1f; 72 if (state == STATE.Air) { 73 y -= 2f; 74 } 75 if (state == STATE.JumpUp) { 76 y += 2f; 77 count--; 78 if (0 == count) { 79 state = STATE.Air; 80 } 81 } 82 if (state == STATE.JumpDown) { 83 y -= 2f; 84 count--; 85 if (0 == count) { 86 state = STATE.Air; 87 } 88 } 89 90 } 91 92 @Override 93 public void draw(SpriteBatch batch, float parentAlpha) { 94 95 batch.draw(currentFrame, x, y); 96 } 97 98 public void show() { 99 100 tblood = new Image(new Texture(Gdx.files.internal("data/blood.png")));101 102 TextureRegion[] regionWalk = new TextureRegion[2];103 TextureRegion[] regionJumpUp = new TextureRegion[2];104 TextureRegion[] regionJumpDown = new TextureRegion[2];105 regionWalk[0] = new TextureRegion(new Texture(106 Gdx.files.internal("data/red.png")), 32, 32);107 regionWalk[1] = new TextureRegion(new Texture(108 Gdx.files.internal("data/blue.png")), 32, 32);109 regionJumpUp[0] = new TextureRegion(new Texture(110 Gdx.files.internal("data/red.png")), 32, 32);111 regionJumpUp[1] = new TextureRegion(new Texture(112 Gdx.files.internal("data/blue.png")), 32, 32);113 regionJumpDown[0] = new TextureRegion(new Texture(114 Gdx.files.internal("data/red.png")), 32, 32);115 regionJumpDown[1] = new TextureRegion(new Texture(116 Gdx.files.internal("data/blue.png")), 32, 32);117 walk = new Animation(0.1f, regionWalk);118 119 buttonUp = new ImageButton(new TextureRegionDrawable(regionJumpUp[0]),120 new TextureRegionDrawable(regionJumpUp[1]));121 buttonDown = new ImageButton(new TextureRegionDrawable(122 regionJumpDown[0]),123 new TextureRegionDrawable(regionJumpDown[1]));124 125 // buttonUp.setPosition(20, 20);126 // buttonDown.setPosition(420, 20);127 buttonUp.addListener(new InputListener() {128 129 @Override130 public void touchUp(InputEvent event, float x, float y,131 int pointer, int button) {132 super.touchUp(event, x, y, pointer, button);133 }134 135 @Override136 public boolean touchDown(InputEvent event, float x, float y,137 int pointer, int button) {138 if (state == STATE.Ceiling || state == STATE.Floor) {139 state = STATE.JumpUp;140 count = 64;141 }142 return true;143 }144 145 });146 147 buttonDown.addListener(new InputListener() {148 149 @Override150 public void touchUp(InputEvent event, float x, float y,151 int pointer, int button) {152 super.touchUp(event, x, y, pointer, button);153 }154 155 @Override156 public boolean touchDown(InputEvent event, float x, float y,157 int pointer, int button) {158 if (state == STATE.Ceiling) {159 state = STATE.JumpDown;160 count = 32;161 }162 return true;163 }164 165 });166 }167 168 }
1 package com.me.mygdxgame; 2 3 import com.badlogic.gdx.Gdx; 4 import com.badlogic.gdx.graphics.Texture; 5 import com.badlogic.gdx.graphics.g2d.SpriteBatch; 6 import com.badlogic.gdx.graphics.g2d.TextureRegion; 7 import com.badlogic.gdx.scenes.scene2d.Actor; 8 9 public class Monster extends Actor{10 public float x;11 public float y;12 public int blood;13 public int attack;14 // public int defence;15 16 private Texture texture;17 private TextureRegion region;18 19 public STATE state;20 21 enum STATE {22 Stop,Run23 };24 25 public Monster(float x,float y){26 this.state = STATE.Stop;27 this.x = x;28 this.y = y;29 this.creat();30 }31 32 private void creat() {33 texture = new Texture(Gdx.files.internal("data/green.png"));34 region = new TextureRegion(texture,32,32);35 }36 37 @Override38 public void draw(SpriteBatch batch, float parentAlpha) {39 batch.draw(region,this.x,y);40 }41 42 @Override43 public void act(float delta) {44 this.update();45 this.check();46 super.act(delta);47 }48 49 private void check() {50 51 }52 53 private void update() {54 if(state == STATE.Run){55 x -= 1f;56 }57 58 }59 60 // private void check() {61 // // TODO Auto-generated method stub62 // 63 // }64 65 66 67 }
1 package com.me.mygdxgame; 2 3 import com.badlogic.gdx.Game; 4 5 public class MyGame extends Game { 6 GameScreen gameScreen; 7 StartScreen startScreen; 8 PauseScreen pauseScreen; 9 10 @Override11 public void create() {12 startScreen = new StartScreen();13 gameScreen = new GameScreen(this);14 // this .setScreen(startScreen);15 this.setScreen(gameScreen);16 }17 18 }
1 package com.me.mygdxgame; 2 3 import com.badlogic.gdx.Gdx; 4 import com.badlogic.gdx.Screen; 5 import com.badlogic.gdx.graphics.GL10; 6 import com.badlogic.gdx.graphics.Texture; 7 import com.badlogic.gdx.graphics.g2d.TextureRegion; 8 import com.badlogic.gdx.scenes.scene2d.InputEvent; 9 import com.badlogic.gdx.scenes.scene2d.InputListener;10 import com.badlogic.gdx.scenes.scene2d.Stage;11 import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;12 import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;13 14 public class PauseScreen implements Screen {15 16 GameScreen gameScreen;17 private Stage stage;18 private ImageButton keeponButton;19 private TextureRegion[] region;20 21 public PauseScreen(GameScreen gameScreen) {22 super();23 this.gameScreen = gameScreen;24 }25 26 @Override27 public void render(float delta) {28 // TODO Auto-generated method stub29 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);30 gameScreen.draw();31 stage.act();32 stage.draw();33 }34 35 @Override36 public void resize(int width, int height) {37 // TODO Auto-generated method stub38 39 }40 41 @Override42 public void show() {43 stage = new Stage(480, 320, false);44 45 region = new TextureRegion[2];46 47 region[0] = new TextureRegion(new Texture(48 Gdx.files.internal("data/red.png")), 32, 32);49 region[1] = new TextureRegion(new Texture(50 Gdx.files.internal("data/blue.png")), 32, 32);51 52 keeponButton = new ImageButton(new TextureRegionDrawable(region[0]),53 new TextureRegionDrawable(region[1]));54 keeponButton.setPosition(100, 100);55 stage.addActor(keeponButton);56 Gdx.input.setInputProcessor(stage);57 keeponButton.addListener(new InputListener() {58 @Override59 public void touchUp(InputEvent event, float x, float y,60 int pointer, int button) {61 super.touchUp(event, x, y, pointer, button);62 }63 64 @Override65 public boolean touchDown(InputEvent event, float x, float y,66 int pointer, int button) {67 stage.dispose();68 gameScreen.getGame().setScreen(gameScreen);69 return true;70 }71 72 });73 }74 75 @Override76 public void hide() {77 // TODO Auto-generated method stub78 79 }80 81 @Override82 public void pause() {83 // TODO Auto-generated method stub84 85 }86 87 @Override88 public void resume() {89 // TODO Auto-generated method stub90 91 }92 93 @Override94 public void dispose() {95 // TODO Auto-generated method stub96 97 }98 99 }
1 package com.me.mygdxgame; 2 3 import com.badlogic.gdx.Screen; 4 5 public class StartScreen implements Screen{ 6 7 @Override 8 public void render(float delta) { 9 10 }11 12 @Override13 public void resize(int width, int height) {14 15 }16 17 @Override18 public void show() {19 20 }21 22 @Override23 public void hide() {24 25 }26 27 @Override28 public void pause() {29 30 }31 32 @Override33 public void resume() {34 35 }36 37 @Override38 public void dispose() {39 40 }41 42 }
四,测试及性能测试
敬请期待.....
五,总结
到此为止整个游戏的从
收集素材,整理素材,美工切图(张洋华)
策划----------->设计: 学习引擎框架,准备编码(黄少曦)
设计文档,收集资料(杨卓)
修改设计界面
----------->实现: 细节编码 -----------> 调试,测试,性能分析(暂无)
完善文档
也算是有了点结果了,算起来作为一个导航员我已经不是第一次做游戏了,但是在这个过程中所遇到的问题还是很多,不管是设计上还是编码有很多地方存在不足之处,在一边抓紧进度的同时也尽力寻求突破口,整个过程确确实实给了我们三个很大的挑战,非常感谢也很感动我们这个特别的三人组(老师要求的是结对编程)的两位小伙伴在整个过程中的坚持不懈,毫无怨言,华仔(张洋华)在切图的过程中,连续很多个小时盯着PS不断的修修修改改改,那种感觉不是每个人都能体会到都能承受的;对于少爷(黄少曦)实实在在的很感动,断断续续也算是熬了好多个半夜吧,真的辛苦了。我想不管结果怎么样,我相信对于我们三个收获的东西已经足够多了,一次有始有终还蛮成功的合作并没有到12点就截止,在这个过程中明确的分工让我们体会到了团队的重要性,彼此对于作为团队成员的重要性,你给与别人的信任相同的他也是一样的信任于你;前前后后蹲实验室也是蹲了很多天,少了蛮多的休息和娱乐的时间,换回来的不只是一个简单的游戏,更多的是对于未来的明确和下一步的目标,只要我们坚持下去,胜利的钟声肯定是为我们敲响的。
We are all running hero.
原谅我笨拙的英语,总之一起加油吧,兄弟。
Running Hero.