canvas小游戲——flappy_bird

前言

如果說學(xué)編程就是學(xué)邏輯的話家妆,那鍛煉邏輯能力的最好方法就莫過于寫游戲了。最近看了一位大神的fly bird小游戲冕茅,感覺很有幫助伤极。于是為了尋求進(jìn)一步的提高蛹找,我花了兩天時間自己寫了一個canvas版本的。雖然看起來原理都差不多哨坪,但是實現(xiàn)方法大相徑庭庸疾,如果有興趣的話可以大家自己下載下來玩一玩,大概效果就像下面這樣:

游戲效果
游戲效果


怎么樣当编?是不是感覺難度巨大届慈?...可能是因為我比較菜吧。相信高手還是大有人在的忿偷,隨便過個幾十關(guān)也是不在話下金顿。但是如果有和我一樣10關(guān)都過不了小菜雞的話,根本不用喪氣對吧鲤桥?咱是程序員是不是揍拆?游戲不會玩,作弊還不會嗎茶凳?咳咳礁凡,下面就是作弊的方法:

首先搞清楚結(jié)構(gòu)

<style>a
  *{
    margin: 0;
    padding: 0;
  }
  html,body {
    height: 100%;
    width: 100%;
    overflow: hidden;
  }
  #canvas{
    display: block;
    margin: 50px auto;
  }
</style>
<canvas id="canvas" width="343" height="480"></canvas>

很簡單,就是這樣慧妄。

注意顷牌!我要開始說了

首先咱先加載一下所有的圖片

// 圖片集合
var imgs = {
  //創(chuàng)建圖片
  bg: new Image(),
  grass: new Image(),
  title: new Image(),
  bird0: new Image(),
  bird1: new Image(),
  up_bird0: new Image(),
  up_bird1: new Image(),
  down_bird0: new Image(),
  down_bird1: new Image(),
  startBtn: new Image(),
  up_pipe: new Image(),
  up_mod: new Image(),
  down_pipe: new Image(),
  down_mod: new Image(),
  scroe0:new Image(),
  scroe1:new Image(),
  scroe2:new Image(),
  scroe3:new Image(),
  scroe4:new Image(),
  scroe5:new Image(),
  scroe6:new Image(),
  scroe7:new Image(),
  scroe8:new Image(),
  scroe9:new Image(),
  //加載圖片
  loadImg: function (fn) {
    this.bg.src = './img/bg.jpg';
    this.grass.src = './img/banner.jpg';
    this.title.src = './img/head.jpg';
    this.bird0.src = './img/bird0.png';
    this.bird1.src = './img/bird1.png';
    this.up_bird0.src = './img/up_bird0.png';
    this.up_bird1.src = './img/up_bird1.png';
    this.down_bird0.src = './img/down_bird0.png';
    this.down_bird1.src = './img/down_bird1.png';
    this.startBtn.src = './img/start.jpg';
    this.up_pipe.src = './img/up_pipe.png';
    this.up_mod.src = './img/up_mod.png';
    this.down_pipe.src = './img/down_pipe.png';
    this.down_mod.src = './img/down_mod.png';
    this.scroe0.src = './img/0.jpg';
    this.scroe1.src = './img/1.jpg';
    this.scroe2.src = './img/2.jpg';
    this.scroe3.src = './img/3.jpg';
    this.scroe4.src = './img/4.jpg';
    this.scroe5.src = './img/5.jpg';
    this.scroe6.src = './img/6.jpg';
    this.scroe7.src = './img/7.jpg';
    this.scroe8.src = './img/8.jpg';
    this.scroe9.src = './img/9.jpg';
    var that = this;
    //添加定時器,判斷圖片是否加載完成
    var timer = setInterval(function() {
      if (that.bg.complete&&that.grass.complete
        &&that.title.complete&&that.startBtn.complete
        &&that.bird0.complete&&that.bird1.complete
        &&that.up_bird0.complete&&that.up_bird1.complete
        &&that.down_bird0.complete&&that.down_bird1.complete
        &&that.up_pipe.complete&&that.up_mod.complete
        &&that.down_mod.complete&&that.down_pipe.complete
        &&that.scroe0.complete&&that.scroe1.complete
        &&that.scroe2.complete&&that.scroe3.complete
        &&that.scroe4.complete&&that.scroe5.complete
        &&that.scroe6.complete&&that.scroe7.complete
        &&that.scroe8.complete&&that.scroe9.complete) {
        //刪除定時器
        clearInterval(timer);
        //圖片全部加載完成后塞淹,運(yùn)行此函數(shù)
        fn();
      }
    }, 50)
  }
}

...抱歉有點(diǎn)長窟蓝,但是怕破壞代碼的結(jié)構(gòu),就全部拷下來了饱普,上面的朋友快點(diǎn)下來吧运挫,都是重復(fù)的沒啥好看的。我來給大家解釋一下套耕,首先這是一個對象字面量谁帕,創(chuàng)建的時候新建了若干個圖片對象,然后它有一個函數(shù)loadImg冯袍,只要一執(zhí)行匈挖,就會給所有的圖片添加路徑,然后添加一個定時器每一段時間通過查詢所有圖片的complete屬性判斷圖片是否全部加載完成康愤。如果是儡循,就刪除這個定時器,并執(zhí)行一段回調(diào)函數(shù)征冷,還是很好理解的吧:)择膝,不過我感覺這種方法可能有點(diǎn)蠢,不知道各位高人有沒有更好的方法检激?

接下來肴捉,就要開始畫了

大家都知道腹侣,其實canvas就是畫圖,如果要用canvas實現(xiàn)動畫效果的話齿穗,就只能一遍一遍的擦了畫谱醇、畫了擦了京景。

首先

先把幾個固定不動的部分的繪制方法和清空畫布的方法寫在函數(shù)里

//繪制背景
  function drawBg() {
    ctx.drawImage(imgs.bg,0,0);
  }
  //繪制開始按鈕
  function drawStartBtn() {
    ctx.drawImage(imgs.startBtn,130,300);
  }
    //清空畫布
  function clean() {
    ctx.clearRect(0,0,canvas.width,canvas.height);
  }

然后

把會動的部分也加上

var v = 0;//草坪滾動的增量
  //繪制草坪
  function drawGrass() {
    //每次運(yùn)行橫坐標(biāo)向左移
    ctx.drawImage(imgs.grass,3*v--,423);
    ctx.drawImage(imgs.grass,337+3*v--,423);
    if(3*v < -343){
      v=0;
    }
  }

這樣每次運(yùn)行一次坯汤,草坪就會向左移一點(diǎn)了

var shake = true;//標(biāo)題的抖動狀態(tài)
  //標(biāo)題的抖動效果
  function titleShake() {
    if (shake) {
      ctx.drawImage(imgs.title,53,97);
      ctx.drawImage(imgs.bird1,250,137);
    }else{
      ctx.drawImage(imgs.title,53,103);
      ctx.drawImage(imgs.bird0,250,143);
    }
  }

這樣通過改變shake的值瘾晃,就可以使標(biāo)題的抖動了蓝晒。
機(jī)智的各位應(yīng)該已經(jīng)發(fā)現(xiàn)了腮出,上面兩個函數(shù)需要重復(fù)調(diào)用,才能產(chǎn)生動畫的效果芝薇,所以這就是我接下來要講的胚嘲。

開始界面的定時器

開始界面
開始界面
var startTimer;//開始界面定時器
var startTime = 0;//定時器運(yùn)行的次數(shù)
function startLayer() {
    startTimer = setInterval(function () {
      clean();
      drawBg();
      drawStartBtn();
      drawGrass();
      titleShake();
      //定時器每運(yùn)行7次改變標(biāo)題位置
      if(startTime == 7){
        shake = !shake;
        startTime = 0;
      }
      //運(yùn)行次數(shù)+1
      startTime++;
      //window.requestAnimationFrame(startLayer)
    }, 24);
  }

大家也可以理解為這就是開始界面,因為開始界面就是通過定時器一次次運(yùn)行上面的函數(shù)所實現(xiàn)的洛二。然而上面定義的startTimer和startTime又有什么用呢馋劈,當(dāng)然不是多此一舉,首先晾嘶,把這個定時器賦給一個變量妓雾,是為了在開始游戲的時候把這個界面關(guān)掉,也就是把這個定時器取消垒迂,往后看大家就明白了:)其次械姻,startTime是為了記錄定時器運(yùn)行的次數(shù),因為這個定時器刷新的實現(xiàn)極快机断,只有短短的24毫秒楷拳,如果標(biāo)題以這個速度抖動的話,大家的眼睛一定受不了了吧吏奸,所以我設(shè)法讓他慢下來欢揖,每運(yùn)行7次抖動一次,當(dāng)然大家可以設(shè)置9奋蔚、10她混、11使它的頻率更加緩慢(大家還可以嘗試使用requestAnimation-
-Frame,那樣性能更佳,但是控制頻率略顯麻煩泊碑。這里使用setInterval更容易理解)當(dāng)然這個作弊沒有半毛錢關(guān)系产上,不過下面就是重頭戲了。

主角登場6旯贰=痢!

var bird = {
  bird: [imgs.bird0,imgs.bird1],//正常狀態(tài)沉桌,圖片
  up_bird: [imgs.up_bird0,imgs.up_bird1],//向上飛狀態(tài)
  down_bird: [imgs.down_bird0,imgs.down_bird1],//向下掉狀態(tài)
  posX: 100,//橫坐標(biāo)
  posY: 200,//縱坐標(biāo)Y
  speed: 0,//速度
  index: 0,//翅膀揮動谢鹊,切換圖片的標(biāo)
  alive: true,//存活狀態(tài)
  //繪制小鳥
  draw: function (bird) {
    ctx.drawImage(bird,this.posX,this.posY);
  },
  //飛行中
  fly: function () {
    //縱坐標(biāo)隨速度改變
    this.posY+=this.speed;
    //加速度為1
    this.speed++;
    //如果墜地算吩,死亡
    if(this.posY >= 395){
      this.speed = 0;
      this.draw(this.bird[this.index]);
      this.dead();
    }
    //如果撞頂,彈回來
    if(this.posY <= 0){
      this.speed = 6;
    }
    //如果速度為正佃扼,則向下偎巢,反之,則向上兼耀,否則水平
    if(this.speed>0){
      this.draw(this.down_bird[this.index]);
    }else if(this.speed<0){
      this.draw(this.up_bird[this.index]);
    }else{
      this.draw(this.bird[this.index]);
    }
    //確保墜落速度不會太快
    if(bird.speed > 6){
      bird.speed = 6;
    }
  },
  //煽動翅膀压昼,切換圖片
  wingWave: function () {
    this.index++;
    if(this.index > 1){
      this.index = 0;
    }
  },
  //死亡
  dead: function() {
    this.alive = false;
  }
}

...當(dāng)然這只是主角的代碼,一個對象字面量瘤运。但是它可以操控主角的所有行為(雖然也沒有幾個行為...)窍霞,首先就是畫出主角draw(),通過傳進(jìn)不同的圖片繪制出主角不同情況下的英姿...然后是wingWave()拯坟,通過改變index,切換上面定義的圖片數(shù)組中的圖片但金,也就是揮翅膀。再然后就是飛行fly(),在飛行過程中主角會碰到各種各樣的事故郁季,像是飛的太高撞到天花板啊冷溃,或是飛的太低,摔了個狗啃屎梦裂。再干脆點(diǎn)一頭撞死在了鋼管上似枕,但是這個函數(shù)并不在這里,因為小鳥撞死在鋼管上到底是小鳥的行為年柠,還是鋼管的行為呢菠净,我還沒想明白,所以干脆放在了全局中彪杉。

  //判斷是否碰撞
  function isHit(oPipe){
    if(bird.posX+bird.bird[0].width>oPipe.posX&&bird.posX<oPipe.posX+oPipe.down_pipe.width){
      if(bird.posY<oPipe.up_posY||bird.posY+30>oPipe.down_posY){
        bird.dead();
      }
    }
  }

就像這樣毅往,通過判斷小鳥和鋼管的位置判斷小鳥是不是撞在鋼管上了。反正結(jié)果還是撞死bird.dead()派近∨饰ǎ看到這里相信不用我說,大家也明白了吧渴丸,只要將這段代碼注釋掉侯嘀,我們的小鳥不就練成的絕世鐵頭功,鋼管都捅穿給你看谱轨〗溽#或者稍稍增大一點(diǎn)小鳥會被碰撞到的體積,那就是凌波微步土童、輕功管上飄了呀诗茎。說了半天,還沒告訴大家這個水管又是哪里來的献汗。

鋼管

//水管類
class Pipe {
  constructor(up_pipe,up_mod,down_pipe,down_mod) {
    //構(gòu)造函數(shù)
    this.up_pipe = up_pipe;//上水管頭部
    this.up_mod = up_mod;//上水管中間部分
    this.down_pipe = down_pipe;
    this.down_mod = down_mod;
    this.up_height = Math.floor(Math.random()*60);//隨機(jī)生成上管體高度
    this.down_height = (60 - this.up_height)*3;//保證所有上下水管距離相同
    this.posX = 300;//橫坐標(biāo)
    this.up_posY = this.up_height*3+this.up_pipe.height;//上水管縱坐標(biāo)
    this.down_posY = 362-this.down_height;//下水管縱坐標(biāo)
    this.hadSkipped = false;//是否被越過
    this.hadSkippedChange = false;//去重
  }
  //繪制水管
  drawPipe() {
    ctx.drawImage(this.up_pipe,this.posX,this.up_height*3);
    ctx.drawImage(this.down_pipe,this.posX,362-this.down_height);
  }
  //繪制管體
  drawMods() {
    for(var i=0;i<this.up_height;i++){
      ctx.drawImage(this.up_mod,this.posX,i*3)
    }
    for(var j=0;j<this.down_height;j++){
      ctx.drawImage(this.down_mod,this.posX,362-this.down_height+this.down_pipe.height+j);
    }
  }
  //水管移動
  move() {
    this.posX -= 6;
    this.drawMods();
    this.drawPipe();
  }
}

管口
管口
管體
管體


又是一段冗長的代碼敢订,大家不要急躁王污,我來給大家詳細(xì)解釋,水管分為兩部分楚午,一部分是固定的管口昭齐,還有一部分是為了控制鋼管長度的管體,在上面的圖片也可以看到矾柜,每一關(guān)的管道是分為上下兩個的——up_pipe和down_pipe阱驾,也就是說我們看到的鋼管是由數(shù)個相同的管體加管口構(gòu)成的,這里管體的數(shù)量是隨機(jī)的怪蔑,這樣就可以使管道擁有隨機(jī)的長度了里覆。然后為了保證上下兩個鋼管的中間距離固定,下管道的高度就是總高度減去上管道的高度饮睬,嗯租谈,這里需要理一理篮奄,大家也可以直接去看我的代碼捆愁。有了上面的理論,接下來就簡單了窟却,繪制管口drawPipe()昼丑,注意給管體預(yù)留出位置來,再繪制管體drawMods(),用一個for循環(huán)依次繪制出數(shù)個管體疊加在一起的樣子夸赫。水管移動move(),就是改變水管的橫坐標(biāo)了菩帝。這里可以通過改變上下水管高度的總值,來增加上下水管之間的距離茬腿,是不是游戲難度一下就降了很多呼奢?再有就是判斷水管是否被小鳥跨越的hadskiped屬性,往下看

//判斷是否越過水管
  function isSkipped(oPipe) {
    if(bird.posX>oPipe.posX+oPipe.down_pipe.width){
      //水管已經(jīng)被越過
      oPipe.hadSkipped = true;
      //確保水管只被越過一次
      if(!oPipe.hadSkippedChange&&oPipe.hadSkipped){
        //分?jǐn)?shù)+1
        scroll++;
        oPipe.hadSkippedChange = true;
      }
    }
  }

我是通過判斷水管的位置是否已經(jīng)位于小鳥的后面來判斷切平,小鳥是否越過了水管的握础,如果越過了就+1分,至于沒越過就是通過前面講過到的isHit()判斷了悴品,因為不是同一時間段發(fā)生的事情所以不能放在一起禀综。

計分表

計分表
計分表
var scroll = 0;//當(dāng)前得分
var scrollImg = [imgs.scroe0,imgs.scroe1,imgs.scroe2,
              imgs.scroe3,imgs.scroe4,imgs.scroe5,
              imgs.scroe6,imgs.scroe7,imgs.scroe8,
              imgs.scroe9];//存儲數(shù)字圖片
  //繪制當(dāng)前得分
  function drawScore() {
    //每繪制一位數(shù),向右移23苔严,繪制下一位數(shù)
    for(var i=0;i<scroll.toString().length;i++){
      ctx.drawImage(scrollImg[parseInt(scroll.toString().substr(i,1))],147+i*23,40)
    }
  }

首先定枷,把所有分?jǐn)?shù)有關(guān)的圖片放到這里scrollImg來,方便使用届氢。然后判斷數(shù)字的位數(shù)欠窒,也就是個十百千萬。循環(huán)并截取每個位數(shù)退子,再通過相應(yīng)的圖片繪制出來贱迟,并且每繪制一個位數(shù)的圖片位置向右移23姐扮,這樣數(shù)字就不會疊在一起了。這里有一種最沒意思的作弊方法衣吠,就是手動調(diào)整分?jǐn)?shù)茶敏,但這只是一個數(shù)字,游戲的樂趣果然還是在于過程缚俏,下面...

游戲開始惊搏!

//游戲界面
  function gameLayer() {
    gameTimer = setInterval(function () {
      clean();
      drawBg();
      drawGrass();
      if(gameTime%5 == 0){
        if(gameTime == 30){
          createPipes();
          gameTime = 0;
        }
        bird.wingWave();
      }
      gameTime++;
      for(var i = 0;i< pipes.length;i++){
        pipes[i].move();
        isHit(pipes[i]);
        isSkipped(pipes[i]);
      }
      drawScore();
      bird.fly();
      //如果小鳥死了
      if(!bird.alive){
        gameOver();//游戲結(jié)束
        reset();//數(shù)據(jù)重置
      }
    }, 24);
  }

...看到這里,估計已經(jīng)有人在罵我了忧换,講了半天游戲還沒開始...好吧恬惯,你們看,其實游戲的界面也不過是一個定時器亚茬,將前面講到的函數(shù)和代碼酪耳,無腦的、重復(fù)的執(zhí)行著刹缝。然后這里一定要注意畫圖的順序碗暗,不然后畫的部分會把前面覆蓋掉,其次這里的gameTimer和gameTime也和開始界面中startTimer梢夯、startTime起到類似的作用言疗,每過一段較長的時間生成一個水管,也就是通過水管類實例化一個水管對象颂砸,具體的方法被我封裝進(jìn)一個createPipes函數(shù)里了噪奄。

var pipes = [];//用于存放水管
function createPipes() {
    var pipe = new Pipe(imgs.up_pipe,imgs.up_mod,imgs.down_pipe,imgs.down_mod);
    //添加進(jìn)pipes中,如果已經(jīng)有三個水管人乓,則依次替換
    if(pipes.length<3){
      pipes.push(pipe);
    }else{
      pipes[index] = pipe;
      index++;
      if(index >= 3){
        index = 0;
      }
    }
  }

因為實現(xiàn)的方法沒有想象中那么簡單勤篮,首先我們要創(chuàng)造一個水管的數(shù)組,它的作用就是為了控制水管的數(shù)量色罚,不然我們的定時器就會一遍一遍的創(chuàng)造出無數(shù)的水管碰缔,但是前面的水管早就離我們遠(yuǎn)去,所以我就用數(shù)組把水管裝起來保屯,控制只有一個屏幕的水管手负,也就是三個。如果創(chuàng)建了超過三個水管姑尺,就會把最前面一個替換掉竟终,因為它已經(jīng)超出了我們的視野。

響應(yīng)事件

光有動畫也不行切蟋,只能看不能玩有個皮用啊统捶。所以我們當(dāng)然要添加響應(yīng)事件了。

//鍵盤點(diǎn)擊事件
  function kd(e) {
    if (e.keyCode === 32) {
      bird.speed = -10;
    }
  }
  //觸屏事件
  function ts() {
    bird.speed = -10;
  }
  //start按鈕點(diǎn)擊事件
  function startBtn_click(e) {
    //判斷點(diǎn)擊位置
    if(e.clientX>canvas.offsetLeft+canvas.width/2-imgs.startBtn.width/2
      &&e.clientX<canvas.offsetLeft+canvas.width/2+imgs.startBtn.width/2
      &&e.clientY<canvas.offsetTop+300+imgs.startBtn.height
      &&e.clientY>canvas.offsetTop+300){
      clean();
      //清除開始界面定時器
      clearInterval(startTimer);
      gameLayer();
      //添加響應(yīng)事件
      window.addEventListener('keydown',kd,false)
      window.addEventListener('touchstart',ts,false)
      //刪除start按鈕響應(yīng)事件
      canvas.removeEventListener('click',startBtn_click,false);
    }
  }
  canvas.addEventListener('click', startBtn_click , false);

這就是所有的響應(yīng)事件了,通過按空格鍵和點(diǎn)擊屏幕都可以改變小鳥的速度喘鸟,只要把這個速度調(diào)整到一個比較舒服的程度匆绣,游戲難度就會大大降低。其次什黑,因為canvas是一個整體崎淳,所以我們沒有辦法直接監(jiān)聽里面圖片按鈕的響應(yīng)事件,只能退而求其次愕把,判斷點(diǎn)擊的位置是否在按鈕的位置上了拣凹,就上面那段有點(diǎn)長的if判斷語句。

游戲結(jié)束

假如我們的主角真的一個不小心如我們所料的撞死在了鋼管上(往上翻恨豁,就在游戲開始那里)嚣镜,那就表示gameOver();

  //游戲結(jié)束
  function gameOver(){
    //清除定時器
    clearInterval(gameTimer);
    //清除窗口響應(yīng)事件
    window.removeEventListener('keydown',kd,false);
    window.removeEventListener('touchstart',ts,false);
    //繪制GAME OVER
    ctx.font = "50px blod";
    ctx.fontWeight = '1000'
    ctx.fillStyle = "white";
    ctx.fillText("GAME OVER", 20, 200);
    drawStartBtn();
  }

游戲結(jié)束
游戲結(jié)束


整個世界都平靜了下來,定時器關(guān)掉橘蜜,響應(yīng)事件移除掉菊匿,然后繪上大大的、慘白的GAME OVER,下面附帶一個游戲開始時就出現(xiàn)的start按鈕计福。不是有一句話說的是跌捆,結(jié)束不過是新的開始嗎,你又可以再來一局了棒搜。......好吧疹蛉,這個就是我為了偷懶隨便搞搞的活箕。不過這還沒完力麸,數(shù)據(jù)還得重置一下,不然怎么重新開始育韩。

  //重置數(shù)據(jù)
  function reset(){
    bird.posY = 200;
    bird.speed = 0;
    bird.alive = true;
    pipes = [];
    scroll = 0;
    canvas.addEventListener('click', startBtn_click , false);
  }

最后再給這個start按鈕添加上點(diǎn)擊事件克蚂,大功告成!這就是我調(diào)整難度之后的樣子:

低難度版
低難度版


嘖嘖嘖筋讨,這種閑庭信步的感覺......

果然游戲還是有點(diǎn)難度才有意思......

總結(jié)

吁...一篇又臭又長埃叭、廢話又多的文章終于寫完了,如果大家覺得有幫助悉罕,或者對這篇文章有興趣的話赤屋,就賞個贊。如果覺得我的程序有問題壁袄,或者有別的想說的类早,都可以在評論里告訴我,我會看的嗜逻。

我的項目地址:https://github.com/tzc123/canvas_game

參考項目地址:http://www.reibang.com/p/45d994d04a25

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涩僻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逆日,老刑警劉巖嵌巷,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異室抽,居然都是意外死亡搪哪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門坪圾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來噩死,“玉大人,你說我怎么就攤上這事神年∫盐” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵已日,是天一觀的道長垛耳。 經(jīng)常有香客問我,道長飘千,這世上最難降的妖魔是什么堂鲜? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮护奈,結(jié)果婚禮上缔莲,老公的妹妹穿的比我還像新娘。我一直安慰自己霉旗,他們只是感情好痴奏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厌秒,像睡著了一般读拆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鸵闪,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天檐晕,我揣著相機(jī)與錄音,去河邊找鬼蚌讼。 笑死辟灰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的篡石。 我是一名探鬼主播芥喇,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼夏志!你這毒婦竟也來了乃坤?” 一聲冷哼從身側(cè)響起苛让,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎湿诊,沒想到半個月后狱杰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厅须,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年仿畸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朗和。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡错沽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出眶拉,到底是詐尸還是另有隱情千埃,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布忆植,位于F島的核電站放可,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏朝刊。R本人自食惡果不足惜耀里,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拾氓。 院中可真熱鬧冯挎,春花似錦、人聲如沸咙鞍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奶陈。三九已至易阳,卻和暖如春附较,著一層夾襖步出監(jiān)牢的瞬間吃粒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工拒课, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留徐勃,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓早像,卻偏偏與公主長得像僻肖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子卢鹦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 由于很多小伙伴要demo我就不一一發(fā)了臀脏,直接丟在github上自己下載吧:https://github.com/s...
    FKSky閱讀 23,331評論 27 99
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,734評論 25 707
  • 原文發(fā)表于2017-03-09 的淘寶技術(shù)微信公眾號 https://mp.weixin.qq.com/s?__b...
    leonliu2閱讀 5,626評論 0 4
  • 一:canvas簡介 1.1什么是canvas? ①:canvas是HTML5提供的一種新標(biāo)簽 ②:HTML5 ...
    GreenHand1閱讀 4,674評論 2 32
  • 6月22日,今天被領(lǐng)導(dǎo)罵了一頓揉稚,事情的發(fā)展超出我的預(yù)料秒啦,有什么問題要及時的和領(lǐng)導(dǎo)溝通,雖然有件事有點(diǎn)超出自己的能力...
    i學(xué)思閱讀 205評論 0 0